From 40bd2330780bfaba487c4c5200f7190946b6dd6e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 21 Mar 2022 12:08:26 +0100 Subject: [PATCH 001/666] Tasmota/203 * Changes for C3 and S3 * Add Adafruit Feather ESP32 V2 board * S2 has no PSRAM bugs which needs fixes * Fix Esptool S3 bootloader patching Co-authored-by: Maximilian Gerhardt --- .github/workflows/examples.yml | 8 +- README.md | 18 +-- boards/adafruit_feather_esp32_v2.json | 37 ++++++ boards/esp32-c3-devkitm-1.json | 1 + boards/esp32-s2-franzininho.json | 3 + boards/esp32-s2-kaluga-1.json | 2 + boards/esp32-s2-saola-1.json | 2 + boards/esp32-s3-devkitc-1.json | 35 ++++++ boards/featheresp32-s2.json | 2 + boards/qtpy-esp32-s2.json | 34 ++++++ builder/frameworks/_embed_files.py | 2 +- builder/frameworks/espidf.py | 114 +++++++++++++----- builder/main.py | 92 ++++++++------ examples/arduino-rmt-blink/platformio.ini | 17 +++ .../src/RMTWriteNeoPixel.ino | 100 +++++++++++++++ examples/espidf-arduino-blink/platformio.ini | 3 - .../espidf-arduino-blink/sdkconfig.defaults | 3 +- .../espidf-arduino-wifiscan/platformio.ini | 3 - .../sdkconfig.defaults | 1 - examples/espidf-blink/platformio.ini | 17 +++ .../espidf-coap-server/src/certs/coap_ca.pem | 46 +++---- .../src/certs/coap_server.crt | 79 ++---------- .../src/certs/coap_server.key | 31 +---- .../src/coap_server_example_main.c | 109 +++++++++++------ .../src/tusb_sample_descriptor.c | 2 +- monitor/filter_exception_decoder.py | 2 +- platform.json | 40 ++++-- platform.py | 77 +++++------- 28 files changed, 571 insertions(+), 309 deletions(-) create mode 100644 boards/adafruit_feather_esp32_v2.json create mode 100644 boards/esp32-s3-devkitc-1.json create mode 100644 boards/qtpy-esp32-s2.json create mode 100644 examples/arduino-rmt-blink/platformio.ini create mode 100644 examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 2f42e32de..90cab3dcc 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -7,14 +7,16 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-18.04, windows-latest, macos-latest] - python-version: [3.7] + os: [ubuntu-latest, windows-latest, macos-latest] + python-version: [3.8] example: - "examples/arduino-blink" + - "examples/arduino-rmt-blink" - "examples/arduino-briki-internal-libs" - "examples/arduino-wifiscan" - "examples/espidf-arduino-blink" - "examples/espidf-arduino-wifiscan" + - "examples/espidf-blink" - "examples/espidf-aws-iot" - "examples/espidf-ble-eddystone" - "examples/espidf-coap-server" @@ -41,7 +43,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -U https://github.com/platformio/platformio/archive/develop.zip + pip install -U platformio platformio platform install file://. - name: Build examples run: | diff --git a/README.md b/README.md index cd538167b..a0268dc64 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ -# Espressif 32: development platform for [PlatformIO](http://platformio.org) +[![Build_special_firmware](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md) -[![Build Status](https://github.com/platformio/platform-espressif32/workflows/Examples/badge.svg)](https://github.com/platformio/platform-espressif32/actions) + +# Tasmota Espressif 32: development platform for [PlatformIO](http://platformio.org) + +[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml) Espressif Systems is a privately held fabless semiconductor company. They provide wireless communications and Wi-Fi chips which are widely used in mobile devices and the Internet of Things applications. @@ -16,16 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid ```ini [env:stable] -platform = espressif32 -board = ... -... -``` - -## Development version - -```ini -[env:development] -platform = https://github.com/platformio/platform-espressif32.git +platform = replace with url board = ... ... ``` diff --git a/boards/adafruit_feather_esp32_v2.json b/boards/adafruit_feather_esp32_v2.json new file mode 100644 index 000000000..2cd0eede4 --- /dev/null +++ b/boards/adafruit_feather_esp32_v2.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DADAFRUIT_FEATHER_ESP32_V2 -DBOARD_HAS_PSRAM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "adafruit_feather_esp32_v2" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32 V2", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5400", + "vendor": "Adafruit" +} diff --git a/boards/esp32-c3-devkitm-1.json b/boards/esp32-c3-devkitm-1.json index 5b101a862..a17aed860 100644 --- a/boards/esp32-c3-devkitm-1.json +++ b/boards/esp32-c3-devkitm-1.json @@ -17,6 +17,7 @@ "openocd_target": "esp32c3.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Espressif ESP32-C3-DevKitM-1", diff --git a/boards/esp32-s2-franzininho.json b/boards/esp32-s2-franzininho.json index 206456339..15854fdf4 100644 --- a/boards/esp32-s2-franzininho.json +++ b/boards/esp32-s2-franzininho.json @@ -4,6 +4,7 @@ "ld": "esp32s2_out.ld" }, "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", @@ -11,6 +12,8 @@ "variant": "esp32s2" }, "connectivity": [ + "arduino", + "espidf", "wifi" ], "debug": { diff --git a/boards/esp32-s2-kaluga-1.json b/boards/esp32-s2-kaluga-1.json index ae785b77c..b0120ffb7 100644 --- a/boards/esp32-s2-kaluga-1.json +++ b/boards/esp32-s2-kaluga-1.json @@ -4,6 +4,7 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", @@ -21,6 +22,7 @@ "openocd_target": "esp32s2.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Espressif ESP32-S2-Kaluga-1 Kit", diff --git a/boards/esp32-s2-saola-1.json b/boards/esp32-s2-saola-1.json index ab4f9fe09..a02952b11 100644 --- a/boards/esp32-s2-saola-1.json +++ b/boards/esp32-s2-saola-1.json @@ -4,6 +4,7 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", @@ -17,6 +18,7 @@ "openocd_target": "esp32s2.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Espressif ESP32-S2-Saola-1", diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json new file mode 100644 index 000000000..67c43b8f6 --- /dev/null +++ b/boards/esp32-s3-devkitc-1.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qspi_qspi" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S3-DevKitC-1", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 524288, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html", + "vendor": "Espressif" +} diff --git a/boards/featheresp32-s2.json b/boards/featheresp32-s2.json index 00bf22d46..47387f578 100644 --- a/boards/featheresp32-s2.json +++ b/boards/featheresp32-s2.json @@ -4,6 +4,7 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", @@ -17,6 +18,7 @@ "openocd_target": "esp32s2.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Adafruit ESP32-S2 Feather Development Board", diff --git a/boards/qtpy-esp32-s2.json b/boards/qtpy-esp32-s2.json new file mode 100644 index 000000000..73d927da5 --- /dev/null +++ b/boards/qtpy-esp32-s2.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s2", + "variant": "adafruit_qtpy_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5325", + "vendor": "Adafruit" +} diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index a267e0f7a..63add2202 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -108,7 +108,7 @@ def transform_to_asm(target, source, env): action=env.VerboseAction( " ".join( [ - "xtensa-esp32-elf-objcopy", + "xtensa-%s-elf-objcopy" % board.get("build.mcu", "esp32"), "--input-target", "binary", "--output-target", diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 0b8e3566d..425d02bc9 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -55,18 +55,13 @@ % ( "riscv32-esp" if mcu == "esp32c3" - else ("xtensa-esp32s2" if mcu == "esp32s2" else "xtensa-esp32") + else ("xtensa-%s" % mcu) ) ) -# Legacy toolchains for mixed IDF/Arduino projects -if "arduino" in env.subst("$PIOFRAMEWORK"): - TOOLCHAIN_DIR = platform.get_package_dir("toolchain-xtensa32") - assert os.path.isdir(FRAMEWORK_DIR) assert os.path.isdir(TOOLCHAIN_DIR) -# Arduino framework as a component is not compatible with ESP-IDF >=4.1 if "arduino" in env.subst("$PIOFRAMEWORK"): ARDUINO_FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") # Possible package names in 'package@version' format is not compatible with CMake @@ -233,7 +228,13 @@ def populate_idf_env_vars(idf_env): if mcu != "esp32c3": additional_packages.append( - os.path.join(platform.get_package_dir("toolchain-%sulp" % mcu), "bin"), + os.path.join( + platform.get_package_dir( + "toolchain-%sulp" + % ("esp32s2" if (mcu == "esp32s3" or mcu == "esp32s2") else mcu) + ), + "bin" + ), ) if "windows" in get_systype(): @@ -341,7 +342,7 @@ def _add_archive(archive_path, link_args): if fragment.startswith("-l"): link_args["LIBS"].extend(args) elif fragment.startswith("-L"): - lib_path = fragment.replace("-L", "").strip() + lib_path = fragment.replace("-L", "").strip().strip('"') _add_to_libpath(lib_path, link_args) elif fragment.startswith("-") and not fragment.startswith("-l"): # CMake mistakenly marks LINKFLAGS as libraries @@ -452,20 +453,11 @@ def find_framework_service_files(search_path, sdk_config): result["lf_files"].extend( [ - os.path.join( - FRAMEWORK_DIR, - "components", - idf_variant, - "ld", - "%s_fragments.lf" % idf_variant, - ), - os.path.join( - FRAMEWORK_DIR, - "components", - idf_variant, - "linker.lf", - ), + os.path.join(FRAMEWORK_DIR, "components", "esp_common", "common.lf"), + os.path.join(FRAMEWORK_DIR, "components", "esp_common", "soc.lf"), + os.path.join(FRAMEWORK_DIR, "components", "esp_system", "app.lf"), os.path.join(FRAMEWORK_DIR, "components", "newlib", "newlib.lf"), + os.path.join(FRAMEWORK_DIR, "components", "newlib", "system_libs.lf"), ] ) @@ -515,6 +507,46 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): libraries_list = create_custom_libraries_list( os.path.join(BUILD_DIR, "ldgen_libraries"), ignore_targets ) + # Rework the memory template linker script, following components/esp_system/ld.cmake + args = { + "preprocess" : os.path.join( + TOOLCHAIN_DIR, + "bin", + env.subst("$CC")), + "ld_output": os.path.join("$BUILD_DIR", "memory.ld"), + "ld_dir": os.path.join( + FRAMEWORK_DIR, + "components", + "esp_system", + "ld"), + "ld_input": os.path.join( + FRAMEWORK_DIR, + "components", + "esp_system", + "ld", + idf_variant, + "memory.ld.in", + ), + "config": os.path.join("$BUILD_DIR", "config"), + "flags" : '-C -P -x c -E -o ' + } + + cmd = ( + '"{preprocess}" {flags} "{ld_output}" -I "{config}" -I "{ld_dir}" "{ld_input}"' + ).format(**args) + + env.Command( + os.path.join("$BUILD_DIR", "memory.ld"), + os.path.join( + FRAMEWORK_DIR, + "components", + "esp_system", + "ld", + idf_variant, + "memory.ld.in", + ), + env.VerboseAction(cmd, "Generating memory linker script $TARGET"), + ) args = { "script": os.path.join(FRAMEWORK_DIR, "tools", "ldgen", "ldgen.py"), @@ -539,13 +571,14 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): ).format(**args) return env.Command( - os.path.join("$BUILD_DIR", "%s.project.ld" % idf_variant), + os.path.join("$BUILD_DIR", "sections.ld"), os.path.join( FRAMEWORK_DIR, "components", - idf_variant, + "esp_system", "ld", - "%s.project.ld.in" % idf_variant, + idf_variant, + "sections.ld.in", ), env.VerboseAction(cmd, "Generating project linker script $TARGET"), ) @@ -703,6 +736,20 @@ def find_lib_deps(components_map, elf_config, link_args, ignore_components=None) return result +def fix_ld_paths(extra_flags): + peripheral_framework_path = os.path.join(FRAMEWORK_DIR, "components", "soc", idf_variant, "ld") + rom_framework_path = os.path.join(FRAMEWORK_DIR, "components", "esp_rom", idf_variant, "ld") + bl_framework_path = os.path.join(FRAMEWORK_DIR, "components", "bootloader", "subproject", "main", "ld", idf_variant) + + # ESP linker scripts changed path in ESP-IDF 4.4+, so add missing paths to linker's search path + try: + ld_index = extra_flags.index("%s.peripherals.ld" % idf_variant) + extra_flags[ld_index-1:ld_index-1] = [ "-L", peripheral_framework_path, "-L", rom_framework_path, "-L", bl_framework_path] + except: + print("Error while parsing the flags") + + return extra_flags + def build_bootloader(): bootloader_src_dir = os.path.join( @@ -747,6 +794,7 @@ def build_bootloader(): build_components(bootloader_env, components_map, bootloader_src_dir, "bootloader") link_args = extract_link_args(elf_config) extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) + extra_flags = fix_ld_paths(extra_flags) link_args["LINKFLAGS"] = sorted( list(set(link_args["LINKFLAGS"]) - set(extra_flags)) ) @@ -1061,21 +1109,23 @@ def _get_installed_pip_packages(): if not board.get("build.ldscript", ""): linker_script = env.Command( - os.path.join("$BUILD_DIR", "%s_out.ld" % idf_variant), + os.path.join("$BUILD_DIR", "memory.ld"), board.get( "build.esp-idf.ldscript", os.path.join( - FRAMEWORK_DIR, "components", idf_variant, "ld", "%s.ld" % idf_variant + FRAMEWORK_DIR, "components", "esp_system", "ld", idf_variant, "memory.ld.in" ), ), env.VerboseAction( - '$CC -I"$BUILD_DIR/config" -C -P -x c -E $SOURCE -o $TARGET', + '$CC -I"$BUILD_DIR/config" -I"' + + os.path.join(FRAMEWORK_DIR, "components", "esp_system", "ld") + + '" -C -P -x c -E $SOURCE -o $TARGET', "Generating LD script $TARGET", ), ) env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", linker_script) - env.Replace(LDSCRIPT_PATH="%s_out.ld" % idf_variant) + env.Replace(LDSCRIPT_PATH="memory.ld") # # Generate partition table @@ -1257,13 +1307,15 @@ def _get_installed_pip_packages(): # Extra flags which need to be explicitly specified in LINKFLAGS section because SCons # cannot merge them correctly extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) +extra_flags = fix_ld_paths(extra_flags) link_args["LINKFLAGS"] = sorted(list(set(link_args["LINKFLAGS"]) - set(extra_flags))) -# remove the main linker script flags '-T esp32_out.ld' +# remove the main linker script flags '-T memory.ld' since it already appears later on try: - ld_index = extra_flags.index("%s_out.ld" % idf_variant) + ld_index = extra_flags.index("memory.ld") extra_flags.pop(ld_index) extra_flags.pop(ld_index - 1) + pass except: print("Warning! Couldn't find the main linker script in the CMake code model.") @@ -1319,7 +1371,7 @@ def _skip_prj_source_files(node): FLASH_EXTRA_IMAGES=[ ( board.get( - "upload.bootloader_offset", "0x0" if mcu == "esp32c3" else "0x1000" + "upload.bootloader_offset", "0x0" if (mcu == "esp32c3" or mcu == "esp32s3") else "0x1000" ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), diff --git a/builder/main.py b/builder/main.py index 1f01bf870..58912d2a4 100644 --- a/builder/main.py +++ b/builder/main.py @@ -106,54 +106,62 @@ def _to_unix_slashes(path): # -# SPIFFS helpers +# FS helpers # +env = DefaultEnvironment() +env.SConscript("compat.py", exports="env") +platform = env.PioPlatform() +board = env.BoardConfig() +filesystem = board.get("build.filesystem", "spiffs") +print("FILESYSTEM ", filesystem) +mcu = board.get("build.mcu", "esp32") +toolchain_arch = "xtensa-%s" % mcu +if mcu == "esp32c3": + toolchain_arch = "riscv32-esp" -def fetch_spiffs_size(env): - spiffs = None +def fetch_fs_size(env): + fs = None for p in _parse_partitions(env): - if p['type'] == "data" and p['subtype'] == "spiffs": - spiffs = p - if not spiffs: + # The option to use a partition subtype of "spiffs" eliminates the + # need to simultaneously update both this platform code and the + # framework code that handles partitions. You can use a framwork + # that only supports partitions named "spiffs", putting a LittleFS + # image therein. Going forward, the framework code can be updated + # to support partitions named "littlefs" and the code here will + # continue to work. + if p['type'] == "data" and (p['subtype'] == filesystem or p['subtype'] == "spiffs"): + fs = p + if not fs: sys.stderr.write( - "Could not find the `spiffs` section in the partitions " - "table %s\n" % env.subst("$PARTITIONS_TABLE_CSV") + "Could not find the `%s` section in the partitions " + "table %s\n" % (filesystem, env.subst("$PARTITIONS_TABLE_CSV")) ) env.Exit(1) return - env["SPIFFS_START"] = _parse_size(spiffs['offset']) - env["SPIFFS_SIZE"] = _parse_size(spiffs['size']) - env["SPIFFS_PAGE"] = int("0x100", 16) - env["SPIFFS_BLOCK"] = int("0x1000", 16) + env["FS_START"] = _parse_size(fs['offset']) + env["FS_SIZE"] = _parse_size(fs['size']) + env["FS_PAGE"] = int("0x100", 16) + env["FS_BLOCK"] = int("0x1000", 16) -def __fetch_spiffs_size(target, source, env): - fetch_spiffs_size(env) +def __fetch_fs_size(target, source, env): + fetch_fs_size(env) return (target, source) -env = DefaultEnvironment() -env.SConscript("compat.py", exports="env") -platform = env.PioPlatform() -board = env.BoardConfig() -mcu = board.get("build.mcu", "esp32") -toolchain_arch = "xtensa-%s" % mcu -if mcu == "esp32c3": - toolchain_arch = "riscv32-esp" - env.Replace( __get_board_f_flash=_get_board_f_flash, __get_board_flash_mode=_get_board_flash_mode, - AR="%s-elf-ar" % toolchain_arch, + AR="%s-elf-gcc-ar" % toolchain_arch, AS="%s-elf-as" % toolchain_arch, CC="%s-elf-gcc" % toolchain_arch, CXX="%s-elf-g++" % toolchain_arch, GDB="%s-elf-gdb" % toolchain_arch, OBJCOPY=join( platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), - RANLIB="%s-elf-ranlib" % toolchain_arch, + RANLIB="%s-elf-gcc-ranlib" % toolchain_arch, SIZETOOL="%s-elf-size" % toolchain_arch, ARFLAGS=["rc"], @@ -169,9 +177,10 @@ def __fetch_spiffs_size(target, source, env): ], ERASECMD='"$PYTHONEXE" "$OBJCOPY" $ERASEFLAGS erase_flash', - MKSPIFFSTOOL="mkspiffs_${PIOPLATFORM}_" + ("espidf" if "espidf" in env.subst( - "$PIOFRAMEWORK") else "${PIOFRAMEWORK}"), - ESP32_SPIFFS_IMAGE_NAME=env.get("ESP32_SPIFFS_IMAGE_NAME", "spiffs"), + MKFSTOOL=("mklittlefs" if filesystem == "littlefs" else + "mkspiffs_${PIOPLATFORM}_" + ("espidf" if "espidf" in env.subst("$PIOFRAMEWORK") else "${PIOFRAMEWORK}")), + ESP32_FS_IMAGE_NAME=env.get("ESP32_FS_IMAGE_NAME", env.get( + "ESP32_SPIFFS_IMAGE_NAME", filesystem)), ESP32_APP_OFFSET="0x10000", PROGSUFFIX=".elf" @@ -200,14 +209,14 @@ def __fetch_spiffs_size(target, source, env): ), DataToBin=Builder( action=env.VerboseAction(" ".join([ - '"$MKSPIFFSTOOL"', + '"$MKFSTOOL"', "-c", "$SOURCES", - "-p", "$SPIFFS_PAGE", - "-b", "$SPIFFS_BLOCK", - "-s", "$SPIFFS_SIZE", + "-p", "$FS_PAGE", + "-b", "$FS_BLOCK", + "-s", "$FS_SIZE", "$TARGET" - ]), "Building SPIFFS image from '$SOURCES' directory to $TARGET"), - emitter=__fetch_spiffs_size, + ]), "Building FS image from '$SOURCES' directory to $TARGET"), + emitter=__fetch_fs_size, source_factory=env.Dir, suffix=".bin" ) @@ -218,20 +227,23 @@ def __fetch_spiffs_size(target, source, env): env.SConscript("frameworks/_bare.py", exports="env") # -# Target: Build executable and linkable firmware or SPIFFS image +# Target: Build executable and linkable firmware or FS image # target_elf = None if "nobuild" in COMMAND_LINE_TARGETS: target_elf = join("$BUILD_DIR", "${PROGNAME}.elf") if set(["uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): - fetch_spiffs_size(env) - target_firm = join("$BUILD_DIR", "${ESP32_SPIFFS_IMAGE_NAME}.bin") + fetch_fs_size(env) + target_firm = join("$BUILD_DIR", "${ESP32_FS_IMAGE_NAME}.bin") else: target_firm = join("$BUILD_DIR", "${PROGNAME}.bin") else: target_elf = env.BuildProgram() if set(["buildfs", "uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): + if filesystem not in ("littlefs", "spiffs"): + sys.stderr.write("Filesystem %s is not supported!\n" % filesystem) + env.Exit(1) target_firm = env.DataToBin( join("$BUILD_DIR", "${ESP32_SPIFFS_IMAGE_NAME}"), "$PROJECT_DATA_DIR") env.NoCache(target_firm) @@ -269,7 +281,7 @@ def __fetch_spiffs_size(target, source, env): ) # -# Target: Upload firmware or SPIFFS image +# Target: Upload firmware or filesystem image # upload_protocol = env.subst("$UPLOAD_PROTOCOL") @@ -303,7 +315,7 @@ def __fetch_spiffs_size(target, source, env): UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS -f $SOURCE' ) if set(["uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): - env.Append(UPLOADERFLAGS=["--spiffs"]) + env.Append(UPLOADERFLAGS=["-s"]) upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")] elif upload_protocol == "esptool": @@ -337,7 +349,7 @@ def __fetch_spiffs_size(target, source, env): "write_flash", "-z", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_size", "detect", - "$SPIFFS_START" + "$FS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', ) diff --git a/examples/arduino-rmt-blink/platformio.ini b/examples/arduino-rmt-blink/platformio.ini new file mode 100644 index 000000000..14244480d --- /dev/null +++ b/examples/arduino-rmt-blink/platformio.ini @@ -0,0 +1,17 @@ +[env:esp32-s2] +platform = espressif32 +framework = arduino +board = esp32-s2-saola-1 +build_flags = -DBUILTIN_RGBLED_PIN=18 + +[env:esp32-s3] +platform = espressif32 +framework = arduino +board = esp32-s3-devkitc-1 +build_flags = -DBUILTIN_RGBLED_PIN=48 + +[env:esp32-c3] +platform = espressif32 +framework = arduino +board = esp32-c3-devkitm-1 +build_flags = -DBUILTIN_RGBLED_PIN=8 diff --git a/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino b/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino new file mode 100644 index 000000000..eee7dcf3b --- /dev/null +++ b/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino @@ -0,0 +1,100 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "Arduino.h" + +#include "esp32-hal.h" + +// The effect seen in ESP32C3, ESP32S2 and ESP32S3 is like a Blink of RGB LED +//#if CONFIG_IDF_TARGET_ESP32S2 +//#define BUILTIN_RGBLED_PIN 18 +//#elif CONFIG_IDF_TARGET_ESP32S3 +//#define BUILTIN_RGBLED_PIN 48 +//#elif CONFIG_IDF_TARGET_ESP32C3 +//#define BUILTIN_RGBLED_PIN 8 +//#else +//#define BUILTIN_RGBLED_PIN 21 // ESP32 has no builtin RGB LED +//#endif + +#define NR_OF_LEDS 8*4 +#define NR_OF_ALL_BITS 24*NR_OF_LEDS + +// +// Note: This example uses Neopixel LED board, 32 LEDs chained one +// after another, each RGB LED has its 24 bit value +// for color configuration (8b for each color) +// +// Bits encoded as pulses as follows: +// +// "0": +// +-------+ +-- +// | | | +// | | | +// | | | +// ---| |--------------| +// + + + +// | 0.4us | 0.85 0us | +// +// "1": +// +-------------+ +-- +// | | | +// | | | +// | | | +// | | | +// ---+ +-------+ +// | 0.8us | 0.4us | + +rmt_data_t led_data[NR_OF_ALL_BITS]; + +rmt_obj_t* rmt_send = NULL; + +void setup() +{ + Serial.begin(115200); + + if ((rmt_send = rmtInit(BUILTIN_RGBLED_PIN, RMT_TX_MODE, RMT_MEM_64)) == NULL) + { + Serial.println("init sender failed\n"); + } + + float realTick = rmtSetTick(rmt_send, 100); + Serial.printf("real tick set to: %fns\n", realTick); + +} + +int color[] = { 0x55, 0x11, 0x77 }; // RGB value +int led_index = 0; + +void loop() +{ + // Init data with only one led ON + int led, col, bit; + int i=0; + for (led=0; led=NR_OF_LEDS) { + led_index = 0; + } + + // Send the data + rmtWrite(rmt_send, led_data, NR_OF_ALL_BITS); + + delay(100); +} diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 8ee11c971..0f991013b 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -13,9 +13,6 @@ framework = arduino, espidf build_flags = -D CONFIG_BLINK_GPIO=2 monitor_speed = 115200 -platform_packages = - ; use a special branch - framework-arduinoespressif32 @ https://github.com/marcovannoord/arduino-esp32.git#idf-release/v4.0 [env:esp32dev] board = esp32dev diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index 909461e58..f56753404 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -7,7 +7,6 @@ CONFIG_ARDUINO_EVENT_RUN_CORE1=y CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 CONFIG_ARDUINO_UDP_RUN_CORE1=y CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -CONFIG_DISABLE_HAL_LOCKS=y CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y @@ -15,4 +14,4 @@ CONFIG_ARDUHAL_PARTITION_SCHEME="default" CONFIG_AUTOCONNECT_WIFI=y CONFIG_ARDUINO_SELECTIVE_WiFi=y CONFIG_MBEDTLS_PSK_MODES=y -CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y \ No newline at end of file +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y diff --git a/examples/espidf-arduino-wifiscan/platformio.ini b/examples/espidf-arduino-wifiscan/platformio.ini index 32d44b6d9..79e7284f6 100644 --- a/examples/espidf-arduino-wifiscan/platformio.ini +++ b/examples/espidf-arduino-wifiscan/platformio.ini @@ -11,9 +11,6 @@ platform = espressif32 framework = arduino, espidf monitor_speed = 115200 -platform_packages = - ; use a special branch - framework-arduinoespressif32 @ https://github.com/marcovannoord/arduino-esp32.git#idf-release/v4.0 [env:esp32dev] board = esp32dev diff --git a/examples/espidf-arduino-wifiscan/sdkconfig.defaults b/examples/espidf-arduino-wifiscan/sdkconfig.defaults index bc79532a0..cf124f4c4 100644 --- a/examples/espidf-arduino-wifiscan/sdkconfig.defaults +++ b/examples/espidf-arduino-wifiscan/sdkconfig.defaults @@ -7,7 +7,6 @@ CONFIG_ARDUINO_EVENT_RUN_CORE1=y CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 CONFIG_ARDUINO_UDP_RUN_CORE1=y CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -CONFIG_DISABLE_HAL_LOCKS=y CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y diff --git a/examples/espidf-blink/platformio.ini b/examples/espidf-blink/platformio.ini index 8cdfb1506..bb18e7640 100644 --- a/examples/espidf-blink/platformio.ini +++ b/examples/espidf-blink/platformio.ini @@ -16,3 +16,20 @@ build_flags = ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led -D CONFIG_BLINK_GPIO=2 +[env:esp32-s2] +platform = espressif32 +framework = espidf +board = esp32-s2-saola-1 +monitor_speed = 115200 +build_flags = + ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led + -D CONFIG_BLINK_GPIO=2 + +[env:esp32-s3] +platform = espressif32 +framework = espidf +board = esp32-s3-devkitc-1 +monitor_speed = 115200 +build_flags = + ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led + -D CONFIG_BLINK_GPIO=2 diff --git a/examples/espidf-coap-server/src/certs/coap_ca.pem b/examples/espidf-coap-server/src/certs/coap_ca.pem index 1bdf23d94..07900ec47 100644 --- a/examples/espidf-coap-server/src/certs/coap_ca.pem +++ b/examples/espidf-coap-server/src/certs/coap_ca.pem @@ -1,23 +1,27 @@ -----BEGIN CERTIFICATE----- -MIID3DCCA0WgAwIBAgIJAMnlgL1czsmjMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD -VQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hlcmUxFTAT -BgNVBAoMDEV4YW1wbGUgSW5jLjEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBs -ZS5jb20xJjAkBgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X -DTE3MDYwNzA4MDY0OVoXDTI3MDYwNTA4MDY0OVowgZMxCzAJBgNVBAYTAkZSMQ8w -DQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMGA1UECgwMRXhh -bXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTEmMCQG -A1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBALpWR23fn/TmHxsXsHdrydzPSd17fZkc71WsaicgQR66 -1tIVYb22UWGfj9KPM8THMsV74ew4ZkaQ39qvU0iuQIRrKARFHFok+vbaecgWMeWe -vGIqdnmyB9gJYaFOKgtSkfXsu2ddsqdvLYwcDbczrq8X9yEXpN6mnxXeCcPG4F0p -AgMBAAGjggE0MIIBMDAdBgNVHQ4EFgQUgigpdAUpONoDq0pQ3yfxrslCSpcwgcgG -A1UdIwSBwDCBvYAUgigpdAUpONoDq0pQ3yfxrslCSpehgZmkgZYwgZMxCzAJBgNV -BAYTAkZSMQ8wDQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMG -A1UECgwMRXhhbXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxl -LmNvbTEmMCQGA1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCCQDJ -5YC9XM7JozAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly93 -d3cuZXhhbXBsZS5jb20vZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcNAQELBQADgYEA -euxOBPInSJRKAIseMxPmAabtAqKNslZSmpG4He3lkKt+HM3jfznUt3psmD7j1hFW -S4l7KXzzajvaGYybDq5N9MqrDjhGn3VXZqOLMUNDL7OQq96TzgqsTBT1dmVSbNlt -PQgiAeKAk3tmH4lRRi9MTBSyJ6I92JYcS5H6Bs4ZwCc= +MIICDzCCAbSgAwIBAgIIAbOUoVFDz/QwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMzWhcNMjExMTExMTAzMDMzWjBaMQ4wDAYDVQQDEwVjZi1jYTEUMBIGA1UECxML +Q2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZPdHRh +d2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7/3EXOZn +GZXNEIj7LuQAMZ8lfRYSCnpME1TBjKjZPtVeztLtGWgkkLvIX11pAJcBh51cpi7Z +fQtGpVE9CLOh6aNgMF4wHQYDVR0OBBYEFEvf57UcJhYYkx14twkeitd691fVMAsG +A1UdDwQEAwIBBjAPBgNVHRMECDAGAQH/AgEBMB8GA1UdIwQYMBaAFAsi3KbVERiK +JzFCfC/GVrYksGzEMAwGCCqGSM49BAMCBQADRwAwRAIgc5nVF/5Pip0XB17IZXqi +V84FXanWdn9Z0SiPdpOgvZMCIH13vL9tkCCjPN3tg3TYRY/bzyGohFGBcTrrEtUr +rVIm +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIB4DCCAYWgAwIBAgIIQR8ro8AQ02AwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMyWhcNMjExMTExMTAzMDMyWjBcMRAwDgYDVQQDEwdjZi1yb290MRQwEgYDVQQL +EwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBzZSBJb1QxDzANBgNVBAcTBk90 +dGF3YTELMAkGA1UEBhMCQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATZ1BRM +T1//Fzh9sneRZNwS4kgCxN1PvgwT271qCpYqyxnjLEa38AP1IAanhpiD/OkVc0Zd +7NgDPCw7n94EULMyoy8wLTAdBgNVHQ4EFgQUCyLcptURGIonMUJ8L8ZWtiSwbMQw +DAYDVR0TBAUwAwEB/zAMBggqhkjOPQQDAgUAA0cAMEQCIAdLEgcUWdpAl9jwdJiz +/cHW7/CBIWEvqiQfzE+XLyLOAiAvuxSdOtSDjh2aC5qEjUCH8CSKCxWB74j23tmp +aqPH4A== -----END CERTIFICATE----- diff --git a/examples/espidf-coap-server/src/certs/coap_server.crt b/examples/espidf-coap-server/src/certs/coap_server.crt index 8f1dfcda6..6522f4e4c 100644 --- a/examples/espidf-coap-server/src/certs/coap_server.crt +++ b/examples/espidf-coap-server/src/certs/coap_server.crt @@ -1,70 +1,13 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 47 (0x2f) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FR, ST=Radius, L=Somewhere, O=Example Inc./emailAddress=admin@example.com, CN=Example Certificate Authority - Validity - Not Before: Jun 7 08:06:49 2017 GMT - Not After : Jun 5 08:06:49 2027 GMT - Subject: C=FR, ST=Radius, O=Example Inc., CN=Example Server Certificate/emailAddress=admin@example.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:c9:d8:e2:e0:75:91:83:87:d8:c8:80:c6:20:4d: - e9:14:24:30:98:33:53:fa:56:0e:ec:9a:43:7f:87: - a9:22:94:26:06:c7:ac:b5:d9:ec:55:06:81:b7:0d: - c9:24:51:49:fa:47:fb:4b:4e:fc:ed:75:8a:e1:28: - 32:bc:c5:e0:4c:45:c4:58:60:15:67:1e:6b:40:19: - 3f:f0:ab:92:61:92:2d:71:10:2e:f2:eb:bc:81:2f: - 5a:3b:74:ca:5f:fd:e0:ee:d1:d9:07:6a:6c:20:c0: - 07:88:b4:8b:0f:ad:1e:c9:4f:7c:11:98:37:89:15: - de:24:b1:11:1a:7c:97:4a:cf:f3:c8:cb:79:9e:9c: - c3:71:da:a6:94:97:f5:95:fd:61:06:44:e2:3f:12: - 43:0b:1d:33:48:91:d2:ce:4f:97:a1:ed:6a:30:c7: - 5d:98:b5:6e:0a:b7:4f:d9:03:ec:80:76:09:b0:40: - a1:a1:af:ab:2a:59:c4:0f:56:22:bc:be:14:be:18: - df:10:7d:5d:22:bf:e5:04:77:7a:75:6b:3e:eb:6d: - 20:a1:a7:60:d4:f1:87:9d:9f:60:b9:d3:db:2c:25: - f4:91:4a:f1:d2:40:e5:a1:10:88:a0:41:5a:98:40: - ca:15:d7:e3:e6:3e:c0:6a:d5:46:b2:b4:90:b4:ae: - 3b:e3 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Extended Key Usage: - TLS Web Server Authentication - X509v3 CRL Distribution Points: - - Full Name: - URI:http://www.example.com/example_ca.crl - - Signature Algorithm: sha1WithRSAEncryption - a4:25:21:51:0b:22:6c:63:8d:a9:c1:4f:04:33:69:79:34:f0: - 36:dd:8f:6a:27:5f:07:a2:1d:ef:8b:f0:96:e6:e7:a3:b8:3b: - 85:5e:3f:26:43:8a:8e:95:58:9c:a6:db:9c:51:bf:ea:53:16: - 3e:c1:a8:11:1a:c6:cf:0e:a1:17:18:64:d2:05:f1:c0:9c:a6: - 2b:16:c4:29:54:03:d2:17:bd:15:74:d6:ad:8a:8f:2d:cc:27: - 3b:88:88:f2:ea:d0:a2:cb:e9:42:57:df:26:9f:8a:a2:02:2f: - 35:b6:19:1d:26:43:44:af:12:4b:bc:b9:84:50:02:fd:1d:fa: - 50:e8 -----BEGIN CERTIFICATE----- -MIIDWTCCAsKgAwIBAgIBLzANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UEBhMCRlIx -DzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRUwEwYDVQQKDAxF -eGFtcGxlIEluYy4xIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMSYw -JAYDVQQDDB1FeGFtcGxlIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNzA2MDcw -ODA2NDlaFw0yNzA2MDUwODA2NDlaMHwxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZS -YWRpdXMxFTATBgNVBAoMDEV4YW1wbGUgSW5jLjEjMCEGA1UEAwwaRXhhbXBsZSBT -ZXJ2ZXIgQ2VydGlmaWNhdGUxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUu -Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydji4HWRg4fYyIDG -IE3pFCQwmDNT+lYO7JpDf4epIpQmBsestdnsVQaBtw3JJFFJ+kf7S0787XWK4Sgy -vMXgTEXEWGAVZx5rQBk/8KuSYZItcRAu8uu8gS9aO3TKX/3g7tHZB2psIMAHiLSL -D60eyU98EZg3iRXeJLERGnyXSs/zyMt5npzDcdqmlJf1lf1hBkTiPxJDCx0zSJHS -zk+Xoe1qMMddmLVuCrdP2QPsgHYJsEChoa+rKlnED1YivL4UvhjfEH1dIr/lBHd6 -dWs+620goadg1PGHnZ9gudPbLCX0kUrx0kDloRCIoEFamEDKFdfj5j7AatVGsrSQ -tK474wIDAQABo08wTTATBgNVHSUEDDAKBggrBgEFBQcDATA2BgNVHR8ELzAtMCug -KaAnhiVodHRwOi8vd3d3LmV4YW1wbGUuY29tL2V4YW1wbGVfY2EuY3JsMA0GCSqG -SIb3DQEBBQUAA4GBAKQlIVELImxjjanBTwQzaXk08Dbdj2onXweiHe+L8Jbm56O4 -O4VePyZDio6VWJym25xRv+pTFj7BqBEaxs8OoRcYZNIF8cCcpisWxClUA9IXvRV0 -1q2Kjy3MJzuIiPLq0KLL6UJX3yafiqICLzW2GR0mQ0SvEku8uYRQAv0d+lDo +MIICAzCCAaagAwIBAgIJANqCHDjOKHh+MAwGCCqGSM49BAMCBQAwWjEOMAwGA1UE +AxMFY2YtY2ExFDASBgNVBAsTC0NhbGlmb3JuaXVtMRQwEgYDVQQKEwtFY2xpcHNl +IElvVDEPMA0GA1UEBxMGT3R0YXdhMQswCQYDVQQGEwJDQTAeFw0yMDExMTExMDMw +MzRaFw0yMTExMTExMDMwMzRaMF4xEjAQBgNVBAMTCWNmLXNlcnZlcjEUMBIGA1UE +CxMLQ2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZP +dHRhd2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+obM +gHmMB7zS4KArciXPD7CrvgEYqlnAf7NOTdb54RbTr4qEpPL+OJ6Pg8VhrF4hGEne +T6Aa4qqpmTkxmfT0vqNPME0wHQYDVR0OBBYEFE4XpfFad+F3+RcwI+s1cmJbTZWG +MAsGA1UdDwQEAwIHgDAfBgNVHSMEGDAWgBRL3+e1HCYWGJMdeLcJHorXevdX1TAM +BggqhkjOPQQDAgUAA0kAMEYCIQCEo+O5zqYKdwi/ElB4wfNVIf76P1OhIXAT5CHc +3ebBPQIhAN6UhCgQ0av6kf7INCazV3KmN7HmPXARaY4YKWsRwsg+ -----END CERTIFICATE----- diff --git a/examples/espidf-coap-server/src/certs/coap_server.key b/examples/espidf-coap-server/src/certs/coap_server.key index 9b3433273..362851524 100644 --- a/examples/espidf-coap-server/src/certs/coap_server.key +++ b/examples/espidf-coap-server/src/certs/coap_server.key @@ -1,27 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAydji4HWRg4fYyIDGIE3pFCQwmDNT+lYO7JpDf4epIpQmBses -tdnsVQaBtw3JJFFJ+kf7S0787XWK4SgyvMXgTEXEWGAVZx5rQBk/8KuSYZItcRAu -8uu8gS9aO3TKX/3g7tHZB2psIMAHiLSLD60eyU98EZg3iRXeJLERGnyXSs/zyMt5 -npzDcdqmlJf1lf1hBkTiPxJDCx0zSJHSzk+Xoe1qMMddmLVuCrdP2QPsgHYJsECh -oa+rKlnED1YivL4UvhjfEH1dIr/lBHd6dWs+620goadg1PGHnZ9gudPbLCX0kUrx -0kDloRCIoEFamEDKFdfj5j7AatVGsrSQtK474wIDAQABAoIBAQC2kGDEPBJdMSW2 -VCLfXRiPixwYzXQLXIMrJWwfkQg9qlmqkDd6U50aWkRA2UswegW7RhfYSZ0i+cmf -VMhvTVpOIlwwwtcY6b5/v1bBy60eaySGuuh79xQMlFO8qynQIMStvUfbGTqrdIRb -9VBB4YeS9T12fILejtTZwv2BQ2dj1Y1SCay6Ri85UzJqSClRKgHISybvVdLNjPvP -0TRFBr57zyjL6WE8teKiKchzQko2u86No5uBCdKGsrAkrsdcR0YqlM/pZxd3VKNm -+eny0k+dZZlvcPxzkzP4hEp9+Rw5rP9/s3s/cCwvuuC5JO32ATBWKCbTvPv/XPDb -MdSJtOshAoGBAPzk0eswkcbFYtpnpBNmBAr1dtAdW1lfjUI2ucMMwt7Wns0P/tt+ -gq6Hi1wTaGP0l/dIECgeHwjtWj31ZJjQtFJ1y/kafxo4o9cA8vCydpdvSZaldAfg -sbLlDTDYzEpelaDIbNQBBXFoC5U9JlBhBsIFCL5Z8ZuIeFPsb7t5wwuHAoGBAMxT -jyWfNm1uNxp1xgCnrRsLPQPVnURrSFAqcHrECqRu3F7sozTN7q/cZViemxPvVDGQ -p9c+9bHwaYvW4trO5qDHJ++gGwm5L52bMAY1VUfeTt67fqrey43XpdmzcTX1V9Uj -QWawPUCSDzFjL1MjfCIejtyYf5ash53vj+T8r/vFAoGAA/OPVB1uKazr3n3AEo2F -gqZTNO1AgCT+EArK3EFWyiSQVqPpV4SihheYFdg3yVgJB9QYbIgL9BfBUTaEW97m -8mLkzP+c/Mvlw3ZAVYJ0V+llPPVY2saoACOUES9SAdd4fwqiqK1baGo3xB0wfBEI -CgAKIu9E1ylKuAT5ufQtGAECgYEAtP/kU5h5N3El4QupTdU7VDSdZTMqsHw0v8cI -gsf9AXKvRmtrnBA8u46KPHmruHoO5CVXeSZtsaXdaaH+rYQQ6yXg67WxnehtFLlv -TmCaXiLBTS9cYvMf8FOyuGnsBLeEietEOTov2G5KhR5uwsAxa2wUc7endor5S9/2 -YQuyvV0CgYALbiFpILd5l1ip65eE6JdA3hfttUbV2j2NSW12ej69vqbeOfaSgNse -uYCcXFsBbQPhNPwA+4d1oCe8SyXZg1f7gE812z2Tyr/3vdVnNZlitoxhsHmGiyS7 -gZdaTYCb78l9z0EBdaCVvA16owEle4SR6f9eCwzSI0WPOUra+x/hrA== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCLBQT66xp2w4+1K+Ai +/TXEC8tQZBxl9brFyK4F7AQNGw== +-----END PRIVATE KEY----- diff --git a/examples/espidf-coap-server/src/coap_server_example_main.c b/examples/espidf-coap-server/src/coap_server_example_main.c index 58a698d8a..ed96cc6e2 100644 --- a/examples/espidf-coap-server/src/coap_server_example_main.c +++ b/examples/espidf-coap-server/src/coap_server_example_main.c @@ -29,15 +29,10 @@ #include "protocol_examples_common.h" -#if 1 -/* Needed until coap_dtls.h becomes a part of libcoap proper */ -#include "libcoap.h" -#include "coap_dtls.h" -#endif -#include "coap.h" +#include "coap3/coap.h" /* The examples use simple Pre-Shared-Key configuration that you can set via - 'make menuconfig'. + 'idf.py menuconfig'. If you'd rather not, just change the below entries to strings with the config you want - ie #define EXAMPLE_COAP_PSK_KEY "some-agreed-preshared-key" @@ -49,7 +44,7 @@ #define EXAMPLE_COAP_PSK_KEY CONFIG_EXAMPLE_COAP_PSK_KEY /* The examples use CoAP Logging Level that - you can set via 'make menuconfig'. + you can set via 'idf.py menuconfig'. If you'd rather not, just change the below entry to a value that is between 0 and 7 with @@ -67,8 +62,10 @@ static int espressif_data_len = 0; Server cert, taken from coap_server.crt Server key, taken from coap_server.key - The PEM, CRT and KEY file are examples taken from the wpa2 enterprise - example. + The PEM, CRT and KEY file are examples taken from + https://github.com/eclipse/californium/tree/master/demo-certs/src/main/resources + as the Certificate test (by default) for the coap_client is against the + californium server. To embed it in the app binary, the PEM, CRT and KEY file is named in the component.mk COMPONENT_EMBED_TXTFILES variable. @@ -87,39 +84,42 @@ extern uint8_t server_key_end[] asm("_binary_coap_server_key_end"); * The resource handler */ static void -hnd_espressif_get(coap_context_t *ctx, coap_resource_t *resource, +hnd_espressif_get(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, coap_binary_t *token, - coap_string_t *query, coap_pdu_t *response) + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response) { - coap_add_data_blocked_response(resource, session, request, response, token, - COAP_MEDIATYPE_TEXT_PLAIN, 0, - (size_t)espressif_data_len, - (const u_char *)espressif_data); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, 60, 0, + (size_t)espressif_data_len, + (const u_char *)espressif_data, + NULL, NULL); } static void -hnd_espressif_put(coap_context_t *ctx, - coap_resource_t *resource, +hnd_espressif_put(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, - coap_binary_t *token, - coap_string_t *query, + const coap_pdu_t *request, + const coap_string_t *query, coap_pdu_t *response) { size_t size; - unsigned char *data; + size_t offset; + size_t total; + const unsigned char *data; coap_resource_notify_observers(resource, NULL); if (strcmp (espressif_data, INITIAL_DATA) == 0) { - response->code = COAP_RESPONSE_CODE(201); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); } else { - response->code = COAP_RESPONSE_CODE(204); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); } - /* coap_get_data() sets size to 0 on error */ - (void)coap_get_data(request, &size, &data); + /* coap_get_data_large() sets size to 0 on error */ + (void)coap_get_data_large(request, &size, &data, &offset, &total); if (size == 0) { /* re-init */ snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); @@ -131,18 +131,16 @@ hnd_espressif_put(coap_context_t *ctx, } static void -hnd_espressif_delete(coap_context_t *ctx, - coap_resource_t *resource, +hnd_espressif_delete(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, - coap_binary_t *token, - coap_string_t *query, + const coap_pdu_t *request, + const coap_string_t *query, coap_pdu_t *response) { coap_resource_notify_observers(resource, NULL); snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); espressif_data_len = strlen(espressif_data); - response->code = COAP_RESPONSE_CODE(202); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); } #ifdef CONFIG_COAP_MBEDTLS_PKI @@ -163,6 +161,18 @@ verify_cn_callback(const char *cn, } #endif /* CONFIG_COAP_MBEDTLS_PKI */ +static void +coap_log_handler (coap_log_t level, const char *message) +{ + uint32_t esp_level = ESP_LOG_INFO; + char *cp = strchr(message, '\n'); + + if (cp) + ESP_LOG_LEVEL(esp_level, TAG, "%.*s", (int)(cp-message), message); + else + ESP_LOG_LEVEL(esp_level, TAG, "%s", message); +} + static void coap_example_server(void *p) { coap_context_t *ctx = NULL; @@ -171,6 +181,7 @@ static void coap_example_server(void *p) snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); espressif_data_len = strlen(espressif_data); + coap_set_log_handler(coap_log_handler); coap_set_log_level(EXAMPLE_COAP_LOG_DEFAULT_LEVEL); while (1) { @@ -179,15 +190,16 @@ static void coap_example_server(void *p) /* Prepare the CoAP server socket */ coap_address_init(&serv_addr); - serv_addr.addr.sin.sin_family = AF_INET; - serv_addr.addr.sin.sin_addr.s_addr = INADDR_ANY; - serv_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT); + serv_addr.addr.sin6.sin6_family = AF_INET6; + serv_addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); ctx = coap_new_context(NULL); if (!ctx) { ESP_LOGE(TAG, "coap_new_context() failed"); continue; } + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY); #ifdef CONFIG_COAP_MBEDTLS_PSK /* Need PSK setup before we set up endpoints */ coap_context_set_psk(ctx, "CoAP", @@ -196,6 +208,7 @@ static void coap_example_server(void *p) #endif /* CONFIG_COAP_MBEDTLS_PSK */ #ifdef CONFIG_COAP_MBEDTLS_PKI + /* Need PKI setup before we set up endpoints */ unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start; unsigned int server_crt_bytes = server_crt_end - server_crt_start; unsigned int server_key_bytes = server_key_end - server_key_start; @@ -214,7 +227,7 @@ static void coap_example_server(void *p) * define what checking actually takes place. */ dtls_pki.verify_peer_cert = 1; - dtls_pki.require_peer_cert = 1; + dtls_pki.check_common_ca = 1; dtls_pki.allow_self_signed = 1; dtls_pki.allow_expired_certs = 1; dtls_pki.cert_chain_validation = 1; @@ -256,7 +269,7 @@ static void coap_example_server(void *p) /* This is not critical as unencrypted support is still available */ ESP_LOGI(TAG, "MbedTLS (D)TLS Server Mode not configured"); #else /* CONFIG_MBEDTLS_TLS_SERVER */ - serv_addr.addr.sin.sin_port = htons(COAPS_DEFAULT_PORT); + serv_addr.addr.sin6.sin6_port = htons(COAPS_DEFAULT_PORT); ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_DTLS); if (!ep) { ESP_LOGE(TAG, "dtls: coap_new_endpoint() failed"); @@ -267,7 +280,7 @@ static void coap_example_server(void *p) /* This is not critical as unencrypted support is still available */ ESP_LOGI(TAG, "MbedTLS (D)TLS Server Mode not configured"); } -#endif /* CONFIG_COAP_MBEDTLS_PSK CONFIG_COAP_MBEDTLS_PKI */ +#endif /* CONFIG_COAP_MBEDTLS_PSK || CONFIG_COAP_MBEDTLS_PKI */ resource = coap_resource_init(coap_make_str_const("Espressif"), 0); if (!resource) { ESP_LOGE(TAG, "coap_resource_init() failed"); @@ -280,10 +293,26 @@ static void coap_example_server(void *p) coap_resource_set_get_observable(resource, 1); coap_add_resource(ctx, resource); +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV4) || defined(CONFIG_EXAMPLE_COAP_MCAST_IPV6) + esp_netif_t *netif = NULL; + for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) { + char buf[8]; + netif = esp_netif_next(netif); + esp_netif_get_netif_impl_name(netif, buf); +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV4) + coap_join_mcast_group_intf(ctx, CONFIG_EXAMPLE_COAP_MULTICAST_IPV4_ADDR, buf); +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV4 */ +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV6) + /* When adding IPV6 esp-idf requires ifname param to be filled in */ + coap_join_mcast_group_intf(ctx, CONFIG_EXAMPLE_COAP_MULTICAST_IPV6_ADDR, buf); +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV6 */ + } +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV4 || CONFIG_EXAMPLE_COAP_MCAST_IPV6 */ + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; while (1) { - int result = coap_run_once(ctx, wait_ms); + int result = coap_io_process(ctx, wait_ms); if (result < 0) { break; } else if (result && (unsigned)result < wait_ms) { diff --git a/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c b/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c index 1d82721db..2da369c2c 100644 --- a/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c +++ b/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c @@ -39,7 +39,7 @@ void app_main(void) { .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, // USB version. 0x0200 means version 2.0 .bDeviceClass = TUSB_CLASS_UNSPECIFIED, - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0x303A, .idProduct = 0x3000, diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index 6a90a5909..81c69c1ee 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -32,7 +32,7 @@ class Esp32ExceptionDecoder(DeviceMonitorFilter): def __call__(self): self.buffer = "" self.backtrace_re = re.compile( - r"^Backtrace: ?((0x[0-9a-fA-F]+:0x[0-9a-fA-F]+ ?)+)\s*" + r"^Backtrace: ?((0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8} ?)+)\s*" ) self.firmware_path = None diff --git a/platform.json b/platform.json index 39b3e15d3..2a5f574c8 100644 --- a/platform.json +++ b/platform.json @@ -16,9 +16,9 @@ }, "repository": { "type": "git", - "url": "https://github.com/platformio/platform-espressif32.git" + "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "3.4.0", + "version": "2.0.3", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -49,6 +49,7 @@ "packages": { "toolchain-xtensa32": { "type": "toolchain", + "optional": true, "owner": "platformio", "version": "~2.50200.0", "optionalVersions": ["~2.80400.0"] @@ -89,17 +90,35 @@ "owner": "espressif", "version": "8.4.0+2021r2-patch2" }, + "toolchain-xtensa-esp32s3": { + "type": "toolchain", + "optional": true, + "owner": "espressif", + "version": "8.4.0+2021r2-patch2" + }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", "version": "8.4.0+2021r2-patch2" }, + "toolchain-esp32ulp": { + "type": "toolchain", + "optional": true, + "owner": "platformio", + "version": "~1.22851.0" + }, + "toolchain-esp32s2ulp": { + "type": "toolchain", + "optional": true, + "owner": "platformio", + "version": "~1.22851.0" + }, "framework-arduinoespressif32": { "type": "framework", "optional": true, - "owner": "platformio", - "version": "~3.10006.0" + "owner": "tasmota", + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/773/framework-arduinoespressif32-v4.4_dev-40d126bfd1.tar.gz" }, "framework-arduino-mbcwb": { "type": "framework", @@ -111,8 +130,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.40302.0", - "optionalVersions": ["~3.40001.0"] + "version": "https://github.com/tasmota/esp-idf/releases/download/v.4.4.0/esp-idf-v4.4.zip" }, "framework-simba": { "type": "framework", @@ -128,8 +146,8 @@ }, "tool-esptoolpy": { "type": "uploader", - "owner": "platformio", - "version": "~1.30100.0" + "owner": "tasmota", + "version": "https://github.com/tasmota/esptool/releases/download/v3.2.3/esptool-3.2.3.zip" }, "tool-mbctool": { "optional": true, @@ -144,10 +162,14 @@ }, "tool-mkspiffs": { "type": "uploader", - "optional": true, "owner": "platformio", "version": "~2.230.0" }, + "tool-mklittlefs": { + "type": "uploader", + "owner": "platformio", + "version": "~1.203.0" + }, "tool-cmake": { "optional": true, "owner": "platformio", diff --git a/platform.py b/platform.py index f620980cd..5d7ee1456 100644 --- a/platform.py +++ b/platform.py @@ -28,74 +28,62 @@ def configure_default_packages(self, variables, targets): board_config = self.board_config(variables.get("board")) mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32")) frameworks = variables.get("pioframework", []) - - # Legacy toolchain names are default value. This logic is temporary as the - # platform is gradually being switched to the toolchain packages from the - # Espressif organization. - - xtensa32_toolchain = "toolchain-xtensa32" - xtensa32s2_toolchain = "toolchain-xtensa32s2" - riscv_toolchain = "toolchain-riscv-esp" - if "buildfs" in targets: self.packages["tool-mkspiffs"]["optional"] = False + self.packages['tool-mklittlefs']['optional'] = False if variables.get("upload_protocol"): self.packages["tool-openocd-esp32"]["optional"] = False if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False - if "espidf" in frameworks: - # Legacy setting for mixed IDF+Arduino projects - if "arduino" in frameworks: - self.packages[xtensa32_toolchain]["version"] = "~2.80400.0" - # Arduino component is not compatible with ESP-IDF >=4.1 - self.packages["framework-espidf"]["version"] = "~3.40001.0" - else: - xtensa32_toolchain = "toolchain-xtensa-esp32" - xtensa32s2_toolchain = "toolchain-xtensa-esp32s2" - riscv_toolchain = "toolchain-riscv32-esp" - - for p in self.packages.copy(): - # Disable old toolchains used by default - if ( - p.startswith("toolchain") - and "ulp" not in p - ): - if self.packages[p]["owner"] == "espressif": - self.packages[p]["optional"] = False - else: - del self.packages[p] + xtensa_toolchain = "toolchain-xtensa-esp32" + xtensa32s2_toolchain = "toolchain-xtensa-esp32s2" + xtensa32s3_toolchain = "toolchain-xtensa-esp32s3" + riscv_toolchain = "toolchain-riscv32-esp" + + if "espidf" in frameworks: for p in self.packages: if p in ("tool-cmake", "tool-ninja", "toolchain-%sulp" % mcu): self.packages[p]["optional"] = False elif p in ("tool-mconf", "tool-idf") and "windows" in get_systype(): self.packages[p]["optional"] = False - else: - # Remove the latest toolchains from PATH for frameworks except IDF - for toolchain in ( - "toolchain-xtensa-esp32", - "toolchain-xtensa-esp32s2", - "toolchain-riscv32-esp", - ): - self.packages.pop(toolchain, None) - - if mcu in ("esp32s2", "esp32c3"): - self.packages.pop(xtensa32_toolchain, None) + self.packages[xtensa_toolchain]["version"] = "8.4.0+2021r2-patch2" + self.packages[xtensa_toolchain]["optional"] = False + + if "arduino" in frameworks: + self.packages[xtensa_toolchain]["version"] = "8.4.0+2021r2-patch2" + self.packages[xtensa_toolchain]["optional"] = False + + if mcu in ("esp32s2", "esp32s3", "esp32c3"): + self.packages.pop(xtensa_toolchain, None) self.packages.pop("toolchain-esp32ulp", None) # RISC-V based toolchain for ESP32C3 and ESP32S2 ULP self.packages[riscv_toolchain]["optional"] = False if mcu == "esp32s2": self.packages[xtensa32s2_toolchain]["optional"] = False + self.packages["toolchain-esp32s2ulp"]["optional"] = False + if mcu == "esp32s3": + self.packages[xtensa32s3_toolchain]["optional"] = False + self.packages["toolchain-esp32s2ulp"]["optional"] = False build_core = variables.get( "board_build.core", board_config.get("build.core", "arduino") ).lower() - if build_core == "mbcwb": + if "arduino" in frameworks and build_core == "mbcwb": + # Briki MCB core packages depend on previous toolchain packages + self.packages.pop("toolchain-xtensa-esp32", None) + self.packages["toolchain-xtensa32"]["optional"] = False + self.packages["toolchain-xtensa32"]["version"] = "~2.50200.0" self.packages["framework-arduinoespressif32"]["optional"] = True self.packages["framework-arduino-mbcwb"]["optional"] = False self.packages["tool-mbctool"]["type"] = "uploader" self.packages["tool-mbctool"]["optional"] = False + if set(("simba", "pumbaa")) & set(frameworks): + # Legacy frameworks depend on previous toolchain packages + self.packages["toolchain-xtensa32"]["optional"] = False + self.packages["toolchain-xtensa32"]["version"] = "~2.50200.0" + return PlatformBase.configure_default_packages(self, variables, targets) def get_boards(self, id_=None): @@ -241,10 +229,7 @@ def configure_debug_options(self, initial_debug_options, ide_data): if "openocd" in debug_options["server"].get("executable", ""): debug_options["server"]["arguments"].extend( - [ - "-c", - "adapter_khz %s" % (initial_debug_options.get("speed") or "5000"), - ] + ["-c", "adapter_khz %s" % (initial_debug_options.get("speed") or "5000")] ) ignore_conds = [ From cf24146819dabdfbbc8e4ac6ab1dc660e482627c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 23 Mar 2022 12:18:36 +0100 Subject: [PATCH 002/666] Tasmota esptool v3.3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 2a5f574c8..776ff3beb 100644 --- a/platform.json +++ b/platform.json @@ -147,7 +147,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v3.2.3/esptool-3.2.3.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v3.3/esptool-3.3.zip" }, "tool-mbctool": { "optional": true, From 021c867daaa67dc6ae427ca68d27a06ebfbb6d5c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Mar 2022 17:06:21 +0200 Subject: [PATCH 003/666] toolchain-xtensa 8.4.0+2021r2-patch3 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 776ff3beb..92bd4fe3c 100644 --- a/platform.json +++ b/platform.json @@ -82,25 +82,25 @@ "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch2" + "version": "8.4.0+2021r2-patch3" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch2" + "version": "8.4.0+2021r2-patch3" }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch2" + "version": "8.4.0+2021r2-patch3" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch2" + "version": "8.4.0+2021r2-patch3" }, "toolchain-esp32ulp": { "type": "toolchain", From 4f9a5f8921c0e113194368e780765a80e09c477c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Mar 2022 17:25:44 +0200 Subject: [PATCH 004/666] 8.4.0+2021r2-patch3 --- platform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.py b/platform.py index 5d7ee1456..c5c5d5082 100644 --- a/platform.py +++ b/platform.py @@ -47,11 +47,11 @@ def configure_default_packages(self, variables, targets): self.packages[p]["optional"] = False elif p in ("tool-mconf", "tool-idf") and "windows" in get_systype(): self.packages[p]["optional"] = False - self.packages[xtensa_toolchain]["version"] = "8.4.0+2021r2-patch2" + self.packages[xtensa_toolchain]["version"] = "8.4.0+2021r2-patch3" self.packages[xtensa_toolchain]["optional"] = False if "arduino" in frameworks: - self.packages[xtensa_toolchain]["version"] = "8.4.0+2021r2-patch2" + self.packages[xtensa_toolchain]["version"] = "8.4.0+2021r2-patch3" self.packages[xtensa_toolchain]["optional"] = False if mcu in ("esp32s2", "esp32s3", "esp32c3"): From 948c46dbbdb5c24c9ea543358e116bc0b0cbab34 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Mar 2022 18:08:41 +0200 Subject: [PATCH 005/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 92bd4fe3c..0fcbf5f3a 100644 --- a/platform.json +++ b/platform.json @@ -118,7 +118,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/773/framework-arduinoespressif32-v4.4_dev-40d126bfd1.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/789/framework-arduinoespressif32-v4.4_dev-40d126bfd1.tar.gz" }, "framework-arduino-mbcwb": { "type": "framework", From cd9375a6e4082ec1ae964d3a2a671a3eda26ba86 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 31 Mar 2022 16:20:03 +0200 Subject: [PATCH 006/666] Revert https://github.com/espressif/arduino-esp32/pull/6456 since it generates crashes --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 0fcbf5f3a..5d24186c8 100644 --- a/platform.json +++ b/platform.json @@ -118,7 +118,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/789/framework-arduinoespressif32-v4.4_dev-40d126bfd1.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/803/framework-arduinoespressif32-v4.4_dev-40d126bfd1.tar.gz" }, "framework-arduino-mbcwb": { "type": "framework", From f766d98dddf4e60bd5be126eadb05580f37cdc22 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 4 Apr 2022 12:38:05 +0200 Subject: [PATCH 007/666] Add files via upload --- boards/adafruit_qt_py_esp32-c3.json | 34 +++++++++++++++++++++++++++++ boards/esp32-c3-mini.json | 34 +++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 boards/adafruit_qt_py_esp32-c3.json create mode 100644 boards/esp32-c3-mini.json diff --git a/boards/adafruit_qt_py_esp32-c3.json b/boards/adafruit_qt_py_esp32-c3.json new file mode 100644 index 000000000..515397eac --- /dev/null +++ b/boards/adafruit_qt_py_esp32-c3.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5405", + "vendor": "Adafruit" +} diff --git a/boards/esp32-c3-mini.json b/boards/esp32-c3-mini.json new file mode 100644 index 000000000..936f27c26 --- /dev/null +++ b/boards/esp32-c3-mini.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-C3-MINI", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html", + "vendor": "Espressif" +} From 399ac09a0f47f38e7f83880ee274d72a46092012 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 4 Apr 2022 15:50:32 +0200 Subject: [PATCH 008/666] Add files via upload --- boards/esp32-s3-usb.json | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 boards/esp32-s3-usb.json diff --git a/boards/esp32-s3-usb.json b/boards/esp32-s3-usb.json new file mode 100644 index 000000000..92daae518 --- /dev/null +++ b/boards/esp32-s3-usb.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qspi_qspi" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S3-DevKitC-1", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 524288, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html", + "vendor": "Espressif" +} From a1f4b045016b0c26a7a93dbb681f6384b08bfe58 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 4 Apr 2022 15:56:06 +0200 Subject: [PATCH 009/666] Add files via upload --- boards/esp32-s2-usb.json | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 boards/esp32-s2-usb.json diff --git a/boards/esp32-s2-usb.json b/boards/esp32-s2-usb.json new file mode 100644 index 000000000..9ef92b3e2 --- /dev/null +++ b/boards/esp32-s2-usb.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s2", + "variant": "adafruit_qtpy_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5325", + "vendor": "Adafruit" +} From efa7e17244ce5900cf40b330e65aa431ec502b7e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 18 Apr 2022 14:12:44 +0200 Subject: [PATCH 010/666] Update featheresp32-s2.json --- boards/featheresp32-s2.json | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/boards/featheresp32-s2.json b/boards/featheresp32-s2.json index 47387f578..bf6f0cbc2 100644 --- a/boards/featheresp32-s2.json +++ b/boards/featheresp32-s2.json @@ -4,12 +4,29 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80EB" + ], + [ + "0x239A", + "0x00EB" + ], + [ + "0x239A", + "0x80EC" + ] + ], "mcu": "esp32s2", - "variant": "esp32s2" + "variant": "adafruit_feather_esp32s2" }, "connectivity": [ "wifi" @@ -23,9 +40,19 @@ ], "name": "Adafruit ESP32-S2 Feather Development Board", "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2/tinyuf2.bin" + ] + ] + }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, "require_upload_port": true, "speed": 460800 }, From 405f3b4ad7838d2822cc905911c2a0dfff247ba2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 18 Apr 2022 14:13:21 +0200 Subject: [PATCH 011/666] Update main.py --- builder/main.py | 141 ++++++++++++++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 52 deletions(-) diff --git a/builder/main.py b/builder/main.py index 58912d2a4..52cd1370c 100644 --- a/builder/main.py +++ b/builder/main.py @@ -20,11 +20,28 @@ ARGUMENTS, COMMAND_LINE_TARGETS, AlwaysBuild, Builder, Default, DefaultEnvironment) +from platformio.util import get_serial_ports + # # Helpers # +def BeforeUpload(target, source, env): + upload_options = {} + if "BOARD" in env: + upload_options = env.BoardConfig().get("upload", {}) + + env.AutodetectUploadPort() + + before_ports = get_serial_ports() + if upload_options.get("use_1200bps_touch", False): + env.TouchSerialPort("$UPLOAD_PORT", 1200) + + if upload_options.get("wait_for_upload_port", False): + env.Replace(UPLOAD_PORT=env.WaitForNewSerialPort(before_ports)) + + def _get_board_f_flash(env): frequency = env.subst("$BOARD_F_FLASH") frequency = str(frequency).replace("L", "") @@ -102,54 +119,53 @@ def _update_max_upload_size(env): def _to_unix_slashes(path): - return path.replace('\\', '/') + return path.replace("\\", "/") # -# FS helpers +# Filesystem helpers # -env = DefaultEnvironment() -env.SConscript("compat.py", exports="env") -platform = env.PioPlatform() -board = env.BoardConfig() -filesystem = board.get("build.filesystem", "spiffs") -print("FILESYSTEM ", filesystem) -mcu = board.get("build.mcu", "esp32") -toolchain_arch = "xtensa-%s" % mcu -if mcu == "esp32c3": - toolchain_arch = "riscv32-esp" def fetch_fs_size(env): fs = None for p in _parse_partitions(env): - # The option to use a partition subtype of "spiffs" eliminates the - # need to simultaneously update both this platform code and the - # framework code that handles partitions. You can use a framwork - # that only supports partitions named "spiffs", putting a LittleFS - # image therein. Going forward, the framework code can be updated - # to support partitions named "littlefs" and the code here will - # continue to work. - if p['type'] == "data" and (p['subtype'] == filesystem or p['subtype'] == "spiffs"): + if p["type"] == "data" and p["subtype"] in ("spiffs", "fat"): fs = p if not fs: sys.stderr.write( - "Could not find the `%s` section in the partitions " - "table %s\n" % (filesystem, env.subst("$PARTITIONS_TABLE_CSV")) + "Could not find the any filesystem section in the partitions " + "table %s\n" % env.subst("$PARTITIONS_TABLE_CSV") ) env.Exit(1) return - env["FS_START"] = _parse_size(fs['offset']) - env["FS_SIZE"] = _parse_size(fs['size']) + env["FS_START"] = _parse_size(fs["offset"]) + env["FS_SIZE"] = _parse_size(fs["size"]) env["FS_PAGE"] = int("0x100", 16) env["FS_BLOCK"] = int("0x1000", 16) + # FFat specific offsets, see: + # https://github.com/lorol/arduino-esp32fatfs-plugin#notes-for-fatfs + if filesystem == "fatfs": + env["FS_START"] += 4096 + env["FS_SIZE"] -= 4096 + def __fetch_fs_size(target, source, env): fetch_fs_size(env) return (target, source) +env = DefaultEnvironment() +env.SConscript("compat.py", exports="env") +platform = env.PioPlatform() +board = env.BoardConfig() +mcu = board.get("build.mcu", "esp32") +toolchain_arch = "xtensa-%s" % mcu +filesystem = board.get("build.filesystem", "spiffs") +if mcu == "esp32c3": + toolchain_arch = "riscv32-esp" + env.Replace( __get_board_f_flash=_get_board_f_flash, __get_board_flash_mode=_get_board_flash_mode, @@ -177,10 +193,25 @@ def __fetch_fs_size(target, source, env): ], ERASECMD='"$PYTHONEXE" "$OBJCOPY" $ERASEFLAGS erase_flash', - MKFSTOOL=("mklittlefs" if filesystem == "littlefs" else - "mkspiffs_${PIOPLATFORM}_" + ("espidf" if "espidf" in env.subst("$PIOFRAMEWORK") else "${PIOFRAMEWORK}")), - ESP32_FS_IMAGE_NAME=env.get("ESP32_FS_IMAGE_NAME", env.get( - "ESP32_SPIFFS_IMAGE_NAME", filesystem)), + # mkspiffs package contains two different binaries for IDF and Arduino + MKFSTOOL="mk%s" % filesystem + + ( + ( + "_${PIOPLATFORM}_" + + ( + "espidf" + if "espidf" in env.subst("$PIOFRAMEWORK") + else "${PIOFRAMEWORK}" + ) + ) + if filesystem == "spiffs" + else "" + ), + # Legacy `ESP32_SPIFFS_IMAGE_NAME` is used as the second fallback value for + # backward compatibility + ESP32_FS_IMAGE_NAME=env.get( + "ESP32_FS_IMAGE_NAME", env.get("ESP32_SPIFFS_IMAGE_NAME", filesystem) + ), ESP32_APP_OFFSET="0x10000", PROGSUFFIX=".elf" @@ -197,9 +228,9 @@ def __fetch_fs_size(target, source, env): BUILDERS=dict( ElfToBin=Builder( action=env.VerboseAction(" ".join([ - '"$PYTHONEXE" "$OBJCOPY"', + '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, - "elf2image", + "elf2image", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "detect"), @@ -208,18 +239,27 @@ def __fetch_fs_size(target, source, env): suffix=".bin" ), DataToBin=Builder( - action=env.VerboseAction(" ".join([ - '"$MKFSTOOL"', - "-c", "$SOURCES", - "-p", "$FS_PAGE", - "-b", "$FS_BLOCK", - "-s", "$FS_SIZE", - "$TARGET" - ]), "Building FS image from '$SOURCES' directory to $TARGET"), + action=env.VerboseAction( + " ".join( + ['"$MKFSTOOL"', "-c", "$SOURCES", "-s", "$FS_SIZE"] + + ( + [ + "-p", + "$FS_PAGE", + "-b", + "$FS_BLOCK", + ] + if filesystem in ("spiffs", "littlefs") + else [] + ) + + ["$TARGET"] + ), + "Building FS image from '$SOURCES' directory to $TARGET", + ), emitter=__fetch_fs_size, source_factory=env.Dir, - suffix=".bin" - ) + suffix=".bin", + ), ) ) @@ -241,11 +281,9 @@ def __fetch_fs_size(target, source, env): else: target_elf = env.BuildProgram() if set(["buildfs", "uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): - if filesystem not in ("littlefs", "spiffs"): - sys.stderr.write("Filesystem %s is not supported!\n" % filesystem) - env.Exit(1) target_firm = env.DataToBin( - join("$BUILD_DIR", "${ESP32_SPIFFS_IMAGE_NAME}"), "$PROJECT_DATA_DIR") + join("$BUILD_DIR", "${ESP32_FS_IMAGE_NAME}"), "$PROJECT_DATA_DIR" + ) env.NoCache(target_firm) AlwaysBuild(target_firm) else: @@ -281,7 +319,7 @@ def __fetch_fs_size(target, source, env): ) # -# Target: Upload firmware or filesystem image +# Target: Upload firmware or FS image # upload_protocol = env.subst("$UPLOAD_PROTOCOL") @@ -315,7 +353,7 @@ def __fetch_fs_size(target, source, env): UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS -f $SOURCE' ) if set(["uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): - env.Append(UPLOADERFLAGS=["-s"]) + env.Append(UPLOADERFLAGS=["--spiffs"]) upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")] elif upload_protocol == "esptool": @@ -349,14 +387,13 @@ def __fetch_fs_size(target, source, env): "write_flash", "-z", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_size", "detect", - "$FS_START" + "$SPIFFS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', ) upload_actions = [ - env.VerboseAction(env.AutodetectUploadPort, - "Looking for upload port..."), + env.VerboseAction(BeforeUpload, "Looking for upload port..."), env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE") ] @@ -394,13 +431,13 @@ def __fetch_fs_size(target, source, env): debug_tools.get(upload_protocol).get("server").get("arguments", [])) openocd_args.extend([ "-c", "adapter_khz %s" % env.GetProjectOption("debug_speed", "5000"), - "-c", + "-c", "program_esp {{$SOURCE}} %s verify" % board.get("upload.offset_address", "$ESP32_APP_OFFSET"), ]) for image in env.get("FLASH_EXTRA_IMAGES", []): openocd_args.extend([ - "-c", + "-c", 'program_esp {{%s}} %s verify' % (_to_unix_slashes(image[1]), image[0]) ]) @@ -413,7 +450,7 @@ def __fetch_fs_size(target, source, env): for f in openocd_args ] env.Replace(UPLOADER="openocd", - UPLOADERFLAGS=openocd_args, + UPLOADERFLAGS=openocd_args, UPLOADCMD="$UPLOADER $UPLOADERFLAGS") upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")] From 3797869e2a90d7ece6c9e9e905be73e98189bc0f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 18 Apr 2022 14:14:06 +0200 Subject: [PATCH 012/666] Update platform.json --- platform.json | 64 +++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/platform.json b/platform.json index 5d24186c8..c06bf0ee4 100644 --- a/platform.json +++ b/platform.json @@ -9,7 +9,7 @@ "Wi-Fi", "Bluetooth", "Xtensa", - "LX6" + "RISC-V" ], "engines": { "platformio": "^5" @@ -47,60 +47,40 @@ } }, "packages": { - "toolchain-xtensa32": { - "type": "toolchain", - "optional": true, - "owner": "platformio", - "version": "~2.50200.0", - "optionalVersions": ["~2.80400.0"] - }, - "toolchain-xtensa32s2": { - "type": "toolchain", - "optional": true, - "owner": "platformio", - "version": "~1.80400.0" - }, - "toolchain-esp32ulp": { - "type": "toolchain", - "optional": true, - "owner": "platformio", - "version": "~1.22851.0" - }, - "toolchain-esp32s2ulp": { - "type": "toolchain", - "optional": true, - "owner": "platformio", - "version": "~1.22851.0" - }, - "toolchain-riscv-esp": { - "type": "toolchain", - "optional": true, - "owner": "platformio", - "version": "~1.80400.0" - }, "toolchain-xtensa-esp32": { "type": "toolchain", - "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3" + "version": "8.4.0+2021r2-patch3", + "optionalVersions": [ + "8.4.0+2021r2-patch2" + ] }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3" + "version": "8.4.0+2021r2-patch3", + "optionalVersions": [ + "8.4.0+2021r2-patch2" + ] }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3" + "version": "8.4.0+2021r2-patch3", + "optionalVersions": [ + "8.4.0+2021r2-patch2" + ] }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3" + "version": "8.4.0+2021r2-patch3", + "optionalVersions": [ + "8.4.0+2021r2-patch2" + ] }, "toolchain-esp32ulp": { "type": "toolchain", @@ -158,18 +138,26 @@ "type": "debugger", "optional": true, "owner": "platformio", - "version": "~2.1000.0" + "version": "~2.1100.0" }, "tool-mkspiffs": { "type": "uploader", + "optional": true, "owner": "platformio", "version": "~2.230.0" }, "tool-mklittlefs": { "type": "uploader", + "optional": true, "owner": "platformio", "version": "~1.203.0" }, + "tool-mkfatfs": { + "type": "uploader", + "optional": true, + "owner": "platformio", + "version": "~2.0.0" + }, "tool-cmake": { "optional": true, "owner": "platformio", From e5c46510a3eec638b16a098670b3085b81c26704 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 18 Apr 2022 14:14:39 +0200 Subject: [PATCH 013/666] Update platform.py --- platform.py | 225 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 188 insertions(+), 37 deletions(-) diff --git a/platform.py b/platform.py index c5c5d5082..26d58d456 100644 --- a/platform.py +++ b/platform.py @@ -14,6 +14,11 @@ import copy import os +import urllib +import sys +import json +import re +import requests from platformio import fs from platformio.managers.platform import PlatformBase @@ -28,61 +33,107 @@ def configure_default_packages(self, variables, targets): board_config = self.board_config(variables.get("board")) mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32")) frameworks = variables.get("pioframework", []) + if "buildfs" in targets: - self.packages["tool-mkspiffs"]["optional"] = False - self.packages['tool-mklittlefs']['optional'] = False + filesystem = variables.get("board_build.filesystem", "spiffs") + if filesystem == "littlefs": + self.packages["tool-mklittlefs"]["optional"] = False + elif filesystem == "fatfs": + self.packages["tool-mkfatfs"]["optional"] = False + else: + self.packages["tool-mkspiffs"]["optional"] = False if variables.get("upload_protocol"): self.packages["tool-openocd-esp32"]["optional"] = False if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False - xtensa_toolchain = "toolchain-xtensa-esp32" - xtensa32s2_toolchain = "toolchain-xtensa-esp32s2" - xtensa32s3_toolchain = "toolchain-xtensa-esp32s3" - riscv_toolchain = "toolchain-riscv32-esp" - + build_core = variables.get( + "board_build.core", board_config.get("build.core", "arduino") + ).lower() + + if len(frameworks) == 1 and "arduino" in frameworks and build_core == "esp32": + # In case the upstream Arduino framework is specified in the configuration + # file then we need to dynamically extract toolchain versions from the + # Arduino index file. This feature can be disabled via a special option: + if ( + variables.get( + "board_build.arduino.upstream_packages", + board_config.get("build.arduino.upstream_packages", "yes"), + ).lower() + == "yes" + ): + package_version = self.packages["framework-arduinoespressif32"][ + "version" + ] + + url_items = urllib.parse.urlparse(package_version) + # Only GitHub repositories support dynamic packages + if ( + url_items.scheme in ("http", "https") + and url_items.netloc.startswith("github") + and url_items.path.endswith(".git") + ): + try: + self.configure_upstream_arduino_packages(url_items) + except Exception as e: + sys.stderr.write( + "Error! Failed to extract upstream toolchain" + "configurations:\n%s\n" % str(e) + ) + sys.stderr.write( + "You can disable this feature via the " + "`board_build.arduino.upstream_packages = no` setting in " + "your `platformio.ini` file.\n" + ) + sys.exit(1) + if "espidf" in frameworks: + # Common package for IDF and mixed Arduino+IDF projects for p in self.packages: if p in ("tool-cmake", "tool-ninja", "toolchain-%sulp" % mcu): self.packages[p]["optional"] = False elif p in ("tool-mconf", "tool-idf") and "windows" in get_systype(): self.packages[p]["optional"] = False - self.packages[xtensa_toolchain]["version"] = "8.4.0+2021r2-patch3" - self.packages[xtensa_toolchain]["optional"] = False - - if "arduino" in frameworks: - self.packages[xtensa_toolchain]["version"] = "8.4.0+2021r2-patch3" - self.packages[xtensa_toolchain]["optional"] = False if mcu in ("esp32s2", "esp32s3", "esp32c3"): - self.packages.pop(xtensa_toolchain, None) + self.packages.pop("toolchain-xtensa-esp32", None) self.packages.pop("toolchain-esp32ulp", None) # RISC-V based toolchain for ESP32C3 and ESP32S2 ULP - self.packages[riscv_toolchain]["optional"] = False + self.packages["toolchain-riscv32-esp"]["optional"] = False if mcu == "esp32s2": - self.packages[xtensa32s2_toolchain]["optional"] = False - self.packages["toolchain-esp32s2ulp"]["optional"] = False + self.packages["toolchain-xtensa-esp32s2"]["optional"] = False if mcu == "esp32s3": - self.packages[xtensa32s3_toolchain]["optional"] = False - self.packages["toolchain-esp32s2ulp"]["optional"] = False + self.packages["toolchain-xtensa-esp32s3"]["optional"] = False - build_core = variables.get( - "board_build.core", board_config.get("build.core", "arduino") - ).lower() - if "arduino" in frameworks and build_core == "mbcwb": - # Briki MCB core packages depend on previous toolchain packages - self.packages.pop("toolchain-xtensa-esp32", None) - self.packages["toolchain-xtensa32"]["optional"] = False - self.packages["toolchain-xtensa32"]["version"] = "~2.50200.0" - self.packages["framework-arduinoespressif32"]["optional"] = True - self.packages["framework-arduino-mbcwb"]["optional"] = False - self.packages["tool-mbctool"]["type"] = "uploader" - self.packages["tool-mbctool"]["optional"] = False - - if set(("simba", "pumbaa")) & set(frameworks): - # Legacy frameworks depend on previous toolchain packages - self.packages["toolchain-xtensa32"]["optional"] = False - self.packages["toolchain-xtensa32"]["version"] = "~2.50200.0" + is_legacy_project = ( + build_core == "mbcwb" + or set(("simba", "pumbaa")) & set(frameworks) + ) + + if is_legacy_project: + # Remove the main toolchains from PATH + for toolchain in ( + "toolchain-xtensa-esp32", + "toolchain-xtensa-esp32s2", + "toolchain-xtensa-esp32s3", + "toolchain-riscv32-esp", + ): + self.packages.pop(toolchain, None) + + # Add legacy toolchain with specific version + self.packages["toolchain-xtensa32"] = { + "type": "toolchain", + "owner": "platformio", + "version": "~2.80400.0" + if "arduino" in frameworks and build_core != "mbcwb" + else "~2.50200.0", + } + + if build_core == "mbcwb": + self.packages["framework-arduinoespressif32"]["optional"] = True + self.packages["framework-arduino-mbcwb"]["optional"] = False + self.packages["tool-mbctool"]["type"] = "uploader" + self.packages["tool-mbctool"]["optional"] = False return PlatformBase.configure_default_packages(self, variables, targets) @@ -229,7 +280,10 @@ def configure_debug_options(self, initial_debug_options, ide_data): if "openocd" in debug_options["server"].get("executable", ""): debug_options["server"]["arguments"].extend( - ["-c", "adapter_khz %s" % (initial_debug_options.get("speed") or "5000")] + [ + "-c", + "adapter_khz %s" % (initial_debug_options.get("speed") or "5000"), + ] ) ignore_conds = [ @@ -256,3 +310,100 @@ def configure_debug_options(self, initial_debug_options, ide_data): ) debug_options["load_cmds"] = load_cmds return debug_options + + @staticmethod + def extract_toolchain_versions(tool_deps): + def _parse_version(original_version): + assert original_version + match = re.match(r"^gcc(\d+)_(\d+)_(\d+)\-esp\-(.+)$", original_version) + if not match: + raise ValueError("Bad package version `%s`" % original_version) + assert len(match.groups()) == 4 + return "%s.%s.%s+%s" % (match.groups()) + + if not tool_deps: + raise ValueError( + ("Failed to extract tool dependencies from the remote package file") + ) + + toolchain_remap = { + "xtensa-esp32-elf-gcc": "toolchain-xtensa-esp32", + "xtensa-esp32s2-elf-gcc": "toolchain-xtensa-esp32s2", + "xtensa-esp32s3-elf-gcc": "toolchain-xtensa-esp32s3", + "riscv32-esp-elf-gcc": "toolchain-riscv32-esp", + } + + result = dict() + for tool in tool_deps: + if tool["name"] in toolchain_remap: + result[toolchain_remap[tool["name"]]] = _parse_version(tool["version"]) + + return result + + @staticmethod + def parse_tool_dependencies(index_data): + for package in index_data.get("packages", []): + if package["name"] == "esp32": + for platform in package["platforms"]: + if platform["name"] == "esp32": + return platform["toolsDependencies"] + + return [] + + @staticmethod + def download_remote_package_index(url_items): + def _prepare_url_for_index_file(url_items): + tag = "master" + if url_items.fragment: + tag = url_items.fragment + return ( + "https://raw.githubusercontent.com/%s/" + "%s/package/package_esp32_index.template.json" + % (url_items.path.replace(".git", ""), tag) + ) + + index_file_url = _prepare_url_for_index_file(url_items) + r = requests.get(index_file_url, timeout=10) + if r.status_code != 200: + raise ValueError( + ( + "Failed to download package index file due to a bad response (%d) " + "from the remote `%s`" + ) + % (r.status_code, index_file_url) + ) + return r.json() + + def configure_arduino_toolchains(self, package_index): + if not package_index: + return + + toolchain_packages = self.extract_toolchain_versions( + self.parse_tool_dependencies(package_index) + ) + for toolchain_package, version in toolchain_packages.items(): + if toolchain_package not in self.packages: + self.packages[toolchain_package] = dict() + self.packages[toolchain_package]["version"] = version + self.packages[toolchain_package]["owner"] = "espressif" + + def configure_upstream_arduino_packages(self, url_items): + framework_index_file = os.path.join( + self.get_package_dir("framework-arduinoespressif32") or "", + "package", + "package_esp32_index.template.json", + ) + + # Detect whether the remote is already cloned + if os.path.isfile(framework_index_file) and os.path.isdir( + os.path.join( + self.get_package_dir("framework-arduinoespressif32") or "", ".git" + ) + ): + with open(framework_index_file) as fp: + self.configure_arduino_toolchains(json.load(fp)) + else: + print("Configuring toolchain packages from a remote source...") + self.configure_arduino_toolchains( + self.download_remote_package_index(url_items) + ) From dbc1471cde4b4d926232b9134bf4d078619d4057 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 18 Apr 2022 14:15:03 +0200 Subject: [PATCH 014/666] Integrate upstream develop changes --- .github/workflows/examples.yml | 2 + boards/adafruit_funhouse_esp32s2.json | 62 ++++++++++++++++ boards/adafruit_magtag29_esp32s2.json | 62 ++++++++++++++++ boards/adafruit_metro_esp32s2.json | 62 ++++++++++++++++ boards/adafruit_qtpy_esp32-s2.json | 34 +++++++++ boards/atmegazero_esp32s2.json | 53 ++++++++++++++ boards/az-delivery-devkit-v4.json | 2 +- boards/deneyapkart.json | 41 +++++++++++ boards/deneyapmini.json | 44 ++++++++++++ boards/denky32.json | 39 ++++++++++ boards/denky_d4.json | 37 ++++++++++ boards/esp32-c3-devkitm-1.json | 1 + boards/esp32-s2-franzininho.json | 1 + boards/esp32-s2-kaluga-1.json | 2 +- boards/esp32-s2-saola-1.json | 2 +- boards/franzininho_wifi_esp32s2.json | 45 ++++++++++++ boards/franzininho_wifi_msc_esp32s2.json | 47 ++++++++++++ boards/kb32-ft.json | 42 +++++++++++ boards/m5stack-fire.json | 7 +- boards/m5stack-timer-cam.json | 7 +- boards/micros2.json | 48 +++++++++++++ boards/sparkfun_esp32micromod.json | 34 +++++++++ boards/sparkfun_esp32s2_thing_plus.json | 43 +++++++++++ boards/tinypico.json | 11 ++- boards/trueverit-iot-driver-mk2.json | 37 ++++++++++ boards/trueverit-iot-driver.json | 37 ++++++++++ boards/ttgo-t-watch.json | 7 +- boards/um_feathers2.json | 46 ++++++++++++ boards/um_feathers2_neo.json | 46 ++++++++++++ boards/um_tinys2.json | 46 ++++++++++++ boards/upesy_wroom.json | 37 ++++++++++ boards/upesy_wrover.json | 42 +++++++++++ examples/arduino-ble5-advertising/.gitignore | 1 + examples/arduino-ble5-advertising/README.md | 27 +++++++ .../arduino-ble5-advertising/include/README | 39 ++++++++++ examples/arduino-ble5-advertising/lib/README | 46 ++++++++++++ .../arduino-ble5-advertising/platformio.ini | 14 ++++ .../src/BLE5_periodic_advertising.ino | 72 +++++++++++++++++++ examples/arduino-ble5-advertising/test/README | 11 +++ examples/arduino-usb-keyboard/.gitignore | 1 + examples/arduino-usb-keyboard/README.md | 27 +++++++ examples/arduino-usb-keyboard/include/README | 39 ++++++++++ examples/arduino-usb-keyboard/lib/README | 46 ++++++++++++ examples/arduino-usb-keyboard/platformio.ini | 19 +++++ .../src/KeyboardSerial.ino | 40 +++++++++++ examples/arduino-usb-keyboard/test/README | 11 +++ 46 files changed, 1410 insertions(+), 9 deletions(-) create mode 100644 boards/adafruit_funhouse_esp32s2.json create mode 100644 boards/adafruit_magtag29_esp32s2.json create mode 100644 boards/adafruit_metro_esp32s2.json create mode 100644 boards/adafruit_qtpy_esp32-s2.json create mode 100644 boards/atmegazero_esp32s2.json create mode 100644 boards/deneyapkart.json create mode 100644 boards/deneyapmini.json create mode 100644 boards/denky32.json create mode 100644 boards/denky_d4.json create mode 100644 boards/franzininho_wifi_esp32s2.json create mode 100644 boards/franzininho_wifi_msc_esp32s2.json create mode 100644 boards/kb32-ft.json create mode 100644 boards/micros2.json create mode 100644 boards/sparkfun_esp32micromod.json create mode 100644 boards/sparkfun_esp32s2_thing_plus.json create mode 100644 boards/trueverit-iot-driver-mk2.json create mode 100644 boards/trueverit-iot-driver.json create mode 100644 boards/um_feathers2.json create mode 100644 boards/um_feathers2_neo.json create mode 100644 boards/um_tinys2.json create mode 100644 boards/upesy_wroom.json create mode 100644 boards/upesy_wrover.json create mode 100644 examples/arduino-ble5-advertising/.gitignore create mode 100644 examples/arduino-ble5-advertising/README.md create mode 100644 examples/arduino-ble5-advertising/include/README create mode 100644 examples/arduino-ble5-advertising/lib/README create mode 100644 examples/arduino-ble5-advertising/platformio.ini create mode 100644 examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino create mode 100644 examples/arduino-ble5-advertising/test/README create mode 100644 examples/arduino-usb-keyboard/.gitignore create mode 100644 examples/arduino-usb-keyboard/README.md create mode 100644 examples/arduino-usb-keyboard/include/README create mode 100644 examples/arduino-usb-keyboard/lib/README create mode 100644 examples/arduino-usb-keyboard/platformio.ini create mode 100644 examples/arduino-usb-keyboard/src/KeyboardSerial.ino create mode 100644 examples/arduino-usb-keyboard/test/README diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 90cab3dcc..5f3048252 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -10,9 +10,11 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] python-version: [3.8] example: + - "examples/arduino-ble5-advertising" - "examples/arduino-blink" - "examples/arduino-rmt-blink" - "examples/arduino-briki-internal-libs" + - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/espidf-arduino-blink" - "examples/espidf-arduino-wifiscan" diff --git a/boards/adafruit_funhouse_esp32s2.json b/boards/adafruit_funhouse_esp32s2.json new file mode 100644 index 000000000..974761247 --- /dev/null +++ b/boards/adafruit_funhouse_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FUNHOUSE_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80F9" + ], + [ + "0x239A", + "0x00F9" + ], + [ + "0x239A", + "0x80FA" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_funhouse_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit FunHouse", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_funhouse_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4985", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_magtag29_esp32s2.json b/boards/adafruit_magtag29_esp32s2.json new file mode 100644 index 000000000..40d7bd3e9 --- /dev/null +++ b/boards/adafruit_magtag29_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_MAGTAG29_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80DF" + ], + [ + "0x239A", + "0x00DF" + ], + [ + "0x239A", + "0x80E0" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_magtag29_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit MagTag 2.9", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_magtag29_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4800", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_metro_esp32s2.json b/boards/adafruit_metro_esp32s2.json new file mode 100644 index 000000000..af8df2279 --- /dev/null +++ b/boards/adafruit_metro_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_METRO_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80DF" + ], + [ + "0x239A", + "0x00DF" + ], + [ + "0x239A", + "0x80E0" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_metro_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Metro ESP32-S2", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_metro_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4775", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32-s2.json b/boards/adafruit_qtpy_esp32-s2.json new file mode 100644 index 000000000..9ef92b3e2 --- /dev/null +++ b/boards/adafruit_qtpy_esp32-s2.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s2", + "variant": "adafruit_qtpy_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5325", + "vendor": "Adafruit" +} diff --git a/boards/atmegazero_esp32s2.json b/boards/atmegazero_esp32s2.json new file mode 100644 index 000000000..bfc40697f --- /dev/null +++ b/boards/atmegazero_esp32s2.json @@ -0,0 +1,53 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_atmegazero_esp32s2", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x800A" + ] + ], + "mcu": "esp32s2", + "variant": "atmegazero_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "EspinalLab ATMegaZero ESP32-S2", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/atmegazero_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://shop.atmegazero.com/", + "vendor": "EspinalLab" +} diff --git a/boards/az-delivery-devkit-v4.json b/boards/az-delivery-devkit-v4.json index 45fa0a20b..93237d723 100644 --- a/boards/az-delivery-devkit-v4.json +++ b/boards/az-delivery-devkit-v4.json @@ -28,7 +28,7 @@ "upload": { "flash_size": "4MB", "maximum_ram_size": 532480, - "maximum_size": 16777216, + "maximum_size": 4194304, "require_upload_port": true, "speed": 460800 }, diff --git a/boards/deneyapkart.json b/boards/deneyapkart.json new file mode 100644 index 000000000..3114c0399 --- /dev/null +++ b/boards/deneyapkart.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYDK", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "deneyapkart" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/magaza/urun-deneyap-kart.html", + "vendor": "Deneyap" +} diff --git a/boards/deneyapmini.json b/boards/deneyapmini.json new file mode 100644 index 000000000..02509684b --- /dev/null +++ b/boards/deneyapmini.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_DYM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x0002" + ] + ], + "mcu": "esp32s2", + "variant": "deneyapmini" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/magaza/urun-deneyap-kart-mini.html", + "vendor": "Deneyap" +} diff --git a/boards/denky32.json b/boards/denky32.json new file mode 100644 index 000000000..3b2c40762 --- /dev/null +++ b/boards/denky32.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DENKY_WROOM32", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ch_denky" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Denky32 (WROOM32)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Denky" +} diff --git a/boards/denky_d4.json b/boards/denky_d4.json new file mode 100644 index 000000000..e5d0b76bd --- /dev/null +++ b/boards/denky_d4.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DENKY_PICOV3", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ch_denky" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Denky D4 (PICO-V3-02)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Denky" +} diff --git a/boards/esp32-c3-devkitm-1.json b/boards/esp32-c3-devkitm-1.json index a17aed860..bc4ba058c 100644 --- a/boards/esp32-c3-devkitm-1.json +++ b/boards/esp32-c3-devkitm-1.json @@ -7,6 +7,7 @@ "f_cpu": "160000000L", "f_flash": "80000000L", "flash_mode": "qio", + "extra_flags": "-DARDUINO_ESP32C3_DEV", "mcu": "esp32c3", "variant": "esp32c3" }, diff --git a/boards/esp32-s2-franzininho.json b/boards/esp32-s2-franzininho.json index 15854fdf4..4fe0f5e7e 100644 --- a/boards/esp32-s2-franzininho.json +++ b/boards/esp32-s2-franzininho.json @@ -20,6 +20,7 @@ "openocd_target": "esp32s2.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Franzininho WiFi Board", diff --git a/boards/esp32-s2-kaluga-1.json b/boards/esp32-s2-kaluga-1.json index b0120ffb7..b48abac37 100644 --- a/boards/esp32-s2-kaluga-1.json +++ b/boards/esp32-s2-kaluga-1.json @@ -7,7 +7,7 @@ "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s2", "variant": "esp32s2" }, diff --git a/boards/esp32-s2-saola-1.json b/boards/esp32-s2-saola-1.json index a02952b11..58927bb91 100644 --- a/boards/esp32-s2-saola-1.json +++ b/boards/esp32-s2-saola-1.json @@ -7,7 +7,7 @@ "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s2", "variant": "esp32s2" }, diff --git a/boards/franzininho_wifi_esp32s2.json b/boards/franzininho_wifi_esp32s2.json new file mode 100644 index 000000000..df3a5651f --- /dev/null +++ b/boards/franzininho_wifi_esp32s2.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FRANZININHO_WIFI", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80A9" + ] + ], + "mcu": "esp32s2", + "variant": "franzininho_wifi_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Franzininho WiFi", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.franzininho.com.br/docs/franzininho-wifi/franzininho-wifi/", + "vendor": "Franzininho" +} diff --git a/boards/franzininho_wifi_msc_esp32s2.json b/boards/franzininho_wifi_msc_esp32s2.json new file mode 100644 index 000000000..163587b4f --- /dev/null +++ b/boards/franzininho_wifi_msc_esp32s2.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FRANZININHO_WIFI_MSC", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MSC_ON_BOOT=1", + "-DARDUINO_USB_DFU_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80A9" + ] + ], + "mcu": "esp32s2", + "variant": "franzininho_wifi_msc_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Franzininho WiFi MSC", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.franzininho.com.br/docs/franzininho-wifi/franzininho-wifi/", + "vendor": "Franzininho" +} diff --git a/boards/kb32-ft.json b/boards/kb32-ft.json new file mode 100644 index 000000000..586494f38 --- /dev/null +++ b/boards/kb32-ft.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_DEV", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MakerAsia KB32-FT", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://kb32ft.makerasia.com/", + "vendor": "MakerAsia" +} diff --git a/boards/m5stack-fire.json b/boards/m5stack-fire.json index 4f3ff39fd..1a500ab87 100644 --- a/boards/m5stack-fire.json +++ b/boards/m5stack-fire.json @@ -5,7 +5,12 @@ "partitions": "default_16MB.csv" }, "core": "esp32", - "extra_flags": "-DARDUINO_M5STACK_FIRE -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_M5STACK_FIRE", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", diff --git a/boards/m5stack-timer-cam.json b/boards/m5stack-timer-cam.json index 41ff2a809..5f76a861e 100644 --- a/boards/m5stack-timer-cam.json +++ b/boards/m5stack-timer-cam.json @@ -4,7 +4,12 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_M5Stack_Timer_CAM -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_M5Stack_Timer_CAM", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", diff --git a/boards/micros2.json b/boards/micros2.json new file mode 100644 index 000000000..93243bdba --- /dev/null +++ b/boards/micros2.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld", + "partitions": "ffat.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_MICROS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MSC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80C5" + ] + ], + "mcu": "esp32s2", + "variant": "micro_s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "microS2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/MicroDev1/microS2", + "vendor": "microS2" +} diff --git a/boards/sparkfun_esp32micromod.json b/boards/sparkfun_esp32micromod.json new file mode 100644 index 000000000..2d0f52e8a --- /dev/null +++ b/boards/sparkfun_esp32micromod.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_MICROMOD", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32micromod" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32 MicroMod", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/16781", + "vendor": "SparkFun" +} diff --git a/boards/sparkfun_esp32s2_thing_plus.json b/boards/sparkfun_esp32s2_thing_plus.json new file mode 100644 index 000000000..269d962fc --- /dev/null +++ b/boards/sparkfun_esp32s2_thing_plus.json @@ -0,0 +1,43 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32S2_THING_PLUS", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x1B4F", + "0x0027" + ] + ], + "mcu": "esp32s2", + "variant": "esp32s2thing_plus" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32-S2 Thing Plus", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "mode": "usb", + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/17743", + "vendor": "SparkFun" +} diff --git a/boards/tinypico.json b/boards/tinypico.json index 754a9870c..9f3deeabb 100644 --- a/boards/tinypico.json +++ b/boards/tinypico.json @@ -4,12 +4,17 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_TINYPICO -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_TINYPICO", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "qio", + "flash_mode": "dio", "mcu": "esp32", - "variant": "pico32" + "variant": "um_tinypico" }, "connectivity": [ "wifi", diff --git a/boards/trueverit-iot-driver-mk2.json b/boards/trueverit-iot-driver-mk2.json new file mode 100644 index 000000000..22e3eca79 --- /dev/null +++ b/boards/trueverit-iot-driver-mk2.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver_MK_II", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver-mkii" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver MK II", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} diff --git a/boards/trueverit-iot-driver.json b/boards/trueverit-iot-driver.json new file mode 100644 index 000000000..7f808ec32 --- /dev/null +++ b/boards/trueverit-iot-driver.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} diff --git a/boards/ttgo-t-watch.json b/boards/ttgo-t-watch.json index c58c273f3..354f54f14 100644 --- a/boards/ttgo-t-watch.json +++ b/boards/ttgo-t-watch.json @@ -5,7 +5,12 @@ "partitions": "default_16MB.csv" }, "core": "esp32", - "extra_flags": "-DARDUINO_TWATCH_BASE -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_TWATCH_BASE", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", diff --git a/boards/um_feathers2.json b/boards/um_feathers2.json new file mode 100644 index 000000000..7434f195e --- /dev/null +++ b/boards/um_feathers2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80AB" + ] + ], + "mcu": "esp32s2", + "variant": "um_feathers2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker FeatherS2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://feathers2.io", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_feathers2_neo.json b/boards/um_feathers2_neo.json new file mode 100644 index 000000000..7277d45ff --- /dev/null +++ b/boards/um_feathers2_neo.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS2NEO", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80B4" + ] + ], + "mcu": "esp32s2", + "variant": "um_feathers2neo" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker FeatherS2 Neo", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://unexpectedmaker.com/feathers2-neo", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_tinys2.json b/boards/um_tinys2.json new file mode 100644 index 000000000..8a57216ac --- /dev/null +++ b/boards/um_tinys2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TINYS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x8001" + ] + ], + "mcu": "esp32s2", + "variant": "um_tinys2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker TinyS2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://tinys2.io", + "vendor": "Unexpected Maker" +} diff --git a/boards/upesy_wroom.json b/boards/upesy_wroom.json new file mode 100644 index 000000000..999cef7c2 --- /dev/null +++ b/boards/upesy_wroom.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_uPesy_WROOM", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "uPesy_esp32_wroom_devkit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "uPesy ESP32 Wroom DevKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.upesy.fr/products/upesy-esp32-wroom-devkit-board", + "vendor": "uPesy" +} diff --git a/boards/upesy_wrover.json b/boards/upesy_wrover.json new file mode 100644 index 000000000..38b2eb3e7 --- /dev/null +++ b/boards/upesy_wrover.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_uPesy_WROVER", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "uPesy_esp32_wrover_devkit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "uPesy ESP32 Wrover DevKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.upesy.fr/products/upesy-esp32-wrover-devkit-board", + "vendor": "uPesy" +} diff --git a/examples/arduino-ble5-advertising/.gitignore b/examples/arduino-ble5-advertising/.gitignore new file mode 100644 index 000000000..03f4a3c19 --- /dev/null +++ b/examples/arduino-ble5-advertising/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/examples/arduino-ble5-advertising/README.md b/examples/arduino-ble5-advertising/README.md new file mode 100644 index 000000000..f34cc0db8 --- /dev/null +++ b/examples/arduino-ble5-advertising/README.md @@ -0,0 +1,27 @@ +How to build PlatformIO based project +===================================== + +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) +2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) +3. Extract ZIP archive +4. Run these commands: + +```shell +# Change directory to example +$ cd platform-espressif32/examples/arduino-ble5-advertising + +# Build project +$ pio run + +# Upload firmware +$ pio run --target upload + +# Build specific environment +$ pio run -e esp32-c3-devkitm-1 + +# Upload firmware for the specific environment +$ pio run -e esp32-c3-devkitm-1 --target upload + +# Clean build files +$ pio run --target clean +``` \ No newline at end of file diff --git a/examples/arduino-ble5-advertising/include/README b/examples/arduino-ble5-advertising/include/README new file mode 100644 index 000000000..194dcd432 --- /dev/null +++ b/examples/arduino-ble5-advertising/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/arduino-ble5-advertising/lib/README b/examples/arduino-ble5-advertising/lib/README new file mode 100644 index 000000000..6debab1e8 --- /dev/null +++ b/examples/arduino-ble5-advertising/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/arduino-ble5-advertising/platformio.ini b/examples/arduino-ble5-advertising/platformio.ini new file mode 100644 index 000000000..638c205b6 --- /dev/null +++ b/examples/arduino-ble5-advertising/platformio.ini @@ -0,0 +1,14 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32-c3-devkitm-1] +platform = espressif32 +board = esp32-c3-devkitm-1 +framework = arduino +monitor_speed = 115200 diff --git a/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino b/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino new file mode 100644 index 000000000..1b36bbb8b --- /dev/null +++ b/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino @@ -0,0 +1,72 @@ +/* + Simple BLE5 multi advertising example on esp32 C3/S3 + only ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED can be used for periodic advertising + + author: chegewara +*/ + +#include +#include + + +esp_ble_gap_ext_adv_params_t ext_adv_params_2M = { + .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED, + .interval_min = 0x40, + .interval_max = 0x40, + .channel_map = ADV_CHNL_ALL, + .own_addr_type = BLE_ADDR_TYPE_RANDOM, + .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + .primary_phy = ESP_BLE_GAP_PHY_1M, + .max_skip = 0, + .secondary_phy = ESP_BLE_GAP_PHY_2M, + .sid = 1, + .scan_req_notif = false, +}; + +static uint8_t raw_scan_rsp_data_2m[] = { + 0x02, 0x01, 0x06, + 0x02, 0x0a, 0xeb, + 0x12, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', + 'D', 'V', '_', '2', 'M', 0X0 +}; + +static esp_ble_gap_periodic_adv_params_t periodic_adv_params = { + .interval_min = 0x320, // 1000 ms interval + .interval_max = 0x640, + .properties = 0, // Do not include TX power +}; + +static uint8_t periodic_adv_raw_data[] = { + 0x02, 0x01, 0x06, + 0x02, 0x0a, 0xeb, + 0x03, 0x03, 0xab, 0xcd, + 0x11, 0x09, 'E', 'S', 'P', '_', 'P', 'E', 'R', 'I', 'O', 'D', 'I', + 'C', '_', 'A', 'D', 'V' +}; + + +uint8_t addr_2m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x02}; + +BLEMultiAdvertising advert(1); // max number of advertisement data + +void setup() { + Serial.begin(115200); + Serial.println("Multi-Advertising..."); + + BLEDevice::init(""); + + advert.setAdvertisingParams(0, &ext_adv_params_2M); + advert.setAdvertisingData(0, sizeof(raw_scan_rsp_data_2m), &raw_scan_rsp_data_2m[0]); + advert.setInstanceAddress(0, addr_2m); + advert.setDuration(0, 0, 0); + + delay(100); + advert.start(); + advert.setPeriodicAdvertisingParams(0, &periodic_adv_params); + advert.setPeriodicAdvertisingData(0, sizeof(periodic_adv_raw_data), &periodic_adv_raw_data[0]); + advert.startPeriodicAdvertising(0); +} + +void loop() { + delay(2000); +} diff --git a/examples/arduino-ble5-advertising/test/README b/examples/arduino-ble5-advertising/test/README new file mode 100644 index 000000000..df5066e64 --- /dev/null +++ b/examples/arduino-ble5-advertising/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/examples/arduino-usb-keyboard/.gitignore b/examples/arduino-usb-keyboard/.gitignore new file mode 100644 index 000000000..03f4a3c19 --- /dev/null +++ b/examples/arduino-usb-keyboard/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/examples/arduino-usb-keyboard/README.md b/examples/arduino-usb-keyboard/README.md new file mode 100644 index 000000000..e9bd6a20e --- /dev/null +++ b/examples/arduino-usb-keyboard/README.md @@ -0,0 +1,27 @@ +How to build PlatformIO based project +===================================== + +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) +2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) +3. Extract ZIP archive +4. Run these commands: + +```shell +# Change directory to example +$ cd platform-espressif32/examples/arduino-usb-keyboard + +# Build project +$ pio run + +# Upload firmware +$ pio run --target upload + +# Build specific environment +$ pio run -e esp32-s2-saola-1 + +# Upload firmware for the specific environment +$ pio run -e esp32-s2-saola-1 --target upload + +# Clean build files +$ pio run --target clean +``` \ No newline at end of file diff --git a/examples/arduino-usb-keyboard/include/README b/examples/arduino-usb-keyboard/include/README new file mode 100644 index 000000000..194dcd432 --- /dev/null +++ b/examples/arduino-usb-keyboard/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/arduino-usb-keyboard/lib/README b/examples/arduino-usb-keyboard/lib/README new file mode 100644 index 000000000..6debab1e8 --- /dev/null +++ b/examples/arduino-usb-keyboard/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/arduino-usb-keyboard/platformio.ini b/examples/arduino-usb-keyboard/platformio.ini new file mode 100644 index 000000000..3f51b8378 --- /dev/null +++ b/examples/arduino-usb-keyboard/platformio.ini @@ -0,0 +1,19 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env] +platform = espressif32 +framework = arduino +monitor_speed = 115200 + +[env:esp32-s2-saola-1] +board = esp32-s2-saola-1 + +[env:esp32-s2-kaluga-1] +board = esp32-s2-kaluga-1 \ No newline at end of file diff --git a/examples/arduino-usb-keyboard/src/KeyboardSerial.ino b/examples/arduino-usb-keyboard/src/KeyboardSerial.ino new file mode 100644 index 000000000..e3bb87697 --- /dev/null +++ b/examples/arduino-usb-keyboard/src/KeyboardSerial.ino @@ -0,0 +1,40 @@ +/* + Keyboard test + + Reads a byte from the serial port, sends a keystroke back. + The sent keystroke is one higher than what's received, e.g. if you send a, + you get b, send A you get B, and so forth. + + The circuit: + - none + + created 21 Oct 2011 + modified 27 Mar 2012 + by Tom Igoe + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/KeyboardSerial +*/ + +#include "USB.h" +#include "USBHIDKeyboard.h" +USBHIDKeyboard Keyboard; + +void setup() { + // open the serial port: + Serial.begin(115200); + // initialize control over the keyboard: + Keyboard.begin(); + USB.begin(); +} + +void loop() { + // check for incoming serial data: + if (Serial.available() > 0) { + // read incoming serial data: + char inChar = Serial.read(); + // Type the next ASCII value from what you received: + Keyboard.write(inChar + 1); + } +} diff --git a/examples/arduino-usb-keyboard/test/README b/examples/arduino-usb-keyboard/test/README new file mode 100644 index 000000000..df5066e64 --- /dev/null +++ b/examples/arduino-usb-keyboard/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html From d89f55d7f5e5c68593faf0ea4a9bbc28d8495154 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 18 Apr 2022 16:11:23 +0200 Subject: [PATCH 015/666] Update platform.json --- platform.json | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/platform.json b/platform.json index c06bf0ee4..0117a19e6 100644 --- a/platform.json +++ b/platform.json @@ -30,20 +30,6 @@ "description": "ESP-IDF is the official development framework for the ESP32 and ESP32-S Series SoCs.", "homepage": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32/", "title": "Espressif IoT Development Framework" - }, - "simba": { - "package": "framework-simba", - "script": "builder/frameworks/simba.py", - "description": "Simba is an RTOS and build framework with aims to make embedded programming easy and portable", - "homepage": "http://simba-os.readthedocs.org", - "title": "Simba" - }, - "pumbaa": { - "package": "framework-pumbaa", - "script": "builder/frameworks/pumbaa.py", - "description": "Pumbaa is Python on top of Simba. The implementation is a port of MicroPython, designed for embedded devices with limited amount of RAM and code memory", - "homepage": "http://pumbaa.readthedocs.org/", - "title": "Pumbaa" } }, "packages": { @@ -112,18 +98,6 @@ "owner": "platformio", "version": "https://github.com/tasmota/esp-idf/releases/download/v.4.4.0/esp-idf-v4.4.zip" }, - "framework-simba": { - "type": "framework", - "optional": true, - "owner": "platformio", - "version": ">=12.2.0" - }, - "framework-pumbaa": { - "type": "framework", - "optional": true, - "owner": "platformio", - "version": ">=2.3.0" - }, "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", From 8692362d592bda74e479b3e29052a15612a64a9b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 18 Apr 2022 16:12:14 +0200 Subject: [PATCH 016/666] Update platform.py --- platform.py | 1 - 1 file changed, 1 deletion(-) diff --git a/platform.py b/platform.py index 26d58d456..afb9cb2e6 100644 --- a/platform.py +++ b/platform.py @@ -107,7 +107,6 @@ def configure_default_packages(self, variables, targets): is_legacy_project = ( build_core == "mbcwb" - or set(("simba", "pumbaa")) & set(frameworks) ) if is_legacy_project: From 1555a021f1d9deefcdf860d942e0ac78a40945ca Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 18 Apr 2022 16:12:53 +0200 Subject: [PATCH 017/666] Integrate upstream 2 --- .github/workflows/examples.yml | 2 - boards/nano32.json | 4 +- builder/frameworks/pumbaa.py | 70 ---------------------------- builder/frameworks/simba.py | 68 --------------------------- examples/pumbaa-blink/.gitignore | 1 - examples/pumbaa-blink/.skiptest | 1 - examples/pumbaa-blink/.travis.yml | 67 -------------------------- examples/pumbaa-blink/README.md | 18 ------- examples/pumbaa-blink/include/README | 39 ---------------- examples/pumbaa-blink/lib/README | 46 ------------------ examples/pumbaa-blink/platformio.ini | 13 ------ examples/pumbaa-blink/src/main.c | 22 --------- examples/pumbaa-blink/src/main.py | 40 ---------------- examples/pumbaa-blink/test/README | 11 ----- examples/simba-blink/.gitignore | 1 - examples/simba-blink/.travis.yml | 67 -------------------------- examples/simba-blink/README.md | 18 ------- examples/simba-blink/include/README | 39 ---------------- examples/simba-blink/lib/README | 46 ------------------ examples/simba-blink/platformio.ini | 13 ------ examples/simba-blink/src/main.c | 43 ----------------- examples/simba-blink/test/README | 11 ----- 22 files changed, 1 insertion(+), 639 deletions(-) delete mode 100644 builder/frameworks/pumbaa.py delete mode 100644 builder/frameworks/simba.py delete mode 100755 examples/pumbaa-blink/.gitignore delete mode 100644 examples/pumbaa-blink/.skiptest delete mode 100755 examples/pumbaa-blink/.travis.yml delete mode 100755 examples/pumbaa-blink/README.md delete mode 100644 examples/pumbaa-blink/include/README delete mode 100644 examples/pumbaa-blink/lib/README delete mode 100755 examples/pumbaa-blink/platformio.ini delete mode 100755 examples/pumbaa-blink/src/main.c delete mode 100755 examples/pumbaa-blink/src/main.py delete mode 100644 examples/pumbaa-blink/test/README delete mode 100755 examples/simba-blink/.gitignore delete mode 100755 examples/simba-blink/.travis.yml delete mode 100755 examples/simba-blink/README.md delete mode 100644 examples/simba-blink/include/README delete mode 100644 examples/simba-blink/lib/README delete mode 100755 examples/simba-blink/platformio.ini delete mode 100755 examples/simba-blink/src/main.c delete mode 100644 examples/simba-blink/test/README diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 5f3048252..ced6a39b3 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -31,8 +31,6 @@ jobs: - "examples/espidf-storage-spiffs" - "examples/espidf-ulp-adc" - "examples/espidf-ulp-pulse" - - "examples/pumbaa-blink" - - "examples/simba-blink" runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 diff --git a/boards/nano32.json b/boards/nano32.json index eeb8a20bf..2e1f5568c 100644 --- a/boards/nano32.json +++ b/boards/nano32.json @@ -19,9 +19,7 @@ ], "frameworks": [ "arduino", - "espidf", - "simba", - "pumbaa" + "espidf" ], "name": "MakerAsia Nano32", "upload": { diff --git a/builder/frameworks/pumbaa.py b/builder/frameworks/pumbaa.py deleted file mode 100644 index c9b77c0df..000000000 --- a/builder/frameworks/pumbaa.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2014-present PlatformIO -# -# 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. - -"""Pumbaa - -Pumbaa is Python on top of Simba. - -The implementation is a port of MicroPython, designed for embedded -devices with limited amount of RAM and code memory. - -http://pumbaa.readthedocs.org - -""" - -from os.path import join, sep - -from SCons.Script import DefaultEnvironment, SConscript - -from platformio.builder.tools import platformio as platformio_tool - -# -# Backward compatibility with PlatformIO 2.0 -# -platformio_tool.SRC_DEFAULT_FILTER = " ".join([ - "+<*>", "-<.git%s>" % sep, "-" % sep, - "-" % sep, "-" % sep, - "-" % sep, "-" % sep -]) - - -def LookupSources(env, variant_dir, src_dir, duplicate=True, src_filter=None): - return env.CollectBuildFiles(variant_dir, src_dir, src_filter, duplicate) - - -def VariantDirWrap(env, variant_dir, src_dir, duplicate=False): - env.VariantDir(variant_dir, src_dir, duplicate) - - -env = DefaultEnvironment() - -env.AddMethod(LookupSources) -env.AddMethod(VariantDirWrap) - -env.Replace( - PLATFORMFW_DIR=env.PioPlatform().get_package_dir("framework-pumbaa"), - UPLOADERFLAGS=[] # Backward compatibility for obsolete build script -) - -SConscript( - [env.subst(join("$PLATFORMFW_DIR", "make", "platformio.sconscript"))]) - -env.Replace( - FLASH_EXTRA_IMAGES=[ - ("0x1000", join("$PLATFORMFW_DIR", "simba", "3pp", "esp32", - "bin", "bootloader.bin")), - ("0x8000", join("$PLATFORMFW_DIR", "simba", "3pp", "esp32", - "bin", "partitions_singleapp.bin")) - ] -) diff --git a/builder/frameworks/simba.py b/builder/frameworks/simba.py deleted file mode 100644 index 0def12da6..000000000 --- a/builder/frameworks/simba.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2014-present PlatformIO -# -# 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. - -"""Simba - -Simba is an RTOS and build framework. It aims to make embedded -programming easy and portable. - -http://simba-os.readthedocs.org - -""" - -from os.path import join, sep - -from SCons.Script import DefaultEnvironment, SConscript - -from platformio.builder.tools import platformio as platformio_tool - -# -# Backward compatibility with PlatformIO 2.0 -# -platformio_tool.SRC_DEFAULT_FILTER = " ".join([ - "+<*>", "-<.git%s>" % sep, "-" % sep, - "-" % sep, "-" % sep, - "-" % sep, "-" % sep -]) - - -def LookupSources(env, variant_dir, src_dir, duplicate=True, src_filter=None): - return env.CollectBuildFiles(variant_dir, src_dir, src_filter, duplicate) - - -def VariantDirWrap(env, variant_dir, src_dir, duplicate=False): - env.VariantDir(variant_dir, src_dir, duplicate) - - -env = DefaultEnvironment() - -env.AddMethod(LookupSources) -env.AddMethod(VariantDirWrap) - -env.Replace( - PLATFORMFW_DIR=env.PioPlatform().get_package_dir("framework-simba"), - UPLOADERFLAGS=[] # Backward compatibility for obsolete build script -) - -SConscript( - [env.subst(join("$PLATFORMFW_DIR", "make", "platformio.sconscript"))]) - -env.Replace( - FLASH_EXTRA_IMAGES=[ - ("0x1000", join("$PLATFORMFW_DIR", "3pp", "esp32", - "bin", "bootloader.bin")), - ("0x8000", join("$PLATFORMFW_DIR", "3pp", "esp32", - "bin", "partitions_singleapp.bin")) - ] -) diff --git a/examples/pumbaa-blink/.gitignore b/examples/pumbaa-blink/.gitignore deleted file mode 100755 index 03f4a3c19..000000000 --- a/examples/pumbaa-blink/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/pumbaa-blink/.skiptest b/examples/pumbaa-blink/.skiptest deleted file mode 100644 index 05e3ca046..000000000 --- a/examples/pumbaa-blink/.skiptest +++ /dev/null @@ -1 +0,0 @@ -.skiptest diff --git a/examples/pumbaa-blink/.travis.yml b/examples/pumbaa-blink/.travis.yml deleted file mode 100755 index 7c486f183..000000000 --- a/examples/pumbaa-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/pumbaa-blink/README.md b/examples/pumbaa-blink/README.md deleted file mode 100755 index 1de389c37..000000000 --- a/examples/pumbaa-blink/README.md +++ /dev/null @@ -1,18 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/pumbaa-blink - -# Process example project -$ pio run - -# Upload firmware -$ pio run --target upload -``` diff --git a/examples/pumbaa-blink/include/README b/examples/pumbaa-blink/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/pumbaa-blink/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/pumbaa-blink/lib/README b/examples/pumbaa-blink/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/pumbaa-blink/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/pumbaa-blink/platformio.ini b/examples/pumbaa-blink/platformio.ini deleted file mode 100755 index da2c58b75..000000000 --- a/examples/pumbaa-blink/platformio.ini +++ /dev/null @@ -1,13 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html - -[env:nano32] -platform = espressif32 -framework = pumbaa -board = nano32 diff --git a/examples/pumbaa-blink/src/main.c b/examples/pumbaa-blink/src/main.c deleted file mode 100755 index c43d5310e..000000000 --- a/examples/pumbaa-blink/src/main.c +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @file main.c - * - * @section License - * Copyright (C) 2015-2016, Erik Moqvist - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * This file is part of the Pumbaa project. - */ - -/* - * This file is required by PlatformIO, but is unused in Pumbaa. - */ diff --git a/examples/pumbaa-blink/src/main.py b/examples/pumbaa-blink/src/main.py deleted file mode 100755 index fde1e231c..000000000 --- a/examples/pumbaa-blink/src/main.py +++ /dev/null @@ -1,40 +0,0 @@ -# -# @section License -# -# The MIT License (MIT) -# -# Copyright (c) 2016, Erik Moqvist -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, copy, -# modify, merge, publish, distribute, sublicense, and/or sell copies -# of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# This file is part of the Pumbaa project. -# - - -import time -import board -from drivers import Pin - -LED = Pin(board.PIN_LED, Pin.OUTPUT) - -while True: - LED.toggle() - time.sleep(0.5) diff --git a/examples/pumbaa-blink/test/README b/examples/pumbaa-blink/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/pumbaa-blink/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/examples/simba-blink/.gitignore b/examples/simba-blink/.gitignore deleted file mode 100755 index 03f4a3c19..000000000 --- a/examples/simba-blink/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/simba-blink/.travis.yml b/examples/simba-blink/.travis.yml deleted file mode 100755 index 7c486f183..000000000 --- a/examples/simba-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/simba-blink/README.md b/examples/simba-blink/README.md deleted file mode 100755 index 15437339b..000000000 --- a/examples/simba-blink/README.md +++ /dev/null @@ -1,18 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/simba-blink - -# Process example project -$ pio run - -# Upload firmware -$ pio run --target upload -``` \ No newline at end of file diff --git a/examples/simba-blink/include/README b/examples/simba-blink/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/simba-blink/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/simba-blink/lib/README b/examples/simba-blink/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/simba-blink/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/simba-blink/platformio.ini b/examples/simba-blink/platformio.ini deleted file mode 100755 index 802ec5147..000000000 --- a/examples/simba-blink/platformio.ini +++ /dev/null @@ -1,13 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html - -[env:nano32] -platform = espressif32 -framework = simba -board = nano32 diff --git a/examples/simba-blink/src/main.c b/examples/simba-blink/src/main.c deleted file mode 100755 index 404ec637b..000000000 --- a/examples/simba-blink/src/main.c +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file main.c - * @version 4.1.0 - * - * @section License - * Copyright (C) 2015-2016, Erik Moqvist - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * This file is part of the Simba project. - */ - -#include "simba.h" - -int main() -{ - struct pin_driver_t led; - - /* Start the system. */ - sys_start(); - - /* Initialize the LED pin as output and set its value to 1. */ - pin_init(&led, &pin_led_dev, PIN_OUTPUT); - pin_write(&led, 1); - - while (1) { - /* Wait half a second. */ - thrd_sleep_us(500000); - - /* Toggle the LED on/off. */ - pin_toggle(&led); - } - - return (0); -} diff --git a/examples/simba-blink/test/README b/examples/simba-blink/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/simba-blink/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html From 970a4f2accdfa0f9526146894553bebb7c0d0daf Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:31:55 +0200 Subject: [PATCH 018/666] Update esp32-s2-franzininho.json --- boards/esp32-s2-franzininho.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/boards/esp32-s2-franzininho.json b/boards/esp32-s2-franzininho.json index 4fe0f5e7e..d20d12a45 100644 --- a/boards/esp32-s2-franzininho.json +++ b/boards/esp32-s2-franzininho.json @@ -12,8 +12,6 @@ "variant": "esp32s2" }, "connectivity": [ - "arduino", - "espidf", "wifi" ], "debug": { From caa76b2b7aa2936a822dcab23d47de3da8cc9439 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:32:38 +0200 Subject: [PATCH 019/666] Update _embed_files.py --- builder/frameworks/_embed_files.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index 63add2202..5469e3bce 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -102,19 +102,22 @@ def transform_to_asm(target, source, env): return files, source +mcu = board.get("build.mcu", "esp32") env.Append( BUILDERS=dict( TxtToBin=Builder( action=env.VerboseAction( " ".join( [ - "xtensa-%s-elf-objcopy" % board.get("build.mcu", "esp32"), + "riscv32-esp-elf-objcopy" + if mcu == "esp32c3" + else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", - "elf32-xtensa-le", + "elf32-littleriscv" if mcu == "esp32c3" else "elf32-xtensa-le", "--binary-architecture", - "xtensa", + "riscv" if mcu == "esp32c3" else "xtensa", "--rename-section", ".data=.rodata.embedded", "$SOURCE", From d60119e322afba8e20211b31aa83f5bfde27c176 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:33:04 +0200 Subject: [PATCH 020/666] Update main.py --- builder/main.py | 50 ++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/builder/main.py b/builder/main.py index 52cd1370c..cbfa1c7ec 100644 --- a/builder/main.py +++ b/builder/main.py @@ -212,7 +212,8 @@ def __fetch_fs_size(target, source, env): ESP32_FS_IMAGE_NAME=env.get( "ESP32_FS_IMAGE_NAME", env.get("ESP32_SPIFFS_IMAGE_NAME", filesystem) ), - ESP32_APP_OFFSET="0x10000", + + ESP32_APP_OFFSET=board.get("upload.offset_address", "0x10000"), PROGSUFFIX=".elf" ) @@ -228,9 +229,8 @@ def __fetch_fs_size(target, source, env): BUILDERS=dict( ElfToBin=Builder( action=env.VerboseAction(" ".join([ - '"$PYTHONEXE" "$OBJCOPY"', - "--chip", mcu, - "elf2image", + '"$PYTHONEXE" "$OBJCOPY"', + "--chip", mcu, "elf2image", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "detect"), @@ -369,7 +369,7 @@ def __fetch_fs_size(target, source, env): "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", "detect" + "--flash_size", board.get("upload.flash_size", "detect") ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE' ) @@ -387,7 +387,7 @@ def __fetch_fs_size(target, source, env): "write_flash", "-z", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_size", "detect", - "$SPIFFS_START" + "$FS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', ) @@ -429,18 +429,28 @@ def __fetch_fs_size(target, source, env): openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)] openocd_args.extend( debug_tools.get(upload_protocol).get("server").get("arguments", [])) - openocd_args.extend([ - "-c", "adapter_khz %s" % env.GetProjectOption("debug_speed", "5000"), + openocd_args.extend( + [ "-c", - "program_esp {{$SOURCE}} %s verify" % - board.get("upload.offset_address", "$ESP32_APP_OFFSET"), - ]) - for image in env.get("FLASH_EXTRA_IMAGES", []): - openocd_args.extend([ - "-c", - 'program_esp {{%s}} %s verify' % - (_to_unix_slashes(image[1]), image[0]) - ]) + "adapter_khz %s" % env.GetProjectOption("debug_speed", "5000"), + "-c", + "program_esp {{$SOURCE}} %s verify" + % ( + "$FS_START" + if "uploadfs" in COMMAND_LINE_TARGETS + else "$ESP32_APP_OFFSET" + ), + ] + ) + if "uploadfs" not in COMMAND_LINE_TARGETS: + for image in env.get("FLASH_EXTRA_IMAGES", []): + openocd_args.extend( + [ + "-c", + "program_esp {{%s}} %s verify" + % (_to_unix_slashes(image[1]), image[0]), + ] + ) openocd_args.extend(["-c", "reset run; shutdown"]) openocd_args = [ f.replace( @@ -449,9 +459,11 @@ def __fetch_fs_size(target, source, env): platform.get_package_dir("tool-openocd-esp32") or "")) for f in openocd_args ] - env.Replace(UPLOADER="openocd", + env.Replace( + UPLOADER="openocd", UPLOADERFLAGS=openocd_args, - UPLOADCMD="$UPLOADER $UPLOADERFLAGS") + UPLOADCMD="$UPLOADER $UPLOADERFLAGS", + ) upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")] # custom upload tool From 83db9185323a91979e33ba6e21e7cce80560493d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:33:37 +0200 Subject: [PATCH 021/666] Update platform.json --- platform.json | 46 ++++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/platform.json b/platform.json index 0117a19e6..4a187d918 100644 --- a/platform.json +++ b/platform.json @@ -33,40 +33,40 @@ } }, "packages": { + "framework-arduinoespressif32": { + "type": "framework", + "optional": true, + "owner": "tasmota", + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/803/framework-arduinoespressif32-v4.4_dev-40d126bfd1.tar.gz" + }, + "framework-espidf": { + "type": "framework", + "optional": true, + "owner": "platformio", + "version": "https://github.com/tasmota/esp-idf/releases/download/v.4.4.0/esp-idf-v4.4.zip" + }, "toolchain-xtensa-esp32": { "type": "toolchain", "owner": "espressif", - "version": "8.4.0+2021r2-patch3", - "optionalVersions": [ - "8.4.0+2021r2-patch2" - ] + "version": "8.4.0+2021r2-patch3" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3", - "optionalVersions": [ - "8.4.0+2021r2-patch2" - ] + "version": "8.4.0+2021r2-patch3" }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3", - "optionalVersions": [ - "8.4.0+2021r2-patch2" - ] + "version": "8.4.0+2021r2-patch3" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3", - "optionalVersions": [ - "8.4.0+2021r2-patch2" - ] + "version": "8.4.0+2021r2-patch3" }, "toolchain-esp32ulp": { "type": "toolchain", @@ -80,24 +80,12 @@ "owner": "platformio", "version": "~1.22851.0" }, - "framework-arduinoespressif32": { - "type": "framework", - "optional": true, - "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/803/framework-arduinoespressif32-v4.4_dev-40d126bfd1.tar.gz" - }, "framework-arduino-mbcwb": { "type": "framework", "optional": true, "owner": "meteca", "version": ">=2.1.1" }, - "framework-espidf": { - "type": "framework", - "optional": true, - "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v.4.4.0/esp-idf-v4.4.zip" - }, "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", @@ -116,13 +104,11 @@ }, "tool-mkspiffs": { "type": "uploader", - "optional": true, "owner": "platformio", "version": "~2.230.0" }, "tool-mklittlefs": { "type": "uploader", - "optional": true, "owner": "platformio", "version": "~1.203.0" }, From 71378c823440773e1b42690d1fd6cac0ffcf241d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:34:00 +0200 Subject: [PATCH 022/666] Update platform.py --- platform.py | 1 + 1 file changed, 1 insertion(+) diff --git a/platform.py b/platform.py index afb9cb2e6..895a9c78a 100644 --- a/platform.py +++ b/platform.py @@ -385,6 +385,7 @@ def configure_arduino_toolchains(self, package_index): self.packages[toolchain_package] = dict() self.packages[toolchain_package]["version"] = version self.packages[toolchain_package]["owner"] = "espressif" + self.packages[toolchain_package]["type"] = "toolchain" def configure_upstream_arduino_packages(self, url_items): framework_index_file = os.path.join( From 81dc9d6761f0d98baeda5d1225c72c2835a495eb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:34:12 +0200 Subject: [PATCH 023/666] updates 21.04.2022 (#15) --- builder/frameworks/arduino.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 161ad70ee..c6fc754a6 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -41,3 +41,4 @@ SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) + env["IDE_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) From 29ee84a5d1a7f003a6ad959201b5bd87bfc0e669 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 22 Apr 2022 13:12:15 +0200 Subject: [PATCH 024/666] Tasmota/dev apple --- .github/workflows/examples.yml | 12 +- README.md | 18 +- boards/adafruit_feather_esp32_v2.json | 37 +++ boards/adafruit_funhouse_esp32s2.json | 62 +++++ boards/adafruit_magtag29_esp32s2.json | 62 +++++ boards/adafruit_metro_esp32s2.json | 62 +++++ boards/adafruit_qt_py_esp32-c3.json | 34 +++ boards/adafruit_qtpy_esp32-s2.json | 34 +++ boards/atmegazero_esp32s2.json | 53 ++++ boards/az-delivery-devkit-v4.json | 2 +- boards/deneyapkart.json | 41 +++ boards/deneyapmini.json | 44 ++++ boards/denky32.json | 39 +++ boards/denky_d4.json | 37 +++ boards/esp32-c3-devkitm-1.json | 2 + boards/esp32-c3-mini.json | 34 +++ boards/esp32-s2-franzininho.json | 34 +++ boards/esp32-s2-kaluga-1.json | 4 +- boards/esp32-s2-saola-1.json | 4 +- boards/esp32-s2-usb.json | 34 +++ boards/esp32-s3-devkitc-1.json | 35 +++ boards/esp32-s3-usb.json | 35 +++ boards/featheresp32-s2.json | 31 ++- boards/franzininho_wifi_esp32s2.json | 45 ++++ boards/franzininho_wifi_msc_esp32s2.json | 47 ++++ boards/kb32-ft.json | 42 +++ boards/lionbit.json | 41 +++ boards/m5stack-core2.json | 2 +- boards/m5stack-fire.json | 7 +- boards/m5stack-timer-cam.json | 7 +- boards/micros2.json | 48 ++++ boards/nano32.json | 4 +- boards/qtpy-esp32-s2.json | 34 +++ boards/sparkfun_esp32micromod.json | 34 +++ boards/sparkfun_esp32s2_thing_plus.json | 43 +++ boards/tinypico.json | 11 +- boards/trueverit-iot-driver-mk2.json | 37 +++ boards/trueverit-iot-driver.json | 37 +++ boards/ttgo-t-watch.json | 7 +- boards/um_feathers2.json | 46 ++++ boards/um_feathers2_neo.json | 46 ++++ boards/um_tinys2.json | 46 ++++ boards/upesy_wroom.json | 37 +++ boards/upesy_wrover.json | 42 +++ builder/frameworks/_embed_files.py | 9 +- builder/frameworks/arduino.py | 1 + builder/frameworks/espidf.py | 114 +++++--- builder/frameworks/pumbaa.py | 70 ----- builder/frameworks/simba.py | 68 ----- builder/main.py | 173 ++++++++---- .../.gitignore | 0 examples/arduino-ble5-advertising/README.md | 27 ++ .../include/README | 0 .../lib/README | 0 .../platformio.ini | 9 +- .../src/BLE5_periodic_advertising.ino | 72 +++++ .../test/README | 0 examples/arduino-rmt-blink/platformio.ini | 17 ++ .../src/RMTWriteNeoPixel.ino | 100 +++++++ .../.gitignore | 0 examples/arduino-usb-keyboard/README.md | 27 ++ .../include/README | 0 .../lib/README | 0 .../platformio.ini | 14 +- .../src/KeyboardSerial.ino | 40 +++ .../test/README | 0 examples/espidf-arduino-blink/platformio.ini | 3 - .../espidf-arduino-blink/sdkconfig.defaults | 3 +- .../espidf-arduino-wifiscan/platformio.ini | 3 - .../sdkconfig.defaults | 1 - examples/espidf-blink/platformio.ini | 17 ++ .../espidf-coap-server/src/certs/coap_ca.pem | 46 ++-- .../src/certs/coap_server.crt | 79 +----- .../src/certs/coap_server.key | 31 +-- .../src/coap_server_example_main.c | 109 +++++--- .../src/tusb_sample_descriptor.c | 2 +- examples/pumbaa-blink/.skiptest | 1 - examples/pumbaa-blink/.travis.yml | 67 ----- examples/pumbaa-blink/README.md | 18 -- examples/pumbaa-blink/src/main.c | 22 -- examples/pumbaa-blink/src/main.py | 40 --- examples/simba-blink/.travis.yml | 67 ----- examples/simba-blink/README.md | 18 -- examples/simba-blink/src/main.c | 43 --- monitor/filter_exception_decoder.py | 2 +- platform.json | 129 ++++----- platform.py | 248 ++++++++++++++---- 87 files changed, 2281 insertions(+), 822 deletions(-) create mode 100644 boards/adafruit_feather_esp32_v2.json create mode 100644 boards/adafruit_funhouse_esp32s2.json create mode 100644 boards/adafruit_magtag29_esp32s2.json create mode 100644 boards/adafruit_metro_esp32s2.json create mode 100644 boards/adafruit_qt_py_esp32-c3.json create mode 100644 boards/adafruit_qtpy_esp32-s2.json create mode 100644 boards/atmegazero_esp32s2.json create mode 100644 boards/deneyapkart.json create mode 100644 boards/deneyapmini.json create mode 100644 boards/denky32.json create mode 100644 boards/denky_d4.json create mode 100644 boards/esp32-c3-mini.json create mode 100644 boards/esp32-s2-franzininho.json create mode 100644 boards/esp32-s2-usb.json create mode 100644 boards/esp32-s3-devkitc-1.json create mode 100644 boards/esp32-s3-usb.json create mode 100644 boards/franzininho_wifi_esp32s2.json create mode 100644 boards/franzininho_wifi_msc_esp32s2.json create mode 100644 boards/kb32-ft.json create mode 100644 boards/lionbit.json create mode 100644 boards/micros2.json create mode 100644 boards/qtpy-esp32-s2.json create mode 100644 boards/sparkfun_esp32micromod.json create mode 100644 boards/sparkfun_esp32s2_thing_plus.json create mode 100644 boards/trueverit-iot-driver-mk2.json create mode 100644 boards/trueverit-iot-driver.json create mode 100644 boards/um_feathers2.json create mode 100644 boards/um_feathers2_neo.json create mode 100644 boards/um_tinys2.json create mode 100644 boards/upesy_wroom.json create mode 100644 boards/upesy_wrover.json delete mode 100644 builder/frameworks/pumbaa.py delete mode 100644 builder/frameworks/simba.py rename examples/{pumbaa-blink => arduino-ble5-advertising}/.gitignore (100%) mode change 100755 => 100644 create mode 100644 examples/arduino-ble5-advertising/README.md rename examples/{pumbaa-blink => arduino-ble5-advertising}/include/README (100%) rename examples/{pumbaa-blink => arduino-ble5-advertising}/lib/README (100%) rename examples/{pumbaa-blink => arduino-ble5-advertising}/platformio.ini (67%) mode change 100755 => 100644 create mode 100644 examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino rename examples/{pumbaa-blink => arduino-ble5-advertising}/test/README (100%) create mode 100644 examples/arduino-rmt-blink/platformio.ini create mode 100644 examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino rename examples/{simba-blink => arduino-usb-keyboard}/.gitignore (100%) mode change 100755 => 100644 create mode 100644 examples/arduino-usb-keyboard/README.md rename examples/{simba-blink => arduino-usb-keyboard}/include/README (100%) rename examples/{simba-blink => arduino-usb-keyboard}/lib/README (100%) rename examples/{simba-blink => arduino-usb-keyboard}/platformio.ini (60%) mode change 100755 => 100644 create mode 100644 examples/arduino-usb-keyboard/src/KeyboardSerial.ino rename examples/{simba-blink => arduino-usb-keyboard}/test/README (100%) delete mode 100644 examples/pumbaa-blink/.skiptest delete mode 100755 examples/pumbaa-blink/.travis.yml delete mode 100755 examples/pumbaa-blink/README.md delete mode 100755 examples/pumbaa-blink/src/main.c delete mode 100755 examples/pumbaa-blink/src/main.py delete mode 100755 examples/simba-blink/.travis.yml delete mode 100755 examples/simba-blink/README.md delete mode 100755 examples/simba-blink/src/main.c diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 2f42e32de..ced6a39b3 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -7,14 +7,18 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-18.04, windows-latest, macos-latest] - python-version: [3.7] + os: [ubuntu-latest, windows-latest, macos-latest] + python-version: [3.8] example: + - "examples/arduino-ble5-advertising" - "examples/arduino-blink" + - "examples/arduino-rmt-blink" - "examples/arduino-briki-internal-libs" + - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/espidf-arduino-blink" - "examples/espidf-arduino-wifiscan" + - "examples/espidf-blink" - "examples/espidf-aws-iot" - "examples/espidf-ble-eddystone" - "examples/espidf-coap-server" @@ -27,8 +31,6 @@ jobs: - "examples/espidf-storage-spiffs" - "examples/espidf-ulp-adc" - "examples/espidf-ulp-pulse" - - "examples/pumbaa-blink" - - "examples/simba-blink" runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 @@ -41,7 +43,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -U https://github.com/platformio/platformio/archive/develop.zip + pip install -U platformio platformio platform install file://. - name: Build examples run: | diff --git a/README.md b/README.md index cd538167b..a0268dc64 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ -# Espressif 32: development platform for [PlatformIO](http://platformio.org) +[![Build_special_firmware](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md) -[![Build Status](https://github.com/platformio/platform-espressif32/workflows/Examples/badge.svg)](https://github.com/platformio/platform-espressif32/actions) + +# Tasmota Espressif 32: development platform for [PlatformIO](http://platformio.org) + +[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml) Espressif Systems is a privately held fabless semiconductor company. They provide wireless communications and Wi-Fi chips which are widely used in mobile devices and the Internet of Things applications. @@ -16,16 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid ```ini [env:stable] -platform = espressif32 -board = ... -... -``` - -## Development version - -```ini -[env:development] -platform = https://github.com/platformio/platform-espressif32.git +platform = replace with url board = ... ... ``` diff --git a/boards/adafruit_feather_esp32_v2.json b/boards/adafruit_feather_esp32_v2.json new file mode 100644 index 000000000..2cd0eede4 --- /dev/null +++ b/boards/adafruit_feather_esp32_v2.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DADAFRUIT_FEATHER_ESP32_V2 -DBOARD_HAS_PSRAM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "adafruit_feather_esp32_v2" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32 V2", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5400", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_funhouse_esp32s2.json b/boards/adafruit_funhouse_esp32s2.json new file mode 100644 index 000000000..974761247 --- /dev/null +++ b/boards/adafruit_funhouse_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FUNHOUSE_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80F9" + ], + [ + "0x239A", + "0x00F9" + ], + [ + "0x239A", + "0x80FA" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_funhouse_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit FunHouse", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_funhouse_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4985", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_magtag29_esp32s2.json b/boards/adafruit_magtag29_esp32s2.json new file mode 100644 index 000000000..40d7bd3e9 --- /dev/null +++ b/boards/adafruit_magtag29_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_MAGTAG29_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80DF" + ], + [ + "0x239A", + "0x00DF" + ], + [ + "0x239A", + "0x80E0" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_magtag29_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit MagTag 2.9", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_magtag29_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4800", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_metro_esp32s2.json b/boards/adafruit_metro_esp32s2.json new file mode 100644 index 000000000..af8df2279 --- /dev/null +++ b/boards/adafruit_metro_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_METRO_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80DF" + ], + [ + "0x239A", + "0x00DF" + ], + [ + "0x239A", + "0x80E0" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_metro_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Metro ESP32-S2", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_metro_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4775", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qt_py_esp32-c3.json b/boards/adafruit_qt_py_esp32-c3.json new file mode 100644 index 000000000..515397eac --- /dev/null +++ b/boards/adafruit_qt_py_esp32-c3.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5405", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32-s2.json b/boards/adafruit_qtpy_esp32-s2.json new file mode 100644 index 000000000..9ef92b3e2 --- /dev/null +++ b/boards/adafruit_qtpy_esp32-s2.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s2", + "variant": "adafruit_qtpy_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5325", + "vendor": "Adafruit" +} diff --git a/boards/atmegazero_esp32s2.json b/boards/atmegazero_esp32s2.json new file mode 100644 index 000000000..bfc40697f --- /dev/null +++ b/boards/atmegazero_esp32s2.json @@ -0,0 +1,53 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_atmegazero_esp32s2", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x800A" + ] + ], + "mcu": "esp32s2", + "variant": "atmegazero_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "EspinalLab ATMegaZero ESP32-S2", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/atmegazero_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://shop.atmegazero.com/", + "vendor": "EspinalLab" +} diff --git a/boards/az-delivery-devkit-v4.json b/boards/az-delivery-devkit-v4.json index 45fa0a20b..93237d723 100644 --- a/boards/az-delivery-devkit-v4.json +++ b/boards/az-delivery-devkit-v4.json @@ -28,7 +28,7 @@ "upload": { "flash_size": "4MB", "maximum_ram_size": 532480, - "maximum_size": 16777216, + "maximum_size": 4194304, "require_upload_port": true, "speed": 460800 }, diff --git a/boards/deneyapkart.json b/boards/deneyapkart.json new file mode 100644 index 000000000..3114c0399 --- /dev/null +++ b/boards/deneyapkart.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYDK", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "deneyapkart" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/magaza/urun-deneyap-kart.html", + "vendor": "Deneyap" +} diff --git a/boards/deneyapmini.json b/boards/deneyapmini.json new file mode 100644 index 000000000..02509684b --- /dev/null +++ b/boards/deneyapmini.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_DYM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x0002" + ] + ], + "mcu": "esp32s2", + "variant": "deneyapmini" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/magaza/urun-deneyap-kart-mini.html", + "vendor": "Deneyap" +} diff --git a/boards/denky32.json b/boards/denky32.json new file mode 100644 index 000000000..3b2c40762 --- /dev/null +++ b/boards/denky32.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DENKY_WROOM32", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ch_denky" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Denky32 (WROOM32)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Denky" +} diff --git a/boards/denky_d4.json b/boards/denky_d4.json new file mode 100644 index 000000000..e5d0b76bd --- /dev/null +++ b/boards/denky_d4.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DENKY_PICOV3", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ch_denky" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Denky D4 (PICO-V3-02)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Denky" +} diff --git a/boards/esp32-c3-devkitm-1.json b/boards/esp32-c3-devkitm-1.json index 5b101a862..bc4ba058c 100644 --- a/boards/esp32-c3-devkitm-1.json +++ b/boards/esp32-c3-devkitm-1.json @@ -7,6 +7,7 @@ "f_cpu": "160000000L", "f_flash": "80000000L", "flash_mode": "qio", + "extra_flags": "-DARDUINO_ESP32C3_DEV", "mcu": "esp32c3", "variant": "esp32c3" }, @@ -17,6 +18,7 @@ "openocd_target": "esp32c3.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Espressif ESP32-C3-DevKitM-1", diff --git a/boards/esp32-c3-mini.json b/boards/esp32-c3-mini.json new file mode 100644 index 000000000..936f27c26 --- /dev/null +++ b/boards/esp32-c3-mini.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-C3-MINI", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html", + "vendor": "Espressif" +} diff --git a/boards/esp32-s2-franzininho.json b/boards/esp32-s2-franzininho.json new file mode 100644 index 000000000..d20d12a45 --- /dev/null +++ b/boards/esp32-s2-franzininho.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ld": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32s2", + "variant": "esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Franzininho WiFi Board", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/Franzininho/Franzininho-WIFI", + "vendor": "Franzininho" +} diff --git a/boards/esp32-s2-kaluga-1.json b/boards/esp32-s2-kaluga-1.json index ae785b77c..b48abac37 100644 --- a/boards/esp32-s2-kaluga-1.json +++ b/boards/esp32-s2-kaluga-1.json @@ -4,9 +4,10 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s2", "variant": "esp32s2" }, @@ -21,6 +22,7 @@ "openocd_target": "esp32s2.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Espressif ESP32-S2-Kaluga-1 Kit", diff --git a/boards/esp32-s2-saola-1.json b/boards/esp32-s2-saola-1.json index ab4f9fe09..58927bb91 100644 --- a/boards/esp32-s2-saola-1.json +++ b/boards/esp32-s2-saola-1.json @@ -4,9 +4,10 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s2", "variant": "esp32s2" }, @@ -17,6 +18,7 @@ "openocd_target": "esp32s2.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Espressif ESP32-S2-Saola-1", diff --git a/boards/esp32-s2-usb.json b/boards/esp32-s2-usb.json new file mode 100644 index 000000000..9ef92b3e2 --- /dev/null +++ b/boards/esp32-s2-usb.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s2", + "variant": "adafruit_qtpy_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5325", + "vendor": "Adafruit" +} diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json new file mode 100644 index 000000000..67c43b8f6 --- /dev/null +++ b/boards/esp32-s3-devkitc-1.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qspi_qspi" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S3-DevKitC-1", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 524288, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html", + "vendor": "Espressif" +} diff --git a/boards/esp32-s3-usb.json b/boards/esp32-s3-usb.json new file mode 100644 index 000000000..92daae518 --- /dev/null +++ b/boards/esp32-s3-usb.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qspi_qspi" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S3-DevKitC-1", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 524288, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html", + "vendor": "Espressif" +} diff --git a/boards/featheresp32-s2.json b/boards/featheresp32-s2.json index 00bf22d46..bf6f0cbc2 100644 --- a/boards/featheresp32-s2.json +++ b/boards/featheresp32-s2.json @@ -4,11 +4,29 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80EB" + ], + [ + "0x239A", + "0x00EB" + ], + [ + "0x239A", + "0x80EC" + ] + ], "mcu": "esp32s2", - "variant": "esp32s2" + "variant": "adafruit_feather_esp32s2" }, "connectivity": [ "wifi" @@ -17,13 +35,24 @@ "openocd_target": "esp32s2.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Adafruit ESP32-S2 Feather Development Board", "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2/tinyuf2.bin" + ] + ] + }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, "require_upload_port": true, "speed": 460800 }, diff --git a/boards/franzininho_wifi_esp32s2.json b/boards/franzininho_wifi_esp32s2.json new file mode 100644 index 000000000..df3a5651f --- /dev/null +++ b/boards/franzininho_wifi_esp32s2.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FRANZININHO_WIFI", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80A9" + ] + ], + "mcu": "esp32s2", + "variant": "franzininho_wifi_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Franzininho WiFi", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.franzininho.com.br/docs/franzininho-wifi/franzininho-wifi/", + "vendor": "Franzininho" +} diff --git a/boards/franzininho_wifi_msc_esp32s2.json b/boards/franzininho_wifi_msc_esp32s2.json new file mode 100644 index 000000000..163587b4f --- /dev/null +++ b/boards/franzininho_wifi_msc_esp32s2.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FRANZININHO_WIFI_MSC", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MSC_ON_BOOT=1", + "-DARDUINO_USB_DFU_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80A9" + ] + ], + "mcu": "esp32s2", + "variant": "franzininho_wifi_msc_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Franzininho WiFi MSC", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.franzininho.com.br/docs/franzininho-wifi/franzininho-wifi/", + "vendor": "Franzininho" +} diff --git a/boards/kb32-ft.json b/boards/kb32-ft.json new file mode 100644 index 000000000..586494f38 --- /dev/null +++ b/boards/kb32-ft.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_DEV", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MakerAsia KB32-FT", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://kb32ft.makerasia.com/", + "vendor": "MakerAsia" +} diff --git a/boards/lionbit.json b/boards/lionbit.json new file mode 100644 index 000000000..41e4cf65e --- /dev/null +++ b/boards/lionbit.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "flags" : "-DCORE_DEBUG_LEVEL=5", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "LionBit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 115200 + }, + "monitor": { + "speed" : 115200 + }, + "url": "http://lionbit.lk/", + "vendor": "Lion::Bit" +} diff --git a/boards/m5stack-core2.json b/boards/m5stack-core2.json index 1a3dcb521..2c3b95154 100644 --- a/boards/m5stack-core2.json +++ b/boards/m5stack-core2.json @@ -5,7 +5,7 @@ "partitions": "default_16MB.csv" }, "core": "esp32", - "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", diff --git a/boards/m5stack-fire.json b/boards/m5stack-fire.json index 4f3ff39fd..1a500ab87 100644 --- a/boards/m5stack-fire.json +++ b/boards/m5stack-fire.json @@ -5,7 +5,12 @@ "partitions": "default_16MB.csv" }, "core": "esp32", - "extra_flags": "-DARDUINO_M5STACK_FIRE -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_M5STACK_FIRE", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", diff --git a/boards/m5stack-timer-cam.json b/boards/m5stack-timer-cam.json index 41ff2a809..5f76a861e 100644 --- a/boards/m5stack-timer-cam.json +++ b/boards/m5stack-timer-cam.json @@ -4,7 +4,12 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_M5Stack_Timer_CAM -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_M5Stack_Timer_CAM", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", diff --git a/boards/micros2.json b/boards/micros2.json new file mode 100644 index 000000000..93243bdba --- /dev/null +++ b/boards/micros2.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld", + "partitions": "ffat.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_MICROS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MSC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80C5" + ] + ], + "mcu": "esp32s2", + "variant": "micro_s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "microS2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/MicroDev1/microS2", + "vendor": "microS2" +} diff --git a/boards/nano32.json b/boards/nano32.json index eeb8a20bf..2e1f5568c 100644 --- a/boards/nano32.json +++ b/boards/nano32.json @@ -19,9 +19,7 @@ ], "frameworks": [ "arduino", - "espidf", - "simba", - "pumbaa" + "espidf" ], "name": "MakerAsia Nano32", "upload": { diff --git a/boards/qtpy-esp32-s2.json b/boards/qtpy-esp32-s2.json new file mode 100644 index 000000000..73d927da5 --- /dev/null +++ b/boards/qtpy-esp32-s2.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s2", + "variant": "adafruit_qtpy_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5325", + "vendor": "Adafruit" +} diff --git a/boards/sparkfun_esp32micromod.json b/boards/sparkfun_esp32micromod.json new file mode 100644 index 000000000..2d0f52e8a --- /dev/null +++ b/boards/sparkfun_esp32micromod.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_MICROMOD", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32micromod" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32 MicroMod", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/16781", + "vendor": "SparkFun" +} diff --git a/boards/sparkfun_esp32s2_thing_plus.json b/boards/sparkfun_esp32s2_thing_plus.json new file mode 100644 index 000000000..269d962fc --- /dev/null +++ b/boards/sparkfun_esp32s2_thing_plus.json @@ -0,0 +1,43 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32S2_THING_PLUS", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x1B4F", + "0x0027" + ] + ], + "mcu": "esp32s2", + "variant": "esp32s2thing_plus" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32-S2 Thing Plus", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "mode": "usb", + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/17743", + "vendor": "SparkFun" +} diff --git a/boards/tinypico.json b/boards/tinypico.json index 754a9870c..9f3deeabb 100644 --- a/boards/tinypico.json +++ b/boards/tinypico.json @@ -4,12 +4,17 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_TINYPICO -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_TINYPICO", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "qio", + "flash_mode": "dio", "mcu": "esp32", - "variant": "pico32" + "variant": "um_tinypico" }, "connectivity": [ "wifi", diff --git a/boards/trueverit-iot-driver-mk2.json b/boards/trueverit-iot-driver-mk2.json new file mode 100644 index 000000000..22e3eca79 --- /dev/null +++ b/boards/trueverit-iot-driver-mk2.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver_MK_II", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver-mkii" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver MK II", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} diff --git a/boards/trueverit-iot-driver.json b/boards/trueverit-iot-driver.json new file mode 100644 index 000000000..7f808ec32 --- /dev/null +++ b/boards/trueverit-iot-driver.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} diff --git a/boards/ttgo-t-watch.json b/boards/ttgo-t-watch.json index c58c273f3..354f54f14 100644 --- a/boards/ttgo-t-watch.json +++ b/boards/ttgo-t-watch.json @@ -5,7 +5,12 @@ "partitions": "default_16MB.csv" }, "core": "esp32", - "extra_flags": "-DARDUINO_TWATCH_BASE -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_TWATCH_BASE", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", diff --git a/boards/um_feathers2.json b/boards/um_feathers2.json new file mode 100644 index 000000000..7434f195e --- /dev/null +++ b/boards/um_feathers2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80AB" + ] + ], + "mcu": "esp32s2", + "variant": "um_feathers2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker FeatherS2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://feathers2.io", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_feathers2_neo.json b/boards/um_feathers2_neo.json new file mode 100644 index 000000000..7277d45ff --- /dev/null +++ b/boards/um_feathers2_neo.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS2NEO", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80B4" + ] + ], + "mcu": "esp32s2", + "variant": "um_feathers2neo" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker FeatherS2 Neo", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://unexpectedmaker.com/feathers2-neo", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_tinys2.json b/boards/um_tinys2.json new file mode 100644 index 000000000..8a57216ac --- /dev/null +++ b/boards/um_tinys2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TINYS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x8001" + ] + ], + "mcu": "esp32s2", + "variant": "um_tinys2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker TinyS2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://tinys2.io", + "vendor": "Unexpected Maker" +} diff --git a/boards/upesy_wroom.json b/boards/upesy_wroom.json new file mode 100644 index 000000000..999cef7c2 --- /dev/null +++ b/boards/upesy_wroom.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_uPesy_WROOM", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "uPesy_esp32_wroom_devkit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "uPesy ESP32 Wroom DevKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.upesy.fr/products/upesy-esp32-wroom-devkit-board", + "vendor": "uPesy" +} diff --git a/boards/upesy_wrover.json b/boards/upesy_wrover.json new file mode 100644 index 000000000..38b2eb3e7 --- /dev/null +++ b/boards/upesy_wrover.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_uPesy_WROVER", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "uPesy_esp32_wrover_devkit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "uPesy ESP32 Wrover DevKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.upesy.fr/products/upesy-esp32-wrover-devkit-board", + "vendor": "uPesy" +} diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index a267e0f7a..5469e3bce 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -102,19 +102,22 @@ def transform_to_asm(target, source, env): return files, source +mcu = board.get("build.mcu", "esp32") env.Append( BUILDERS=dict( TxtToBin=Builder( action=env.VerboseAction( " ".join( [ - "xtensa-esp32-elf-objcopy", + "riscv32-esp-elf-objcopy" + if mcu == "esp32c3" + else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", - "elf32-xtensa-le", + "elf32-littleriscv" if mcu == "esp32c3" else "elf32-xtensa-le", "--binary-architecture", - "xtensa", + "riscv" if mcu == "esp32c3" else "xtensa", "--rename-section", ".data=.rodata.embedded", "$SOURCE", diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 161ad70ee..c6fc754a6 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -41,3 +41,4 @@ SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) + env["IDE_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 0b8e3566d..425d02bc9 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -55,18 +55,13 @@ % ( "riscv32-esp" if mcu == "esp32c3" - else ("xtensa-esp32s2" if mcu == "esp32s2" else "xtensa-esp32") + else ("xtensa-%s" % mcu) ) ) -# Legacy toolchains for mixed IDF/Arduino projects -if "arduino" in env.subst("$PIOFRAMEWORK"): - TOOLCHAIN_DIR = platform.get_package_dir("toolchain-xtensa32") - assert os.path.isdir(FRAMEWORK_DIR) assert os.path.isdir(TOOLCHAIN_DIR) -# Arduino framework as a component is not compatible with ESP-IDF >=4.1 if "arduino" in env.subst("$PIOFRAMEWORK"): ARDUINO_FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") # Possible package names in 'package@version' format is not compatible with CMake @@ -233,7 +228,13 @@ def populate_idf_env_vars(idf_env): if mcu != "esp32c3": additional_packages.append( - os.path.join(platform.get_package_dir("toolchain-%sulp" % mcu), "bin"), + os.path.join( + platform.get_package_dir( + "toolchain-%sulp" + % ("esp32s2" if (mcu == "esp32s3" or mcu == "esp32s2") else mcu) + ), + "bin" + ), ) if "windows" in get_systype(): @@ -341,7 +342,7 @@ def _add_archive(archive_path, link_args): if fragment.startswith("-l"): link_args["LIBS"].extend(args) elif fragment.startswith("-L"): - lib_path = fragment.replace("-L", "").strip() + lib_path = fragment.replace("-L", "").strip().strip('"') _add_to_libpath(lib_path, link_args) elif fragment.startswith("-") and not fragment.startswith("-l"): # CMake mistakenly marks LINKFLAGS as libraries @@ -452,20 +453,11 @@ def find_framework_service_files(search_path, sdk_config): result["lf_files"].extend( [ - os.path.join( - FRAMEWORK_DIR, - "components", - idf_variant, - "ld", - "%s_fragments.lf" % idf_variant, - ), - os.path.join( - FRAMEWORK_DIR, - "components", - idf_variant, - "linker.lf", - ), + os.path.join(FRAMEWORK_DIR, "components", "esp_common", "common.lf"), + os.path.join(FRAMEWORK_DIR, "components", "esp_common", "soc.lf"), + os.path.join(FRAMEWORK_DIR, "components", "esp_system", "app.lf"), os.path.join(FRAMEWORK_DIR, "components", "newlib", "newlib.lf"), + os.path.join(FRAMEWORK_DIR, "components", "newlib", "system_libs.lf"), ] ) @@ -515,6 +507,46 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): libraries_list = create_custom_libraries_list( os.path.join(BUILD_DIR, "ldgen_libraries"), ignore_targets ) + # Rework the memory template linker script, following components/esp_system/ld.cmake + args = { + "preprocess" : os.path.join( + TOOLCHAIN_DIR, + "bin", + env.subst("$CC")), + "ld_output": os.path.join("$BUILD_DIR", "memory.ld"), + "ld_dir": os.path.join( + FRAMEWORK_DIR, + "components", + "esp_system", + "ld"), + "ld_input": os.path.join( + FRAMEWORK_DIR, + "components", + "esp_system", + "ld", + idf_variant, + "memory.ld.in", + ), + "config": os.path.join("$BUILD_DIR", "config"), + "flags" : '-C -P -x c -E -o ' + } + + cmd = ( + '"{preprocess}" {flags} "{ld_output}" -I "{config}" -I "{ld_dir}" "{ld_input}"' + ).format(**args) + + env.Command( + os.path.join("$BUILD_DIR", "memory.ld"), + os.path.join( + FRAMEWORK_DIR, + "components", + "esp_system", + "ld", + idf_variant, + "memory.ld.in", + ), + env.VerboseAction(cmd, "Generating memory linker script $TARGET"), + ) args = { "script": os.path.join(FRAMEWORK_DIR, "tools", "ldgen", "ldgen.py"), @@ -539,13 +571,14 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): ).format(**args) return env.Command( - os.path.join("$BUILD_DIR", "%s.project.ld" % idf_variant), + os.path.join("$BUILD_DIR", "sections.ld"), os.path.join( FRAMEWORK_DIR, "components", - idf_variant, + "esp_system", "ld", - "%s.project.ld.in" % idf_variant, + idf_variant, + "sections.ld.in", ), env.VerboseAction(cmd, "Generating project linker script $TARGET"), ) @@ -703,6 +736,20 @@ def find_lib_deps(components_map, elf_config, link_args, ignore_components=None) return result +def fix_ld_paths(extra_flags): + peripheral_framework_path = os.path.join(FRAMEWORK_DIR, "components", "soc", idf_variant, "ld") + rom_framework_path = os.path.join(FRAMEWORK_DIR, "components", "esp_rom", idf_variant, "ld") + bl_framework_path = os.path.join(FRAMEWORK_DIR, "components", "bootloader", "subproject", "main", "ld", idf_variant) + + # ESP linker scripts changed path in ESP-IDF 4.4+, so add missing paths to linker's search path + try: + ld_index = extra_flags.index("%s.peripherals.ld" % idf_variant) + extra_flags[ld_index-1:ld_index-1] = [ "-L", peripheral_framework_path, "-L", rom_framework_path, "-L", bl_framework_path] + except: + print("Error while parsing the flags") + + return extra_flags + def build_bootloader(): bootloader_src_dir = os.path.join( @@ -747,6 +794,7 @@ def build_bootloader(): build_components(bootloader_env, components_map, bootloader_src_dir, "bootloader") link_args = extract_link_args(elf_config) extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) + extra_flags = fix_ld_paths(extra_flags) link_args["LINKFLAGS"] = sorted( list(set(link_args["LINKFLAGS"]) - set(extra_flags)) ) @@ -1061,21 +1109,23 @@ def _get_installed_pip_packages(): if not board.get("build.ldscript", ""): linker_script = env.Command( - os.path.join("$BUILD_DIR", "%s_out.ld" % idf_variant), + os.path.join("$BUILD_DIR", "memory.ld"), board.get( "build.esp-idf.ldscript", os.path.join( - FRAMEWORK_DIR, "components", idf_variant, "ld", "%s.ld" % idf_variant + FRAMEWORK_DIR, "components", "esp_system", "ld", idf_variant, "memory.ld.in" ), ), env.VerboseAction( - '$CC -I"$BUILD_DIR/config" -C -P -x c -E $SOURCE -o $TARGET', + '$CC -I"$BUILD_DIR/config" -I"' + + os.path.join(FRAMEWORK_DIR, "components", "esp_system", "ld") + + '" -C -P -x c -E $SOURCE -o $TARGET', "Generating LD script $TARGET", ), ) env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", linker_script) - env.Replace(LDSCRIPT_PATH="%s_out.ld" % idf_variant) + env.Replace(LDSCRIPT_PATH="memory.ld") # # Generate partition table @@ -1257,13 +1307,15 @@ def _get_installed_pip_packages(): # Extra flags which need to be explicitly specified in LINKFLAGS section because SCons # cannot merge them correctly extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) +extra_flags = fix_ld_paths(extra_flags) link_args["LINKFLAGS"] = sorted(list(set(link_args["LINKFLAGS"]) - set(extra_flags))) -# remove the main linker script flags '-T esp32_out.ld' +# remove the main linker script flags '-T memory.ld' since it already appears later on try: - ld_index = extra_flags.index("%s_out.ld" % idf_variant) + ld_index = extra_flags.index("memory.ld") extra_flags.pop(ld_index) extra_flags.pop(ld_index - 1) + pass except: print("Warning! Couldn't find the main linker script in the CMake code model.") @@ -1319,7 +1371,7 @@ def _skip_prj_source_files(node): FLASH_EXTRA_IMAGES=[ ( board.get( - "upload.bootloader_offset", "0x0" if mcu == "esp32c3" else "0x1000" + "upload.bootloader_offset", "0x0" if (mcu == "esp32c3" or mcu == "esp32s3") else "0x1000" ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), diff --git a/builder/frameworks/pumbaa.py b/builder/frameworks/pumbaa.py deleted file mode 100644 index c9b77c0df..000000000 --- a/builder/frameworks/pumbaa.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2014-present PlatformIO -# -# 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. - -"""Pumbaa - -Pumbaa is Python on top of Simba. - -The implementation is a port of MicroPython, designed for embedded -devices with limited amount of RAM and code memory. - -http://pumbaa.readthedocs.org - -""" - -from os.path import join, sep - -from SCons.Script import DefaultEnvironment, SConscript - -from platformio.builder.tools import platformio as platformio_tool - -# -# Backward compatibility with PlatformIO 2.0 -# -platformio_tool.SRC_DEFAULT_FILTER = " ".join([ - "+<*>", "-<.git%s>" % sep, "-" % sep, - "-" % sep, "-" % sep, - "-" % sep, "-" % sep -]) - - -def LookupSources(env, variant_dir, src_dir, duplicate=True, src_filter=None): - return env.CollectBuildFiles(variant_dir, src_dir, src_filter, duplicate) - - -def VariantDirWrap(env, variant_dir, src_dir, duplicate=False): - env.VariantDir(variant_dir, src_dir, duplicate) - - -env = DefaultEnvironment() - -env.AddMethod(LookupSources) -env.AddMethod(VariantDirWrap) - -env.Replace( - PLATFORMFW_DIR=env.PioPlatform().get_package_dir("framework-pumbaa"), - UPLOADERFLAGS=[] # Backward compatibility for obsolete build script -) - -SConscript( - [env.subst(join("$PLATFORMFW_DIR", "make", "platformio.sconscript"))]) - -env.Replace( - FLASH_EXTRA_IMAGES=[ - ("0x1000", join("$PLATFORMFW_DIR", "simba", "3pp", "esp32", - "bin", "bootloader.bin")), - ("0x8000", join("$PLATFORMFW_DIR", "simba", "3pp", "esp32", - "bin", "partitions_singleapp.bin")) - ] -) diff --git a/builder/frameworks/simba.py b/builder/frameworks/simba.py deleted file mode 100644 index 0def12da6..000000000 --- a/builder/frameworks/simba.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2014-present PlatformIO -# -# 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. - -"""Simba - -Simba is an RTOS and build framework. It aims to make embedded -programming easy and portable. - -http://simba-os.readthedocs.org - -""" - -from os.path import join, sep - -from SCons.Script import DefaultEnvironment, SConscript - -from platformio.builder.tools import platformio as platformio_tool - -# -# Backward compatibility with PlatformIO 2.0 -# -platformio_tool.SRC_DEFAULT_FILTER = " ".join([ - "+<*>", "-<.git%s>" % sep, "-" % sep, - "-" % sep, "-" % sep, - "-" % sep, "-" % sep -]) - - -def LookupSources(env, variant_dir, src_dir, duplicate=True, src_filter=None): - return env.CollectBuildFiles(variant_dir, src_dir, src_filter, duplicate) - - -def VariantDirWrap(env, variant_dir, src_dir, duplicate=False): - env.VariantDir(variant_dir, src_dir, duplicate) - - -env = DefaultEnvironment() - -env.AddMethod(LookupSources) -env.AddMethod(VariantDirWrap) - -env.Replace( - PLATFORMFW_DIR=env.PioPlatform().get_package_dir("framework-simba"), - UPLOADERFLAGS=[] # Backward compatibility for obsolete build script -) - -SConscript( - [env.subst(join("$PLATFORMFW_DIR", "make", "platformio.sconscript"))]) - -env.Replace( - FLASH_EXTRA_IMAGES=[ - ("0x1000", join("$PLATFORMFW_DIR", "3pp", "esp32", - "bin", "bootloader.bin")), - ("0x8000", join("$PLATFORMFW_DIR", "3pp", "esp32", - "bin", "partitions_singleapp.bin")) - ] -) diff --git a/builder/main.py b/builder/main.py index 1f01bf870..cbfa1c7ec 100644 --- a/builder/main.py +++ b/builder/main.py @@ -20,11 +20,28 @@ ARGUMENTS, COMMAND_LINE_TARGETS, AlwaysBuild, Builder, Default, DefaultEnvironment) +from platformio.util import get_serial_ports + # # Helpers # +def BeforeUpload(target, source, env): + upload_options = {} + if "BOARD" in env: + upload_options = env.BoardConfig().get("upload", {}) + + env.AutodetectUploadPort() + + before_ports = get_serial_ports() + if upload_options.get("use_1200bps_touch", False): + env.TouchSerialPort("$UPLOAD_PORT", 1200) + + if upload_options.get("wait_for_upload_port", False): + env.Replace(UPLOAD_PORT=env.WaitForNewSerialPort(before_ports)) + + def _get_board_f_flash(env): frequency = env.subst("$BOARD_F_FLASH") frequency = str(frequency).replace("L", "") @@ -102,34 +119,40 @@ def _update_max_upload_size(env): def _to_unix_slashes(path): - return path.replace('\\', '/') + return path.replace("\\", "/") # -# SPIFFS helpers +# Filesystem helpers # -def fetch_spiffs_size(env): - spiffs = None +def fetch_fs_size(env): + fs = None for p in _parse_partitions(env): - if p['type'] == "data" and p['subtype'] == "spiffs": - spiffs = p - if not spiffs: + if p["type"] == "data" and p["subtype"] in ("spiffs", "fat"): + fs = p + if not fs: sys.stderr.write( - "Could not find the `spiffs` section in the partitions " + "Could not find the any filesystem section in the partitions " "table %s\n" % env.subst("$PARTITIONS_TABLE_CSV") ) env.Exit(1) return - env["SPIFFS_START"] = _parse_size(spiffs['offset']) - env["SPIFFS_SIZE"] = _parse_size(spiffs['size']) - env["SPIFFS_PAGE"] = int("0x100", 16) - env["SPIFFS_BLOCK"] = int("0x1000", 16) + env["FS_START"] = _parse_size(fs["offset"]) + env["FS_SIZE"] = _parse_size(fs["size"]) + env["FS_PAGE"] = int("0x100", 16) + env["FS_BLOCK"] = int("0x1000", 16) + + # FFat specific offsets, see: + # https://github.com/lorol/arduino-esp32fatfs-plugin#notes-for-fatfs + if filesystem == "fatfs": + env["FS_START"] += 4096 + env["FS_SIZE"] -= 4096 -def __fetch_spiffs_size(target, source, env): - fetch_spiffs_size(env) +def __fetch_fs_size(target, source, env): + fetch_fs_size(env) return (target, source) @@ -139,6 +162,7 @@ def __fetch_spiffs_size(target, source, env): board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") toolchain_arch = "xtensa-%s" % mcu +filesystem = board.get("build.filesystem", "spiffs") if mcu == "esp32c3": toolchain_arch = "riscv32-esp" @@ -146,14 +170,14 @@ def __fetch_spiffs_size(target, source, env): __get_board_f_flash=_get_board_f_flash, __get_board_flash_mode=_get_board_flash_mode, - AR="%s-elf-ar" % toolchain_arch, + AR="%s-elf-gcc-ar" % toolchain_arch, AS="%s-elf-as" % toolchain_arch, CC="%s-elf-gcc" % toolchain_arch, CXX="%s-elf-g++" % toolchain_arch, GDB="%s-elf-gdb" % toolchain_arch, OBJCOPY=join( platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), - RANLIB="%s-elf-ranlib" % toolchain_arch, + RANLIB="%s-elf-gcc-ranlib" % toolchain_arch, SIZETOOL="%s-elf-size" % toolchain_arch, ARFLAGS=["rc"], @@ -169,10 +193,27 @@ def __fetch_spiffs_size(target, source, env): ], ERASECMD='"$PYTHONEXE" "$OBJCOPY" $ERASEFLAGS erase_flash', - MKSPIFFSTOOL="mkspiffs_${PIOPLATFORM}_" + ("espidf" if "espidf" in env.subst( - "$PIOFRAMEWORK") else "${PIOFRAMEWORK}"), - ESP32_SPIFFS_IMAGE_NAME=env.get("ESP32_SPIFFS_IMAGE_NAME", "spiffs"), - ESP32_APP_OFFSET="0x10000", + # mkspiffs package contains two different binaries for IDF and Arduino + MKFSTOOL="mk%s" % filesystem + + ( + ( + "_${PIOPLATFORM}_" + + ( + "espidf" + if "espidf" in env.subst("$PIOFRAMEWORK") + else "${PIOFRAMEWORK}" + ) + ) + if filesystem == "spiffs" + else "" + ), + # Legacy `ESP32_SPIFFS_IMAGE_NAME` is used as the second fallback value for + # backward compatibility + ESP32_FS_IMAGE_NAME=env.get( + "ESP32_FS_IMAGE_NAME", env.get("ESP32_SPIFFS_IMAGE_NAME", filesystem) + ), + + ESP32_APP_OFFSET=board.get("upload.offset_address", "0x10000"), PROGSUFFIX=".elf" ) @@ -189,8 +230,7 @@ def __fetch_spiffs_size(target, source, env): ElfToBin=Builder( action=env.VerboseAction(" ".join([ '"$PYTHONEXE" "$OBJCOPY"', - "--chip", mcu, - "elf2image", + "--chip", mcu, "elf2image", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "detect"), @@ -199,18 +239,27 @@ def __fetch_spiffs_size(target, source, env): suffix=".bin" ), DataToBin=Builder( - action=env.VerboseAction(" ".join([ - '"$MKSPIFFSTOOL"', - "-c", "$SOURCES", - "-p", "$SPIFFS_PAGE", - "-b", "$SPIFFS_BLOCK", - "-s", "$SPIFFS_SIZE", - "$TARGET" - ]), "Building SPIFFS image from '$SOURCES' directory to $TARGET"), - emitter=__fetch_spiffs_size, + action=env.VerboseAction( + " ".join( + ['"$MKFSTOOL"', "-c", "$SOURCES", "-s", "$FS_SIZE"] + + ( + [ + "-p", + "$FS_PAGE", + "-b", + "$FS_BLOCK", + ] + if filesystem in ("spiffs", "littlefs") + else [] + ) + + ["$TARGET"] + ), + "Building FS image from '$SOURCES' directory to $TARGET", + ), + emitter=__fetch_fs_size, source_factory=env.Dir, - suffix=".bin" - ) + suffix=".bin", + ), ) ) @@ -218,22 +267,23 @@ def __fetch_spiffs_size(target, source, env): env.SConscript("frameworks/_bare.py", exports="env") # -# Target: Build executable and linkable firmware or SPIFFS image +# Target: Build executable and linkable firmware or FS image # target_elf = None if "nobuild" in COMMAND_LINE_TARGETS: target_elf = join("$BUILD_DIR", "${PROGNAME}.elf") if set(["uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): - fetch_spiffs_size(env) - target_firm = join("$BUILD_DIR", "${ESP32_SPIFFS_IMAGE_NAME}.bin") + fetch_fs_size(env) + target_firm = join("$BUILD_DIR", "${ESP32_FS_IMAGE_NAME}.bin") else: target_firm = join("$BUILD_DIR", "${PROGNAME}.bin") else: target_elf = env.BuildProgram() if set(["buildfs", "uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): target_firm = env.DataToBin( - join("$BUILD_DIR", "${ESP32_SPIFFS_IMAGE_NAME}"), "$PROJECT_DATA_DIR") + join("$BUILD_DIR", "${ESP32_FS_IMAGE_NAME}"), "$PROJECT_DATA_DIR" + ) env.NoCache(target_firm) AlwaysBuild(target_firm) else: @@ -269,7 +319,7 @@ def __fetch_spiffs_size(target, source, env): ) # -# Target: Upload firmware or SPIFFS image +# Target: Upload firmware or FS image # upload_protocol = env.subst("$UPLOAD_PROTOCOL") @@ -319,7 +369,7 @@ def __fetch_spiffs_size(target, source, env): "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", "detect" + "--flash_size", board.get("upload.flash_size", "detect") ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE' ) @@ -337,14 +387,13 @@ def __fetch_spiffs_size(target, source, env): "write_flash", "-z", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_size", "detect", - "$SPIFFS_START" + "$FS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', ) upload_actions = [ - env.VerboseAction(env.AutodetectUploadPort, - "Looking for upload port..."), + env.VerboseAction(BeforeUpload, "Looking for upload port..."), env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE") ] @@ -380,18 +429,28 @@ def __fetch_spiffs_size(target, source, env): openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)] openocd_args.extend( debug_tools.get(upload_protocol).get("server").get("arguments", [])) - openocd_args.extend([ - "-c", "adapter_khz %s" % env.GetProjectOption("debug_speed", "5000"), - "-c", - "program_esp {{$SOURCE}} %s verify" % - board.get("upload.offset_address", "$ESP32_APP_OFFSET"), - ]) - for image in env.get("FLASH_EXTRA_IMAGES", []): - openocd_args.extend([ + openocd_args.extend( + [ + "-c", + "adapter_khz %s" % env.GetProjectOption("debug_speed", "5000"), "-c", - 'program_esp {{%s}} %s verify' % - (_to_unix_slashes(image[1]), image[0]) - ]) + "program_esp {{$SOURCE}} %s verify" + % ( + "$FS_START" + if "uploadfs" in COMMAND_LINE_TARGETS + else "$ESP32_APP_OFFSET" + ), + ] + ) + if "uploadfs" not in COMMAND_LINE_TARGETS: + for image in env.get("FLASH_EXTRA_IMAGES", []): + openocd_args.extend( + [ + "-c", + "program_esp {{%s}} %s verify" + % (_to_unix_slashes(image[1]), image[0]), + ] + ) openocd_args.extend(["-c", "reset run; shutdown"]) openocd_args = [ f.replace( @@ -400,9 +459,11 @@ def __fetch_spiffs_size(target, source, env): platform.get_package_dir("tool-openocd-esp32") or "")) for f in openocd_args ] - env.Replace(UPLOADER="openocd", - UPLOADERFLAGS=openocd_args, - UPLOADCMD="$UPLOADER $UPLOADERFLAGS") + env.Replace( + UPLOADER="openocd", + UPLOADERFLAGS=openocd_args, + UPLOADCMD="$UPLOADER $UPLOADERFLAGS", + ) upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")] # custom upload tool diff --git a/examples/pumbaa-blink/.gitignore b/examples/arduino-ble5-advertising/.gitignore old mode 100755 new mode 100644 similarity index 100% rename from examples/pumbaa-blink/.gitignore rename to examples/arduino-ble5-advertising/.gitignore diff --git a/examples/arduino-ble5-advertising/README.md b/examples/arduino-ble5-advertising/README.md new file mode 100644 index 000000000..f34cc0db8 --- /dev/null +++ b/examples/arduino-ble5-advertising/README.md @@ -0,0 +1,27 @@ +How to build PlatformIO based project +===================================== + +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) +2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) +3. Extract ZIP archive +4. Run these commands: + +```shell +# Change directory to example +$ cd platform-espressif32/examples/arduino-ble5-advertising + +# Build project +$ pio run + +# Upload firmware +$ pio run --target upload + +# Build specific environment +$ pio run -e esp32-c3-devkitm-1 + +# Upload firmware for the specific environment +$ pio run -e esp32-c3-devkitm-1 --target upload + +# Clean build files +$ pio run --target clean +``` \ No newline at end of file diff --git a/examples/pumbaa-blink/include/README b/examples/arduino-ble5-advertising/include/README similarity index 100% rename from examples/pumbaa-blink/include/README rename to examples/arduino-ble5-advertising/include/README diff --git a/examples/pumbaa-blink/lib/README b/examples/arduino-ble5-advertising/lib/README similarity index 100% rename from examples/pumbaa-blink/lib/README rename to examples/arduino-ble5-advertising/lib/README diff --git a/examples/pumbaa-blink/platformio.ini b/examples/arduino-ble5-advertising/platformio.ini old mode 100755 new mode 100644 similarity index 67% rename from examples/pumbaa-blink/platformio.ini rename to examples/arduino-ble5-advertising/platformio.ini index da2c58b75..638c205b6 --- a/examples/pumbaa-blink/platformio.ini +++ b/examples/arduino-ble5-advertising/platformio.ini @@ -5,9 +5,10 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html -[env:nano32] +[env:esp32-c3-devkitm-1] platform = espressif32 -framework = pumbaa -board = nano32 +board = esp32-c3-devkitm-1 +framework = arduino +monitor_speed = 115200 diff --git a/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino b/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino new file mode 100644 index 000000000..1b36bbb8b --- /dev/null +++ b/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino @@ -0,0 +1,72 @@ +/* + Simple BLE5 multi advertising example on esp32 C3/S3 + only ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED can be used for periodic advertising + + author: chegewara +*/ + +#include +#include + + +esp_ble_gap_ext_adv_params_t ext_adv_params_2M = { + .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED, + .interval_min = 0x40, + .interval_max = 0x40, + .channel_map = ADV_CHNL_ALL, + .own_addr_type = BLE_ADDR_TYPE_RANDOM, + .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + .primary_phy = ESP_BLE_GAP_PHY_1M, + .max_skip = 0, + .secondary_phy = ESP_BLE_GAP_PHY_2M, + .sid = 1, + .scan_req_notif = false, +}; + +static uint8_t raw_scan_rsp_data_2m[] = { + 0x02, 0x01, 0x06, + 0x02, 0x0a, 0xeb, + 0x12, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', + 'D', 'V', '_', '2', 'M', 0X0 +}; + +static esp_ble_gap_periodic_adv_params_t periodic_adv_params = { + .interval_min = 0x320, // 1000 ms interval + .interval_max = 0x640, + .properties = 0, // Do not include TX power +}; + +static uint8_t periodic_adv_raw_data[] = { + 0x02, 0x01, 0x06, + 0x02, 0x0a, 0xeb, + 0x03, 0x03, 0xab, 0xcd, + 0x11, 0x09, 'E', 'S', 'P', '_', 'P', 'E', 'R', 'I', 'O', 'D', 'I', + 'C', '_', 'A', 'D', 'V' +}; + + +uint8_t addr_2m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x02}; + +BLEMultiAdvertising advert(1); // max number of advertisement data + +void setup() { + Serial.begin(115200); + Serial.println("Multi-Advertising..."); + + BLEDevice::init(""); + + advert.setAdvertisingParams(0, &ext_adv_params_2M); + advert.setAdvertisingData(0, sizeof(raw_scan_rsp_data_2m), &raw_scan_rsp_data_2m[0]); + advert.setInstanceAddress(0, addr_2m); + advert.setDuration(0, 0, 0); + + delay(100); + advert.start(); + advert.setPeriodicAdvertisingParams(0, &periodic_adv_params); + advert.setPeriodicAdvertisingData(0, sizeof(periodic_adv_raw_data), &periodic_adv_raw_data[0]); + advert.startPeriodicAdvertising(0); +} + +void loop() { + delay(2000); +} diff --git a/examples/pumbaa-blink/test/README b/examples/arduino-ble5-advertising/test/README similarity index 100% rename from examples/pumbaa-blink/test/README rename to examples/arduino-ble5-advertising/test/README diff --git a/examples/arduino-rmt-blink/platformio.ini b/examples/arduino-rmt-blink/platformio.ini new file mode 100644 index 000000000..14244480d --- /dev/null +++ b/examples/arduino-rmt-blink/platformio.ini @@ -0,0 +1,17 @@ +[env:esp32-s2] +platform = espressif32 +framework = arduino +board = esp32-s2-saola-1 +build_flags = -DBUILTIN_RGBLED_PIN=18 + +[env:esp32-s3] +platform = espressif32 +framework = arduino +board = esp32-s3-devkitc-1 +build_flags = -DBUILTIN_RGBLED_PIN=48 + +[env:esp32-c3] +platform = espressif32 +framework = arduino +board = esp32-c3-devkitm-1 +build_flags = -DBUILTIN_RGBLED_PIN=8 diff --git a/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino b/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino new file mode 100644 index 000000000..eee7dcf3b --- /dev/null +++ b/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino @@ -0,0 +1,100 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "Arduino.h" + +#include "esp32-hal.h" + +// The effect seen in ESP32C3, ESP32S2 and ESP32S3 is like a Blink of RGB LED +//#if CONFIG_IDF_TARGET_ESP32S2 +//#define BUILTIN_RGBLED_PIN 18 +//#elif CONFIG_IDF_TARGET_ESP32S3 +//#define BUILTIN_RGBLED_PIN 48 +//#elif CONFIG_IDF_TARGET_ESP32C3 +//#define BUILTIN_RGBLED_PIN 8 +//#else +//#define BUILTIN_RGBLED_PIN 21 // ESP32 has no builtin RGB LED +//#endif + +#define NR_OF_LEDS 8*4 +#define NR_OF_ALL_BITS 24*NR_OF_LEDS + +// +// Note: This example uses Neopixel LED board, 32 LEDs chained one +// after another, each RGB LED has its 24 bit value +// for color configuration (8b for each color) +// +// Bits encoded as pulses as follows: +// +// "0": +// +-------+ +-- +// | | | +// | | | +// | | | +// ---| |--------------| +// + + + +// | 0.4us | 0.85 0us | +// +// "1": +// +-------------+ +-- +// | | | +// | | | +// | | | +// | | | +// ---+ +-------+ +// | 0.8us | 0.4us | + +rmt_data_t led_data[NR_OF_ALL_BITS]; + +rmt_obj_t* rmt_send = NULL; + +void setup() +{ + Serial.begin(115200); + + if ((rmt_send = rmtInit(BUILTIN_RGBLED_PIN, RMT_TX_MODE, RMT_MEM_64)) == NULL) + { + Serial.println("init sender failed\n"); + } + + float realTick = rmtSetTick(rmt_send, 100); + Serial.printf("real tick set to: %fns\n", realTick); + +} + +int color[] = { 0x55, 0x11, 0x77 }; // RGB value +int led_index = 0; + +void loop() +{ + // Init data with only one led ON + int led, col, bit; + int i=0; + for (led=0; led=NR_OF_LEDS) { + led_index = 0; + } + + // Send the data + rmtWrite(rmt_send, led_data, NR_OF_ALL_BITS); + + delay(100); +} diff --git a/examples/simba-blink/.gitignore b/examples/arduino-usb-keyboard/.gitignore old mode 100755 new mode 100644 similarity index 100% rename from examples/simba-blink/.gitignore rename to examples/arduino-usb-keyboard/.gitignore diff --git a/examples/arduino-usb-keyboard/README.md b/examples/arduino-usb-keyboard/README.md new file mode 100644 index 000000000..e9bd6a20e --- /dev/null +++ b/examples/arduino-usb-keyboard/README.md @@ -0,0 +1,27 @@ +How to build PlatformIO based project +===================================== + +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) +2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) +3. Extract ZIP archive +4. Run these commands: + +```shell +# Change directory to example +$ cd platform-espressif32/examples/arduino-usb-keyboard + +# Build project +$ pio run + +# Upload firmware +$ pio run --target upload + +# Build specific environment +$ pio run -e esp32-s2-saola-1 + +# Upload firmware for the specific environment +$ pio run -e esp32-s2-saola-1 --target upload + +# Clean build files +$ pio run --target clean +``` \ No newline at end of file diff --git a/examples/simba-blink/include/README b/examples/arduino-usb-keyboard/include/README similarity index 100% rename from examples/simba-blink/include/README rename to examples/arduino-usb-keyboard/include/README diff --git a/examples/simba-blink/lib/README b/examples/arduino-usb-keyboard/lib/README similarity index 100% rename from examples/simba-blink/lib/README rename to examples/arduino-usb-keyboard/lib/README diff --git a/examples/simba-blink/platformio.ini b/examples/arduino-usb-keyboard/platformio.ini old mode 100755 new mode 100644 similarity index 60% rename from examples/simba-blink/platformio.ini rename to examples/arduino-usb-keyboard/platformio.ini index 802ec5147..3f51b8378 --- a/examples/simba-blink/platformio.ini +++ b/examples/arduino-usb-keyboard/platformio.ini @@ -5,9 +5,15 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html -[env:nano32] +[env] platform = espressif32 -framework = simba -board = nano32 +framework = arduino +monitor_speed = 115200 + +[env:esp32-s2-saola-1] +board = esp32-s2-saola-1 + +[env:esp32-s2-kaluga-1] +board = esp32-s2-kaluga-1 \ No newline at end of file diff --git a/examples/arduino-usb-keyboard/src/KeyboardSerial.ino b/examples/arduino-usb-keyboard/src/KeyboardSerial.ino new file mode 100644 index 000000000..e3bb87697 --- /dev/null +++ b/examples/arduino-usb-keyboard/src/KeyboardSerial.ino @@ -0,0 +1,40 @@ +/* + Keyboard test + + Reads a byte from the serial port, sends a keystroke back. + The sent keystroke is one higher than what's received, e.g. if you send a, + you get b, send A you get B, and so forth. + + The circuit: + - none + + created 21 Oct 2011 + modified 27 Mar 2012 + by Tom Igoe + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/KeyboardSerial +*/ + +#include "USB.h" +#include "USBHIDKeyboard.h" +USBHIDKeyboard Keyboard; + +void setup() { + // open the serial port: + Serial.begin(115200); + // initialize control over the keyboard: + Keyboard.begin(); + USB.begin(); +} + +void loop() { + // check for incoming serial data: + if (Serial.available() > 0) { + // read incoming serial data: + char inChar = Serial.read(); + // Type the next ASCII value from what you received: + Keyboard.write(inChar + 1); + } +} diff --git a/examples/simba-blink/test/README b/examples/arduino-usb-keyboard/test/README similarity index 100% rename from examples/simba-blink/test/README rename to examples/arduino-usb-keyboard/test/README diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 8ee11c971..0f991013b 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -13,9 +13,6 @@ framework = arduino, espidf build_flags = -D CONFIG_BLINK_GPIO=2 monitor_speed = 115200 -platform_packages = - ; use a special branch - framework-arduinoespressif32 @ https://github.com/marcovannoord/arduino-esp32.git#idf-release/v4.0 [env:esp32dev] board = esp32dev diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index 909461e58..f56753404 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -7,7 +7,6 @@ CONFIG_ARDUINO_EVENT_RUN_CORE1=y CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 CONFIG_ARDUINO_UDP_RUN_CORE1=y CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -CONFIG_DISABLE_HAL_LOCKS=y CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y @@ -15,4 +14,4 @@ CONFIG_ARDUHAL_PARTITION_SCHEME="default" CONFIG_AUTOCONNECT_WIFI=y CONFIG_ARDUINO_SELECTIVE_WiFi=y CONFIG_MBEDTLS_PSK_MODES=y -CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y \ No newline at end of file +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y diff --git a/examples/espidf-arduino-wifiscan/platformio.ini b/examples/espidf-arduino-wifiscan/platformio.ini index 32d44b6d9..79e7284f6 100644 --- a/examples/espidf-arduino-wifiscan/platformio.ini +++ b/examples/espidf-arduino-wifiscan/platformio.ini @@ -11,9 +11,6 @@ platform = espressif32 framework = arduino, espidf monitor_speed = 115200 -platform_packages = - ; use a special branch - framework-arduinoespressif32 @ https://github.com/marcovannoord/arduino-esp32.git#idf-release/v4.0 [env:esp32dev] board = esp32dev diff --git a/examples/espidf-arduino-wifiscan/sdkconfig.defaults b/examples/espidf-arduino-wifiscan/sdkconfig.defaults index bc79532a0..cf124f4c4 100644 --- a/examples/espidf-arduino-wifiscan/sdkconfig.defaults +++ b/examples/espidf-arduino-wifiscan/sdkconfig.defaults @@ -7,7 +7,6 @@ CONFIG_ARDUINO_EVENT_RUN_CORE1=y CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 CONFIG_ARDUINO_UDP_RUN_CORE1=y CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -CONFIG_DISABLE_HAL_LOCKS=y CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y diff --git a/examples/espidf-blink/platformio.ini b/examples/espidf-blink/platformio.ini index 8cdfb1506..bb18e7640 100644 --- a/examples/espidf-blink/platformio.ini +++ b/examples/espidf-blink/platformio.ini @@ -16,3 +16,20 @@ build_flags = ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led -D CONFIG_BLINK_GPIO=2 +[env:esp32-s2] +platform = espressif32 +framework = espidf +board = esp32-s2-saola-1 +monitor_speed = 115200 +build_flags = + ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led + -D CONFIG_BLINK_GPIO=2 + +[env:esp32-s3] +platform = espressif32 +framework = espidf +board = esp32-s3-devkitc-1 +monitor_speed = 115200 +build_flags = + ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led + -D CONFIG_BLINK_GPIO=2 diff --git a/examples/espidf-coap-server/src/certs/coap_ca.pem b/examples/espidf-coap-server/src/certs/coap_ca.pem index 1bdf23d94..07900ec47 100644 --- a/examples/espidf-coap-server/src/certs/coap_ca.pem +++ b/examples/espidf-coap-server/src/certs/coap_ca.pem @@ -1,23 +1,27 @@ -----BEGIN CERTIFICATE----- -MIID3DCCA0WgAwIBAgIJAMnlgL1czsmjMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD -VQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hlcmUxFTAT -BgNVBAoMDEV4YW1wbGUgSW5jLjEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBs -ZS5jb20xJjAkBgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X -DTE3MDYwNzA4MDY0OVoXDTI3MDYwNTA4MDY0OVowgZMxCzAJBgNVBAYTAkZSMQ8w -DQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMGA1UECgwMRXhh -bXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTEmMCQG -A1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBALpWR23fn/TmHxsXsHdrydzPSd17fZkc71WsaicgQR66 -1tIVYb22UWGfj9KPM8THMsV74ew4ZkaQ39qvU0iuQIRrKARFHFok+vbaecgWMeWe -vGIqdnmyB9gJYaFOKgtSkfXsu2ddsqdvLYwcDbczrq8X9yEXpN6mnxXeCcPG4F0p -AgMBAAGjggE0MIIBMDAdBgNVHQ4EFgQUgigpdAUpONoDq0pQ3yfxrslCSpcwgcgG -A1UdIwSBwDCBvYAUgigpdAUpONoDq0pQ3yfxrslCSpehgZmkgZYwgZMxCzAJBgNV -BAYTAkZSMQ8wDQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMG -A1UECgwMRXhhbXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxl -LmNvbTEmMCQGA1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCCQDJ -5YC9XM7JozAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly93 -d3cuZXhhbXBsZS5jb20vZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcNAQELBQADgYEA -euxOBPInSJRKAIseMxPmAabtAqKNslZSmpG4He3lkKt+HM3jfznUt3psmD7j1hFW -S4l7KXzzajvaGYybDq5N9MqrDjhGn3VXZqOLMUNDL7OQq96TzgqsTBT1dmVSbNlt -PQgiAeKAk3tmH4lRRi9MTBSyJ6I92JYcS5H6Bs4ZwCc= +MIICDzCCAbSgAwIBAgIIAbOUoVFDz/QwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMzWhcNMjExMTExMTAzMDMzWjBaMQ4wDAYDVQQDEwVjZi1jYTEUMBIGA1UECxML +Q2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZPdHRh +d2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7/3EXOZn +GZXNEIj7LuQAMZ8lfRYSCnpME1TBjKjZPtVeztLtGWgkkLvIX11pAJcBh51cpi7Z +fQtGpVE9CLOh6aNgMF4wHQYDVR0OBBYEFEvf57UcJhYYkx14twkeitd691fVMAsG +A1UdDwQEAwIBBjAPBgNVHRMECDAGAQH/AgEBMB8GA1UdIwQYMBaAFAsi3KbVERiK +JzFCfC/GVrYksGzEMAwGCCqGSM49BAMCBQADRwAwRAIgc5nVF/5Pip0XB17IZXqi +V84FXanWdn9Z0SiPdpOgvZMCIH13vL9tkCCjPN3tg3TYRY/bzyGohFGBcTrrEtUr +rVIm +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIB4DCCAYWgAwIBAgIIQR8ro8AQ02AwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMyWhcNMjExMTExMTAzMDMyWjBcMRAwDgYDVQQDEwdjZi1yb290MRQwEgYDVQQL +EwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBzZSBJb1QxDzANBgNVBAcTBk90 +dGF3YTELMAkGA1UEBhMCQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATZ1BRM +T1//Fzh9sneRZNwS4kgCxN1PvgwT271qCpYqyxnjLEa38AP1IAanhpiD/OkVc0Zd +7NgDPCw7n94EULMyoy8wLTAdBgNVHQ4EFgQUCyLcptURGIonMUJ8L8ZWtiSwbMQw +DAYDVR0TBAUwAwEB/zAMBggqhkjOPQQDAgUAA0cAMEQCIAdLEgcUWdpAl9jwdJiz +/cHW7/CBIWEvqiQfzE+XLyLOAiAvuxSdOtSDjh2aC5qEjUCH8CSKCxWB74j23tmp +aqPH4A== -----END CERTIFICATE----- diff --git a/examples/espidf-coap-server/src/certs/coap_server.crt b/examples/espidf-coap-server/src/certs/coap_server.crt index 8f1dfcda6..6522f4e4c 100644 --- a/examples/espidf-coap-server/src/certs/coap_server.crt +++ b/examples/espidf-coap-server/src/certs/coap_server.crt @@ -1,70 +1,13 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 47 (0x2f) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FR, ST=Radius, L=Somewhere, O=Example Inc./emailAddress=admin@example.com, CN=Example Certificate Authority - Validity - Not Before: Jun 7 08:06:49 2017 GMT - Not After : Jun 5 08:06:49 2027 GMT - Subject: C=FR, ST=Radius, O=Example Inc., CN=Example Server Certificate/emailAddress=admin@example.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:c9:d8:e2:e0:75:91:83:87:d8:c8:80:c6:20:4d: - e9:14:24:30:98:33:53:fa:56:0e:ec:9a:43:7f:87: - a9:22:94:26:06:c7:ac:b5:d9:ec:55:06:81:b7:0d: - c9:24:51:49:fa:47:fb:4b:4e:fc:ed:75:8a:e1:28: - 32:bc:c5:e0:4c:45:c4:58:60:15:67:1e:6b:40:19: - 3f:f0:ab:92:61:92:2d:71:10:2e:f2:eb:bc:81:2f: - 5a:3b:74:ca:5f:fd:e0:ee:d1:d9:07:6a:6c:20:c0: - 07:88:b4:8b:0f:ad:1e:c9:4f:7c:11:98:37:89:15: - de:24:b1:11:1a:7c:97:4a:cf:f3:c8:cb:79:9e:9c: - c3:71:da:a6:94:97:f5:95:fd:61:06:44:e2:3f:12: - 43:0b:1d:33:48:91:d2:ce:4f:97:a1:ed:6a:30:c7: - 5d:98:b5:6e:0a:b7:4f:d9:03:ec:80:76:09:b0:40: - a1:a1:af:ab:2a:59:c4:0f:56:22:bc:be:14:be:18: - df:10:7d:5d:22:bf:e5:04:77:7a:75:6b:3e:eb:6d: - 20:a1:a7:60:d4:f1:87:9d:9f:60:b9:d3:db:2c:25: - f4:91:4a:f1:d2:40:e5:a1:10:88:a0:41:5a:98:40: - ca:15:d7:e3:e6:3e:c0:6a:d5:46:b2:b4:90:b4:ae: - 3b:e3 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Extended Key Usage: - TLS Web Server Authentication - X509v3 CRL Distribution Points: - - Full Name: - URI:http://www.example.com/example_ca.crl - - Signature Algorithm: sha1WithRSAEncryption - a4:25:21:51:0b:22:6c:63:8d:a9:c1:4f:04:33:69:79:34:f0: - 36:dd:8f:6a:27:5f:07:a2:1d:ef:8b:f0:96:e6:e7:a3:b8:3b: - 85:5e:3f:26:43:8a:8e:95:58:9c:a6:db:9c:51:bf:ea:53:16: - 3e:c1:a8:11:1a:c6:cf:0e:a1:17:18:64:d2:05:f1:c0:9c:a6: - 2b:16:c4:29:54:03:d2:17:bd:15:74:d6:ad:8a:8f:2d:cc:27: - 3b:88:88:f2:ea:d0:a2:cb:e9:42:57:df:26:9f:8a:a2:02:2f: - 35:b6:19:1d:26:43:44:af:12:4b:bc:b9:84:50:02:fd:1d:fa: - 50:e8 -----BEGIN CERTIFICATE----- -MIIDWTCCAsKgAwIBAgIBLzANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UEBhMCRlIx -DzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRUwEwYDVQQKDAxF -eGFtcGxlIEluYy4xIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMSYw -JAYDVQQDDB1FeGFtcGxlIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNzA2MDcw -ODA2NDlaFw0yNzA2MDUwODA2NDlaMHwxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZS -YWRpdXMxFTATBgNVBAoMDEV4YW1wbGUgSW5jLjEjMCEGA1UEAwwaRXhhbXBsZSBT -ZXJ2ZXIgQ2VydGlmaWNhdGUxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUu -Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydji4HWRg4fYyIDG -IE3pFCQwmDNT+lYO7JpDf4epIpQmBsestdnsVQaBtw3JJFFJ+kf7S0787XWK4Sgy -vMXgTEXEWGAVZx5rQBk/8KuSYZItcRAu8uu8gS9aO3TKX/3g7tHZB2psIMAHiLSL -D60eyU98EZg3iRXeJLERGnyXSs/zyMt5npzDcdqmlJf1lf1hBkTiPxJDCx0zSJHS -zk+Xoe1qMMddmLVuCrdP2QPsgHYJsEChoa+rKlnED1YivL4UvhjfEH1dIr/lBHd6 -dWs+620goadg1PGHnZ9gudPbLCX0kUrx0kDloRCIoEFamEDKFdfj5j7AatVGsrSQ -tK474wIDAQABo08wTTATBgNVHSUEDDAKBggrBgEFBQcDATA2BgNVHR8ELzAtMCug -KaAnhiVodHRwOi8vd3d3LmV4YW1wbGUuY29tL2V4YW1wbGVfY2EuY3JsMA0GCSqG -SIb3DQEBBQUAA4GBAKQlIVELImxjjanBTwQzaXk08Dbdj2onXweiHe+L8Jbm56O4 -O4VePyZDio6VWJym25xRv+pTFj7BqBEaxs8OoRcYZNIF8cCcpisWxClUA9IXvRV0 -1q2Kjy3MJzuIiPLq0KLL6UJX3yafiqICLzW2GR0mQ0SvEku8uYRQAv0d+lDo +MIICAzCCAaagAwIBAgIJANqCHDjOKHh+MAwGCCqGSM49BAMCBQAwWjEOMAwGA1UE +AxMFY2YtY2ExFDASBgNVBAsTC0NhbGlmb3JuaXVtMRQwEgYDVQQKEwtFY2xpcHNl +IElvVDEPMA0GA1UEBxMGT3R0YXdhMQswCQYDVQQGEwJDQTAeFw0yMDExMTExMDMw +MzRaFw0yMTExMTExMDMwMzRaMF4xEjAQBgNVBAMTCWNmLXNlcnZlcjEUMBIGA1UE +CxMLQ2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZP +dHRhd2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+obM +gHmMB7zS4KArciXPD7CrvgEYqlnAf7NOTdb54RbTr4qEpPL+OJ6Pg8VhrF4hGEne +T6Aa4qqpmTkxmfT0vqNPME0wHQYDVR0OBBYEFE4XpfFad+F3+RcwI+s1cmJbTZWG +MAsGA1UdDwQEAwIHgDAfBgNVHSMEGDAWgBRL3+e1HCYWGJMdeLcJHorXevdX1TAM +BggqhkjOPQQDAgUAA0kAMEYCIQCEo+O5zqYKdwi/ElB4wfNVIf76P1OhIXAT5CHc +3ebBPQIhAN6UhCgQ0av6kf7INCazV3KmN7HmPXARaY4YKWsRwsg+ -----END CERTIFICATE----- diff --git a/examples/espidf-coap-server/src/certs/coap_server.key b/examples/espidf-coap-server/src/certs/coap_server.key index 9b3433273..362851524 100644 --- a/examples/espidf-coap-server/src/certs/coap_server.key +++ b/examples/espidf-coap-server/src/certs/coap_server.key @@ -1,27 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAydji4HWRg4fYyIDGIE3pFCQwmDNT+lYO7JpDf4epIpQmBses -tdnsVQaBtw3JJFFJ+kf7S0787XWK4SgyvMXgTEXEWGAVZx5rQBk/8KuSYZItcRAu -8uu8gS9aO3TKX/3g7tHZB2psIMAHiLSLD60eyU98EZg3iRXeJLERGnyXSs/zyMt5 -npzDcdqmlJf1lf1hBkTiPxJDCx0zSJHSzk+Xoe1qMMddmLVuCrdP2QPsgHYJsECh -oa+rKlnED1YivL4UvhjfEH1dIr/lBHd6dWs+620goadg1PGHnZ9gudPbLCX0kUrx -0kDloRCIoEFamEDKFdfj5j7AatVGsrSQtK474wIDAQABAoIBAQC2kGDEPBJdMSW2 -VCLfXRiPixwYzXQLXIMrJWwfkQg9qlmqkDd6U50aWkRA2UswegW7RhfYSZ0i+cmf -VMhvTVpOIlwwwtcY6b5/v1bBy60eaySGuuh79xQMlFO8qynQIMStvUfbGTqrdIRb -9VBB4YeS9T12fILejtTZwv2BQ2dj1Y1SCay6Ri85UzJqSClRKgHISybvVdLNjPvP -0TRFBr57zyjL6WE8teKiKchzQko2u86No5uBCdKGsrAkrsdcR0YqlM/pZxd3VKNm -+eny0k+dZZlvcPxzkzP4hEp9+Rw5rP9/s3s/cCwvuuC5JO32ATBWKCbTvPv/XPDb -MdSJtOshAoGBAPzk0eswkcbFYtpnpBNmBAr1dtAdW1lfjUI2ucMMwt7Wns0P/tt+ -gq6Hi1wTaGP0l/dIECgeHwjtWj31ZJjQtFJ1y/kafxo4o9cA8vCydpdvSZaldAfg -sbLlDTDYzEpelaDIbNQBBXFoC5U9JlBhBsIFCL5Z8ZuIeFPsb7t5wwuHAoGBAMxT -jyWfNm1uNxp1xgCnrRsLPQPVnURrSFAqcHrECqRu3F7sozTN7q/cZViemxPvVDGQ -p9c+9bHwaYvW4trO5qDHJ++gGwm5L52bMAY1VUfeTt67fqrey43XpdmzcTX1V9Uj -QWawPUCSDzFjL1MjfCIejtyYf5ash53vj+T8r/vFAoGAA/OPVB1uKazr3n3AEo2F -gqZTNO1AgCT+EArK3EFWyiSQVqPpV4SihheYFdg3yVgJB9QYbIgL9BfBUTaEW97m -8mLkzP+c/Mvlw3ZAVYJ0V+llPPVY2saoACOUES9SAdd4fwqiqK1baGo3xB0wfBEI -CgAKIu9E1ylKuAT5ufQtGAECgYEAtP/kU5h5N3El4QupTdU7VDSdZTMqsHw0v8cI -gsf9AXKvRmtrnBA8u46KPHmruHoO5CVXeSZtsaXdaaH+rYQQ6yXg67WxnehtFLlv -TmCaXiLBTS9cYvMf8FOyuGnsBLeEietEOTov2G5KhR5uwsAxa2wUc7endor5S9/2 -YQuyvV0CgYALbiFpILd5l1ip65eE6JdA3hfttUbV2j2NSW12ej69vqbeOfaSgNse -uYCcXFsBbQPhNPwA+4d1oCe8SyXZg1f7gE812z2Tyr/3vdVnNZlitoxhsHmGiyS7 -gZdaTYCb78l9z0EBdaCVvA16owEle4SR6f9eCwzSI0WPOUra+x/hrA== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCLBQT66xp2w4+1K+Ai +/TXEC8tQZBxl9brFyK4F7AQNGw== +-----END PRIVATE KEY----- diff --git a/examples/espidf-coap-server/src/coap_server_example_main.c b/examples/espidf-coap-server/src/coap_server_example_main.c index 58a698d8a..ed96cc6e2 100644 --- a/examples/espidf-coap-server/src/coap_server_example_main.c +++ b/examples/espidf-coap-server/src/coap_server_example_main.c @@ -29,15 +29,10 @@ #include "protocol_examples_common.h" -#if 1 -/* Needed until coap_dtls.h becomes a part of libcoap proper */ -#include "libcoap.h" -#include "coap_dtls.h" -#endif -#include "coap.h" +#include "coap3/coap.h" /* The examples use simple Pre-Shared-Key configuration that you can set via - 'make menuconfig'. + 'idf.py menuconfig'. If you'd rather not, just change the below entries to strings with the config you want - ie #define EXAMPLE_COAP_PSK_KEY "some-agreed-preshared-key" @@ -49,7 +44,7 @@ #define EXAMPLE_COAP_PSK_KEY CONFIG_EXAMPLE_COAP_PSK_KEY /* The examples use CoAP Logging Level that - you can set via 'make menuconfig'. + you can set via 'idf.py menuconfig'. If you'd rather not, just change the below entry to a value that is between 0 and 7 with @@ -67,8 +62,10 @@ static int espressif_data_len = 0; Server cert, taken from coap_server.crt Server key, taken from coap_server.key - The PEM, CRT and KEY file are examples taken from the wpa2 enterprise - example. + The PEM, CRT and KEY file are examples taken from + https://github.com/eclipse/californium/tree/master/demo-certs/src/main/resources + as the Certificate test (by default) for the coap_client is against the + californium server. To embed it in the app binary, the PEM, CRT and KEY file is named in the component.mk COMPONENT_EMBED_TXTFILES variable. @@ -87,39 +84,42 @@ extern uint8_t server_key_end[] asm("_binary_coap_server_key_end"); * The resource handler */ static void -hnd_espressif_get(coap_context_t *ctx, coap_resource_t *resource, +hnd_espressif_get(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, coap_binary_t *token, - coap_string_t *query, coap_pdu_t *response) + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response) { - coap_add_data_blocked_response(resource, session, request, response, token, - COAP_MEDIATYPE_TEXT_PLAIN, 0, - (size_t)espressif_data_len, - (const u_char *)espressif_data); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, 60, 0, + (size_t)espressif_data_len, + (const u_char *)espressif_data, + NULL, NULL); } static void -hnd_espressif_put(coap_context_t *ctx, - coap_resource_t *resource, +hnd_espressif_put(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, - coap_binary_t *token, - coap_string_t *query, + const coap_pdu_t *request, + const coap_string_t *query, coap_pdu_t *response) { size_t size; - unsigned char *data; + size_t offset; + size_t total; + const unsigned char *data; coap_resource_notify_observers(resource, NULL); if (strcmp (espressif_data, INITIAL_DATA) == 0) { - response->code = COAP_RESPONSE_CODE(201); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); } else { - response->code = COAP_RESPONSE_CODE(204); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); } - /* coap_get_data() sets size to 0 on error */ - (void)coap_get_data(request, &size, &data); + /* coap_get_data_large() sets size to 0 on error */ + (void)coap_get_data_large(request, &size, &data, &offset, &total); if (size == 0) { /* re-init */ snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); @@ -131,18 +131,16 @@ hnd_espressif_put(coap_context_t *ctx, } static void -hnd_espressif_delete(coap_context_t *ctx, - coap_resource_t *resource, +hnd_espressif_delete(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, - coap_binary_t *token, - coap_string_t *query, + const coap_pdu_t *request, + const coap_string_t *query, coap_pdu_t *response) { coap_resource_notify_observers(resource, NULL); snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); espressif_data_len = strlen(espressif_data); - response->code = COAP_RESPONSE_CODE(202); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); } #ifdef CONFIG_COAP_MBEDTLS_PKI @@ -163,6 +161,18 @@ verify_cn_callback(const char *cn, } #endif /* CONFIG_COAP_MBEDTLS_PKI */ +static void +coap_log_handler (coap_log_t level, const char *message) +{ + uint32_t esp_level = ESP_LOG_INFO; + char *cp = strchr(message, '\n'); + + if (cp) + ESP_LOG_LEVEL(esp_level, TAG, "%.*s", (int)(cp-message), message); + else + ESP_LOG_LEVEL(esp_level, TAG, "%s", message); +} + static void coap_example_server(void *p) { coap_context_t *ctx = NULL; @@ -171,6 +181,7 @@ static void coap_example_server(void *p) snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); espressif_data_len = strlen(espressif_data); + coap_set_log_handler(coap_log_handler); coap_set_log_level(EXAMPLE_COAP_LOG_DEFAULT_LEVEL); while (1) { @@ -179,15 +190,16 @@ static void coap_example_server(void *p) /* Prepare the CoAP server socket */ coap_address_init(&serv_addr); - serv_addr.addr.sin.sin_family = AF_INET; - serv_addr.addr.sin.sin_addr.s_addr = INADDR_ANY; - serv_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT); + serv_addr.addr.sin6.sin6_family = AF_INET6; + serv_addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); ctx = coap_new_context(NULL); if (!ctx) { ESP_LOGE(TAG, "coap_new_context() failed"); continue; } + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY); #ifdef CONFIG_COAP_MBEDTLS_PSK /* Need PSK setup before we set up endpoints */ coap_context_set_psk(ctx, "CoAP", @@ -196,6 +208,7 @@ static void coap_example_server(void *p) #endif /* CONFIG_COAP_MBEDTLS_PSK */ #ifdef CONFIG_COAP_MBEDTLS_PKI + /* Need PKI setup before we set up endpoints */ unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start; unsigned int server_crt_bytes = server_crt_end - server_crt_start; unsigned int server_key_bytes = server_key_end - server_key_start; @@ -214,7 +227,7 @@ static void coap_example_server(void *p) * define what checking actually takes place. */ dtls_pki.verify_peer_cert = 1; - dtls_pki.require_peer_cert = 1; + dtls_pki.check_common_ca = 1; dtls_pki.allow_self_signed = 1; dtls_pki.allow_expired_certs = 1; dtls_pki.cert_chain_validation = 1; @@ -256,7 +269,7 @@ static void coap_example_server(void *p) /* This is not critical as unencrypted support is still available */ ESP_LOGI(TAG, "MbedTLS (D)TLS Server Mode not configured"); #else /* CONFIG_MBEDTLS_TLS_SERVER */ - serv_addr.addr.sin.sin_port = htons(COAPS_DEFAULT_PORT); + serv_addr.addr.sin6.sin6_port = htons(COAPS_DEFAULT_PORT); ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_DTLS); if (!ep) { ESP_LOGE(TAG, "dtls: coap_new_endpoint() failed"); @@ -267,7 +280,7 @@ static void coap_example_server(void *p) /* This is not critical as unencrypted support is still available */ ESP_LOGI(TAG, "MbedTLS (D)TLS Server Mode not configured"); } -#endif /* CONFIG_COAP_MBEDTLS_PSK CONFIG_COAP_MBEDTLS_PKI */ +#endif /* CONFIG_COAP_MBEDTLS_PSK || CONFIG_COAP_MBEDTLS_PKI */ resource = coap_resource_init(coap_make_str_const("Espressif"), 0); if (!resource) { ESP_LOGE(TAG, "coap_resource_init() failed"); @@ -280,10 +293,26 @@ static void coap_example_server(void *p) coap_resource_set_get_observable(resource, 1); coap_add_resource(ctx, resource); +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV4) || defined(CONFIG_EXAMPLE_COAP_MCAST_IPV6) + esp_netif_t *netif = NULL; + for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) { + char buf[8]; + netif = esp_netif_next(netif); + esp_netif_get_netif_impl_name(netif, buf); +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV4) + coap_join_mcast_group_intf(ctx, CONFIG_EXAMPLE_COAP_MULTICAST_IPV4_ADDR, buf); +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV4 */ +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV6) + /* When adding IPV6 esp-idf requires ifname param to be filled in */ + coap_join_mcast_group_intf(ctx, CONFIG_EXAMPLE_COAP_MULTICAST_IPV6_ADDR, buf); +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV6 */ + } +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV4 || CONFIG_EXAMPLE_COAP_MCAST_IPV6 */ + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; while (1) { - int result = coap_run_once(ctx, wait_ms); + int result = coap_io_process(ctx, wait_ms); if (result < 0) { break; } else if (result && (unsigned)result < wait_ms) { diff --git a/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c b/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c index 1d82721db..2da369c2c 100644 --- a/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c +++ b/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c @@ -39,7 +39,7 @@ void app_main(void) { .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, // USB version. 0x0200 means version 2.0 .bDeviceClass = TUSB_CLASS_UNSPECIFIED, - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0x303A, .idProduct = 0x3000, diff --git a/examples/pumbaa-blink/.skiptest b/examples/pumbaa-blink/.skiptest deleted file mode 100644 index 05e3ca046..000000000 --- a/examples/pumbaa-blink/.skiptest +++ /dev/null @@ -1 +0,0 @@ -.skiptest diff --git a/examples/pumbaa-blink/.travis.yml b/examples/pumbaa-blink/.travis.yml deleted file mode 100755 index 7c486f183..000000000 --- a/examples/pumbaa-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/pumbaa-blink/README.md b/examples/pumbaa-blink/README.md deleted file mode 100755 index 1de389c37..000000000 --- a/examples/pumbaa-blink/README.md +++ /dev/null @@ -1,18 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/pumbaa-blink - -# Process example project -$ pio run - -# Upload firmware -$ pio run --target upload -``` diff --git a/examples/pumbaa-blink/src/main.c b/examples/pumbaa-blink/src/main.c deleted file mode 100755 index c43d5310e..000000000 --- a/examples/pumbaa-blink/src/main.c +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @file main.c - * - * @section License - * Copyright (C) 2015-2016, Erik Moqvist - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * This file is part of the Pumbaa project. - */ - -/* - * This file is required by PlatformIO, but is unused in Pumbaa. - */ diff --git a/examples/pumbaa-blink/src/main.py b/examples/pumbaa-blink/src/main.py deleted file mode 100755 index fde1e231c..000000000 --- a/examples/pumbaa-blink/src/main.py +++ /dev/null @@ -1,40 +0,0 @@ -# -# @section License -# -# The MIT License (MIT) -# -# Copyright (c) 2016, Erik Moqvist -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, copy, -# modify, merge, publish, distribute, sublicense, and/or sell copies -# of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# This file is part of the Pumbaa project. -# - - -import time -import board -from drivers import Pin - -LED = Pin(board.PIN_LED, Pin.OUTPUT) - -while True: - LED.toggle() - time.sleep(0.5) diff --git a/examples/simba-blink/.travis.yml b/examples/simba-blink/.travis.yml deleted file mode 100755 index 7c486f183..000000000 --- a/examples/simba-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/simba-blink/README.md b/examples/simba-blink/README.md deleted file mode 100755 index 15437339b..000000000 --- a/examples/simba-blink/README.md +++ /dev/null @@ -1,18 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/simba-blink - -# Process example project -$ pio run - -# Upload firmware -$ pio run --target upload -``` \ No newline at end of file diff --git a/examples/simba-blink/src/main.c b/examples/simba-blink/src/main.c deleted file mode 100755 index 404ec637b..000000000 --- a/examples/simba-blink/src/main.c +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file main.c - * @version 4.1.0 - * - * @section License - * Copyright (C) 2015-2016, Erik Moqvist - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * This file is part of the Simba project. - */ - -#include "simba.h" - -int main() -{ - struct pin_driver_t led; - - /* Start the system. */ - sys_start(); - - /* Initialize the LED pin as output and set its value to 1. */ - pin_init(&led, &pin_led_dev, PIN_OUTPUT); - pin_write(&led, 1); - - while (1) { - /* Wait half a second. */ - thrd_sleep_us(500000); - - /* Toggle the LED on/off. */ - pin_toggle(&led); - } - - return (0); -} diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index 6a90a5909..81c69c1ee 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -32,7 +32,7 @@ class Esp32ExceptionDecoder(DeviceMonitorFilter): def __call__(self): self.buffer = "" self.backtrace_re = re.compile( - r"^Backtrace: ?((0x[0-9a-fA-F]+:0x[0-9a-fA-F]+ ?)+)\s*" + r"^Backtrace: ?((0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8} ?)+)\s*" ) self.firmware_path = None diff --git a/platform.json b/platform.json index c09cb977c..ef4980de9 100644 --- a/platform.json +++ b/platform.json @@ -9,16 +9,16 @@ "Wi-Fi", "Bluetooth", "Xtensa", - "LX6" + "RISC-V" ], "engines": { "platformio": "^5" }, "repository": { "type": "git", - "url": "https://github.com/platformio/platform-espressif32.git" + "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "3.4.0", + "version": "2.0.3", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -30,106 +30,97 @@ "description": "ESP-IDF is the official development framework for the ESP32 and ESP32-S Series SoCs.", "homepage": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32/", "title": "Espressif IoT Development Framework" - }, - "simba": { - "package": "framework-simba", - "script": "builder/frameworks/simba.py", - "description": "Simba is an RTOS and build framework with aims to make embedded programming easy and portable", - "homepage": "http://simba-os.readthedocs.org", - "title": "Simba" - }, - "pumbaa": { - "package": "framework-pumbaa", - "script": "builder/frameworks/pumbaa.py", - "description": "Pumbaa is Python on top of Simba. The implementation is a port of MicroPython, designed for embedded devices with limited amount of RAM and code memory", - "homepage": "http://pumbaa.readthedocs.org/", - "title": "Pumbaa" } }, "packages": { - "toolchain-xtensa32": { - "type": "toolchain", - "owner": "platformio", - "version": "~2.50200.0", - "optionalVersions": ["~2.80400.0"] + "framework-arduinoespressif32": { + "type": "framework", + "optional": true, + "owner": "tasmota", + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/803/framework-arduinoespressif32-v4.4_dev-40d126bfd1.tar.gz" }, - "toolchain-xtensa32s2": { - "type": "toolchain", + "framework-espidf": { + "type": "framework", "optional": true, "owner": "platformio", - "version": "~1.80400.0" + "version": "https://github.com/tasmota/esp-idf/releases/download/v.4.4.1/esp-idf-v4.4.1.zip" }, - "toolchain-esp32ulp": { + "toolchain-xtensa-esp32": { "type": "toolchain", "optional": true, - "owner": "platformio", - "version": "~1.22851.0" + "owner": "espressif", + "version": "8.4.0+2021r2-patch3" }, - "toolchain-esp32s2ulp": { + "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, - "owner": "platformio", - "version": "~1.22851.0" + "owner": "espressif", + "version": "8.4.0+2021r2-patch3" }, - "toolchain-riscv-esp": { + "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, - "owner": "platformio", - "version": "~1.80400.0" + "owner": "espressif", + "version": "8.4.0+2021r2-patch3" }, - "toolchain-xtensa-esp32": { + "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r1" + "version": "8.4.0+2021r2-patch3" }, - "toolchain-xtensa-esp32s2": { + "toolchain-xtensa-esp32-arm": { "type": "toolchain", "optional": true, - "owner": "espressif", - "version": "8.4.0+2021r1" + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32.tar.gz" }, - "toolchain-riscv32-esp": { + "toolchain-xtensa-esp32s2-arm": { "type": "toolchain", "optional": true, - "owner": "espressif", - "version": "8.4.0+2021r1" + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32s2.tar.gz" }, - "framework-arduinoespressif32": { - "type": "framework", + "toolchain-xtensa-esp32s3-arm": { + "type": "toolchain", "optional": true, - "owner": "platformio", - "version": "~3.10006.0" + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32s3.tar.gz" }, - "framework-arduino-mbcwb": { - "type": "framework", + "toolchain-riscv32-esp-arm": { + "type": "toolchain", "optional": true, - "owner": "meteca", - "version": ">=2.1.1" + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-riscv32-esp.tar.gz" }, - "framework-espidf": { - "type": "framework", + "tool-openocd-esp32-arm": { + "type": "debugger", + "optional": true, + "owner": "tasmota", + "version": "https://github.com/Jason2866/openocd-esp32/releases/download/v0.11.0-esp32-20220404/openocd-esp32-macos-arm-0.11.0-esp32-20220406.zip" + }, + "toolchain-esp32ulp": { + "type": "toolchain", "optional": true, "owner": "platformio", - "version": "~3.40301.0", - "optionalVersions": ["~3.40001.0"] + "version": "~1.22851.0" }, - "framework-simba": { - "type": "framework", + "toolchain-esp32s2ulp": { + "type": "toolchain", "optional": true, "owner": "platformio", - "version": ">=12.2.0" + "version": "~1.22851.0" }, - "framework-pumbaa": { + "framework-arduino-mbcwb": { "type": "framework", "optional": true, - "owner": "platformio", - "version": ">=2.3.0" + "owner": "meteca", + "version": ">=2.1.1" }, "tool-esptoolpy": { "type": "uploader", - "owner": "platformio", - "version": "~1.30100.0" + "owner": "tasmota", + "version": "https://github.com/tasmota/esptool/releases/download/v3.3/esptool-3.3.zip" }, "tool-mbctool": { "optional": true, @@ -140,14 +131,24 @@ "type": "debugger", "optional": true, "owner": "platformio", - "version": "~2.1000.0" + "version": "~2.1100.0" }, "tool-mkspiffs": { "type": "uploader", - "optional": true, "owner": "platformio", "version": "~2.230.0" }, + "tool-mklittlefs": { + "type": "uploader", + "owner": "platformio", + "version": "~1.203.0" + }, + "tool-mkfatfs": { + "type": "uploader", + "optional": true, + "owner": "platformio", + "version": "~2.0.0" + }, "tool-cmake": { "optional": true, "owner": "platformio", diff --git a/platform.py b/platform.py index f620980cd..bad35d328 100644 --- a/platform.py +++ b/platform.py @@ -14,6 +14,11 @@ import copy import os +import urllib +import sys +import json +import re +import requests from platformio import fs from platformio.managers.platform import PlatformBase @@ -29,72 +34,120 @@ def configure_default_packages(self, variables, targets): mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32")) frameworks = variables.get("pioframework", []) - # Legacy toolchain names are default value. This logic is temporary as the - # platform is gradually being switched to the toolchain packages from the - # Espressif organization. - - xtensa32_toolchain = "toolchain-xtensa32" - xtensa32s2_toolchain = "toolchain-xtensa32s2" - riscv_toolchain = "toolchain-riscv-esp" - if "buildfs" in targets: - self.packages["tool-mkspiffs"]["optional"] = False + filesystem = variables.get("board_build.filesystem", "spiffs") + if filesystem == "littlefs": + self.packages["tool-mklittlefs"]["optional"] = False + elif filesystem == "fatfs": + self.packages["tool-mkfatfs"]["optional"] = False + else: + self.packages["tool-mkspiffs"]["optional"] = False if variables.get("upload_protocol"): - self.packages["tool-openocd-esp32"]["optional"] = False + if "darwin" in get_systype() and "arm64" in get_systype(): + self.packages["tool-openocd-esp32-arm"]["optional"] = False + if not "arm64" in get_systype(): + self.packages["tool-openocd-esp32"]["optional"] = False if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False - if "espidf" in frameworks: - # Legacy setting for mixed IDF+Arduino projects - if "arduino" in frameworks: - self.packages[xtensa32_toolchain]["version"] = "~2.80400.0" - # Arduino component is not compatible with ESP-IDF >=4.1 - self.packages["framework-espidf"]["version"] = "~3.40001.0" - else: - xtensa32_toolchain = "toolchain-xtensa-esp32" - xtensa32s2_toolchain = "toolchain-xtensa-esp32s2" - riscv_toolchain = "toolchain-riscv32-esp" - - for p in self.packages.copy(): - # Disable old toolchains used by default - if ( - p.startswith("toolchain") - and "ulp" not in p - ): - if self.packages[p]["owner"] == "espressif": - self.packages[p]["optional"] = False - else: - del self.packages[p] + build_core = variables.get( + "board_build.core", board_config.get("build.core", "arduino") + ).lower() + + if len(frameworks) == 1 and "arduino" in frameworks and build_core == "esp32": + # In case the upstream Arduino framework is specified in the configuration + # file then we need to dynamically extract toolchain versions from the + # Arduino index file. This feature can be disabled via a special option: + if ( + variables.get( + "board_build.arduino.upstream_packages", + board_config.get("build.arduino.upstream_packages", "yes"), + ).lower() + == "yes" + ): + package_version = self.packages["framework-arduinoespressif32"][ + "version" + ] + + url_items = urllib.parse.urlparse(package_version) + # Only GitHub repositories support dynamic packages + if ( + url_items.scheme in ("http", "https") + and url_items.netloc.startswith("github") + and url_items.path.endswith(".git") + ): + try: + self.configure_upstream_arduino_packages(url_items) + except Exception as e: + sys.stderr.write( + "Error! Failed to extract upstream toolchain" + "configurations:\n%s\n" % str(e) + ) + sys.stderr.write( + "You can disable this feature via the " + "`board_build.arduino.upstream_packages = no` setting in " + "your `platformio.ini` file.\n" + ) + sys.exit(1) + + if "espidf" in frameworks: + # Common package for IDF and mixed Arduino+IDF projects for p in self.packages: if p in ("tool-cmake", "tool-ninja", "toolchain-%sulp" % mcu): self.packages[p]["optional"] = False elif p in ("tool-mconf", "tool-idf") and "windows" in get_systype(): self.packages[p]["optional"] = False - else: - # Remove the latest toolchains from PATH for frameworks except IDF + + if mcu in ("esp32", "esp32s2", "esp32s3", "esp32c3"): + # RISC-V based toolchain for ESP32C3 and ESP32Sx ULP + self.packages["toolchain-esp32ulp"]["optional"] = False + if not "arm64" in get_systype(): + if mcu == "esp32c3": + self.packages["toolchain-riscv32-esp"]["optional"] = False + if mcu == "esp32": + self.packages["toolchain-xtensa-esp32"]["optional"] = False + if mcu == "esp32s2": + self.packages["toolchain-xtensa-esp32s2"]["optional"] = False + if mcu == "esp32s3": + self.packages["toolchain-xtensa-esp32s3"]["optional"] = False + if "darwin" in get_systype() and "arm64" in get_systype(): + if mcu == "esp32c3": + self.packages["toolchain-riscv32-esp-arm"]["optional"] = False + if mcu == "esp32": + self.packages["toolchain-xtensa-esp32-arm"]["optional"] = False + if mcu == "esp32s2": + self.packages["toolchain-xtensa-esp32s2-arm"]["optional"] = False + if mcu == "esp32s3": + self.packages["toolchain-xtensa-esp32s3-arm"]["optional"] = False + + is_legacy_project = ( + build_core == "mbcwb" + ) + + if is_legacy_project: + # Remove the main toolchains from PATH for toolchain in ( "toolchain-xtensa-esp32", "toolchain-xtensa-esp32s2", + "toolchain-xtensa-esp32s3", "toolchain-riscv32-esp", ): self.packages.pop(toolchain, None) - if mcu in ("esp32s2", "esp32c3"): - self.packages.pop(xtensa32_toolchain, None) - self.packages.pop("toolchain-esp32ulp", None) - # RISC-V based toolchain for ESP32C3 and ESP32S2 ULP - self.packages[riscv_toolchain]["optional"] = False - if mcu == "esp32s2": - self.packages[xtensa32s2_toolchain]["optional"] = False + # Add legacy toolchain with specific version + self.packages["toolchain-xtensa32"] = { + "type": "toolchain", + "owner": "platformio", + "version": "~2.80400.0" + if "arduino" in frameworks and build_core != "mbcwb" + else "~2.50200.0", + } - build_core = variables.get( - "board_build.core", board_config.get("build.core", "arduino") - ).lower() - if build_core == "mbcwb": - self.packages["framework-arduinoespressif32"]["optional"] = True - self.packages["framework-arduino-mbcwb"]["optional"] = False - self.packages["tool-mbctool"]["type"] = "uploader" - self.packages["tool-mbctool"]["optional"] = False + if build_core == "mbcwb": + self.packages["framework-arduinoespressif32"]["optional"] = True + self.packages["framework-arduino-mbcwb"]["optional"] = False + self.packages["tool-mbctool"]["type"] = "uploader" + self.packages["tool-mbctool"]["optional"] = False return PlatformBase.configure_default_packages(self, variables, targets) @@ -271,3 +324,102 @@ def configure_debug_options(self, initial_debug_options, ide_data): ) debug_options["load_cmds"] = load_cmds return debug_options + + @staticmethod + def extract_toolchain_versions(tool_deps): + def _parse_version(original_version): + assert original_version + match = re.match(r"^gcc(\d+)_(\d+)_(\d+)\-esp\-(.+)$", original_version) + if not match: + raise ValueError("Bad package version `%s`" % original_version) + assert len(match.groups()) == 4 + return "%s.%s.%s+%s" % (match.groups()) + + if not tool_deps: + raise ValueError( + ("Failed to extract tool dependencies from the remote package file") + ) + + toolchain_remap = { + "xtensa-esp32-elf-gcc": "toolchain-xtensa-esp32", + "xtensa-esp32s2-elf-gcc": "toolchain-xtensa-esp32s2", + "xtensa-esp32s3-elf-gcc": "toolchain-xtensa-esp32s3", + "riscv32-esp-elf-gcc": "toolchain-riscv32-esp", + } + + result = dict() + for tool in tool_deps: + if tool["name"] in toolchain_remap: + result[toolchain_remap[tool["name"]]] = _parse_version(tool["version"]) + + return result + + @staticmethod + def parse_tool_dependencies(index_data): + for package in index_data.get("packages", []): + if package["name"] == "esp32": + for platform in package["platforms"]: + if platform["name"] == "esp32": + return platform["toolsDependencies"] + + return [] + + @staticmethod + def download_remote_package_index(url_items): + def _prepare_url_for_index_file(url_items): + tag = "master" + if url_items.fragment: + tag = url_items.fragment + return ( + "https://raw.githubusercontent.com/%s/" + "%s/package/package_esp32_index.template.json" + % (url_items.path.replace(".git", ""), tag) + ) + + index_file_url = _prepare_url_for_index_file(url_items) + r = requests.get(index_file_url, timeout=10) + if r.status_code != 200: + raise ValueError( + ( + "Failed to download package index file due to a bad response (%d) " + "from the remote `%s`" + ) + % (r.status_code, index_file_url) + ) + return r.json() + + def configure_arduino_toolchains(self, package_index): + if not package_index: + return + + toolchain_packages = self.extract_toolchain_versions( + self.parse_tool_dependencies(package_index) + ) + for toolchain_package, version in toolchain_packages.items(): + if toolchain_package not in self.packages: + self.packages[toolchain_package] = dict() + self.packages[toolchain_package]["version"] = version + self.packages[toolchain_package]["owner"] = "espressif" + self.packages[toolchain_package]["type"] = "toolchain" + + def configure_upstream_arduino_packages(self, url_items): + framework_index_file = os.path.join( + self.get_package_dir("framework-arduinoespressif32") or "", + "package", + "package_esp32_index.template.json", + ) + + # Detect whether the remote is already cloned + if os.path.isfile(framework_index_file) and os.path.isdir( + os.path.join( + self.get_package_dir("framework-arduinoespressif32") or "", ".git" + ) + ): + with open(framework_index_file) as fp: + self.configure_arduino_toolchains(json.load(fp)) + else: + print("Configuring toolchain packages from a remote source...") + self.configure_arduino_toolchains( + self.download_remote_package_index(url_items) + ) + From 4a11a4ba2f692c025de6c54afa353c16b467b5da Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 22 Apr 2022 13:24:44 +0200 Subject: [PATCH 025/666] Update platform.json --- platform.json | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 4a187d918..ef4980de9 100644 --- a/platform.json +++ b/platform.json @@ -43,10 +43,11 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v.4.4.0/esp-idf-v4.4.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v.4.4.1/esp-idf-v4.4.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", + "optional": true, "owner": "espressif", "version": "8.4.0+2021r2-patch3" }, @@ -68,6 +69,36 @@ "owner": "espressif", "version": "8.4.0+2021r2-patch3" }, + "toolchain-xtensa-esp32-arm": { + "type": "toolchain", + "optional": true, + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32.tar.gz" + }, + "toolchain-xtensa-esp32s2-arm": { + "type": "toolchain", + "optional": true, + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32s2.tar.gz" + }, + "toolchain-xtensa-esp32s3-arm": { + "type": "toolchain", + "optional": true, + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32s3.tar.gz" + }, + "toolchain-riscv32-esp-arm": { + "type": "toolchain", + "optional": true, + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-riscv32-esp.tar.gz" + }, + "tool-openocd-esp32-arm": { + "type": "debugger", + "optional": true, + "owner": "tasmota", + "version": "https://github.com/Jason2866/openocd-esp32/releases/download/v0.11.0-esp32-20220404/openocd-esp32-macos-arm-0.11.0-esp32-20220406.zip" + }, "toolchain-esp32ulp": { "type": "toolchain", "optional": true, From ad22e19a2122ba133e40970efed90580d44d62b6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 22 Apr 2022 13:25:20 +0200 Subject: [PATCH 026/666] Update platform.py --- platform.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/platform.py b/platform.py index 895a9c78a..2be5d1b41 100644 --- a/platform.py +++ b/platform.py @@ -43,7 +43,10 @@ def configure_default_packages(self, variables, targets): else: self.packages["tool-mkspiffs"]["optional"] = False if variables.get("upload_protocol"): - self.packages["tool-openocd-esp32"]["optional"] = False + if "darwin" in get_systype() and "arm64" in get_systype(): + self.packages["tool-openocd-esp32-arm"]["optional"] = False + if not "arm64" in get_systype(): + self.packages["tool-openocd-esp32"]["optional"] = False if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False @@ -95,15 +98,27 @@ def configure_default_packages(self, variables, targets): elif p in ("tool-mconf", "tool-idf") and "windows" in get_systype(): self.packages[p]["optional"] = False - if mcu in ("esp32s2", "esp32s3", "esp32c3"): - self.packages.pop("toolchain-xtensa-esp32", None) - self.packages.pop("toolchain-esp32ulp", None) - # RISC-V based toolchain for ESP32C3 and ESP32S2 ULP - self.packages["toolchain-riscv32-esp"]["optional"] = False - if mcu == "esp32s2": - self.packages["toolchain-xtensa-esp32s2"]["optional"] = False - if mcu == "esp32s3": - self.packages["toolchain-xtensa-esp32s3"]["optional"] = False + if mcu in ("esp32", "esp32s2", "esp32s3", "esp32c3"): + # RISC-V based toolchain for ESP32C3 and ESP32Sx ULP + self.packages["toolchain-esp32ulp"]["optional"] = False + if not "arm64" in get_systype(): + if mcu == "esp32c3": + self.packages["toolchain-riscv32-esp"]["optional"] = False + if mcu == "esp32": + self.packages["toolchain-xtensa-esp32"]["optional"] = False + if mcu == "esp32s2": + self.packages["toolchain-xtensa-esp32s2"]["optional"] = False + if mcu == "esp32s3": + self.packages["toolchain-xtensa-esp32s3"]["optional"] = False + if "darwin" in get_systype() and "arm64" in get_systype(): + if mcu == "esp32c3": + self.packages["toolchain-riscv32-esp-arm"]["optional"] = False + if mcu == "esp32": + self.packages["toolchain-xtensa-esp32-arm"]["optional"] = False + if mcu == "esp32s2": + self.packages["toolchain-xtensa-esp32s2-arm"]["optional"] = False + if mcu == "esp32s3": + self.packages["toolchain-xtensa-esp32s3-arm"]["optional"] = False is_legacy_project = ( build_core == "mbcwb" From 06151e2b5a7291ea34d5bbb77056817c49c8874a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 22 Apr 2022 22:08:08 +0200 Subject: [PATCH 027/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a0268dc64..82c9a2bfa 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # Tasmota Espressif 32: development platform for [PlatformIO](http://platformio.org) -[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml) +[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml)[![GitHub Releases](https://img.shields.io/github/downloads/Jason2866/platform-espressif32/total?label=downloads)](https://github.com/Jason2866/platform-espressif32/releases/latest) Espressif Systems is a privately held fabless semiconductor company. They provide wireless communications and Wi-Fi chips which are widely used in mobile devices and the Internet of Things applications. From 5e4bf93c5b7cce4b2fe13ea8f1288d19ca517634 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 24 Apr 2022 18:31:24 +0200 Subject: [PATCH 028/666] Update OCD Apple Silicon to build from 20220424 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index ef4980de9..de37b5aff 100644 --- a/platform.json +++ b/platform.json @@ -97,7 +97,7 @@ "type": "debugger", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/openocd-esp32/releases/download/v0.11.0-esp32-20220404/openocd-esp32-macos-arm-0.11.0-esp32-20220406.zip" + "version": "https://github.com/Jason2866/openocd-esp32/releases/download/v0.11.0-esp32-20220404/openocd-esp32-macos-arm64-0.11.0-esp32-20220424.zip" }, "toolchain-esp32ulp": { "type": "toolchain", From b09761c56825bebade0b7af6c9e0caf9c615395c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 26 Apr 2022 12:37:43 +0200 Subject: [PATCH 029/666] esptool.py v3.3 now in registry --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index de37b5aff..782316d4f 100644 --- a/platform.json +++ b/platform.json @@ -119,8 +119,8 @@ }, "tool-esptoolpy": { "type": "uploader", - "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v3.3/esptool-3.3.zip" + "owner": "platformio", + "version": "~1.30300.0" }, "tool-mbctool": { "optional": true, From 97148cc6950e949bfbc668c0aca9732ec0514423 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 26 Apr 2022 12:40:40 +0200 Subject: [PATCH 030/666] Add CMSIS-DAP as available debug probe --- platform.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform.py b/platform.py index 2be5d1b41..75355a721 100644 --- a/platform.py +++ b/platform.py @@ -173,6 +173,7 @@ def _add_dynamic_options(self, board): debug = board.manifest.get("debug", {}) non_debug_protocols = ["esptool", "espota", "mbctool"] supported_debug_tools = [ + "cmsis-dap", "esp-prog", "iot-bus-jtag", "jlink", @@ -202,6 +203,8 @@ def _add_dynamic_options(self, board): if link == "jlink": openocd_interface = link + elif link == "cmsis-dap": + openocd_interface = link elif link in ("esp-prog", "ftdi"): if board.id == "esp32-s2-kaluga-1": openocd_interface = "ftdi/esp32s2_kaluga_v1" From a83160868413dbca6998cc33d320deb7037941cc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 26 Apr 2022 12:46:32 +0200 Subject: [PATCH 031/666] Use GetBuildType for detecting debug mode --- builder/frameworks/espidf.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 425d02bc9..624f0f839 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -587,11 +587,8 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): def prepare_build_envs(config, default_env): build_envs = [] target_compile_groups = config.get("compileGroups") - is_build_type_debug = ( - set(["debug", "sizedata"]) & set(COMMAND_LINE_TARGETS) - or default_env.GetProjectOption("build_type") == "debug" - ) + is_build_type_debug = "debug" in env.GetBuildType() for cg in target_compile_groups: includes = [] sys_includes = [] From a226e7d695f3c6ac1fc85b84f727d4f004b1d71a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 26 Apr 2022 13:17:16 +0200 Subject: [PATCH 032/666] rm Python2 add C3 exception decoder --- monitor/filter_exception_decoder.py | 119 ++++++++++++++++------------ 1 file changed, 70 insertions(+), 49 deletions(-) diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index 81c69c1ee..154440cbe 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -17,7 +17,7 @@ import subprocess import sys -from platformio.compat import path_to_unicode, WINDOWS, PY2 +from platformio.compat import path_to_unicode, WINDOWS from platformio.project.exception import PlatformioException from platformio.project.helpers import load_project_ide_data from platformio.commands.device import DeviceMonitorFilter @@ -31,53 +31,74 @@ class Esp32ExceptionDecoder(DeviceMonitorFilter): def __call__(self): self.buffer = "" - self.backtrace_re = re.compile( - r"^Backtrace: ?((0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8} ?)+)\s*" - ) + # regex matches potential PC value (0x4xxxxxxx) + # Logic identical to https://github.com/espressif/esp-idf/blob/master/tools/idf_monitor_base/constants.py#L56 + self.pcaddr_re = re.compile(r'0x4[0-9a-f]{7}', re.IGNORECASE) self.firmware_path = None self.addr2line_path = None self.enabled = self.setup_paths() - if self.config.get("env:" + self.environment, "build_type") != "debug": - print( + return self + + def setup_paths(self): + self.project_dir = path_to_unicode(os.path.abspath(self.project_dir)) + + self.project_strip_dir = os.environ.get("esp32_exception_decoder_project_strip_dir") + self.firmware_path = os.environ.get("esp32_exception_decoder_firmware_path") + self.addr2line_path = os.environ.get("esp32_exception_decoder_addr2line_path") + + if self.project_strip_dir is None: + self.project_strip_dir = self.project_dir + + try: + if self.firmware_path is None or self.addr2line_path is None: + # Only load if necessary, as the call is expensive + data = load_project_ide_data(self.project_dir, self.environment) + + if self.firmware_path is None: + # Only do this check when the firmware path is not externally provided + if self.config.get("env:" + self.environment, "build_type") != "debug": + print( """ Please build project in debug configuration to get more details about an exception. See https://docs.platformio.org/page/projectconf/build_configurations.html """ - ) - - return self + ) + self.firmware_path = data["prog_path"] - def setup_paths(self): - self.project_dir = path_to_unicode(os.path.abspath(self.project_dir)) - try: - data = load_project_ide_data(self.project_dir, self.environment) - self.firmware_path = data["prog_path"] if not os.path.isfile(self.firmware_path): sys.stderr.write( - "%s: firmware at %s does not exist, rebuild the project?\n" + "%s: disabling, firmware at %s does not exist, rebuild the project?\n" % (self.__class__.__name__, self.firmware_path) ) return False - cc_path = data.get("cc_path", "") - if "-gcc" in cc_path: - path = cc_path.replace("-gcc", "-addr2line") - if os.path.isfile(path): - self.addr2line_path = path - return True + if self.addr2line_path is None: + cc_path = data.get("cc_path", "") + if "-gcc" in cc_path: + self.addr2line_path = cc_path.replace("-gcc", "-addr2line") + else: + sys.stderr.write( + "%s: disabling, failed to find addr2line.\n" % self.__class__.__name__ + ) + return False + + if not os.path.isfile(self.addr2line_path): + sys.stderr.write( + "%s: disabling, addr2line at %s does not exist\n" + % (self.__class__.__name__, self.addr2line_path) + ) + return False + + return True except PlatformioException as e: sys.stderr.write( "%s: disabling, exception while looking for addr2line: %s\n" % (self.__class__.__name__, e) ) return False - sys.stderr.write( - "%s: disabling, failed to find addr2line.\n" % self.__class__.__name__ - ) - return False def rx(self, text): if not self.enabled: @@ -97,36 +118,36 @@ def rx(self, text): self.buffer = "" last = idx + 1 - m = self.backtrace_re.match(line) - if m is None: - continue + # Output each trace on a separate line below ours + # Logic identical to https://github.com/espressif/esp-idf/blob/master/tools/idf_monitor_base/logger.py#L131 + for m in re.finditer(self.pcaddr_re, line): + if m is None: + continue + + trace = self.get_backtrace(m) + if len(trace) != "": + text = text[: last] + trace + text[last :] + last += len(trace) - trace = self.get_backtrace(m) - if len(trace) != "": - text = text[: idx + 1] + trace + text[idx + 1 :] - last += len(trace) return text def get_backtrace(self, match): trace = "" enc = "mbcs" if WINDOWS else "utf-8" args = [self.addr2line_path, u"-fipC", u"-e", self.firmware_path] - if PY2: - args = [a.encode(enc) for a in args] try: - for i, addr in enumerate(match.group(1).split()): - if PY2: - addr = addr.encode(enc) - output = ( - subprocess.check_output(args + [addr]) - .decode(enc) - .strip() - ) - output = output.replace( - "\n", "\n " - ) # newlines happen with inlined methods - output = self.strip_project_dir(output) - trace += " #%-2d %s in %s\n" % (i, addr, output) + addr = match.group() + output = ( + subprocess.check_output(args + [addr]) + .decode(enc) + .strip() + ) + output = output.replace( + "\n", "\n " + ) # newlines happen with inlined methods + output = self.strip_project_dir(output) + # Output the trace in yellow color so that it is easier to spot + trace += "\033[33m=> %s: %s\033[0m\n" % (addr, output) except subprocess.CalledProcessError as e: sys.stderr.write( "%s: failed to call %s: %s\n" @@ -136,8 +157,8 @@ def get_backtrace(self, match): def strip_project_dir(self, trace): while True: - idx = trace.find(self.project_dir) + idx = trace.find(self.project_strip_dir) if idx == -1: break - trace = trace[:idx] + trace[idx + len(self.project_dir) + 1 :] + trace = trace[:idx] + trace[idx + len(self.project_strip_dir) + 1 :] return trace From 2e9045e914a541a226b285bf67ac228d731c817e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 30 Apr 2022 13:54:00 +0200 Subject: [PATCH 033/666] remove fix firmware address 0x10000 --- builder/main.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/builder/main.py b/builder/main.py index cbfa1c7ec..fb8ffd665 100644 --- a/builder/main.py +++ b/builder/main.py @@ -80,6 +80,7 @@ def _parse_partitions(env): result = [] next_offset = 0 + bound = 0x10000 # default value with open(partitions_csv) as fp: for line in fp.readlines(): line = line.strip() @@ -97,13 +98,14 @@ def _parse_partitions(env): "flags": tokens[5] if len(tokens) > 5 else None } result.append(partition) - next_offset = _parse_size(partition["offset"]) + _parse_size( - partition["size"] - ) - - bound = 0x10000 if partition["type"] in ("0", "app") else 4 + next_offset = _parse_size(partition["offset"]) + #print("App start from .csv:", hex(next_offset)) + #print("Partition subtype from .csv:", partition["subtype"]) + if (partition["subtype"] == "ota_0"): + bound = next_offset next_offset = (next_offset + bound - 1) & ~(bound - 1) - + #print("Main Firmware will be flashed to:", hex(bound)) + env["ESP32_APP_OFFSET"] = hex(bound) return result @@ -213,8 +215,6 @@ def __fetch_fs_size(target, source, env): "ESP32_FS_IMAGE_NAME", env.get("ESP32_SPIFFS_IMAGE_NAME", filesystem) ), - ESP32_APP_OFFSET=board.get("upload.offset_address", "0x10000"), - PROGSUFFIX=".elf" ) From c20949e8b4eda529a22fa0169c1510978ee06c93 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 3 May 2022 23:36:39 +0200 Subject: [PATCH 034/666] Apple arm toolchains for IDF --- builder/frameworks/espidf.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 624f0f839..cd4780940 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -50,14 +50,24 @@ idf_variant = mcu.lower() FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") -TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" - % ( - "riscv32-esp" - if mcu == "esp32c3" - else ("xtensa-%s" % mcu) +if "darwin" in get_systype() and "arm64" in get_systype(): + TOOLCHAIN_DIR = platform.get_package_dir( + "toolchain-%s" + % ( + "riscv32-esp-arm" + if mcu == "esp32c3" + else ("xtensa-%s-arm" % mcu) + ) + ) +if not "arm64" in get_systype(): + TOOLCHAIN_DIR = platform.get_package_dir( + "toolchain-%s" + % ( + "riscv32-esp" + if mcu == "esp32c3" + else ("xtensa-%s" % mcu) + ) ) -) assert os.path.isdir(FRAMEWORK_DIR) assert os.path.isdir(TOOLCHAIN_DIR) From 27911286c3dda046d4754bb0c81d4984411e2091 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 4 May 2022 10:14:57 +0200 Subject: [PATCH 035/666] Arduino framework based on IDF4.4.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 782316d4f..63a575c83 100644 --- a/platform.json +++ b/platform.json @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/803/framework-arduinoespressif32-v4.4_dev-40d126bfd1.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/829/framework-arduinoespressif32-v4.4.1-3010c4571f.tar.gz" }, "framework-espidf": { "type": "framework", From fee4322df9cbe9e3758a981ca141d0493e999faa Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 5 May 2022 20:56:08 +0200 Subject: [PATCH 036/666] Use Tasmota release versions --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 63a575c83..9ee99b0d7 100644 --- a/platform.json +++ b/platform.json @@ -37,13 +37,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/829/framework-arduinoespressif32-v4.4.1-3010c4571f.tar.gz" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.3/framework-arduinoespressif32-203.tar.gz" }, "framework-espidf": { "type": "framework", "optional": true, - "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v.4.4.1/esp-idf-v4.4.1.zip" + "owner": "tasmota", + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.1/esp-idf-v4.4.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From b0edbde3f6e80f4a30b70da5ab6f95a8106d4825 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 6 May 2022 20:23:42 +0200 Subject: [PATCH 037/666] Compile IDF bootloader with optimizations by default By default the size of bootloader is limited to 0x2000 bytes, in debug mode the footprint can be easily grow beyond this limit --- builder/frameworks/espidf.py | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index cd4780940..3058d9343 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -282,13 +282,15 @@ def load_target_configurations(cmake_codemodel, cmake_api_reply_dir): return configs -def build_library(default_env, lib_config, project_src_dir, prepend_dir=None): +def build_library( + default_env, lib_config, project_src_dir, prepend_dir=None, debug_allowed=True +): lib_name = lib_config["nameOnDisk"] lib_path = lib_config["paths"]["build"] if prepend_dir: lib_path = os.path.join(prepend_dir, lib_path) lib_objects = compile_source_files( - lib_config, default_env, project_src_dir, prepend_dir + lib_config, default_env, project_src_dir, prepend_dir, debug_allowed ) return default_env.Library( target=os.path.join("$BUILD_DIR", lib_path, lib_name), source=lib_objects @@ -594,11 +596,11 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): ) -def prepare_build_envs(config, default_env): +def prepare_build_envs(config, default_env, debug_allowed=True): build_envs = [] target_compile_groups = config.get("compileGroups") - is_build_type_debug = "debug" in env.GetBuildType() + is_build_type_debug = "debug" in env.GetBuildType() and debug_allowed for cg in target_compile_groups: includes = [] sys_includes = [] @@ -628,8 +630,8 @@ def prepare_build_envs(config, default_env): return build_envs -def compile_source_files(config, default_env, project_src_dir, prepend_dir=None): - build_envs = prepare_build_envs(config, default_env) +def compile_source_files(config, default_env, project_src_dir, prepend_dir=None, debug_allowed=True): + build_envs = prepare_build_envs(config, default_env, debug_allowed) objects = [] components_dir = fs.to_unix_path(os.path.join(FRAMEWORK_DIR, "components")) for source in config.get("sources", []): @@ -758,7 +760,7 @@ def fix_ld_paths(extra_flags): return extra_flags -def build_bootloader(): +def build_bootloader(sdk_config): bootloader_src_dir = os.path.join( FRAMEWORK_DIR, "components", "bootloader", "subproject" ) @@ -798,7 +800,15 @@ def build_bootloader(): target_configs, ["STATIC_LIBRARY", "OBJECT_LIBRARY"] ) - build_components(bootloader_env, components_map, bootloader_src_dir, "bootloader") + # Note: By default the size of bootloader is limited to 0x2000 bytes, + # in debug mode the footprint size can be easily grow beyond this limit + build_components( + bootloader_env, + components_map, + bootloader_src_dir, + "bootloader", + debug_allowed=sdk_config.get("BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG", False), + ) link_args = extract_link_args(elf_config) extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) extra_flags = fix_ld_paths(extra_flags) @@ -844,10 +854,12 @@ def get_components_map(target_configs, target_types, ignore_components=None): return result -def build_components(env, components_map, project_src_dir, prepend_dir=None): +def build_components( + env, components_map, project_src_dir, prepend_dir=None, debug_allowed=True +): for k, v in components_map.items(): components_map[k]["lib"] = build_library( - env, v["config"], project_src_dir, prepend_dir + env, v["config"], project_src_dir, prepend_dir, debug_allowed ) @@ -1290,7 +1302,7 @@ def _get_installed_pip_packages(): # Compile bootloader # -env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", build_bootloader()) +env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", build_bootloader(sdk_config)) # # Target: ESP-IDF menuconfig From 87e642008ff6bd73d7f391aa9c6d00f8de8ef9a0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 6 May 2022 20:32:12 +0200 Subject: [PATCH 038/666] Update examples.yml --- .github/workflows/examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index ced6a39b3..a49859fa0 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -33,11 +33,11 @@ jobs: - "examples/espidf-ulp-pulse" runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: "recursive" - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies From b070465de5f5dc913b7b98f793dfb0d4f578713b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 15 May 2022 23:33:30 +0200 Subject: [PATCH 039/666] esptool.py v3.3.1 --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 9ee99b0d7..0148e4f63 100644 --- a/platform.json +++ b/platform.json @@ -119,8 +119,8 @@ }, "tool-esptoolpy": { "type": "uploader", - "owner": "platformio", - "version": "~1.30300.0" + "owner": "tasmota", + "version": "https://github.com/tasmota/esptool/releases/download/v3.3.1/esptool-3.3.1.zip" }, "tool-mbctool": { "optional": true, From 6ff8331828492820c7950f62f4d21930f625bc7a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 May 2022 17:14:27 +0200 Subject: [PATCH 040/666] Update platform.py --- platform.py | 53 +++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/platform.py b/platform.py index 75355a721..d9ad86189 100644 --- a/platform.py +++ b/platform.py @@ -98,27 +98,33 @@ def configure_default_packages(self, variables, targets): elif p in ("tool-mconf", "tool-idf") and "windows" in get_systype(): self.packages[p]["optional"] = False - if mcu in ("esp32", "esp32s2", "esp32s3", "esp32c3"): - # RISC-V based toolchain for ESP32C3 and ESP32Sx ULP - self.packages["toolchain-esp32ulp"]["optional"] = False - if not "arm64" in get_systype(): - if mcu == "esp32c3": - self.packages["toolchain-riscv32-esp"]["optional"] = False - if mcu == "esp32": - self.packages["toolchain-xtensa-esp32"]["optional"] = False - if mcu == "esp32s2": - self.packages["toolchain-xtensa-esp32s2"]["optional"] = False - if mcu == "esp32s3": - self.packages["toolchain-xtensa-esp32s3"]["optional"] = False - if "darwin" in get_systype() and "arm64" in get_systype(): - if mcu == "esp32c3": - self.packages["toolchain-riscv32-esp-arm"]["optional"] = False - if mcu == "esp32": - self.packages["toolchain-xtensa-esp32-arm"]["optional"] = False - if mcu == "esp32s2": - self.packages["toolchain-xtensa-esp32s2-arm"]["optional"] = False - if mcu == "esp32s3": - self.packages["toolchain-xtensa-esp32s3-arm"]["optional"] = False + if not "arm64" in get_systype(): + for available_mcu in ("esp32", "esp32s2", "esp32s3"): + if available_mcu == mcu: + self.packages["toolchain-xtensa-%s" % mcu]["optional"] = False + else: + self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) + + if mcu in ("esp32s2", "esp32s3", "esp32c3"): + self.packages.pop("toolchain-esp32ulp", None) + if mcu == "esp32" or mcu == "esp32c3": + self.packages.pop("toolchain-esp32s2ulp", None) + # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP + self.packages["toolchain-riscv32-esp"]["optional"] = False + + if "darwin" in get_systype() and "arm64" in get_systype(): + for available_mcu in ("esp32", "esp32s2", "esp32s3"): + if available_mcu == mcu: + self.packages["toolchain-xtensa-%s-arm" % mcu]["optional"] = False + else: + self.packages.pop("toolchain-xtensa-%s-arm" % available_mcu, None) + + if mcu in ("esp32s2", "esp32s3", "esp32c3"): + self.packages.pop("toolchain-esp32ulp", None) + if mcu == "esp32" or mcu == "esp32c3": + self.packages.pop("toolchain-esp32s2ulp", None) + # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP + self.packages["toolchain-riscv32-esp-arm"]["optional"] = False is_legacy_project = ( build_core == "mbcwb" @@ -175,6 +181,7 @@ def _add_dynamic_options(self, board): supported_debug_tools = [ "cmsis-dap", "esp-prog", + "esp_usb_jtag", "iot-bus-jtag", "jlink", "minimodule", @@ -201,9 +208,7 @@ def _add_dynamic_options(self, board): if link in non_debug_protocols or link in debug["tools"]: continue - if link == "jlink": - openocd_interface = link - elif link == "cmsis-dap": + if link in ("jlink", "cmsis-dap", "esp_usb_jtag"): openocd_interface = link elif link in ("esp-prog", "ftdi"): if board.id == "esp32-s2-kaluga-1": From f795b235695cca6d90d16b1b2e8115d95af13fd8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 16 May 2022 21:20:04 +0200 Subject: [PATCH 041/666] add `_get_board_boot_mode` --- builder/main.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index fb8ffd665..046503975 100644 --- a/builder/main.py +++ b/builder/main.py @@ -57,6 +57,10 @@ def _get_board_flash_mode(env): return mode +def _get_board_boot_mode(env): + return env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE") + + def _parse_size(value): if isinstance(value, int): return value @@ -113,8 +117,8 @@ def _update_max_upload_size(env): if not env.get("PARTITIONS_TABLE_CSV"): return sizes = [ - _parse_size(p['size']) for p in _parse_partitions(env) - if p['type'] in ("0", "app") + _parse_size(p["size"]) for p in _parse_partitions(env) + if p["type"] in ("0", "app") ] if sizes: board.update("upload.maximum_size", max(sizes)) @@ -169,6 +173,7 @@ def __fetch_fs_size(target, source, env): toolchain_arch = "riscv32-esp" env.Replace( + __get_board_boot_mode=_get_board_boot_mode, __get_board_f_flash=_get_board_f_flash, __get_board_flash_mode=_get_board_flash_mode, From 2447d782a64676dda8b8333b5a998c05987969bf Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 25 May 2022 14:43:45 +0200 Subject: [PATCH 042/666] esptool.py v4.0.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 0148e4f63..54dded7d0 100644 --- a/platform.json +++ b/platform.json @@ -120,7 +120,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v3.3.1/esptool-3.3.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.0.1/esptool-4.0.1.zip" }, "tool-mbctool": { "optional": true, From 46869e30c56b2ff89cbc1268f1c066cef14c0af1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 15:46:28 +0200 Subject: [PATCH 043/666] Improve support for assembly programming --- builder/frameworks/espidf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 3058d9343..8e790205c 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -621,7 +621,6 @@ def prepare_build_envs(config, default_env, debug_allowed=True): build_env.AppendUnique(CPPDEFINES=defines, CPPPATH=includes) if sys_includes: build_env.Append(CCFLAGS=[("-isystem", inc) for inc in sys_includes]) - build_env.Append(ASFLAGS=build_env.get("CCFLAGS", [])[:]) build_env.ProcessUnFlags(default_env.get("BUILD_UNFLAGS")) if is_build_type_debug: build_env.ConfigureDebugFlags() From 87a7913f3a2951d5c3ae4a8cec034f73dc1f0a36 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 15:53:17 +0200 Subject: [PATCH 044/666] Add compatibility with PIO Core 6.0 --- monitor/filter_exception_decoder.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index 154440cbe..5feb28e17 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -17,16 +17,19 @@ import subprocess import sys -from platformio.compat import path_to_unicode, WINDOWS from platformio.project.exception import PlatformioException -from platformio.project.helpers import load_project_ide_data -from platformio.commands.device import DeviceMonitorFilter +from platformio.public import ( + DeviceMonitorFilterBase, + load_build_metadata, +) # By design, __init__ is called inside miniterm and we can't pass context to it. # pylint: disable=attribute-defined-outside-init +IS_WINDOWS = sys.platform.startswith("win") -class Esp32ExceptionDecoder(DeviceMonitorFilter): + +class Esp32ExceptionDecoder(DeviceMonitorFilterBase) NAME = "esp32_exception_decoder" def __call__(self): @@ -42,7 +45,7 @@ def __call__(self): return self def setup_paths(self): - self.project_dir = path_to_unicode(os.path.abspath(self.project_dir)) + self.project_dir = os.path.abspath(self.project_dir) self.project_strip_dir = os.environ.get("esp32_exception_decoder_project_strip_dir") self.firmware_path = os.environ.get("esp32_exception_decoder_firmware_path") @@ -54,7 +57,7 @@ def setup_paths(self): try: if self.firmware_path is None or self.addr2line_path is None: # Only load if necessary, as the call is expensive - data = load_project_ide_data(self.project_dir, self.environment) + data = load_build_metadata(self.project_dir, self.environment) if self.firmware_path is None: # Only do this check when the firmware path is not externally provided @@ -133,7 +136,7 @@ def rx(self, text): def get_backtrace(self, match): trace = "" - enc = "mbcs" if WINDOWS else "utf-8" + enc = "mbcs" if IS_WINDOWS else "utf-8" args = [self.addr2line_path, u"-fipC", u"-e", self.firmware_path] try: addr = match.group() From 2bb002334ea6a952b624ee2fa072fc895d437975 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 15:56:11 +0200 Subject: [PATCH 045/666] Update platform.py --- platform.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform.py b/platform.py index d9ad86189..fa817b08a 100644 --- a/platform.py +++ b/platform.py @@ -21,10 +21,9 @@ import requests from platformio import fs -from platformio.managers.platform import PlatformBase +from platformio.public import PlatformBase, to_unix_path from platformio.util import get_systype - class Espressif32Platform(PlatformBase): def configure_default_packages(self, variables, targets): if not variables.get("board"): From f09dfd79ae0fda1374d23a8d95d728ace7733999 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 15:59:32 +0200 Subject: [PATCH 046/666] Update examples.yml --- .github/workflows/examples.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index a49859fa0..d57f14183 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -8,7 +8,6 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: [3.8] example: - "examples/arduino-ble5-advertising" - "examples/arduino-blink" @@ -36,15 +35,14 @@ jobs: - uses: actions/checkout@v3 with: submodules: "recursive" - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - name: Set up Python + uses: actions/setup-python@v3 with: - python-version: ${{ matrix.python-version }} + python-version: "3.9" - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install -U platformio - platformio platform install file://. + pip install -U https://github.com/platformio/platformio/archive/develop.zip + pio pkg install --global --platform symlink://. - name: Build examples run: | - platformio run -d ${{ matrix.example }} + pio run -d ${{ matrix.example }} From 62fb7b9d03a1a8cff8b3a3c76c040892d9847bae Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 16:03:02 +0200 Subject: [PATCH 047/666] Explicitly exit from build process when there is default IDF component --- builder/frameworks/espidf.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 8e790205c..77446f3b1 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -901,7 +901,13 @@ def find_default_component(target_configs): for config in target_configs: if "__pio_env" in config: return config - return "" + sys.stderr.write( + "Error! Failed to find the default IDF component with build information for " + "generic files.\nCheck that the `EXTRA_COMPONENT_DIRS` option is not overridden " + "in your CMakeLists.txt.\nSee an example with an extra component here " + "https://docs.platformio.org/en/latest/frameworks/espidf.html#esp-idf-components\n" + ) + env.Exit(1) def create_version_file(): From b0ed550f0ff5d79114e100c060709d6b7386e933 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 16:06:32 +0200 Subject: [PATCH 048/666] revert Use empty ASM and CXX flags if config empty --- builder/frameworks/espidf.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 77446f3b1..8e790205c 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -901,13 +901,7 @@ def find_default_component(target_configs): for config in target_configs: if "__pio_env" in config: return config - sys.stderr.write( - "Error! Failed to find the default IDF component with build information for " - "generic files.\nCheck that the `EXTRA_COMPONENT_DIRS` option is not overridden " - "in your CMakeLists.txt.\nSee an example with an extra component here " - "https://docs.platformio.org/en/latest/frameworks/espidf.html#esp-idf-components\n" - ) - env.Exit(1) + return "" def create_version_file(): From dc222e0a892a4379ee4d51e1320bd24e9cd760de Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 19:20:39 +0200 Subject: [PATCH 049/666] Update main.py --- builder/main.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/builder/main.py b/builder/main.py index 046503975..bbfa4f49f 100644 --- a/builder/main.py +++ b/builder/main.py @@ -163,7 +163,6 @@ def __fetch_fs_size(target, source, env): env = DefaultEnvironment() -env.SConscript("compat.py", exports="env") platform = env.PioPlatform() board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") @@ -228,9 +227,6 @@ def __fetch_fs_size(target, source, env): env.Replace(PROGNAME="firmware") env.Append( - # copy CCFLAGS to ASFLAGS (-x assembler-with-cpp mode) - ASFLAGS=env.get("CCFLAGS", [])[:], - BUILDERS=dict( ElfToBin=Builder( action=env.VerboseAction(" ".join([ From 7ce2557a099d0b6cb0d4e803eccaec13a9f3ddef Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 19:27:31 +0200 Subject: [PATCH 050/666] Update platform.py --- platform.py | 59 ++++++++--------------------------------------------- 1 file changed, 9 insertions(+), 50 deletions(-) diff --git a/platform.py b/platform.py index fa817b08a..e47e1e484 100644 --- a/platform.py +++ b/platform.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import copy import os import urllib import sys @@ -20,14 +19,15 @@ import re import requests -from platformio import fs from platformio.public import PlatformBase, to_unix_path -from platformio.util import get_systype + + +IS_WINDOWS = sys.platform.startswith("win") class Espressif32Platform(PlatformBase): def configure_default_packages(self, variables, targets): if not variables.get("board"): - return PlatformBase.configure_default_packages(self, variables, targets) + return super().configure_default_packages(variables, targets) board_config = self.board_config(variables.get("board")) mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32")) @@ -94,7 +94,7 @@ def configure_default_packages(self, variables, targets): for p in self.packages: if p in ("tool-cmake", "tool-ninja", "toolchain-%sulp" % mcu): self.packages[p]["optional"] = False - elif p in ("tool-mconf", "tool-idf") and "windows" in get_systype(): + elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: self.packages[p]["optional"] = False if not "arm64" in get_systype(): @@ -154,10 +154,10 @@ def configure_default_packages(self, variables, targets): self.packages["tool-mbctool"]["type"] = "uploader" self.packages["tool-mbctool"]["optional"] = False - return PlatformBase.configure_default_packages(self, variables, targets) + return super().configure_default_packages(variables, targets) def get_boards(self, id_=None): - result = PlatformBase.get_boards(self, id_) + result = super().get_boards(id_) if not result: return result if id_: @@ -278,60 +278,19 @@ def configure_debug_session(self, debug_config): load_cmds = [ 'monitor program_esp "{{{path}}}" {offset} verify'.format( - path=fs.to_unix_path(item["path"]), offset=item["offset"] + path=to_unix_path(item["path"]), offset=item["offset"] ) for item in flash_images ] load_cmds.append( 'monitor program_esp "{%s.bin}" %s verify' % ( - fs.to_unix_path(debug_config.build_data["prog_path"][:-4]), + to_unix_path(debug_config.build_data["prog_path"][:-4]), build_extra_data.get("application_offset", "0x10000"), ) ) debug_config.load_cmds = load_cmds - def configure_debug_options(self, initial_debug_options, ide_data): - """ - Deprecated. Remove method when PlatformIO Core 5.2 is released - """ - ide_extra_data = ide_data.get("extra", {}) - flash_images = ide_extra_data.get("flash_images", []) - debug_options = copy.deepcopy(initial_debug_options) - - if "openocd" in debug_options["server"].get("executable", ""): - debug_options["server"]["arguments"].extend( - [ - "-c", - "adapter_khz %s" % (initial_debug_options.get("speed") or "5000"), - ] - ) - - ignore_conds = [ - initial_debug_options["load_cmds"] != ["load"], - not flash_images, - not all([os.path.isfile(item["path"]) for item in flash_images]), - ] - - if any(ignore_conds): - return debug_options - - load_cmds = [ - 'monitor program_esp "{{{path}}}" {offset} verify'.format( - path=fs.to_unix_path(item["path"]), offset=item["offset"] - ) - for item in flash_images - ] - load_cmds.append( - 'monitor program_esp "{%s.bin}" %s verify' - % ( - fs.to_unix_path(ide_data["prog_path"][:-4]), - ide_extra_data.get("application_offset", "0x10000"), - ) - ) - debug_options["load_cmds"] = load_cmds - return debug_options - @staticmethod def extract_toolchain_versions(tool_deps): def _parse_version(original_version): From 07139bdd707ff1ff9710c7436bb43a75a313e81a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 19:28:45 +0200 Subject: [PATCH 051/666] "platformio": "^6" --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 54dded7d0..25ded6b02 100644 --- a/platform.json +++ b/platform.json @@ -12,7 +12,7 @@ "RISC-V" ], "engines": { - "platformio": "^5" + "platformio": "^6" }, "repository": { "type": "git", From 5c75ac9d7b184e439eae9090f8e27d5fcdb21823 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 19:29:52 +0200 Subject: [PATCH 052/666] Update _bare.py --- builder/frameworks/_bare.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/builder/frameworks/_bare.py b/builder/frameworks/_bare.py index 5db4a07f6..6cb23ea2f 100644 --- a/builder/frameworks/_bare.py +++ b/builder/frameworks/_bare.py @@ -21,7 +21,12 @@ Import("env") env.Append( - ASFLAGS=["-x", "assembler-with-cpp"], + ASFLAGS=[ + "-mlongcalls", + ], + ASPPFLAGS=[ + "-x", "assembler-with-cpp", + ], CFLAGS=["-std=gnu99"], @@ -60,6 +65,3 @@ "-Wl,--gc-sections" ] ) - -# copy CCFLAGS to ASFLAGS (-x assembler-with-cpp mode) -env.Append(ASFLAGS=env.get("CCFLAGS", [])[:]) From 6b68e757c63a62f18d668321c4683a4e6111fd44 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 19:37:53 +0200 Subject: [PATCH 053/666] Update platform.py --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index e47e1e484..7502c1935 100644 --- a/platform.py +++ b/platform.py @@ -20,7 +20,7 @@ import requests from platformio.public import PlatformBase, to_unix_path - +from platformio.util import get_systype IS_WINDOWS = sys.platform.startswith("win") From b9bfcc045b106e2098387874b545439f9a51d5b6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 31 May 2022 19:39:54 +0200 Subject: [PATCH 054/666] Delete compat.py --- builder/compat.py | 38 -------------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 builder/compat.py diff --git a/builder/compat.py b/builder/compat.py deleted file mode 100644 index b8dfe3d3f..000000000 --- a/builder/compat.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2014-present PlatformIO -# -# 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. - -from SCons.Script import AlwaysBuild, Import - - -Import("env") - - -# Added in PIO Core 4.4.0 -if not hasattr(env, "AddPlatformTarget"): - - def AddPlatformTarget( - env, - name, - dependencies, - actions, - title=None, - description=None, - always_build=True, - ): - target = env.Alias(name, dependencies, actions) - if always_build: - AlwaysBuild(target) - return target - - env.AddMethod(AddPlatformTarget) From 452fe13d9f14232b210dd941aa69cd40bea669dd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 1 Jun 2022 16:24:35 +0200 Subject: [PATCH 055/666] Platformio core 6.0.2 since Tasmota uses ino folder feature, which is introduced with 6.0.2 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 25ded6b02..3a9273729 100644 --- a/platform.json +++ b/platform.json @@ -12,7 +12,7 @@ "RISC-V" ], "engines": { - "platformio": "^6" + "platformio": ">=6.0.2" }, "repository": { "type": "git", From 6b6ea7bf9706c4d7f98b63b9aeb82f6dca60fa45 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 1 Jun 2022 19:13:37 +0200 Subject: [PATCH 056/666] pio core v6.0.2 --- .github/workflows/examples.yml | 20 +- README.md | 2 +- boards/adafruit_funhouse_esp32s2.json | 62 ++++ boards/adafruit_magtag29_esp32s2.json | 62 ++++ boards/adafruit_metro_esp32s2.json | 62 ++++ boards/adafruit_qtpy_esp32-s2.json | 34 ++ boards/atmegazero_esp32s2.json | 53 ++++ boards/az-delivery-devkit-v4.json | 2 +- boards/deneyapkart.json | 41 +++ boards/deneyapmini.json | 44 +++ boards/denky32.json | 39 +++ boards/denky_d4.json | 37 +++ boards/esp32-c3-devkitm-1.json | 1 + boards/esp32-s2-franzininho.json | 3 +- boards/esp32-s2-kaluga-1.json | 2 +- boards/esp32-s2-saola-1.json | 2 +- boards/featheresp32-s2.json | 31 +- boards/franzininho_wifi_esp32s2.json | 45 +++ boards/franzininho_wifi_msc_esp32s2.json | 47 +++ boards/kb32-ft.json | 42 +++ boards/m5stack-fire.json | 7 +- boards/m5stack-timer-cam.json | 7 +- boards/micros2.json | 48 +++ boards/nano32.json | 4 +- boards/sparkfun_esp32micromod.json | 34 ++ boards/sparkfun_esp32s2_thing_plus.json | 43 +++ boards/tinypico.json | 11 +- boards/trueverit-iot-driver-mk2.json | 37 +++ boards/trueverit-iot-driver.json | 37 +++ boards/ttgo-t-watch.json | 7 +- boards/um_feathers2.json | 46 +++ boards/um_feathers2_neo.json | 46 +++ boards/um_tinys2.json | 46 +++ boards/upesy_wroom.json | 37 +++ boards/upesy_wrover.json | 42 +++ builder/compat.py | 38 --- builder/frameworks/_bare.py | 10 +- builder/frameworks/_embed_files.py | 9 +- builder/frameworks/arduino.py | 1 + builder/frameworks/espidf.py | 62 ++-- builder/frameworks/pumbaa.py | 70 ---- builder/frameworks/simba.py | 68 ---- builder/main.py | 200 +++++++----- .../.gitignore | 0 examples/arduino-ble5-advertising/README.md | 27 ++ .../include/README | 0 .../lib/README | 0 .../platformio.ini | 9 +- .../src/BLE5_periodic_advertising.ino | 72 +++++ .../test/README | 0 .../.gitignore | 0 examples/arduino-usb-keyboard/README.md | 27 ++ .../include/README | 0 .../lib/README | 0 .../platformio.ini | 14 +- .../src/KeyboardSerial.ino | 40 +++ .../test/README | 0 examples/pumbaa-blink/.skiptest | 1 - examples/pumbaa-blink/.travis.yml | 67 ---- examples/pumbaa-blink/README.md | 18 -- examples/pumbaa-blink/src/main.c | 22 -- examples/pumbaa-blink/src/main.py | 40 --- examples/simba-blink/.travis.yml | 67 ---- examples/simba-blink/README.md | 18 -- examples/simba-blink/src/main.c | 43 --- monitor/filter_exception_decoder.py | 130 ++++---- platform.json | 113 +++---- platform.py | 300 +++++++++++++----- 68 files changed, 1753 insertions(+), 796 deletions(-) create mode 100644 boards/adafruit_funhouse_esp32s2.json create mode 100644 boards/adafruit_magtag29_esp32s2.json create mode 100644 boards/adafruit_metro_esp32s2.json create mode 100644 boards/adafruit_qtpy_esp32-s2.json create mode 100644 boards/atmegazero_esp32s2.json create mode 100644 boards/deneyapkart.json create mode 100644 boards/deneyapmini.json create mode 100644 boards/denky32.json create mode 100644 boards/denky_d4.json create mode 100644 boards/franzininho_wifi_esp32s2.json create mode 100644 boards/franzininho_wifi_msc_esp32s2.json create mode 100644 boards/kb32-ft.json create mode 100644 boards/micros2.json create mode 100644 boards/sparkfun_esp32micromod.json create mode 100644 boards/sparkfun_esp32s2_thing_plus.json create mode 100644 boards/trueverit-iot-driver-mk2.json create mode 100644 boards/trueverit-iot-driver.json create mode 100644 boards/um_feathers2.json create mode 100644 boards/um_feathers2_neo.json create mode 100644 boards/um_tinys2.json create mode 100644 boards/upesy_wroom.json create mode 100644 boards/upesy_wrover.json delete mode 100644 builder/compat.py delete mode 100644 builder/frameworks/pumbaa.py delete mode 100644 builder/frameworks/simba.py rename examples/{pumbaa-blink => arduino-ble5-advertising}/.gitignore (100%) mode change 100755 => 100644 create mode 100644 examples/arduino-ble5-advertising/README.md rename examples/{pumbaa-blink => arduino-ble5-advertising}/include/README (100%) rename examples/{pumbaa-blink => arduino-ble5-advertising}/lib/README (100%) rename examples/{pumbaa-blink => arduino-ble5-advertising}/platformio.ini (67%) mode change 100755 => 100644 create mode 100644 examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino rename examples/{pumbaa-blink => arduino-ble5-advertising}/test/README (100%) rename examples/{simba-blink => arduino-usb-keyboard}/.gitignore (100%) mode change 100755 => 100644 create mode 100644 examples/arduino-usb-keyboard/README.md rename examples/{simba-blink => arduino-usb-keyboard}/include/README (100%) rename examples/{simba-blink => arduino-usb-keyboard}/lib/README (100%) rename examples/{simba-blink => arduino-usb-keyboard}/platformio.ini (60%) mode change 100755 => 100644 create mode 100644 examples/arduino-usb-keyboard/src/KeyboardSerial.ino rename examples/{simba-blink => arduino-usb-keyboard}/test/README (100%) delete mode 100644 examples/pumbaa-blink/.skiptest delete mode 100755 examples/pumbaa-blink/.travis.yml delete mode 100755 examples/pumbaa-blink/README.md delete mode 100755 examples/pumbaa-blink/src/main.c delete mode 100755 examples/pumbaa-blink/src/main.py delete mode 100755 examples/simba-blink/.travis.yml delete mode 100755 examples/simba-blink/README.md delete mode 100755 examples/simba-blink/src/main.c diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 90cab3dcc..d57f14183 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -8,11 +8,12 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: [3.8] example: + - "examples/arduino-ble5-advertising" - "examples/arduino-blink" - "examples/arduino-rmt-blink" - "examples/arduino-briki-internal-libs" + - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/espidf-arduino-blink" - "examples/espidf-arduino-wifiscan" @@ -29,22 +30,19 @@ jobs: - "examples/espidf-storage-spiffs" - "examples/espidf-ulp-adc" - "examples/espidf-ulp-pulse" - - "examples/pumbaa-blink" - - "examples/simba-blink" runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: "recursive" - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + - name: Set up Python + uses: actions/setup-python@v3 with: - python-version: ${{ matrix.python-version }} + python-version: "3.9" - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install -U platformio - platformio platform install file://. + pip install -U https://github.com/platformio/platformio/archive/develop.zip + pio pkg install --global --platform symlink://. - name: Build examples run: | - platformio run -d ${{ matrix.example }} + pio run -d ${{ matrix.example }} diff --git a/README.md b/README.md index a0268dc64..82c9a2bfa 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # Tasmota Espressif 32: development platform for [PlatformIO](http://platformio.org) -[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml) +[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml)[![GitHub Releases](https://img.shields.io/github/downloads/Jason2866/platform-espressif32/total?label=downloads)](https://github.com/Jason2866/platform-espressif32/releases/latest) Espressif Systems is a privately held fabless semiconductor company. They provide wireless communications and Wi-Fi chips which are widely used in mobile devices and the Internet of Things applications. diff --git a/boards/adafruit_funhouse_esp32s2.json b/boards/adafruit_funhouse_esp32s2.json new file mode 100644 index 000000000..974761247 --- /dev/null +++ b/boards/adafruit_funhouse_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FUNHOUSE_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80F9" + ], + [ + "0x239A", + "0x00F9" + ], + [ + "0x239A", + "0x80FA" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_funhouse_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit FunHouse", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_funhouse_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4985", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_magtag29_esp32s2.json b/boards/adafruit_magtag29_esp32s2.json new file mode 100644 index 000000000..40d7bd3e9 --- /dev/null +++ b/boards/adafruit_magtag29_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_MAGTAG29_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80DF" + ], + [ + "0x239A", + "0x00DF" + ], + [ + "0x239A", + "0x80E0" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_magtag29_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit MagTag 2.9", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_magtag29_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4800", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_metro_esp32s2.json b/boards/adafruit_metro_esp32s2.json new file mode 100644 index 000000000..af8df2279 --- /dev/null +++ b/boards/adafruit_metro_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_METRO_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80DF" + ], + [ + "0x239A", + "0x00DF" + ], + [ + "0x239A", + "0x80E0" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_metro_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Metro ESP32-S2", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_metro_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4775", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32-s2.json b/boards/adafruit_qtpy_esp32-s2.json new file mode 100644 index 000000000..9ef92b3e2 --- /dev/null +++ b/boards/adafruit_qtpy_esp32-s2.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s2", + "variant": "adafruit_qtpy_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5325", + "vendor": "Adafruit" +} diff --git a/boards/atmegazero_esp32s2.json b/boards/atmegazero_esp32s2.json new file mode 100644 index 000000000..bfc40697f --- /dev/null +++ b/boards/atmegazero_esp32s2.json @@ -0,0 +1,53 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_atmegazero_esp32s2", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x800A" + ] + ], + "mcu": "esp32s2", + "variant": "atmegazero_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "EspinalLab ATMegaZero ESP32-S2", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/atmegazero_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://shop.atmegazero.com/", + "vendor": "EspinalLab" +} diff --git a/boards/az-delivery-devkit-v4.json b/boards/az-delivery-devkit-v4.json index 45fa0a20b..93237d723 100644 --- a/boards/az-delivery-devkit-v4.json +++ b/boards/az-delivery-devkit-v4.json @@ -28,7 +28,7 @@ "upload": { "flash_size": "4MB", "maximum_ram_size": 532480, - "maximum_size": 16777216, + "maximum_size": 4194304, "require_upload_port": true, "speed": 460800 }, diff --git a/boards/deneyapkart.json b/boards/deneyapkart.json new file mode 100644 index 000000000..3114c0399 --- /dev/null +++ b/boards/deneyapkart.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYDK", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "deneyapkart" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/magaza/urun-deneyap-kart.html", + "vendor": "Deneyap" +} diff --git a/boards/deneyapmini.json b/boards/deneyapmini.json new file mode 100644 index 000000000..02509684b --- /dev/null +++ b/boards/deneyapmini.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_DYM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x0002" + ] + ], + "mcu": "esp32s2", + "variant": "deneyapmini" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/magaza/urun-deneyap-kart-mini.html", + "vendor": "Deneyap" +} diff --git a/boards/denky32.json b/boards/denky32.json new file mode 100644 index 000000000..3b2c40762 --- /dev/null +++ b/boards/denky32.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DENKY_WROOM32", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ch_denky" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Denky32 (WROOM32)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Denky" +} diff --git a/boards/denky_d4.json b/boards/denky_d4.json new file mode 100644 index 000000000..e5d0b76bd --- /dev/null +++ b/boards/denky_d4.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DENKY_PICOV3", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ch_denky" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Denky D4 (PICO-V3-02)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Denky" +} diff --git a/boards/esp32-c3-devkitm-1.json b/boards/esp32-c3-devkitm-1.json index a17aed860..bc4ba058c 100644 --- a/boards/esp32-c3-devkitm-1.json +++ b/boards/esp32-c3-devkitm-1.json @@ -7,6 +7,7 @@ "f_cpu": "160000000L", "f_flash": "80000000L", "flash_mode": "qio", + "extra_flags": "-DARDUINO_ESP32C3_DEV", "mcu": "esp32c3", "variant": "esp32c3" }, diff --git a/boards/esp32-s2-franzininho.json b/boards/esp32-s2-franzininho.json index 15854fdf4..d20d12a45 100644 --- a/boards/esp32-s2-franzininho.json +++ b/boards/esp32-s2-franzininho.json @@ -12,14 +12,13 @@ "variant": "esp32s2" }, "connectivity": [ - "arduino", - "espidf", "wifi" ], "debug": { "openocd_target": "esp32s2.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Franzininho WiFi Board", diff --git a/boards/esp32-s2-kaluga-1.json b/boards/esp32-s2-kaluga-1.json index b0120ffb7..b48abac37 100644 --- a/boards/esp32-s2-kaluga-1.json +++ b/boards/esp32-s2-kaluga-1.json @@ -7,7 +7,7 @@ "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s2", "variant": "esp32s2" }, diff --git a/boards/esp32-s2-saola-1.json b/boards/esp32-s2-saola-1.json index a02952b11..58927bb91 100644 --- a/boards/esp32-s2-saola-1.json +++ b/boards/esp32-s2-saola-1.json @@ -7,7 +7,7 @@ "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s2", "variant": "esp32s2" }, diff --git a/boards/featheresp32-s2.json b/boards/featheresp32-s2.json index 47387f578..bf6f0cbc2 100644 --- a/boards/featheresp32-s2.json +++ b/boards/featheresp32-s2.json @@ -4,12 +4,29 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80EB" + ], + [ + "0x239A", + "0x00EB" + ], + [ + "0x239A", + "0x80EC" + ] + ], "mcu": "esp32s2", - "variant": "esp32s2" + "variant": "adafruit_feather_esp32s2" }, "connectivity": [ "wifi" @@ -23,9 +40,19 @@ ], "name": "Adafruit ESP32-S2 Feather Development Board", "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2/tinyuf2.bin" + ] + ] + }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, "require_upload_port": true, "speed": 460800 }, diff --git a/boards/franzininho_wifi_esp32s2.json b/boards/franzininho_wifi_esp32s2.json new file mode 100644 index 000000000..df3a5651f --- /dev/null +++ b/boards/franzininho_wifi_esp32s2.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FRANZININHO_WIFI", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80A9" + ] + ], + "mcu": "esp32s2", + "variant": "franzininho_wifi_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Franzininho WiFi", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.franzininho.com.br/docs/franzininho-wifi/franzininho-wifi/", + "vendor": "Franzininho" +} diff --git a/boards/franzininho_wifi_msc_esp32s2.json b/boards/franzininho_wifi_msc_esp32s2.json new file mode 100644 index 000000000..163587b4f --- /dev/null +++ b/boards/franzininho_wifi_msc_esp32s2.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FRANZININHO_WIFI_MSC", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MSC_ON_BOOT=1", + "-DARDUINO_USB_DFU_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80A9" + ] + ], + "mcu": "esp32s2", + "variant": "franzininho_wifi_msc_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Franzininho WiFi MSC", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.franzininho.com.br/docs/franzininho-wifi/franzininho-wifi/", + "vendor": "Franzininho" +} diff --git a/boards/kb32-ft.json b/boards/kb32-ft.json new file mode 100644 index 000000000..586494f38 --- /dev/null +++ b/boards/kb32-ft.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_DEV", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MakerAsia KB32-FT", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://kb32ft.makerasia.com/", + "vendor": "MakerAsia" +} diff --git a/boards/m5stack-fire.json b/boards/m5stack-fire.json index 4f3ff39fd..1a500ab87 100644 --- a/boards/m5stack-fire.json +++ b/boards/m5stack-fire.json @@ -5,7 +5,12 @@ "partitions": "default_16MB.csv" }, "core": "esp32", - "extra_flags": "-DARDUINO_M5STACK_FIRE -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_M5STACK_FIRE", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", diff --git a/boards/m5stack-timer-cam.json b/boards/m5stack-timer-cam.json index 41ff2a809..5f76a861e 100644 --- a/boards/m5stack-timer-cam.json +++ b/boards/m5stack-timer-cam.json @@ -4,7 +4,12 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_M5Stack_Timer_CAM -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_M5Stack_Timer_CAM", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", diff --git a/boards/micros2.json b/boards/micros2.json new file mode 100644 index 000000000..93243bdba --- /dev/null +++ b/boards/micros2.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld", + "partitions": "ffat.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_MICROS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MSC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80C5" + ] + ], + "mcu": "esp32s2", + "variant": "micro_s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "microS2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/MicroDev1/microS2", + "vendor": "microS2" +} diff --git a/boards/nano32.json b/boards/nano32.json index eeb8a20bf..2e1f5568c 100644 --- a/boards/nano32.json +++ b/boards/nano32.json @@ -19,9 +19,7 @@ ], "frameworks": [ "arduino", - "espidf", - "simba", - "pumbaa" + "espidf" ], "name": "MakerAsia Nano32", "upload": { diff --git a/boards/sparkfun_esp32micromod.json b/boards/sparkfun_esp32micromod.json new file mode 100644 index 000000000..2d0f52e8a --- /dev/null +++ b/boards/sparkfun_esp32micromod.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_MICROMOD", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32micromod" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32 MicroMod", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/16781", + "vendor": "SparkFun" +} diff --git a/boards/sparkfun_esp32s2_thing_plus.json b/boards/sparkfun_esp32s2_thing_plus.json new file mode 100644 index 000000000..269d962fc --- /dev/null +++ b/boards/sparkfun_esp32s2_thing_plus.json @@ -0,0 +1,43 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32S2_THING_PLUS", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x1B4F", + "0x0027" + ] + ], + "mcu": "esp32s2", + "variant": "esp32s2thing_plus" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32-S2 Thing Plus", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "mode": "usb", + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/17743", + "vendor": "SparkFun" +} diff --git a/boards/tinypico.json b/boards/tinypico.json index 754a9870c..9f3deeabb 100644 --- a/boards/tinypico.json +++ b/boards/tinypico.json @@ -4,12 +4,17 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_TINYPICO -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_TINYPICO", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "qio", + "flash_mode": "dio", "mcu": "esp32", - "variant": "pico32" + "variant": "um_tinypico" }, "connectivity": [ "wifi", diff --git a/boards/trueverit-iot-driver-mk2.json b/boards/trueverit-iot-driver-mk2.json new file mode 100644 index 000000000..22e3eca79 --- /dev/null +++ b/boards/trueverit-iot-driver-mk2.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver_MK_II", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver-mkii" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver MK II", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} diff --git a/boards/trueverit-iot-driver.json b/boards/trueverit-iot-driver.json new file mode 100644 index 000000000..7f808ec32 --- /dev/null +++ b/boards/trueverit-iot-driver.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} diff --git a/boards/ttgo-t-watch.json b/boards/ttgo-t-watch.json index c58c273f3..354f54f14 100644 --- a/boards/ttgo-t-watch.json +++ b/boards/ttgo-t-watch.json @@ -5,7 +5,12 @@ "partitions": "default_16MB.csv" }, "core": "esp32", - "extra_flags": "-DARDUINO_TWATCH_BASE -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "extra_flags": [ + "-DARDUINO_TWATCH_BASE", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", diff --git a/boards/um_feathers2.json b/boards/um_feathers2.json new file mode 100644 index 000000000..7434f195e --- /dev/null +++ b/boards/um_feathers2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80AB" + ] + ], + "mcu": "esp32s2", + "variant": "um_feathers2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker FeatherS2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://feathers2.io", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_feathers2_neo.json b/boards/um_feathers2_neo.json new file mode 100644 index 000000000..7277d45ff --- /dev/null +++ b/boards/um_feathers2_neo.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS2NEO", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80B4" + ] + ], + "mcu": "esp32s2", + "variant": "um_feathers2neo" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker FeatherS2 Neo", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://unexpectedmaker.com/feathers2-neo", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_tinys2.json b/boards/um_tinys2.json new file mode 100644 index 000000000..8a57216ac --- /dev/null +++ b/boards/um_tinys2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TINYS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x8001" + ] + ], + "mcu": "esp32s2", + "variant": "um_tinys2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker TinyS2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://tinys2.io", + "vendor": "Unexpected Maker" +} diff --git a/boards/upesy_wroom.json b/boards/upesy_wroom.json new file mode 100644 index 000000000..999cef7c2 --- /dev/null +++ b/boards/upesy_wroom.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_uPesy_WROOM", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "uPesy_esp32_wroom_devkit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "uPesy ESP32 Wroom DevKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.upesy.fr/products/upesy-esp32-wroom-devkit-board", + "vendor": "uPesy" +} diff --git a/boards/upesy_wrover.json b/boards/upesy_wrover.json new file mode 100644 index 000000000..38b2eb3e7 --- /dev/null +++ b/boards/upesy_wrover.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_uPesy_WROVER", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "uPesy_esp32_wrover_devkit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "uPesy ESP32 Wrover DevKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.upesy.fr/products/upesy-esp32-wrover-devkit-board", + "vendor": "uPesy" +} diff --git a/builder/compat.py b/builder/compat.py deleted file mode 100644 index b8dfe3d3f..000000000 --- a/builder/compat.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2014-present PlatformIO -# -# 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. - -from SCons.Script import AlwaysBuild, Import - - -Import("env") - - -# Added in PIO Core 4.4.0 -if not hasattr(env, "AddPlatformTarget"): - - def AddPlatformTarget( - env, - name, - dependencies, - actions, - title=None, - description=None, - always_build=True, - ): - target = env.Alias(name, dependencies, actions) - if always_build: - AlwaysBuild(target) - return target - - env.AddMethod(AddPlatformTarget) diff --git a/builder/frameworks/_bare.py b/builder/frameworks/_bare.py index 5db4a07f6..6cb23ea2f 100644 --- a/builder/frameworks/_bare.py +++ b/builder/frameworks/_bare.py @@ -21,7 +21,12 @@ Import("env") env.Append( - ASFLAGS=["-x", "assembler-with-cpp"], + ASFLAGS=[ + "-mlongcalls", + ], + ASPPFLAGS=[ + "-x", "assembler-with-cpp", + ], CFLAGS=["-std=gnu99"], @@ -60,6 +65,3 @@ "-Wl,--gc-sections" ] ) - -# copy CCFLAGS to ASFLAGS (-x assembler-with-cpp mode) -env.Append(ASFLAGS=env.get("CCFLAGS", [])[:]) diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index 63add2202..5469e3bce 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -102,19 +102,22 @@ def transform_to_asm(target, source, env): return files, source +mcu = board.get("build.mcu", "esp32") env.Append( BUILDERS=dict( TxtToBin=Builder( action=env.VerboseAction( " ".join( [ - "xtensa-%s-elf-objcopy" % board.get("build.mcu", "esp32"), + "riscv32-esp-elf-objcopy" + if mcu == "esp32c3" + else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", - "elf32-xtensa-le", + "elf32-littleriscv" if mcu == "esp32c3" else "elf32-xtensa-le", "--binary-architecture", - "xtensa", + "riscv" if mcu == "esp32c3" else "xtensa", "--rename-section", ".data=.rodata.embedded", "$SOURCE", diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 161ad70ee..c6fc754a6 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -41,3 +41,4 @@ SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) + env["IDE_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 425d02bc9..8e790205c 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -50,14 +50,24 @@ idf_variant = mcu.lower() FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") -TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" - % ( - "riscv32-esp" - if mcu == "esp32c3" - else ("xtensa-%s" % mcu) +if "darwin" in get_systype() and "arm64" in get_systype(): + TOOLCHAIN_DIR = platform.get_package_dir( + "toolchain-%s" + % ( + "riscv32-esp-arm" + if mcu == "esp32c3" + else ("xtensa-%s-arm" % mcu) + ) + ) +if not "arm64" in get_systype(): + TOOLCHAIN_DIR = platform.get_package_dir( + "toolchain-%s" + % ( + "riscv32-esp" + if mcu == "esp32c3" + else ("xtensa-%s" % mcu) + ) ) -) assert os.path.isdir(FRAMEWORK_DIR) assert os.path.isdir(TOOLCHAIN_DIR) @@ -272,13 +282,15 @@ def load_target_configurations(cmake_codemodel, cmake_api_reply_dir): return configs -def build_library(default_env, lib_config, project_src_dir, prepend_dir=None): +def build_library( + default_env, lib_config, project_src_dir, prepend_dir=None, debug_allowed=True +): lib_name = lib_config["nameOnDisk"] lib_path = lib_config["paths"]["build"] if prepend_dir: lib_path = os.path.join(prepend_dir, lib_path) lib_objects = compile_source_files( - lib_config, default_env, project_src_dir, prepend_dir + lib_config, default_env, project_src_dir, prepend_dir, debug_allowed ) return default_env.Library( target=os.path.join("$BUILD_DIR", lib_path, lib_name), source=lib_objects @@ -584,14 +596,11 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): ) -def prepare_build_envs(config, default_env): +def prepare_build_envs(config, default_env, debug_allowed=True): build_envs = [] target_compile_groups = config.get("compileGroups") - is_build_type_debug = ( - set(["debug", "sizedata"]) & set(COMMAND_LINE_TARGETS) - or default_env.GetProjectOption("build_type") == "debug" - ) + is_build_type_debug = "debug" in env.GetBuildType() and debug_allowed for cg in target_compile_groups: includes = [] sys_includes = [] @@ -612,7 +621,6 @@ def prepare_build_envs(config, default_env): build_env.AppendUnique(CPPDEFINES=defines, CPPPATH=includes) if sys_includes: build_env.Append(CCFLAGS=[("-isystem", inc) for inc in sys_includes]) - build_env.Append(ASFLAGS=build_env.get("CCFLAGS", [])[:]) build_env.ProcessUnFlags(default_env.get("BUILD_UNFLAGS")) if is_build_type_debug: build_env.ConfigureDebugFlags() @@ -621,8 +629,8 @@ def prepare_build_envs(config, default_env): return build_envs -def compile_source_files(config, default_env, project_src_dir, prepend_dir=None): - build_envs = prepare_build_envs(config, default_env) +def compile_source_files(config, default_env, project_src_dir, prepend_dir=None, debug_allowed=True): + build_envs = prepare_build_envs(config, default_env, debug_allowed) objects = [] components_dir = fs.to_unix_path(os.path.join(FRAMEWORK_DIR, "components")) for source in config.get("sources", []): @@ -751,7 +759,7 @@ def fix_ld_paths(extra_flags): return extra_flags -def build_bootloader(): +def build_bootloader(sdk_config): bootloader_src_dir = os.path.join( FRAMEWORK_DIR, "components", "bootloader", "subproject" ) @@ -791,7 +799,15 @@ def build_bootloader(): target_configs, ["STATIC_LIBRARY", "OBJECT_LIBRARY"] ) - build_components(bootloader_env, components_map, bootloader_src_dir, "bootloader") + # Note: By default the size of bootloader is limited to 0x2000 bytes, + # in debug mode the footprint size can be easily grow beyond this limit + build_components( + bootloader_env, + components_map, + bootloader_src_dir, + "bootloader", + debug_allowed=sdk_config.get("BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG", False), + ) link_args = extract_link_args(elf_config) extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) extra_flags = fix_ld_paths(extra_flags) @@ -837,10 +853,12 @@ def get_components_map(target_configs, target_types, ignore_components=None): return result -def build_components(env, components_map, project_src_dir, prepend_dir=None): +def build_components( + env, components_map, project_src_dir, prepend_dir=None, debug_allowed=True +): for k, v in components_map.items(): components_map[k]["lib"] = build_library( - env, v["config"], project_src_dir, prepend_dir + env, v["config"], project_src_dir, prepend_dir, debug_allowed ) @@ -1283,7 +1301,7 @@ def _get_installed_pip_packages(): # Compile bootloader # -env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", build_bootloader()) +env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", build_bootloader(sdk_config)) # # Target: ESP-IDF menuconfig diff --git a/builder/frameworks/pumbaa.py b/builder/frameworks/pumbaa.py deleted file mode 100644 index c9b77c0df..000000000 --- a/builder/frameworks/pumbaa.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2014-present PlatformIO -# -# 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. - -"""Pumbaa - -Pumbaa is Python on top of Simba. - -The implementation is a port of MicroPython, designed for embedded -devices with limited amount of RAM and code memory. - -http://pumbaa.readthedocs.org - -""" - -from os.path import join, sep - -from SCons.Script import DefaultEnvironment, SConscript - -from platformio.builder.tools import platformio as platformio_tool - -# -# Backward compatibility with PlatformIO 2.0 -# -platformio_tool.SRC_DEFAULT_FILTER = " ".join([ - "+<*>", "-<.git%s>" % sep, "-" % sep, - "-" % sep, "-" % sep, - "-" % sep, "-" % sep -]) - - -def LookupSources(env, variant_dir, src_dir, duplicate=True, src_filter=None): - return env.CollectBuildFiles(variant_dir, src_dir, src_filter, duplicate) - - -def VariantDirWrap(env, variant_dir, src_dir, duplicate=False): - env.VariantDir(variant_dir, src_dir, duplicate) - - -env = DefaultEnvironment() - -env.AddMethod(LookupSources) -env.AddMethod(VariantDirWrap) - -env.Replace( - PLATFORMFW_DIR=env.PioPlatform().get_package_dir("framework-pumbaa"), - UPLOADERFLAGS=[] # Backward compatibility for obsolete build script -) - -SConscript( - [env.subst(join("$PLATFORMFW_DIR", "make", "platformio.sconscript"))]) - -env.Replace( - FLASH_EXTRA_IMAGES=[ - ("0x1000", join("$PLATFORMFW_DIR", "simba", "3pp", "esp32", - "bin", "bootloader.bin")), - ("0x8000", join("$PLATFORMFW_DIR", "simba", "3pp", "esp32", - "bin", "partitions_singleapp.bin")) - ] -) diff --git a/builder/frameworks/simba.py b/builder/frameworks/simba.py deleted file mode 100644 index 0def12da6..000000000 --- a/builder/frameworks/simba.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2014-present PlatformIO -# -# 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. - -"""Simba - -Simba is an RTOS and build framework. It aims to make embedded -programming easy and portable. - -http://simba-os.readthedocs.org - -""" - -from os.path import join, sep - -from SCons.Script import DefaultEnvironment, SConscript - -from platformio.builder.tools import platformio as platformio_tool - -# -# Backward compatibility with PlatformIO 2.0 -# -platformio_tool.SRC_DEFAULT_FILTER = " ".join([ - "+<*>", "-<.git%s>" % sep, "-" % sep, - "-" % sep, "-" % sep, - "-" % sep, "-" % sep -]) - - -def LookupSources(env, variant_dir, src_dir, duplicate=True, src_filter=None): - return env.CollectBuildFiles(variant_dir, src_dir, src_filter, duplicate) - - -def VariantDirWrap(env, variant_dir, src_dir, duplicate=False): - env.VariantDir(variant_dir, src_dir, duplicate) - - -env = DefaultEnvironment() - -env.AddMethod(LookupSources) -env.AddMethod(VariantDirWrap) - -env.Replace( - PLATFORMFW_DIR=env.PioPlatform().get_package_dir("framework-simba"), - UPLOADERFLAGS=[] # Backward compatibility for obsolete build script -) - -SConscript( - [env.subst(join("$PLATFORMFW_DIR", "make", "platformio.sconscript"))]) - -env.Replace( - FLASH_EXTRA_IMAGES=[ - ("0x1000", join("$PLATFORMFW_DIR", "3pp", "esp32", - "bin", "bootloader.bin")), - ("0x8000", join("$PLATFORMFW_DIR", "3pp", "esp32", - "bin", "partitions_singleapp.bin")) - ] -) diff --git a/builder/main.py b/builder/main.py index 58912d2a4..bbfa4f49f 100644 --- a/builder/main.py +++ b/builder/main.py @@ -20,11 +20,28 @@ ARGUMENTS, COMMAND_LINE_TARGETS, AlwaysBuild, Builder, Default, DefaultEnvironment) +from platformio.util import get_serial_ports + # # Helpers # +def BeforeUpload(target, source, env): + upload_options = {} + if "BOARD" in env: + upload_options = env.BoardConfig().get("upload", {}) + + env.AutodetectUploadPort() + + before_ports = get_serial_ports() + if upload_options.get("use_1200bps_touch", False): + env.TouchSerialPort("$UPLOAD_PORT", 1200) + + if upload_options.get("wait_for_upload_port", False): + env.Replace(UPLOAD_PORT=env.WaitForNewSerialPort(before_ports)) + + def _get_board_f_flash(env): frequency = env.subst("$BOARD_F_FLASH") frequency = str(frequency).replace("L", "") @@ -40,6 +57,10 @@ def _get_board_flash_mode(env): return mode +def _get_board_boot_mode(env): + return env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE") + + def _parse_size(value): if isinstance(value, int): return value @@ -63,6 +84,7 @@ def _parse_partitions(env): result = [] next_offset = 0 + bound = 0x10000 # default value with open(partitions_csv) as fp: for line in fp.readlines(): line = line.strip() @@ -80,13 +102,14 @@ def _parse_partitions(env): "flags": tokens[5] if len(tokens) > 5 else None } result.append(partition) - next_offset = _parse_size(partition["offset"]) + _parse_size( - partition["size"] - ) - - bound = 0x10000 if partition["type"] in ("0", "app") else 4 + next_offset = _parse_size(partition["offset"]) + #print("App start from .csv:", hex(next_offset)) + #print("Partition subtype from .csv:", partition["subtype"]) + if (partition["subtype"] == "ota_0"): + bound = next_offset next_offset = (next_offset + bound - 1) & ~(bound - 1) - + #print("Main Firmware will be flashed to:", hex(bound)) + env["ESP32_APP_OFFSET"] = hex(bound) return result @@ -94,63 +117,62 @@ def _update_max_upload_size(env): if not env.get("PARTITIONS_TABLE_CSV"): return sizes = [ - _parse_size(p['size']) for p in _parse_partitions(env) - if p['type'] in ("0", "app") + _parse_size(p["size"]) for p in _parse_partitions(env) + if p["type"] in ("0", "app") ] if sizes: board.update("upload.maximum_size", max(sizes)) def _to_unix_slashes(path): - return path.replace('\\', '/') + return path.replace("\\", "/") # -# FS helpers +# Filesystem helpers # -env = DefaultEnvironment() -env.SConscript("compat.py", exports="env") -platform = env.PioPlatform() -board = env.BoardConfig() -filesystem = board.get("build.filesystem", "spiffs") -print("FILESYSTEM ", filesystem) -mcu = board.get("build.mcu", "esp32") -toolchain_arch = "xtensa-%s" % mcu -if mcu == "esp32c3": - toolchain_arch = "riscv32-esp" def fetch_fs_size(env): fs = None for p in _parse_partitions(env): - # The option to use a partition subtype of "spiffs" eliminates the - # need to simultaneously update both this platform code and the - # framework code that handles partitions. You can use a framwork - # that only supports partitions named "spiffs", putting a LittleFS - # image therein. Going forward, the framework code can be updated - # to support partitions named "littlefs" and the code here will - # continue to work. - if p['type'] == "data" and (p['subtype'] == filesystem or p['subtype'] == "spiffs"): + if p["type"] == "data" and p["subtype"] in ("spiffs", "fat"): fs = p if not fs: sys.stderr.write( - "Could not find the `%s` section in the partitions " - "table %s\n" % (filesystem, env.subst("$PARTITIONS_TABLE_CSV")) + "Could not find the any filesystem section in the partitions " + "table %s\n" % env.subst("$PARTITIONS_TABLE_CSV") ) env.Exit(1) return - env["FS_START"] = _parse_size(fs['offset']) - env["FS_SIZE"] = _parse_size(fs['size']) + env["FS_START"] = _parse_size(fs["offset"]) + env["FS_SIZE"] = _parse_size(fs["size"]) env["FS_PAGE"] = int("0x100", 16) env["FS_BLOCK"] = int("0x1000", 16) + # FFat specific offsets, see: + # https://github.com/lorol/arduino-esp32fatfs-plugin#notes-for-fatfs + if filesystem == "fatfs": + env["FS_START"] += 4096 + env["FS_SIZE"] -= 4096 + def __fetch_fs_size(target, source, env): fetch_fs_size(env) return (target, source) +env = DefaultEnvironment() +platform = env.PioPlatform() +board = env.BoardConfig() +mcu = board.get("build.mcu", "esp32") +toolchain_arch = "xtensa-%s" % mcu +filesystem = board.get("build.filesystem", "spiffs") +if mcu == "esp32c3": + toolchain_arch = "riscv32-esp" + env.Replace( + __get_board_boot_mode=_get_board_boot_mode, __get_board_f_flash=_get_board_f_flash, __get_board_flash_mode=_get_board_flash_mode, @@ -177,11 +199,25 @@ def __fetch_fs_size(target, source, env): ], ERASECMD='"$PYTHONEXE" "$OBJCOPY" $ERASEFLAGS erase_flash', - MKFSTOOL=("mklittlefs" if filesystem == "littlefs" else - "mkspiffs_${PIOPLATFORM}_" + ("espidf" if "espidf" in env.subst("$PIOFRAMEWORK") else "${PIOFRAMEWORK}")), - ESP32_FS_IMAGE_NAME=env.get("ESP32_FS_IMAGE_NAME", env.get( - "ESP32_SPIFFS_IMAGE_NAME", filesystem)), - ESP32_APP_OFFSET="0x10000", + # mkspiffs package contains two different binaries for IDF and Arduino + MKFSTOOL="mk%s" % filesystem + + ( + ( + "_${PIOPLATFORM}_" + + ( + "espidf" + if "espidf" in env.subst("$PIOFRAMEWORK") + else "${PIOFRAMEWORK}" + ) + ) + if filesystem == "spiffs" + else "" + ), + # Legacy `ESP32_SPIFFS_IMAGE_NAME` is used as the second fallback value for + # backward compatibility + ESP32_FS_IMAGE_NAME=env.get( + "ESP32_FS_IMAGE_NAME", env.get("ESP32_SPIFFS_IMAGE_NAME", filesystem) + ), PROGSUFFIX=".elf" ) @@ -191,15 +227,11 @@ def __fetch_fs_size(target, source, env): env.Replace(PROGNAME="firmware") env.Append( - # copy CCFLAGS to ASFLAGS (-x assembler-with-cpp mode) - ASFLAGS=env.get("CCFLAGS", [])[:], - BUILDERS=dict( ElfToBin=Builder( action=env.VerboseAction(" ".join([ '"$PYTHONEXE" "$OBJCOPY"', - "--chip", mcu, - "elf2image", + "--chip", mcu, "elf2image", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "detect"), @@ -208,18 +240,27 @@ def __fetch_fs_size(target, source, env): suffix=".bin" ), DataToBin=Builder( - action=env.VerboseAction(" ".join([ - '"$MKFSTOOL"', - "-c", "$SOURCES", - "-p", "$FS_PAGE", - "-b", "$FS_BLOCK", - "-s", "$FS_SIZE", - "$TARGET" - ]), "Building FS image from '$SOURCES' directory to $TARGET"), + action=env.VerboseAction( + " ".join( + ['"$MKFSTOOL"', "-c", "$SOURCES", "-s", "$FS_SIZE"] + + ( + [ + "-p", + "$FS_PAGE", + "-b", + "$FS_BLOCK", + ] + if filesystem in ("spiffs", "littlefs") + else [] + ) + + ["$TARGET"] + ), + "Building FS image from '$SOURCES' directory to $TARGET", + ), emitter=__fetch_fs_size, source_factory=env.Dir, - suffix=".bin" - ) + suffix=".bin", + ), ) ) @@ -241,11 +282,9 @@ def __fetch_fs_size(target, source, env): else: target_elf = env.BuildProgram() if set(["buildfs", "uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): - if filesystem not in ("littlefs", "spiffs"): - sys.stderr.write("Filesystem %s is not supported!\n" % filesystem) - env.Exit(1) target_firm = env.DataToBin( - join("$BUILD_DIR", "${ESP32_SPIFFS_IMAGE_NAME}"), "$PROJECT_DATA_DIR") + join("$BUILD_DIR", "${ESP32_FS_IMAGE_NAME}"), "$PROJECT_DATA_DIR" + ) env.NoCache(target_firm) AlwaysBuild(target_firm) else: @@ -281,7 +320,7 @@ def __fetch_fs_size(target, source, env): ) # -# Target: Upload firmware or filesystem image +# Target: Upload firmware or FS image # upload_protocol = env.subst("$UPLOAD_PROTOCOL") @@ -315,7 +354,7 @@ def __fetch_fs_size(target, source, env): UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS -f $SOURCE' ) if set(["uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): - env.Append(UPLOADERFLAGS=["-s"]) + env.Append(UPLOADERFLAGS=["--spiffs"]) upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")] elif upload_protocol == "esptool": @@ -331,7 +370,7 @@ def __fetch_fs_size(target, source, env): "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", "detect" + "--flash_size", board.get("upload.flash_size", "detect") ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE' ) @@ -355,8 +394,7 @@ def __fetch_fs_size(target, source, env): ) upload_actions = [ - env.VerboseAction(env.AutodetectUploadPort, - "Looking for upload port..."), + env.VerboseAction(BeforeUpload, "Looking for upload port..."), env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE") ] @@ -392,18 +430,28 @@ def __fetch_fs_size(target, source, env): openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)] openocd_args.extend( debug_tools.get(upload_protocol).get("server").get("arguments", [])) - openocd_args.extend([ - "-c", "adapter_khz %s" % env.GetProjectOption("debug_speed", "5000"), - "-c", - "program_esp {{$SOURCE}} %s verify" % - board.get("upload.offset_address", "$ESP32_APP_OFFSET"), - ]) - for image in env.get("FLASH_EXTRA_IMAGES", []): - openocd_args.extend([ + openocd_args.extend( + [ "-c", - 'program_esp {{%s}} %s verify' % - (_to_unix_slashes(image[1]), image[0]) - ]) + "adapter_khz %s" % env.GetProjectOption("debug_speed", "5000"), + "-c", + "program_esp {{$SOURCE}} %s verify" + % ( + "$FS_START" + if "uploadfs" in COMMAND_LINE_TARGETS + else "$ESP32_APP_OFFSET" + ), + ] + ) + if "uploadfs" not in COMMAND_LINE_TARGETS: + for image in env.get("FLASH_EXTRA_IMAGES", []): + openocd_args.extend( + [ + "-c", + "program_esp {{%s}} %s verify" + % (_to_unix_slashes(image[1]), image[0]), + ] + ) openocd_args.extend(["-c", "reset run; shutdown"]) openocd_args = [ f.replace( @@ -412,9 +460,11 @@ def __fetch_fs_size(target, source, env): platform.get_package_dir("tool-openocd-esp32") or "")) for f in openocd_args ] - env.Replace(UPLOADER="openocd", - UPLOADERFLAGS=openocd_args, - UPLOADCMD="$UPLOADER $UPLOADERFLAGS") + env.Replace( + UPLOADER="openocd", + UPLOADERFLAGS=openocd_args, + UPLOADCMD="$UPLOADER $UPLOADERFLAGS", + ) upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")] # custom upload tool diff --git a/examples/pumbaa-blink/.gitignore b/examples/arduino-ble5-advertising/.gitignore old mode 100755 new mode 100644 similarity index 100% rename from examples/pumbaa-blink/.gitignore rename to examples/arduino-ble5-advertising/.gitignore diff --git a/examples/arduino-ble5-advertising/README.md b/examples/arduino-ble5-advertising/README.md new file mode 100644 index 000000000..f34cc0db8 --- /dev/null +++ b/examples/arduino-ble5-advertising/README.md @@ -0,0 +1,27 @@ +How to build PlatformIO based project +===================================== + +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) +2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) +3. Extract ZIP archive +4. Run these commands: + +```shell +# Change directory to example +$ cd platform-espressif32/examples/arduino-ble5-advertising + +# Build project +$ pio run + +# Upload firmware +$ pio run --target upload + +# Build specific environment +$ pio run -e esp32-c3-devkitm-1 + +# Upload firmware for the specific environment +$ pio run -e esp32-c3-devkitm-1 --target upload + +# Clean build files +$ pio run --target clean +``` \ No newline at end of file diff --git a/examples/pumbaa-blink/include/README b/examples/arduino-ble5-advertising/include/README similarity index 100% rename from examples/pumbaa-blink/include/README rename to examples/arduino-ble5-advertising/include/README diff --git a/examples/pumbaa-blink/lib/README b/examples/arduino-ble5-advertising/lib/README similarity index 100% rename from examples/pumbaa-blink/lib/README rename to examples/arduino-ble5-advertising/lib/README diff --git a/examples/pumbaa-blink/platformio.ini b/examples/arduino-ble5-advertising/platformio.ini old mode 100755 new mode 100644 similarity index 67% rename from examples/pumbaa-blink/platformio.ini rename to examples/arduino-ble5-advertising/platformio.ini index da2c58b75..638c205b6 --- a/examples/pumbaa-blink/platformio.ini +++ b/examples/arduino-ble5-advertising/platformio.ini @@ -5,9 +5,10 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html -[env:nano32] +[env:esp32-c3-devkitm-1] platform = espressif32 -framework = pumbaa -board = nano32 +board = esp32-c3-devkitm-1 +framework = arduino +monitor_speed = 115200 diff --git a/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino b/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino new file mode 100644 index 000000000..1b36bbb8b --- /dev/null +++ b/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino @@ -0,0 +1,72 @@ +/* + Simple BLE5 multi advertising example on esp32 C3/S3 + only ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED can be used for periodic advertising + + author: chegewara +*/ + +#include +#include + + +esp_ble_gap_ext_adv_params_t ext_adv_params_2M = { + .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED, + .interval_min = 0x40, + .interval_max = 0x40, + .channel_map = ADV_CHNL_ALL, + .own_addr_type = BLE_ADDR_TYPE_RANDOM, + .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + .primary_phy = ESP_BLE_GAP_PHY_1M, + .max_skip = 0, + .secondary_phy = ESP_BLE_GAP_PHY_2M, + .sid = 1, + .scan_req_notif = false, +}; + +static uint8_t raw_scan_rsp_data_2m[] = { + 0x02, 0x01, 0x06, + 0x02, 0x0a, 0xeb, + 0x12, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', + 'D', 'V', '_', '2', 'M', 0X0 +}; + +static esp_ble_gap_periodic_adv_params_t periodic_adv_params = { + .interval_min = 0x320, // 1000 ms interval + .interval_max = 0x640, + .properties = 0, // Do not include TX power +}; + +static uint8_t periodic_adv_raw_data[] = { + 0x02, 0x01, 0x06, + 0x02, 0x0a, 0xeb, + 0x03, 0x03, 0xab, 0xcd, + 0x11, 0x09, 'E', 'S', 'P', '_', 'P', 'E', 'R', 'I', 'O', 'D', 'I', + 'C', '_', 'A', 'D', 'V' +}; + + +uint8_t addr_2m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x02}; + +BLEMultiAdvertising advert(1); // max number of advertisement data + +void setup() { + Serial.begin(115200); + Serial.println("Multi-Advertising..."); + + BLEDevice::init(""); + + advert.setAdvertisingParams(0, &ext_adv_params_2M); + advert.setAdvertisingData(0, sizeof(raw_scan_rsp_data_2m), &raw_scan_rsp_data_2m[0]); + advert.setInstanceAddress(0, addr_2m); + advert.setDuration(0, 0, 0); + + delay(100); + advert.start(); + advert.setPeriodicAdvertisingParams(0, &periodic_adv_params); + advert.setPeriodicAdvertisingData(0, sizeof(periodic_adv_raw_data), &periodic_adv_raw_data[0]); + advert.startPeriodicAdvertising(0); +} + +void loop() { + delay(2000); +} diff --git a/examples/pumbaa-blink/test/README b/examples/arduino-ble5-advertising/test/README similarity index 100% rename from examples/pumbaa-blink/test/README rename to examples/arduino-ble5-advertising/test/README diff --git a/examples/simba-blink/.gitignore b/examples/arduino-usb-keyboard/.gitignore old mode 100755 new mode 100644 similarity index 100% rename from examples/simba-blink/.gitignore rename to examples/arduino-usb-keyboard/.gitignore diff --git a/examples/arduino-usb-keyboard/README.md b/examples/arduino-usb-keyboard/README.md new file mode 100644 index 000000000..e9bd6a20e --- /dev/null +++ b/examples/arduino-usb-keyboard/README.md @@ -0,0 +1,27 @@ +How to build PlatformIO based project +===================================== + +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) +2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) +3. Extract ZIP archive +4. Run these commands: + +```shell +# Change directory to example +$ cd platform-espressif32/examples/arduino-usb-keyboard + +# Build project +$ pio run + +# Upload firmware +$ pio run --target upload + +# Build specific environment +$ pio run -e esp32-s2-saola-1 + +# Upload firmware for the specific environment +$ pio run -e esp32-s2-saola-1 --target upload + +# Clean build files +$ pio run --target clean +``` \ No newline at end of file diff --git a/examples/simba-blink/include/README b/examples/arduino-usb-keyboard/include/README similarity index 100% rename from examples/simba-blink/include/README rename to examples/arduino-usb-keyboard/include/README diff --git a/examples/simba-blink/lib/README b/examples/arduino-usb-keyboard/lib/README similarity index 100% rename from examples/simba-blink/lib/README rename to examples/arduino-usb-keyboard/lib/README diff --git a/examples/simba-blink/platformio.ini b/examples/arduino-usb-keyboard/platformio.ini old mode 100755 new mode 100644 similarity index 60% rename from examples/simba-blink/platformio.ini rename to examples/arduino-usb-keyboard/platformio.ini index 802ec5147..3f51b8378 --- a/examples/simba-blink/platformio.ini +++ b/examples/arduino-usb-keyboard/platformio.ini @@ -5,9 +5,15 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html -[env:nano32] +[env] platform = espressif32 -framework = simba -board = nano32 +framework = arduino +monitor_speed = 115200 + +[env:esp32-s2-saola-1] +board = esp32-s2-saola-1 + +[env:esp32-s2-kaluga-1] +board = esp32-s2-kaluga-1 \ No newline at end of file diff --git a/examples/arduino-usb-keyboard/src/KeyboardSerial.ino b/examples/arduino-usb-keyboard/src/KeyboardSerial.ino new file mode 100644 index 000000000..e3bb87697 --- /dev/null +++ b/examples/arduino-usb-keyboard/src/KeyboardSerial.ino @@ -0,0 +1,40 @@ +/* + Keyboard test + + Reads a byte from the serial port, sends a keystroke back. + The sent keystroke is one higher than what's received, e.g. if you send a, + you get b, send A you get B, and so forth. + + The circuit: + - none + + created 21 Oct 2011 + modified 27 Mar 2012 + by Tom Igoe + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/KeyboardSerial +*/ + +#include "USB.h" +#include "USBHIDKeyboard.h" +USBHIDKeyboard Keyboard; + +void setup() { + // open the serial port: + Serial.begin(115200); + // initialize control over the keyboard: + Keyboard.begin(); + USB.begin(); +} + +void loop() { + // check for incoming serial data: + if (Serial.available() > 0) { + // read incoming serial data: + char inChar = Serial.read(); + // Type the next ASCII value from what you received: + Keyboard.write(inChar + 1); + } +} diff --git a/examples/simba-blink/test/README b/examples/arduino-usb-keyboard/test/README similarity index 100% rename from examples/simba-blink/test/README rename to examples/arduino-usb-keyboard/test/README diff --git a/examples/pumbaa-blink/.skiptest b/examples/pumbaa-blink/.skiptest deleted file mode 100644 index 05e3ca046..000000000 --- a/examples/pumbaa-blink/.skiptest +++ /dev/null @@ -1 +0,0 @@ -.skiptest diff --git a/examples/pumbaa-blink/.travis.yml b/examples/pumbaa-blink/.travis.yml deleted file mode 100755 index 7c486f183..000000000 --- a/examples/pumbaa-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/pumbaa-blink/README.md b/examples/pumbaa-blink/README.md deleted file mode 100755 index 1de389c37..000000000 --- a/examples/pumbaa-blink/README.md +++ /dev/null @@ -1,18 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/pumbaa-blink - -# Process example project -$ pio run - -# Upload firmware -$ pio run --target upload -``` diff --git a/examples/pumbaa-blink/src/main.c b/examples/pumbaa-blink/src/main.c deleted file mode 100755 index c43d5310e..000000000 --- a/examples/pumbaa-blink/src/main.c +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @file main.c - * - * @section License - * Copyright (C) 2015-2016, Erik Moqvist - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * This file is part of the Pumbaa project. - */ - -/* - * This file is required by PlatformIO, but is unused in Pumbaa. - */ diff --git a/examples/pumbaa-blink/src/main.py b/examples/pumbaa-blink/src/main.py deleted file mode 100755 index fde1e231c..000000000 --- a/examples/pumbaa-blink/src/main.py +++ /dev/null @@ -1,40 +0,0 @@ -# -# @section License -# -# The MIT License (MIT) -# -# Copyright (c) 2016, Erik Moqvist -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, copy, -# modify, merge, publish, distribute, sublicense, and/or sell copies -# of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# This file is part of the Pumbaa project. -# - - -import time -import board -from drivers import Pin - -LED = Pin(board.PIN_LED, Pin.OUTPUT) - -while True: - LED.toggle() - time.sleep(0.5) diff --git a/examples/simba-blink/.travis.yml b/examples/simba-blink/.travis.yml deleted file mode 100755 index 7c486f183..000000000 --- a/examples/simba-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/simba-blink/README.md b/examples/simba-blink/README.md deleted file mode 100755 index 15437339b..000000000 --- a/examples/simba-blink/README.md +++ /dev/null @@ -1,18 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/simba-blink - -# Process example project -$ pio run - -# Upload firmware -$ pio run --target upload -``` \ No newline at end of file diff --git a/examples/simba-blink/src/main.c b/examples/simba-blink/src/main.c deleted file mode 100755 index 404ec637b..000000000 --- a/examples/simba-blink/src/main.c +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file main.c - * @version 4.1.0 - * - * @section License - * Copyright (C) 2015-2016, Erik Moqvist - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * This file is part of the Simba project. - */ - -#include "simba.h" - -int main() -{ - struct pin_driver_t led; - - /* Start the system. */ - sys_start(); - - /* Initialize the LED pin as output and set its value to 1. */ - pin_init(&led, &pin_led_dev, PIN_OUTPUT); - pin_write(&led, 1); - - while (1) { - /* Wait half a second. */ - thrd_sleep_us(500000); - - /* Toggle the LED on/off. */ - pin_toggle(&led); - } - - return (0); -} diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index 81c69c1ee..5feb28e17 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -17,67 +17,91 @@ import subprocess import sys -from platformio.compat import path_to_unicode, WINDOWS, PY2 from platformio.project.exception import PlatformioException -from platformio.project.helpers import load_project_ide_data -from platformio.commands.device import DeviceMonitorFilter +from platformio.public import ( + DeviceMonitorFilterBase, + load_build_metadata, +) # By design, __init__ is called inside miniterm and we can't pass context to it. # pylint: disable=attribute-defined-outside-init +IS_WINDOWS = sys.platform.startswith("win") -class Esp32ExceptionDecoder(DeviceMonitorFilter): + +class Esp32ExceptionDecoder(DeviceMonitorFilterBase) NAME = "esp32_exception_decoder" def __call__(self): self.buffer = "" - self.backtrace_re = re.compile( - r"^Backtrace: ?((0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8} ?)+)\s*" - ) + # regex matches potential PC value (0x4xxxxxxx) + # Logic identical to https://github.com/espressif/esp-idf/blob/master/tools/idf_monitor_base/constants.py#L56 + self.pcaddr_re = re.compile(r'0x4[0-9a-f]{7}', re.IGNORECASE) self.firmware_path = None self.addr2line_path = None self.enabled = self.setup_paths() - if self.config.get("env:" + self.environment, "build_type") != "debug": - print( + return self + + def setup_paths(self): + self.project_dir = os.path.abspath(self.project_dir) + + self.project_strip_dir = os.environ.get("esp32_exception_decoder_project_strip_dir") + self.firmware_path = os.environ.get("esp32_exception_decoder_firmware_path") + self.addr2line_path = os.environ.get("esp32_exception_decoder_addr2line_path") + + if self.project_strip_dir is None: + self.project_strip_dir = self.project_dir + + try: + if self.firmware_path is None or self.addr2line_path is None: + # Only load if necessary, as the call is expensive + data = load_build_metadata(self.project_dir, self.environment) + + if self.firmware_path is None: + # Only do this check when the firmware path is not externally provided + if self.config.get("env:" + self.environment, "build_type") != "debug": + print( """ Please build project in debug configuration to get more details about an exception. See https://docs.platformio.org/page/projectconf/build_configurations.html """ - ) - - return self + ) + self.firmware_path = data["prog_path"] - def setup_paths(self): - self.project_dir = path_to_unicode(os.path.abspath(self.project_dir)) - try: - data = load_project_ide_data(self.project_dir, self.environment) - self.firmware_path = data["prog_path"] if not os.path.isfile(self.firmware_path): sys.stderr.write( - "%s: firmware at %s does not exist, rebuild the project?\n" + "%s: disabling, firmware at %s does not exist, rebuild the project?\n" % (self.__class__.__name__, self.firmware_path) ) return False - cc_path = data.get("cc_path", "") - if "-gcc" in cc_path: - path = cc_path.replace("-gcc", "-addr2line") - if os.path.isfile(path): - self.addr2line_path = path - return True + if self.addr2line_path is None: + cc_path = data.get("cc_path", "") + if "-gcc" in cc_path: + self.addr2line_path = cc_path.replace("-gcc", "-addr2line") + else: + sys.stderr.write( + "%s: disabling, failed to find addr2line.\n" % self.__class__.__name__ + ) + return False + + if not os.path.isfile(self.addr2line_path): + sys.stderr.write( + "%s: disabling, addr2line at %s does not exist\n" + % (self.__class__.__name__, self.addr2line_path) + ) + return False + + return True except PlatformioException as e: sys.stderr.write( "%s: disabling, exception while looking for addr2line: %s\n" % (self.__class__.__name__, e) ) return False - sys.stderr.write( - "%s: disabling, failed to find addr2line.\n" % self.__class__.__name__ - ) - return False def rx(self, text): if not self.enabled: @@ -97,36 +121,36 @@ def rx(self, text): self.buffer = "" last = idx + 1 - m = self.backtrace_re.match(line) - if m is None: - continue + # Output each trace on a separate line below ours + # Logic identical to https://github.com/espressif/esp-idf/blob/master/tools/idf_monitor_base/logger.py#L131 + for m in re.finditer(self.pcaddr_re, line): + if m is None: + continue + + trace = self.get_backtrace(m) + if len(trace) != "": + text = text[: last] + trace + text[last :] + last += len(trace) - trace = self.get_backtrace(m) - if len(trace) != "": - text = text[: idx + 1] + trace + text[idx + 1 :] - last += len(trace) return text def get_backtrace(self, match): trace = "" - enc = "mbcs" if WINDOWS else "utf-8" + enc = "mbcs" if IS_WINDOWS else "utf-8" args = [self.addr2line_path, u"-fipC", u"-e", self.firmware_path] - if PY2: - args = [a.encode(enc) for a in args] try: - for i, addr in enumerate(match.group(1).split()): - if PY2: - addr = addr.encode(enc) - output = ( - subprocess.check_output(args + [addr]) - .decode(enc) - .strip() - ) - output = output.replace( - "\n", "\n " - ) # newlines happen with inlined methods - output = self.strip_project_dir(output) - trace += " #%-2d %s in %s\n" % (i, addr, output) + addr = match.group() + output = ( + subprocess.check_output(args + [addr]) + .decode(enc) + .strip() + ) + output = output.replace( + "\n", "\n " + ) # newlines happen with inlined methods + output = self.strip_project_dir(output) + # Output the trace in yellow color so that it is easier to spot + trace += "\033[33m=> %s: %s\033[0m\n" % (addr, output) except subprocess.CalledProcessError as e: sys.stderr.write( "%s: failed to call %s: %s\n" @@ -136,8 +160,8 @@ def get_backtrace(self, match): def strip_project_dir(self, trace): while True: - idx = trace.find(self.project_dir) + idx = trace.find(self.project_strip_dir) if idx == -1: break - trace = trace[:idx] + trace[idx + len(self.project_dir) + 1 :] + trace = trace[:idx] + trace[idx + len(self.project_strip_dir) + 1 :] return trace diff --git a/platform.json b/platform.json index 5d24186c8..3a9273729 100644 --- a/platform.json +++ b/platform.json @@ -9,10 +9,10 @@ "Wi-Fi", "Bluetooth", "Xtensa", - "LX6" + "RISC-V" ], "engines": { - "platformio": "^5" + "platformio": ">=6.0.2" }, "repository": { "type": "git", @@ -30,53 +30,20 @@ "description": "ESP-IDF is the official development framework for the ESP32 and ESP32-S Series SoCs.", "homepage": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32/", "title": "Espressif IoT Development Framework" - }, - "simba": { - "package": "framework-simba", - "script": "builder/frameworks/simba.py", - "description": "Simba is an RTOS and build framework with aims to make embedded programming easy and portable", - "homepage": "http://simba-os.readthedocs.org", - "title": "Simba" - }, - "pumbaa": { - "package": "framework-pumbaa", - "script": "builder/frameworks/pumbaa.py", - "description": "Pumbaa is Python on top of Simba. The implementation is a port of MicroPython, designed for embedded devices with limited amount of RAM and code memory", - "homepage": "http://pumbaa.readthedocs.org/", - "title": "Pumbaa" } }, "packages": { - "toolchain-xtensa32": { - "type": "toolchain", - "optional": true, - "owner": "platformio", - "version": "~2.50200.0", - "optionalVersions": ["~2.80400.0"] - }, - "toolchain-xtensa32s2": { - "type": "toolchain", - "optional": true, - "owner": "platformio", - "version": "~1.80400.0" - }, - "toolchain-esp32ulp": { - "type": "toolchain", - "optional": true, - "owner": "platformio", - "version": "~1.22851.0" - }, - "toolchain-esp32s2ulp": { - "type": "toolchain", + "framework-arduinoespressif32": { + "type": "framework", "optional": true, - "owner": "platformio", - "version": "~1.22851.0" + "owner": "tasmota", + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.3/framework-arduinoespressif32-203.tar.gz" }, - "toolchain-riscv-esp": { - "type": "toolchain", + "framework-espidf": { + "type": "framework", "optional": true, - "owner": "platformio", - "version": "~1.80400.0" + "owner": "tasmota", + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.1/esp-idf-v4.4.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -102,52 +69,58 @@ "owner": "espressif", "version": "8.4.0+2021r2-patch3" }, - "toolchain-esp32ulp": { + "toolchain-xtensa-esp32-arm": { "type": "toolchain", "optional": true, - "owner": "platformio", - "version": "~1.22851.0" + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32.tar.gz" }, - "toolchain-esp32s2ulp": { + "toolchain-xtensa-esp32s2-arm": { "type": "toolchain", "optional": true, - "owner": "platformio", - "version": "~1.22851.0" + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32s2.tar.gz" }, - "framework-arduinoespressif32": { - "type": "framework", + "toolchain-xtensa-esp32s3-arm": { + "type": "toolchain", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/803/framework-arduinoespressif32-v4.4_dev-40d126bfd1.tar.gz" + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32s3.tar.gz" }, - "framework-arduino-mbcwb": { - "type": "framework", + "toolchain-riscv32-esp-arm": { + "type": "toolchain", "optional": true, - "owner": "meteca", - "version": ">=2.1.1" + "owner": "tasmota", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-riscv32-esp.tar.gz" }, - "framework-espidf": { - "type": "framework", + "tool-openocd-esp32-arm": { + "type": "debugger", + "optional": true, + "owner": "tasmota", + "version": "https://github.com/Jason2866/openocd-esp32/releases/download/v0.11.0-esp32-20220404/openocd-esp32-macos-arm64-0.11.0-esp32-20220424.zip" + }, + "toolchain-esp32ulp": { + "type": "toolchain", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v.4.4.0/esp-idf-v4.4.zip" + "version": "~1.22851.0" }, - "framework-simba": { - "type": "framework", + "toolchain-esp32s2ulp": { + "type": "toolchain", "optional": true, "owner": "platformio", - "version": ">=12.2.0" + "version": "~1.22851.0" }, - "framework-pumbaa": { + "framework-arduino-mbcwb": { "type": "framework", "optional": true, - "owner": "platformio", - "version": ">=2.3.0" + "owner": "meteca", + "version": ">=2.1.1" }, "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v3.3/esptool-3.3.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.0.1/esptool-4.0.1.zip" }, "tool-mbctool": { "optional": true, @@ -158,7 +131,7 @@ "type": "debugger", "optional": true, "owner": "platformio", - "version": "~2.1000.0" + "version": "~2.1100.0" }, "tool-mkspiffs": { "type": "uploader", @@ -170,6 +143,12 @@ "owner": "platformio", "version": "~1.203.0" }, + "tool-mkfatfs": { + "type": "uploader", + "optional": true, + "owner": "platformio", + "version": "~2.0.0" + }, "tool-cmake": { "optional": true, "owner": "platformio", diff --git a/platform.py b/platform.py index c5c5d5082..7502c1935 100644 --- a/platform.py +++ b/platform.py @@ -12,82 +12,152 @@ # See the License for the specific language governing permissions and # limitations under the License. -import copy import os +import urllib +import sys +import json +import re +import requests -from platformio import fs -from platformio.managers.platform import PlatformBase +from platformio.public import PlatformBase, to_unix_path from platformio.util import get_systype +IS_WINDOWS = sys.platform.startswith("win") class Espressif32Platform(PlatformBase): def configure_default_packages(self, variables, targets): if not variables.get("board"): - return PlatformBase.configure_default_packages(self, variables, targets) + return super().configure_default_packages(variables, targets) board_config = self.board_config(variables.get("board")) mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32")) frameworks = variables.get("pioframework", []) + if "buildfs" in targets: - self.packages["tool-mkspiffs"]["optional"] = False - self.packages['tool-mklittlefs']['optional'] = False + filesystem = variables.get("board_build.filesystem", "spiffs") + if filesystem == "littlefs": + self.packages["tool-mklittlefs"]["optional"] = False + elif filesystem == "fatfs": + self.packages["tool-mkfatfs"]["optional"] = False + else: + self.packages["tool-mkspiffs"]["optional"] = False if variables.get("upload_protocol"): - self.packages["tool-openocd-esp32"]["optional"] = False + if "darwin" in get_systype() and "arm64" in get_systype(): + self.packages["tool-openocd-esp32-arm"]["optional"] = False + if not "arm64" in get_systype(): + self.packages["tool-openocd-esp32"]["optional"] = False if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False - xtensa_toolchain = "toolchain-xtensa-esp32" - xtensa32s2_toolchain = "toolchain-xtensa-esp32s2" - xtensa32s3_toolchain = "toolchain-xtensa-esp32s3" - riscv_toolchain = "toolchain-riscv32-esp" - + build_core = variables.get( + "board_build.core", board_config.get("build.core", "arduino") + ).lower() + + if len(frameworks) == 1 and "arduino" in frameworks and build_core == "esp32": + # In case the upstream Arduino framework is specified in the configuration + # file then we need to dynamically extract toolchain versions from the + # Arduino index file. This feature can be disabled via a special option: + if ( + variables.get( + "board_build.arduino.upstream_packages", + board_config.get("build.arduino.upstream_packages", "yes"), + ).lower() + == "yes" + ): + package_version = self.packages["framework-arduinoespressif32"][ + "version" + ] + + url_items = urllib.parse.urlparse(package_version) + # Only GitHub repositories support dynamic packages + if ( + url_items.scheme in ("http", "https") + and url_items.netloc.startswith("github") + and url_items.path.endswith(".git") + ): + try: + self.configure_upstream_arduino_packages(url_items) + except Exception as e: + sys.stderr.write( + "Error! Failed to extract upstream toolchain" + "configurations:\n%s\n" % str(e) + ) + sys.stderr.write( + "You can disable this feature via the " + "`board_build.arduino.upstream_packages = no` setting in " + "your `platformio.ini` file.\n" + ) + sys.exit(1) + if "espidf" in frameworks: + # Common package for IDF and mixed Arduino+IDF projects for p in self.packages: if p in ("tool-cmake", "tool-ninja", "toolchain-%sulp" % mcu): self.packages[p]["optional"] = False - elif p in ("tool-mconf", "tool-idf") and "windows" in get_systype(): + elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: self.packages[p]["optional"] = False - self.packages[xtensa_toolchain]["version"] = "8.4.0+2021r2-patch3" - self.packages[xtensa_toolchain]["optional"] = False - - if "arduino" in frameworks: - self.packages[xtensa_toolchain]["version"] = "8.4.0+2021r2-patch3" - self.packages[xtensa_toolchain]["optional"] = False - - if mcu in ("esp32s2", "esp32s3", "esp32c3"): - self.packages.pop(xtensa_toolchain, None) - self.packages.pop("toolchain-esp32ulp", None) - # RISC-V based toolchain for ESP32C3 and ESP32S2 ULP - self.packages[riscv_toolchain]["optional"] = False - if mcu == "esp32s2": - self.packages[xtensa32s2_toolchain]["optional"] = False - self.packages["toolchain-esp32s2ulp"]["optional"] = False - if mcu == "esp32s3": - self.packages[xtensa32s3_toolchain]["optional"] = False - self.packages["toolchain-esp32s2ulp"]["optional"] = False - build_core = variables.get( - "board_build.core", board_config.get("build.core", "arduino") - ).lower() - if "arduino" in frameworks and build_core == "mbcwb": - # Briki MCB core packages depend on previous toolchain packages - self.packages.pop("toolchain-xtensa-esp32", None) - self.packages["toolchain-xtensa32"]["optional"] = False - self.packages["toolchain-xtensa32"]["version"] = "~2.50200.0" - self.packages["framework-arduinoespressif32"]["optional"] = True - self.packages["framework-arduino-mbcwb"]["optional"] = False - self.packages["tool-mbctool"]["type"] = "uploader" - self.packages["tool-mbctool"]["optional"] = False - - if set(("simba", "pumbaa")) & set(frameworks): - # Legacy frameworks depend on previous toolchain packages - self.packages["toolchain-xtensa32"]["optional"] = False - self.packages["toolchain-xtensa32"]["version"] = "~2.50200.0" - - return PlatformBase.configure_default_packages(self, variables, targets) + if not "arm64" in get_systype(): + for available_mcu in ("esp32", "esp32s2", "esp32s3"): + if available_mcu == mcu: + self.packages["toolchain-xtensa-%s" % mcu]["optional"] = False + else: + self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) + + if mcu in ("esp32s2", "esp32s3", "esp32c3"): + self.packages.pop("toolchain-esp32ulp", None) + if mcu == "esp32" or mcu == "esp32c3": + self.packages.pop("toolchain-esp32s2ulp", None) + # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP + self.packages["toolchain-riscv32-esp"]["optional"] = False + + if "darwin" in get_systype() and "arm64" in get_systype(): + for available_mcu in ("esp32", "esp32s2", "esp32s3"): + if available_mcu == mcu: + self.packages["toolchain-xtensa-%s-arm" % mcu]["optional"] = False + else: + self.packages.pop("toolchain-xtensa-%s-arm" % available_mcu, None) + + if mcu in ("esp32s2", "esp32s3", "esp32c3"): + self.packages.pop("toolchain-esp32ulp", None) + if mcu == "esp32" or mcu == "esp32c3": + self.packages.pop("toolchain-esp32s2ulp", None) + # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP + self.packages["toolchain-riscv32-esp-arm"]["optional"] = False + + is_legacy_project = ( + build_core == "mbcwb" + ) + + if is_legacy_project: + # Remove the main toolchains from PATH + for toolchain in ( + "toolchain-xtensa-esp32", + "toolchain-xtensa-esp32s2", + "toolchain-xtensa-esp32s3", + "toolchain-riscv32-esp", + ): + self.packages.pop(toolchain, None) + + # Add legacy toolchain with specific version + self.packages["toolchain-xtensa32"] = { + "type": "toolchain", + "owner": "platformio", + "version": "~2.80400.0" + if "arduino" in frameworks and build_core != "mbcwb" + else "~2.50200.0", + } + + if build_core == "mbcwb": + self.packages["framework-arduinoespressif32"]["optional"] = True + self.packages["framework-arduino-mbcwb"]["optional"] = False + self.packages["tool-mbctool"]["type"] = "uploader" + self.packages["tool-mbctool"]["optional"] = False + + return super().configure_default_packages(variables, targets) def get_boards(self, id_=None): - result = PlatformBase.get_boards(self, id_) + result = super().get_boards(id_) if not result: return result if id_: @@ -108,7 +178,9 @@ def _add_dynamic_options(self, board): debug = board.manifest.get("debug", {}) non_debug_protocols = ["esptool", "espota", "mbctool"] supported_debug_tools = [ + "cmsis-dap", "esp-prog", + "esp_usb_jtag", "iot-bus-jtag", "jlink", "minimodule", @@ -135,7 +207,7 @@ def _add_dynamic_options(self, board): if link in non_debug_protocols or link in debug["tools"]: continue - if link == "jlink": + if link in ("jlink", "cmsis-dap", "esp_usb_jtag"): openocd_interface = link elif link in ("esp-prog", "ftdi"): if board.id == "esp32-s2-kaluga-1": @@ -206,53 +278,113 @@ def configure_debug_session(self, debug_config): load_cmds = [ 'monitor program_esp "{{{path}}}" {offset} verify'.format( - path=fs.to_unix_path(item["path"]), offset=item["offset"] + path=to_unix_path(item["path"]), offset=item["offset"] ) for item in flash_images ] load_cmds.append( 'monitor program_esp "{%s.bin}" %s verify' % ( - fs.to_unix_path(debug_config.build_data["prog_path"][:-4]), + to_unix_path(debug_config.build_data["prog_path"][:-4]), build_extra_data.get("application_offset", "0x10000"), ) ) debug_config.load_cmds = load_cmds - def configure_debug_options(self, initial_debug_options, ide_data): - """ - Deprecated. Remove method when PlatformIO Core 5.2 is released - """ - ide_extra_data = ide_data.get("extra", {}) - flash_images = ide_extra_data.get("flash_images", []) - debug_options = copy.deepcopy(initial_debug_options) - - if "openocd" in debug_options["server"].get("executable", ""): - debug_options["server"]["arguments"].extend( - ["-c", "adapter_khz %s" % (initial_debug_options.get("speed") or "5000")] + @staticmethod + def extract_toolchain_versions(tool_deps): + def _parse_version(original_version): + assert original_version + match = re.match(r"^gcc(\d+)_(\d+)_(\d+)\-esp\-(.+)$", original_version) + if not match: + raise ValueError("Bad package version `%s`" % original_version) + assert len(match.groups()) == 4 + return "%s.%s.%s+%s" % (match.groups()) + + if not tool_deps: + raise ValueError( + ("Failed to extract tool dependencies from the remote package file") ) - ignore_conds = [ - initial_debug_options["load_cmds"] != ["load"], - not flash_images, - not all([os.path.isfile(item["path"]) for item in flash_images]), - ] + toolchain_remap = { + "xtensa-esp32-elf-gcc": "toolchain-xtensa-esp32", + "xtensa-esp32s2-elf-gcc": "toolchain-xtensa-esp32s2", + "xtensa-esp32s3-elf-gcc": "toolchain-xtensa-esp32s3", + "riscv32-esp-elf-gcc": "toolchain-riscv32-esp", + } - if any(ignore_conds): - return debug_options + result = dict() + for tool in tool_deps: + if tool["name"] in toolchain_remap: + result[toolchain_remap[tool["name"]]] = _parse_version(tool["version"]) - load_cmds = [ - 'monitor program_esp "{{{path}}}" {offset} verify'.format( - path=fs.to_unix_path(item["path"]), offset=item["offset"] + return result + + @staticmethod + def parse_tool_dependencies(index_data): + for package in index_data.get("packages", []): + if package["name"] == "esp32": + for platform in package["platforms"]: + if platform["name"] == "esp32": + return platform["toolsDependencies"] + + return [] + + @staticmethod + def download_remote_package_index(url_items): + def _prepare_url_for_index_file(url_items): + tag = "master" + if url_items.fragment: + tag = url_items.fragment + return ( + "https://raw.githubusercontent.com/%s/" + "%s/package/package_esp32_index.template.json" + % (url_items.path.replace(".git", ""), tag) ) - for item in flash_images - ] - load_cmds.append( - 'monitor program_esp "{%s.bin}" %s verify' - % ( - fs.to_unix_path(ide_data["prog_path"][:-4]), - ide_extra_data.get("application_offset", "0x10000"), + + index_file_url = _prepare_url_for_index_file(url_items) + r = requests.get(index_file_url, timeout=10) + if r.status_code != 200: + raise ValueError( + ( + "Failed to download package index file due to a bad response (%d) " + "from the remote `%s`" + ) + % (r.status_code, index_file_url) ) + return r.json() + + def configure_arduino_toolchains(self, package_index): + if not package_index: + return + + toolchain_packages = self.extract_toolchain_versions( + self.parse_tool_dependencies(package_index) ) - debug_options["load_cmds"] = load_cmds - return debug_options + for toolchain_package, version in toolchain_packages.items(): + if toolchain_package not in self.packages: + self.packages[toolchain_package] = dict() + self.packages[toolchain_package]["version"] = version + self.packages[toolchain_package]["owner"] = "espressif" + self.packages[toolchain_package]["type"] = "toolchain" + + def configure_upstream_arduino_packages(self, url_items): + framework_index_file = os.path.join( + self.get_package_dir("framework-arduinoespressif32") or "", + "package", + "package_esp32_index.template.json", + ) + + # Detect whether the remote is already cloned + if os.path.isfile(framework_index_file) and os.path.isdir( + os.path.join( + self.get_package_dir("framework-arduinoespressif32") or "", ".git" + ) + ): + with open(framework_index_file) as fp: + self.configure_arduino_toolchains(json.load(fp)) + else: + print("Configuring toolchain packages from a remote source...") + self.configure_arduino_toolchains( + self.download_remote_package_index(url_items) + ) From 4934c12d4ab7a4f8e03d7a88d2bcfb9cff00dfec Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 4 Jun 2022 17:08:22 +0200 Subject: [PATCH 057/666] Add misso --- monitor/filter_exception_decoder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index 5feb28e17..a580550c9 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -29,7 +29,7 @@ IS_WINDOWS = sys.platform.startswith("win") -class Esp32ExceptionDecoder(DeviceMonitorFilterBase) +class Esp32ExceptionDecoder(DeviceMonitorFilterBase): NAME = "esp32_exception_decoder" def __call__(self): From 3f4bdfb3323c3126dc10861bab6c6ee5d5628677 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 4 Jun 2022 17:09:41 +0200 Subject: [PATCH 058/666] Missing `:` in class def --- monitor/filter_exception_decoder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index 5feb28e17..a580550c9 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -29,7 +29,7 @@ IS_WINDOWS = sys.platform.startswith("win") -class Esp32ExceptionDecoder(DeviceMonitorFilterBase) +class Esp32ExceptionDecoder(DeviceMonitorFilterBase): NAME = "esp32_exception_decoder" def __call__(self): From 05340d54fd7c035086c4e1d1ec871cdf3867835d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 10 Jun 2022 08:45:56 +0200 Subject: [PATCH 059/666] Esptool v4.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 3a9273729..cc7be0348 100644 --- a/platform.json +++ b/platform.json @@ -120,7 +120,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.0.1/esptool-4.0.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.0.1.zip" }, "tool-mbctool": { "optional": true, From 896fee3c7aa6682f0b26e4e948c917e5b5863bed Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 10 Jun 2022 08:46:56 +0200 Subject: [PATCH 060/666] Esptool v4.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 3a9273729..cc7be0348 100644 --- a/platform.json +++ b/platform.json @@ -120,7 +120,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.0.1/esptool-4.0.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.0.1.zip" }, "tool-mbctool": { "optional": true, From a7f9e968a3bf8d1d9cb96f7bd135a031c8af552f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 10 Jun 2022 08:59:33 +0200 Subject: [PATCH 061/666] really Esptool v4.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index cc7be0348..2206aa46f 100644 --- a/platform.json +++ b/platform.json @@ -120,7 +120,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.0.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.1.zip" }, "tool-mbctool": { "optional": true, From 8bfa2c366bc134e9420d2ab9578a0ce078f2dd45 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 10 Jun 2022 09:00:59 +0200 Subject: [PATCH 062/666] really Esptool v4.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index cc7be0348..2206aa46f 100644 --- a/platform.json +++ b/platform.json @@ -120,7 +120,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.0.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.1.zip" }, "tool-mbctool": { "optional": true, From debd76d261b9fecb8bf34374a867d9d792eb3ec6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 10 Jun 2022 09:18:54 +0200 Subject: [PATCH 063/666] Boards update --- boards/adafruit_feather_esp32_v2.json | 13 +++-- boards/adafruit_feather_esp32s2_tft.json | 62 ++++++++++++++++++++++ boards/adafruit_feather_esp32s3.json | 62 ++++++++++++++++++++++ boards/adafruit_magtag29_esp32s2.json | 6 +-- boards/adafruit_qtpy_esp32.json | 42 +++++++++++++++ boards/adafruit_qtpy_esp32c3.json | 44 ++++++++++++++++ boards/adafruit_qtpy_esp32s2.json | 62 ++++++++++++++++++++++ boards/adafruit_qtpy_esp32s3.json | 62 ++++++++++++++++++++++ boards/airm2m_core_esp32c3.json | 37 +++++++++++++ boards/deneyapkart1A.json | 41 +++++++++++++++ boards/dpu_esp32.json | 43 +++++++++++++++ boards/esp32s3box.json | 48 +++++++++++++++++ boards/esp32s3camlcd.json | 48 +++++++++++++++++ boards/lionbit.json | 12 +++-- boards/lolin_c3_mini.json | 44 ++++++++++++++++ boards/lolin_s2_mini.json | 46 ++++++++++++++++ boards/lolin_s2_pico.json | 46 ++++++++++++++++ boards/sparkfun_esp32s2_thing_plus.json | 1 - boards/trueverit-iot-driver-mk3.json | 38 ++++++++++++++ boards/ttgo-t-oi-plus.json | 34 ++++++++++++ boards/um_feathers3.json | 48 +++++++++++++++++ boards/um_pros3.json | 48 +++++++++++++++++ boards/um_rmp.json | 46 ++++++++++++++++ boards/um_tinys3.json | 48 +++++++++++++++++ boards/watchy.json | 38 ++++++++++++++ boards/wipy3.json | 37 +++++++++++++ boards/wt32-eth01.json | 39 ++++++++++++++ examples/espidf-ulp-adc/.travis.yml | 67 ------------------------ 28 files changed, 1083 insertions(+), 79 deletions(-) create mode 100644 boards/adafruit_feather_esp32s2_tft.json create mode 100644 boards/adafruit_feather_esp32s3.json create mode 100644 boards/adafruit_qtpy_esp32.json create mode 100644 boards/adafruit_qtpy_esp32c3.json create mode 100644 boards/adafruit_qtpy_esp32s2.json create mode 100644 boards/adafruit_qtpy_esp32s3.json create mode 100644 boards/airm2m_core_esp32c3.json create mode 100644 boards/deneyapkart1A.json create mode 100644 boards/dpu_esp32.json create mode 100644 boards/esp32s3box.json create mode 100644 boards/esp32s3camlcd.json create mode 100644 boards/lolin_c3_mini.json create mode 100644 boards/lolin_s2_mini.json create mode 100644 boards/lolin_s2_pico.json create mode 100644 boards/trueverit-iot-driver-mk3.json create mode 100644 boards/ttgo-t-oi-plus.json create mode 100644 boards/um_feathers3.json create mode 100644 boards/um_pros3.json create mode 100644 boards/um_rmp.json create mode 100644 boards/um_tinys3.json create mode 100644 boards/watchy.json create mode 100644 boards/wipy3.json create mode 100644 boards/wt32-eth01.json delete mode 100644 examples/espidf-ulp-adc/.travis.yml diff --git a/boards/adafruit_feather_esp32_v2.json b/boards/adafruit_feather_esp32_v2.json index 2cd0eede4..a45636e4d 100644 --- a/boards/adafruit_feather_esp32_v2.json +++ b/boards/adafruit_feather_esp32_v2.json @@ -4,10 +4,15 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DADAFRUIT_FEATHER_ESP32_V2 -DBOARD_HAS_PSRAM", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32_V2", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", + "f_flash": "40000000L", + "flash_mode": "dio", "mcu": "esp32", "variant": "adafruit_feather_esp32_v2" }, @@ -30,7 +35,7 @@ "maximum_ram_size": 327680, "maximum_size": 8388608, "require_upload_port": true, - "speed": 921600 + "speed": 460800 }, "url": "https://www.adafruit.com/product/5400", "vendor": "Adafruit" diff --git a/boards/adafruit_feather_esp32s2_tft.json b/boards/adafruit_feather_esp32s2_tft.json new file mode 100644 index 000000000..6f141b03c --- /dev/null +++ b/boards/adafruit_feather_esp32s2_tft.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x810F" + ], + [ + "0x239A", + "0x010F" + ], + [ + "0x239A", + "0x8110" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_feather_esp32s2_tft" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S2 TFT", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2_tft/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5300", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json new file mode 100644 index 000000000..3d5906802 --- /dev/null +++ b/boards/adafruit_feather_esp32s3.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8113" + ], + [ + "0x239A", + "0x0113" + ], + [ + "0x239A", + "0x8114" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3_nopsram" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "Adafruit Feather ESP32-S3 No PSRAM", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5323", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_magtag29_esp32s2.json b/boards/adafruit_magtag29_esp32s2.json index 40d7bd3e9..5e2dd717f 100644 --- a/boards/adafruit_magtag29_esp32s2.json +++ b/boards/adafruit_magtag29_esp32s2.json @@ -15,15 +15,15 @@ "hwids": [ [ "0x239A", - "0x80DF" + "0x80E5" ], [ "0x239A", - "0x00DF" + "0x00E5" ], [ "0x239A", - "0x80E0" + "0x80E6" ] ], "mcu": "esp32s2", diff --git a/boards/adafruit_qtpy_esp32.json b/boards/adafruit_qtpy_esp32.json new file mode 100644 index 000000000..39896da9d --- /dev/null +++ b/boards/adafruit_qtpy_esp32.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32_PICO", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "adafruit_qtpy_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5395", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32c3.json b/boards/adafruit_qtpy_esp32c3.json new file mode 100644 index 000000000..335002d1c --- /dev/null +++ b/boards/adafruit_qtpy_esp32c3.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32C3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "dout", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "adafruit_qtpy_esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5405", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32s2.json b/boards/adafruit_qtpy_esp32s2.json new file mode 100644 index 000000000..30f51dcec --- /dev/null +++ b/boards/adafruit_qtpy_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8111" + ], + [ + "0x239A", + "0x0111" + ], + [ + "0x239A", + "0x8112" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_qtpy_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S2", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_qtpy_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5325", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32s3.json b/boards/adafruit_qtpy_esp32s3.json new file mode 100644 index 000000000..e01498f1d --- /dev/null +++ b/boards/adafruit_qtpy_esp32s3.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8119" + ], + [ + "0x239A", + "0x0119" + ], + [ + "0x239A", + "0x811A" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_qtpy_esp32s3_nopsram" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "Adafruit QT Py ESP32-S3 No PSRAM", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5426", + "vendor": "Adafruit" +} diff --git a/boards/airm2m_core_esp32c3.json b/boards/airm2m_core_esp32c3.json new file mode 100644 index 000000000..e227fadd8 --- /dev/null +++ b/boards/airm2m_core_esp32c3.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "extra_flags": [ + "-DARDUINO_AirM2M_CORE_ESP32C3", + "-DARDUINO_USB_MODE=1" + ], + "mcu": "esp32c3", + "variant": "AirM2M_CORE_ESP32C3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "AirM2M CORE ESP32C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.luatos.com/chips/esp32c3/board.html", + "vendor": "AirM2M" +} diff --git a/boards/deneyapkart1A.json b/boards/deneyapkart1A.json new file mode 100644 index 000000000..436950859 --- /dev/null +++ b/boards/deneyapkart1A.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYDK1A", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "deneyapkart1A" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart 1A", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/magaza/urun-deneyap-kart.html", + "vendor": "Deneyap" +} diff --git a/boards/dpu_esp32.json b/boards/dpu_esp32.json new file mode 100644 index 000000000..1d6ed4eb3 --- /dev/null +++ b/boards/dpu_esp32.json @@ -0,0 +1,43 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DPU_ESP32", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "dpu_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TAMC DPU ESP32", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/TAMCTec/dpu-esp32", + "vendor": "TAMC" +} diff --git a/boards/esp32s3box.json b/boards/esp32s3box.json new file mode 100644 index 000000000..6198d80a2 --- /dev/null +++ b/boards/esp32s3box.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qspi_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_ESP32_S3_BOX", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3box" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "Espressif ESP32-S3-Box", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5290", + "vendor": "Espressif" +} diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json new file mode 100644 index 000000000..372e89be2 --- /dev/null +++ b/boards/esp32s3camlcd.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "memory_type": "opi_opi" + }, + "boot": "opi", + "core": "esp32", + "extra_flags": [ + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_ESP32S3_CAM_LCD", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dout", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3camlcd" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "ESP32S3 CAM LCD", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.espressif.com/en/news/Maple_Eye_ESP32-S3", + "vendor": "Espressif" +} diff --git a/boards/lionbit.json b/boards/lionbit.json index 41e4cf65e..c8186d0b2 100644 --- a/boards/lionbit.json +++ b/boards/lionbit.json @@ -4,13 +4,17 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", + "extra_flags": [ + "-DARDUINO_LIONBIT", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", "flags" : "-DCORE_DEBUG_LEVEL=5", "mcu": "esp32", - "variant": "esp32" + "variant": "lionbit" }, "connectivity": [ "wifi", @@ -25,7 +29,7 @@ "arduino", "espidf" ], - "name": "LionBit", + "name": "Lion:Bit Dev Board", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, @@ -37,5 +41,5 @@ "speed" : 115200 }, "url": "http://lionbit.lk/", - "vendor": "Lion::Bit" + "vendor": "Lion:Bit" } diff --git a/boards/lolin_c3_mini.json b/boards/lolin_c3_mini.json new file mode 100644 index 000000000..76304465f --- /dev/null +++ b/boards/lolin_c3_mini.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LOLIN_C3_MINI", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN C3 Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc/en/latest/c3/c3_mini.html", + "vendor": "WEMOS" +} diff --git a/boards/lolin_s2_mini.json b/boards/lolin_s2_mini.json new file mode 100644 index 000000000..3fe4f7122 --- /dev/null +++ b/boards/lolin_s2_mini.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LOLIN_S2_MINI", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x80C2" + ] + ], + "mcu": "esp32s2", + "variant": "lolin_s2_mini" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_board": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S2 Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.wemos.cc/en/latest/s2/s2_mini.html", + "vendor": "WEMOS" +} diff --git a/boards/lolin_s2_pico.json b/boards/lolin_s2_pico.json new file mode 100644 index 000000000..dab2b7ec0 --- /dev/null +++ b/boards/lolin_s2_pico.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LOLIN_S2_PICO", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x80C5" + ] + ], + "mcu": "esp32s2", + "variant": "lolin_s2_pico" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_board": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S2 PICO", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.wemos.cc/en/latest/s2/s2_pico.html", + "vendor": "WEMOS" +} diff --git a/boards/sparkfun_esp32s2_thing_plus.json b/boards/sparkfun_esp32s2_thing_plus.json index 269d962fc..f8697e73a 100644 --- a/boards/sparkfun_esp32s2_thing_plus.json +++ b/boards/sparkfun_esp32s2_thing_plus.json @@ -32,7 +32,6 @@ "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, - "mode": "usb", "use_1200bps_touch": true, "wait_for_upload_port": true, "require_upload_port": true, diff --git a/boards/trueverit-iot-driver-mk3.json b/boards/trueverit-iot-driver-mk3.json new file mode 100644 index 000000000..c74f96011 --- /dev/null +++ b/boards/trueverit-iot-driver-mk3.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver_MK_III", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver-mkiii" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver MK III", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} + diff --git a/boards/ttgo-t-oi-plus.json b/boards/ttgo-t-oi-plus.json new file mode 100644 index 000000000..3b05918ef --- /dev/null +++ b/boards/ttgo-t-oi-plus.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": "-DARDUINO_TTGO_T_OI_PLUS_DEV", + "mcu": "esp32c3", + "variant": "ttgo-t-oi-plus" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO T-OI PLUS RISC-V ESP32-C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.lilygo.cn/prod_view.aspx?TypeId=50044&Id=1361&FId=t3:50044:3", + "vendor": "TTGO" +} diff --git a/boards/um_feathers3.json b/boards/um_feathers3.json new file mode 100644 index 000000000..2be96cd96 --- /dev/null +++ b/boards/um_feathers3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x80D0" + ] + ], + "mcu": "esp32s3", + "variant": "um_feathers3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "Unexpected Maker FeatherS3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/feathers3", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_pros3.json b/boards/um_pros3.json new file mode 100644 index 000000000..130079f82 --- /dev/null +++ b/boards/um_pros3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_PROS3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x80D0" + ] + ], + "mcu": "esp32s3", + "variant": "um_pros3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "Unexpected Maker PROS3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/pros3", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_rmp.json b/boards/um_rmp.json new file mode 100644 index 000000000..c5e547acc --- /dev/null +++ b/boards/um_rmp.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_RMP", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x80F6" + ] + ], + "mcu": "esp32s2", + "variant": "um_rmp" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker RMP", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://unexpectedmaker.com/esp32s2", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_tinys3.json b/boards/um_tinys3.json new file mode 100644 index 000000000..a7007091e --- /dev/null +++ b/boards/um_tinys3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TINYS3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x80D0" + ] + ], + "mcu": "esp32s3", + "variant": "um_tinys3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "Unexpected Maker TinyS3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/ttinys3-esp32s3", + "vendor": "Unexpected Maker" +} diff --git a/boards/watchy.json b/boards/watchy.json new file mode 100644 index 000000000..f91eed072 --- /dev/null +++ b/boards/watchy.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "huge_app.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_WATCHY", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "watchy" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SQFMI Watchy v2.0", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://watchy.sqfmi.com/", + "vendor": "SQFMI" +} diff --git a/boards/wipy3.json b/boards/wipy3.json new file mode 100644 index 000000000..b9e5419b1 --- /dev/null +++ b/boards/wipy3.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_WIPY3", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "wipy3" + }, + "connectivity": [ + "wifi", + "bluetooth", + "can", + "ethernet" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Pycom WiPy3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 1310720, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://pycom.io/", + "vendor": "Pycom Ltd." +} diff --git a/boards/wt32-eth01.json b/boards/wt32-eth01.json new file mode 100644 index 000000000..e5a5192cf --- /dev/null +++ b/boards/wt32-eth01.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_WT32_ETH01" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "wt32-eth01" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Wireless-Tag WT32-ETH01 Ethernet Module", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.wireless-tag.com/portfolio/wt32-eth01/", + "vendor": "Wireless-Tag" +} diff --git a/examples/espidf-ulp-adc/.travis.yml b/examples/espidf-ulp-adc/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-ulp-adc/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N From 51a7f0518f9cec4f9d4309acb61c78806489ffff Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 10 Jun 2022 09:24:45 +0200 Subject: [PATCH 064/666] add framework espidf to all boards --- boards/adafruit_feather_esp32s3.json | 3 ++- boards/adafruit_qtpy_esp32s3.json | 3 ++- boards/alksesp32.json | 3 ++- boards/briki_abc_esp32.json | 3 ++- boards/briki_mbc-wb_esp32.json | 3 ++- boards/esp32s3box.json | 3 ++- boards/esp32s3camlcd.json | 3 ++- boards/iotaap_magnolia.json | 3 ++- boards/um_feathers3.json | 3 ++- boards/um_pros3.json | 3 ++- boards/um_tinys3.json | 3 ++- 11 files changed, 22 insertions(+), 11 deletions(-) diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json index 3d5906802..d6e5e97ec 100644 --- a/boards/adafruit_feather_esp32s3.json +++ b/boards/adafruit_feather_esp32s3.json @@ -37,7 +37,8 @@ "openocd_target": "esp32s3.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "Adafruit Feather ESP32-S3 No PSRAM", "upload": { diff --git a/boards/adafruit_qtpy_esp32s3.json b/boards/adafruit_qtpy_esp32s3.json index e01498f1d..067d8a676 100644 --- a/boards/adafruit_qtpy_esp32s3.json +++ b/boards/adafruit_qtpy_esp32s3.json @@ -37,7 +37,8 @@ "openocd_target": "esp32s3.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "Adafruit QT Py ESP32-S3 No PSRAM", "upload": { diff --git a/boards/alksesp32.json b/boards/alksesp32.json index 6a4ae15ad..3e2e67b9b 100644 --- a/boards/alksesp32.json +++ b/boards/alksesp32.json @@ -21,7 +21,8 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "ALKS ESP32", "upload": { diff --git a/boards/briki_abc_esp32.json b/boards/briki_abc_esp32.json index 429514895..53113bb1b 100644 --- a/boards/briki_abc_esp32.json +++ b/boards/briki_abc_esp32.json @@ -22,7 +22,8 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "Briki ABC (MBC-WB) - ESP32", "upload": { diff --git a/boards/briki_mbc-wb_esp32.json b/boards/briki_mbc-wb_esp32.json index df5c3756a..86af17f3f 100644 --- a/boards/briki_mbc-wb_esp32.json +++ b/boards/briki_mbc-wb_esp32.json @@ -22,7 +22,8 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "Briki MBC-WB - ESP32", "upload": { diff --git a/boards/esp32s3box.json b/boards/esp32s3box.json index 6198d80a2..2d7f99db4 100644 --- a/boards/esp32s3box.json +++ b/boards/esp32s3box.json @@ -33,7 +33,8 @@ "openocd_target": "esp32s3.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "Espressif ESP32-S3-Box", "upload": { diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index 372e89be2..34810b5a5 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -33,7 +33,8 @@ "openocd_target": "esp32s3.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "ESP32S3 CAM LCD", "upload": { diff --git a/boards/iotaap_magnolia.json b/boards/iotaap_magnolia.json index 47c1ebad6..fffc85354 100644 --- a/boards/iotaap_magnolia.json +++ b/boards/iotaap_magnolia.json @@ -21,7 +21,8 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "IoTaaP Magnolia", "upload": { diff --git a/boards/um_feathers3.json b/boards/um_feathers3.json index 2be96cd96..435123421 100644 --- a/boards/um_feathers3.json +++ b/boards/um_feathers3.json @@ -31,7 +31,8 @@ "openocd_target": "esp32s3.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "Unexpected Maker FeatherS3", "upload": { diff --git a/boards/um_pros3.json b/boards/um_pros3.json index 130079f82..e4ba4ee4a 100644 --- a/boards/um_pros3.json +++ b/boards/um_pros3.json @@ -31,7 +31,8 @@ "openocd_target": "esp32s3.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "Unexpected Maker PROS3", "upload": { diff --git a/boards/um_tinys3.json b/boards/um_tinys3.json index a7007091e..7a72da444 100644 --- a/boards/um_tinys3.json +++ b/boards/um_tinys3.json @@ -31,7 +31,8 @@ "openocd_target": "esp32s3.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "Unexpected Maker TinyS3", "upload": { From d37c542560a31f38c12634443c7a6d722fe1e216 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Jun 2022 22:00:32 +0200 Subject: [PATCH 065/666] Update espidf.py --- builder/frameworks/espidf.py | 306 +++++++++++++++++------------------ 1 file changed, 148 insertions(+), 158 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 8e790205c..a360a04e3 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -52,21 +52,11 @@ FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") if "darwin" in get_systype() and "arm64" in get_systype(): TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" - % ( - "riscv32-esp-arm" - if mcu == "esp32c3" - else ("xtensa-%s-arm" % mcu) - ) + "toolchain-%s" % ("riscv32-esp-arm" if mcu == "esp32c3" else ("xtensa-%s-arm" % mcu)) ) if not "arm64" in get_systype(): TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" - % ( - "riscv32-esp" - if mcu == "esp32c3" - else ("xtensa-%s" % mcu) - ) + "toolchain-%s" % ("riscv32-esp" if mcu == "esp32c3" else ("xtensa-%s" % mcu)) ) assert os.path.isdir(FRAMEWORK_DIR) @@ -236,15 +226,9 @@ def populate_idf_env_vars(idf_env): os.path.dirname(env.subst("$PYTHONEXE")), ] - if mcu != "esp32c3": + if mcu not in ("esp32c3", "esp32s3"): additional_packages.append( - os.path.join( - platform.get_package_dir( - "toolchain-%sulp" - % ("esp32s2" if (mcu == "esp32s3" or mcu == "esp32s2") else mcu) - ), - "bin" - ), + os.path.join(platform.get_package_dir("toolchain-%sulp" % mcu), "bin"), ) if "windows" in get_systype(): @@ -354,7 +338,7 @@ def _add_archive(archive_path, link_args): if fragment.startswith("-l"): link_args["LIBS"].extend(args) elif fragment.startswith("-L"): - lib_path = fragment.replace("-L", "").strip().strip('"') + lib_path = fragment.replace("-L", "").strip(" '\"") _add_to_libpath(lib_path, link_args) elif fragment.startswith("-") and not fragment.startswith("-l"): # CMake mistakenly marks LINKFLAGS as libraries @@ -438,48 +422,85 @@ def get_sdk_configuration(): return {} -def find_framework_service_files(search_path, sdk_config): - result = {} - result["lf_files"] = list() - result["kconfig_files"] = list() - result["kconfig_build_files"] = list() - for d in os.listdir(search_path): - path = os.path.join(search_path, d) - if not os.path.isdir(path): - continue - for f in os.listdir(path): - # Skip hardware specific files as they will be added later - if f == "linker.lf" and not os.path.basename(path).startswith( - ("esp32", "riscv") +def load_component_paths(framework_components_dir, ignored_component_prefixes=None): + def _scan_components_from_framework(): + result = [] + for component in os.listdir(framework_components_dir): + component_path = os.path.join(framework_components_dir, component) + if component.startswith(ignored_component_prefixes) or not os.path.isdir( + component_path ): - result["lf_files"].append(os.path.join(path, f)) - elif f == "Kconfig.projbuild": - result["kconfig_build_files"].append(os.path.join(path, f)) - elif f == "Kconfig": - result["kconfig_files"].append(os.path.join(path, f)) + continue + result.append(component_path) - if mcu == "esp32c3": - result["lf_files"].append( - os.path.join(FRAMEWORK_DIR, "components", "riscv", "linker.lf") - ) + return result - result["lf_files"].extend( - [ - os.path.join(FRAMEWORK_DIR, "components", "esp_common", "common.lf"), - os.path.join(FRAMEWORK_DIR, "components", "esp_common", "soc.lf"), - os.path.join(FRAMEWORK_DIR, "components", "esp_system", "app.lf"), - os.path.join(FRAMEWORK_DIR, "components", "newlib", "newlib.lf"), - os.path.join(FRAMEWORK_DIR, "components", "newlib", "system_libs.lf"), - ] + # First of all, try to load the list of used components from the project description + components = [] + ignored_component_prefixes = ignored_component_prefixes or [] + project_description_file = os.path.join(BUILD_DIR, "project_description.json") + if os.path.isfile(project_description_file): + with open(project_description_file) as fp: + try: + data = json.load(fp) + for path in data.get("build_component_paths", []): + if not os.path.basename(path).startswith( + ignored_component_prefixes + ): + components.append(path) + except: + print( + "Warning: Could not find load components from project description!\n" + ) + + return components or _scan_components_from_framework() + + +def extract_linker_script_fragments(framework_components_dir, sdk_config): + # Hardware-specific components are excluded from search and added manually below + project_components = load_component_paths( + framework_components_dir, ignored_component_prefixes=("esp32", "riscv") ) + result = [] + for component_path in project_components: + linker_fragment = os.path.join(component_path, "linker.lf") + if os.path.isfile(linker_fragment): + result.append(linker_fragment) + + if not result: + sys.stderr.write("Error: Failed to extract paths to linker script fragments\n") + env.Exit(1) + + if mcu == "esp32c3": + result.append(os.path.join(framework_components_dir, "riscv", "linker.lf")) + + # Add extra linker fragments + for fragment in ( + os.path.join("esp_system", "app.lf"), + os.path.join("esp_common", "common.lf"), + os.path.join("esp_common", "soc.lf"), + os.path.join("newlib", "system_libs.lf"), + os.path.join("newlib", "newlib.lf"), + ): + result.append(os.path.join(framework_components_dir, fragment)) + if sdk_config.get("SPIRAM_CACHE_WORKAROUND", False): - result["lf_files"].append( + result.append( os.path.join( - FRAMEWORK_DIR, "components", "newlib", "esp32-spiram-rom-functions-c.lf" + framework_components_dir, "newlib", "esp32-spiram-rom-functions-c.lf" ) ) + if board.get("build.esp-idf.extra_lf_files", ""): + result.extend( + [ + lf if os.path.isabs(lf) else os.path.join(PROJECT_DIR, lf) + for lf in board.get("build.esp-idf.extra_lf_files").splitlines() + if lf.strip() + ] + ) + return result @@ -510,7 +531,7 @@ def create_custom_libraries_list(ldgen_libraries_file, ignore_targets): def generate_project_ld_script(sdk_config, ignore_targets=None): ignore_targets = ignore_targets or [] - project_files = find_framework_service_files( + linker_script_fragments = extract_linker_script_fragments( os.path.join(FRAMEWORK_DIR, "components"), sdk_config ) @@ -519,51 +540,13 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): libraries_list = create_custom_libraries_list( os.path.join(BUILD_DIR, "ldgen_libraries"), ignore_targets ) - # Rework the memory template linker script, following components/esp_system/ld.cmake - args = { - "preprocess" : os.path.join( - TOOLCHAIN_DIR, - "bin", - env.subst("$CC")), - "ld_output": os.path.join("$BUILD_DIR", "memory.ld"), - "ld_dir": os.path.join( - FRAMEWORK_DIR, - "components", - "esp_system", - "ld"), - "ld_input": os.path.join( - FRAMEWORK_DIR, - "components", - "esp_system", - "ld", - idf_variant, - "memory.ld.in", - ), - "config": os.path.join("$BUILD_DIR", "config"), - "flags" : '-C -P -x c -E -o ' - } - - cmd = ( - '"{preprocess}" {flags} "{ld_output}" -I "{config}" -I "{ld_dir}" "{ld_input}"' - ).format(**args) - - env.Command( - os.path.join("$BUILD_DIR", "memory.ld"), - os.path.join( - FRAMEWORK_DIR, - "components", - "esp_system", - "ld", - idf_variant, - "memory.ld.in", - ), - env.VerboseAction(cmd, "Generating memory linker script $TARGET"), - ) args = { "script": os.path.join(FRAMEWORK_DIR, "tools", "ldgen", "ldgen.py"), "config": SDKCONFIG_PATH, - "fragments": " ".join(['"%s"' % f for f in project_files.get("lf_files")]), + "fragments": " ".join( + ['"%s"' % fs.to_unix_path(f) for f in linker_script_fragments] + ), "kconfig": os.path.join(FRAMEWORK_DIR, "Kconfig"), "env_file": os.path.join("$BUILD_DIR", "config.env"), "libraries_list": libraries_list, @@ -629,7 +612,9 @@ def prepare_build_envs(config, default_env, debug_allowed=True): return build_envs -def compile_source_files(config, default_env, project_src_dir, prepend_dir=None, debug_allowed=True): +def compile_source_files( + config, default_env, project_src_dir, prepend_dir=None, debug_allowed=True +): build_envs = prepare_build_envs(config, default_env, debug_allowed) objects = [] components_dir = fs.to_unix_path(os.path.join(FRAMEWORK_DIR, "components")) @@ -744,20 +729,6 @@ def find_lib_deps(components_map, elf_config, link_args, ignore_components=None) return result -def fix_ld_paths(extra_flags): - peripheral_framework_path = os.path.join(FRAMEWORK_DIR, "components", "soc", idf_variant, "ld") - rom_framework_path = os.path.join(FRAMEWORK_DIR, "components", "esp_rom", idf_variant, "ld") - bl_framework_path = os.path.join(FRAMEWORK_DIR, "components", "bootloader", "subproject", "main", "ld", idf_variant) - - # ESP linker scripts changed path in ESP-IDF 4.4+, so add missing paths to linker's search path - try: - ld_index = extra_flags.index("%s.peripherals.ld" % idf_variant) - extra_flags[ld_index-1:ld_index-1] = [ "-L", peripheral_framework_path, "-L", rom_framework_path, "-L", bl_framework_path] - except: - print("Error while parsing the flags") - - return extra_flags - def build_bootloader(sdk_config): bootloader_src_dir = os.path.join( @@ -810,7 +781,6 @@ def build_bootloader(sdk_config): ) link_args = extract_link_args(elf_config) extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) - extra_flags = fix_ld_paths(extra_flags) link_args["LINKFLAGS"] = sorted( list(set(link_args["LINKFLAGS"]) - set(extra_flags)) ) @@ -880,9 +850,11 @@ def generate_default_component(): file(GLOB component_sources *.c* *.S) idf_component_register(SRCS ${component_sources}) """ - dummy_component_path = os.path.join(BUILD_DIR, "__pio_env") - if not os.path.isdir(dummy_component_path): - os.makedirs(dummy_component_path) + dummy_component_path = os.path.join(FRAMEWORK_DIR, "components", "__pio_env") + if os.path.isdir(dummy_component_path): + return + + os.makedirs(dummy_component_path) for ext in (".cpp", ".c", ".S"): dummy_file = os.path.join(dummy_component_path, "__dummy" + ext) @@ -894,14 +866,18 @@ def generate_default_component(): with open(component_cmake, "w") as fp: fp.write(prj_cmake_tpl) - return dummy_component_path - def find_default_component(target_configs): for config in target_configs: if "__pio_env" in config: return config - return "" + sys.stderr.write( + "Error! Failed to find the default IDF component with build information for " + "generic files.\nCheck that the `EXTRA_COMPONENT_DIRS` option is not overridden " + "in your CMakeLists.txt.\nSee an example with an extra component here " + "https://docs.platformio.org/en/latest/frameworks/espidf.html#esp-idf-components\n" + ) + env.Exit(1) def create_version_file(): @@ -1115,12 +1091,17 @@ def _get_installed_pip_packages(): install_python_deps() - # ESP-IDF package doesn't contain .git folder, instead package version is specified # in a special file "version.h" in the root folder of the package create_version_file() +# Generate a default component with dummy C/C++/ASM source files in the framework +# folder. This component is used to force the IDF build system generate build +# information for generic C/C++/ASM sources regardless of whether such files are used in project + +generate_default_component() + # # Generate final linker script # @@ -1131,13 +1112,17 @@ def _get_installed_pip_packages(): board.get( "build.esp-idf.ldscript", os.path.join( - FRAMEWORK_DIR, "components", "esp_system", "ld", idf_variant, "memory.ld.in" + FRAMEWORK_DIR, + "components", + "esp_system", + "ld", + idf_variant, + "memory.ld.in", ), ), env.VerboseAction( - '$CC -I"$BUILD_DIR/config" -I"' + - os.path.join(FRAMEWORK_DIR, "components", "esp_system", "ld") + - '" -C -P -x c -E $SOURCE -o $TARGET', + '$CC -I"$BUILD_DIR/config" -I"%s" -C -P -x c -E $SOURCE -o $TARGET' + % os.path.join(FRAMEWORK_DIR, "components", "esp_system", "ld"), "Generating LD script $TARGET", ), ) @@ -1145,37 +1130,6 @@ def _get_installed_pip_packages(): env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", linker_script) env.Replace(LDSCRIPT_PATH="memory.ld") -# -# Generate partition table -# - -fwpartitions_dir = os.path.join(FRAMEWORK_DIR, "components", "partition_table") -partitions_csv = board.get("build.partitions", "partitions_singleapp.csv") - -env.Replace( - PARTITIONS_TABLE_CSV=os.path.abspath( - os.path.join(fwpartitions_dir, partitions_csv) - if os.path.isfile(os.path.join(fwpartitions_dir, partitions_csv)) - else partitions_csv - ) -) - -partition_table = env.Command( - os.path.join("$BUILD_DIR", "partitions.bin"), - "$PARTITIONS_TABLE_CSV", - env.VerboseAction( - '"$PYTHONEXE" "%s" -q --flash-size "%s" $SOURCE $TARGET' - % ( - os.path.join( - FRAMEWORK_DIR, "components", "partition_table", "gen_esp32part.py" - ), - board.get("upload.flash_size", "4MB"), - ), - "Generating partitions $TARGET", - ), -) - -env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", partition_table) # # Current build script limitations @@ -1213,7 +1167,7 @@ def _get_installed_pip_packages(): # By default 'main' folder is used to store source files. In case when a user has # default 'src' folder we need to add this as an extra component. If there is no 'main' # folder CMake won't generate dependencies properly -extra_components = [generate_default_component()] +extra_components = [] if PROJECT_SRC_DIR != os.path.join(PROJECT_DIR, "main"): extra_components.append(PROJECT_SRC_DIR) if "arduino" in env.subst("$PIOFRAMEWORK"): @@ -1325,15 +1279,13 @@ def _get_installed_pip_packages(): # Extra flags which need to be explicitly specified in LINKFLAGS section because SCons # cannot merge them correctly extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) -extra_flags = fix_ld_paths(extra_flags) link_args["LINKFLAGS"] = sorted(list(set(link_args["LINKFLAGS"]) - set(extra_flags))) -# remove the main linker script flags '-T memory.ld' since it already appears later on +# remove the main linker script flags '-T memory.ld' try: ld_index = extra_flags.index("memory.ld") extra_flags.pop(ld_index) extra_flags.pop(ld_index - 1) - pass except: print("Warning! Couldn't find the main linker script in the CMake code model.") @@ -1378,7 +1330,44 @@ def _skip_prj_source_files(node): ) ) +# +# Generate partition table +# + +fwpartitions_dir = os.path.join(FRAMEWORK_DIR, "components", "partition_table") +partitions_csv = board.get("build.partitions", "partitions_singleapp.csv") partition_table_offset = sdk_config.get("PARTITION_TABLE_OFFSET", 0x8000) + +env.Replace( + PARTITIONS_TABLE_CSV=os.path.abspath( + os.path.join(fwpartitions_dir, partitions_csv) + if os.path.isfile(os.path.join(fwpartitions_dir, partitions_csv)) + else partitions_csv + ) +) + +partition_table = env.Command( + os.path.join("$BUILD_DIR", "partitions.bin"), + "$PARTITIONS_TABLE_CSV", + env.VerboseAction( + '"$PYTHONEXE" "%s" -q --offset "%s" --flash-size "%s" $SOURCE $TARGET' + % ( + os.path.join( + FRAMEWORK_DIR, "components", "partition_table", "gen_esp32part.py" + ), + partition_table_offset, + board.get("upload.flash_size", "4MB"), + ), + "Generating partitions $TARGET", + ), +) + +env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", partition_table) + +# +# Main environment configuration +# + project_flags.update(link_args) env.MergeFlags(project_flags) env.Prepend( @@ -1389,7 +1378,8 @@ def _skip_prj_source_files(node): FLASH_EXTRA_IMAGES=[ ( board.get( - "upload.bootloader_offset", "0x0" if (mcu == "esp32c3" or mcu == "esp32s3") else "0x1000" + "upload.bootloader_offset", + "0x0" if mcu in ("esp32c3", "esp32s3") else "0x1000", ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), From d38762441db541ce93ae4a50667431d989deb585 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Jun 2022 22:11:57 +0200 Subject: [PATCH 066/666] use upstream version --- builder/frameworks/espidf.py | 306 +++++++++++++++++------------------ 1 file changed, 148 insertions(+), 158 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 8e790205c..a360a04e3 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -52,21 +52,11 @@ FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") if "darwin" in get_systype() and "arm64" in get_systype(): TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" - % ( - "riscv32-esp-arm" - if mcu == "esp32c3" - else ("xtensa-%s-arm" % mcu) - ) + "toolchain-%s" % ("riscv32-esp-arm" if mcu == "esp32c3" else ("xtensa-%s-arm" % mcu)) ) if not "arm64" in get_systype(): TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" - % ( - "riscv32-esp" - if mcu == "esp32c3" - else ("xtensa-%s" % mcu) - ) + "toolchain-%s" % ("riscv32-esp" if mcu == "esp32c3" else ("xtensa-%s" % mcu)) ) assert os.path.isdir(FRAMEWORK_DIR) @@ -236,15 +226,9 @@ def populate_idf_env_vars(idf_env): os.path.dirname(env.subst("$PYTHONEXE")), ] - if mcu != "esp32c3": + if mcu not in ("esp32c3", "esp32s3"): additional_packages.append( - os.path.join( - platform.get_package_dir( - "toolchain-%sulp" - % ("esp32s2" if (mcu == "esp32s3" or mcu == "esp32s2") else mcu) - ), - "bin" - ), + os.path.join(platform.get_package_dir("toolchain-%sulp" % mcu), "bin"), ) if "windows" in get_systype(): @@ -354,7 +338,7 @@ def _add_archive(archive_path, link_args): if fragment.startswith("-l"): link_args["LIBS"].extend(args) elif fragment.startswith("-L"): - lib_path = fragment.replace("-L", "").strip().strip('"') + lib_path = fragment.replace("-L", "").strip(" '\"") _add_to_libpath(lib_path, link_args) elif fragment.startswith("-") and not fragment.startswith("-l"): # CMake mistakenly marks LINKFLAGS as libraries @@ -438,48 +422,85 @@ def get_sdk_configuration(): return {} -def find_framework_service_files(search_path, sdk_config): - result = {} - result["lf_files"] = list() - result["kconfig_files"] = list() - result["kconfig_build_files"] = list() - for d in os.listdir(search_path): - path = os.path.join(search_path, d) - if not os.path.isdir(path): - continue - for f in os.listdir(path): - # Skip hardware specific files as they will be added later - if f == "linker.lf" and not os.path.basename(path).startswith( - ("esp32", "riscv") +def load_component_paths(framework_components_dir, ignored_component_prefixes=None): + def _scan_components_from_framework(): + result = [] + for component in os.listdir(framework_components_dir): + component_path = os.path.join(framework_components_dir, component) + if component.startswith(ignored_component_prefixes) or not os.path.isdir( + component_path ): - result["lf_files"].append(os.path.join(path, f)) - elif f == "Kconfig.projbuild": - result["kconfig_build_files"].append(os.path.join(path, f)) - elif f == "Kconfig": - result["kconfig_files"].append(os.path.join(path, f)) + continue + result.append(component_path) - if mcu == "esp32c3": - result["lf_files"].append( - os.path.join(FRAMEWORK_DIR, "components", "riscv", "linker.lf") - ) + return result - result["lf_files"].extend( - [ - os.path.join(FRAMEWORK_DIR, "components", "esp_common", "common.lf"), - os.path.join(FRAMEWORK_DIR, "components", "esp_common", "soc.lf"), - os.path.join(FRAMEWORK_DIR, "components", "esp_system", "app.lf"), - os.path.join(FRAMEWORK_DIR, "components", "newlib", "newlib.lf"), - os.path.join(FRAMEWORK_DIR, "components", "newlib", "system_libs.lf"), - ] + # First of all, try to load the list of used components from the project description + components = [] + ignored_component_prefixes = ignored_component_prefixes or [] + project_description_file = os.path.join(BUILD_DIR, "project_description.json") + if os.path.isfile(project_description_file): + with open(project_description_file) as fp: + try: + data = json.load(fp) + for path in data.get("build_component_paths", []): + if not os.path.basename(path).startswith( + ignored_component_prefixes + ): + components.append(path) + except: + print( + "Warning: Could not find load components from project description!\n" + ) + + return components or _scan_components_from_framework() + + +def extract_linker_script_fragments(framework_components_dir, sdk_config): + # Hardware-specific components are excluded from search and added manually below + project_components = load_component_paths( + framework_components_dir, ignored_component_prefixes=("esp32", "riscv") ) + result = [] + for component_path in project_components: + linker_fragment = os.path.join(component_path, "linker.lf") + if os.path.isfile(linker_fragment): + result.append(linker_fragment) + + if not result: + sys.stderr.write("Error: Failed to extract paths to linker script fragments\n") + env.Exit(1) + + if mcu == "esp32c3": + result.append(os.path.join(framework_components_dir, "riscv", "linker.lf")) + + # Add extra linker fragments + for fragment in ( + os.path.join("esp_system", "app.lf"), + os.path.join("esp_common", "common.lf"), + os.path.join("esp_common", "soc.lf"), + os.path.join("newlib", "system_libs.lf"), + os.path.join("newlib", "newlib.lf"), + ): + result.append(os.path.join(framework_components_dir, fragment)) + if sdk_config.get("SPIRAM_CACHE_WORKAROUND", False): - result["lf_files"].append( + result.append( os.path.join( - FRAMEWORK_DIR, "components", "newlib", "esp32-spiram-rom-functions-c.lf" + framework_components_dir, "newlib", "esp32-spiram-rom-functions-c.lf" ) ) + if board.get("build.esp-idf.extra_lf_files", ""): + result.extend( + [ + lf if os.path.isabs(lf) else os.path.join(PROJECT_DIR, lf) + for lf in board.get("build.esp-idf.extra_lf_files").splitlines() + if lf.strip() + ] + ) + return result @@ -510,7 +531,7 @@ def create_custom_libraries_list(ldgen_libraries_file, ignore_targets): def generate_project_ld_script(sdk_config, ignore_targets=None): ignore_targets = ignore_targets or [] - project_files = find_framework_service_files( + linker_script_fragments = extract_linker_script_fragments( os.path.join(FRAMEWORK_DIR, "components"), sdk_config ) @@ -519,51 +540,13 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): libraries_list = create_custom_libraries_list( os.path.join(BUILD_DIR, "ldgen_libraries"), ignore_targets ) - # Rework the memory template linker script, following components/esp_system/ld.cmake - args = { - "preprocess" : os.path.join( - TOOLCHAIN_DIR, - "bin", - env.subst("$CC")), - "ld_output": os.path.join("$BUILD_DIR", "memory.ld"), - "ld_dir": os.path.join( - FRAMEWORK_DIR, - "components", - "esp_system", - "ld"), - "ld_input": os.path.join( - FRAMEWORK_DIR, - "components", - "esp_system", - "ld", - idf_variant, - "memory.ld.in", - ), - "config": os.path.join("$BUILD_DIR", "config"), - "flags" : '-C -P -x c -E -o ' - } - - cmd = ( - '"{preprocess}" {flags} "{ld_output}" -I "{config}" -I "{ld_dir}" "{ld_input}"' - ).format(**args) - - env.Command( - os.path.join("$BUILD_DIR", "memory.ld"), - os.path.join( - FRAMEWORK_DIR, - "components", - "esp_system", - "ld", - idf_variant, - "memory.ld.in", - ), - env.VerboseAction(cmd, "Generating memory linker script $TARGET"), - ) args = { "script": os.path.join(FRAMEWORK_DIR, "tools", "ldgen", "ldgen.py"), "config": SDKCONFIG_PATH, - "fragments": " ".join(['"%s"' % f for f in project_files.get("lf_files")]), + "fragments": " ".join( + ['"%s"' % fs.to_unix_path(f) for f in linker_script_fragments] + ), "kconfig": os.path.join(FRAMEWORK_DIR, "Kconfig"), "env_file": os.path.join("$BUILD_DIR", "config.env"), "libraries_list": libraries_list, @@ -629,7 +612,9 @@ def prepare_build_envs(config, default_env, debug_allowed=True): return build_envs -def compile_source_files(config, default_env, project_src_dir, prepend_dir=None, debug_allowed=True): +def compile_source_files( + config, default_env, project_src_dir, prepend_dir=None, debug_allowed=True +): build_envs = prepare_build_envs(config, default_env, debug_allowed) objects = [] components_dir = fs.to_unix_path(os.path.join(FRAMEWORK_DIR, "components")) @@ -744,20 +729,6 @@ def find_lib_deps(components_map, elf_config, link_args, ignore_components=None) return result -def fix_ld_paths(extra_flags): - peripheral_framework_path = os.path.join(FRAMEWORK_DIR, "components", "soc", idf_variant, "ld") - rom_framework_path = os.path.join(FRAMEWORK_DIR, "components", "esp_rom", idf_variant, "ld") - bl_framework_path = os.path.join(FRAMEWORK_DIR, "components", "bootloader", "subproject", "main", "ld", idf_variant) - - # ESP linker scripts changed path in ESP-IDF 4.4+, so add missing paths to linker's search path - try: - ld_index = extra_flags.index("%s.peripherals.ld" % idf_variant) - extra_flags[ld_index-1:ld_index-1] = [ "-L", peripheral_framework_path, "-L", rom_framework_path, "-L", bl_framework_path] - except: - print("Error while parsing the flags") - - return extra_flags - def build_bootloader(sdk_config): bootloader_src_dir = os.path.join( @@ -810,7 +781,6 @@ def build_bootloader(sdk_config): ) link_args = extract_link_args(elf_config) extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) - extra_flags = fix_ld_paths(extra_flags) link_args["LINKFLAGS"] = sorted( list(set(link_args["LINKFLAGS"]) - set(extra_flags)) ) @@ -880,9 +850,11 @@ def generate_default_component(): file(GLOB component_sources *.c* *.S) idf_component_register(SRCS ${component_sources}) """ - dummy_component_path = os.path.join(BUILD_DIR, "__pio_env") - if not os.path.isdir(dummy_component_path): - os.makedirs(dummy_component_path) + dummy_component_path = os.path.join(FRAMEWORK_DIR, "components", "__pio_env") + if os.path.isdir(dummy_component_path): + return + + os.makedirs(dummy_component_path) for ext in (".cpp", ".c", ".S"): dummy_file = os.path.join(dummy_component_path, "__dummy" + ext) @@ -894,14 +866,18 @@ def generate_default_component(): with open(component_cmake, "w") as fp: fp.write(prj_cmake_tpl) - return dummy_component_path - def find_default_component(target_configs): for config in target_configs: if "__pio_env" in config: return config - return "" + sys.stderr.write( + "Error! Failed to find the default IDF component with build information for " + "generic files.\nCheck that the `EXTRA_COMPONENT_DIRS` option is not overridden " + "in your CMakeLists.txt.\nSee an example with an extra component here " + "https://docs.platformio.org/en/latest/frameworks/espidf.html#esp-idf-components\n" + ) + env.Exit(1) def create_version_file(): @@ -1115,12 +1091,17 @@ def _get_installed_pip_packages(): install_python_deps() - # ESP-IDF package doesn't contain .git folder, instead package version is specified # in a special file "version.h" in the root folder of the package create_version_file() +# Generate a default component with dummy C/C++/ASM source files in the framework +# folder. This component is used to force the IDF build system generate build +# information for generic C/C++/ASM sources regardless of whether such files are used in project + +generate_default_component() + # # Generate final linker script # @@ -1131,13 +1112,17 @@ def _get_installed_pip_packages(): board.get( "build.esp-idf.ldscript", os.path.join( - FRAMEWORK_DIR, "components", "esp_system", "ld", idf_variant, "memory.ld.in" + FRAMEWORK_DIR, + "components", + "esp_system", + "ld", + idf_variant, + "memory.ld.in", ), ), env.VerboseAction( - '$CC -I"$BUILD_DIR/config" -I"' + - os.path.join(FRAMEWORK_DIR, "components", "esp_system", "ld") + - '" -C -P -x c -E $SOURCE -o $TARGET', + '$CC -I"$BUILD_DIR/config" -I"%s" -C -P -x c -E $SOURCE -o $TARGET' + % os.path.join(FRAMEWORK_DIR, "components", "esp_system", "ld"), "Generating LD script $TARGET", ), ) @@ -1145,37 +1130,6 @@ def _get_installed_pip_packages(): env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", linker_script) env.Replace(LDSCRIPT_PATH="memory.ld") -# -# Generate partition table -# - -fwpartitions_dir = os.path.join(FRAMEWORK_DIR, "components", "partition_table") -partitions_csv = board.get("build.partitions", "partitions_singleapp.csv") - -env.Replace( - PARTITIONS_TABLE_CSV=os.path.abspath( - os.path.join(fwpartitions_dir, partitions_csv) - if os.path.isfile(os.path.join(fwpartitions_dir, partitions_csv)) - else partitions_csv - ) -) - -partition_table = env.Command( - os.path.join("$BUILD_DIR", "partitions.bin"), - "$PARTITIONS_TABLE_CSV", - env.VerboseAction( - '"$PYTHONEXE" "%s" -q --flash-size "%s" $SOURCE $TARGET' - % ( - os.path.join( - FRAMEWORK_DIR, "components", "partition_table", "gen_esp32part.py" - ), - board.get("upload.flash_size", "4MB"), - ), - "Generating partitions $TARGET", - ), -) - -env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", partition_table) # # Current build script limitations @@ -1213,7 +1167,7 @@ def _get_installed_pip_packages(): # By default 'main' folder is used to store source files. In case when a user has # default 'src' folder we need to add this as an extra component. If there is no 'main' # folder CMake won't generate dependencies properly -extra_components = [generate_default_component()] +extra_components = [] if PROJECT_SRC_DIR != os.path.join(PROJECT_DIR, "main"): extra_components.append(PROJECT_SRC_DIR) if "arduino" in env.subst("$PIOFRAMEWORK"): @@ -1325,15 +1279,13 @@ def _get_installed_pip_packages(): # Extra flags which need to be explicitly specified in LINKFLAGS section because SCons # cannot merge them correctly extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) -extra_flags = fix_ld_paths(extra_flags) link_args["LINKFLAGS"] = sorted(list(set(link_args["LINKFLAGS"]) - set(extra_flags))) -# remove the main linker script flags '-T memory.ld' since it already appears later on +# remove the main linker script flags '-T memory.ld' try: ld_index = extra_flags.index("memory.ld") extra_flags.pop(ld_index) extra_flags.pop(ld_index - 1) - pass except: print("Warning! Couldn't find the main linker script in the CMake code model.") @@ -1378,7 +1330,44 @@ def _skip_prj_source_files(node): ) ) +# +# Generate partition table +# + +fwpartitions_dir = os.path.join(FRAMEWORK_DIR, "components", "partition_table") +partitions_csv = board.get("build.partitions", "partitions_singleapp.csv") partition_table_offset = sdk_config.get("PARTITION_TABLE_OFFSET", 0x8000) + +env.Replace( + PARTITIONS_TABLE_CSV=os.path.abspath( + os.path.join(fwpartitions_dir, partitions_csv) + if os.path.isfile(os.path.join(fwpartitions_dir, partitions_csv)) + else partitions_csv + ) +) + +partition_table = env.Command( + os.path.join("$BUILD_DIR", "partitions.bin"), + "$PARTITIONS_TABLE_CSV", + env.VerboseAction( + '"$PYTHONEXE" "%s" -q --offset "%s" --flash-size "%s" $SOURCE $TARGET' + % ( + os.path.join( + FRAMEWORK_DIR, "components", "partition_table", "gen_esp32part.py" + ), + partition_table_offset, + board.get("upload.flash_size", "4MB"), + ), + "Generating partitions $TARGET", + ), +) + +env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", partition_table) + +# +# Main environment configuration +# + project_flags.update(link_args) env.MergeFlags(project_flags) env.Prepend( @@ -1389,7 +1378,8 @@ def _skip_prj_source_files(node): FLASH_EXTRA_IMAGES=[ ( board.get( - "upload.bootloader_offset", "0x0" if (mcu == "esp32c3" or mcu == "esp32s3") else "0x1000" + "upload.bootloader_offset", + "0x0" if mcu in ("esp32c3", "esp32s3") else "0x1000", ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), From 73abc81917bee6383710466360cfa83d77e4def9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 15 Jun 2022 17:57:55 +0200 Subject: [PATCH 067/666] Update platform.py --- platform.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/platform.py b/platform.py index 7502c1935..507b2a4b2 100644 --- a/platform.py +++ b/platform.py @@ -125,11 +125,8 @@ def configure_default_packages(self, variables, targets): # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp-arm"]["optional"] = False - is_legacy_project = ( - build_core == "mbcwb" - ) - if is_legacy_project: + if build_core == "mbcwb": # Remove the main toolchains from PATH for toolchain in ( "toolchain-xtensa-esp32", @@ -143,9 +140,7 @@ def configure_default_packages(self, variables, targets): self.packages["toolchain-xtensa32"] = { "type": "toolchain", "owner": "platformio", - "version": "~2.80400.0" - if "arduino" in frameworks and build_core != "mbcwb" - else "~2.50200.0", + "version": "~2.50200.0" } if build_core == "mbcwb": @@ -180,7 +175,7 @@ def _add_dynamic_options(self, board): supported_debug_tools = [ "cmsis-dap", "esp-prog", - "esp_usb_jtag", + "esp-bridge", "iot-bus-jtag", "jlink", "minimodule", @@ -191,6 +186,10 @@ def _add_dynamic_options(self, board): "tumpa", ] + if board.get("build.mcu", "") in ("esp32c3", "esp32s3"): + supported_debug_tools.append("esp-builtin") + + upload_protocol = board.manifest.get("upload", {}).get("protocol") upload_protocols = board.manifest.get("upload", {}).get("protocols", []) if debug: @@ -202,18 +201,21 @@ def _add_dynamic_options(self, board): if "tools" not in debug: debug["tools"] = {} - # Only FTDI based debug probes for link in upload_protocols: if link in non_debug_protocols or link in debug["tools"]: continue - if link in ("jlink", "cmsis-dap", "esp_usb_jtag"): + if link in ("jlink", "cmsis-dap"): openocd_interface = link elif link in ("esp-prog", "ftdi"): if board.id == "esp32-s2-kaluga-1": openocd_interface = "ftdi/esp32s2_kaluga_v1" else: openocd_interface = "ftdi/esp32_devkitj_v1" + elif link == "esp-bridge": + openocd_interface = "esp_usb_bridge" + elif link == "esp-builtin": + openocd_interface = "esp_usb_jtag" else: openocd_interface = "ftdi/" + link From b2ec5ba7b12c63d0d028802c9f2c5b92a20b02ed Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Jun 2022 12:21:44 +0200 Subject: [PATCH 068/666] Update platform.py --- platform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.py b/platform.py index 507b2a4b2..59f31a0f6 100644 --- a/platform.py +++ b/platform.py @@ -106,7 +106,7 @@ def configure_default_packages(self, variables, targets): if mcu in ("esp32s2", "esp32s3", "esp32c3"): self.packages.pop("toolchain-esp32ulp", None) - if mcu == "esp32" or mcu == "esp32c3": + if mcu != "esp32s2": self.packages.pop("toolchain-esp32s2ulp", None) # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp"]["optional"] = False @@ -120,7 +120,7 @@ def configure_default_packages(self, variables, targets): if mcu in ("esp32s2", "esp32s3", "esp32c3"): self.packages.pop("toolchain-esp32ulp", None) - if mcu == "esp32" or mcu == "esp32c3": + if mcu != "esp32s2": self.packages.pop("toolchain-esp32s2ulp", None) # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp-arm"]["optional"] = False From 37da3e1432ada49cb4395731fd49f0a4e9ace8ba Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Jun 2022 12:37:55 +0200 Subject: [PATCH 069/666] Integrate upstream updates (#21) * Update featheresp32-s2.json * Update main.py * Update platform.json * Update platform.py * Integrate upstream develop changes * Update platform.json * Update platform.py * Integrate upstream 2 * Update esp32-s2-franzininho.json * Update _embed_files.py * Update main.py * Update platform.json * Update platform.py * updates 21.04.2022 (#15) * Tasmota/dev apple * Update platform.json * Update platform.py * Update README.md * Update OCD Apple Silicon to build from 20220424 * esptool.py v3.3 now in registry * Add CMSIS-DAP as available debug probe * Use GetBuildType for detecting debug mode * rm Python2 add C3 exception decoder * remove fix firmware address 0x10000 * Apple arm toolchains for IDF * Arduino framework based on IDF4.4.1 * Use Tasmota release versions * Compile IDF bootloader with optimizations by default By default the size of bootloader is limited to 0x2000 bytes, in debug mode the footprint can be easily grow beyond this limit * Update examples.yml * esptool.py v3.3.1 * Update platform.py * add `_get_board_boot_mode` * esptool.py v4.0.1 * Improve support for assembly programming * Add compatibility with PIO Core 6.0 * Update platform.py * Update examples.yml * Explicitly exit from build process when there is default IDF component * revert Use empty ASM and CXX flags if config empty * Update main.py * Update platform.py * "platformio": "^6" * Update _bare.py * Update platform.py * Delete compat.py * Platformio core 6.0.2 since Tasmota uses ino folder feature, which is introduced with 6.0.2 * Add misso * Esptool v4.1 * really Esptool v4.1 * Boards update * add framework espidf to all boards * Update espidf.py * Update platform.py * Update platform.py --- boards/adafruit_feather_esp32_v2.json | 13 +++-- boards/adafruit_feather_esp32s2_tft.json | 62 ++++++++++++++++++++++ boards/adafruit_feather_esp32s3.json | 63 ++++++++++++++++++++++ boards/adafruit_magtag29_esp32s2.json | 6 +-- boards/adafruit_qtpy_esp32.json | 42 +++++++++++++++ boards/adafruit_qtpy_esp32c3.json | 44 ++++++++++++++++ boards/adafruit_qtpy_esp32s2.json | 62 ++++++++++++++++++++++ boards/adafruit_qtpy_esp32s3.json | 63 ++++++++++++++++++++++ boards/airm2m_core_esp32c3.json | 37 +++++++++++++ boards/alksesp32.json | 3 +- boards/briki_abc_esp32.json | 3 +- boards/briki_mbc-wb_esp32.json | 3 +- boards/deneyapkart1A.json | 41 +++++++++++++++ boards/dpu_esp32.json | 43 +++++++++++++++ boards/esp32s3box.json | 49 +++++++++++++++++ boards/esp32s3camlcd.json | 49 +++++++++++++++++ boards/iotaap_magnolia.json | 3 +- boards/lionbit.json | 12 +++-- boards/lolin_c3_mini.json | 44 ++++++++++++++++ boards/lolin_s2_mini.json | 46 ++++++++++++++++ boards/lolin_s2_pico.json | 46 ++++++++++++++++ boards/sparkfun_esp32s2_thing_plus.json | 3 +- boards/trueverit-iot-driver-mk3.json | 38 ++++++++++++++ boards/ttgo-t-oi-plus.json | 34 ++++++++++++ boards/um_feathers3.json | 49 +++++++++++++++++ boards/um_pros3.json | 49 +++++++++++++++++ boards/um_rmp.json | 46 ++++++++++++++++ boards/um_tinys3.json | 49 +++++++++++++++++ boards/watchy.json | 38 ++++++++++++++ boards/wipy3.json | 37 +++++++++++++ boards/wt32-eth01.json | 39 ++++++++++++++ examples/espidf-ulp-adc/.travis.yml | 67 ------------------------ platform.py | 28 +++++----- 33 files changed, 1114 insertions(+), 97 deletions(-) create mode 100644 boards/adafruit_feather_esp32s2_tft.json create mode 100644 boards/adafruit_feather_esp32s3.json create mode 100644 boards/adafruit_qtpy_esp32.json create mode 100644 boards/adafruit_qtpy_esp32c3.json create mode 100644 boards/adafruit_qtpy_esp32s2.json create mode 100644 boards/adafruit_qtpy_esp32s3.json create mode 100644 boards/airm2m_core_esp32c3.json create mode 100644 boards/deneyapkart1A.json create mode 100644 boards/dpu_esp32.json create mode 100644 boards/esp32s3box.json create mode 100644 boards/esp32s3camlcd.json create mode 100644 boards/lolin_c3_mini.json create mode 100644 boards/lolin_s2_mini.json create mode 100644 boards/lolin_s2_pico.json create mode 100644 boards/trueverit-iot-driver-mk3.json create mode 100644 boards/ttgo-t-oi-plus.json create mode 100644 boards/um_feathers3.json create mode 100644 boards/um_pros3.json create mode 100644 boards/um_rmp.json create mode 100644 boards/um_tinys3.json create mode 100644 boards/watchy.json create mode 100644 boards/wipy3.json create mode 100644 boards/wt32-eth01.json delete mode 100644 examples/espidf-ulp-adc/.travis.yml diff --git a/boards/adafruit_feather_esp32_v2.json b/boards/adafruit_feather_esp32_v2.json index 2cd0eede4..a45636e4d 100644 --- a/boards/adafruit_feather_esp32_v2.json +++ b/boards/adafruit_feather_esp32_v2.json @@ -4,10 +4,15 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DADAFRUIT_FEATHER_ESP32_V2 -DBOARD_HAS_PSRAM", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32_V2", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", + "f_flash": "40000000L", + "flash_mode": "dio", "mcu": "esp32", "variant": "adafruit_feather_esp32_v2" }, @@ -30,7 +35,7 @@ "maximum_ram_size": 327680, "maximum_size": 8388608, "require_upload_port": true, - "speed": 921600 + "speed": 460800 }, "url": "https://www.adafruit.com/product/5400", "vendor": "Adafruit" diff --git a/boards/adafruit_feather_esp32s2_tft.json b/boards/adafruit_feather_esp32s2_tft.json new file mode 100644 index 000000000..6f141b03c --- /dev/null +++ b/boards/adafruit_feather_esp32s2_tft.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x810F" + ], + [ + "0x239A", + "0x010F" + ], + [ + "0x239A", + "0x8110" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_feather_esp32s2_tft" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S2 TFT", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2_tft/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5300", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json new file mode 100644 index 000000000..d6e5e97ec --- /dev/null +++ b/boards/adafruit_feather_esp32s3.json @@ -0,0 +1,63 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8113" + ], + [ + "0x239A", + "0x0113" + ], + [ + "0x239A", + "0x8114" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3_nopsram" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S3 No PSRAM", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5323", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_magtag29_esp32s2.json b/boards/adafruit_magtag29_esp32s2.json index 40d7bd3e9..5e2dd717f 100644 --- a/boards/adafruit_magtag29_esp32s2.json +++ b/boards/adafruit_magtag29_esp32s2.json @@ -15,15 +15,15 @@ "hwids": [ [ "0x239A", - "0x80DF" + "0x80E5" ], [ "0x239A", - "0x00DF" + "0x00E5" ], [ "0x239A", - "0x80E0" + "0x80E6" ] ], "mcu": "esp32s2", diff --git a/boards/adafruit_qtpy_esp32.json b/boards/adafruit_qtpy_esp32.json new file mode 100644 index 000000000..39896da9d --- /dev/null +++ b/boards/adafruit_qtpy_esp32.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32_PICO", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "adafruit_qtpy_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5395", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32c3.json b/boards/adafruit_qtpy_esp32c3.json new file mode 100644 index 000000000..335002d1c --- /dev/null +++ b/boards/adafruit_qtpy_esp32c3.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32C3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "dout", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "adafruit_qtpy_esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5405", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32s2.json b/boards/adafruit_qtpy_esp32s2.json new file mode 100644 index 000000000..30f51dcec --- /dev/null +++ b/boards/adafruit_qtpy_esp32s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8111" + ], + [ + "0x239A", + "0x0111" + ], + [ + "0x239A", + "0x8112" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_qtpy_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S2", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_qtpy_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5325", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32s3.json b/boards/adafruit_qtpy_esp32s3.json new file mode 100644 index 000000000..067d8a676 --- /dev/null +++ b/boards/adafruit_qtpy_esp32s3.json @@ -0,0 +1,63 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8119" + ], + [ + "0x239A", + "0x0119" + ], + [ + "0x239A", + "0x811A" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_qtpy_esp32s3_nopsram" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S3 No PSRAM", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5426", + "vendor": "Adafruit" +} diff --git a/boards/airm2m_core_esp32c3.json b/boards/airm2m_core_esp32c3.json new file mode 100644 index 000000000..e227fadd8 --- /dev/null +++ b/boards/airm2m_core_esp32c3.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "extra_flags": [ + "-DARDUINO_AirM2M_CORE_ESP32C3", + "-DARDUINO_USB_MODE=1" + ], + "mcu": "esp32c3", + "variant": "AirM2M_CORE_ESP32C3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "AirM2M CORE ESP32C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.luatos.com/chips/esp32c3/board.html", + "vendor": "AirM2M" +} diff --git a/boards/alksesp32.json b/boards/alksesp32.json index 6a4ae15ad..3e2e67b9b 100644 --- a/boards/alksesp32.json +++ b/boards/alksesp32.json @@ -21,7 +21,8 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "ALKS ESP32", "upload": { diff --git a/boards/briki_abc_esp32.json b/boards/briki_abc_esp32.json index 429514895..53113bb1b 100644 --- a/boards/briki_abc_esp32.json +++ b/boards/briki_abc_esp32.json @@ -22,7 +22,8 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "Briki ABC (MBC-WB) - ESP32", "upload": { diff --git a/boards/briki_mbc-wb_esp32.json b/boards/briki_mbc-wb_esp32.json index df5c3756a..86af17f3f 100644 --- a/boards/briki_mbc-wb_esp32.json +++ b/boards/briki_mbc-wb_esp32.json @@ -22,7 +22,8 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "Briki MBC-WB - ESP32", "upload": { diff --git a/boards/deneyapkart1A.json b/boards/deneyapkart1A.json new file mode 100644 index 000000000..436950859 --- /dev/null +++ b/boards/deneyapkart1A.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYDK1A", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "deneyapkart1A" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart 1A", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/magaza/urun-deneyap-kart.html", + "vendor": "Deneyap" +} diff --git a/boards/dpu_esp32.json b/boards/dpu_esp32.json new file mode 100644 index 000000000..1d6ed4eb3 --- /dev/null +++ b/boards/dpu_esp32.json @@ -0,0 +1,43 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DPU_ESP32", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "dpu_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TAMC DPU ESP32", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/TAMCTec/dpu-esp32", + "vendor": "TAMC" +} diff --git a/boards/esp32s3box.json b/boards/esp32s3box.json new file mode 100644 index 000000000..2d7f99db4 --- /dev/null +++ b/boards/esp32s3box.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qspi_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_ESP32_S3_BOX", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3box" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S3-Box", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5290", + "vendor": "Espressif" +} diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json new file mode 100644 index 000000000..34810b5a5 --- /dev/null +++ b/boards/esp32s3camlcd.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "memory_type": "opi_opi" + }, + "boot": "opi", + "core": "esp32", + "extra_flags": [ + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_ESP32S3_CAM_LCD", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dout", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3camlcd" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ESP32S3 CAM LCD", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.espressif.com/en/news/Maple_Eye_ESP32-S3", + "vendor": "Espressif" +} diff --git a/boards/iotaap_magnolia.json b/boards/iotaap_magnolia.json index 47c1ebad6..fffc85354 100644 --- a/boards/iotaap_magnolia.json +++ b/boards/iotaap_magnolia.json @@ -21,7 +21,8 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino" + "arduino", + "espidf" ], "name": "IoTaaP Magnolia", "upload": { diff --git a/boards/lionbit.json b/boards/lionbit.json index 41e4cf65e..c8186d0b2 100644 --- a/boards/lionbit.json +++ b/boards/lionbit.json @@ -4,13 +4,17 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", + "extra_flags": [ + "-DARDUINO_LIONBIT", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", "flags" : "-DCORE_DEBUG_LEVEL=5", "mcu": "esp32", - "variant": "esp32" + "variant": "lionbit" }, "connectivity": [ "wifi", @@ -25,7 +29,7 @@ "arduino", "espidf" ], - "name": "LionBit", + "name": "Lion:Bit Dev Board", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, @@ -37,5 +41,5 @@ "speed" : 115200 }, "url": "http://lionbit.lk/", - "vendor": "Lion::Bit" + "vendor": "Lion:Bit" } diff --git a/boards/lolin_c3_mini.json b/boards/lolin_c3_mini.json new file mode 100644 index 000000000..76304465f --- /dev/null +++ b/boards/lolin_c3_mini.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LOLIN_C3_MINI", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN C3 Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc/en/latest/c3/c3_mini.html", + "vendor": "WEMOS" +} diff --git a/boards/lolin_s2_mini.json b/boards/lolin_s2_mini.json new file mode 100644 index 000000000..3fe4f7122 --- /dev/null +++ b/boards/lolin_s2_mini.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LOLIN_S2_MINI", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x80C2" + ] + ], + "mcu": "esp32s2", + "variant": "lolin_s2_mini" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_board": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S2 Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.wemos.cc/en/latest/s2/s2_mini.html", + "vendor": "WEMOS" +} diff --git a/boards/lolin_s2_pico.json b/boards/lolin_s2_pico.json new file mode 100644 index 000000000..dab2b7ec0 --- /dev/null +++ b/boards/lolin_s2_pico.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LOLIN_S2_PICO", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x80C5" + ] + ], + "mcu": "esp32s2", + "variant": "lolin_s2_pico" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_board": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S2 PICO", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.wemos.cc/en/latest/s2/s2_pico.html", + "vendor": "WEMOS" +} diff --git a/boards/sparkfun_esp32s2_thing_plus.json b/boards/sparkfun_esp32s2_thing_plus.json index 269d962fc..763c409c8 100644 --- a/boards/sparkfun_esp32s2_thing_plus.json +++ b/boards/sparkfun_esp32s2_thing_plus.json @@ -32,7 +32,6 @@ "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, - "mode": "usb", "use_1200bps_touch": true, "wait_for_upload_port": true, "require_upload_port": true, @@ -40,4 +39,4 @@ }, "url": "https://www.sparkfun.com/products/17743", "vendor": "SparkFun" -} +} \ No newline at end of file diff --git a/boards/trueverit-iot-driver-mk3.json b/boards/trueverit-iot-driver-mk3.json new file mode 100644 index 000000000..c74f96011 --- /dev/null +++ b/boards/trueverit-iot-driver-mk3.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver_MK_III", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver-mkiii" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver MK III", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} + diff --git a/boards/ttgo-t-oi-plus.json b/boards/ttgo-t-oi-plus.json new file mode 100644 index 000000000..3b05918ef --- /dev/null +++ b/boards/ttgo-t-oi-plus.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": "-DARDUINO_TTGO_T_OI_PLUS_DEV", + "mcu": "esp32c3", + "variant": "ttgo-t-oi-plus" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO T-OI PLUS RISC-V ESP32-C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.lilygo.cn/prod_view.aspx?TypeId=50044&Id=1361&FId=t3:50044:3", + "vendor": "TTGO" +} diff --git a/boards/um_feathers3.json b/boards/um_feathers3.json new file mode 100644 index 000000000..435123421 --- /dev/null +++ b/boards/um_feathers3.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x80D0" + ] + ], + "mcu": "esp32s3", + "variant": "um_feathers3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker FeatherS3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/feathers3", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_pros3.json b/boards/um_pros3.json new file mode 100644 index 000000000..e4ba4ee4a --- /dev/null +++ b/boards/um_pros3.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_PROS3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x80D0" + ] + ], + "mcu": "esp32s3", + "variant": "um_pros3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker PROS3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/pros3", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_rmp.json b/boards/um_rmp.json new file mode 100644 index 000000000..c5e547acc --- /dev/null +++ b/boards/um_rmp.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_RMP", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x80F6" + ] + ], + "mcu": "esp32s2", + "variant": "um_rmp" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker RMP", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://unexpectedmaker.com/esp32s2", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_tinys3.json b/boards/um_tinys3.json new file mode 100644 index 000000000..7a72da444 --- /dev/null +++ b/boards/um_tinys3.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TINYS3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x80D0" + ] + ], + "mcu": "esp32s3", + "variant": "um_tinys3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker TinyS3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/ttinys3-esp32s3", + "vendor": "Unexpected Maker" +} diff --git a/boards/watchy.json b/boards/watchy.json new file mode 100644 index 000000000..f91eed072 --- /dev/null +++ b/boards/watchy.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "huge_app.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_WATCHY", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "watchy" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SQFMI Watchy v2.0", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://watchy.sqfmi.com/", + "vendor": "SQFMI" +} diff --git a/boards/wipy3.json b/boards/wipy3.json new file mode 100644 index 000000000..b9e5419b1 --- /dev/null +++ b/boards/wipy3.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_WIPY3", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "wipy3" + }, + "connectivity": [ + "wifi", + "bluetooth", + "can", + "ethernet" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Pycom WiPy3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 1310720, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://pycom.io/", + "vendor": "Pycom Ltd." +} diff --git a/boards/wt32-eth01.json b/boards/wt32-eth01.json new file mode 100644 index 000000000..e5a5192cf --- /dev/null +++ b/boards/wt32-eth01.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_WT32_ETH01" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "wt32-eth01" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Wireless-Tag WT32-ETH01 Ethernet Module", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.wireless-tag.com/portfolio/wt32-eth01/", + "vendor": "Wireless-Tag" +} diff --git a/examples/espidf-ulp-adc/.travis.yml b/examples/espidf-ulp-adc/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-ulp-adc/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/platform.py b/platform.py index 7502c1935..9b048fcf6 100644 --- a/platform.py +++ b/platform.py @@ -106,7 +106,7 @@ def configure_default_packages(self, variables, targets): if mcu in ("esp32s2", "esp32s3", "esp32c3"): self.packages.pop("toolchain-esp32ulp", None) - if mcu == "esp32" or mcu == "esp32c3": + if mcu != "esp32s2": self.packages.pop("toolchain-esp32s2ulp", None) # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp"]["optional"] = False @@ -120,16 +120,13 @@ def configure_default_packages(self, variables, targets): if mcu in ("esp32s2", "esp32s3", "esp32c3"): self.packages.pop("toolchain-esp32ulp", None) - if mcu == "esp32" or mcu == "esp32c3": + if mcu != "esp32s2": self.packages.pop("toolchain-esp32s2ulp", None) # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp-arm"]["optional"] = False - is_legacy_project = ( - build_core == "mbcwb" - ) - if is_legacy_project: + if build_core == "mbcwb": # Remove the main toolchains from PATH for toolchain in ( "toolchain-xtensa-esp32", @@ -143,9 +140,7 @@ def configure_default_packages(self, variables, targets): self.packages["toolchain-xtensa32"] = { "type": "toolchain", "owner": "platformio", - "version": "~2.80400.0" - if "arduino" in frameworks and build_core != "mbcwb" - else "~2.50200.0", + "version": "~2.50200.0" } if build_core == "mbcwb": @@ -180,7 +175,7 @@ def _add_dynamic_options(self, board): supported_debug_tools = [ "cmsis-dap", "esp-prog", - "esp_usb_jtag", + "esp-bridge", "iot-bus-jtag", "jlink", "minimodule", @@ -191,6 +186,10 @@ def _add_dynamic_options(self, board): "tumpa", ] + if board.get("build.mcu", "") in ("esp32c3", "esp32s3"): + supported_debug_tools.append("esp-builtin") + + upload_protocol = board.manifest.get("upload", {}).get("protocol") upload_protocols = board.manifest.get("upload", {}).get("protocols", []) if debug: @@ -202,18 +201,21 @@ def _add_dynamic_options(self, board): if "tools" not in debug: debug["tools"] = {} - # Only FTDI based debug probes for link in upload_protocols: if link in non_debug_protocols or link in debug["tools"]: continue - if link in ("jlink", "cmsis-dap", "esp_usb_jtag"): + if link in ("jlink", "cmsis-dap"): openocd_interface = link elif link in ("esp-prog", "ftdi"): if board.id == "esp32-s2-kaluga-1": openocd_interface = "ftdi/esp32s2_kaluga_v1" else: openocd_interface = "ftdi/esp32_devkitj_v1" + elif link == "esp-bridge": + openocd_interface = "esp_usb_bridge" + elif link == "esp-builtin": + openocd_interface = "esp_usb_jtag" else: openocd_interface = "ftdi/" + link @@ -387,4 +389,4 @@ def configure_upstream_arduino_packages(self, url_items): print("Configuring toolchain packages from a remote source...") self.configure_arduino_toolchains( self.download_remote_package_index(url_items) - ) + ) \ No newline at end of file From 9eff55cb67ae148d24d3364833202786f7d33556 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Jun 2022 12:47:48 +0200 Subject: [PATCH 070/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 82c9a2bfa..43d9ec728 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # Tasmota Espressif 32: development platform for [PlatformIO](http://platformio.org) -[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml)[![GitHub Releases](https://img.shields.io/github/downloads/Jason2866/platform-espressif32/total?label=downloads)](https://github.com/Jason2866/platform-espressif32/releases/latest) +[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml)[![GitHub Releases](https://img.shields.io/github/downloads/tasmota/platform-espressif32/total?label=downloads)](https://github.com/tasmota/platform-espressif32/releases/latest) Espressif Systems is a privately held fabless semiconductor company. They provide wireless communications and Wi-Fi chips which are widely used in mobile devices and the Internet of Things applications. From 73e94436666c5407da2f073c0ac41272382d9217 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Jun 2022 12:49:01 +0200 Subject: [PATCH 071/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 82c9a2bfa..43d9ec728 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # Tasmota Espressif 32: development platform for [PlatformIO](http://platformio.org) -[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml)[![GitHub Releases](https://img.shields.io/github/downloads/Jason2866/platform-espressif32/total?label=downloads)](https://github.com/Jason2866/platform-espressif32/releases/latest) +[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml)[![GitHub Releases](https://img.shields.io/github/downloads/tasmota/platform-espressif32/total?label=downloads)](https://github.com/tasmota/platform-espressif32/releases/latest) Espressif Systems is a privately held fabless semiconductor company. They provide wireless communications and Wi-Fi chips which are widely used in mobile devices and the Internet of Things applications. From 14e336b28c2fd6d9a7740f9a4827ee98ba40861b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Jun 2022 21:08:13 +0200 Subject: [PATCH 072/666] Back to esptool.py v3.3.1 since v4 does not work with S3 > 4MB !! --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 2206aa46f..499671286 100644 --- a/platform.json +++ b/platform.json @@ -120,7 +120,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v3.3.1/esptool-3.3.1.zip" }, "tool-mbctool": { "optional": true, From 749a7e8a9bacc81306932eb0e1675b957e476c6c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Jun 2022 21:55:18 +0200 Subject: [PATCH 073/666] --dont-append-digest --- builder/main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/builder/main.py b/builder/main.py index bbfa4f49f..3bc063307 100644 --- a/builder/main.py +++ b/builder/main.py @@ -232,6 +232,7 @@ def __fetch_fs_size(target, source, env): action=env.VerboseAction(" ".join([ '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", + "--dont-append-digest", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "detect"), @@ -363,6 +364,7 @@ def __fetch_fs_size(target, source, env): platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), UPLOADERFLAGS=[ "--chip", mcu, + "--dont-append-digest", "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", "--before", "default_reset", @@ -381,6 +383,7 @@ def __fetch_fs_size(target, source, env): env.Replace( UPLOADERFLAGS=[ "--chip", mcu, + "--dont-append-digest", "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", "--before", "default_reset", From 4635e092a221f3ff4a2b1ed8da2b662008272a34 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 17 Jun 2022 12:05:47 +0200 Subject: [PATCH 074/666] Back to esptool v3.3.1 since header patching is not working anymore when using esptool merge --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 2206aa46f..499671286 100644 --- a/platform.json +++ b/platform.json @@ -120,7 +120,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v3.3.1/esptool-3.3.1.zip" }, "tool-mbctool": { "optional": true, From dd81ae099eac6d12169a05138ac8f0d67479d8d1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 17 Jun 2022 12:06:38 +0200 Subject: [PATCH 075/666] revert "--dont-append-digest" --- builder/main.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/builder/main.py b/builder/main.py index 3bc063307..bbfa4f49f 100644 --- a/builder/main.py +++ b/builder/main.py @@ -232,7 +232,6 @@ def __fetch_fs_size(target, source, env): action=env.VerboseAction(" ".join([ '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", - "--dont-append-digest", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "detect"), @@ -364,7 +363,6 @@ def __fetch_fs_size(target, source, env): platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), UPLOADERFLAGS=[ "--chip", mcu, - "--dont-append-digest", "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", "--before", "default_reset", @@ -383,7 +381,6 @@ def __fetch_fs_size(target, source, env): env.Replace( UPLOADERFLAGS=[ "--chip", mcu, - "--dont-append-digest", "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", "--before", "default_reset", From 472b00cc6c0d8fd76ec47c6a3b05ea7f91a2f9f0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Jun 2022 22:19:57 +0200 Subject: [PATCH 076/666] Tasmota 204pre --- boards/esp32-s3-devkitc-1.json | 3 +-- boards/esp32-s3-usb.json | 3 +-- platform.json | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json index 67c43b8f6..01a39aa5f 100644 --- a/boards/esp32-s3-devkitc-1.json +++ b/boards/esp32-s3-devkitc-1.json @@ -1,8 +1,7 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld", - "memory_type": "qspi_qspi" + "ldscript": "esp32s3_out.ld" }, "core": "esp32", "extra_flags": "-DBOARD_HAS_PSRAM", diff --git a/boards/esp32-s3-usb.json b/boards/esp32-s3-usb.json index 92daae518..f741cafe6 100644 --- a/boards/esp32-s3-usb.json +++ b/boards/esp32-s3-usb.json @@ -1,8 +1,7 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld", - "memory_type": "qspi_qspi" + "ldscript": "esp32s3_out.ld" }, "core": "esp32", "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0", diff --git a/platform.json b/platform.json index 499671286..2ddfedbe3 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.3", + "version": "2.0.4pre", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.3/framework-arduinoespressif32-203.tar.gz" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.4pre/framework-arduinoespressif32-204pre.tar.gz" }, "framework-espidf": { "type": "framework", From 0023bb89e4b16fb89ecd76e43b9c97499b152e5a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 1 Jul 2022 20:21:05 +0200 Subject: [PATCH 077/666] Update esp32-s3-devkitc-1.json --- boards/esp32-s3-devkitc-1.json | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json index 67c43b8f6..9f32208fc 100644 --- a/boards/esp32-s3-devkitc-1.json +++ b/boards/esp32-s3-devkitc-1.json @@ -2,13 +2,24 @@ "build": { "arduino":{ "ldscript": "esp32s3_out.ld", - "memory_type": "qspi_qspi" + "partitions": "default_8MB.csv" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], "mcu": "esp32s3", "variant": "esp32s3" }, @@ -16,16 +27,20 @@ "wifi" ], "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], "openocd_target": "esp32s3.cfg" }, "frameworks": [ "arduino", "espidf" ], - "name": "Espressif ESP32-S3-DevKitC-1", + "name": "Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)", "upload": { "flash_size": "8MB", - "maximum_ram_size": 524288, + "maximum_ram_size": 327680, "maximum_size": 8388608, "require_upload_port": true, "speed": 460800 From 4c5de63d3d4eb0a71ead3901a32bc8e2ccb7a9a2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 1 Jul 2022 20:24:01 +0200 Subject: [PATCH 078/666] Update esp32-s3-devkitc-1.json --- boards/esp32-s3-devkitc-1.json | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json index 01a39aa5f..9f32208fc 100644 --- a/boards/esp32-s3-devkitc-1.json +++ b/boards/esp32-s3-devkitc-1.json @@ -1,13 +1,25 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld" + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], "mcu": "esp32s3", "variant": "esp32s3" }, @@ -15,16 +27,20 @@ "wifi" ], "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], "openocd_target": "esp32s3.cfg" }, "frameworks": [ "arduino", "espidf" ], - "name": "Espressif ESP32-S3-DevKitC-1", + "name": "Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)", "upload": { "flash_size": "8MB", - "maximum_ram_size": 524288, + "maximum_ram_size": 327680, "maximum_size": 8388608, "require_upload_port": true, "speed": 460800 From ab5fd3360feab92dcd1b95dd13f65a04bb5fd850 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 6 Jul 2022 20:15:21 +0200 Subject: [PATCH 079/666] Core 2.0.4 / IDF 442 (#23) --- boards/adafruit_feather_esp32s3.json | 4 ++-- platform.json | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json index d6e5e97ec..85d530afb 100644 --- a/boards/adafruit_feather_esp32s3.json +++ b/boards/adafruit_feather_esp32s3.json @@ -50,9 +50,9 @@ ] ] }, - "flash_size": "4MB", + "flash_size": "8MB", "maximum_ram_size": 327680, - "maximum_size": 4194304, + "maximum_size": 8388608, "use_1200bps_touch": true, "wait_for_upload_port": true, "require_upload_port": true, diff --git a/platform.json b/platform.json index 2ddfedbe3..816653d7e 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.4pre", + "version": "2.0.4", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -37,13 +37,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.4pre/framework-arduinoespressif32-204pre.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/880/framework-arduinoespressif32.tar.gz" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.1/esp-idf-v4.4.1.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.2/esp-idf-v4.4.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 667e2cc331696fcc64d047a37892a8d52e9b0f30 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 6 Jul 2022 20:27:09 +0200 Subject: [PATCH 080/666] Tasmota github for core 204 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 816653d7e..58b71cff7 100644 --- a/platform.json +++ b/platform.json @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/880/framework-arduinoespressif32.tar.gz" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.4/framework-arduinoespressif32-204.tar.gz" }, "framework-espidf": { "type": "framework", From cb740a5fb62dd75fb1972bcede3efb7d351fa720 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 7 Jul 2022 12:00:56 +0200 Subject: [PATCH 081/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 43d9ec728..16e2ee1cb 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid ```ini [env:stable] -platform = replace with url +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4/platform-espressif32-2.0.4.zip board = ... ... ``` From 46040f98cdaf082a5183570d2ab5555e5d1165a1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 7 Jul 2022 19:51:33 +0200 Subject: [PATCH 082/666] core 2.0.4 --- boards/adafruit_feather_esp32s3.json | 4 ++-- boards/esp32-s3-usb.json | 3 +-- platform.json | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json index d6e5e97ec..85d530afb 100644 --- a/boards/adafruit_feather_esp32s3.json +++ b/boards/adafruit_feather_esp32s3.json @@ -50,9 +50,9 @@ ] ] }, - "flash_size": "4MB", + "flash_size": "8MB", "maximum_ram_size": 327680, - "maximum_size": 4194304, + "maximum_size": 8388608, "use_1200bps_touch": true, "wait_for_upload_port": true, "require_upload_port": true, diff --git a/boards/esp32-s3-usb.json b/boards/esp32-s3-usb.json index 92daae518..f741cafe6 100644 --- a/boards/esp32-s3-usb.json +++ b/boards/esp32-s3-usb.json @@ -1,8 +1,7 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld", - "memory_type": "qspi_qspi" + "ldscript": "esp32s3_out.ld" }, "core": "esp32", "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0", diff --git a/platform.json b/platform.json index 499671286..816653d7e 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.3", + "version": "2.0.4", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -37,13 +37,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.3/framework-arduinoespressif32-203.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/880/framework-arduinoespressif32.tar.gz" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.1/esp-idf-v4.4.1.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.2/esp-idf-v4.4.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From f9d0a9aba06ba7ed32deb7a5b81f7e75248cdecc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 7 Jul 2022 19:55:53 +0200 Subject: [PATCH 083/666] Tasmota github as source --- README.md | 2 +- platform.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 43d9ec728..16e2ee1cb 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid ```ini [env:stable] -platform = replace with url +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4/platform-espressif32-2.0.4.zip board = ... ... ``` diff --git a/platform.json b/platform.json index 816653d7e..58b71cff7 100644 --- a/platform.json +++ b/platform.json @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/880/framework-arduinoespressif32.tar.gz" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.4/framework-arduinoespressif32-204.tar.gz" }, "framework-espidf": { "type": "framework", From 120f7653f0ba21ce07cfa05fc25116b5d17a1f21 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Jul 2022 18:05:28 +0200 Subject: [PATCH 084/666] --dont-append-digest --- builder/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/main.py b/builder/main.py index bbfa4f49f..a666270b1 100644 --- a/builder/main.py +++ b/builder/main.py @@ -232,6 +232,7 @@ def __fetch_fs_size(target, source, env): action=env.VerboseAction(" ".join([ '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", + "--dont-append-digest", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "detect"), From 499430f0f8fb294bf8f6e312fab0d560daa2904a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Jul 2022 18:06:03 +0200 Subject: [PATCH 085/666] esptool v4.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 58b71cff7..022a54121 100644 --- a/platform.json +++ b/platform.json @@ -120,7 +120,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v3.3.1/esptool-3.3.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.1.zip" }, "tool-mbctool": { "optional": true, From 4a81b6085c107b69b28e2082919ce02175271091 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 17 Jul 2022 18:27:26 +0200 Subject: [PATCH 086/666] 2.0.5dev --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 022a54121..6c52c8e8f 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.4", + "version": "2.0.5dev", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.4/framework-arduinoespressif32-204.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/912/framework-arduinoespressif32-442_esp41-ce8eca3a26.tar.gz" }, "framework-espidf": { "type": "framework", From 5fe82818fb31ca203b138240b910384c533e03ef Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 17 Jul 2022 18:31:05 +0200 Subject: [PATCH 087/666] platformio": ">=6.1.0 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 6c52c8e8f..fc07c6793 100644 --- a/platform.json +++ b/platform.json @@ -12,7 +12,7 @@ "RISC-V" ], "engines": { - "platformio": ">=6.0.2" + "platformio": ">=6.1.0" }, "repository": { "type": "git", From f2a78a19c8165d48b398aade5ce0458f72da0855 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 17 Jul 2022 18:46:54 +0200 Subject: [PATCH 088/666] Update espidf.py --- builder/frameworks/espidf.py | 73 +++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index a360a04e3..2e7e0cce1 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1249,7 +1249,6 @@ def _get_installed_pip_packages(): project_flags = get_app_flags(project_config, default_config) link_args = extract_link_args(elf_config) app_includes = get_app_includes(elf_config) -project_lib_includes = get_project_lib_includes(env) # # Compile bootloader @@ -1304,32 +1303,6 @@ def _skip_prj_source_files(node): env.AddBuildMiddleware(_skip_prj_source_files) -# Project files should be compiled only when a special -# option is enabled when running 'test' command -if "__test" not in COMMAND_LINE_TARGETS or env.GetProjectOption( - "test_build_project_src" -): - project_env = env.Clone() - if project_target_name != "__idf_main": - # Manually add dependencies to CPPPATH since ESP-IDF build system doesn't generate - # this info if the folder with sources is not named 'main' - # https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#rename-main - project_env.AppendUnique(CPPPATH=app_includes["plain_includes"]) - - # Add include dirs from PlatformIO build system to project CPPPATH so - # they're visible to PIOBUILDFILES - project_env.Append( - CPPPATH=["$PROJECT_INCLUDE_DIR", "$PROJECT_SRC_DIR"] + project_lib_includes - ) - - env.Append( - PIOBUILDFILES=compile_source_files( - target_configs.get(project_target_name), - project_env, - project_env.subst("$PROJECT_DIR"), - ) - ) - # # Generate partition table # @@ -1390,6 +1363,52 @@ def _skip_prj_source_files(node): ], ) +# +# Propagate Arduino defines to the main build environment +# + +if "arduino" in env.subst("$PIOFRAMEWORK"): + arduino_config_name = list( + filter( + lambda config_name: config_name.startswith( + "__idf_framework-arduinoespressif32" + ), + target_configs, + ) + )[0] + env.AppendUnique( + CPPDEFINES=extract_defines( + target_configs.get(arduino_config_name, {}).get("compileGroups", [])[0] + ) + ) + +# Project files should be compiled only when a special +# option is enabled when running 'test' command +if "__test" not in COMMAND_LINE_TARGETS or env.GetProjectOption( + "test_build_project_src" +): + project_env = env.Clone() + if project_target_name != "__idf_main": + # Manually add dependencies to CPPPATH since ESP-IDF build system doesn't generate + # this info if the folder with sources is not named 'main' + # https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#rename-main + project_env.AppendUnique(CPPPATH=app_includes["plain_includes"]) + + # Add include dirs from PlatformIO build system to project CPPPATH so + # they're visible to PIOBUILDFILES + project_env.AppendUnique( + CPPPATH=["$PROJECT_INCLUDE_DIR", "$PROJECT_SRC_DIR"] + + get_project_lib_includes(env) + ) + + env.Append( + PIOBUILDFILES=compile_source_files( + target_configs.get(project_target_name), + project_env, + project_env.subst("$PROJECT_DIR"), + ) + ) + # # Generate mbedtls bundle # From c06e78baf675e21a2035167a477cecd87784b56d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 26 Jul 2022 18:31:57 +0200 Subject: [PATCH 089/666] Add default nameOnDisk value for external CMake projects --- builder/frameworks/espidf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 2e7e0cce1..bfbc70542 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -818,6 +818,8 @@ def get_targets_by_type(target_configs, target_types, ignore_targets=None): def get_components_map(target_configs, target_types, ignore_components=None): result = {} for config in get_targets_by_type(target_configs, target_types, ignore_components): + if "nameOnDisk" not in config: + config["nameOnDisk"] = "lib%s.a" % config["name"] result[config["id"]] = {"config": config} return result From dc33007e0df5588587393d74f51a2d874ae125ce Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 28 Jul 2022 19:17:32 +0200 Subject: [PATCH 090/666] Build 918 newest wifi libs from idf44 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index fc07c6793..df4b5ebfd 100644 --- a/platform.json +++ b/platform.json @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/912/framework-arduinoespressif32-442_esp41-ce8eca3a26.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/918/framework-arduinoespressif32-442_esp41-554da8627d.tar.gz" }, "framework-espidf": { "type": "framework", From 27dfa7eaefaa5b9e767bb12a49050df3f39f9b6d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 29 Jul 2022 14:27:38 +0200 Subject: [PATCH 091/666] Tasmota IDF 4.4.3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index df4b5ebfd..15444875f 100644 --- a/platform.json +++ b/platform.json @@ -43,7 +43,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.2/esp-idf-v4.4.2.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From f9a33fac9f90606ccd04e61360b956ce672e3e2b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 29 Jul 2022 15:44:51 +0200 Subject: [PATCH 092/666] Tasmota Core 2.0.4.1 based on IDF 4.4.3 --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 58b71cff7..520ce0892 100644 --- a/platform.json +++ b/platform.json @@ -37,13 +37,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.4/framework-arduinoespressif32-204.tar.gz" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.4.1/framework-arduinoespressif32.tar.gz" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.2/esp-idf-v4.4.2.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 70c2615d4170b25bdcc7635660f58d36b9ad8c2a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 29 Jul 2022 16:06:34 +0200 Subject: [PATCH 093/666] Tasmota release Core 2.0.4.1 --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 15444875f..a38d53edc 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.5dev", + "version": "2.0.4+1", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/918/framework-arduinoespressif32-442_esp41-554da8627d.tar.gz" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.4.1/framework-arduinoespressif32.tar.gz" }, "framework-espidf": { "type": "framework", From f50b7729533395e76a951051964e62eadd4cc3a6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 29 Jul 2022 20:55:01 +0200 Subject: [PATCH 094/666] stable 2.0.4.1 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16e2ee1cb..f4a06b969 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid ```ini [env:stable] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4/platform-espressif32-2.0.4.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4.1/platform-espressif32-2.0.4.1.zip board = ... ... ``` From 6683ce4215cae37e009ef75de0a0ff715bb072a7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 31 Jul 2022 13:06:54 +0200 Subject: [PATCH 095/666] Merge firmware before flashing via OpenOCD --- builder/main.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/builder/main.py b/builder/main.py index a666270b1..41a93dc05 100644 --- a/builder/main.py +++ b/builder/main.py @@ -162,6 +162,18 @@ def __fetch_fs_size(target, source, env): return (target, source) +def merge_binaries(source, target, env, for_signature): + return " ".join([ + '"$PYTHONEXE"', + join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), + "--chip", mcu, "merge_bin", + "-o", "$TARGET", + "--flash_mode", "$BOARD_FLASH_MODE", + "--flash_size", board.get("upload.flash_size", "4MB"), + "$ESP32_APP_OFFSET", "$SOURCES" + ] + ['"%s"' % itm for img in env.get("FLASH_EXTRA_IMAGES", []) for itm in img]) + + env = DefaultEnvironment() platform = env.PioPlatform() board = env.BoardConfig() @@ -171,6 +183,24 @@ def __fetch_fs_size(target, source, env): if mcu == "esp32c3": toolchain_arch = "riscv32-esp" +# Arduino core v2.0.4 contains updated bootloader images that have innacurate default +# headers. This results in bootloops if firmware is flashed via OpenOCD (e.g. debugging +# or uploading via debug tools). For this reason, before uploading or debugging we need +# to merge binaries via esptoolpy so that the image headers will be adjusted according to +# --flash-size and --flash-mode arguments. +# Note: This behavior doesn't occur if uploading is done via esptoolpy, as esptoolpy +# overrides the binary image headers before flashing. +firmware_merge_required = bool( + env.get("PIOFRAMEWORK", []) == ["arduino"] + and ( + "debug" in env.GetBuildType() + or env.subst("$UPLOAD_PROTOCOL") in board.get("debug.tools", {}) + ) +) + +if "INTEGRATION_EXTRA_DATA" not in env: + env["INTEGRATION_EXTRA_DATA"] = {} + env.Replace( __get_board_boot_mode=_get_board_boot_mode, __get_board_f_flash=_get_board_f_flash, @@ -235,7 +265,7 @@ def __fetch_fs_size(target, source, env): "--dont-append-digest", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", board.get("upload.flash_size", "detect"), + "--flash_size", board.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" ]), "Building $TARGET"), suffix=".bin" @@ -262,6 +292,10 @@ def __fetch_fs_size(target, source, env): source_factory=env.Dir, suffix=".bin", ), + MergeBin=Builder( + generator=merge_binaries, + suffix=".bin", + ), ) ) @@ -273,6 +307,7 @@ def __fetch_fs_size(target, source, env): # target_elf = None +target_firm_merged = None if "nobuild" in COMMAND_LINE_TARGETS: target_elf = join("$BUILD_DIR", "${PROGNAME}.elf") if set(["uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): @@ -291,6 +326,14 @@ def __fetch_fs_size(target, source, env): else: target_firm = env.ElfToBin( join("$BUILD_DIR", "${PROGNAME}"), target_elf) + if firmware_merge_required: + # Note: Default offset address must be set to 0x0 because debugging + # relies on OpenOCD that requires merged firmware + env["INTEGRATION_EXTRA_DATA"].update( + {"application_offset": "0x0", "merged_firmware": True} + ) + target_firm_merged = env.MergeBin(join( + "$BUILD_DIR", "${PROGNAME}_merged"), target_firm) env.Depends(target_firm, "checkprogsize") env.AddPlatformTarget("buildfs", target_firm, target_firm, "Build Filesystem Image") @@ -428,6 +471,10 @@ def __fetch_fs_size(target, source, env): elif upload_protocol in debug_tools: + if firmware_merge_required: + # Only merged firmware with proper headers will work when uploading is done via + # debug probes. The firmware offset address must be adjusted to 0x0 accordingly. + target_firm = target_firm_merged openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)] openocd_args.extend( debug_tools.get(upload_protocol).get("server").get("arguments", [])) @@ -440,11 +487,14 @@ def __fetch_fs_size(target, source, env): % ( "$FS_START" if "uploadfs" in COMMAND_LINE_TARGETS - else "$ESP32_APP_OFFSET" + else board.get( + "upload.offset_address", + "0x0" if firmware_merge_required else "$ESP32_APP_OFFSET" + ) ), ] ) - if "uploadfs" not in COMMAND_LINE_TARGETS: + if "uploadfs" not in COMMAND_LINE_TARGETS and not firmware_merge_required: for image in env.get("FLASH_EXTRA_IMAGES", []): openocd_args.extend( [ @@ -502,6 +552,13 @@ def __fetch_fs_size(target, source, env): print("Warning! '-Wl,-T' option for specifying linker scripts is deprecated. " "Please use 'board_build.ldscript' option in your 'platformio.ini' file.") +# +# A temporary workaround to propagate additional data to the debug configuration routine +# + +Import("projenv") +projenv["INTEGRATION_EXTRA_DATA"] = env.get("INTEGRATION_EXTRA_DATA") + # # Default targets # From f32d4564875615f69bc37b942ec08cd3dca12a76 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 31 Jul 2022 13:12:09 +0200 Subject: [PATCH 096/666] Merge firmware before flashing via OpenOCD --- platform.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/platform.py b/platform.py index 9b048fcf6..2219d0954 100644 --- a/platform.py +++ b/platform.py @@ -278,16 +278,23 @@ def configure_debug_session(self, debug_config): if any(ignore_conds): return - load_cmds = [ - 'monitor program_esp "{{{path}}}" {offset} verify'.format( - path=to_unix_path(item["path"]), offset=item["offset"] - ) - for item in flash_images - ] + merged_firmware = build_extra_data.get("merged_firmware", False) + load_cmds = [] + if not merged_firmware: + load_cmds.extend([ + 'monitor program_esp "{{{path}}}" {offset} verify'.format( + path=to_unix_path(item["path"]), offset=item["offset"] + ) + for item in flash_images + ]) + load_cmds.append( 'monitor program_esp "{%s.bin}" %s verify' % ( - to_unix_path(debug_config.build_data["prog_path"][:-4]), + to_unix_path( + debug_config.build_data["prog_path"][:-4] + + ("_merged" if merged_firmware else "") + ), build_extra_data.get("application_offset", "0x10000"), ) ) @@ -389,4 +396,4 @@ def configure_upstream_arduino_packages(self, url_items): print("Configuring toolchain packages from a remote source...") self.configure_arduino_toolchains( self.download_remote_package_index(url_items) - ) \ No newline at end of file + ) From d50a00657b504a8b83630ccc7394a051f72a9dd7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 31 Jul 2022 13:13:05 +0200 Subject: [PATCH 097/666] Update arduino.py --- builder/frameworks/arduino.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index c6fc754a6..eea32aa38 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -41,4 +41,4 @@ SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) - env["IDE_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) + env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) From e9cecb2264f57b2b42ef2cc1cf2350e3fd25af06 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 31 Jul 2022 13:14:22 +0200 Subject: [PATCH 098/666] Update espidf.py --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index bfbc70542..187a4ed5c 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1473,4 +1473,4 @@ def _skip_prj_source_files(node): ) # Propagate application offset to debug configurations -env["IDE_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) +env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) From 276370dfbb2810ccdde40db1585084b3f6d4bf4f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 31 Jul 2022 13:21:58 +0200 Subject: [PATCH 099/666] update boards 1/2 --- boards/adafruit_feather_esp32s2_tft.json | 11 +--- boards/adafruit_feather_esp32s3.json | 29 ++++----- boards/adafruit_feather_esp32s3_nopsram.json | 63 +++++++++++++++++++ boards/adafruit_feather_esp32s3_tft.json | 64 ++++++++++++++++++++ boards/adafruit_funhouse_esp32s2.json | 11 +--- boards/adafruit_magtag29_esp32s2.json | 11 +--- boards/adafruit_metro_esp32s2.json | 11 +--- boards/adafruit_qtpy_esp32s2.json | 11 +--- boards/adafruit_qtpy_esp32s3_nopsram.json | 63 +++++++++++++++++++ boards/alksesp32.json | 3 +- boards/atmegazero_esp32s2.json | 11 +--- boards/briki_abc_esp32.json | 3 +- boards/briki_mbc-wb_esp32.json | 3 +- boards/cnrs_aw2eth.json | 36 +++++++++++ boards/connaxio_espoir.json | 47 ++++++++++++++ boards/dfrobot_beetle_esp32c3.json | 47 ++++++++++++++ boards/dfrobot_firebeetle2_esp32s3.json | 49 +++++++++++++++ boards/esp32-devkitlipo.json | 1 + boards/esp32-evb.json | 1 + boards/esp32-gateway.json | 1 + boards/esp32-poe-iso.json | 1 + boards/esp32-poe.json | 1 + boards/esp32-s2-franzininho.json | 2 - boards/esp32-s2-kaluga-1.json | 1 - boards/esp32-s2-saola-1.json | 2 +- boards/featheresp32-s2.json | 3 +- boards/firebeetle32.json | 12 ++-- boards/iotaap_magnolia.json | 3 +- 28 files changed, 409 insertions(+), 92 deletions(-) create mode 100644 boards/adafruit_feather_esp32s3_nopsram.json create mode 100644 boards/adafruit_feather_esp32s3_tft.json create mode 100644 boards/adafruit_qtpy_esp32s3_nopsram.json create mode 100644 boards/cnrs_aw2eth.json create mode 100644 boards/connaxio_espoir.json create mode 100644 boards/dfrobot_beetle_esp32c3.json create mode 100644 boards/dfrobot_firebeetle2_esp32s3.json diff --git a/boards/adafruit_feather_esp32s2_tft.json b/boards/adafruit_feather_esp32s2_tft.json index 6f141b03c..aee443134 100644 --- a/boards/adafruit_feather_esp32s2_tft.json +++ b/boards/adafruit_feather_esp32s2_tft.json @@ -1,7 +1,8 @@ { "build": { "arduino": { - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -41,14 +42,6 @@ ], "name": "Adafruit Feather ESP32-S2 TFT", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_feather_esp32s2_tft/tinyuf2.bin" - ] - ] - }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json index 85d530afb..9c14bd3f8 100644 --- a/boards/adafruit_feather_esp32s3.json +++ b/boards/adafruit_feather_esp32s3.json @@ -1,11 +1,12 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld" + "ldscript": "esp32s3_out.ld", + "partitions": "partitions.csv" }, "core": "esp32", "extra_flags": [ - "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM", + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3", "-DARDUINO_USB_CDC_ON_BOOT=1", "-DARDUINO_RUNNING_CORE=1", "-DARDUINO_EVENT_RUNNING_CORE=1" @@ -16,19 +17,19 @@ "hwids": [ [ "0x239A", - "0x8113" + "0x811B" ], [ "0x239A", - "0x0113" + "0x011B" ], [ "0x239A", - "0x8114" + "0x811C" ] ], "mcu": "esp32s3", - "variant": "adafruit_feather_esp32s3_nopsram" + "variant": "adafruit_feather_esp32s3" }, "connectivity": [ "wifi" @@ -40,24 +41,16 @@ "arduino", "espidf" ], - "name": "Adafruit Feather ESP32-S3 No PSRAM", + "name": "Adafruit Feather ESP32-S3 2MB PSRAM", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x410000", - "variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin" - ] - ] - }, - "flash_size": "8MB", + "flash_size": "4MB", "maximum_ram_size": 327680, - "maximum_size": 8388608, + "maximum_size": 4194304, "use_1200bps_touch": true, "wait_for_upload_port": true, "require_upload_port": true, "speed": 460800 }, - "url": "https://www.adafruit.com/product/5323", + "url": "https://www.adafruit.com/product/5477", "vendor": "Adafruit" } diff --git a/boards/adafruit_feather_esp32s3_nopsram.json b/boards/adafruit_feather_esp32s3_nopsram.json new file mode 100644 index 000000000..29541e559 --- /dev/null +++ b/boards/adafruit_feather_esp32s3_nopsram.json @@ -0,0 +1,63 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x811B" + ], + [ + "0x239A", + "0x011B" + ], + [ + "0x239A", + "0x811C" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3_nopsram" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S3 No PSRAM", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5323", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3_tft.json b/boards/adafruit_feather_esp32s3_tft.json new file mode 100644 index 000000000..4e38ae0d1 --- /dev/null +++ b/boards/adafruit_feather_esp32s3_tft.json @@ -0,0 +1,64 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "partitions.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x811D" + ], + [ + "0x239A", + "0x011D" + ], + [ + "0x239A", + "0x811E" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3_tft" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S3 TFT", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s3_tft/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5483", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_funhouse_esp32s2.json b/boards/adafruit_funhouse_esp32s2.json index 974761247..eb5ee1d52 100644 --- a/boards/adafruit_funhouse_esp32s2.json +++ b/boards/adafruit_funhouse_esp32s2.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -41,14 +42,6 @@ ], "name": "Adafruit FunHouse", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_funhouse_esp32s2/tinyuf2.bin" - ] - ] - }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_magtag29_esp32s2.json b/boards/adafruit_magtag29_esp32s2.json index 5e2dd717f..fc51f6101 100644 --- a/boards/adafruit_magtag29_esp32s2.json +++ b/boards/adafruit_magtag29_esp32s2.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -41,14 +42,6 @@ ], "name": "Adafruit MagTag 2.9", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_magtag29_esp32s2/tinyuf2.bin" - ] - ] - }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_metro_esp32s2.json b/boards/adafruit_metro_esp32s2.json index af8df2279..7f75dfbe4 100644 --- a/boards/adafruit_metro_esp32s2.json +++ b/boards/adafruit_metro_esp32s2.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -41,14 +42,6 @@ ], "name": "Adafruit Metro ESP32-S2", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_metro_esp32s2/tinyuf2.bin" - ] - ] - }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_qtpy_esp32s2.json b/boards/adafruit_qtpy_esp32s2.json index 30f51dcec..51beac63e 100644 --- a/boards/adafruit_qtpy_esp32s2.json +++ b/boards/adafruit_qtpy_esp32s2.json @@ -1,7 +1,8 @@ { "build": { "arduino": { - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -41,14 +42,6 @@ ], "name": "Adafruit QT Py ESP32-S2", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_qtpy_esp32s2/tinyuf2.bin" - ] - ] - }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_qtpy_esp32s3_nopsram.json b/boards/adafruit_qtpy_esp32s3_nopsram.json new file mode 100644 index 000000000..4412a31e4 --- /dev/null +++ b/boards/adafruit_qtpy_esp32s3_nopsram.json @@ -0,0 +1,63 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8119" + ], + [ + "0x239A", + "0x0119" + ], + [ + "0x239A", + "0x811A" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_qtpy_esp32s3_nopsram" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S3 No PSRAM", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5426", + "vendor": "Adafruit" +} diff --git a/boards/alksesp32.json b/boards/alksesp32.json index 3e2e67b9b..6a4ae15ad 100644 --- a/boards/alksesp32.json +++ b/boards/alksesp32.json @@ -21,8 +21,7 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino", - "espidf" + "arduino" ], "name": "ALKS ESP32", "upload": { diff --git a/boards/atmegazero_esp32s2.json b/boards/atmegazero_esp32s2.json index bfc40697f..a23a6ce9d 100644 --- a/boards/atmegazero_esp32s2.json +++ b/boards/atmegazero_esp32s2.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-16MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -32,14 +33,6 @@ ], "name": "EspinalLab ATMegaZero ESP32-S2", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/atmegazero_esp32s2/tinyuf2.bin" - ] - ] - }, "flash_size": "16MB", "maximum_ram_size": 327680, "maximum_size": 16777216, diff --git a/boards/briki_abc_esp32.json b/boards/briki_abc_esp32.json index 53113bb1b..429514895 100644 --- a/boards/briki_abc_esp32.json +++ b/boards/briki_abc_esp32.json @@ -22,8 +22,7 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino", - "espidf" + "arduino" ], "name": "Briki ABC (MBC-WB) - ESP32", "upload": { diff --git a/boards/briki_mbc-wb_esp32.json b/boards/briki_mbc-wb_esp32.json index 86af17f3f..df5c3756a 100644 --- a/boards/briki_mbc-wb_esp32.json +++ b/boards/briki_mbc-wb_esp32.json @@ -22,8 +22,7 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino", - "espidf" + "arduino" ], "name": "Briki MBC-WB - ESP32", "upload": { diff --git a/boards/cnrs_aw2eth.json b/boards/cnrs_aw2eth.json new file mode 100644 index 000000000..3669347a4 --- /dev/null +++ b/boards/cnrs_aw2eth.json @@ -0,0 +1,36 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_PICO" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "cnrs_aw2eth" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "CNRS AW2ETH", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "CNRS" +} diff --git a/boards/connaxio_espoir.json b/boards/connaxio_espoir.json new file mode 100644 index 000000000..e9e7265bf --- /dev/null +++ b/boards/connaxio_espoir.json @@ -0,0 +1,47 @@ + +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_CONNAXIO_ESPOIR", + "-DCONFIG_FREERTOS_UNICORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "connaxio_espoir", + "hwids": [ + [ + "0x10C4", + "0x8D9A" + ] + ] + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-solo-1.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Connaxio's Espoir", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.connaxio.com/electronics/espoir/", + "vendor": "Connaxio" +} diff --git a/boards/dfrobot_beetle_esp32c3.json b/boards/dfrobot_beetle_esp32c3.json new file mode 100644 index 000000000..a5b884f2f --- /dev/null +++ b/boards/dfrobot_beetle_esp32c3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32C3_DEV", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x3343", + "0x8364" + ], + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "dfrobot_beetle_esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DFRobot Beetle ESP32-C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.dfrobot.com/product-2566.html", + "vendor": "DFRobot" +} diff --git a/boards/dfrobot_firebeetle2_esp32s3.json b/boards/dfrobot_firebeetle2_esp32s3.json new file mode 100644 index 000000000..0f87150d6 --- /dev/null +++ b/boards/dfrobot_firebeetle2_esp32s3.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x83CF" + ], + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "dfrobot_firebeetle2_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DFRobot Firebeetle 2 ESP32-S3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.dfrobot.com/product-1590.html", + "vendor": "DFRobot" +} diff --git a/boards/esp32-devkitlipo.json b/boards/esp32-devkitlipo.json index 399d0846f..cbc926b17 100644 --- a/boards/esp32-devkitlipo.json +++ b/boards/esp32-devkitlipo.json @@ -8,6 +8,7 @@ "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "qio", + "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", "variant": "esp32-devkit-lipo" }, diff --git a/boards/esp32-evb.json b/boards/esp32-evb.json index 69dde4347..c821386ae 100644 --- a/boards/esp32-evb.json +++ b/boards/esp32-evb.json @@ -8,6 +8,7 @@ "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", "variant": "esp32-evb" }, diff --git a/boards/esp32-gateway.json b/boards/esp32-gateway.json index 1a8aac8d6..33f0f2f2a 100644 --- a/boards/esp32-gateway.json +++ b/boards/esp32-gateway.json @@ -8,6 +8,7 @@ "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", "variant": "esp32-gateway" }, diff --git a/boards/esp32-poe-iso.json b/boards/esp32-poe-iso.json index 82898b1f7..4412f9466 100644 --- a/boards/esp32-poe-iso.json +++ b/boards/esp32-poe-iso.json @@ -8,6 +8,7 @@ "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", "variant": "esp32-poe-iso" }, diff --git a/boards/esp32-poe.json b/boards/esp32-poe.json index 60c992e53..0cf9bd46e 100644 --- a/boards/esp32-poe.json +++ b/boards/esp32-poe.json @@ -8,6 +8,7 @@ "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", "variant": "esp32-poe" }, diff --git a/boards/esp32-s2-franzininho.json b/boards/esp32-s2-franzininho.json index d20d12a45..206456339 100644 --- a/boards/esp32-s2-franzininho.json +++ b/boards/esp32-s2-franzininho.json @@ -4,7 +4,6 @@ "ld": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", @@ -18,7 +17,6 @@ "openocd_target": "esp32s2.cfg" }, "frameworks": [ - "arduino", "espidf" ], "name": "Franzininho WiFi Board", diff --git a/boards/esp32-s2-kaluga-1.json b/boards/esp32-s2-kaluga-1.json index b48abac37..1f1653351 100644 --- a/boards/esp32-s2-kaluga-1.json +++ b/boards/esp32-s2-kaluga-1.json @@ -4,7 +4,6 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", diff --git a/boards/esp32-s2-saola-1.json b/boards/esp32-s2-saola-1.json index 58927bb91..f264131f9 100644 --- a/boards/esp32-s2-saola-1.json +++ b/boards/esp32-s2-saola-1.json @@ -4,7 +4,7 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", + "extra_flags": "-DARDUINO_ESP32S2_DEV", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", diff --git a/boards/featheresp32-s2.json b/boards/featheresp32-s2.json index bf6f0cbc2..f645bf629 100644 --- a/boards/featheresp32-s2.json +++ b/boards/featheresp32-s2.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ diff --git a/boards/firebeetle32.json b/boards/firebeetle32.json index d580c39e9..3463fa131 100644 --- a/boards/firebeetle32.json +++ b/boards/firebeetle32.json @@ -13,9 +13,7 @@ }, "connectivity": [ "wifi", - "bluetooth", - "ethernet", - "can" + "bluetooth" ], "debug": { "openocd_board": "esp-wroom-32.cfg" @@ -26,12 +24,12 @@ ], "name": "FireBeetle-ESP32", "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, + "flash_size": "16MB", + "maximum_ram_size": 532480, + "maximum_size": 16777216, "require_upload_port": true, "speed": 460800 }, - "url": "https://dfrobotblog.wordpress.com", + "url": "https://wiki.dfrobot.com/FireBeetle_ESP32_IOT_Microcontroller(V3.0)__Supports_Wi-Fi_&_Bluetooth__SKU__DFR0478", "vendor": "DFRobot" } diff --git a/boards/iotaap_magnolia.json b/boards/iotaap_magnolia.json index fffc85354..47c1ebad6 100644 --- a/boards/iotaap_magnolia.json +++ b/boards/iotaap_magnolia.json @@ -21,8 +21,7 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino", - "espidf" + "arduino" ], "name": "IoTaaP Magnolia", "upload": { From 4059ae98b8f6347cf1d18e6a71945f97f6c9a274 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 31 Jul 2022 13:23:22 +0200 Subject: [PATCH 100/666] Update Boards 2/2 --- boards/m5stack-coreink.json | 2 +- boards/seeed_xiao_esp32c3.json | 44 +++++++++++++++++++++++++ boards/sparkfun_esp32s2_thing_plus.json | 2 +- boards/wemos_d1_mini32.json | 2 +- boards/wemos_d1_uno32.json | 37 +++++++++++++++++++++ 5 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 boards/seeed_xiao_esp32c3.json create mode 100644 boards/wemos_d1_uno32.json diff --git a/boards/m5stack-coreink.json b/boards/m5stack-coreink.json index f5aee0d7b..e7b3cbb1c 100644 --- a/boards/m5stack-coreink.json +++ b/boards/m5stack-coreink.json @@ -21,7 +21,7 @@ "arduino", "espidf" ], - "name": "M5Stick-Core Ink", + "name": "M5Stack-Core Ink", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, diff --git a/boards/seeed_xiao_esp32c3.json b/boards/seeed_xiao_esp32c3.json new file mode 100644 index 000000000..4d8ded042 --- /dev/null +++ b/boards/seeed_xiao_esp32c3.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_XIAO_ESP32C3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x2886", + "0x0047" + ] + ], + "mcu": "esp32c3", + "variant": "XIAO_ESP32C3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Seeed Studio XIAO ESP32C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/", + "vendor": "Seeed Studio" +} diff --git a/boards/sparkfun_esp32s2_thing_plus.json b/boards/sparkfun_esp32s2_thing_plus.json index 763c409c8..f8697e73a 100644 --- a/boards/sparkfun_esp32s2_thing_plus.json +++ b/boards/sparkfun_esp32s2_thing_plus.json @@ -39,4 +39,4 @@ }, "url": "https://www.sparkfun.com/products/17743", "vendor": "SparkFun" -} \ No newline at end of file +} diff --git a/boards/wemos_d1_mini32.json b/boards/wemos_d1_mini32.json index 4770623ac..90b1d6b95 100644 --- a/boards/wemos_d1_mini32.json +++ b/boards/wemos_d1_mini32.json @@ -24,7 +24,7 @@ "arduino", "espidf" ], - "name": "WeMos D1 MINI ESP32", + "name": "WEMOS D1 MINI ESP32", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, diff --git a/boards/wemos_d1_uno32.json b/boards/wemos_d1_uno32.json new file mode 100644 index 000000000..2a38aa423 --- /dev/null +++ b/boards/wemos_d1_uno32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_D1_UNO32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "d1_uno32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS D1 R32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc", + "vendor": "WEMOS" +} From a395f652b38011a2bf59d8c085f62500e8e037d9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 31 Jul 2022 13:29:57 +0200 Subject: [PATCH 101/666] v2.0.4.1 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16e2ee1cb..f4a06b969 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid ```ini [env:stable] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4/platform-espressif32-2.0.4.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4.1/platform-espressif32-2.0.4.1.zip board = ... ... ``` From 2556b29bf8cbe447ad77bdcae181da488d0ffa30 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 31 Jul 2022 13:58:39 +0200 Subject: [PATCH 102/666] FIx OCD flash, Esptool v4.1, Board updates (#24) * Tasmota github as source * --dont-append-digest * esptool v4.1 * 2.0.5dev * platformio": ">=6.1.0 * Update espidf.py * Add default nameOnDisk value for external CMake projects * Build 918 newest wifi libs from idf44 * Tasmota IDF 4.4.3 * Tasmota release Core 2.0.4.1 * Merge firmware before flashing via OpenOCD * Merge firmware before flashing via OpenOCD * Update arduino.py * Update espidf.py * update boards 1/2 * Update Boards 2/2 * v2.0.4.1 --- boards/adafruit_feather_esp32s2_tft.json | 11 +-- boards/adafruit_feather_esp32s3.json | 29 +++----- boards/adafruit_feather_esp32s3_nopsram.json | 63 ++++++++++++++++ boards/adafruit_feather_esp32s3_tft.json | 64 ++++++++++++++++ boards/adafruit_funhouse_esp32s2.json | 11 +-- boards/adafruit_magtag29_esp32s2.json | 11 +-- boards/adafruit_metro_esp32s2.json | 11 +-- boards/adafruit_qtpy_esp32s2.json | 11 +-- boards/adafruit_qtpy_esp32s3_nopsram.json | 63 ++++++++++++++++ boards/alksesp32.json | 3 +- boards/atmegazero_esp32s2.json | 11 +-- boards/briki_abc_esp32.json | 3 +- boards/briki_mbc-wb_esp32.json | 3 +- boards/cnrs_aw2eth.json | 36 +++++++++ boards/connaxio_espoir.json | 47 ++++++++++++ boards/dfrobot_beetle_esp32c3.json | 47 ++++++++++++ boards/dfrobot_firebeetle2_esp32s3.json | 49 +++++++++++++ boards/esp32-devkitlipo.json | 1 + boards/esp32-evb.json | 1 + boards/esp32-gateway.json | 1 + boards/esp32-poe-iso.json | 1 + boards/esp32-poe.json | 1 + boards/esp32-s2-franzininho.json | 2 - boards/esp32-s2-kaluga-1.json | 1 - boards/esp32-s2-saola-1.json | 2 +- boards/featheresp32-s2.json | 3 +- boards/firebeetle32.json | 12 ++- boards/iotaap_magnolia.json | 3 +- boards/m5stack-coreink.json | 2 +- boards/seeed_xiao_esp32c3.json | 44 +++++++++++ boards/sparkfun_esp32s2_thing_plus.json | 2 +- boards/wemos_d1_mini32.json | 2 +- boards/wemos_d1_uno32.json | 37 ++++++++++ builder/frameworks/arduino.py | 2 +- builder/frameworks/espidf.py | 77 +++++++++++++------- builder/main.py | 64 +++++++++++++++- platform.json | 6 +- platform.py | 23 ++++-- 38 files changed, 622 insertions(+), 138 deletions(-) create mode 100644 boards/adafruit_feather_esp32s3_nopsram.json create mode 100644 boards/adafruit_feather_esp32s3_tft.json create mode 100644 boards/adafruit_qtpy_esp32s3_nopsram.json create mode 100644 boards/cnrs_aw2eth.json create mode 100644 boards/connaxio_espoir.json create mode 100644 boards/dfrobot_beetle_esp32c3.json create mode 100644 boards/dfrobot_firebeetle2_esp32s3.json create mode 100644 boards/seeed_xiao_esp32c3.json create mode 100644 boards/wemos_d1_uno32.json diff --git a/boards/adafruit_feather_esp32s2_tft.json b/boards/adafruit_feather_esp32s2_tft.json index 6f141b03c..aee443134 100644 --- a/boards/adafruit_feather_esp32s2_tft.json +++ b/boards/adafruit_feather_esp32s2_tft.json @@ -1,7 +1,8 @@ { "build": { "arduino": { - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -41,14 +42,6 @@ ], "name": "Adafruit Feather ESP32-S2 TFT", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_feather_esp32s2_tft/tinyuf2.bin" - ] - ] - }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json index 85d530afb..9c14bd3f8 100644 --- a/boards/adafruit_feather_esp32s3.json +++ b/boards/adafruit_feather_esp32s3.json @@ -1,11 +1,12 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld" + "ldscript": "esp32s3_out.ld", + "partitions": "partitions.csv" }, "core": "esp32", "extra_flags": [ - "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM", + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3", "-DARDUINO_USB_CDC_ON_BOOT=1", "-DARDUINO_RUNNING_CORE=1", "-DARDUINO_EVENT_RUNNING_CORE=1" @@ -16,19 +17,19 @@ "hwids": [ [ "0x239A", - "0x8113" + "0x811B" ], [ "0x239A", - "0x0113" + "0x011B" ], [ "0x239A", - "0x8114" + "0x811C" ] ], "mcu": "esp32s3", - "variant": "adafruit_feather_esp32s3_nopsram" + "variant": "adafruit_feather_esp32s3" }, "connectivity": [ "wifi" @@ -40,24 +41,16 @@ "arduino", "espidf" ], - "name": "Adafruit Feather ESP32-S3 No PSRAM", + "name": "Adafruit Feather ESP32-S3 2MB PSRAM", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x410000", - "variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin" - ] - ] - }, - "flash_size": "8MB", + "flash_size": "4MB", "maximum_ram_size": 327680, - "maximum_size": 8388608, + "maximum_size": 4194304, "use_1200bps_touch": true, "wait_for_upload_port": true, "require_upload_port": true, "speed": 460800 }, - "url": "https://www.adafruit.com/product/5323", + "url": "https://www.adafruit.com/product/5477", "vendor": "Adafruit" } diff --git a/boards/adafruit_feather_esp32s3_nopsram.json b/boards/adafruit_feather_esp32s3_nopsram.json new file mode 100644 index 000000000..29541e559 --- /dev/null +++ b/boards/adafruit_feather_esp32s3_nopsram.json @@ -0,0 +1,63 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x811B" + ], + [ + "0x239A", + "0x011B" + ], + [ + "0x239A", + "0x811C" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3_nopsram" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S3 No PSRAM", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5323", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3_tft.json b/boards/adafruit_feather_esp32s3_tft.json new file mode 100644 index 000000000..4e38ae0d1 --- /dev/null +++ b/boards/adafruit_feather_esp32s3_tft.json @@ -0,0 +1,64 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "partitions.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x811D" + ], + [ + "0x239A", + "0x011D" + ], + [ + "0x239A", + "0x811E" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3_tft" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S3 TFT", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s3_tft/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5483", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_funhouse_esp32s2.json b/boards/adafruit_funhouse_esp32s2.json index 974761247..eb5ee1d52 100644 --- a/boards/adafruit_funhouse_esp32s2.json +++ b/boards/adafruit_funhouse_esp32s2.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -41,14 +42,6 @@ ], "name": "Adafruit FunHouse", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_funhouse_esp32s2/tinyuf2.bin" - ] - ] - }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_magtag29_esp32s2.json b/boards/adafruit_magtag29_esp32s2.json index 5e2dd717f..fc51f6101 100644 --- a/boards/adafruit_magtag29_esp32s2.json +++ b/boards/adafruit_magtag29_esp32s2.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -41,14 +42,6 @@ ], "name": "Adafruit MagTag 2.9", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_magtag29_esp32s2/tinyuf2.bin" - ] - ] - }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_metro_esp32s2.json b/boards/adafruit_metro_esp32s2.json index af8df2279..7f75dfbe4 100644 --- a/boards/adafruit_metro_esp32s2.json +++ b/boards/adafruit_metro_esp32s2.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -41,14 +42,6 @@ ], "name": "Adafruit Metro ESP32-S2", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_metro_esp32s2/tinyuf2.bin" - ] - ] - }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_qtpy_esp32s2.json b/boards/adafruit_qtpy_esp32s2.json index 30f51dcec..51beac63e 100644 --- a/boards/adafruit_qtpy_esp32s2.json +++ b/boards/adafruit_qtpy_esp32s2.json @@ -1,7 +1,8 @@ { "build": { "arduino": { - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -41,14 +42,6 @@ ], "name": "Adafruit QT Py ESP32-S2", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_qtpy_esp32s2/tinyuf2.bin" - ] - ] - }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_qtpy_esp32s3_nopsram.json b/boards/adafruit_qtpy_esp32s3_nopsram.json new file mode 100644 index 000000000..4412a31e4 --- /dev/null +++ b/boards/adafruit_qtpy_esp32s3_nopsram.json @@ -0,0 +1,63 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8119" + ], + [ + "0x239A", + "0x0119" + ], + [ + "0x239A", + "0x811A" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_qtpy_esp32s3_nopsram" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S3 No PSRAM", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5426", + "vendor": "Adafruit" +} diff --git a/boards/alksesp32.json b/boards/alksesp32.json index 3e2e67b9b..6a4ae15ad 100644 --- a/boards/alksesp32.json +++ b/boards/alksesp32.json @@ -21,8 +21,7 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino", - "espidf" + "arduino" ], "name": "ALKS ESP32", "upload": { diff --git a/boards/atmegazero_esp32s2.json b/boards/atmegazero_esp32s2.json index bfc40697f..a23a6ce9d 100644 --- a/boards/atmegazero_esp32s2.json +++ b/boards/atmegazero_esp32s2.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-16MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ @@ -32,14 +33,6 @@ ], "name": "EspinalLab ATMegaZero ESP32-S2", "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/atmegazero_esp32s2/tinyuf2.bin" - ] - ] - }, "flash_size": "16MB", "maximum_ram_size": 327680, "maximum_size": 16777216, diff --git a/boards/briki_abc_esp32.json b/boards/briki_abc_esp32.json index 53113bb1b..429514895 100644 --- a/boards/briki_abc_esp32.json +++ b/boards/briki_abc_esp32.json @@ -22,8 +22,7 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino", - "espidf" + "arduino" ], "name": "Briki ABC (MBC-WB) - ESP32", "upload": { diff --git a/boards/briki_mbc-wb_esp32.json b/boards/briki_mbc-wb_esp32.json index 86af17f3f..df5c3756a 100644 --- a/boards/briki_mbc-wb_esp32.json +++ b/boards/briki_mbc-wb_esp32.json @@ -22,8 +22,7 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino", - "espidf" + "arduino" ], "name": "Briki MBC-WB - ESP32", "upload": { diff --git a/boards/cnrs_aw2eth.json b/boards/cnrs_aw2eth.json new file mode 100644 index 000000000..3669347a4 --- /dev/null +++ b/boards/cnrs_aw2eth.json @@ -0,0 +1,36 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_PICO" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "cnrs_aw2eth" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "CNRS AW2ETH", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "CNRS" +} diff --git a/boards/connaxio_espoir.json b/boards/connaxio_espoir.json new file mode 100644 index 000000000..e9e7265bf --- /dev/null +++ b/boards/connaxio_espoir.json @@ -0,0 +1,47 @@ + +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_CONNAXIO_ESPOIR", + "-DCONFIG_FREERTOS_UNICORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "connaxio_espoir", + "hwids": [ + [ + "0x10C4", + "0x8D9A" + ] + ] + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-solo-1.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Connaxio's Espoir", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.connaxio.com/electronics/espoir/", + "vendor": "Connaxio" +} diff --git a/boards/dfrobot_beetle_esp32c3.json b/boards/dfrobot_beetle_esp32c3.json new file mode 100644 index 000000000..a5b884f2f --- /dev/null +++ b/boards/dfrobot_beetle_esp32c3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32C3_DEV", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x3343", + "0x8364" + ], + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "dfrobot_beetle_esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DFRobot Beetle ESP32-C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.dfrobot.com/product-2566.html", + "vendor": "DFRobot" +} diff --git a/boards/dfrobot_firebeetle2_esp32s3.json b/boards/dfrobot_firebeetle2_esp32s3.json new file mode 100644 index 000000000..0f87150d6 --- /dev/null +++ b/boards/dfrobot_firebeetle2_esp32s3.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x83CF" + ], + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "dfrobot_firebeetle2_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DFRobot Firebeetle 2 ESP32-S3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.dfrobot.com/product-1590.html", + "vendor": "DFRobot" +} diff --git a/boards/esp32-devkitlipo.json b/boards/esp32-devkitlipo.json index 399d0846f..cbc926b17 100644 --- a/boards/esp32-devkitlipo.json +++ b/boards/esp32-devkitlipo.json @@ -8,6 +8,7 @@ "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "qio", + "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", "variant": "esp32-devkit-lipo" }, diff --git a/boards/esp32-evb.json b/boards/esp32-evb.json index 69dde4347..c821386ae 100644 --- a/boards/esp32-evb.json +++ b/boards/esp32-evb.json @@ -8,6 +8,7 @@ "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", "variant": "esp32-evb" }, diff --git a/boards/esp32-gateway.json b/boards/esp32-gateway.json index 1a8aac8d6..33f0f2f2a 100644 --- a/boards/esp32-gateway.json +++ b/boards/esp32-gateway.json @@ -8,6 +8,7 @@ "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", "variant": "esp32-gateway" }, diff --git a/boards/esp32-poe-iso.json b/boards/esp32-poe-iso.json index 82898b1f7..4412f9466 100644 --- a/boards/esp32-poe-iso.json +++ b/boards/esp32-poe-iso.json @@ -8,6 +8,7 @@ "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", "variant": "esp32-poe-iso" }, diff --git a/boards/esp32-poe.json b/boards/esp32-poe.json index 60c992e53..0cf9bd46e 100644 --- a/boards/esp32-poe.json +++ b/boards/esp32-poe.json @@ -8,6 +8,7 @@ "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", "variant": "esp32-poe" }, diff --git a/boards/esp32-s2-franzininho.json b/boards/esp32-s2-franzininho.json index d20d12a45..206456339 100644 --- a/boards/esp32-s2-franzininho.json +++ b/boards/esp32-s2-franzininho.json @@ -4,7 +4,6 @@ "ld": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", @@ -18,7 +17,6 @@ "openocd_target": "esp32s2.cfg" }, "frameworks": [ - "arduino", "espidf" ], "name": "Franzininho WiFi Board", diff --git a/boards/esp32-s2-kaluga-1.json b/boards/esp32-s2-kaluga-1.json index b48abac37..1f1653351 100644 --- a/boards/esp32-s2-kaluga-1.json +++ b/boards/esp32-s2-kaluga-1.json @@ -4,7 +4,6 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", diff --git a/boards/esp32-s2-saola-1.json b/boards/esp32-s2-saola-1.json index 58927bb91..f264131f9 100644 --- a/boards/esp32-s2-saola-1.json +++ b/boards/esp32-s2-saola-1.json @@ -4,7 +4,7 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", + "extra_flags": "-DARDUINO_ESP32S2_DEV", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", diff --git a/boards/featheresp32-s2.json b/boards/featheresp32-s2.json index bf6f0cbc2..f645bf629 100644 --- a/boards/featheresp32-s2.json +++ b/boards/featheresp32-s2.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ diff --git a/boards/firebeetle32.json b/boards/firebeetle32.json index d580c39e9..3463fa131 100644 --- a/boards/firebeetle32.json +++ b/boards/firebeetle32.json @@ -13,9 +13,7 @@ }, "connectivity": [ "wifi", - "bluetooth", - "ethernet", - "can" + "bluetooth" ], "debug": { "openocd_board": "esp-wroom-32.cfg" @@ -26,12 +24,12 @@ ], "name": "FireBeetle-ESP32", "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, + "flash_size": "16MB", + "maximum_ram_size": 532480, + "maximum_size": 16777216, "require_upload_port": true, "speed": 460800 }, - "url": "https://dfrobotblog.wordpress.com", + "url": "https://wiki.dfrobot.com/FireBeetle_ESP32_IOT_Microcontroller(V3.0)__Supports_Wi-Fi_&_Bluetooth__SKU__DFR0478", "vendor": "DFRobot" } diff --git a/boards/iotaap_magnolia.json b/boards/iotaap_magnolia.json index fffc85354..47c1ebad6 100644 --- a/boards/iotaap_magnolia.json +++ b/boards/iotaap_magnolia.json @@ -21,8 +21,7 @@ "openocd_board": "esp-wroom-32.cfg" }, "frameworks": [ - "arduino", - "espidf" + "arduino" ], "name": "IoTaaP Magnolia", "upload": { diff --git a/boards/m5stack-coreink.json b/boards/m5stack-coreink.json index f5aee0d7b..e7b3cbb1c 100644 --- a/boards/m5stack-coreink.json +++ b/boards/m5stack-coreink.json @@ -21,7 +21,7 @@ "arduino", "espidf" ], - "name": "M5Stick-Core Ink", + "name": "M5Stack-Core Ink", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, diff --git a/boards/seeed_xiao_esp32c3.json b/boards/seeed_xiao_esp32c3.json new file mode 100644 index 000000000..4d8ded042 --- /dev/null +++ b/boards/seeed_xiao_esp32c3.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_XIAO_ESP32C3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x2886", + "0x0047" + ] + ], + "mcu": "esp32c3", + "variant": "XIAO_ESP32C3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Seeed Studio XIAO ESP32C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/", + "vendor": "Seeed Studio" +} diff --git a/boards/sparkfun_esp32s2_thing_plus.json b/boards/sparkfun_esp32s2_thing_plus.json index 763c409c8..f8697e73a 100644 --- a/boards/sparkfun_esp32s2_thing_plus.json +++ b/boards/sparkfun_esp32s2_thing_plus.json @@ -39,4 +39,4 @@ }, "url": "https://www.sparkfun.com/products/17743", "vendor": "SparkFun" -} \ No newline at end of file +} diff --git a/boards/wemos_d1_mini32.json b/boards/wemos_d1_mini32.json index 4770623ac..90b1d6b95 100644 --- a/boards/wemos_d1_mini32.json +++ b/boards/wemos_d1_mini32.json @@ -24,7 +24,7 @@ "arduino", "espidf" ], - "name": "WeMos D1 MINI ESP32", + "name": "WEMOS D1 MINI ESP32", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, diff --git a/boards/wemos_d1_uno32.json b/boards/wemos_d1_uno32.json new file mode 100644 index 000000000..2a38aa423 --- /dev/null +++ b/boards/wemos_d1_uno32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_D1_UNO32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "d1_uno32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS D1 R32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc", + "vendor": "WEMOS" +} diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index c6fc754a6..eea32aa38 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -41,4 +41,4 @@ SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) - env["IDE_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) + env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index a360a04e3..187a4ed5c 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -818,6 +818,8 @@ def get_targets_by_type(target_configs, target_types, ignore_targets=None): def get_components_map(target_configs, target_types, ignore_components=None): result = {} for config in get_targets_by_type(target_configs, target_types, ignore_components): + if "nameOnDisk" not in config: + config["nameOnDisk"] = "lib%s.a" % config["name"] result[config["id"]] = {"config": config} return result @@ -1249,7 +1251,6 @@ def _get_installed_pip_packages(): project_flags = get_app_flags(project_config, default_config) link_args = extract_link_args(elf_config) app_includes = get_app_includes(elf_config) -project_lib_includes = get_project_lib_includes(env) # # Compile bootloader @@ -1304,32 +1305,6 @@ def _skip_prj_source_files(node): env.AddBuildMiddleware(_skip_prj_source_files) -# Project files should be compiled only when a special -# option is enabled when running 'test' command -if "__test" not in COMMAND_LINE_TARGETS or env.GetProjectOption( - "test_build_project_src" -): - project_env = env.Clone() - if project_target_name != "__idf_main": - # Manually add dependencies to CPPPATH since ESP-IDF build system doesn't generate - # this info if the folder with sources is not named 'main' - # https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#rename-main - project_env.AppendUnique(CPPPATH=app_includes["plain_includes"]) - - # Add include dirs from PlatformIO build system to project CPPPATH so - # they're visible to PIOBUILDFILES - project_env.Append( - CPPPATH=["$PROJECT_INCLUDE_DIR", "$PROJECT_SRC_DIR"] + project_lib_includes - ) - - env.Append( - PIOBUILDFILES=compile_source_files( - target_configs.get(project_target_name), - project_env, - project_env.subst("$PROJECT_DIR"), - ) - ) - # # Generate partition table # @@ -1390,6 +1365,52 @@ def _skip_prj_source_files(node): ], ) +# +# Propagate Arduino defines to the main build environment +# + +if "arduino" in env.subst("$PIOFRAMEWORK"): + arduino_config_name = list( + filter( + lambda config_name: config_name.startswith( + "__idf_framework-arduinoespressif32" + ), + target_configs, + ) + )[0] + env.AppendUnique( + CPPDEFINES=extract_defines( + target_configs.get(arduino_config_name, {}).get("compileGroups", [])[0] + ) + ) + +# Project files should be compiled only when a special +# option is enabled when running 'test' command +if "__test" not in COMMAND_LINE_TARGETS or env.GetProjectOption( + "test_build_project_src" +): + project_env = env.Clone() + if project_target_name != "__idf_main": + # Manually add dependencies to CPPPATH since ESP-IDF build system doesn't generate + # this info if the folder with sources is not named 'main' + # https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#rename-main + project_env.AppendUnique(CPPPATH=app_includes["plain_includes"]) + + # Add include dirs from PlatformIO build system to project CPPPATH so + # they're visible to PIOBUILDFILES + project_env.AppendUnique( + CPPPATH=["$PROJECT_INCLUDE_DIR", "$PROJECT_SRC_DIR"] + + get_project_lib_includes(env) + ) + + env.Append( + PIOBUILDFILES=compile_source_files( + target_configs.get(project_target_name), + project_env, + project_env.subst("$PROJECT_DIR"), + ) + ) + # # Generate mbedtls bundle # @@ -1452,4 +1473,4 @@ def _skip_prj_source_files(node): ) # Propagate application offset to debug configurations -env["IDE_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) +env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) diff --git a/builder/main.py b/builder/main.py index bbfa4f49f..41a93dc05 100644 --- a/builder/main.py +++ b/builder/main.py @@ -162,6 +162,18 @@ def __fetch_fs_size(target, source, env): return (target, source) +def merge_binaries(source, target, env, for_signature): + return " ".join([ + '"$PYTHONEXE"', + join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), + "--chip", mcu, "merge_bin", + "-o", "$TARGET", + "--flash_mode", "$BOARD_FLASH_MODE", + "--flash_size", board.get("upload.flash_size", "4MB"), + "$ESP32_APP_OFFSET", "$SOURCES" + ] + ['"%s"' % itm for img in env.get("FLASH_EXTRA_IMAGES", []) for itm in img]) + + env = DefaultEnvironment() platform = env.PioPlatform() board = env.BoardConfig() @@ -171,6 +183,24 @@ def __fetch_fs_size(target, source, env): if mcu == "esp32c3": toolchain_arch = "riscv32-esp" +# Arduino core v2.0.4 contains updated bootloader images that have innacurate default +# headers. This results in bootloops if firmware is flashed via OpenOCD (e.g. debugging +# or uploading via debug tools). For this reason, before uploading or debugging we need +# to merge binaries via esptoolpy so that the image headers will be adjusted according to +# --flash-size and --flash-mode arguments. +# Note: This behavior doesn't occur if uploading is done via esptoolpy, as esptoolpy +# overrides the binary image headers before flashing. +firmware_merge_required = bool( + env.get("PIOFRAMEWORK", []) == ["arduino"] + and ( + "debug" in env.GetBuildType() + or env.subst("$UPLOAD_PROTOCOL") in board.get("debug.tools", {}) + ) +) + +if "INTEGRATION_EXTRA_DATA" not in env: + env["INTEGRATION_EXTRA_DATA"] = {} + env.Replace( __get_board_boot_mode=_get_board_boot_mode, __get_board_f_flash=_get_board_f_flash, @@ -232,9 +262,10 @@ def __fetch_fs_size(target, source, env): action=env.VerboseAction(" ".join([ '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", + "--dont-append-digest", "--flash_mode", "$BOARD_FLASH_MODE", "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", board.get("upload.flash_size", "detect"), + "--flash_size", board.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" ]), "Building $TARGET"), suffix=".bin" @@ -261,6 +292,10 @@ def __fetch_fs_size(target, source, env): source_factory=env.Dir, suffix=".bin", ), + MergeBin=Builder( + generator=merge_binaries, + suffix=".bin", + ), ) ) @@ -272,6 +307,7 @@ def __fetch_fs_size(target, source, env): # target_elf = None +target_firm_merged = None if "nobuild" in COMMAND_LINE_TARGETS: target_elf = join("$BUILD_DIR", "${PROGNAME}.elf") if set(["uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): @@ -290,6 +326,14 @@ def __fetch_fs_size(target, source, env): else: target_firm = env.ElfToBin( join("$BUILD_DIR", "${PROGNAME}"), target_elf) + if firmware_merge_required: + # Note: Default offset address must be set to 0x0 because debugging + # relies on OpenOCD that requires merged firmware + env["INTEGRATION_EXTRA_DATA"].update( + {"application_offset": "0x0", "merged_firmware": True} + ) + target_firm_merged = env.MergeBin(join( + "$BUILD_DIR", "${PROGNAME}_merged"), target_firm) env.Depends(target_firm, "checkprogsize") env.AddPlatformTarget("buildfs", target_firm, target_firm, "Build Filesystem Image") @@ -427,6 +471,10 @@ def __fetch_fs_size(target, source, env): elif upload_protocol in debug_tools: + if firmware_merge_required: + # Only merged firmware with proper headers will work when uploading is done via + # debug probes. The firmware offset address must be adjusted to 0x0 accordingly. + target_firm = target_firm_merged openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)] openocd_args.extend( debug_tools.get(upload_protocol).get("server").get("arguments", [])) @@ -439,11 +487,14 @@ def __fetch_fs_size(target, source, env): % ( "$FS_START" if "uploadfs" in COMMAND_LINE_TARGETS - else "$ESP32_APP_OFFSET" + else board.get( + "upload.offset_address", + "0x0" if firmware_merge_required else "$ESP32_APP_OFFSET" + ) ), ] ) - if "uploadfs" not in COMMAND_LINE_TARGETS: + if "uploadfs" not in COMMAND_LINE_TARGETS and not firmware_merge_required: for image in env.get("FLASH_EXTRA_IMAGES", []): openocd_args.extend( [ @@ -501,6 +552,13 @@ def __fetch_fs_size(target, source, env): print("Warning! '-Wl,-T' option for specifying linker scripts is deprecated. " "Please use 'board_build.ldscript' option in your 'platformio.ini' file.") +# +# A temporary workaround to propagate additional data to the debug configuration routine +# + +Import("projenv") +projenv["INTEGRATION_EXTRA_DATA"] = env.get("INTEGRATION_EXTRA_DATA") + # # Default targets # diff --git a/platform.json b/platform.json index 520ce0892..a38d53edc 100644 --- a/platform.json +++ b/platform.json @@ -12,13 +12,13 @@ "RISC-V" ], "engines": { - "platformio": ">=6.0.2" + "platformio": ">=6.1.0" }, "repository": { "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.4", + "version": "2.0.4+1", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -120,7 +120,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v3.3.1/esptool-3.3.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.1.zip" }, "tool-mbctool": { "optional": true, diff --git a/platform.py b/platform.py index 9b048fcf6..2219d0954 100644 --- a/platform.py +++ b/platform.py @@ -278,16 +278,23 @@ def configure_debug_session(self, debug_config): if any(ignore_conds): return - load_cmds = [ - 'monitor program_esp "{{{path}}}" {offset} verify'.format( - path=to_unix_path(item["path"]), offset=item["offset"] - ) - for item in flash_images - ] + merged_firmware = build_extra_data.get("merged_firmware", False) + load_cmds = [] + if not merged_firmware: + load_cmds.extend([ + 'monitor program_esp "{{{path}}}" {offset} verify'.format( + path=to_unix_path(item["path"]), offset=item["offset"] + ) + for item in flash_images + ]) + load_cmds.append( 'monitor program_esp "{%s.bin}" %s verify' % ( - to_unix_path(debug_config.build_data["prog_path"][:-4]), + to_unix_path( + debug_config.build_data["prog_path"][:-4] + + ("_merged" if merged_firmware else "") + ), build_extra_data.get("application_offset", "0x10000"), ) ) @@ -389,4 +396,4 @@ def configure_upstream_arduino_packages(self, url_items): print("Configuring toolchain packages from a remote source...") self.configure_arduino_toolchains( self.download_remote_package_index(url_items) - ) \ No newline at end of file + ) From c93d422db276edd53b88ea17b2ce232320f7d7ba Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 3 Aug 2022 11:10:46 +0200 Subject: [PATCH 103/666] Mode qio --- boards/esp32-s3-devkitc-1.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json index 9f32208fc..7bc3b3725 100644 --- a/boards/esp32-s3-devkitc-1.json +++ b/boards/esp32-s3-devkitc-1.json @@ -13,7 +13,7 @@ ], "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "hwids": [ [ "0X303A", From ef3fb36a9676026644c5cc5558cf01d2379afe84 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 3 Aug 2022 11:11:51 +0200 Subject: [PATCH 104/666] Mode qio --- boards/esp32-s3-devkitc-1.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json index 9f32208fc..7bc3b3725 100644 --- a/boards/esp32-s3-devkitc-1.json +++ b/boards/esp32-s3-devkitc-1.json @@ -13,7 +13,7 @@ ], "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "hwids": [ [ "0X303A", From dc7249d0e069ec2729a49725a387a7669a92ff8e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 4 Aug 2022 10:22:44 +0200 Subject: [PATCH 105/666] Board supports qio --- boards/pico32.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/pico32.json b/boards/pico32.json index 5580b07e0..c5bf35332 100644 --- a/boards/pico32.json +++ b/boards/pico32.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ESP32_PICO", "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32", "variant": "pico32" }, From 2f2e317b4cbad74e6311873157fa30a14a646433 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 5 Aug 2022 18:24:58 +0200 Subject: [PATCH 106/666] OpenOCD has now apple ARM support --- platform.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/platform.json b/platform.json index a38d53edc..c5211bd8e 100644 --- a/platform.json +++ b/platform.json @@ -93,12 +93,6 @@ "owner": "tasmota", "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-riscv32-esp.tar.gz" }, - "tool-openocd-esp32-arm": { - "type": "debugger", - "optional": true, - "owner": "tasmota", - "version": "https://github.com/Jason2866/openocd-esp32/releases/download/v0.11.0-esp32-20220404/openocd-esp32-macos-arm64-0.11.0-esp32-20220424.zip" - }, "toolchain-esp32ulp": { "type": "toolchain", "optional": true, From cc39700b677c503f38ea3b370b3bc8e4320745a2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 5 Aug 2022 18:26:36 +0200 Subject: [PATCH 107/666] rm custom OpenOCD --- platform.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/platform.py b/platform.py index 2219d0954..9f0417eab 100644 --- a/platform.py +++ b/platform.py @@ -41,11 +41,6 @@ def configure_default_packages(self, variables, targets): self.packages["tool-mkfatfs"]["optional"] = False else: self.packages["tool-mkspiffs"]["optional"] = False - if variables.get("upload_protocol"): - if "darwin" in get_systype() and "arm64" in get_systype(): - self.packages["tool-openocd-esp32-arm"]["optional"] = False - if not "arm64" in get_systype(): - self.packages["tool-openocd-esp32"]["optional"] = False if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False From 07b93579fbc700f848a81276e214e3cd7669f52c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 5 Aug 2022 19:03:14 +0200 Subject: [PATCH 108/666] fix install OpenOCD --- platform.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform.py b/platform.py index 9f0417eab..becb183f0 100644 --- a/platform.py +++ b/platform.py @@ -41,6 +41,8 @@ def configure_default_packages(self, variables, targets): self.packages["tool-mkfatfs"]["optional"] = False else: self.packages["tool-mkspiffs"]["optional"] = False + if variables.get("upload_protocol"): + self.packages["tool-openocd-esp32"]["optional"] = False if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False From 0d2e4d52b9be8377ad1f7f491e744c77ccf122a8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 10 Aug 2022 12:50:01 +0200 Subject: [PATCH 109/666] Allow overriding reset operation via project file --- builder/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index 41a93dc05..bfbf355f3 100644 --- a/builder/main.py +++ b/builder/main.py @@ -409,8 +409,8 @@ def merge_binaries(source, target, env, for_signature): "--chip", mcu, "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", - "--before", "default_reset", - "--after", "hard_reset", + "--before", board.get("upload.before_reset", "default_reset"), + "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", From ce4344357998ecb004ccad028406e521db81eb7e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 10 Aug 2022 12:52:10 +0200 Subject: [PATCH 110/666] Allow overriding reset operation via project file --- builder/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index 41a93dc05..bfbf355f3 100644 --- a/builder/main.py +++ b/builder/main.py @@ -409,8 +409,8 @@ def merge_binaries(source, target, env, for_signature): "--chip", mcu, "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", - "--before", "default_reset", - "--after", "hard_reset", + "--before", board.get("upload.before_reset", "default_reset"), + "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", From 2d897ad4faddcdf4033f2b09ce18f52b2de7c0df Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 14 Aug 2022 13:07:45 +0200 Subject: [PATCH 111/666] flash options from env for uploadfs --- builder/main.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/builder/main.py b/builder/main.py index bfbf355f3..81efb60d1 100644 --- a/builder/main.py +++ b/builder/main.py @@ -427,11 +427,12 @@ def merge_binaries(source, target, env, for_signature): "--chip", mcu, "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", - "--before", "default_reset", - "--after", "hard_reset", + "--before", board.get("upload.before_reset", "default_reset"), + "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", - "--flash_mode", "$BOARD_FLASH_MODE", - "--flash_size", "detect", + "--flash_mode", "${__get_board_flash_mode(__env__)}", + "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_size", board.get("upload.flash_size", "detect") "$FS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', From 2950684722676a13e305c6fa059523401f0c34b4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 14 Aug 2022 13:13:09 +0200 Subject: [PATCH 112/666] revert --- builder/main.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/builder/main.py b/builder/main.py index 81efb60d1..bfbf355f3 100644 --- a/builder/main.py +++ b/builder/main.py @@ -427,12 +427,11 @@ def merge_binaries(source, target, env, for_signature): "--chip", mcu, "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", - "--before", board.get("upload.before_reset", "default_reset"), - "--after", board.get("upload.after_reset", "hard_reset"), + "--before", "default_reset", + "--after", "hard_reset", "write_flash", "-z", - "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", board.get("upload.flash_size", "detect") + "--flash_mode", "$BOARD_FLASH_MODE", + "--flash_size", "detect", "$FS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', From 5b63b5e56556a917c51dff5337efe918eb15de65 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 14 Aug 2022 13:21:01 +0200 Subject: [PATCH 113/666] flash options from env for uploadfs --- builder/main.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/builder/main.py b/builder/main.py index bfbf355f3..2845c069e 100644 --- a/builder/main.py +++ b/builder/main.py @@ -422,16 +422,19 @@ def merge_binaries(source, target, env, for_signature): env.Append(UPLOADERFLAGS=[image[0], env.subst(image[1])]) if "uploadfs" in COMMAND_LINE_TARGETS: + before_reset = board.get("upload.before_reset", "default_reset"), + after_reset = board.get("upload.after_reset", "hard_reset"), + flash_size = board.get("upload.flash_size", "detect"), env.Replace( UPLOADERFLAGS=[ "--chip", mcu, "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", - "--before", "default_reset", - "--after", "hard_reset", + "--before", before_reset, + "--after", after_reset, "write_flash", "-z", "--flash_mode", "$BOARD_FLASH_MODE", - "--flash_size", "detect", + "--flash_size", flash_size, "$FS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', From c09de188d82b4485fc76d9e0b50d1d752f5691cc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 14 Aug 2022 13:39:58 +0200 Subject: [PATCH 114/666] no .DS_Store --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0d20b6487..0205d62f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.pyc +.DS_Store From 6485cf46a42c19eb6497db20d14bc6dc871b5ab1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 14 Aug 2022 14:21:33 +0200 Subject: [PATCH 115/666] fix boot flash mode --- builder/main.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index 2845c069e..485c9a3e4 100644 --- a/builder/main.py +++ b/builder/main.py @@ -168,7 +168,8 @@ def merge_binaries(source, target, env, for_signature): join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), "--chip", mcu, "merge_bin", "-o", "$TARGET", - "--flash_mode", "$BOARD_FLASH_MODE", + "--flash_mode", "${__get_board_flash_mode(__env__)}", + "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "4MB"), "$ESP32_APP_OFFSET", "$SOURCES" ] + ['"%s"' % itm for img in env.get("FLASH_EXTRA_IMAGES", []) for itm in img]) @@ -433,7 +434,8 @@ def merge_binaries(source, target, env, for_signature): "--before", before_reset, "--after", after_reset, "write_flash", "-z", - "--flash_mode", "$BOARD_FLASH_MODE", + "--flash_mode", "${__get_board_flash_mode(__env__)}", + "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", flash_size, "$FS_START" ], From 2caf038500c9baa21874ed758baedc9b370432e8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 14 Aug 2022 14:28:20 +0200 Subject: [PATCH 116/666] refactor --- builder/main.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/builder/main.py b/builder/main.py index 485c9a3e4..38db70e8c 100644 --- a/builder/main.py +++ b/builder/main.py @@ -423,20 +423,17 @@ def merge_binaries(source, target, env, for_signature): env.Append(UPLOADERFLAGS=[image[0], env.subst(image[1])]) if "uploadfs" in COMMAND_LINE_TARGETS: - before_reset = board.get("upload.before_reset", "default_reset"), - after_reset = board.get("upload.after_reset", "hard_reset"), - flash_size = board.get("upload.flash_size", "detect"), env.Replace( UPLOADERFLAGS=[ "--chip", mcu, "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", - "--before", before_reset, - "--after", after_reset, + "--before", board.get("upload.before_reset", "default_reset"), + "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", flash_size, + "--flash_size", board.get("upload.flash_size", "detect"), "$FS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', From c0fb913997f6941065aef6fea58057750fb1cab3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 14 Aug 2022 14:53:38 +0200 Subject: [PATCH 117/666] Fix bootloader flash mode * Allow overriding reset operation via project file * fix boot flash mode --- .gitignore | 1 + boards/pico32.json | 2 +- builder/main.py | 12 +++++++----- platform.json | 6 ------ platform.py | 5 +---- 5 files changed, 10 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 0d20b6487..0205d62f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.pyc +.DS_Store diff --git a/boards/pico32.json b/boards/pico32.json index 5580b07e0..c5bf35332 100644 --- a/boards/pico32.json +++ b/boards/pico32.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ESP32_PICO", "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32", "variant": "pico32" }, diff --git a/builder/main.py b/builder/main.py index bfbf355f3..38db70e8c 100644 --- a/builder/main.py +++ b/builder/main.py @@ -168,7 +168,8 @@ def merge_binaries(source, target, env, for_signature): join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), "--chip", mcu, "merge_bin", "-o", "$TARGET", - "--flash_mode", "$BOARD_FLASH_MODE", + "--flash_mode", "${__get_board_flash_mode(__env__)}", + "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "4MB"), "$ESP32_APP_OFFSET", "$SOURCES" ] + ['"%s"' % itm for img in env.get("FLASH_EXTRA_IMAGES", []) for itm in img]) @@ -427,11 +428,12 @@ def merge_binaries(source, target, env, for_signature): "--chip", mcu, "--port", '"$UPLOAD_PORT"', "--baud", "$UPLOAD_SPEED", - "--before", "default_reset", - "--after", "hard_reset", + "--before", board.get("upload.before_reset", "default_reset"), + "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", - "--flash_mode", "$BOARD_FLASH_MODE", - "--flash_size", "detect", + "--flash_mode", "${__get_board_flash_mode(__env__)}", + "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_size", board.get("upload.flash_size", "detect"), "$FS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', diff --git a/platform.json b/platform.json index a38d53edc..c5211bd8e 100644 --- a/platform.json +++ b/platform.json @@ -93,12 +93,6 @@ "owner": "tasmota", "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-riscv32-esp.tar.gz" }, - "tool-openocd-esp32-arm": { - "type": "debugger", - "optional": true, - "owner": "tasmota", - "version": "https://github.com/Jason2866/openocd-esp32/releases/download/v0.11.0-esp32-20220404/openocd-esp32-macos-arm64-0.11.0-esp32-20220424.zip" - }, "toolchain-esp32ulp": { "type": "toolchain", "optional": true, diff --git a/platform.py b/platform.py index 2219d0954..becb183f0 100644 --- a/platform.py +++ b/platform.py @@ -42,10 +42,7 @@ def configure_default_packages(self, variables, targets): else: self.packages["tool-mkspiffs"]["optional"] = False if variables.get("upload_protocol"): - if "darwin" in get_systype() and "arm64" in get_systype(): - self.packages["tool-openocd-esp32-arm"]["optional"] = False - if not "arm64" in get_systype(): - self.packages["tool-openocd-esp32"]["optional"] = False + self.packages["tool-openocd-esp32"]["optional"] = False if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False From a8824c593fc78ea41e4e4cda16fc0c552dd48922 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 14 Aug 2022 15:31:35 +0200 Subject: [PATCH 118/666] Esptool.py v4.2.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index c5211bd8e..f0c23f0ec 100644 --- a/platform.json +++ b/platform.json @@ -114,7 +114,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.2.1/esptool-4.2.1.zip" }, "tool-mbctool": { "optional": true, From 6e03048e340abe25039537dc7cb330d82d3198ec Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 14 Aug 2022 15:42:53 +0200 Subject: [PATCH 119/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index c5211bd8e..f0c23f0ec 100644 --- a/platform.json +++ b/platform.json @@ -114,7 +114,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.1/esptool-4.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.2.1/esptool-4.2.1.zip" }, "tool-mbctool": { "optional": true, From 624d139d1146f3386a04b66578f9e7ac4a814558 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 16 Aug 2022 13:15:45 +0200 Subject: [PATCH 120/666] =?UTF-8?q?Update=20bootloader=20image=20headers?= =?UTF-8?q?=20before=20debugging=20or=20uploading=20via=20deb=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ug tools This approach is less intrusive than merging the entire application into one binary implemented in #006d64e8b268e479703a0aac7eed8bef1ebea587 In this implementation we safely copy the required bootloader binary to the build directory, adjust the headers via esptoolpy and the "merge_bin" command according to --flash-size and --flash-mode arguments. --- builder/main.py | 91 +++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/builder/main.py b/builder/main.py index 38db70e8c..582fecf73 100644 --- a/builder/main.py +++ b/builder/main.py @@ -162,19 +162,6 @@ def __fetch_fs_size(target, source, env): return (target, source) -def merge_binaries(source, target, env, for_signature): - return " ".join([ - '"$PYTHONEXE"', - join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), - "--chip", mcu, "merge_bin", - "-o", "$TARGET", - "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", board.get("upload.flash_size", "4MB"), - "$ESP32_APP_OFFSET", "$SOURCES" - ] + ['"%s"' % itm for img in env.get("FLASH_EXTRA_IMAGES", []) for itm in img]) - - env = DefaultEnvironment() platform = env.PioPlatform() board = env.BoardConfig() @@ -184,21 +171,6 @@ def merge_binaries(source, target, env, for_signature): if mcu == "esp32c3": toolchain_arch = "riscv32-esp" -# Arduino core v2.0.4 contains updated bootloader images that have innacurate default -# headers. This results in bootloops if firmware is flashed via OpenOCD (e.g. debugging -# or uploading via debug tools). For this reason, before uploading or debugging we need -# to merge binaries via esptoolpy so that the image headers will be adjusted according to -# --flash-size and --flash-mode arguments. -# Note: This behavior doesn't occur if uploading is done via esptoolpy, as esptoolpy -# overrides the binary image headers before flashing. -firmware_merge_required = bool( - env.get("PIOFRAMEWORK", []) == ["arduino"] - and ( - "debug" in env.GetBuildType() - or env.subst("$UPLOAD_PROTOCOL") in board.get("debug.tools", {}) - ) -) - if "INTEGRATION_EXTRA_DATA" not in env: env["INTEGRATION_EXTRA_DATA"] = {} @@ -293,10 +265,6 @@ def merge_binaries(source, target, env, for_signature): source_factory=env.Dir, suffix=".bin", ), - MergeBin=Builder( - generator=merge_binaries, - suffix=".bin", - ), ) ) @@ -308,7 +276,6 @@ def merge_binaries(source, target, env, for_signature): # target_elf = None -target_firm_merged = None if "nobuild" in COMMAND_LINE_TARGETS: target_elf = join("$BUILD_DIR", "${PROGNAME}.elf") if set(["uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): @@ -327,14 +294,6 @@ def merge_binaries(source, target, env, for_signature): else: target_firm = env.ElfToBin( join("$BUILD_DIR", "${PROGNAME}"), target_elf) - if firmware_merge_required: - # Note: Default offset address must be set to 0x0 because debugging - # relies on OpenOCD that requires merged firmware - env["INTEGRATION_EXTRA_DATA"].update( - {"application_offset": "0x0", "merged_firmware": True} - ) - target_firm_merged = env.MergeBin(join( - "$BUILD_DIR", "${PROGNAME}_merged"), target_firm) env.Depends(target_firm, "checkprogsize") env.AddPlatformTarget("buildfs", target_firm, target_firm, "Build Filesystem Image") @@ -364,6 +323,47 @@ def merge_binaries(source, target, env, for_signature): "Calculate program size", ) +# Arduino core v2.0.4 contains updated bootloader images that have innacurate default +# headers. This results in bootloops if firmware is flashed via OpenOCD (e.g. debugging +# or uploading via debug tools). For this reason, before uploading or debugging we need +# to adjust the bootloader binary according to --flash-size and --flash-mode arguments. +# Note: This behavior doesn't occur if uploading is done via esptoolpy, as esptoolpy +# overrides the binary image headers before flashing. +bootloader_patch_required = bool( + env.get("PIOFRAMEWORK", []) == ["arduino"] + and ( + "debug" in env.GetBuildType() + or env.subst("$UPLOAD_PROTOCOL") in board.get("debug.tools", {}) + ) +) + +if bootloader_patch_required: + result = [] + for offset, image in env.get("FLASH_EXTRA_IMAGES", []): + # 0x1000 for ESP32/S2, 0x0 for others + default_bootloader_offsets = ("0x0", "0x0000", "0x1000") + if offset in default_bootloader_offsets: + original_bootloader_path = env.subst(image) + image = join(env.subst("$BUILD_DIR"), "patched_bootloader.bin") + env.AddPreAction( + target_elf, + env.VerboseAction(" ".join([ + '"$PYTHONEXE"', + join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), + "--chip", mcu, "merge_bin", + "-o", '"%s"' % image, + "--flash_mode", _get_board_flash_mode(env), + "--flash_freq", _get_board_f_flash(env), + "--flash_size", board.get("upload.flash_size", "4MB"), + "--target-offset", offset, + offset, '"%s"' % original_bootloader_path + ]), "Updating bootloader headers") + ) + + result.append((offset, image)) + + env.Replace(FLASH_EXTRA_IMAGES=result) + # # Target: Upload firmware or FS image # @@ -473,10 +473,6 @@ def merge_binaries(source, target, env, for_signature): elif upload_protocol in debug_tools: - if firmware_merge_required: - # Only merged firmware with proper headers will work when uploading is done via - # debug probes. The firmware offset address must be adjusted to 0x0 accordingly. - target_firm = target_firm_merged openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)] openocd_args.extend( debug_tools.get(upload_protocol).get("server").get("arguments", [])) @@ -490,13 +486,12 @@ def merge_binaries(source, target, env, for_signature): "$FS_START" if "uploadfs" in COMMAND_LINE_TARGETS else board.get( - "upload.offset_address", - "0x0" if firmware_merge_required else "$ESP32_APP_OFFSET" + "upload.offset_address", "$ESP32_APP_OFFSET" ) ), ] ) - if "uploadfs" not in COMMAND_LINE_TARGETS and not firmware_merge_required: + if "uploadfs" not in COMMAND_LINE_TARGETS: for image in env.get("FLASH_EXTRA_IMAGES", []): openocd_args.extend( [ From 4a71d4b843329f70fa4aa2315238ee4e200538ff Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 16 Aug 2022 13:32:03 +0200 Subject: [PATCH 121/666] Change in OCD firmware generation In this implementation we safely copy the required bootloader binary to the build directory, adjust the headers via esptoolpy and the "merge_bin" command according to --flash-size and --flash-mode arguments. --- builder/main.py | 91 +++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/builder/main.py b/builder/main.py index 38db70e8c..582fecf73 100644 --- a/builder/main.py +++ b/builder/main.py @@ -162,19 +162,6 @@ def __fetch_fs_size(target, source, env): return (target, source) -def merge_binaries(source, target, env, for_signature): - return " ".join([ - '"$PYTHONEXE"', - join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), - "--chip", mcu, "merge_bin", - "-o", "$TARGET", - "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", board.get("upload.flash_size", "4MB"), - "$ESP32_APP_OFFSET", "$SOURCES" - ] + ['"%s"' % itm for img in env.get("FLASH_EXTRA_IMAGES", []) for itm in img]) - - env = DefaultEnvironment() platform = env.PioPlatform() board = env.BoardConfig() @@ -184,21 +171,6 @@ def merge_binaries(source, target, env, for_signature): if mcu == "esp32c3": toolchain_arch = "riscv32-esp" -# Arduino core v2.0.4 contains updated bootloader images that have innacurate default -# headers. This results in bootloops if firmware is flashed via OpenOCD (e.g. debugging -# or uploading via debug tools). For this reason, before uploading or debugging we need -# to merge binaries via esptoolpy so that the image headers will be adjusted according to -# --flash-size and --flash-mode arguments. -# Note: This behavior doesn't occur if uploading is done via esptoolpy, as esptoolpy -# overrides the binary image headers before flashing. -firmware_merge_required = bool( - env.get("PIOFRAMEWORK", []) == ["arduino"] - and ( - "debug" in env.GetBuildType() - or env.subst("$UPLOAD_PROTOCOL") in board.get("debug.tools", {}) - ) -) - if "INTEGRATION_EXTRA_DATA" not in env: env["INTEGRATION_EXTRA_DATA"] = {} @@ -293,10 +265,6 @@ def merge_binaries(source, target, env, for_signature): source_factory=env.Dir, suffix=".bin", ), - MergeBin=Builder( - generator=merge_binaries, - suffix=".bin", - ), ) ) @@ -308,7 +276,6 @@ def merge_binaries(source, target, env, for_signature): # target_elf = None -target_firm_merged = None if "nobuild" in COMMAND_LINE_TARGETS: target_elf = join("$BUILD_DIR", "${PROGNAME}.elf") if set(["uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): @@ -327,14 +294,6 @@ def merge_binaries(source, target, env, for_signature): else: target_firm = env.ElfToBin( join("$BUILD_DIR", "${PROGNAME}"), target_elf) - if firmware_merge_required: - # Note: Default offset address must be set to 0x0 because debugging - # relies on OpenOCD that requires merged firmware - env["INTEGRATION_EXTRA_DATA"].update( - {"application_offset": "0x0", "merged_firmware": True} - ) - target_firm_merged = env.MergeBin(join( - "$BUILD_DIR", "${PROGNAME}_merged"), target_firm) env.Depends(target_firm, "checkprogsize") env.AddPlatformTarget("buildfs", target_firm, target_firm, "Build Filesystem Image") @@ -364,6 +323,47 @@ def merge_binaries(source, target, env, for_signature): "Calculate program size", ) +# Arduino core v2.0.4 contains updated bootloader images that have innacurate default +# headers. This results in bootloops if firmware is flashed via OpenOCD (e.g. debugging +# or uploading via debug tools). For this reason, before uploading or debugging we need +# to adjust the bootloader binary according to --flash-size and --flash-mode arguments. +# Note: This behavior doesn't occur if uploading is done via esptoolpy, as esptoolpy +# overrides the binary image headers before flashing. +bootloader_patch_required = bool( + env.get("PIOFRAMEWORK", []) == ["arduino"] + and ( + "debug" in env.GetBuildType() + or env.subst("$UPLOAD_PROTOCOL") in board.get("debug.tools", {}) + ) +) + +if bootloader_patch_required: + result = [] + for offset, image in env.get("FLASH_EXTRA_IMAGES", []): + # 0x1000 for ESP32/S2, 0x0 for others + default_bootloader_offsets = ("0x0", "0x0000", "0x1000") + if offset in default_bootloader_offsets: + original_bootloader_path = env.subst(image) + image = join(env.subst("$BUILD_DIR"), "patched_bootloader.bin") + env.AddPreAction( + target_elf, + env.VerboseAction(" ".join([ + '"$PYTHONEXE"', + join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), + "--chip", mcu, "merge_bin", + "-o", '"%s"' % image, + "--flash_mode", _get_board_flash_mode(env), + "--flash_freq", _get_board_f_flash(env), + "--flash_size", board.get("upload.flash_size", "4MB"), + "--target-offset", offset, + offset, '"%s"' % original_bootloader_path + ]), "Updating bootloader headers") + ) + + result.append((offset, image)) + + env.Replace(FLASH_EXTRA_IMAGES=result) + # # Target: Upload firmware or FS image # @@ -473,10 +473,6 @@ def merge_binaries(source, target, env, for_signature): elif upload_protocol in debug_tools: - if firmware_merge_required: - # Only merged firmware with proper headers will work when uploading is done via - # debug probes. The firmware offset address must be adjusted to 0x0 accordingly. - target_firm = target_firm_merged openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)] openocd_args.extend( debug_tools.get(upload_protocol).get("server").get("arguments", [])) @@ -490,13 +486,12 @@ def merge_binaries(source, target, env, for_signature): "$FS_START" if "uploadfs" in COMMAND_LINE_TARGETS else board.get( - "upload.offset_address", - "0x0" if firmware_merge_required else "$ESP32_APP_OFFSET" + "upload.offset_address", "$ESP32_APP_OFFSET" ) ), ] ) - if "uploadfs" not in COMMAND_LINE_TARGETS and not firmware_merge_required: + if "uploadfs" not in COMMAND_LINE_TARGETS: for image in env.get("FLASH_EXTRA_IMAGES", []): openocd_args.extend( [ From 28cf70ee174168c4b6a9ad88c6b64c3132446b20 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 20 Aug 2022 14:46:55 +0200 Subject: [PATCH 122/666] better specs --- boards/denky_d4.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boards/denky_d4.json b/boards/denky_d4.json index e5d0b76bd..7846bf1d8 100644 --- a/boards/denky_d4.json +++ b/boards/denky_d4.json @@ -10,7 +10,7 @@ ], "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32", "variant": "ch_denky" }, @@ -26,11 +26,11 @@ ], "name": "Denky D4 (PICO-V3-02)", "upload": { - "flash_size": "4MB", + "flash_size": "8MB", "maximum_ram_size": 327680, - "maximum_size": 4194304, + "maximum_size": 8388608, "require_upload_port": true, - "speed": 460800 + "speed": 2000000 }, "url": "https://en.wikipedia.org/wiki/ESP32", "vendor": "Denky" From fe5b2067e7d0a004b83b85f2df4671b313e43bb2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 20 Aug 2022 14:47:50 +0200 Subject: [PATCH 123/666] qio and 8MB and faster upload --- boards/denky_d4.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boards/denky_d4.json b/boards/denky_d4.json index e5d0b76bd..7846bf1d8 100644 --- a/boards/denky_d4.json +++ b/boards/denky_d4.json @@ -10,7 +10,7 @@ ], "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32", "variant": "ch_denky" }, @@ -26,11 +26,11 @@ ], "name": "Denky D4 (PICO-V3-02)", "upload": { - "flash_size": "4MB", + "flash_size": "8MB", "maximum_ram_size": 327680, - "maximum_size": 4194304, + "maximum_size": 8388608, "require_upload_port": true, - "speed": 460800 + "speed": 2000000 }, "url": "https://en.wikipedia.org/wiki/ESP32", "vendor": "Denky" From 144b962209cb9a8563852eb3e2552d3e4762c4c0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 23 Aug 2022 13:53:30 +0200 Subject: [PATCH 124/666] replace deprecated flash modes --- boards/adafruit_qtpy_esp32c3.json | 2 +- boards/esp32s3camlcd.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/adafruit_qtpy_esp32c3.json b/boards/adafruit_qtpy_esp32c3.json index 335002d1c..9ec2dbf05 100644 --- a/boards/adafruit_qtpy_esp32c3.json +++ b/boards/adafruit_qtpy_esp32c3.json @@ -11,7 +11,7 @@ ], "f_cpu": "160000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "dio", "hwids": [ [ "0X303A", diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index 34810b5a5..f0fe6a64b 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -15,7 +15,7 @@ ], "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "qio", "hwids": [ [ "0X303A", From 1f809456084221f7446359f12b304ad87776ff44 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 23 Aug 2022 14:00:39 +0200 Subject: [PATCH 125/666] Board support faster flash mode --- boards/m5stack-core2.json | 2 +- boards/onehorse32dev.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/m5stack-core2.json b/boards/m5stack-core2.json index 2c3b95154..4154831c4 100644 --- a/boards/m5stack-core2.json +++ b/boards/m5stack-core2.json @@ -8,7 +8,7 @@ "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32", "variant": "m5stack_core2" }, diff --git a/boards/onehorse32dev.json b/boards/onehorse32dev.json index 4b2364100..42a2f00a5 100644 --- a/boards/onehorse32dev.json +++ b/boards/onehorse32dev.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ONEHORSE_ESP32_DEV", "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32", "variant": "onehorse32dev" }, From af36de60731d6b60c69730eb1350b4addea857fe Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 23 Aug 2022 14:36:37 +0200 Subject: [PATCH 126/666] Update boards manifests (#27) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Tasmota github as source * --dont-append-digest * esptool v4.1 * 2.0.5dev * platformio": ">=6.1.0 * Update espidf.py * Add default nameOnDisk value for external CMake projects * Build 918 newest wifi libs from idf44 * Tasmota IDF 4.4.3 * Tasmota release Core 2.0.4.1 * Merge firmware before flashing via OpenOCD * Merge firmware before flashing via OpenOCD * Update arduino.py * Update espidf.py * update boards 1/2 * Update Boards 2/2 * v2.0.4.1 * Mode qio * Board supports qio * OpenOCD has now apple ARM support * rm custom OpenOCD * fix install OpenOCD * Allow overriding reset operation via project file * flash options from env for uploadfs * revert * flash options from env for uploadfs * no .DS_Store * fix boot flash mode * refactor * Esptool.py v4.2.1 * Update bootloader image headers before debugging or uploading via deb… …ug tools This approach is less intrusive than merging the entire application into one binary implemented in #006d64e8b268e479703a0aac7eed8bef1ebea587 In this implementation we safely copy the required bootloader binary to the build directory, adjust the headers via esptoolpy and the "merge_bin" command according to --flash-size and --flash-mode arguments. * better specs * replace deprecated flash modes * Board support faster flash mode --- boards/adafruit_qtpy_esp32c3.json | 2 +- boards/esp32s3camlcd.json | 2 +- boards/m5stack-core2.json | 2 +- boards/onehorse32dev.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/boards/adafruit_qtpy_esp32c3.json b/boards/adafruit_qtpy_esp32c3.json index 335002d1c..9ec2dbf05 100644 --- a/boards/adafruit_qtpy_esp32c3.json +++ b/boards/adafruit_qtpy_esp32c3.json @@ -11,7 +11,7 @@ ], "f_cpu": "160000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "dio", "hwids": [ [ "0X303A", diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index 34810b5a5..f0fe6a64b 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -15,7 +15,7 @@ ], "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dout", + "flash_mode": "qio", "hwids": [ [ "0X303A", diff --git a/boards/m5stack-core2.json b/boards/m5stack-core2.json index 2c3b95154..4154831c4 100644 --- a/boards/m5stack-core2.json +++ b/boards/m5stack-core2.json @@ -8,7 +8,7 @@ "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM", "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32", "variant": "m5stack_core2" }, diff --git a/boards/onehorse32dev.json b/boards/onehorse32dev.json index 4b2364100..42a2f00a5 100644 --- a/boards/onehorse32dev.json +++ b/boards/onehorse32dev.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ONEHORSE_ESP32_DEV", "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "dout", + "flash_mode": "dio", "mcu": "esp32", "variant": "onehorse32dev" }, From 46184cbc992f1c970aee7d21e7de46a80e42e1ac Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 25 Aug 2022 18:26:59 +0200 Subject: [PATCH 127/666] now "memory_type": "qio_opi" --- boards/esp32s3box.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/esp32s3box.json b/boards/esp32s3box.json index 2d7f99db4..6e31df298 100644 --- a/boards/esp32s3box.json +++ b/boards/esp32s3box.json @@ -2,7 +2,7 @@ "build": { "arduino":{ "ldscript": "esp32s3_out.ld", - "memory_type": "qspi_opi" + "memory_type": "qio_opi" }, "core": "esp32", "extra_flags": [ From 72b1fc1436c690425ef8d78223c3ffef2e83871d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 25 Aug 2022 18:28:48 +0200 Subject: [PATCH 128/666] qio --- boards/esp32-s3-usb.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/esp32-s3-usb.json b/boards/esp32-s3-usb.json index f741cafe6..68153b8f6 100644 --- a/boards/esp32-s3-usb.json +++ b/boards/esp32-s3-usb.json @@ -7,7 +7,7 @@ "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s3", "variant": "esp32s3" }, From c327d371d9d720ca1918b6ed96c6d5e651ec5080 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 26 Aug 2022 22:47:46 +0200 Subject: [PATCH 129/666] opi flash needs flash mode `dout` flash mode `dio `works for `qout` as mode too --- builder/main.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index 582fecf73..f642c94e4 100644 --- a/builder/main.py +++ b/builder/main.py @@ -49,10 +49,11 @@ def _get_board_f_flash(env): def _get_board_flash_mode(env): + memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi") mode = env.subst("$BOARD_FLASH_MODE") - if mode == "qio": + if mode == "qio" or mode == "qout": return "dio" - elif mode == "qout": + if memory_type == "opi_opi" or memory_type == "opi_qspi": return "dout" return mode From 197d6d3e97fe27b2470f0d73ed199929f610f066 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 2 Sep 2022 19:42:38 +0200 Subject: [PATCH 130/666] 8 MB --- boards/adafruit_qtpy_esp32s3_nopsram.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/adafruit_qtpy_esp32s3_nopsram.json b/boards/adafruit_qtpy_esp32s3_nopsram.json index 4412a31e4..57fb0098a 100644 --- a/boards/adafruit_qtpy_esp32s3_nopsram.json +++ b/boards/adafruit_qtpy_esp32s3_nopsram.json @@ -50,9 +50,9 @@ ] ] }, - "flash_size": "4MB", + "flash_size": "8MB", "maximum_ram_size": 327680, - "maximum_size": 4194304, + "maximum_size": 8388608, "use_1200bps_touch": true, "wait_for_upload_port": true, "require_upload_port": true, From 48ff5f1bdb931589ed9d3ab4a94553f64af03ab8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 2 Sep 2022 19:43:38 +0200 Subject: [PATCH 131/666] 8 MB --- boards/adafruit_qtpy_esp32s3_nopsram.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/adafruit_qtpy_esp32s3_nopsram.json b/boards/adafruit_qtpy_esp32s3_nopsram.json index 4412a31e4..57fb0098a 100644 --- a/boards/adafruit_qtpy_esp32s3_nopsram.json +++ b/boards/adafruit_qtpy_esp32s3_nopsram.json @@ -50,9 +50,9 @@ ] ] }, - "flash_size": "4MB", + "flash_size": "8MB", "maximum_ram_size": 327680, - "maximum_size": 4194304, + "maximum_size": 8388608, "use_1200bps_touch": true, "wait_for_upload_port": true, "require_upload_port": true, From 2cf6252b42dc31c37cd96cc5b589596df0a07f04 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 3 Sep 2022 12:22:41 +0200 Subject: [PATCH 132/666] Tasmota/205 * Update IDF to 4.4.3.1 * Use S2 / S3 / C3 as board * cmake v3.21 * core pre 2.0.5 * Move the process of patching bootloader to the Arduino build script * Remove obsolete workaround for propagating debug configurations * Update platform.py * Update platform.json * Update sdkconfig.defaults --- builder/main.py | 48 ------------- examples/arduino-blink/.travis.yml | 67 ------------------- .../arduino-briki-internal-libs/.travis.yml | 67 ------------------- examples/arduino-wifiscan/.travis.yml | 67 ------------------- examples/espidf-arduino-blink/.travis.yml | 67 ------------------- examples/espidf-arduino-blink/platformio.ini | 17 +++-- .../espidf-arduino-blink/sdkconfig.defaults | 18 +---- examples/espidf-arduino-wifiscan/.travis.yml | 67 ------------------- .../sdkconfig.defaults | 20 +----- examples/espidf-aws-iot/.travis.yml | 67 ------------------- examples/espidf-ble-eddystone/.travis.yml | 67 ------------------- examples/espidf-blink/.travis.yml | 67 ------------------- examples/espidf-coap-server/.travis.yml | 67 ------------------- examples/espidf-exceptions/.travis.yml | 67 ------------------- examples/espidf-hello-world/.travis.yml | 67 ------------------- examples/espidf-http-request/.travis.yml | 67 ------------------- examples/espidf-peripherals-uart/.travis.yml | 67 ------------------- examples/espidf-peripherals-usb/.travis.yml | 67 ------------------- examples/espidf-storage-sdcard/.travis.yml | 67 ------------------- examples/espidf-ulp-pulse/.travis.yml | 67 ------------------- platform.json | 8 +-- platform.py | 21 ++---- 22 files changed, 27 insertions(+), 1177 deletions(-) delete mode 100644 examples/arduino-blink/.travis.yml delete mode 100644 examples/arduino-briki-internal-libs/.travis.yml delete mode 100644 examples/arduino-wifiscan/.travis.yml delete mode 100644 examples/espidf-arduino-blink/.travis.yml delete mode 100644 examples/espidf-arduino-wifiscan/.travis.yml delete mode 100644 examples/espidf-aws-iot/.travis.yml delete mode 100644 examples/espidf-ble-eddystone/.travis.yml delete mode 100644 examples/espidf-blink/.travis.yml delete mode 100644 examples/espidf-coap-server/.travis.yml delete mode 100644 examples/espidf-exceptions/.travis.yml delete mode 100644 examples/espidf-hello-world/.travis.yml delete mode 100644 examples/espidf-http-request/.travis.yml delete mode 100644 examples/espidf-peripherals-uart/.travis.yml delete mode 100644 examples/espidf-peripherals-usb/.travis.yml delete mode 100644 examples/espidf-storage-sdcard/.travis.yml delete mode 100644 examples/espidf-ulp-pulse/.travis.yml diff --git a/builder/main.py b/builder/main.py index f642c94e4..347bf506c 100644 --- a/builder/main.py +++ b/builder/main.py @@ -324,47 +324,6 @@ def __fetch_fs_size(target, source, env): "Calculate program size", ) -# Arduino core v2.0.4 contains updated bootloader images that have innacurate default -# headers. This results in bootloops if firmware is flashed via OpenOCD (e.g. debugging -# or uploading via debug tools). For this reason, before uploading or debugging we need -# to adjust the bootloader binary according to --flash-size and --flash-mode arguments. -# Note: This behavior doesn't occur if uploading is done via esptoolpy, as esptoolpy -# overrides the binary image headers before flashing. -bootloader_patch_required = bool( - env.get("PIOFRAMEWORK", []) == ["arduino"] - and ( - "debug" in env.GetBuildType() - or env.subst("$UPLOAD_PROTOCOL") in board.get("debug.tools", {}) - ) -) - -if bootloader_patch_required: - result = [] - for offset, image in env.get("FLASH_EXTRA_IMAGES", []): - # 0x1000 for ESP32/S2, 0x0 for others - default_bootloader_offsets = ("0x0", "0x0000", "0x1000") - if offset in default_bootloader_offsets: - original_bootloader_path = env.subst(image) - image = join(env.subst("$BUILD_DIR"), "patched_bootloader.bin") - env.AddPreAction( - target_elf, - env.VerboseAction(" ".join([ - '"$PYTHONEXE"', - join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), - "--chip", mcu, "merge_bin", - "-o", '"%s"' % image, - "--flash_mode", _get_board_flash_mode(env), - "--flash_freq", _get_board_f_flash(env), - "--flash_size", board.get("upload.flash_size", "4MB"), - "--target-offset", offset, - offset, '"%s"' % original_bootloader_path - ]), "Updating bootloader headers") - ) - - result.append((offset, image)) - - env.Replace(FLASH_EXTRA_IMAGES=result) - # # Target: Upload firmware or FS image # @@ -550,13 +509,6 @@ def __fetch_fs_size(target, source, env): print("Warning! '-Wl,-T' option for specifying linker scripts is deprecated. " "Please use 'board_build.ldscript' option in your 'platformio.ini' file.") -# -# A temporary workaround to propagate additional data to the debug configuration routine -# - -Import("projenv") -projenv["INTEGRATION_EXTRA_DATA"] = env.get("INTEGRATION_EXTRA_DATA") - # # Default targets # diff --git a/examples/arduino-blink/.travis.yml b/examples/arduino-blink/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/arduino-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/arduino-briki-internal-libs/.travis.yml b/examples/arduino-briki-internal-libs/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/arduino-briki-internal-libs/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/arduino-wifiscan/.travis.yml b/examples/arduino-wifiscan/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/arduino-wifiscan/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-arduino-blink/.travis.yml b/examples/espidf-arduino-blink/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-arduino-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 0f991013b..823bb97a9 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -10,15 +10,20 @@ [env] platform = espressif32 framework = arduino, espidf -build_flags = - -D CONFIG_BLINK_GPIO=2 monitor_speed = 115200 [env:esp32dev] board = esp32dev +build_flags = -DCONFIG_BLINK_GPIO=2 -[env:espea32] -board = espea32 +[env:esp32-s2] +board = esp32-s2-saola-1 +build_flags = -DCONFIG_BLINK_GPIO=18 -[env:esp320] -board = esp320 +[env:esp32-s3] +board = esp32-s3-devkitc-1 +build_flags = -DCONFIG_BLINK_GPIO=48 + +[env:esp32-c3] +board = esp32-c3-devkitm-1 +build_flags = -DCONFIG_BLINK_GPIO=8 diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index f56753404..2c9d60715 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -1,17 +1,3 @@ -# Override some defaults to enable Arduino framework -CONFIG_ENABLE_ARDUINO_DEPENDS=y CONFIG_AUTOSTART_ARDUINO=y -CONFIG_ARDUINO_RUN_CORE1=y -CONFIG_ARDUINO_RUNNING_CORE=1 -CONFIG_ARDUINO_EVENT_RUN_CORE1=y -CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 -CONFIG_ARDUINO_UDP_RUN_CORE1=y -CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 -CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y -CONFIG_ARDUHAL_PARTITION_SCHEME="default" -CONFIG_AUTOCONNECT_WIFI=y -CONFIG_ARDUINO_SELECTIVE_WiFi=y -CONFIG_MBEDTLS_PSK_MODES=y -CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +# CONFIG_WS2812_LED_ENABLE is not set +CONFIG_FREERTOS_HZ=1000 diff --git a/examples/espidf-arduino-wifiscan/.travis.yml b/examples/espidf-arduino-wifiscan/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-arduino-wifiscan/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-arduino-wifiscan/sdkconfig.defaults b/examples/espidf-arduino-wifiscan/sdkconfig.defaults index cf124f4c4..8162986c6 100644 --- a/examples/espidf-arduino-wifiscan/sdkconfig.defaults +++ b/examples/espidf-arduino-wifiscan/sdkconfig.defaults @@ -1,20 +1,6 @@ -# Override some defaults to enable Arduino framework -CONFIG_ENABLE_ARDUINO_DEPENDS=y CONFIG_AUTOSTART_ARDUINO=y -CONFIG_ARDUINO_RUN_CORE1=y -CONFIG_ARDUINO_RUNNING_CORE=1 -CONFIG_ARDUINO_EVENT_RUN_CORE1=y -CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 -CONFIG_ARDUINO_UDP_RUN_CORE1=y -CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 -CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y -CONFIG_ARDUHAL_PARTITION_SCHEME="default" -CONFIG_AUTOCONNECT_WIFI=y -CONFIG_ARDUINO_SELECTIVE_WiFi=y -CONFIG_MBEDTLS_PSK_MODES=y -CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y -# Example configs +# CONFIG_WS2812_LED_ENABLE is not set +CONFIG_FREERTOS_HZ=1000 +# Example config CONFIG_EXAMPLE_WIFI_SSID="MYSSID" CONFIG_EXAMPLE_WIFI_PASSWORD="MYPASS" diff --git a/examples/espidf-aws-iot/.travis.yml b/examples/espidf-aws-iot/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-aws-iot/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-ble-eddystone/.travis.yml b/examples/espidf-ble-eddystone/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-ble-eddystone/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-blink/.travis.yml b/examples/espidf-blink/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-coap-server/.travis.yml b/examples/espidf-coap-server/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-coap-server/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-exceptions/.travis.yml b/examples/espidf-exceptions/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-exceptions/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-hello-world/.travis.yml b/examples/espidf-hello-world/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-hello-world/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-http-request/.travis.yml b/examples/espidf-http-request/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-http-request/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-peripherals-uart/.travis.yml b/examples/espidf-peripherals-uart/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-peripherals-uart/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-peripherals-usb/.travis.yml b/examples/espidf-peripherals-usb/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-peripherals-usb/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-storage-sdcard/.travis.yml b/examples/espidf-storage-sdcard/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-storage-sdcard/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-ulp-pulse/.travis.yml b/examples/espidf-ulp-pulse/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-ulp-pulse/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/platform.json b/platform.json index f0c23f0ec..2c267b15d 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.4+1", + "version": "2.0.5", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -37,13 +37,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.4.1/framework-arduinoespressif32.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/978/framework-arduinoespressif32-443_dev-162377cdfa.tar.gz" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" + "version": "https://github.com/Jason2866/esp-idf/releases/download/v4.4.3.1/esp-idf-v4.4.3.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -146,7 +146,7 @@ "tool-cmake": { "optional": true, "owner": "platformio", - "version": "~3.16.0" + "version": "~3.21.0" }, "tool-ninja": { "optional": true, diff --git a/platform.py b/platform.py index becb183f0..3606927de 100644 --- a/platform.py +++ b/platform.py @@ -275,23 +275,16 @@ def configure_debug_session(self, debug_config): if any(ignore_conds): return - merged_firmware = build_extra_data.get("merged_firmware", False) - load_cmds = [] - if not merged_firmware: - load_cmds.extend([ - 'monitor program_esp "{{{path}}}" {offset} verify'.format( - path=to_unix_path(item["path"]), offset=item["offset"] - ) - for item in flash_images - ]) - + load_cmds = [ + 'monitor program_esp "{{{path}}}" {offset} verify'.format( + path=to_unix_path(item["path"]), offset=item["offset"] + ) + for item in flash_images + ] load_cmds.append( 'monitor program_esp "{%s.bin}" %s verify' % ( - to_unix_path( - debug_config.build_data["prog_path"][:-4] - + ("_merged" if merged_firmware else "") - ), + to_unix_path(debug_config.build_data["prog_path"][:-4]), build_extra_data.get("application_offset", "0x10000"), ) ) From 862d74e6af6d8b28ccd6449815dfc838bec64f30 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 3 Sep 2022 12:40:48 +0200 Subject: [PATCH 133/666] PSK needed for wifi --- examples/espidf-arduino-wifiscan/sdkconfig.defaults | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/espidf-arduino-wifiscan/sdkconfig.defaults b/examples/espidf-arduino-wifiscan/sdkconfig.defaults index 8162986c6..f67b30bf1 100644 --- a/examples/espidf-arduino-wifiscan/sdkconfig.defaults +++ b/examples/espidf-arduino-wifiscan/sdkconfig.defaults @@ -1,6 +1,8 @@ CONFIG_AUTOSTART_ARDUINO=y # CONFIG_WS2812_LED_ENABLE is not set CONFIG_FREERTOS_HZ=1000 +CONFIG_MBEDTLS_PSK_MODES=y +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y # Example config CONFIG_EXAMPLE_WIFI_SSID="MYSSID" CONFIG_EXAMPLE_WIFI_PASSWORD="MYPASS" From 6bb182ba2bf85cb184c2a046319f396ccb4b51cc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 3 Sep 2022 20:57:02 +0200 Subject: [PATCH 134/666] Update Arduino / IDF --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 2c267b15d..9818ee763 100644 --- a/platform.json +++ b/platform.json @@ -37,13 +37,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/978/framework-arduinoespressif32-443_dev-162377cdfa.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/984/framework-arduinoespressif32-IDF_Arduino-986a6cda55.tar.gz" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v4.4.3.1/esp-idf-v4.4.3.1.zip" + "version": "https://github.com/Jason2866/esp-idf/releases/download/v4.4.3.2/esp-idf-v4.4.3.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 2cc34f05c408873d4cfd81cac19d9cf7c86aea5c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 3 Sep 2022 21:57:15 +0200 Subject: [PATCH 135/666] Update platform.json --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 9818ee763..4018a5b79 100644 --- a/platform.json +++ b/platform.json @@ -37,13 +37,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/984/framework-arduinoespressif32-IDF_Arduino-986a6cda55.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/985/framework-arduinoespressif32-IDF_Arduino-e2f319fc83.tar.gz" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v4.4.3.2/esp-idf-v4.4.3.2.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.2/esp-idf-v4.4.3.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 9b61ced7f1759ab8855c93263ea93f9d64126fb3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 4 Sep 2022 12:57:15 +0200 Subject: [PATCH 136/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 4018a5b79..ef308ba68 100644 --- a/platform.json +++ b/platform.json @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/985/framework-arduinoespressif32-IDF_Arduino-e2f319fc83.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/987/framework-arduinoespressif32-IDF_Arduino-83797312d3.tar.gz" }, "framework-espidf": { "type": "framework", From 30e8ff17f460b1ddcd6f7e1a6fdcff0e6ca75eba Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 4 Sep 2022 13:21:34 +0200 Subject: [PATCH 137/666] Tasmota/205 (#28) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Tasmota github as source * --dont-append-digest * 2.0.5dev * platformio": ">=6.1.0 * Update espidf.py * Add default nameOnDisk value for external CMake projects * Tasmota IDF 4.4.3 * Merge firmware before flashing via OpenOCD * update boards * OpenOCD has now apple ARM support * Allow overriding reset operation via project file * flash options from env for uploadfs * no .DS_Store * Esptool.py v4.2.1 * Update bootloader image headers before debugging or uploading via deb… …ug tools This approach is less intrusive than merging the entire application into one binary implemented in #006d64e8b268e479703a0aac7eed8bef1ebea587 In this implementation we safely copy the required bootloader binary to the build directory, adjust the headers via esptoolpy and the "merge_bin" command according to --flash-size and --flash-mode arguments. * replace deprecated flash modes * now "memory_type": "qio_opi" * opi flash needs flash mode `dout` flash mode `dio `works for `qout` as mode too * Tasmota/205 * Update IDF to 4.4.3.1 * Use S2 / S3 / C3 as board * cmake v3.21 * core pre 2.0.5 * Move the process of patching bootloader to the Arduino build script * Remove obsolete workaround for propagating debug configurations * Update sdkconfig.defaults * PSK needed for wifi --- boards/esp32-s3-usb.json | 2 +- boards/esp32s3box.json | 2 +- builder/main.py | 5 +- examples/arduino-blink/.travis.yml | 67 ------------------- .../arduino-briki-internal-libs/.travis.yml | 67 ------------------- examples/arduino-wifiscan/.travis.yml | 67 ------------------- examples/espidf-arduino-blink/.travis.yml | 67 ------------------- examples/espidf-arduino-blink/platformio.ini | 17 +++-- .../espidf-arduino-blink/sdkconfig.defaults | 18 +---- examples/espidf-arduino-wifiscan/.travis.yml | 67 ------------------- .../sdkconfig.defaults | 18 +---- examples/espidf-aws-iot/.travis.yml | 67 ------------------- examples/espidf-ble-eddystone/.travis.yml | 67 ------------------- examples/espidf-blink/.travis.yml | 67 ------------------- examples/espidf-coap-server/.travis.yml | 67 ------------------- examples/espidf-exceptions/.travis.yml | 67 ------------------- examples/espidf-hello-world/.travis.yml | 67 ------------------- examples/espidf-http-request/.travis.yml | 67 ------------------- examples/espidf-peripherals-uart/.travis.yml | 67 ------------------- examples/espidf-peripherals-usb/.travis.yml | 67 ------------------- examples/espidf-storage-sdcard/.travis.yml | 67 ------------------- examples/espidf-ulp-pulse/.travis.yml | 67 ------------------- platform.json | 8 +-- 23 files changed, 25 insertions(+), 1117 deletions(-) delete mode 100644 examples/arduino-blink/.travis.yml delete mode 100644 examples/arduino-briki-internal-libs/.travis.yml delete mode 100644 examples/arduino-wifiscan/.travis.yml delete mode 100644 examples/espidf-arduino-blink/.travis.yml delete mode 100644 examples/espidf-arduino-wifiscan/.travis.yml delete mode 100644 examples/espidf-aws-iot/.travis.yml delete mode 100644 examples/espidf-ble-eddystone/.travis.yml delete mode 100644 examples/espidf-blink/.travis.yml delete mode 100644 examples/espidf-coap-server/.travis.yml delete mode 100644 examples/espidf-exceptions/.travis.yml delete mode 100644 examples/espidf-hello-world/.travis.yml delete mode 100644 examples/espidf-http-request/.travis.yml delete mode 100644 examples/espidf-peripherals-uart/.travis.yml delete mode 100644 examples/espidf-peripherals-usb/.travis.yml delete mode 100644 examples/espidf-storage-sdcard/.travis.yml delete mode 100644 examples/espidf-ulp-pulse/.travis.yml diff --git a/boards/esp32-s3-usb.json b/boards/esp32-s3-usb.json index f741cafe6..68153b8f6 100644 --- a/boards/esp32-s3-usb.json +++ b/boards/esp32-s3-usb.json @@ -7,7 +7,7 @@ "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0", "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "mcu": "esp32s3", "variant": "esp32s3" }, diff --git a/boards/esp32s3box.json b/boards/esp32s3box.json index 2d7f99db4..6e31df298 100644 --- a/boards/esp32s3box.json +++ b/boards/esp32s3box.json @@ -2,7 +2,7 @@ "build": { "arduino":{ "ldscript": "esp32s3_out.ld", - "memory_type": "qspi_opi" + "memory_type": "qio_opi" }, "core": "esp32", "extra_flags": [ diff --git a/builder/main.py b/builder/main.py index 582fecf73..f642c94e4 100644 --- a/builder/main.py +++ b/builder/main.py @@ -49,10 +49,11 @@ def _get_board_f_flash(env): def _get_board_flash_mode(env): + memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi") mode = env.subst("$BOARD_FLASH_MODE") - if mode == "qio": + if mode == "qio" or mode == "qout": return "dio" - elif mode == "qout": + if memory_type == "opi_opi" or memory_type == "opi_qspi": return "dout" return mode diff --git a/examples/arduino-blink/.travis.yml b/examples/arduino-blink/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/arduino-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/arduino-briki-internal-libs/.travis.yml b/examples/arduino-briki-internal-libs/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/arduino-briki-internal-libs/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/arduino-wifiscan/.travis.yml b/examples/arduino-wifiscan/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/arduino-wifiscan/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-arduino-blink/.travis.yml b/examples/espidf-arduino-blink/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-arduino-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 0f991013b..823bb97a9 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -10,15 +10,20 @@ [env] platform = espressif32 framework = arduino, espidf -build_flags = - -D CONFIG_BLINK_GPIO=2 monitor_speed = 115200 [env:esp32dev] board = esp32dev +build_flags = -DCONFIG_BLINK_GPIO=2 -[env:espea32] -board = espea32 +[env:esp32-s2] +board = esp32-s2-saola-1 +build_flags = -DCONFIG_BLINK_GPIO=18 -[env:esp320] -board = esp320 +[env:esp32-s3] +board = esp32-s3-devkitc-1 +build_flags = -DCONFIG_BLINK_GPIO=48 + +[env:esp32-c3] +board = esp32-c3-devkitm-1 +build_flags = -DCONFIG_BLINK_GPIO=8 diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index f56753404..2c9d60715 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -1,17 +1,3 @@ -# Override some defaults to enable Arduino framework -CONFIG_ENABLE_ARDUINO_DEPENDS=y CONFIG_AUTOSTART_ARDUINO=y -CONFIG_ARDUINO_RUN_CORE1=y -CONFIG_ARDUINO_RUNNING_CORE=1 -CONFIG_ARDUINO_EVENT_RUN_CORE1=y -CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 -CONFIG_ARDUINO_UDP_RUN_CORE1=y -CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 -CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y -CONFIG_ARDUHAL_PARTITION_SCHEME="default" -CONFIG_AUTOCONNECT_WIFI=y -CONFIG_ARDUINO_SELECTIVE_WiFi=y -CONFIG_MBEDTLS_PSK_MODES=y -CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +# CONFIG_WS2812_LED_ENABLE is not set +CONFIG_FREERTOS_HZ=1000 diff --git a/examples/espidf-arduino-wifiscan/.travis.yml b/examples/espidf-arduino-wifiscan/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-arduino-wifiscan/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-arduino-wifiscan/sdkconfig.defaults b/examples/espidf-arduino-wifiscan/sdkconfig.defaults index cf124f4c4..f67b30bf1 100644 --- a/examples/espidf-arduino-wifiscan/sdkconfig.defaults +++ b/examples/espidf-arduino-wifiscan/sdkconfig.defaults @@ -1,20 +1,8 @@ -# Override some defaults to enable Arduino framework -CONFIG_ENABLE_ARDUINO_DEPENDS=y CONFIG_AUTOSTART_ARDUINO=y -CONFIG_ARDUINO_RUN_CORE1=y -CONFIG_ARDUINO_RUNNING_CORE=1 -CONFIG_ARDUINO_EVENT_RUN_CORE1=y -CONFIG_ARDUINO_EVENT_RUNNING_CORE=1 -CONFIG_ARDUINO_UDP_RUN_CORE1=y -CONFIG_ARDUINO_UDP_RUNNING_CORE=1 -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y -CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1 -CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y -CONFIG_ARDUHAL_PARTITION_SCHEME="default" -CONFIG_AUTOCONNECT_WIFI=y -CONFIG_ARDUINO_SELECTIVE_WiFi=y +# CONFIG_WS2812_LED_ENABLE is not set +CONFIG_FREERTOS_HZ=1000 CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y -# Example configs +# Example config CONFIG_EXAMPLE_WIFI_SSID="MYSSID" CONFIG_EXAMPLE_WIFI_PASSWORD="MYPASS" diff --git a/examples/espidf-aws-iot/.travis.yml b/examples/espidf-aws-iot/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-aws-iot/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-ble-eddystone/.travis.yml b/examples/espidf-ble-eddystone/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-ble-eddystone/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-blink/.travis.yml b/examples/espidf-blink/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-coap-server/.travis.yml b/examples/espidf-coap-server/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-coap-server/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-exceptions/.travis.yml b/examples/espidf-exceptions/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-exceptions/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-hello-world/.travis.yml b/examples/espidf-hello-world/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-hello-world/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-http-request/.travis.yml b/examples/espidf-http-request/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-http-request/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-peripherals-uart/.travis.yml b/examples/espidf-peripherals-uart/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-peripherals-uart/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-peripherals-usb/.travis.yml b/examples/espidf-peripherals-usb/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-peripherals-usb/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-storage-sdcard/.travis.yml b/examples/espidf-storage-sdcard/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-storage-sdcard/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-ulp-pulse/.travis.yml b/examples/espidf-ulp-pulse/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-ulp-pulse/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/platform.json b/platform.json index f0c23f0ec..ef308ba68 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.4+1", + "version": "2.0.5", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -37,13 +37,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.4.1/framework-arduinoespressif32.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/987/framework-arduinoespressif32-IDF_Arduino-83797312d3.tar.gz" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.2/esp-idf-v4.4.3.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -146,7 +146,7 @@ "tool-cmake": { "optional": true, "owner": "platformio", - "version": "~3.16.0" + "version": "~3.21.0" }, "tool-ninja": { "optional": true, From f5b5cf28f6c64be6659376345c51d14ab283e858 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 4 Sep 2022 13:26:12 +0200 Subject: [PATCH 138/666] Update main.py --- builder/main.py | 48 ------------------------------------------------ 1 file changed, 48 deletions(-) diff --git a/builder/main.py b/builder/main.py index f642c94e4..347bf506c 100644 --- a/builder/main.py +++ b/builder/main.py @@ -324,47 +324,6 @@ def __fetch_fs_size(target, source, env): "Calculate program size", ) -# Arduino core v2.0.4 contains updated bootloader images that have innacurate default -# headers. This results in bootloops if firmware is flashed via OpenOCD (e.g. debugging -# or uploading via debug tools). For this reason, before uploading or debugging we need -# to adjust the bootloader binary according to --flash-size and --flash-mode arguments. -# Note: This behavior doesn't occur if uploading is done via esptoolpy, as esptoolpy -# overrides the binary image headers before flashing. -bootloader_patch_required = bool( - env.get("PIOFRAMEWORK", []) == ["arduino"] - and ( - "debug" in env.GetBuildType() - or env.subst("$UPLOAD_PROTOCOL") in board.get("debug.tools", {}) - ) -) - -if bootloader_patch_required: - result = [] - for offset, image in env.get("FLASH_EXTRA_IMAGES", []): - # 0x1000 for ESP32/S2, 0x0 for others - default_bootloader_offsets = ("0x0", "0x0000", "0x1000") - if offset in default_bootloader_offsets: - original_bootloader_path = env.subst(image) - image = join(env.subst("$BUILD_DIR"), "patched_bootloader.bin") - env.AddPreAction( - target_elf, - env.VerboseAction(" ".join([ - '"$PYTHONEXE"', - join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), - "--chip", mcu, "merge_bin", - "-o", '"%s"' % image, - "--flash_mode", _get_board_flash_mode(env), - "--flash_freq", _get_board_f_flash(env), - "--flash_size", board.get("upload.flash_size", "4MB"), - "--target-offset", offset, - offset, '"%s"' % original_bootloader_path - ]), "Updating bootloader headers") - ) - - result.append((offset, image)) - - env.Replace(FLASH_EXTRA_IMAGES=result) - # # Target: Upload firmware or FS image # @@ -550,13 +509,6 @@ def __fetch_fs_size(target, source, env): print("Warning! '-Wl,-T' option for specifying linker scripts is deprecated. " "Please use 'board_build.ldscript' option in your 'platformio.ini' file.") -# -# A temporary workaround to propagate additional data to the debug configuration routine -# - -Import("projenv") -projenv["INTEGRATION_EXTRA_DATA"] = env.get("INTEGRATION_EXTRA_DATA") - # # Default targets # From 23b154cd86fd8771287dd61dd8ec3bedf9980481 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 4 Sep 2022 13:28:04 +0200 Subject: [PATCH 139/666] Update platform.py --- platform.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/platform.py b/platform.py index becb183f0..3606927de 100644 --- a/platform.py +++ b/platform.py @@ -275,23 +275,16 @@ def configure_debug_session(self, debug_config): if any(ignore_conds): return - merged_firmware = build_extra_data.get("merged_firmware", False) - load_cmds = [] - if not merged_firmware: - load_cmds.extend([ - 'monitor program_esp "{{{path}}}" {offset} verify'.format( - path=to_unix_path(item["path"]), offset=item["offset"] - ) - for item in flash_images - ]) - + load_cmds = [ + 'monitor program_esp "{{{path}}}" {offset} verify'.format( + path=to_unix_path(item["path"]), offset=item["offset"] + ) + for item in flash_images + ] load_cmds.append( 'monitor program_esp "{%s.bin}" %s verify' % ( - to_unix_path( - debug_config.build_data["prog_path"][:-4] - + ("_merged" if merged_firmware else "") - ), + to_unix_path(debug_config.build_data["prog_path"][:-4]), build_extra_data.get("application_offset", "0x10000"), ) ) From 60db57ad1e8c100c5f00aba178c25563d52bf5d7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 4 Sep 2022 21:15:58 +0200 Subject: [PATCH 140/666] flash mode `dout` for opi --- boards/esp32s3camlcd.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index f0fe6a64b..34810b5a5 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -15,7 +15,7 @@ ], "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "qio", + "flash_mode": "dout", "hwids": [ [ "0X303A", From a704a9a65967835d04d32cf4a8e45e5cbc36dc65 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 4 Sep 2022 21:16:48 +0200 Subject: [PATCH 141/666] rm litter --- boards/esp32s3camlcd.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index 34810b5a5..d35f26798 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -7,8 +7,6 @@ "boot": "opi", "core": "esp32", "extra_flags": [ - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", "-DBOARD_HAS_PSRAM", "-DARDUINO_ESP32S3_CAM_LCD", "-DARDUINO_USB_MODE=1" From fb1821f4bcf5338f9f46e9cee2085d040f3bc134 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 4 Sep 2022 21:20:52 +0200 Subject: [PATCH 142/666] 16MB flash --- boards/esp32s3camlcd.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index d35f26798..623ee77aa 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -36,7 +36,7 @@ ], "name": "ESP32S3 CAM LCD", "upload": { - "flash_size": "4MB", + "flash_size": "16MB", "maximum_ram_size": 327680, "maximum_size": 16777216, "require_upload_port": true, From 3841a39c604e796b268cb6b2298a6e0d3544e934 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:55:39 +0200 Subject: [PATCH 143/666] framework now as zip --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index ef308ba68..99e55b556 100644 --- a/platform.json +++ b/platform.json @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/987/framework-arduinoespressif32-IDF_Arduino-83797312d3.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/990/framework-arduinoespressif32-IDF_Arduino-bce2fe1fd3.zip" }, "framework-espidf": { "type": "framework", From 39bdf28c707278689b10be30d0ffb206983b3ba6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 8 Sep 2022 20:39:46 +0200 Subject: [PATCH 144/666] Apple ARM toolchain 8.4.0-2021r2-patch4 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 99e55b556..c43cf2a69 100644 --- a/platform.json +++ b/platform.json @@ -73,25 +73,25 @@ "type": "toolchain", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32.tar.gz" + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/xtensa-esp32-elf.tar.gz" }, "toolchain-xtensa-esp32s2-arm": { "type": "toolchain", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32s2.tar.gz" + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/xtensa-esp32s2-elf.tar.gz" }, "toolchain-xtensa-esp32s3-arm": { "type": "toolchain", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32s3.tar.gz" + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/xtensa-esp32s3-elf.tar.gz" }, "toolchain-riscv32-esp-arm": { "type": "toolchain", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-riscv32-esp.tar.gz" + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/riscv32-esp-elf.tar.gz" }, "toolchain-esp32ulp": { "type": "toolchain", From c33574d5884c246e67155da56a2d5c111aa5eeb0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Sep 2022 15:34:09 +0200 Subject: [PATCH 145/666] more "pythonic" --- builder/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builder/main.py b/builder/main.py index 347bf506c..3e4ffb595 100644 --- a/builder/main.py +++ b/builder/main.py @@ -51,10 +51,10 @@ def _get_board_f_flash(env): def _get_board_flash_mode(env): memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi") mode = env.subst("$BOARD_FLASH_MODE") - if mode == "qio" or mode == "qout": - return "dio" - if memory_type == "opi_opi" or memory_type == "opi_qspi": + if memory_type in ("opi_opi", "opi_qspi"): return "dout" + if mode in ("qio", "qout"): + return "dio" return mode From 87ecdd82ff444547ed013b42c4aaa966bf3ff59d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 10 Sep 2022 22:50:32 +0200 Subject: [PATCH 146/666] 205merge (#29) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Tasmota github as source * --dont-append-digest * esptool v4.1 * 2.0.5dev * platformio": ">=6.1.0 * Update espidf.py * Add default nameOnDisk value for external CMake projects * Build 918 newest wifi libs from idf44 * Tasmota IDF 4.4.3 * Tasmota release Core 2.0.4.1 * Merge firmware before flashing via OpenOCD * Merge firmware before flashing via OpenOCD * Update arduino.py * Update espidf.py * update boards 1/2 * Update Boards 2/2 * v2.0.4.1 * Mode qio * Board supports qio * OpenOCD has now apple ARM support * rm custom OpenOCD * fix install OpenOCD * Allow overriding reset operation via project file * flash options from env for uploadfs * revert * flash options from env for uploadfs * no .DS_Store * fix boot flash mode * refactor * Esptool.py v4.2.1 * Update bootloader image headers before debugging or uploading via deb… …ug tools This approach is less intrusive than merging the entire application into one binary implemented in #006d64e8b268e479703a0aac7eed8bef1ebea587 In this implementation we safely copy the required bootloader binary to the build directory, adjust the headers via esptoolpy and the "merge_bin" command according to --flash-size and --flash-mode arguments. * better specs * replace deprecated flash modes * Board support faster flash mode * now "memory_type": "qio_opi" * qio * opi flash needs flash mode `dout` flash mode `dio `works for `qout` as mode too * 8 MB * Tasmota/205 * Update IDF to 4.4.3.1 * Use S2 / S3 / C3 as board * cmake v3.21 * core pre 2.0.5 * Move the process of patching bootloader to the Arduino build script * Remove obsolete workaround for propagating debug configurations * Update platform.py * Update platform.json * Update sdkconfig.defaults * PSK needed for wifi * Update Arduino / IDF * Update platform.json * Update platform.json * Update main.py * Update platform.py * flash mode `dout` for opi * rm litter * 16MB flash * framework now as zip * Apple ARM toolchain 8.4.0-2021r2-patch4 * more "pythonic" --- boards/esp32s3camlcd.json | 6 ++--- builder/main.py | 54 +++------------------------------------ platform.json | 10 ++++---- platform.py | 21 +++++---------- 4 files changed, 17 insertions(+), 74 deletions(-) diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index f0fe6a64b..623ee77aa 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -7,15 +7,13 @@ "boot": "opi", "core": "esp32", "extra_flags": [ - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", "-DBOARD_HAS_PSRAM", "-DARDUINO_ESP32S3_CAM_LCD", "-DARDUINO_USB_MODE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "qio", + "flash_mode": "dout", "hwids": [ [ "0X303A", @@ -38,7 +36,7 @@ ], "name": "ESP32S3 CAM LCD", "upload": { - "flash_size": "4MB", + "flash_size": "16MB", "maximum_ram_size": 327680, "maximum_size": 16777216, "require_upload_port": true, diff --git a/builder/main.py b/builder/main.py index f642c94e4..3e4ffb595 100644 --- a/builder/main.py +++ b/builder/main.py @@ -51,10 +51,10 @@ def _get_board_f_flash(env): def _get_board_flash_mode(env): memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi") mode = env.subst("$BOARD_FLASH_MODE") - if mode == "qio" or mode == "qout": - return "dio" - if memory_type == "opi_opi" or memory_type == "opi_qspi": + if memory_type in ("opi_opi", "opi_qspi"): return "dout" + if mode in ("qio", "qout"): + return "dio" return mode @@ -324,47 +324,6 @@ def __fetch_fs_size(target, source, env): "Calculate program size", ) -# Arduino core v2.0.4 contains updated bootloader images that have innacurate default -# headers. This results in bootloops if firmware is flashed via OpenOCD (e.g. debugging -# or uploading via debug tools). For this reason, before uploading or debugging we need -# to adjust the bootloader binary according to --flash-size and --flash-mode arguments. -# Note: This behavior doesn't occur if uploading is done via esptoolpy, as esptoolpy -# overrides the binary image headers before flashing. -bootloader_patch_required = bool( - env.get("PIOFRAMEWORK", []) == ["arduino"] - and ( - "debug" in env.GetBuildType() - or env.subst("$UPLOAD_PROTOCOL") in board.get("debug.tools", {}) - ) -) - -if bootloader_patch_required: - result = [] - for offset, image in env.get("FLASH_EXTRA_IMAGES", []): - # 0x1000 for ESP32/S2, 0x0 for others - default_bootloader_offsets = ("0x0", "0x0000", "0x1000") - if offset in default_bootloader_offsets: - original_bootloader_path = env.subst(image) - image = join(env.subst("$BUILD_DIR"), "patched_bootloader.bin") - env.AddPreAction( - target_elf, - env.VerboseAction(" ".join([ - '"$PYTHONEXE"', - join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), - "--chip", mcu, "merge_bin", - "-o", '"%s"' % image, - "--flash_mode", _get_board_flash_mode(env), - "--flash_freq", _get_board_f_flash(env), - "--flash_size", board.get("upload.flash_size", "4MB"), - "--target-offset", offset, - offset, '"%s"' % original_bootloader_path - ]), "Updating bootloader headers") - ) - - result.append((offset, image)) - - env.Replace(FLASH_EXTRA_IMAGES=result) - # # Target: Upload firmware or FS image # @@ -550,13 +509,6 @@ def __fetch_fs_size(target, source, env): print("Warning! '-Wl,-T' option for specifying linker scripts is deprecated. " "Please use 'board_build.ldscript' option in your 'platformio.ini' file.") -# -# A temporary workaround to propagate additional data to the debug configuration routine -# - -Import("projenv") -projenv["INTEGRATION_EXTRA_DATA"] = env.get("INTEGRATION_EXTRA_DATA") - # # Default targets # diff --git a/platform.json b/platform.json index ef308ba68..c43cf2a69 100644 --- a/platform.json +++ b/platform.json @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/987/framework-arduinoespressif32-IDF_Arduino-83797312d3.tar.gz" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/990/framework-arduinoespressif32-IDF_Arduino-bce2fe1fd3.zip" }, "framework-espidf": { "type": "framework", @@ -73,25 +73,25 @@ "type": "toolchain", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32.tar.gz" + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/xtensa-esp32-elf.tar.gz" }, "toolchain-xtensa-esp32s2-arm": { "type": "toolchain", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32s2.tar.gz" + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/xtensa-esp32s2-elf.tar.gz" }, "toolchain-xtensa-esp32s3-arm": { "type": "toolchain", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-xtensa-esp32s3.tar.gz" + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/xtensa-esp32s3-elf.tar.gz" }, "toolchain-riscv32-esp-arm": { "type": "toolchain", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/8.4.0/toolchain-riscv32-esp.tar.gz" + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/riscv32-esp-elf.tar.gz" }, "toolchain-esp32ulp": { "type": "toolchain", diff --git a/platform.py b/platform.py index becb183f0..3606927de 100644 --- a/platform.py +++ b/platform.py @@ -275,23 +275,16 @@ def configure_debug_session(self, debug_config): if any(ignore_conds): return - merged_firmware = build_extra_data.get("merged_firmware", False) - load_cmds = [] - if not merged_firmware: - load_cmds.extend([ - 'monitor program_esp "{{{path}}}" {offset} verify'.format( - path=to_unix_path(item["path"]), offset=item["offset"] - ) - for item in flash_images - ]) - + load_cmds = [ + 'monitor program_esp "{{{path}}}" {offset} verify'.format( + path=to_unix_path(item["path"]), offset=item["offset"] + ) + for item in flash_images + ] load_cmds.append( 'monitor program_esp "{%s.bin}" %s verify' % ( - to_unix_path( - debug_config.build_data["prog_path"][:-4] - + ("_merged" if merged_firmware else "") - ), + to_unix_path(debug_config.build_data["prog_path"][:-4]), build_extra_data.get("application_offset", "0x10000"), ) ) From 46ce39e58341306a92d97bd502dfc5a9126de602 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 13 Sep 2022 14:20:57 +0200 Subject: [PATCH 147/666] idf-component-manager --- builder/frameworks/espidf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 187a4ed5c..fd6a53a21 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1050,6 +1050,7 @@ def _get_installed_pip_packages(): "future": ">=0.15.2", "pyparsing": ">=2.0.3,<2.4.0", "kconfiglib": "==13.7.1", + "idf-component-manager": "~=1.0" } installed_packages = _get_installed_pip_packages() From e558a8d1db167713a8aa07a028e6b2de588c6fd6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 13 Sep 2022 14:43:44 +0200 Subject: [PATCH 148/666] esp-idf-v4.4.3.3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index c43cf2a69..c048589c3 100644 --- a/platform.json +++ b/platform.json @@ -43,7 +43,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.2/esp-idf-v4.4.3.2.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.3/esp-idf-v4.4.3.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 8043d55edcc339462726c732a7bc59dc4044bc84 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Sep 2022 12:22:22 +0200 Subject: [PATCH 149/666] set correct `_get_board_boot_mode` for `opi` --- builder/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builder/main.py b/builder/main.py index 3e4ffb595..173a128c9 100644 --- a/builder/main.py +++ b/builder/main.py @@ -59,6 +59,8 @@ def _get_board_flash_mode(env): def _get_board_boot_mode(env): + if memory_type in ("opi_opi", "opi_qspi"): + return "opi" return env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE") From 5b65d9a48300be5c0b6508c49c6a636bd7eecfd8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Sep 2022 12:36:39 +0200 Subject: [PATCH 150/666] fix logic for replacing with `opi` --- builder/main.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index 173a128c9..e6add4547 100644 --- a/builder/main.py +++ b/builder/main.py @@ -59,9 +59,11 @@ def _get_board_flash_mode(env): def _get_board_boot_mode(env): + memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi") + build_boot = env.subst(("build.boot", "$BOARD_FLASH_MODE")) if memory_type in ("opi_opi", "opi_qspi"): - return "opi" - return env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE") + build_boot = "opi" + return build_boot def _parse_size(value): From 14727012277c4dea3eedb3099dd99144aeabb46b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Sep 2022 12:52:09 +0200 Subject: [PATCH 151/666] fix wrong pio syntax to get `build.boot` --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index e6add4547..a0b3ef405 100644 --- a/builder/main.py +++ b/builder/main.py @@ -60,7 +60,7 @@ def _get_board_flash_mode(env): def _get_board_boot_mode(env): memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi") - build_boot = env.subst(("build.boot", "$BOARD_FLASH_MODE")) + build_boot = env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE") if memory_type in ("opi_opi", "opi_qspi"): build_boot = "opi" return build_boot From bd60781d5fd0369530844c85127ec1e433f26345 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Sep 2022 13:54:38 +0200 Subject: [PATCH 152/666] use opi bootloader for opi flash --- builder/main.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index 3e4ffb595..a0b3ef405 100644 --- a/builder/main.py +++ b/builder/main.py @@ -59,7 +59,11 @@ def _get_board_flash_mode(env): def _get_board_boot_mode(env): - return env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE") + memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi") + build_boot = env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE") + if memory_type in ("opi_opi", "opi_qspi"): + build_boot = "opi" + return build_boot def _parse_size(value): From cb755e3efcbeae0dff6240c60a65116e5f5279b2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Sep 2022 15:38:17 +0200 Subject: [PATCH 153/666] esptool.py v4.3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index c048589c3..81303380a 100644 --- a/platform.json +++ b/platform.json @@ -114,7 +114,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.2.1/esptool-4.2.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.3/esptool-4.3.zip" }, "tool-mbctool": { "optional": true, From eaf248c4e5f9e7132544611f592e4bbed5048132 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Sep 2022 17:09:16 +0200 Subject: [PATCH 154/666] rm redundant entrys --- boards/adafruit_feather_esp32s3.json | 4 +--- boards/adafruit_feather_esp32s3_nopsram.json | 4 +--- boards/adafruit_feather_esp32s3_tft.json | 4 +--- boards/adafruit_qtpy_esp32s3.json | 4 +--- boards/adafruit_qtpy_esp32s3_nopsram.json | 4 +--- boards/dfrobot_firebeetle2_esp32s3.json | 4 +--- boards/esp32-s3-devkitc-1.json | 4 +--- boards/lionbit.json | 4 +--- boards/um_feathers3.json | 4 +--- boards/um_pros3.json | 4 +--- boards/um_tinys3.json | 4 +--- 11 files changed, 11 insertions(+), 33 deletions(-) diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json index 9c14bd3f8..f9e795ceb 100644 --- a/boards/adafruit_feather_esp32s3.json +++ b/boards/adafruit_feather_esp32s3.json @@ -7,9 +7,7 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/adafruit_feather_esp32s3_nopsram.json b/boards/adafruit_feather_esp32s3_nopsram.json index 29541e559..39bc7eabb 100644 --- a/boards/adafruit_feather_esp32s3_nopsram.json +++ b/boards/adafruit_feather_esp32s3_nopsram.json @@ -6,9 +6,7 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/adafruit_feather_esp32s3_tft.json b/boards/adafruit_feather_esp32s3_tft.json index 4e38ae0d1..4eb9df9e5 100644 --- a/boards/adafruit_feather_esp32s3_tft.json +++ b/boards/adafruit_feather_esp32s3_tft.json @@ -7,9 +7,7 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/adafruit_qtpy_esp32s3.json b/boards/adafruit_qtpy_esp32s3.json index 067d8a676..6413a7ef3 100644 --- a/boards/adafruit_qtpy_esp32s3.json +++ b/boards/adafruit_qtpy_esp32s3.json @@ -6,9 +6,7 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/adafruit_qtpy_esp32s3_nopsram.json b/boards/adafruit_qtpy_esp32s3_nopsram.json index 57fb0098a..804bf37e3 100644 --- a/boards/adafruit_qtpy_esp32s3_nopsram.json +++ b/boards/adafruit_qtpy_esp32s3_nopsram.json @@ -6,9 +6,7 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/dfrobot_firebeetle2_esp32s3.json b/boards/dfrobot_firebeetle2_esp32s3.json index 0f87150d6..83d842d3f 100644 --- a/boards/dfrobot_firebeetle2_esp32s3.json +++ b/boards/dfrobot_firebeetle2_esp32s3.json @@ -6,9 +6,7 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ESP32S3_DEV", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_MODE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json index 7bc3b3725..f5a9757b9 100644 --- a/boards/esp32-s3-devkitc-1.json +++ b/boards/esp32-s3-devkitc-1.json @@ -7,9 +7,7 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ESP32S3_DEV", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_MODE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/lionbit.json b/boards/lionbit.json index c8186d0b2..92c20d138 100644 --- a/boards/lionbit.json +++ b/boards/lionbit.json @@ -5,9 +5,7 @@ }, "core": "esp32", "extra_flags": [ - "-DARDUINO_LIONBIT", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_LIONBIT" ], "f_cpu": "240000000L", "f_flash": "40000000L", diff --git a/boards/um_feathers3.json b/boards/um_feathers3.json index 435123421..a0d393510 100644 --- a/boards/um_feathers3.json +++ b/boards/um_feathers3.json @@ -8,9 +8,7 @@ "extra_flags": [ "-DARDUINO_FEATHERS3", "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/um_pros3.json b/boards/um_pros3.json index e4ba4ee4a..14cbdac16 100644 --- a/boards/um_pros3.json +++ b/boards/um_pros3.json @@ -8,9 +8,7 @@ "extra_flags": [ "-DARDUINO_PROS3", "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/um_tinys3.json b/boards/um_tinys3.json index 7a72da444..294733c7d 100644 --- a/boards/um_tinys3.json +++ b/boards/um_tinys3.json @@ -8,9 +8,7 @@ "extra_flags": [ "-DARDUINO_TINYS3", "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", From 793c22770f9a055fcbc8f4d0d39146165e11b430 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Sep 2022 20:45:03 +0200 Subject: [PATCH 155/666] Tasmota IDF 4.4.3.3 / Esptool v4.3 --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index c43cf2a69..81303380a 100644 --- a/platform.json +++ b/platform.json @@ -43,7 +43,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.2/esp-idf-v4.4.3.2.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.3/esp-idf-v4.4.3.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -114,7 +114,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.2.1/esptool-4.2.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.3/esptool-4.3.zip" }, "tool-mbctool": { "optional": true, From 18982ef59dc75512143fc5b31387c9d6a06b8e1b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 16 Sep 2022 14:06:25 +0200 Subject: [PATCH 156/666] Tasmota Arduino build 998 / IDF 4.4.3.4 --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 81303380a..72af6f9fa 100644 --- a/platform.json +++ b/platform.json @@ -37,13 +37,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/990/framework-arduinoespressif32-IDF_Arduino-bce2fe1fd3.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/998/framework-arduinoespressif32-IDF_Arduino-e466fc4ea.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.3/esp-idf-v4.4.3.3.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.4/esp-idf-v4.4.3.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 1e6608517772a74762164296a6a1b1d69d548e49 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 16 Sep 2022 15:11:54 +0200 Subject: [PATCH 157/666] Build 999 and back to IDF 4.4.3.3 since 4.4.3.4 needs patch4 toolchains (not yet in Pio registry) --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 72af6f9fa..b592209db 100644 --- a/platform.json +++ b/platform.json @@ -37,13 +37,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/998/framework-arduinoespressif32-IDF_Arduino-e466fc4ea.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/999/framework-arduinoespressif32-IDF_Arduino-e466fc4ea.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.4/esp-idf-v4.4.3.4.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.3/esp-idf-v4.4.3.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From e15851fe66e8506fbc312a8e5e460a7830d5f965 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 17 Sep 2022 14:07:38 +0200 Subject: [PATCH 158/666] Tasmota Core 2.0.5 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index b592209db..761881ebb 100644 --- a/platform.json +++ b/platform.json @@ -37,7 +37,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/999/framework-arduinoespressif32-IDF_Arduino-e466fc4ea.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5/framework-arduinoespressif32.zip" }, "framework-espidf": { "type": "framework", From 0606c33126937442c66f8a7534d3dded53072e35 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 17 Sep 2022 16:15:31 +0200 Subject: [PATCH 159/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f4a06b969..7c6e51125 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid ```ini [env:stable] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4.1/platform-espressif32-2.0.4.1.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5/platform-espressif32-2.0.5.zip board = ... ... ``` From 1bfc895eb215c29ea507228be8cf7f3f56c660ae Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 17 Sep 2022 16:17:21 +0200 Subject: [PATCH 160/666] Tasmota core 2.0.5 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f4a06b969..7c6e51125 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid ```ini [env:stable] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4.1/platform-espressif32-2.0.4.1.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5/platform-espressif32-2.0.5.zip board = ... ... ``` From ad3a531be9bc76039c5f6f5c833aea2aa0b2d5bc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 17 Sep 2022 18:54:46 +0200 Subject: [PATCH 161/666] `adapter speed` --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index a0b3ef405..1677e5133 100644 --- a/builder/main.py +++ b/builder/main.py @@ -443,7 +443,7 @@ def __fetch_fs_size(target, source, env): openocd_args.extend( [ "-c", - "adapter_khz %s" % env.GetProjectOption("debug_speed", "5000"), + "adapter speed %s" % env.GetProjectOption("debug_speed", "5000"), "-c", "program_esp {{$SOURCE}} %s verify" % ( From 7d2f4f209cbc8192472912bed144948887b75542 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 17 Sep 2022 18:55:43 +0200 Subject: [PATCH 162/666] `adapter speed` --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index 3606927de..17b2802b3 100644 --- a/platform.py +++ b/platform.py @@ -263,7 +263,7 @@ def configure_debug_session(self, debug_config): if "openocd" in (debug_config.server or {}).get("executable", ""): debug_config.server["arguments"].extend( - ["-c", "adapter_khz %s" % (debug_config.speed or "5000")] + ["-c", "adapter speed %s" % (debug_config.speed or "5000")] ) ignore_conds = [ From c869c06cf996eb550272ddd50af41fcd16e0a716 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 18 Sep 2022 17:55:17 +0200 Subject: [PATCH 163/666] Update platform.py --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index 17b2802b3..f93d18bac 100644 --- a/platform.py +++ b/platform.py @@ -263,7 +263,7 @@ def configure_debug_session(self, debug_config): if "openocd" in (debug_config.server or {}).get("executable", ""): debug_config.server["arguments"].extend( - ["-c", "adapter speed %s" % (debug_config.speed or "5000")] + ["-c", "adapter speed %s" % (debug_config.speed or "20000")] ) ignore_conds = [ From a40cbe873714f8ac3a6714566e0afd86d41f85c2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 18 Sep 2022 17:57:43 +0200 Subject: [PATCH 164/666] adapter speed 20000 --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index 1677e5133..c205bfb54 100644 --- a/builder/main.py +++ b/builder/main.py @@ -443,7 +443,7 @@ def __fetch_fs_size(target, source, env): openocd_args.extend( [ "-c", - "adapter speed %s" % env.GetProjectOption("debug_speed", "5000"), + "adapter speed %s" % env.GetProjectOption("debug_speed", "20000"), "-c", "program_esp {{$SOURCE}} %s verify" % ( From 8317b5a02604c1033aed2cd938a2854a37499084 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Sep 2022 13:16:08 +0200 Subject: [PATCH 165/666] rm adapter speed --- builder/main.py | 2 -- platform.py | 5 ----- 2 files changed, 7 deletions(-) diff --git a/builder/main.py b/builder/main.py index c205bfb54..852b99c9f 100644 --- a/builder/main.py +++ b/builder/main.py @@ -442,8 +442,6 @@ def __fetch_fs_size(target, source, env): debug_tools.get(upload_protocol).get("server").get("arguments", [])) openocd_args.extend( [ - "-c", - "adapter speed %s" % env.GetProjectOption("debug_speed", "20000"), "-c", "program_esp {{$SOURCE}} %s verify" % ( diff --git a/platform.py b/platform.py index f93d18bac..630a740f3 100644 --- a/platform.py +++ b/platform.py @@ -261,11 +261,6 @@ def configure_debug_session(self, debug_config): build_extra_data = debug_config.build_data.get("extra", {}) flash_images = build_extra_data.get("flash_images", []) - if "openocd" in (debug_config.server or {}).get("executable", ""): - debug_config.server["arguments"].extend( - ["-c", "adapter speed %s" % (debug_config.speed or "20000")] - ) - ignore_conds = [ debug_config.load_cmds != ["load"], not flash_images, From 20066108e9b0bbc412a94b0481c159d3e47eb00a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Sep 2022 21:20:16 +0200 Subject: [PATCH 166/666] toolchain patch5 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 761881ebb..45df05f29 100644 --- a/platform.json +++ b/platform.json @@ -49,25 +49,25 @@ "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3" + "version": "8.4.0+2021r2-patch5" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3" + "version": "8.4.0+2021r2-patch5" }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3" + "version": "8.4.0+2021r2-patch5" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch3" + "version": "8.4.0+2021r2-patch5" }, "toolchain-xtensa-esp32-arm": { "type": "toolchain", From 5a400f282ed5d326176d67e3cc4309a9f0e677f0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Sep 2022 21:27:27 +0200 Subject: [PATCH 167/666] rm custom arm toolchains --- platform.py | 43 +++++++++++++------------------------------ 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/platform.py b/platform.py index 630a740f3..d92452e85 100644 --- a/platform.py +++ b/platform.py @@ -20,7 +20,6 @@ import requests from platformio.public import PlatformBase, to_unix_path -from platformio.util import get_systype IS_WINDOWS = sys.platform.startswith("win") @@ -87,41 +86,25 @@ def configure_default_packages(self, variables, targets): sys.exit(1) if "espidf" in frameworks: - # Common package for IDF and mixed Arduino+IDF projects + # Common packages for IDF and mixed Arduino+IDF projects for p in self.packages: if p in ("tool-cmake", "tool-ninja", "toolchain-%sulp" % mcu): self.packages[p]["optional"] = False elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: self.packages[p]["optional"] = False - if not "arm64" in get_systype(): - for available_mcu in ("esp32", "esp32s2", "esp32s3"): - if available_mcu == mcu: - self.packages["toolchain-xtensa-%s" % mcu]["optional"] = False - else: - self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) - - if mcu in ("esp32s2", "esp32s3", "esp32c3"): - self.packages.pop("toolchain-esp32ulp", None) - if mcu != "esp32s2": - self.packages.pop("toolchain-esp32s2ulp", None) - # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP - self.packages["toolchain-riscv32-esp"]["optional"] = False - - if "darwin" in get_systype() and "arm64" in get_systype(): - for available_mcu in ("esp32", "esp32s2", "esp32s3"): - if available_mcu == mcu: - self.packages["toolchain-xtensa-%s-arm" % mcu]["optional"] = False - else: - self.packages.pop("toolchain-xtensa-%s-arm" % available_mcu, None) - - if mcu in ("esp32s2", "esp32s3", "esp32c3"): - self.packages.pop("toolchain-esp32ulp", None) - if mcu != "esp32s2": - self.packages.pop("toolchain-esp32s2ulp", None) - # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP - self.packages["toolchain-riscv32-esp-arm"]["optional"] = False - + for available_mcu in ("esp32", "esp32s2", "esp32s3"): + if available_mcu == mcu: + self.packages["toolchain-xtensa-%s" % mcu]["optional"] = False + else: + self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) + + if mcu in ("esp32s2", "esp32s3", "esp32c3"): + self.packages.pop("toolchain-esp32ulp", None) + if mcu != "esp32s2": + self.packages.pop("toolchain-esp32s2ulp", None) + # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP + self.packages["toolchain-riscv32-esp"]["optional"] = False if build_core == "mbcwb": # Remove the main toolchains from PATH From b3667d960f656264e17d8a22ef74b23481d8eb61 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Sep 2022 21:30:43 +0200 Subject: [PATCH 168/666] rm custom arm toolchains --- builder/frameworks/espidf.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index fd6a53a21..643253470 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -50,14 +50,10 @@ idf_variant = mcu.lower() FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") -if "darwin" in get_systype() and "arm64" in get_systype(): - TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" % ("riscv32-esp-arm" if mcu == "esp32c3" else ("xtensa-%s-arm" % mcu)) - ) -if not "arm64" in get_systype(): - TOOLCHAIN_DIR = platform.get_package_dir( +TOOLCHAIN_DIR = platform.get_package_dir( "toolchain-%s" % ("riscv32-esp" if mcu == "esp32c3" else ("xtensa-%s" % mcu)) - ) +) + assert os.path.isdir(FRAMEWORK_DIR) assert os.path.isdir(TOOLCHAIN_DIR) From 5cad2543a3ff11cf3d0902e45a7d3e58cfca67d9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Sep 2022 21:35:42 +0200 Subject: [PATCH 169/666] rm custom arm toolchains --- platform.json | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/platform.json b/platform.json index 45df05f29..fd37c77a1 100644 --- a/platform.json +++ b/platform.json @@ -69,30 +69,6 @@ "owner": "espressif", "version": "8.4.0+2021r2-patch5" }, - "toolchain-xtensa-esp32-arm": { - "type": "toolchain", - "optional": true, - "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/xtensa-esp32-elf.tar.gz" - }, - "toolchain-xtensa-esp32s2-arm": { - "type": "toolchain", - "optional": true, - "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/xtensa-esp32s2-elf.tar.gz" - }, - "toolchain-xtensa-esp32s3-arm": { - "type": "toolchain", - "optional": true, - "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/xtensa-esp32s3-elf.tar.gz" - }, - "toolchain-riscv32-esp-arm": { - "type": "toolchain", - "optional": true, - "owner": "tasmota", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/riscv32-esp-elf.tar.gz" - }, "toolchain-esp32ulp": { "type": "toolchain", "optional": true, From ffd77f766201af61750bbf55769526ce183d35c5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 21 Sep 2022 15:31:33 +0200 Subject: [PATCH 170/666] IDF 4.4.3.5 which uses patch5 toolchains --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index fd37c77a1..f30de5fb4 100644 --- a/platform.json +++ b/platform.json @@ -43,7 +43,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.3/esp-idf-v4.4.3.3.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.5/esp-idf-v4.4.3.5.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From bd5dcc2e71f510a7698f5f52ecea926aacfb2986 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Sep 2022 11:31:01 +0200 Subject: [PATCH 171/666] Tasmota/one platform (#32) * ULP CI test Linux * new ulp examples * use `toolchain-riscv32-esp` for riscv ulp projects * rm example `SPIFFS` * rm `mbcwb` support * One Tasmota Platformio Platform --- .github/workflows/examples.yml | 6 +- builder/frameworks/arduino.py | 20 ++- builder/frameworks/espidf.py | 4 +- builder/frameworks/ulp.py | 15 +- builder/main.py | 27 ---- .../arduino-briki-internal-libs/.gitignore | 1 - .../arduino-briki-internal-libs/README.md | 27 ---- .../include/README | 39 ------ .../arduino-briki-internal-libs/lib/README | 46 ------- .../platformio.ini | 18 --- .../src/WiFiTelnetToSerial.ino | 129 ------------------ .../arduino-briki-internal-libs/test/README | 11 -- examples/espidf-storage-spiffs/.gitignore | 1 - examples/espidf-storage-spiffs/README.md | 24 ---- examples/espidf-storage-spiffs/data/hello.txt | 1 - examples/espidf-storage-spiffs/include/README | 39 ------ examples/espidf-storage-spiffs/lib/README | 46 ------- .../partitions_example.csv | 6 - .../espidf-storage-spiffs/sdkconfig.defaults | 3 - .../espidf-storage-spiffs/src/CMakeLists.txt | 2 - .../src/spiffs_example_main.c | 73 ---------- examples/espidf-storage-spiffs/test/README | 11 -- examples/espidf-ulp-adc/.gitignore | 1 - examples/espidf-ulp-adc/README.md | 27 ---- examples/espidf-ulp-adc/include/README | 39 ------ examples/espidf-ulp-adc/lib/README | 46 ------- .../main/ulp_adc_example_main.c | 100 -------------- examples/espidf-ulp-adc/test/README | 11 -- examples/espidf-ulp-adc/ulp/adc.S | 115 ---------------- examples/espidf-ulp-pulse/.gitignore | 1 - examples/espidf-ulp-pulse/CMakeLists.txt | 3 - examples/espidf-ulp-pulse/README.md | 27 ---- examples/espidf-ulp-pulse/include/README | 39 ------ examples/espidf-ulp-pulse/lib/README | 46 ------- examples/espidf-ulp-pulse/platformio.ini | 13 -- examples/espidf-ulp-pulse/test/README | 11 -- .../CMakeLists.txt | 2 +- examples/espidf-ulp-riscv/README.md | 31 +++++ examples/espidf-ulp-riscv/example_test.py | 48 +++++++ .../main/CMakeLists.txt | 22 +-- .../main/ulp_riscv_example_main.c | 75 ++++++++++ .../platformio.ini | 9 +- .../sdkconfig.defaults | 4 - .../sdkconfig.defaults.esp32s2 | 4 + .../sdkconfig.defaults.esp32s3 | 4 + examples/espidf-ulp-riscv/ulp/main.c | 41 ++++++ .../CMakeLists.txt | 2 +- examples/espidf-ulp/Makefile | 8 ++ examples/espidf-ulp/README.md | 57 ++++++++ examples/espidf-ulp/example_test.py | 45 ++++++ examples/espidf-ulp/image/ulp_power_graph.png | Bin 0 -> 39281 bytes .../src => espidf-ulp/main}/CMakeLists.txt | 6 +- examples/espidf-ulp/main/component.mk | 24 ++++ .../main}/ulp_example_main.c | 14 +- .../platformio.ini | 15 +- .../sdkconfig.defaults | 3 - examples/espidf-ulp/sdkconfig.defaults.esp32 | 3 + .../espidf-ulp/sdkconfig.defaults.esp32s2 | 3 + .../espidf-ulp/sdkconfig.defaults.esp32s3 | 3 + .../ulp/pulse_cnt.S | 17 ++- .../ulp/wake_up.S | 2 +- platform.json | 39 +++--- platform.py | 31 +---- 63 files changed, 466 insertions(+), 1074 deletions(-) delete mode 100644 examples/arduino-briki-internal-libs/.gitignore delete mode 100644 examples/arduino-briki-internal-libs/README.md delete mode 100644 examples/arduino-briki-internal-libs/include/README delete mode 100644 examples/arduino-briki-internal-libs/lib/README delete mode 100644 examples/arduino-briki-internal-libs/platformio.ini delete mode 100644 examples/arduino-briki-internal-libs/src/WiFiTelnetToSerial.ino delete mode 100644 examples/arduino-briki-internal-libs/test/README delete mode 100644 examples/espidf-storage-spiffs/.gitignore delete mode 100644 examples/espidf-storage-spiffs/README.md delete mode 100644 examples/espidf-storage-spiffs/data/hello.txt delete mode 100644 examples/espidf-storage-spiffs/include/README delete mode 100644 examples/espidf-storage-spiffs/lib/README delete mode 100644 examples/espidf-storage-spiffs/partitions_example.csv delete mode 100644 examples/espidf-storage-spiffs/sdkconfig.defaults delete mode 100644 examples/espidf-storage-spiffs/src/CMakeLists.txt delete mode 100644 examples/espidf-storage-spiffs/src/spiffs_example_main.c delete mode 100644 examples/espidf-storage-spiffs/test/README delete mode 100644 examples/espidf-ulp-adc/.gitignore delete mode 100644 examples/espidf-ulp-adc/README.md delete mode 100644 examples/espidf-ulp-adc/include/README delete mode 100644 examples/espidf-ulp-adc/lib/README delete mode 100644 examples/espidf-ulp-adc/main/ulp_adc_example_main.c delete mode 100644 examples/espidf-ulp-adc/test/README delete mode 100644 examples/espidf-ulp-adc/ulp/adc.S delete mode 100644 examples/espidf-ulp-pulse/.gitignore delete mode 100644 examples/espidf-ulp-pulse/CMakeLists.txt delete mode 100644 examples/espidf-ulp-pulse/README.md delete mode 100644 examples/espidf-ulp-pulse/include/README delete mode 100644 examples/espidf-ulp-pulse/lib/README delete mode 100644 examples/espidf-ulp-pulse/platformio.ini delete mode 100644 examples/espidf-ulp-pulse/test/README rename examples/{espidf-ulp-adc => espidf-ulp-riscv}/CMakeLists.txt (88%) create mode 100644 examples/espidf-ulp-riscv/README.md create mode 100644 examples/espidf-ulp-riscv/example_test.py rename examples/{espidf-ulp-adc => espidf-ulp-riscv}/main/CMakeLists.txt (52%) create mode 100644 examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c rename examples/{espidf-ulp-adc => espidf-ulp-riscv}/platformio.ini (76%) rename examples/{espidf-ulp-pulse => espidf-ulp-riscv}/sdkconfig.defaults (56%) create mode 100644 examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 create mode 100644 examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 create mode 100644 examples/espidf-ulp-riscv/ulp/main.c rename examples/{espidf-storage-spiffs => espidf-ulp}/CMakeLists.txt (91%) create mode 100644 examples/espidf-ulp/Makefile create mode 100644 examples/espidf-ulp/README.md create mode 100644 examples/espidf-ulp/example_test.py create mode 100644 examples/espidf-ulp/image/ulp_power_graph.png rename examples/{espidf-ulp-pulse/src => espidf-ulp/main}/CMakeLists.txt (83%) create mode 100644 examples/espidf-ulp/main/component.mk rename examples/{espidf-ulp-pulse/src => espidf-ulp/main}/ulp_example_main.c (92%) rename examples/{espidf-storage-spiffs => espidf-ulp}/platformio.ini (67%) rename examples/{espidf-ulp-adc => espidf-ulp}/sdkconfig.defaults (71%) create mode 100644 examples/espidf-ulp/sdkconfig.defaults.esp32 create mode 100644 examples/espidf-ulp/sdkconfig.defaults.esp32s2 create mode 100644 examples/espidf-ulp/sdkconfig.defaults.esp32s3 rename examples/{espidf-ulp-pulse => espidf-ulp}/ulp/pulse_cnt.S (85%) rename examples/{espidf-ulp-pulse => espidf-ulp}/ulp/wake_up.S (89%) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index d57f14183..0f765c7bc 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -12,7 +12,6 @@ jobs: - "examples/arduino-ble5-advertising" - "examples/arduino-blink" - "examples/arduino-rmt-blink" - - "examples/arduino-briki-internal-libs" - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/espidf-arduino-blink" @@ -27,9 +26,8 @@ jobs: - "examples/espidf-peripherals-uart" - "examples/espidf-peripherals-usb" - "examples/espidf-storage-sdcard" - - "examples/espidf-storage-spiffs" - - "examples/espidf-ulp-adc" - - "examples/espidf-ulp-pulse" + - "examples/espidf-ulp" + - "examples/espidf-ulp-riscv" runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index eea32aa38..eb8e8c447 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -28,16 +28,28 @@ env = DefaultEnvironment() board = env.BoardConfig() -build_core = board.get("build.core", "").lower() +extra_flags = board.get("build.extra_flags", "") +extra_flags = [element.replace("-D", " ") for element in extra_flags] +extra_flags = ''.join(extra_flags) +build_flags = env.GetProjectOption("build_flags") +build_flags = [element.replace("-D", " ") for element in build_flags] +build_flags = ''.join(build_flags) SConscript("_embed_files.py", exports="env") -if build_core == "mbcwb": +if ("CORE32SOLO1" in extra_flags or "FRAMEWORK_ARDUINO_SOLO1" in build_flags) and ("arduino" in env.subst("$PIOFRAMEWORK") and "espidf" not in env.subst("$PIOFRAMEWORK")): SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( - "framework-arduino-mbcwb"), "tools", "platformio-esp-build.py")) + "framework-arduino-solo1"), "tools", "platformio-build.py")) + env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) + +elif "arduino" in env.subst("$PIOFRAMEWORK") and "FRAMEWORK_ARDUINO_ITEAD" in build_flags and "espidf" not in env.subst("$PIOFRAMEWORK"): + SConscript( + join(DefaultEnvironment().PioPlatform().get_package_dir( + "framework-arduino-ITEAD"), "tools", "platformio-build.py")) + env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) -elif "espidf" not in env.subst("$PIOFRAMEWORK"): +elif "arduino" in env.subst("$PIOFRAMEWORK") and "CORE32SOLO1" not in extra_flags and "FRAMEWORK_ARDUINO_ITEAD" not in build_flags and "espidf" not in env.subst("$PIOFRAMEWORK"): SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 643253470..54c0cb382 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -222,9 +222,9 @@ def populate_idf_env_vars(idf_env): os.path.dirname(env.subst("$PYTHONEXE")), ] - if mcu not in ("esp32c3", "esp32s3"): + if mcu not in ("esp32c3"): additional_packages.append( - os.path.join(platform.get_package_dir("toolchain-%sulp" % mcu), "bin"), + os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), ) if "windows" in get_systype(): diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index c71245133..7f16e7f94 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -34,16 +34,21 @@ def prepare_ulp_env_vars(env): ulp_env.PrependENVPath("IDF_PATH", FRAMEWORK_DIR) + mcu = "32" + if "esp32s2" in idf_variant: + mcu = "32s2" + elif "esp32s3" in idf_variant: + mcu = "32s3" + additional_packages = [ os.path.join( platform.get_package_dir( - "toolchain-xtensa-esp%s" - % ("32s2" if idf_variant == "esp32s2" else "32") + "toolchain-xtensa-esp%s" % mcu ), "bin", ), os.path.join( - platform.get_package_dir("toolchain-%sulp" % idf_variant), + platform.get_package_dir("toolchain-esp32ulp"), "bin", ), platform.get_package_dir("tool-ninja"), @@ -92,8 +97,8 @@ def generate_ulp_config(target_config): "components", "ulp", "cmake", - "toolchain-%s-ulp%s.cmake" - % (idf_variant, "-riscv" if riscv_ulp_enabled else ""), + "toolchain-%sulp%s.cmake" + % ("" if riscv_ulp_enabled else idf_variant + "-", "-riscv" if riscv_ulp_enabled else ""), ), '-DULP_S_SOURCES="%s"' % ";".join(ulp_sources), "-DULP_APP_NAME=ulp_main", diff --git a/builder/main.py b/builder/main.py index 852b99c9f..80ba655ac 100644 --- a/builder/main.py +++ b/builder/main.py @@ -409,33 +409,6 @@ def __fetch_fs_size(target, source, env): ] -elif upload_protocol == "mbctool": - env.Replace( - UPLOADER=join( - platform.get_package_dir("tool-mbctool") or "", "bin", "mbctool"), - UPLOADERFLAGS=[ - "--device", "esp", - "--speed", "$UPLOAD_SPEED", - "--port", '"$UPLOAD_PORT"', - "--upload", - "0x1000", join( - platform.get_package_dir("framework-arduino-mbcwb"), - "tools", "sdk", "bin", "bootloader_qio_80m.bin"), - "0x8000", join("$BUILD_DIR", "partitions.bin"), - "0xe000", join( - platform.get_package_dir("framework-arduino-mbcwb"), - "tools", "partitions", "boot_app0.bin"), - "0x10000", join("$BUILD_DIR", "${PROGNAME}.bin"), - ], - UPLOADCMD='"$UPLOADER" $UPLOADERFLAGS' - ) - upload_actions = [ - env.VerboseAction(env.AutodetectUploadPort, - "Looking for upload port..."), - env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE") - ] - - elif upload_protocol in debug_tools: openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)] openocd_args.extend( diff --git a/examples/arduino-briki-internal-libs/.gitignore b/examples/arduino-briki-internal-libs/.gitignore deleted file mode 100644 index 03f4a3c19..000000000 --- a/examples/arduino-briki-internal-libs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/arduino-briki-internal-libs/README.md b/examples/arduino-briki-internal-libs/README.md deleted file mode 100644 index 97c25a7f3..000000000 --- a/examples/arduino-briki-internal-libs/README.md +++ /dev/null @@ -1,27 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/arduino-briki-internal-libs - -# Build project -$ pio run - -# Upload firmware -$ pio run --target upload - -# Build specific environment -$ pio run -e briki_abc_esp32 - -# Upload firmware for the specific environment -$ pio run -e briki_abc_esp32 --target upload - -# Clean build files -$ pio run --target clean -``` \ No newline at end of file diff --git a/examples/arduino-briki-internal-libs/include/README b/examples/arduino-briki-internal-libs/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/arduino-briki-internal-libs/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/arduino-briki-internal-libs/lib/README b/examples/arduino-briki-internal-libs/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/arduino-briki-internal-libs/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/arduino-briki-internal-libs/platformio.ini b/examples/arduino-briki-internal-libs/platformio.ini deleted file mode 100644 index adc286502..000000000 --- a/examples/arduino-briki-internal-libs/platformio.ini +++ /dev/null @@ -1,18 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html - -[env:briki_abc_esp32] -platform = espressif32 -board = briki_abc_esp32 -framework = arduino - -[env:briki_mbc-wb_esp32] -platform = espressif32 -board = briki_mbc-wb_esp32 -framework = arduino diff --git a/examples/arduino-briki-internal-libs/src/WiFiTelnetToSerial.ino b/examples/arduino-briki-internal-libs/src/WiFiTelnetToSerial.ino deleted file mode 100644 index 63bdf6c13..000000000 --- a/examples/arduino-briki-internal-libs/src/WiFiTelnetToSerial.ino +++ /dev/null @@ -1,129 +0,0 @@ -/* - WiFiTelnetToSerial - Example Transparent UART to Telnet Server for ESP32 - - Copyright (c) 2017 Hristo Gochkov. All rights reserved. - This file is part of the ESP32 WiFi library for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include -#include - -WiFiMulti wifiMulti; - -//how many clients should be able to telnet to this ESP32 -#define MAX_SRV_CLIENTS 1 -const char* ssid = "**********"; -const char* password = "**********"; - -WiFiServer server(23); -WiFiClient serverClients[MAX_SRV_CLIENTS]; - -void setup() { - Serial.begin(115200); - Serial.println("\nConnecting"); - - wifiMulti.addAP(ssid, password); - wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); - wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); - - Serial.println("Connecting Wifi "); - for (int loops = 10; loops > 0; loops--) { - if (wifiMulti.run() == WL_CONNECTED) { - Serial.println(""); - Serial.print("WiFi connected "); - Serial.print("IP address: "); - Serial.println(WiFi.localIP()); - break; - } - else { - Serial.println(loops); - delay(1000); - } - } - if (wifiMulti.run() != WL_CONNECTED) { - Serial.println("WiFi connect failed"); - delay(1000); - ESP.restart(); - } - - //start UART and the server - Serial2.begin(9600); - server.begin(); - server.setNoDelay(true); - - Serial.print("Ready! Use 'telnet "); - Serial.print(WiFi.localIP()); - Serial.println(" 23' to connect"); -} - -void loop() { - uint8_t i; - if (wifiMulti.run() == WL_CONNECTED) { - //check if there are any new clients - if (server.hasClient()){ - for(i = 0; i < MAX_SRV_CLIENTS; i++){ - //find free/disconnected spot - if (!serverClients[i] || !serverClients[i].connected()){ - if(serverClients[i]) serverClients[i].stop(); - serverClients[i] = server.available(); - if (!serverClients[i]) Serial.println("available broken"); - Serial.print("New client: "); - Serial.print(i); Serial.print(' '); - Serial.println(serverClients[i].remoteIP()); - break; - } - } - if (i >= MAX_SRV_CLIENTS) { - //no free/disconnected spot so reject - server.available().stop(); - } - } - //check clients for data - for(i = 0; i < MAX_SRV_CLIENTS; i++){ - if (serverClients[i] && serverClients[i].connected()){ - if(serverClients[i].available()){ - //get data from the telnet client and push it to the UART - while(serverClients[i].available()) Serial2.write(serverClients[i].read()); - } - } - else { - if (serverClients[i]) { - serverClients[i].stop(); - } - } - } - //check UART for data - if(Serial2.available()){ - size_t len = Serial2.available(); - uint8_t sbuf[len]; - Serial2.readBytes(sbuf, len); - //push UART data to all connected telnet clients - for(i = 0; i < MAX_SRV_CLIENTS; i++){ - if (serverClients[i] && serverClients[i].connected()){ - serverClients[i].write(sbuf, len); - delay(1); - } - } - } - } - else { - Serial.println("WiFi not connected!"); - for(i = 0; i < MAX_SRV_CLIENTS; i++) { - if (serverClients[i]) serverClients[i].stop(); - } - delay(1000); - } -} diff --git a/examples/arduino-briki-internal-libs/test/README b/examples/arduino-briki-internal-libs/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/arduino-briki-internal-libs/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/examples/espidf-storage-spiffs/.gitignore b/examples/espidf-storage-spiffs/.gitignore deleted file mode 100644 index 03f4a3c19..000000000 --- a/examples/espidf-storage-spiffs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/espidf-storage-spiffs/README.md b/examples/espidf-storage-spiffs/README.md deleted file mode 100644 index 81c1f0eae..000000000 --- a/examples/espidf-storage-spiffs/README.md +++ /dev/null @@ -1,24 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/espidf-storage-spiffs - -# Build project -$ pio run - -# Upload firmware -$ pio run --target upload - -# Upload SPIFFS image -$ pio run --target uploadfs - -# Clean build files -$ pio run --target clean -``` diff --git a/examples/espidf-storage-spiffs/data/hello.txt b/examples/espidf-storage-spiffs/data/hello.txt deleted file mode 100644 index 5a8367719..000000000 --- a/examples/espidf-storage-spiffs/data/hello.txt +++ /dev/null @@ -1 +0,0 @@ -Hello World from SPIFFS. diff --git a/examples/espidf-storage-spiffs/include/README b/examples/espidf-storage-spiffs/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/espidf-storage-spiffs/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-storage-spiffs/lib/README b/examples/espidf-storage-spiffs/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/espidf-storage-spiffs/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-storage-spiffs/partitions_example.csv b/examples/espidf-storage-spiffs/partitions_example.csv deleted file mode 100644 index 92db904e0..000000000 --- a/examples/espidf-storage-spiffs/partitions_example.csv +++ /dev/null @@ -1,6 +0,0 @@ -# Name, Type, SubType, Offset, Size, Flags -# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap -nvs, data, nvs, 0x9000, 0x6000, -phy_init, data, phy, 0xf000, 0x1000, -factory, app, factory, 0x10000, 1M, -spiffs, data, spiffs, , 0xF0000, diff --git a/examples/espidf-storage-spiffs/sdkconfig.defaults b/examples/espidf-storage-spiffs/sdkconfig.defaults deleted file mode 100644 index b9bb0c0a5..000000000 --- a/examples/espidf-storage-spiffs/sdkconfig.defaults +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv" diff --git a/examples/espidf-storage-spiffs/src/CMakeLists.txt b/examples/espidf-storage-spiffs/src/CMakeLists.txt deleted file mode 100644 index 026db1313..000000000 --- a/examples/espidf-storage-spiffs/src/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "spiffs_example_main.c" - INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/espidf-storage-spiffs/src/spiffs_example_main.c b/examples/espidf-storage-spiffs/src/spiffs_example_main.c deleted file mode 100644 index 279f3df19..000000000 --- a/examples/espidf-storage-spiffs/src/spiffs_example_main.c +++ /dev/null @@ -1,73 +0,0 @@ -/* SPIFFS filesystem example. - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include "esp_err.h" -#include "esp_log.h" -#include "esp_spiffs.h" - -static const char *TAG = "example"; - -void app_main(void) -{ - ESP_LOGI(TAG, "Initializing SPIFFS"); - - esp_vfs_spiffs_conf_t conf = { - .base_path = "/spiffs", - .partition_label = NULL, - .max_files = 5, - .format_if_mount_failed = true - }; - - // Use settings defined above to initialize and mount SPIFFS filesystem. - // Note: esp_vfs_spiffs_register is an all-in-one convenience function. - esp_err_t ret = esp_vfs_spiffs_register(&conf); - - if (ret != ESP_OK) { - if (ret == ESP_FAIL) { - ESP_LOGE(TAG, "Failed to mount or format filesystem"); - } else if (ret == ESP_ERR_NOT_FOUND) { - ESP_LOGE(TAG, "Failed to find SPIFFS partition"); - } else { - ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); - } - return; - } - - size_t total = 0, used = 0; - ret = esp_spiffs_info(conf.partition_label, &total, &used); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret)); - } else { - ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); - } - - // Open renamed file for reading - ESP_LOGI(TAG, "Reading file"); - FILE* f = fopen("/spiffs/hello.txt", "r"); - if (f == NULL) { - ESP_LOGI(TAG, "Failed to open file for reading"); - return; - } - char line[64]; - fgets(line, sizeof(line), f); - fclose(f); - // strip newline - char* pos = strchr(line, '\n'); - if (pos) { - *pos = '\0'; - } - ESP_LOGI(TAG, "Read from file: '%s'", line); - - // All done, unmount partition and disable SPIFFS - esp_vfs_spiffs_unregister(conf.partition_label); - ESP_LOGI(TAG, "SPIFFS unmounted"); -} diff --git a/examples/espidf-storage-spiffs/test/README b/examples/espidf-storage-spiffs/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/espidf-storage-spiffs/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/examples/espidf-ulp-adc/.gitignore b/examples/espidf-ulp-adc/.gitignore deleted file mode 100644 index 03f4a3c19..000000000 --- a/examples/espidf-ulp-adc/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/espidf-ulp-adc/README.md b/examples/espidf-ulp-adc/README.md deleted file mode 100644 index 465d156ed..000000000 --- a/examples/espidf-ulp-adc/README.md +++ /dev/null @@ -1,27 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/espidf-ulp-adc - -# Build project -$ pio run - -# Upload firmware -$ pio run --target upload - -# Build specific environment -$ pio run -e esp32dev - -# Upload firmware for the specific environment -$ pio run -e esp32dev --target upload - -# Clean build files -$ pio run --target clean -``` diff --git a/examples/espidf-ulp-adc/include/README b/examples/espidf-ulp-adc/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/espidf-ulp-adc/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-ulp-adc/lib/README b/examples/espidf-ulp-adc/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/espidf-ulp-adc/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-ulp-adc/main/ulp_adc_example_main.c b/examples/espidf-ulp-adc/main/ulp_adc_example_main.c deleted file mode 100644 index 9e38e9ff7..000000000 --- a/examples/espidf-ulp-adc/main/ulp_adc_example_main.c +++ /dev/null @@ -1,100 +0,0 @@ -/* ULP Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include "esp_sleep.h" -#include "nvs.h" -#include "nvs_flash.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/sens_reg.h" -#include "driver/gpio.h" -#include "driver/rtc_io.h" -#include "driver/adc.h" -#include "driver/dac.h" -#include "esp32/ulp.h" -#include "ulp_main.h" - -extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); -extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end"); - -/* This function is called once after power-on reset, to load ULP program into - * RTC memory and configure the ADC. - */ -static void init_ulp_program(void); - -/* This function is called every time before going into deep sleep. - * It starts the ULP program and resets measurement counter. - */ -static void start_ulp_program(void); - -void app_main(void) -{ - esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); - if (cause != ESP_SLEEP_WAKEUP_ULP) { - printf("Not ULP wakeup\n"); - init_ulp_program(); - } else { - printf("Deep sleep wakeup\n"); - printf("ULP did %d measurements since last reset\n", ulp_sample_counter & UINT16_MAX); - printf("Thresholds: low=%d high=%d\n", ulp_low_thr, ulp_high_thr); - ulp_last_result &= UINT16_MAX; - printf("Value=%d was %s threshold\n", ulp_last_result, - ulp_last_result < ulp_low_thr ? "below" : "above"); - } - printf("Entering deep sleep\n\n"); - start_ulp_program(); - ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() ); - esp_deep_sleep_start(); -} - -static void init_ulp_program(void) -{ - esp_err_t err = ulp_load_binary(0, ulp_main_bin_start, - (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t)); - ESP_ERROR_CHECK(err); - - /* Configure ADC channel */ - /* Note: when changing channel here, also change 'adc_channel' constant - in adc.S */ - adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); -#if CONFIG_IDF_TARGET_ESP32 - adc1_config_width(ADC_WIDTH_BIT_12); -#elif CONFIG_IDF_TARGET_ESP32S2 - adc1_config_width(ADC_WIDTH_BIT_13); -#endif - adc1_ulp_enable(); - - /* Set low and high thresholds, approx. 1.35V - 1.75V*/ - ulp_low_thr = 1500; - ulp_high_thr = 2000; - - /* Set ULP wake up period to 20ms */ - ulp_set_wakeup_period(0, 20000); - - /* Disconnect GPIO12 and GPIO15 to remove current drain through - * pullup/pulldown resistors. - * GPIO12 may be pulled high to select flash voltage. - */ - rtc_gpio_isolate(GPIO_NUM_12); - rtc_gpio_isolate(GPIO_NUM_15); -#if CONFIG_IDF_TARGET_ESP32 - esp_deep_sleep_disable_rom_logging(); // suppress boot messages -#endif -} - -static void start_ulp_program(void) -{ - /* Reset sample counter */ - ulp_sample_counter = 0; - - /* Start the program */ - esp_err_t err = ulp_run(&ulp_entry - RTC_SLOW_MEM); - ESP_ERROR_CHECK(err); -} diff --git a/examples/espidf-ulp-adc/test/README b/examples/espidf-ulp-adc/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/espidf-ulp-adc/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/examples/espidf-ulp-adc/ulp/adc.S b/examples/espidf-ulp-adc/ulp/adc.S deleted file mode 100644 index 70d0439c8..000000000 --- a/examples/espidf-ulp-adc/ulp/adc.S +++ /dev/null @@ -1,115 +0,0 @@ -/* ULP Example: using ADC in deep sleep - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. - - This file contains assembly code which runs on the ULP. - - ULP wakes up to run this code at a certain period, determined by the values - in SENS_ULP_CP_SLEEP_CYCx_REG registers. On each wake up, the program - measures input voltage on the given ADC channel 'adc_oversampling_factor' - times. Measurements are accumulated and average value is calculated. - Average value is compared to the two thresholds: 'low_thr' and 'high_thr'. - If the value is less than 'low_thr' or more than 'high_thr', ULP wakes up - the chip from deep sleep. -*/ - -/* ULP assembly files are passed through C preprocessor first, so include directives - and C macros may be used in these files - */ -#include "soc/rtc_cntl_reg.h" -#include "soc/soc_ulp.h" - - /* ADC1 channel 6, GPIO34 */ - .set adc_channel, 6 - - /* Configure the number of ADC samples to average on each measurement. - For convenience, make it a power of 2. */ - .set adc_oversampling_factor_log, 2 - .set adc_oversampling_factor, (1 << adc_oversampling_factor_log) - - /* Define variables, which go into .bss section (zero-initialized data) */ - .bss - - /* Low threshold of ADC reading. - Set by the main program. */ - .global low_thr -low_thr: - .long 0 - - /* High threshold of ADC reading. - Set by the main program. */ - .global high_thr -high_thr: - .long 0 - - /* Counter of measurements done */ - .global sample_counter -sample_counter: - .long 0 - - .global last_result -last_result: - .long 0 - - /* Code goes into .text section */ - .text - .global entry -entry: - /* increment sample counter */ - move r3, sample_counter - ld r2, r3, 0 - add r2, r2, 1 - st r2, r3, 0 - - /* do measurements using ADC */ - /* r0 will be used as accumulator */ - move r0, 0 - /* initialize the loop counter */ - stage_rst -measure: - /* measure and add value to accumulator */ - adc r1, 0, adc_channel + 1 - add r0, r0, r1 - /* increment loop counter and check exit condition */ - stage_inc 1 - jumps measure, adc_oversampling_factor, lt - - /* divide accumulator by adc_oversampling_factor. - Since it is chosen as a power of two, use right shift */ - rsh r0, r0, adc_oversampling_factor_log - /* averaged value is now in r0; store it into last_result */ - move r3, last_result - st r0, r3, 0 - - /* compare with low_thr; wake up if value < low_thr */ - move r3, low_thr - ld r3, r3, 0 - sub r3, r0, r3 - jump wake_up, ov - - /* compare with high_thr; wake up if value > high_thr */ - move r3, high_thr - ld r3, r3, 0 - sub r3, r3, r0 - jump wake_up, ov - - /* value within range, end the program */ - .global exit -exit: - halt - - .global wake_up -wake_up: - /* Check if the system can be woken up */ - READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP) - and r0, r0, 1 - jump exit, eq - - /* Wake up the SoC, end program */ - wake - WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0) - halt diff --git a/examples/espidf-ulp-pulse/.gitignore b/examples/espidf-ulp-pulse/.gitignore deleted file mode 100644 index 03f4a3c19..000000000 --- a/examples/espidf-ulp-pulse/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/espidf-ulp-pulse/CMakeLists.txt b/examples/espidf-ulp-pulse/CMakeLists.txt deleted file mode 100644 index f0c74a151..000000000 --- a/examples/espidf-ulp-pulse/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -cmake_minimum_required(VERSION 3.16.0) -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(espidf-ulp-pulse-new) diff --git a/examples/espidf-ulp-pulse/README.md b/examples/espidf-ulp-pulse/README.md deleted file mode 100644 index d6ca4f9bf..000000000 --- a/examples/espidf-ulp-pulse/README.md +++ /dev/null @@ -1,27 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/espidf-ulp-pulse - -# Build project -$ pio run - -# Upload firmware -$ pio run --target upload - -# Build specific environment -$ pio run -e esp32dev - -# Upload firmware for the specific environment -$ pio run -e esp32dev --target upload - -# Clean build files -$ pio run --target clean -``` diff --git a/examples/espidf-ulp-pulse/include/README b/examples/espidf-ulp-pulse/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/espidf-ulp-pulse/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-ulp-pulse/lib/README b/examples/espidf-ulp-pulse/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/espidf-ulp-pulse/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-ulp-pulse/platformio.ini b/examples/espidf-ulp-pulse/platformio.ini deleted file mode 100644 index fe714f0c9..000000000 --- a/examples/espidf-ulp-pulse/platformio.ini +++ /dev/null @@ -1,13 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html - -[env:esp32dev] -platform = espressif32 -framework = espidf -board = esp32dev diff --git a/examples/espidf-ulp-pulse/test/README b/examples/espidf-ulp-pulse/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/espidf-ulp-pulse/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/examples/espidf-ulp-adc/CMakeLists.txt b/examples/espidf-ulp-riscv/CMakeLists.txt similarity index 88% rename from examples/espidf-ulp-adc/CMakeLists.txt rename to examples/espidf-ulp-riscv/CMakeLists.txt index 7037f86d8..d49885b79 100644 --- a/examples/espidf-ulp-adc/CMakeLists.txt +++ b/examples/espidf-ulp-riscv/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(ulp-adc-example) \ No newline at end of file +project(ulp_riscv_example) diff --git a/examples/espidf-ulp-riscv/README.md b/examples/espidf-ulp-riscv/README.md new file mode 100644 index 000000000..bfe9e639b --- /dev/null +++ b/examples/espidf-ulp-riscv/README.md @@ -0,0 +1,31 @@ +| Supported Targets | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | + +# ULP-RISC-V simple example with GPIO Polling: + +This example demonstrates how to program the ULP-RISC-V coprocessor to poll a gpio and wakeup the main CPU when it changes its state; + +ULP program written in C can be found across `ulp/main.c`. The build system compiles and links this program, converts it into binary format, and embeds it into the .rodata section of the ESP-IDF application. + +At runtime, the application running inside the main CPU loads ULP program into the `RTC_SLOW_MEM` memory region using `ulp_riscv_load_binary` function. The main code then configures the ULP wakeup period and starts the coprocessor by using `ulp_riscv_run`. Once the ULP program is started, it runs periodically, with the period set by the main program. The main program enables ULP wakeup source and puts the chip into deep sleep mode. + +When the ULP program finds an state changing in the pin, it saves the current state and sends a wakeup signal to the main CPU. + +Upon wakeup, the main program prints the current level of the measured gpio and go back to the deep sleep. + +In this example the input signal is connected to GPIO0. Note that this pin was chosen because most development boards have a button connected to it, so the pulses to be counted can be generated by pressing the button. For real world applications this is not a good choice of a pin, because GPIO0 also acts as a bootstrapping pin. To change the pin number, check the ESP32-S2 Chip Pin List document and adjust `gpio_num` and `ulp_io_number` variables in main.c. + + +## Example output + +``` +Not a ULP wakeup, initializing it! +Entering in deep sleep + +... + +ULP-RISC-V woke up the main CPU! +ULP-RISC-V read changes in GPIO_0 current is: High +Entering in deep sleep + +``` \ No newline at end of file diff --git a/examples/espidf-ulp-riscv/example_test.py b/examples/espidf-ulp-riscv/example_test.py new file mode 100644 index 000000000..cce2c6e01 --- /dev/null +++ b/examples/espidf-ulp-riscv/example_test.py @@ -0,0 +1,48 @@ +from __future__ import unicode_literals + +import re +import time + +import tiny_test_fw +import ttfw_idf +from tiny_test_fw import DUT + + +@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32s2', 'esp32s3']) +def test_examples_ulp_riscv(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument + dut = env.get_dut('ulp_riscv', 'examples/system/ulp_riscv/gpio') + dut.start_app() + + dut.expect_all('Not a ULP-RISC-V wakeup, initializing it!', + 'Entering in deep sleep', + timeout=30) + + # Give the chip time to enter deepsleep + time.sleep(1) + + # Run two times to make sure device sleep + # and wake up properly + for i in range(0, 2): + # Set GPIO0 using DTR + dut.port_inst.setDTR(i % 2 == 0) + + dut.expect('ULP-RISC-V woke up the main CPU!', timeout=5) + + # Check GPIO state + state = 'Low' if i % 2 == 0 else 'High' + dut.expect(re.compile(r'ULP-RISC-V read changes in GPIO_0 current is: %s' % state), timeout=5) + + # Go back to sleep + dut.expect('Entering in deep sleep', timeout=5) + + try: + # We expect a timeout here, otherwise it means that + # the main CPU woke up unexpectedly! + dut.expect('ULP-RISC-V woke up the main CPU!', timeout=20) + raise Exception('Main CPU woke up unexpectedly!') + except DUT.ExpectTimeout: + pass + + +if __name__ == '__main__': + test_examples_ulp_riscv() diff --git a/examples/espidf-ulp-adc/main/CMakeLists.txt b/examples/espidf-ulp-riscv/main/CMakeLists.txt similarity index 52% rename from examples/espidf-ulp-adc/main/CMakeLists.txt rename to examples/espidf-ulp-riscv/main/CMakeLists.txt index 036d000fb..51344fa9a 100644 --- a/examples/espidf-ulp-adc/main/CMakeLists.txt +++ b/examples/espidf-ulp-riscv/main/CMakeLists.txt @@ -1,21 +1,27 @@ -idf_component_register(SRCS "ulp_adc_example_main.c" - INCLUDE_DIRS "" - REQUIRES soc nvs_flash ulp driver) +# Set usual component variables +set(COMPONENT_SRCS "ulp_riscv_example_main.c") +set(COMPONENT_ADD_INCLUDEDIRS "") +set(COMPONENT_REQUIRES soc nvs_flash ulp driver) + +register_component() + # # ULP support additions to component CMakeLists.txt. # # 1. The ULP app name must be unique (if multiple components use ULP). -set(ulp_app_name ulp_main) +set(ulp_app_name ulp_${COMPONENT_NAME}) # -# 2. Specify all assembly source files. +# 2. Specify all C and Assembly source files. # Files should be placed into a separate directory (in this case, ulp/), # which should not be added to COMPONENT_SRCS. -set(ulp_s_sources "../ulp/adc.S") +set(ulp_riscv_sources "ulp/main.c") + # # 3. List all the component source files which include automatically # generated ULP export file, ${ulp_app_name}.h: -set(ulp_exp_dep_srcs "ulp_adc_example_main.c") +set(ulp_exp_dep_srcs "../ulp_riscv_example_main.c") + # # 4. Call function to build ULP binary and embed in project using the argument # values above. -ulp_embed_binary(${ulp_app_name} ${ulp_s_sources} ${ulp_exp_dep_srcs}) +ulp_embed_binary(${ulp_app_name} "${ulp_riscv_sources}" "${ulp_exp_dep_srcs}") diff --git a/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c b/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c new file mode 100644 index 000000000..de9c20e3b --- /dev/null +++ b/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c @@ -0,0 +1,75 @@ +/* ULP riscv DS18B20 1wire temperature sensor example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include "esp_sleep.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/sens_reg.h" +#include "soc/rtc_periph.h" +#include "driver/gpio.h" +#include "driver/rtc_io.h" +#include "esp32s2/ulp.h" +#include "esp32s2/ulp_riscv.h" +#include "ulp_main.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); +extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end"); + +static void init_ulp_program(void); + +void app_main(void) +{ + /* Initialize selected GPIO as RTC IO, enable input, disable pullup and pulldown */ + rtc_gpio_init(GPIO_NUM_0); + rtc_gpio_set_direction(GPIO_NUM_0, RTC_GPIO_MODE_INPUT_ONLY); + rtc_gpio_pulldown_dis(GPIO_NUM_0); + rtc_gpio_pullup_dis(GPIO_NUM_0); + rtc_gpio_hold_en(GPIO_NUM_0); + + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + /* not a wakeup from ULP, load the firmware */ + if (cause != ESP_SLEEP_WAKEUP_ULP) { + printf("Not a ULP-RISC-V wakeup, initializing it! \n"); + init_ulp_program(); + } + + /* ULP Risc-V read and detected a change in GPIO_0, prints */ + if (cause == ESP_SLEEP_WAKEUP_ULP) { + printf("ULP-RISC-V woke up the main CPU! \n"); + printf("ULP-RISC-V read changes in GPIO_0 current is: %s \n", + (bool)(ulp_gpio_level_previous == 0) ? "Low" : "High" ); + + } + + /* Go back to sleep, only the ULP Risc-V will run */ + printf("Entering in deep sleep\n\n"); + + /* Small delay to ensure the messages are printed */ + vTaskDelay(100); + + ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup()); + esp_deep_sleep_start(); +} + +static void init_ulp_program(void) +{ + esp_err_t err = ulp_riscv_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start)); + ESP_ERROR_CHECK(err); + + /* The first argument is the period index, which is not used by the ULP-RISC-V timer + * The second argument is the period in microseconds, which gives a wakeup time period of: 20ms + */ + ulp_set_wakeup_period(0, 20000); + + /* Start the program */ + err = ulp_riscv_run(); + ESP_ERROR_CHECK(err); +} diff --git a/examples/espidf-ulp-adc/platformio.ini b/examples/espidf-ulp-riscv/platformio.ini similarity index 76% rename from examples/espidf-ulp-adc/platformio.ini rename to examples/espidf-ulp-riscv/platformio.ini index c3a3cadaa..2cc98730b 100644 --- a/examples/espidf-ulp-adc/platformio.ini +++ b/examples/espidf-ulp-riscv/platformio.ini @@ -10,7 +10,12 @@ [platformio] src_dir = main -[env:esp32dev] +[env:esp32-s2] platform = espressif32 framework = espidf -board = esp32dev +board = esp32-s2-saola-1 + +[env:esp32-s3] +platform = espressif32 +framework = espidf +board = esp32-s3-devkitc-1 diff --git a/examples/espidf-ulp-pulse/sdkconfig.defaults b/examples/espidf-ulp-riscv/sdkconfig.defaults similarity index 56% rename from examples/espidf-ulp-pulse/sdkconfig.defaults rename to examples/espidf-ulp-riscv/sdkconfig.defaults index 7214df17c..302c87aa9 100644 --- a/examples/espidf-ulp-pulse/sdkconfig.defaults +++ b/examples/espidf-ulp-riscv/sdkconfig.defaults @@ -1,9 +1,5 @@ -# Enable ULP -CONFIG_ESP32_ULP_COPROC_ENABLED=y -CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=1024 # Set log level to Warning to produce clean output CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y CONFIG_BOOTLOADER_LOG_LEVEL=2 CONFIG_LOG_DEFAULT_LEVEL_WARN=y CONFIG_LOG_DEFAULT_LEVEL=2 -CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y diff --git a/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 b/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 new file mode 100644 index 000000000..f86c0eff1 --- /dev/null +++ b/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 @@ -0,0 +1,4 @@ +# Enable ULP +CONFIG_ESP32S2_ULP_COPROC_ENABLED=y +CONFIG_ESP32S2_ULP_COPROC_RISCV=y +CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=4096 diff --git a/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 b/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 new file mode 100644 index 000000000..165e30dd5 --- /dev/null +++ b/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 @@ -0,0 +1,4 @@ +# Enable ULP +CONFIG_ESP32S3_ULP_COPROC_ENABLED=y +CONFIG_ESP32S3_ULP_COPROC_RISCV=y +CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=4096 diff --git a/examples/espidf-ulp-riscv/ulp/main.c b/examples/espidf-ulp-riscv/ulp/main.c new file mode 100644 index 000000000..2f24ba377 --- /dev/null +++ b/examples/espidf-ulp-riscv/ulp/main.c @@ -0,0 +1,41 @@ +/* ULP-RISC-V example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + + This code runs on ULP-RISC-V coprocessor +*/ + +#include +#include +#include +#include "ulp_riscv/ulp_riscv.h" +#include "ulp_riscv/ulp_riscv_utils.h" +#include "ulp_riscv/ulp_riscv_gpio.h" + +static bool gpio_level = false; + +/* this variable will be exported as a public symbol, visible from main CPU: */ +bool gpio_level_previous = false; + +int main (void) +{ + gpio_level = (bool)ulp_riscv_gpio_get_level(GPIO_NUM_0); + gpio_level_previous = gpio_level; + + while(1) { + gpio_level = (bool)ulp_riscv_gpio_get_level(GPIO_NUM_0); + + /* Wakes up the main CPU if pin changed its state */ + if(gpio_level != gpio_level_previous) { + gpio_level_previous = gpio_level; + ulp_riscv_wakeup_main_processor(); + break; + } + } + /* ulp_riscv_shutdown() is called automatically when main exits */ + return 0; +} diff --git a/examples/espidf-storage-spiffs/CMakeLists.txt b/examples/espidf-ulp/CMakeLists.txt similarity index 91% rename from examples/espidf-storage-spiffs/CMakeLists.txt rename to examples/espidf-ulp/CMakeLists.txt index 1894b31ca..13c487bc5 100644 --- a/examples/espidf-storage-spiffs/CMakeLists.txt +++ b/examples/espidf-ulp/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(spiffs) +project(ulp_example) diff --git a/examples/espidf-ulp/Makefile b/examples/espidf-ulp/Makefile new file mode 100644 index 000000000..b9b17e5ef --- /dev/null +++ b/examples/espidf-ulp/Makefile @@ -0,0 +1,8 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := ulp_example + +include $(IDF_PATH)/make/project.mk diff --git a/examples/espidf-ulp/README.md b/examples/espidf-ulp/README.md new file mode 100644 index 000000000..afb7c6c45 --- /dev/null +++ b/examples/espidf-ulp/README.md @@ -0,0 +1,57 @@ +| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | + +# ULP Pulse Counting Example + +This example demonstrates how to program the ULP FSM coprocessor to count pulses on an IO while the main CPUs are either running some other code or are in deep sleep. See the README.md file in the upper level 'examples' directory for more information about examples. + +ULP program written in assembly can be found across `ulp/pulse_cnt.S` and `ulp/wake_up.S` (demonstrating multiple ULP source files). The build system assembles and links this program, converts it into binary format, and embeds it into the .rodata section of the ESP-IDF application. + +At runtime, the main code running on the ESP32 (found in main.c) loads ULP program into the `RTC_SLOW_MEM` memory region using `ulp_load_binary` function. Main code configures the ULP program by setting up values of some variables and then starts it using `ulp_run`. Once the ULP program is started, it runs periodically, with the period set by the main program. The main program enables ULP wakeup source and puts the chip into deep sleep mode. + +When the ULP program finds an edge in the input signal, it performs debouncing and increments the variable maintaining the total edge count. Once the edge count reaches certain value (set by the main program), ULP triggers wake up from deep sleep. Note that the ULP program keeps running and monitoring the input signal even when the SoC is woken up. + +Upon wakeup, the main program saves total edge count into NVS and returns to deep sleep. + +In this example the input signal is connected to GPIO0. Note that this pin was chosen because most development boards have a button connected to it, so the pulses to be counted can be generated by pressing the button. For real world applications this is not a good choice of a pin, because GPIO0 also acts as a bootstrapping pin. To change the pin number, check the ESP32 Chip Pin List document and adjust `gpio_num` and `ulp_io_number` variables in main.c. + +In this example, the `CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` Kconfig option is used, which allows you to reduce the boot time of the bootloader during waking up from deep sleep. The bootloader stores in rtc memory the address of a running partition and uses it when it wakes up. This example allows you to skip all image checks and speed up the boot. + +## Example output + +``` +Not ULP wakeup, initializing ULP +Entering deep sleep + +ULP wakeup, saving pulse count +Read pulse count from NVS: 384 +Pulse count from ULP: 5 +Wrote updated pulse count to NVS: 389 +Entering deep sleep + +ULP wakeup, saving pulse count +Read pulse count from NVS: 389 +Pulse count from ULP: 5 +Wrote updated pulse count to NVS: 394 +Entering deep sleep + +ULP wakeup, saving pulse count +Read pulse count from NVS: 394 +Pulse count from ULP: 6 +Wrote updated pulse count to NVS: 400 +Entering deep sleep + +ULP wakeup, saving pulse count +Read pulse count from NVS: 400 +Pulse count from ULP: 5 +Wrote updated pulse count to NVS: 405 +Entering deep sleep +``` + +Note that in one case the pulse count captured by the ULP program is 6, even though the `edge_count_to_wake_up` variable is set to 10 by the main program. This shows that the ULP program keeps track of pulses while the main CPUs are starting up, so when pulses are sent rapidly it is possible to register more pulses between wake up and entry into app_main. + +With the default configuration (20ms ULP wakeup period), average current consumption in deep sleep mode is 16uA. + +## Typical current consumption + +![CurrentConsumption](image/ulp_power_graph.png) diff --git a/examples/espidf-ulp/example_test.py b/examples/espidf-ulp/example_test.py new file mode 100644 index 000000000..4c7840e71 --- /dev/null +++ b/examples/espidf-ulp/example_test.py @@ -0,0 +1,45 @@ +from __future__ import unicode_literals + +import re +import time + +import ttfw_idf +from tiny_test_fw import Utility + + +@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32']) +def test_examples_ulp(env, extra_data): + + dut = env.get_dut('ulp', 'examples/system/ulp_fsm/ulp') + dut.start_app() + + dut.expect_all('Not ULP wakeup, initializing ULP', + 'Entering deep sleep', + timeout=30) + + def generate_gpio0_events(): + for _ in range(5): + dut.port_inst.setDTR(True) # Pulling GPIO0 low using DTR + time.sleep(0.25) + dut.port_inst.setDTR(False) + time.sleep(0.25) + + nvs_value = None + for _ in range(5): + generate_gpio0_events() + dut.expect('ULP wakeup, saving pulse count', timeout=5) + Utility.console_log('Woke up...') + init_count = int(dut.expect(re.compile(r'Read pulse count from NVS:\s+(\d+)'), timeout=5)[0], 10) + assert nvs_value in (init_count, None), ('Read count is {} and previously written value is {}' + ''.format(init_count, nvs_value)) + inc = int(dut.expect(re.compile(r'Pulse count from ULP:\s+(\d+)'), timeout=5)[0], 10) + assert inc in (5, 6), 'pulse count is {}'.format(inc) + new_count = int(dut.expect(re.compile(r'Wrote updated pulse count to NVS:\s+(\d+)'), timeout=5)[0], 10) + assert init_count + inc == new_count, '{} + {} != {}'.format(init_count, inc, new_count) + nvs_value = new_count + Utility.console_log('Pulse count written to NVS: {}. Entering deep sleep...'.format(nvs_value)) + dut.expect('Entering deep sleep', timeout=5) + + +if __name__ == '__main__': + test_examples_ulp() diff --git a/examples/espidf-ulp/image/ulp_power_graph.png b/examples/espidf-ulp/image/ulp_power_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..79dfb10dd79a59f3ad52fbb9bcc696142d24a6a4 GIT binary patch literal 39281 zcmdqJcRZJU8$SL)DH4V3hzcRQ$WF>0+1Yzxq8OhGh-g}eH_q^(U z?&taa^ZV!f-}iYvz3$>OuIv4NpXYg;$8nsOpPY>7Wo$BR6bf}&TuekBg+lj4q0lBS zV!}`Eb&t%zf6mzpiz{A)|G8Z>cnkl=vJrb`k3!+;B7e{_1k+97huqH}t3Fq-HhS)) zYiEeE)O~JaVg1~~RPTnPp`E>{wG{_58#6o84U^~3ZFpE%{`-4oYdd3>+x|%sDAWy< zxX44r7qKg&&KiWfXBRdGv})_^=u8ox=!=kM_%JHOibT#D?V2oxeHM8QLY#p84D!rwXId| zacoCjWosh2NbP+^_-)^nm~wRZ%SGx>E>F?LkRR$9(xcr%epJBz5rq%G@m3|3Kw%*- z|BQ3n^UsTwees2m-&|pQgmvT32Zbe_dyjlf!wOgk8~_6A555T9UXTtVMD3d-Yr5LoXe3bN{C)Pm)Y~(&!l&>a{&ie8%06 zF6%c1)GhU8OKVEk5n`Vodog|avt~tquhN~H0s@qG?%X+E?(J1gCaIQUgtAXJ;E5n=aSr+m~>0pV-*2o*j;q*+=p^F~9cmVzZn1&c3ZMC3^Ad zI~ggjNX!(4+OqIu(z$f`T zbDas=Mr!i%_#!k{l|QSZq2w6CA_YAJ$nINQqQt^9FM3%2%I1GZ7LIO;zoUc~w;K!ur$D(8#H(sv4Em9B*BM zd&MZz2#UUEj;!hT@84O?)Gt!^`MbdBsN{G3o#=jY2*2=p8ZKzkb%WDl@QOdtUE!8& zSw)6xF27g&y1L|;G|LI$E>WI0MS~Jyc}#lJF4Nq+NloN`m4Ltt?rO4A@T@_SrRr1h zah=zNZ=IcZPoF+5wV6ck|NIQY$;pXHtC9q@QFC^JH{BHY4PNMtML>(97l_O9fAi)7 zkJDN}j(Q0VJG;F3ukgF-H$I55!lj@Zu}l;d32WfkTEy}?;Sw`z2nAE};}G!ii#&e( zkU2shKE2d-8ngOnjrY3&``bo6KIg4-u$A9371Hw^SJn0p4s_Q>%8p&(t#2RL&*^MT z)RAymQLuAxY>qmOCn==Ml)l)c(a_Mys^a&)a#P3qNInR;z_OXu5TKdpjy2 zfoi!sMKo%*X18Bmt@Xvp?m$#_cD8bqmlp;(zsvK~U!`V!449sp)o#zSD{ZHnKC72l z9WN8zRm&H6d8lX>b;#}d+oFukD4?Jtj<*p0Z0Etv|3KxZNymIiPNu1L8_d_0x`kh$ zRpnw@CCJSkd2o2RmDlt0XQT*??j>U8-sttM*;Xlru<$!{-jOUk=cO*9p$v?TF;EoO zuLph&Dj9dL7%^S1+z#qr_Vzw^i;hlze`E5+&cann0k^kr@Th25Snzapb>I5?V>H`d zW3JI}4nlrAe*fiV5>}LaCZYOQi^tkJ3G{s8J|7Iy#h)j7(5>|K$99dZ7kGSTY+RS!NbS#!L6i zdMC7x_V-Ps2c%rLX0XNuUiM}wU4qLWEO%fOI9lOAHKu!{%HP4nA*t;w(Wyhf>A{zu#Ln z5+Z(^x}g%OOK5VjsQz3{a+O?-%-&;~4`Rk;YB|h%{B~s;#$`D}>GrSj+v?qd;=bNKl9U0)0(Ek?_)!6j!XWfKX?rpv@3 zNk_B7adM*0OSRDGa`oX7yW~&-o)I zaJ^4OyAcxdRVu1H2VQ(l&MI@+1c5$=8t3h_hfB$%v6D~;)_->bXv#6)U#UM@NC}>pnDB(tJb8L@WSExz>C;4vbu}zfWFPE?t*x!v_VLCyJj_hV znERF!>+8X(k`XjqTqSKgZEaEyTODj{=tGN?8z6N;VruBmQ7>@bHX0lpO!PQARomus z*%4bV7ETiK!n|B$RS*&u=CeGIcaxD(Qm!idnOYphY!_c(H}T(-TG=doaQi&MBb!7OLZ;ek*=?n>hRT*2_C0xVww$l zY>-~OAi9#oLurvT9>?QgbM)Jig5QNuMn-0^&^UOk)e-0i|pp>dRY5~tM&iDvophj8a|g+|gyMyokJWK5Has_!h+Z^nhS zzClYn=kxMoOihiTz}c}qYy-Kesp-OajUa^Vhv?{c*LfXv>b@N9? zdz@WgTU&#@h+x*dLPZtaDR6|tsQg(7N+lmZe>ViGR4n(?F7^l(?I1|k6Fstmj~_ln zdlF1}GIB28dc695>+JWImTt0>Y&M4_#g(xt@(XyBBD%WNZZBVM9?U09f5Q_bR1{T! z(nCac&&)fo`tV&1*4L5}E-mNTYdfpM0}aJDy-Be7FGc=^XkGXIuV7sH)#ul2DBkco zt<`pSKV6^qM^It|Cy72><-^rq#neRV#@ZyeJ(Xj13|0B)wz( z(-rT`+|p;;v+DiMQ!#(;{@qh_6BNE*L$4AmFTUS7$QGXl7yYJaDH>(C-^IcEbm^^{ z==1{E6jbUp42_Ku=<)2?v**~z;;|7tKTb18T^3H2k1EGD5>1t-W@g5P6Z=|GqC(g3 z>BvqqiI+sG@YAPPJL38M;qc3^?0k~Xv{@T@@GcGoAD%_V@`YLQ+yVzrI>tO5Cr#LQ3kF;C_e&N#(Ja*hM&Ue!iEJB`kcWhZB1p_V{H3Qe*C?yO#~`D)Eu#bfjT{c+D3okZ^OgnY;0_9NC7_+)W-pUdr#nGM*%4psC@Sm zmlrQy=s+})@H{su9*DZ4#|NukaJ=#Wz~;hO74I3Pv9WQH z^*H6`<|Yq8ZGF8kK)tQJ!oor{Pr-bYrz(@L2+b?C9L#3hbcKyedpBP{v5a-uEHGJQfo`mYj#hY7T@nim_+Mcmb^7z3xZ}_lY!jpfLi9+_UvjCWB zK72Qry*;hhcHdMl{h9CWqRjFi*C{AaLfM*gW3>9#=|2-xs2zHlv@;dAQv4*{MOAtI zrBP=md)l8h%JA1~&IANb_w{4>U5NmY`2+@Dh7=R%y0?ag;^X5h8k?V-tdnKD%fNuW zJ>SWq;J(mB?Jl~zx%n_#Ip=+3Io~Uz}m{V|IVOM8b0h(ZGYimO~r>3KO z!-9v4>kH5rmy$1|7|GMu?8+#P_SOfo9<7g6J(ZL51kABz2q)&{;ZEJRH+WDsJ0o~` zc#;8>0b&*s7Dm@zo1626RDa{a15$BuakmG>i;d=?aC&pKYpkAHvhO%D(9?SYgt4=? zrw(no5!&)TAt6u6solQvp5Pp3Y;5fQ@?A+gTiaIo*4CbP6>x?CRM^?s72%fR;^Mw*caIY;5fJA3nT-G6OK(i_I4h{OOI< zXDmWhtexuVa}%pGGm3ZF@;_460;r^BV#0wkm!V#g+pmLZZ>i8?r*B0UG+iW+C%go0 z%v+DM6Jm(3<2yR-P7Tw|!IMi%W_=~E3I;FXS5{VbmD=j(d`V2aQB7Re(?fu=IXius zA_{i!&*in|AVcNyaW}k!;{+)mKj@b z-(G}l1OFc!8cNdr=Bt{ogVt+S+;PCDzL!;$X>go%6SJ?I_ECfroVoR?y?AA36BBx? z@#@O}YU5hjlw+*MD*X!do0FjlgN|0{o9|^dk5ji((KxYN!ghA-_4W18{+@^a?QnNl zza#d6+R-!TR_zk2>(N}+xUR0QFI-%vpp}`OXJKM$P`9q~fexa!sRd{mBFv5S?(kE5V`M3YpWd?AVxtxy&x+qOCjJ!0%hl%+(?QO zw6~Sp9lU*7+QJvRFXG{eLhi@Dbg97O%v~y;kCZ(Mr_i|bzC$01a8JZM#7$m+oSYo4 zCH%o{GmC*dZAgTw#b(#YI88hmRdRKX_c!4HfBTs#iAH!h`-Ft7<|?JhG}GN-RXWXOY9!cQoaAWth6*A;Bx_Bqy9W?!MXYQW;mD(#X-<8 zV|wzt?RTlR=c_{gwt$5GIV0nHuM!(%!oj8PFZ-tC7f|!9i9? zL|>mT%Dew^8h_aw&1qU+GghE~0izbGW=n*Rk57TDz=5|%mHoU-f0h!Xk-2&6@$vCs zrSo>AeCA9#h7JHUL%>c9P%e$30p(dfT^Zu|-7QL00JV@E7JhDhy%WIdH(5d82+Sd$ z7Zw!g#>dB7%(X?SEiVE&;kq~KH1vkb{kvIjMjet>`x|X3`~w0EAgVxb*RCQ;2B^+!Rwy=+E8VAU3Ta(YLU%6$xXIwCeg31uC|!0 z_hF);d3}cvdv0~LT{%ZBm1FEs^@{-(w9wf$@rym_g}rA)jspdwhOdtg%at z%D}@yz{j5fR0gm$LGRuS-Gn;i21yACJwO*y%n{q-GJ1M61b!mNueN}=(JwaZ(|hEL zqZ@GT>@5HZW8i(@ty5D|k)fdk>J^T6CB?;c0bU#IF7@dnY}EjsXIVu>;lhGRct}V+ zq>;?RHLnYJMzEn4(1I}CzU_0J=lNU9vC1g6ra_=rBCD$SV>nImD;!tJhT;5WD`kf( zzaA*FH=diBX+U=F6k0!^mv{gn3<8ZqsvlrE{59~wg9imCM|*`aT-IND(q+wG=BeCA z!-0jofJ>nRWRM}mD!V!KLCZf=FC8uC)eJ&FszQr42xu**SQ_{!a(07@6?U`O!xc^} z_V)JrR367{`T+&$vI$=%CUovQj&M8ft!W~E(&RJu&jI=NCSbaB-io*B9YHO04_^Qy z#NVc)E6m8Chq5`eyF5@l#p$wR5;vU4m*BRA1z#^+))N{U`bPED*twVd4ka~r=y-Kxgbw-Q?*Yytxf;m}w#1(3oP`QlM^xa=$> z?Z)E?9=}II-Xl0Wn{oK7B{|$8I@;0mEz?0td%*CG zW+igUoi46^e-iLgeOWYt7R?PvooVj1vf-eDsdF|n-#;9i2Tey-R8%PAtwHzR0&P$# z2WB~tIvjL#>FjYg0@#QsDB56oNm2K8>%FmEzo#T8M@rG^qoJX#)V{)C5)g<-(i&j0 zYObPNF9~Wxh7E!E!|_zM)?Zu|#?t9iUAggoNo0@UXM#j(J#Yng1st6U<4K=8_v3Tv z>zoNY8-L2-fsj+FLqS2&mG}^2e}Dg@`04A{uYZg*{Dukx4AfPRE(i*a zT&=2ikgk$oi&5`F>w#FCgx|Z7qKd3W$pEmMz}uq)+wXEPqyT3N9b0oS)xZOOdismd zS*c4ZdG#Xl~YTe0Obs z@(tC#Gn~O7AX0Q7mIfh}dP2BD61w6iqLxmLFgz;SFRuv*2)vjMosD7j`Ju-Ss%a#W`(9S^t??$ z*ZpM$PY40kBOmhdj>3NVz~=9|S^s%k-kaBpR~0j0526eejfRz)GM=W$LG0SeVwi^r z0#pLAL2=piLG;mx)nGmv0L}L3dtOkx;S{}rrbQnin%f}YUco=60TrV>p9GR6Y1g<% z-nS%E&eKAmHNu>|di4r9bu~e7(vv}Eg7f`EMh5q+m#Y2lz<2*w_(B+ohWdg_GioeIR$VK5Wyp9D?IV2L%A@S{g) zgmga8V1NwU#S=GNXe_%jT0wk?h^cm}(I2|ND~1V5lHh?y40D!5trXXMF)(Vxy5*djhim8?~G#g+}f9#+{U> z;!;5CJpyKy$8qKDuVV9QNYZs62{Be3zw`F-LHdw|-b?~O>ueT-tf%EtD3W`&*mF_| z-e{v*O@+qi#iXTY(@o=zo<>=!kS;DRUZZUXxPd4skPDxtIVtsEFosDKyx7z`-tH9C z38;e}K_N}5ZfCLQz`5|tmmedtPA7-EkpeGy4tEwY3RDANZ>AyftNA%XKW)1`Cw*Ex zXViYE;i10uq+@oHJE;0ncC8-Od6ny53JWJ!Rsx{(*AER1_4ctbuAEWbRoW`h2%m~j z;M!d5U_^NuIm8yskIH%79S)f`GJ)3e5dcWQ#5%^t7n(@8gL)2%&>l%vDjkmus9~%3 zI7?Q3=9V%oha=YwgJZ|cU9N!G5;L`88)wvU+;_;WRQzR^jjimrKK^LGE z&@vTRX2zr-M>o7(xFAUFP0|nQ<7N}N^~COgb~Aj7<e`DTCe z-)Ukw1$?!T42mi6Yt$<(E#>ogB9Hlp6=WsknogmFgUlPc96ZeprO8t-oeo&W05kt?^#(@g>d^hbh3P| zzj4U9th|GRgLN6wFFb0H8MryrYqoo7Tc4JXj{;(I_Ut}@8rcf_dE9cR^&lvX6R z%z^vWhmCX_f|5EpJ^gK5Q3W}^7cXC)bxqTHxvK=C`9=@4v3Nehub{Q8w)pu;{2~s{ z=M6Sf*WW7-0e&Gz5o&D!#eWP-`6T1 zt#C?#Opsq(JexpWVbo4`?)>?>jt*SNQfjizT};-7NO*np&O@ZXI%%Jg) zH^e@$FQTm4;{$>I;o0d)fk`(FFqnuq4Oz+)z!x-yZvkQ>lGsSh%41g?eMA;oJcTj6RnhBL< z)o;SNb?a6lkj5nUEl5DbMsNopZ!*Z!Zg^vm#8D_{pdMAZ?8d7PKq{{r9lZ|7^~HRg z)5b#gO?NfuT7i--im#@QAReDMg7^O9W$v_}`F<5{^8%YQ0guY{=QB_tZ!lcQIJXioBjG--1ge z(DqRxH8We!rkZ1K%OlVIDE)8SQ3TwdBXem z_OAQ-LU+nD5UK~EhDSn$l$4azhmzaY(Gg^5Wb_5FX#rH3h@(?be*P%UQ7o>2JhIhG zm|fv!BSCssFSXJ2akz+!YlOHOv?GG9qrQR`m9xjq%Uc*3Nzz23pP8A7gE|7?sCdo~ zC;^nJu<&c;GLWc-OKnq>hl~?mHi7A)IJ^W7wfiBcN}!6v_HDL0Iyy4vAD;`*C4mN?~Tv_mNJnM+LUIr9|1x9yww`!T)ZBQlI%=^iiI)($PqWsD8B|g#esf zT*ML-6of>exG$xZ$n6*u6m+daK@IeWqVVO($ydY+Gk6g=SPSXfv@*D4ZZKasw?9!^rSMDvNbqqqLsx2KAV=OE~{AF2EVvElv4kKPDE z2DSepHg-L*@ITs|wr0c;qYPA-SHejXp+B}j!qvzg2w?Mtd?4U!Wo1?By2mWY|KLGc zJ=*PSn;RQK5Ko(s7?U4*VXAq6A|Iv|6c`v-CxG;<_3%CWT1`K9mFNivzZhNunXIco zl53>XU3u+`_bt!EUo{?rpe5LBPCbTq&j+*!tj_g65I)-#D? zG-w|lAF+JvZs|6uN>{NmHm%A{&G$(!ygtJ&{$M==TqkwK<^%g@lG#sFFyY`7xa^v} zaCWBV=dWs890mAPc`z3f$>YF)h|jQ;$y8D6x9B~K~*o(wb?*&t|mY#1;9)LX+EU0d^7wN*sj<}exS4sKsd7_$6B%c^yH{8 zRJ`bvb2w72xFdXkGYA zB)2UMXbL&@W#BJBz*xTPo>h^>5I%s8W+3DC7olPB0@)pD7+^&J3y{tR(dPz0nMcYp z)cuFhTyy~y2(CTlJjzgt zFGBr%4CiJ85J7!^e|W+=&{9yAE&!zPg=SwLd>^pqS^Zyr%7=W232m>|_RP7-Rw?j#$GT=HuZ>;+AwPF~7QXkjz8c3OVq7bTl^P zI}m9$xx)K2Y7BAwN{VEQ%O3oyZ+)iKF*29Jqi38eVQr5x(b}t_3z1v#W)m5a@VM~t z(*t*7L&LBmjMkssR~t|ZLZ1aQ72m<~M3$3bD)Ag}U`ht4J6!b>0ZJ(?*Z0|9Y1?Y+ev1hnMRHK=#;+k0@X3XZYBEv@cHW=KwkC{MTQ#1eBuEkjQyGK`fi5pCrkWfMFWYY=sW_!HCVBQwV z21TQ0Y#l(vHz*lkwYpHIfeS88kta{WonK3sB3K`){*2uN=nPm_b0)>AHiP^5pfEgE zRV9I5bz*7h9oN_k3_uAk0|j3|H$i+ZK<2bAaK+^^vup_%-&vs7LzP=~NifiU5bFZ5 z!~dP8gPZg-y^$<`v0JaJs;Y)4gAPU1xD+hf?z$gF>CgpQVdDQTH9|h9M{FBs)S+t5W z29=s;-I0`DPx1&XozFBB;~|S61YMld*u#GyfIC^UEhw4HpzUPt#sf?dW+Ivfavk-K zAQlu9L??u(<9@zyMTF+54;DHIUm$mYPKE-@4zOD~fNOOECZQWaXr16|l44?>KyE^k zLFquUhyJV%D5!4GJO_XMLi`l#ses|A%?5GJ0!hU0_p>Io?TD*U-SvAr;gy=2gB1UL^$-3@{pD zf=f?p@(Ae&!2*^9c@>cQy)?HSthLdyKwi>ClxHt_3&Lm-F{ygOH6T7Gs+T)g5e3$o zToZA(=BW7~)D&1qq1Xw#x$z-RUS`d5DSR-P7DdJg#PrPfY5ZsX zAvEAV{|SvZtuf!w3;|C=+AeBE#PVD!q_vjFA@$YC%L`v7qQ zeUB~(>L6a|gL<+LO+tLd7{VSQ#xH1)YyfIojFf^6kWwe$A;>vdYX=7hs+BMPIKXPo zPRYS1h4KWva1+uz^ePDXhSK@*@y^@e;AU9I58y(83QP^{Do}%Jt?K2^@0{+{oFN_@ z;8&1UMCm}%CE>%7jwv98wOF{491J+G2KInmU6Db2mo$-OtcfMj%o_o*% zzH8(H0Vc8m!*>jhtZTH(Td2{a&lb~~*iOX}(srW3=Ln#E^V-p1Q8ZO3i+oCTn zHde_{H0wf}M8c+b4t3-HeIocUFvaq#6`8z39Kjl;`SlJU93lR`x{%wFte`RMA06EU z%QCQ&J=tqu6c9Y#z(ATWI25N>ZNaaAm>5C-d<|&y20#CGh}1!lNuVlSgggTo2qP&e z2~J?Q+87ejP{@e(N~NRf1qW1;fva1#8#R=XKjx6k+b`;#-5>x4nvAdDiy@b_6eD6f+M`+&e3x2Gbza`oyf(7IBf zU5tESPYe1aD=fm!$`Aoq1%Xjii=ym+^F<2XqA=J+k&FhvRA6-X{`dyg5Jx04P3wWY z1JI@1_H#JU>tiPFFS3AC(alpl0G3W@^EazJfopC?h*nSy+(|*9Lz?*U?Vpk?N~L2+ ztDB#H1(2XpR?T1Jua#B_Al}Um69wKokT;&BJPF)4kN}4W@a$^o4^{!fgXCNDduyv6 zJ~m!G7!8oLLx_NSWJ{XVgapJ}h2dcL4 zHG05xULuGRZigkp)8lPfxYS7i;g8_PeOm95a^d0Op&D%&pZx~4*}#|>j~V(bRd61h z>7)G#J3xCspP_GQ?BH-m1Lj5kKQ8ZL+~DCM zgOUwzn`Dcvv+krv7d~rMmCLW&Iy(A- zl#RHG4YSd&{_4dO#a(%vcWSM3ma7d^jqm>c3$Tr|HX+U~r0W1?ryit@R!ysxuV#7~ z*;1h+CxA{$VO4!`NRx{x0D(dt0Ax)WcB%f-_rU}eVSZ1{hd0@G={|@7-78kmL(nMA z{XtC8%1-a%e5i&PXWm@X$Jswy?(>|Y6e>_{TQ>&m3E>D826H{k zKPadPZn^k(7^D)M>pZ8AT2NCiCeU^ z5Um9JJ3X>!i6a%dVU;g_78jQCO|Skj?PiAhO`z;p$ov+PNLY=R9yka_QA z^h_t@4v=OZ8yV3;DSZRCVA@UqL_LQwn7&WJl?FoGBy5P7tZZ{jC>`7MDqDVW;Uklh zsj;sUL7E#gEd+=K1`gV{Fh-S)xfp9<&=4Sug@scU;6ou^yb#`HNCnByalB4b5PO*F z+72AQ=fmXCO|BGqEd{gr0x9!%Nll-8A!Bru-O6?kE`ghVzCIQw*slH)Ab>5nGjqtX zkr0MzQ4iXBt^>9T%?HGQ2;I$NIIXN!Bi!zU`EhZYWy=ZRXb{++z(8aR2x1aY-6{EA zpqh}e5rj5_#Z7VEoz`VfoL}p=h3TUt{9sB?ou@i~SAVu-vMGCs1a<$R`T2L#xKLe(qBH&r$OazkMd- zXLS5*Il|#~sPEmo2Awfbu`tH)y`#eyYywYnlcXwl6^)&@%b78?Bd*ZN#0nwCtdY{B zdl|{>kQnV#741tMOICW^qx)^=s4j~a5P)Ho@n6p9JTz*L6o*#2Zh-r?KnR*uC_0FJ z3((zVshInhA+fs9d3P zu!Zd3zkI&y7^W;^wI!A5>t(q)8Ky^v)7ZXGZ_kDz`;aLJBrISnxs@FeTY{iJhP?6& z4KTx6g)PQF)AGocLqGy`+0#+(1R^{%^wHlmhKMcDs|Xb^2Cot3&lJD<>p~WV-lHM8 z8_kPWyRs>pkomshehBAe&L|U=(9mbWho6n2#P` zDAAq(Vw{#30ZVshCsI)-rly3)BWCjl&)L9m0*p^pDxt_6Bu+p91{;sNVW$HlU>ec~P8)$U(4?{f zCx=7A>gf^iUVyVR{#IDJB7^P5#6v_$>E+J@8@M}!B&doLYimKk?Hohu2LXdkVx`Ga zFs<--A3I%huy_uy36g>JTuN!0Hnb&Ue*FOx z4;nDZJcVa~G(`0xY_B zTwL5!+=deSUY=G)m*2T%U9s;tlvmoq0wq4#S7bNJyH_Zzcqf&TCOoF|gdCiqS#ckj zBw%9#z}NyE3sSql^o*F51+Bqr6fK0RT=v;f2)>`ldx_N9@CX&B zM_f_4Hk zDk{p&87P;@FZFUx(R)d={ z8TeyJZq!rL(+74iM(}*O|1v2lshF79MC<6t2o&lIV8nqw#E*r`C`M0T|8AP}?42Rz zM@8Z(JS7A=r$<^)8&QPo_Dv?RB&NKYr8Y<_MAVm-wc?uT#GbUw>T+6t-iFIRGzgr~ zX!HUyk&j}uKCV6oz<@e?sdagjmO8@q8QIms5b{~XO#?f>vnQ1$F6QSwKEPjz~Q#(;pz z)6qXKo-OcRRb+R();AjaOELQWeeu@JU{#vQk&$=n?K?1L_K=AP zp;6ViUeo@W&VCNAORyuB)i1*K?8C<+?ll#KKxAMWV+nO@uGTCUjgz)KQqcnp_f@WY zX@ACCVhi+%HOBksTVG!7a!;pHo?;M!Q4K`jKKDLS>fx(3dWPU7(uRGrr2zaT^mlLcn>!lE?C=!f zqS9wbb^dd2T`2I2XJ+d-0#1gQzvJkVT>5viC_N!0#q*A1z1&DZ@Smx65fs_-!!}a5 z50cu-QID8%>;~`nnQOXxsk~{qn9dJX4?S<_k(#^>M1xTc1(muL_zw)-s7bB#$4h00 z@2aYeWQDTna~Z8Z)A;eiY-6^X-lT?c+0^|i?df`Khv{us%zwWQBQa^|FjOKHsz^*` zwyq-}e^L&|@YrLtqH!!!v4{Wh0xWLLQi+$o&vmWfNIPMIyE=s-CDC-x%bri}EP^9p zq|!O`FLU$9NMUF=M;OkVGlTU%_iyqs

fmMj+|`=jN%D%?Mc=Wjy{K0A#}H#*=Se zex!+i#`)Q9NSwWWka(^Og}fVTDNvIC^KO-JdCk*e(^OG3g_RvqfHq{+W++Zkyh)K{d*?in>p|D;Qv+pOICy@!7d1rs{+pSF0+x zn6Bsj@5c!eRc{zK<8;~!va$bM}^sk>vmAL-NLY0{B|BVL} zS?VXjpy~JV@m5z0vO6e+B;Tn!{E6fq*~O=|FfI1V8TZ_YBWk>vQo$uZm+D!gAbNj- z2+czsoy5ltGVMy*#EG{XbIPL_93}B+m6i_!>Z12}KZu>}tw>h3o>~9TiZF!zK!)(3 zZ>N)u=R6vmCC=b0?C)QRCjJ5G&EIbtD=62RSqE_fhHNKcesdtWM+3;MiX6l?( zf0mYuPObC=0Jc(oNkg%K_k!?slJNOmDw)V~Y;Q$~eoP_a%q3YctHO*9eAiO-g~Zf` zc0wFdUL(U3m!fe~g+*IUy1!?zyAUGLH}k)ZL&ldS8Pwg|R%tp}gU^Js#E$+mSST9h z|4$lapm<={u%fRrn!d*bFBB>u=!n**d+m8t`|*E|4YC;lY=CVdU#@)YJC2n=)&^4T zpI!a$Es_SC60&BJT(7-I%|e4XaQ=B*$Dgx>AWXZ^aN zlO3d~^f!&_v2#{xLv-4ty^Tv9;f((MXBrcJ*UErj3o|3=z>L704y86idLdmtFi{}w zkZ{}F06yEgUhU6=M-=h=Wl>;D^9S)N2|8-ES>TqNp~J|x9KH`sDg_Wxbuf=Cr6`F! zjpY53em9m5;306syh5fXk!kf-Fw$KCu@IRY22a{QMp1-liRE#SSl<;(tljF$g{>w!A}h8b+?6M{1=E-@1F3}Nrzald7-edW<& zsoHnnbgCbm2SC)NSf_`yy&Q+!JP6t~;5amx;L4CD3n-8XmYI=gHxC*XFC4FeHVa1P z`nIm?uG|k}2GDl~B^T6%{{S))jNum; zcx{9>5Sldn^~`;9PC7aj^Mkp{IA)DfPni75{wdfs zpR&1E)uBz<*e(i0lVB^9gVO|x+HDhoyh}3JDg`xm}A-AJ~H~HI@`$7ye!jl_E-D!l4?t0g~D55gq+vzvAhk( zcm8(i;#>6OT8)l%JcC#?%z3xSZ&CJhyKa1Lgl{< z81#q^;p$98C3N@YMq8GSu*qeKi(J&STq|f=1E1(urQhYdyVvV@`*-G?-)iP+e0X-T zY_8=ORVl5}TVJbxAN2^Fml)4>4$WLYU~tmDjOo=p-lth|x@xk?-B(2Y{xE)7VPsf; zt=vlbgQ9kgxk=3FsoPfXld@LwU+K}!r2;aGFR^cxOWlBZOprV5)E!412B_KDf0ns{ z)P;yxYQ<(g;I=^MEf9H27t>-4&iEZ~9kdy7fZOR_LR^v`-K&M$T=(|bc}L^!mtp?q zwQZBZu~&%CHAdq?o-|YnGlguXKW~k=EaxC850Ob73($TQ384nT(U6={btG|@$o(+M-`};0f+BzDI%|xZeWMSvodQ-N+{H`*@2$vy zK9(zg)+2mr0M!x2aRH{m_gqehwcV})_L9$kywy^652aM7%7i@PW3F)f_e@vIc6C|g zGq{^qLw@>>TZZv`c%DOkdR9NS{n7L1)Hy3R>o2kN9$<47myNlFR8HG)%gMBVHN6wg^z1cQF0w`mgEiLm zWX1}HSHZ{CW$E~^SZ435mDV2S6wOY2Oh{xLw~>>jL;SRg069A^Tbs1AyE-Z@HFXkZ z6Q01l)8-GxJRNZ7n{oMN;HJDmtIfZ%XReZEaZE@qMoEUB?MU!lRAe6IWVL#dDlKBR zkVnnijA)gn2gVu7b$>w*>jXh|5}b>dF7;SC zPA07-A4F#EA`EAHhpiX*ryI^VK8oh(mK;G}Zr17>_5eDC+1V~Ayx zB04SZ1KA?JYQ!1c{moxtm0VQ1*3T$(NDi;QECnDbU{OYy2zeft-Yg= zrn5QKSbFk%7_l)-0X=5MB~H{KAJRE#GXc6sn+)w7ZSI}IWeSJgLl*u3?fh})l+&l$ z|6B%kEu>LAAW2?K`O$5RpPdo|1>Xn{Ou8W+LW>I?iWcLN;SW(!nFlLNuJ-FhDI<;J zE-liRrK3ir<4%^fQUe>^oh;W+YtVL?jUDwOW44ZyQRh5Cv_ijBb zWB+LUEC^VesZd#gIv9i5nDD~O8f8l6G1Fdla(DotakjOb9UA!LW>YX#Fz6pp@`P6B zUNp$=Z;|3)g2G}dz-t||o?VBknn}Yf{?hX;N$;O%pFPk-djT5>Ps1thP^l%s!Gwe( z-5BoN^sII(s@(`QD#cYJ`X`wKOjYw~pVHc7tkcg1*BjXWo=K%LChckp7^%GlV?ywp zibdsvBYU*({))4OaIoP?Ai!MdvLDP*I-8j+b*3RpSKYRzc0PXjC2E(|z3$(=%r-|E zgCq$?fs{|5&LI*mSSe!9f++d39Jl#?)=L?BK(xJ&i_1A!;S1bxF2A2&uoDtP7R}CE zC5`@{+%fk058b=OJ}Dn|HGB6r?|~UD`hS)f#SAm$ zh{=QU<<8UM7@AAQXsyVpgeUTV`E4QJQ+e%NVzs?OI7?x+v;7_?`e&~Hel?l;Wn5gu ztI=!aYZ04zE8*KDJaZ;@uF!m`!~;1Ex4&#Fo-O7u8T@-7l+gCuI64tansNoHNMPDY zsCzHTTFI-YdDlfm;`jUROaMyOg|WAN@bYwn(8m)hgp?Nf*0(d0G447Wd_U9k$RA!{ z_ozON&0ssuLRoYtpI@s!vMP?DCPzYwlMH!O(#c9C-@tsfWaIPD80_93GI+Zf|K^80 z>{{r!GDpu*R|+W!gtj1$Ps$#}X{6tkzTwg-EiN4uH#X;+KMq+M2|87^BhPjtg$k@_ z{lcMq7^4_9O7G1G9oUXzE>@%XfsR4A8_zKFQ4TcZU5bwb*OG=IxzC7rE(Da;jzeR{q{@L z!J4edsq`-T2GD37M_mv+s_} z@o&Sv?h;Z-p^TQwmNFXJhzf~9q$N~JOB&i{5v4+C+##i{rM;0*DWyHMwf7$HaTR{Q z=Xsy^pVuEgKDxW_>;BI3JkH}d&V<<)!Vf1k&wFU`=$Eg;#Sq5s44S;5=!;@8B~9s9 z#c$lsJ3XGPzNKP1G4Unx7k~g`Ksh680YObTXyDk z8|BXgc+dqhn?3Qe_u_vM5pg83QkeOao|$HE@@7SH5W*bXj!~zXoU;DDDMg`lae&tI z9_~_>+@@F0;{}>!c%Pqn+n14HD0=gGMU$wtN-Dja)_ICTGi`$4I77_Sw^NBX{bd$? z4&9d$cKC!vg0HMnSG4tr?8CdJ;XzD}<*I^+ph=CEU|Ju|JvTQBf!gtKs;^9H=6Ukcm1d|o2_*no8iuxmOcpaI zYkNs99BGCErRZ3Z)66TY<((gJ+O2+Y5ak@KvU9?Gw!`ei=aY2mMM_Fvk8;F$N4K6t zAV6L^;h!&pTx2s;Ebr;mn&lre0U=K)i5Efc0oamdgSR;tH|J3BLn`x z(4L{-4>eP_u@IAmq>df!j;p^GJz_+OTb^6Dr7I%iB7;IJOUKcR#BaPnwNe`zOMCqP@}?@#`i5fylTi$Wr&7SfPKyYnJ{I3r~uO z@-Ua_`Mq*8pRk8gdr}yn7>~91RIVdLs%v3FAqhfI(3MVC$?w$$%q%RweDP+ahz@={ zEJ%^R_y{(=t2W7H60ISL@@W$t;fA6`d~uc0ttAFGDldNo6JUPTuvR8N==n9aUzTT7 zVm}}A<=@NE@$qHIDq?5>lxD%OqyJY3m8|R&Z!cHwtbw!?r@|tWlwZLIdsfmd zDePr5>mr&d`cB@Ns?#g_=59z*K?Op21Bz9fwr@XZZoUK2^DP`nO{k}^%&fIa*`u=GVGY z1Ixd#~TQMo(yWM$JY=FOvVJ;MJ^=S3jEnxXkc& z8PDF7fz##2VjOCt`OY0xMTT+Nh6y6JRLmk$spnl{$tAY+yL<}@rPbn0uZ-sZ`YaOh zZX)wF#v>Z*IX|h)#x3*l%Ou%I55y5waF?~)8NKIkS*bMd0a*12F6VX8bJ7p#FJVUmK~u})O9JW_zbqmg018X}~^i+XXZQHF*EmS^=RJurk}8bYF57xeVR zedG@uI7gb1A{w)@dS|g`G}M-QiNYkgg^g?Dvq`ul-A0KlIlb~zZO9sS!6$s{*VDC}3T(YtI$W?3 z|GxO-2@$3BHR`?euYR%dYUz`wPKf!u4hl+QI+i33D?rHH8s4gn-h?4+{E~%O+Z*8f zN|FWod>u+Yn?oj%sXO_;bDDCqS)P3hXmwm9ix@w5#hRuiNWRa;02>;TY>WN0CSe+N z#us21CC$!E!i-h{Otm`W6+$3`k}zRhk@VT#rp~n#Y%)IR=MbXO%bumaEuAVgNKhwT z{y-j*2$`6il=j~onpF_3mg(G0eSAxAub%xx)8?;d26vhCuD)q0bJ9sc@t#LciTol8 zk&^b5#$~}}yB-la7dlZ}s^OKxFh(dgDD4Wd6P^gDH6dA5u+?I6`@kEotf_BI5LfSA zzQgq0^q~2*m3PvfEG1miwl8k`98M5>qVH!b>mS--p1(By?&54_r;L-H4u)Y(C%*UM znz@NYLdj!Wez)CucH@I1m2O0sM>v8{pIJ?pD)*V`rPxhZsl%LGB9;ct{$h(aWm)2q zdmTjMF1RBtH(DAL>=*=?`B3jv8s}sqHvU z2jpqtF{wQy{2QA%j5NN%U7|SKLi6FrJWae8`*`7S!HNO$!Q9)={$LGmzCz78cecGupXGHg;-DZ623hM0ULs zA`C54qhBSjnP#M68U}XzN8F_8b-^2%{MiC0&TM15zgF~Ux1PaL3lg~5@dy3s7^Pgb zoSC|o=tM_HR}p_{Ib!p>0Gi*_N_uDrO0Mt4!3#GHA&F;CeZ|(tTFh<{qZ`o*(7(K|X4$H%vSuu^z@9<8c2VA6VDN+qO2jPTg~_p9+nd=$HvkTl&cLP0UmV5@pb&`l4!s zF8OT@Q)S{fEk$MBz}r0-uE?`X@2lD5887~3@U(I1K9#%{3oDg(RipN=jCRe#4E9## zDNL@}I(@&c>5`eu>$vZO>;9byCYjbtCsL6XlT<~W>>Eaf%T6s13Hzci;_Lb7QIORx z``}QmmqSm^s;clxm>#l|s@d{z8qwZ-VD{Lpb98|rJ@S<{Gcocoz1me#+~gCks)>lX zr1IA_KVC8nmk*@blloDIj0{hBdwF%F*8=7V)plZSK$zNPC4mb;n5wDD+(Sn2n>_tH z+XDiWPsaSoT#y|dQC5~edGe%x%gU8=))OZTSUjzVrdpLP%QPl8XAh@3ml-m#c-lLf zFA>|i^~?Ay)Ns271_%9Rs=KYo3>9ag+N(>D2+O53vD4|mKaX)CE#t!d=^?iJ_wVmV zmKOePXRq0iy!6d%XYhy$^vg@x$2#YqXL7U7{PbUowvwC254Be~!!`USzhXPAK0sT! zjo)eOB@=v3PA2dCAYF#F|A7vS9Z@Z$`Jrl}gyf(mW69CH@BgGoj>nUs{Kb+5`k76{Rn< zO049doa2k&E{pVq-`=z>dFXmoewgN)<pi@8#ZB;Mq*A81Q>!T3 zGS4StniRyXDx?n(*i0bH?Tyw-?*sA()QMO0Je%>}dLPj@wTvpy3LGu3-e{rDIK(zB zDD+Vat!3n;9-Cexs|Hx$BLI^fP|)GZpdohd+}Vc!8veuVWJ2;;AcFfZ5>V82LD!`5 z(Wj^vy)-|*JM&CxCS*oQy9z(kzaVwzch*H?mhZKG48Ru&eu?`4EZ1!R9>RNb6(~6_-U; zsyA~wnfPYLR$i{iaFB@ezB@N*rk`b`N?rd>G{QV?$FXzU&cp^44nPRS%`7$aaEZXc z(v9JtHY&2BMrZlV-z#Khh+HF|3cFLCE$vtG{K=(@qK{H&%e-YtRAP|1p}D^h2ZYJ2aTDPag=UAyvm@?nE>|1xz@@qxlsscNpXb zT1eHITrcGr*!xKHWIavG8d)z7?uk$Jz`ve8c@k{3{FWK3tNjLV2xRH!Akd?CyEshv zoF^hjDtpt^Qn`hG<9CGN%8<}6BqGDk4m4_h(Wc6-Zu-|j+M;s&_;shLCT{pYk=2{x zOed#ArMjuZdl)s zvfz0aN1WM(vnR2ho&C$?(vQJ8|Aqw${`0sR#Pq;F=snn|{g5A#0-NX07U(9ZmzmsX zJso+9ltn@O8LHaut&banwUX}hgTTsvkW&IGQckc9+p80!tCU`B$oe%6C`(LRzisjT z31(u_Un7djG*?R5mMLysnQmu|X#Y&N-m-BGXT}wD9OY+EtV%G?xpBeEj`v=zb9@f+ z{c4)(&59v*-CFA4Z#=PutU^5 zqcG~lfU+s=jX$%9=cTi+Hcq@Y#lCuVDB#=1+hGHhmqjqEf1(bChZNb7)PwV99PYq~ z$cP9=R0O0KGIM=>mMzz8U6VCPmeVq>Iz8 zS&%kPU{61uP82(=C>>XM9~s%-QQMgU$W2?R{P$OUNlc+WLHY-ff&t`egZVx(rgdqn zNt;c`q)F8*&L%j>1g53cBo`uaaWl;rUx?6ky$F~B&`UJn4NQjWH}v)e*Uzt%jlyEg zr?o43(@wwweJ*TiVW(@rDRKPNsXG+fg=B$ zRBeMvK@hOPI}IHj8(KF61@VJUO@LCH3q0zgw&|xchvsJQ_3ItKV@8HY(KpWj#fuM6 zY`!ar{sjG777n5T_5+IcBbEB32^`1LMZkgZFhANek$TV&B!`#K0hsbuJ#v+>;Uf!w z;JSR^0AL?Hn6Z>SS(7LPXAl=gIQOF@~MvI2^{q00Jq()Z3(I^Ht6N%E0 z3Nq5W7EH?_O-LYzp$oJvQ9O2R8Gx6c?@VB(ifE~`_UOfn>#-R8Wyuhhkp8g#q9%)OYYARfh`MfQuN{~n~>X# zwn&$C`IH%!eU&Z?(c=XEz@Jx^rxi+n`P9~kQx>mA^Alute=xuD`f*e9C8}Xkk57$5 zSV7OZ#oqwIbWxi}L=$ZM3}@~X=-vFFOaCULt=lpHh{wUEvK=dZBPT4Q^n7RHmDTqg z%_^&TR1qQzurM$jRfMlp8E&WrbAejl#Dpr?oFx|#*v>%QejH4=M3VC*tWEq|01X)Y zh*&)*DMUiDA8`f@H2gbZc=HN(CFx&}yUYK}a#mJ&7`s4SoAlu728czl=FxYy)>e|m-CR>920ffKYJ8a6GmTDhjU+{+_2b|2cHGX1q(BB|9Q z3HE-Z0SCOe=uXt9+K;oQnIm3D+_|UPKOkdu@rx|7nU08Wr(a>|#GvA@rmGV}mk2d# zbVgkW>V50Jt>#y(AFK#)oVa8Uqa4z|0h-=sjSTpjkV4tEBC7RTy8CW!xui7!!k8bG zryTg4;j1DC12!lCDF(gEpK!?tZ%I%N5j@fGWV}aPP0Xm~fz8G4bv2c#Ol)=4YuUFN zFJ_1ltLBn1;tadI^zzJi0fTbh(%un8k37YEhYoS0o7F`E`vj8Al5Kq_^*wStZ|uBk z;=mcjAkyR$$G)S-zuTZza`EaS=Fw`0k|y(k7HK6L{jDR^Eqfir;~5X!E^~j{r(-`j zR3NnGLHl%x?W20yQgq4C3qkL0#dGUr zS2GtoTq%g$?5=v=XHvD^LX1NUTq?K~Yqptwsa0zeF-nga%FGxpqZSBv3zw#H3UF>L zcPu|vod83DYle3FwL3U2i11Dq<(}KUN@sUUw7$q$zi3P3y~86C*q`w=)Bxpxs!i6( zA@6A4jE;v5Nz<`rK3(wg7JAmqRZ{`t-UG_r+|~x*y?#%mBrh)w>Ar@r>>(73fJ++^ zGp7YmYcR(dmp^efimLKS0+=cetUqy8nuNp4Y42@a*2B99A>aF!_hi)O^C*+U4RdA= za4qe5XOFTwSv8;#z)^9$yeB;~&zvFss2jCsC)AcFK5~u!{BtM$EemH_kC^Mld;PUF z4~Pd=(|q&YsQsIU0gPUBubZoasfPAN8}?N+V|$(B_a}xp`?B`VuBT?}$O8KN8&<7u zrf+sE|HfsvT>dvSpTbGGd?@Yd3G%MOmQC<|v1cwa*+UaVb0ITa8$Do*<^w|x$`GYI zw5^#Fa1w66zt{Ht0gvgZ9rFYaHfQN9@@nX|0?as{fdEdJ+>)fek-=y-;^LohK$6W_ zPRV%}&2WCMX!ddEzSb2&o|(E7g&>{`sdnE^Vdn@sSB1l;i3x(t2!vKGTeE8F!@<CIOo!tKQ%gB8Q7l`Z~y2XI(CEPaaNK7)6u4sUo^)&i6Qt^9tIqxW%V2#GNUys z5yf=KEz#v%c6#iENBoW7g}#HYSitOdOSW9b5XyCUR;8+ z9GUQgtohG~AEEdbAnn+lrx!=s_RYN!Qdx%Pt~GXXZNFy(bL{*++~J}(KRrq#e_nIm z>NjI(?!mqdZa$ZCW6`tSa|6wC-1!_v*>3?aHUGjsARF_mTRion*4Eadzfrs&T^Fri z@OH8;uc6^rRq&0Yb;D77jk7bzyhAgr9?WHt|D*H?u!sFqWxha{Q8f3bO5ueTs$2}R z_`3g@qimIs;@JA9_=Xqo(yhMgp!-l^cFE^0WhOM9yr&6PmT_nIHs=NLHI0Y4obs4$ zf-Y_&9GsCNk%inNM=n_HM5ug7KV^D68FsFQu9vV zIWvN}(H^w4qDq;256-gJm6va<9#X?eXE*iaXt{>V{IF6K!swZpPNvf5^sKF*6ralu zn=%$?3l`DV)8DDZ`Rh{UwogsAwtJR;a$LkQZ5KN@Tb;Q0Lp#?FEvb3nM;9}kcI+ew zWp^OLDbOpA)4UaNCLkk)OQAD4G#~U=PBmu3hiB>qUth23HR-MVI6iyO=jChwg)>dO zcJ2JU1!QO^xY~b8aP{WT4>zSWw8&1BZENpfGL(pKR=BOj)KR*G5Q=Cj*~ zy9+>dVY8-0UF$0|@~%4gmME2oE1ss0_EDW&k%alA*PUjsh;o?lkdiC6p|Y2V{XXu% ziGe1}NL)hLWHivFrnIrMOT!~0Xt1B>-!o7!$FZAFkG>Wr%rM`|#?P(G#hart=XgS~ zf6hBpDv_}N>MBiIc#JtY^h0^&wO#ZIf(Yu>Qq|@UV?3?vf(2EJd6JuUY>fPFOi8-< zg^jF?02sZQt&;_didsiOMOM;}0!b3t$qp*jeMgVFABtQr(6~(}?8T@N5xSkrqC~uw z%^8l^$T(l7%MQG!ZSZB)s=eX@wJvDbbqf(cWHbeNcJaM<#rRhekgrgKgDN*6^ zof4+<#PCj)zZ8lR;}q)}^F;vc+-;qJgVfm%DoqVXJCXb;f|wmIa$1ItbucDsy1t0( z;c((Mw!^Qg*BWeNV?ap(V8faN4_IWSnuFPp^NKTQY!nWV@3OYMcD7>I95_MVR-bS^ zqP2$yiadLK(7cPxXuy|ym@b82{7Wm{0^Cm^Mk`%Zn|$Q4rpZbDYk~HdxI|)gR{O=L zMYJQSDQQxTzi(rCVyzdI%1pT4HJ|0}h2LIVZ-**wV3a7^ieA5dO*r4Xw*-kh;aqHR z3n@UYiFIeve1X#U_PS=+V#}}!DTA#@aC@g{9 zOcs_h`>M$jWvxl{E}9102t#Vho7j`R7UxGpHzXoiRPYKKLwYcr0XmPrLzG^rR*!V@ zm1+M4rIi~~r#pHz<4PON!+u$lev$?T2Ht50H>E2l_#nKxdhr>GlSXRYRHG`bI8l*s zrc>c7m%6+jW_etsOQ_p=Egg@qMas|SRrg$CyBH(v2XxYx7|iR7>Q+T*Sf)< zjcm7uyQ9z&YN%o$3|&K-1$sLeU)Tj+E9ujLiXRYg|1U5t7rNSh3=#&!lhw%@ z`3{Gal#nskt$dlBDZbyo7mL3aojmbsvxj%5^!TLt zK)mwblpz0PRj|^VYxIx#F;+$f!`7dwx~&qsjmE{gVG0b$iQ!F#HS&2Pi{y-ZU0EWW zmp0KBzI>6I-+7Am#uj>E$mGf5SAvFUJkc;m*o9Icuz!0YdfSXgJQWqaF>Fu zjP>;nr#mZB=-&MnC!r5tNkUDGysKt?n>fmUq2EWeEPlL7`|RFJO6%Hb>mx684}DvIijS*^ob>lIgul~US;Wdd#cE38&ht5Zkxs@o&7#L zYCGc7XSarK+8&)#6|%foU;`uK2w43zEe`zZ0F#=lUkb`6PiSb|N56+hj~?;BDCGJk z9(h8-vf~yUV#)NNkmfBg7Lu*5sw~ygZ~iAakleKCO`+T}@B9;O@#`9{o$?N83E1%T z(;1W9YtHTdkzVtiEDR!f#;zd&mQ9;JUE7hK+3VdrVz->A9i$k=i4Ww4;#xL&I=8$FOw7j@%rcI z6fzO%UB&ouVz%e84_#a(4YGINg4US&&;+u8zrj1SuI5o)i0sSi1>3dKT;WkwHa7gB9(@4*_X7^&!H3nuQ z=*Pu7X=)DU6=nlQ3E!?-MI}-$ZL$5NB#=>9I4u28JR0=Nj&=HMLUG<6$(xlE=^9|L zvrbXP-wDb2qGQvo(;%pjO~lA@5)`4u$iVK1c3kfqW@zR_R0)a(d0f(I1) zrInsHi%bD01HJQy6QgnQ0d?;xdZVg_8x^M1ZCLL5^QEg(=OPiTUFJUClVsTqeywiDbN36yAMP}AKT>9I zEj93%@YBgRs8W!4i?F=i+B~HYQlr*7duCB-*0+~xkrS6mpp)d@~L#2xw z$FoPJ40eb*fdciniaQgnWkNITKoJ)HdSU0D%wXlM_%7kXGa>k7Ix@ij&A{CjITvJt zZ418^s$QIGC*#{67OLLrm7y{wH8%gs!RC^+`Errrmeh$2*LPd4d-LD#M#e=~Eq%3l zd6(=)*pb%E>@BMxA*L$%w*TGn=H5R+%N&7ozHCD#X>I9MmNN6hb|wp-1Lp9N4X{?x z?AH6lx}2+VYWD52Ys#EZN&MH>zm-i)+OU@#_97!OB z-_ATXt8OJOcJptMVlKPcZ8?rgHJB+N$+ilKLPmkSU@l~CiMi5GA=%_eYruGYUKADD zI~?v)Q~Is6^4BksZ~r~Mie9&XY0Z7m+!T!)zSNy(s3M|lD7R-h?lAUQRy~{MAs%y6 z78!4o?|xw?lun+N`R{AySHOG?I`8*j{v{@!S!1#OUUby?VqKG&8zf`kcj9zvyR^>V zx&!GdIasMVXbWG6WkGmUq-cMZ6>^txwD^Ido~N^@nNZR>TKP zfz69Bdl6qIxSIXXoKH@Ua%WEBK_+_&C}XeC`LobasfTHcP~~`smf7_uzJhaK% zJUn4BK5#L?H&ASS>*7WGOb(sdGspi2l^{dsySaDWBZ#F>!wKS#GEcA zD?R__VYIn*86G5thomy=bpBie<_o?p!o^kI`9y7^^~R~x{rhg0^^90Nh+PuiXC-*5 z%B+8laYTHjr)38X$I_U=b6)(}dU2#^4Jea{UG3DC2&*ZZv+=Fr=Ziau7=a}Flx8i@D+te^!Cc?x9Y|=ebbyz zCw^%WS#IG=8?r~Ovw9x(l{}}KO@B?;6#lkx;+avgMWJn4!j8O7W1o|!&&5gbD6(?R zj(Uvc&ccV|>a`towfd2{9}cb68XwUgdYZm8q)i`qvX#HKvX^O|x}OF8gzCFjcNfH`{e+YsA=9{p}|H z)H_WFTE=Yh=&w=}me%X}UouObc|S*Kp|!GWT2d~1A+b8f!ET`y$L4+cuRE9(jp7FS z2A`=AWqFyw%wQdkWWTrE{KJ1tdzV1yu6Q5EI(p3r}& zt#ZA3#`Df-BFEmnm*{LW<0<60l|2jTpMF6T#PKQbb9#thwJj$9bjt9mEyhdl+Zk=G ztG=>==xdMVj%o4P$7pA~{N1$rt@8(3k~;k(Pg@Ide`qP{)Oh=!PXH?r&<_vRct>^gx| z!e!u4aqr_3+v=?t$JeiHA1<+-`sFr_*mGZ|no9Bc5!**v@6JtnT8KT;zH>2iRm{&e znnx$A`aZ>KJ{=xb7E?Lx{vz5qr&W6ig_x~*dh@ZJ^0}<~jJ)U5`h7;(2Zo&1uk1CE zzAsQf9s$(e>R_#)*Bf?f zm-A-v5(8_6P01S5!TgG>h*iXAWio?aPMC`EbBLY1ap-K5_NMiUIeUCE%_nj$wyh27 z^lkb%Rbu46LNrK^UjwuzKY^RI$2ILQ`lmE}H7t+OUGeDD;@Jn!^SJQqL82w(ymf8f z+2HhK#?{<()>$*}-j3n#=?adWiz+x-HwaX^Z^rT_+K2WnF&V4xJ$5ePyw>M+HM>n; z?P8bJ+Hp+lVxGBA+Y=5ems{K(>=L{7Xlu1_Toc?BX|`R)I)=6FOZcssg+#N@2{Dhs z4~KjQXFXPET^&jO-jb!PcJE>`c(a~4Zf~_Vhq-+T_oK6VUC>h#vb^oHr@!`wH0~&F z@xxmqu))PRST}5|yCd&&(kW@y>9BRT~3CP(!73#)H64s1zF>fj;QqlA0F z{*EI39b;v^G1Cex?kltw5SPWb^*UVtRKJ>EfYEN#1*GRjZ#l|@J9!TGcIR0wdkqOlQ`%t__|$y36{s>+1aUs>Z?EGKYSEVsCYo zhg}|)>YIMp&)p+OUCNSVts_6RwOeh4W<-u#zNl`&%=Zc$TgqJAH|nR1B!~ugE#to0 zY7p%SC3!nw!v3nO!>8@p)0y-txrv+23C$T~27?9v#X~rV-?4*V-d^q8At@5EJmtggysuk}ibDBPbj+(f#jE}C z@O5=VTL~QlABD>@SC%?Y4yLUemdZ2g++oML{p3mZR#T}8=CiR3eYr1G$C{o7Bwcvi zXZU&D*Yxm>M-I}?q)hN=J*!~I-oO_yxrKo*Rldo+&bYr#aFiAfjukpbW(?S?Zn-q% z=F|4$n$8~fEI)Upad^z2dPlR*DV@TxfKP>jA12SbH~P>1@+h)u(Y0({eZPD4O?vw7 z7@hqhGxbX5?ZqOH<`kJ6S@Vq|`i?0thbc4ANrU0OtH;OkXZpvkRNmWY(tY1Fu8^nc z6D+Y4gjJTFkWp(>?zma7=k{se$1aM~5`hk1j@g5U7LX~$wO5btiK)zW3EPCd_D5FD z47E7c>4 zk@e`u#530_CX8T?ZY!mG_KvK$#WIf?|AE18N+W+Q zg-a73Jsa;>8$Dp=>R~2?Rxt|s7MO`~n1qBo3T(^cG&NQYzZ>N2r}i<+V0R9xuzGRH z{^}ynjsPn%;huQYA6#c873|T`Y9D~YTw*7Uk-H1v7x&);aM~1tvEob?+0CK48}7g6 zXSo2;qC8eU`4lpab7=0SR4h4Qv3YaZ?b@#5>9;y=tLfJrD7;9JPQ9qrhm}dHoIYcI zebB}Q&<&(2_?~ildchW)@^PmOg*{e4d2j<91!RAmaLn9y?q}KYT;yIT#)npjJE*6P zi=~{Lz6VArl%*@s?h+=ERx{E7T>eE+_!4dD_s+P$RiC+5Iq*rRX`h1!3=WPTA+5SQFmPpRBr)@3>KtYG z9(_9v*;PoMG&4s50oK<*Hp%`amK*M9xUKt^!Txy>_{88)&&j^#Gvj$}D#eZ|P_S-7#;?i4>dNn*&XE5j%lsGmF<++rhjTwbrhP0d zbWfdUwj_NFOSX>%7mdyBK+6vUw=%;IppqR^SO45~LFeD&pIB0&La5c}(XudP9Tcgu|K?l95@=`HhOk;@4S@6VlhlE21O}t6}c$gx)0p5KX z7#LVL3@>tbnD8zmc^=@w37I#_kbIn<2V2m?h+0)MotNwY1_MBOe3MVDj&wEcA*g4_OdeU;xZ+i z0li<-aG8#Bth=zNFCj_!Ju_D0;vmt-w9nQtd-t9^bBA%P~Bs(J6Ta5fA_EeU!eTue(uQjij1ty7P$3KJWcabUu zrF59Z&tJbXCP|}YOj7P5)DxEAk;$IIQRAydQVsFoAInq1aZTVL?VRSE^rI;axZQ}Q z(6wu`nAmCc4Ey9E^vOD`EZKjn6di{)WBwu8w?+4$*C_Xim)E~D_PrqD`x?W)A59S+ z?$$5l$k&ZgKo{*}M(ii}L{p*1JOsIyk2}X6-tNjcdE18Ti-Mr$h7!zC1up?25&UN z6;H6*D|{sm&0js^K|tQTaihGrS%dQs%oP+4zB)dEOSi0w?xf^!sj3QYi$?(g+p*I3 zke>DV$xF36J2rY@?}Zik?NP0Qjuh9%j?HLZ@qCX(@CBh&K}>5!6ujO`m#;WYXyu|0 zp#Yr14`Ieipc#0LkAJl zi&|8}H}BbVrYhAsdP(FdwSq`R!`bkBLr7Rlj1y~5we3JbSOsBGDcTlY0+UUt&cumF zG__pYNwcHmwc84mtCs`B;@QHEZ0Q8oY+a*@WTV=w2UWtT6f3fad`t`4?-up z&0Dq{TC?X$P~4a||44GM&O?4h!<7DmxXO4{)<%QJkMe`i{}m4Wfz1D(KYl|mInn+K zojG1s74Y!VWC3K~9gJ=d%2LBCptxm$i!xcc#L)!nXx}O&KHd_>xGE+dUa#|LIr%0m zY)48s;O|z%`H#Dsvvj&nz z0m7_brZ&8P$*v!0G0}upU2>rLnnQ!fCn#8y>|Se4Q~z_DOE z+VcQPQT(qidfsgk6jb9C;e9ENxW-ct_XG!yj69G;j)UjkD-OdOK^*dPeLQgA%t`an z*98twL>5}7_WRaPE&Of&FJe;T3R90!xkX{(@+kXKH#Go)iP*-{vLpBENhd(@%(wjg_1%e!+>2r^25)MD6V5(g}@ zIkXCJwKxOY0+24u+rO=Ai^Ty#N|@)K#SL^8LRL|c9%9m(cjutRFl&%)D7)|M3?k3^1#)uDbVq5{@fKi*X2Uy=?D_EZxiAA1s!5XmK|m zZwi|`7E|kRdoe8;3_+3vN7W{r&EYh@f zU=YJ^urEvi5eaz&#q?qzmZ3WK#ef_IcnfrJ1ztDw4cO3TY6BAHbTA zG5fhsBgrg#d=kAAbdg}K+NH;cK0)O0kgf2rP2s5c&vu)ctxnj#;$+jN`?=ArU(^y@ zzr1xgP3N|C8C_g1wuQ|1OmsQ?2rfO};9IaEu5#Pxq*SemsHJAe_h0;qcXH1awpqNZHbzt! z7IsLpoVx31i0YFs7e6+cYelPdq#XUeTe~nr=1kf|6iU*F$MeWnM@qYlPvl*cP literal 0 HcmV?d00001 diff --git a/examples/espidf-ulp-pulse/src/CMakeLists.txt b/examples/espidf-ulp/main/CMakeLists.txt similarity index 83% rename from examples/espidf-ulp-pulse/src/CMakeLists.txt rename to examples/espidf-ulp/main/CMakeLists.txt index 75dedd2f6..a79852fbe 100644 --- a/examples/espidf-ulp-pulse/src/CMakeLists.txt +++ b/examples/espidf-ulp/main/CMakeLists.txt @@ -5,16 +5,16 @@ idf_component_register(SRCS "ulp_example_main.c" # ULP support additions to component CMakeLists.txt. # # 1. The ULP app name must be unique (if multiple components use ULP). -set(ulp_app_name ulp_main) +set(ulp_app_name ulp_${COMPONENT_NAME}) # # 2. Specify all assembly source files. # Files should be placed into a separate directory (in this case, ulp/), # which should not be added to COMPONENT_SRCS. -set(ulp_s_sources "../ulp/pulse_cnt.S" "../ulp/wake_up.S") +set(ulp_s_sources "ulp/pulse_cnt.S" "ulp/wake_up.S") # # 3. List all the component source files which include automatically # generated ULP export file, ${ulp_app_name}.h: -set(ulp_exp_dep_srcs "ulp_example_main.c") +set(ulp_exp_dep_srcs "../ulp_example_main.c") # # 4. Call function to build ULP binary and embed in project using the argument # values above. diff --git a/examples/espidf-ulp/main/component.mk b/examples/espidf-ulp/main/component.mk new file mode 100644 index 000000000..22e0a859a --- /dev/null +++ b/examples/espidf-ulp/main/component.mk @@ -0,0 +1,24 @@ +# +# ULP support additions to component makefile. +# +# 1. ULP_APP_NAME must be unique (if multiple components use ULP) +# Default value, override if necessary: +ULP_APP_NAME ?= ulp_$(COMPONENT_NAME) +# +# 2. Specify all assembly source files here. +# Files should be placed into a separate directory (in this case, ulp/), +# which should not be added to COMPONENT_SRCDIRS. +ULP_S_SOURCES = $(addprefix $(COMPONENT_PATH)/ulp/, \ + pulse_cnt.S \ + wake_up.S \ + ) +# +# 3. List all the component object files which include automatically +# generated ULP export file, $(ULP_APP_NAME).h: +ULP_EXP_DEP_OBJECTS := ulp_example_main.o +# +# 4. Include build rules for ULP program +include $(IDF_PATH)/components/ulp/component_ulp_common.mk +# +# End of ULP support additions to component makefile. +# diff --git a/examples/espidf-ulp-pulse/src/ulp_example_main.c b/examples/espidf-ulp/main/ulp_example_main.c similarity index 92% rename from examples/espidf-ulp-pulse/src/ulp_example_main.c rename to examples/espidf-ulp/main/ulp_example_main.c index 296c123b2..b7593bc4d 100644 --- a/examples/espidf-ulp-pulse/src/ulp_example_main.c +++ b/examples/espidf-ulp/main/ulp_example_main.c @@ -16,7 +16,15 @@ #include "soc/rtc_periph.h" #include "driver/gpio.h" #include "driver/rtc_io.h" + +#if CONFIG_IDF_TARGET_ESP32 #include "esp32/ulp.h" +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/ulp.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/ulp.h" +#endif + #include "ulp_main.h" extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); @@ -28,6 +36,7 @@ static void update_pulse_count(void); void app_main(void) { esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + printf("cause %d\n", cause); if (cause != ESP_SLEEP_WAKEUP_ULP) { printf("Not ULP wakeup, initializing ULP\n"); init_ulp_program(); @@ -74,12 +83,15 @@ static void init_ulp_program(void) rtc_gpio_pullup_dis(gpio_num); rtc_gpio_hold_en(gpio_num); +#if CONFIG_IDF_TARGET_ESP32 /* Disconnect GPIO12 and GPIO15 to remove current drain through - * pullup/pulldown resistors. + * pullup/pulldown resistors on modules which have these (e.g. ESP32-WROVER) * GPIO12 may be pulled high to select flash voltage. */ rtc_gpio_isolate(GPIO_NUM_12); rtc_gpio_isolate(GPIO_NUM_15); +#endif // CONFIG_IDF_TARGET_ESP32 + esp_deep_sleep_disable_rom_logging(); // suppress boot messages /* Set ULP wake up period to T = 20ms. diff --git a/examples/espidf-storage-spiffs/platformio.ini b/examples/espidf-ulp/platformio.ini similarity index 67% rename from examples/espidf-storage-spiffs/platformio.ini rename to examples/espidf-ulp/platformio.ini index 83870a9a3..55cf15bb7 100644 --- a/examples/espidf-storage-spiffs/platformio.ini +++ b/examples/espidf-ulp/platformio.ini @@ -7,9 +7,20 @@ ; Please visit documentation for the other options and examples ; http://docs.platformio.org/page/projectconf.html +[platformio] +src_dir = main + [env:esp32dev] platform = espressif32 framework = espidf board = esp32dev -monitor_speed = 115200 -board_build.partitions = partitions_example.csv + +[env:esp32-s2] +platform = espressif32 +framework = espidf +board = esp32-s2-saola-1 + +[env:esp32-s3] +platform = espressif32 +framework = espidf +board = esp32-s3-devkitc-1 diff --git a/examples/espidf-ulp-adc/sdkconfig.defaults b/examples/espidf-ulp/sdkconfig.defaults similarity index 71% rename from examples/espidf-ulp-adc/sdkconfig.defaults rename to examples/espidf-ulp/sdkconfig.defaults index 7214df17c..c7e68b3c8 100644 --- a/examples/espidf-ulp-adc/sdkconfig.defaults +++ b/examples/espidf-ulp/sdkconfig.defaults @@ -1,6 +1,3 @@ -# Enable ULP -CONFIG_ESP32_ULP_COPROC_ENABLED=y -CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=1024 # Set log level to Warning to produce clean output CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y CONFIG_BOOTLOADER_LOG_LEVEL=2 diff --git a/examples/espidf-ulp/sdkconfig.defaults.esp32 b/examples/espidf-ulp/sdkconfig.defaults.esp32 new file mode 100644 index 000000000..be391d8c4 --- /dev/null +++ b/examples/espidf-ulp/sdkconfig.defaults.esp32 @@ -0,0 +1,3 @@ +# Enable ULP +CONFIG_ESP32_ULP_COPROC_ENABLED=y +CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=1024 diff --git a/examples/espidf-ulp/sdkconfig.defaults.esp32s2 b/examples/espidf-ulp/sdkconfig.defaults.esp32s2 new file mode 100644 index 000000000..5175d2b6c --- /dev/null +++ b/examples/espidf-ulp/sdkconfig.defaults.esp32s2 @@ -0,0 +1,3 @@ +# Enable ULP +CONFIG_ESP32S2_ULP_COPROC_ENABLED=y +CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=1024 diff --git a/examples/espidf-ulp/sdkconfig.defaults.esp32s3 b/examples/espidf-ulp/sdkconfig.defaults.esp32s3 new file mode 100644 index 000000000..f63dcae20 --- /dev/null +++ b/examples/espidf-ulp/sdkconfig.defaults.esp32s3 @@ -0,0 +1,3 @@ +# Enable ULP +CONFIG_ESP32S3_ULP_COPROC_ENABLED=y +CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=1024 diff --git a/examples/espidf-ulp-pulse/ulp/pulse_cnt.S b/examples/espidf-ulp/ulp/pulse_cnt.S similarity index 85% rename from examples/espidf-ulp-pulse/ulp/pulse_cnt.S rename to examples/espidf-ulp/ulp/pulse_cnt.S index 33e6ef686..3ec02338b 100644 --- a/examples/espidf-ulp-pulse/ulp/pulse_cnt.S +++ b/examples/espidf-ulp/ulp/pulse_cnt.S @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* ULP Example: pulse counting This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -20,11 +25,13 @@ */ /* ULP assembly files are passed through C preprocessor first, so include directives - and C macros may be used in these files + and C macros may be used in these files */ +#include "sdkconfig.h" #include "soc/rtc_cntl_reg.h" #include "soc/rtc_io_reg.h" #include "soc/soc_ulp.h" +#include "soc/sens_reg.h" /* Define variables, which go into .bss section (zero-initialized data) */ .bss @@ -70,6 +77,14 @@ entry: move r3, io_number ld r3, r3, 0 +#if CONFIG_IDF_TARGET_ESP32S2 + /* ESP32S2 powers down RTC periph when entering deep sleep and thus by association SENS_SAR_IO_MUX_CONF_REG */ + WRITE_RTC_FIELD(SENS_SAR_IO_MUX_CONF_REG, SENS_IOMUX_CLK_GATE_EN, 1) +#elif CONFIG_IDF_TARGET_ESP32S3 + /* ESP32S3 powers down RTC periph when entering deep sleep and thus by association SENS_SAR_PERI_CLK_GATE_CONF_REG */ + WRITE_RTC_FIELD(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_IOMUX_CLK_EN, 1); +#endif + /* Lower 16 IOs and higher need to be handled separately, * because r0-r3 registers are 16 bit wide. * Check which IO this is. diff --git a/examples/espidf-ulp-pulse/ulp/wake_up.S b/examples/espidf-ulp/ulp/wake_up.S similarity index 89% rename from examples/espidf-ulp-pulse/ulp/wake_up.S rename to examples/espidf-ulp/ulp/wake_up.S index ec2e05da4..34b80b411 100644 --- a/examples/espidf-ulp-pulse/ulp/wake_up.S +++ b/examples/espidf-ulp/ulp/wake_up.S @@ -1,5 +1,5 @@ /* ULP assembly files are passed through C preprocessor first, so include directives - and C macros may be used in these files + and C macros may be used in these files */ #include "soc/rtc_cntl_reg.h" #include "soc/soc_ulp.h" diff --git a/platform.json b/platform.json index f30de5fb4..25429679f 100644 --- a/platform.json +++ b/platform.json @@ -21,7 +21,6 @@ "version": "2.0.5", "frameworks": { "arduino": { - "package": "framework-arduinoespressif32", "script": "builder/frameworks/arduino.py" }, "espidf": { @@ -35,9 +34,21 @@ "packages": { "framework-arduinoespressif32": { "type": "framework", - "optional": true, + "optional": false, "owner": "tasmota", "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5/framework-arduinoespressif32.zip" + }, + "framework-arduino-solo1": { + "type": "framework", + "optional": false, + "owner": "tasmota", + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1014/framework-arduinoespressif32-solo1-IDF_Arduino-d772747b2.zip" + }, + "framework-arduino-ITEAD": { + "type": "framework", + "optional": false, + "owner": "tasmota", + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1013/framework-arduinoespressif32-ITEAD-IDF_Arduino-d772747b2.zip" }, "framework-espidf": { "type": "framework", @@ -72,31 +83,14 @@ "toolchain-esp32ulp": { "type": "toolchain", "optional": true, - "owner": "platformio", - "version": "~1.22851.0" - }, - "toolchain-esp32s2ulp": { - "type": "toolchain", - "optional": true, - "owner": "platformio", - "version": "~1.22851.0" - }, - "framework-arduino-mbcwb": { - "type": "framework", - "optional": true, - "owner": "meteca", - "version": ">=2.1.1" + "owner": "jason2866", + "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/esp32ulp-elf-2.35_20220830-linux_x86_64.zip" }, "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", "version": "https://github.com/tasmota/esptool/releases/download/v4.3/esptool-4.3.zip" }, - "tool-mbctool": { - "optional": true, - "owner": "meteca", - "version": ">=2.0.0" - }, "tool-openocd-esp32": { "type": "debugger", "optional": true, @@ -122,7 +116,7 @@ "tool-cmake": { "optional": true, "owner": "platformio", - "version": "~3.21.0" + "version": "~3.16.0" }, "tool-ninja": { "optional": true, @@ -141,3 +135,4 @@ } } } + diff --git a/platform.py b/platform.py index d92452e85..9ac1ed554 100644 --- a/platform.py +++ b/platform.py @@ -87,8 +87,9 @@ def configure_default_packages(self, variables, targets): if "espidf" in frameworks: # Common packages for IDF and mixed Arduino+IDF projects + self.packages["toolchain-esp32ulp"]["optional"] = False for p in self.packages: - if p in ("tool-cmake", "tool-ninja", "toolchain-%sulp" % mcu): + if p in ("tool-cmake", "tool-ninja"): self.packages[p]["optional"] = False elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: self.packages[p]["optional"] = False @@ -100,35 +101,11 @@ def configure_default_packages(self, variables, targets): self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) if mcu in ("esp32s2", "esp32s3", "esp32c3"): - self.packages.pop("toolchain-esp32ulp", None) - if mcu != "esp32s2": - self.packages.pop("toolchain-esp32s2ulp", None) + if mcu == "esp32c3": + self.packages.pop("toolchain-esp32ulp", None) # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp"]["optional"] = False - if build_core == "mbcwb": - # Remove the main toolchains from PATH - for toolchain in ( - "toolchain-xtensa-esp32", - "toolchain-xtensa-esp32s2", - "toolchain-xtensa-esp32s3", - "toolchain-riscv32-esp", - ): - self.packages.pop(toolchain, None) - - # Add legacy toolchain with specific version - self.packages["toolchain-xtensa32"] = { - "type": "toolchain", - "owner": "platformio", - "version": "~2.50200.0" - } - - if build_core == "mbcwb": - self.packages["framework-arduinoespressif32"]["optional"] = True - self.packages["framework-arduino-mbcwb"]["optional"] = False - self.packages["tool-mbctool"]["type"] = "uploader" - self.packages["tool-mbctool"]["optional"] = False - return super().configure_default_packages(variables, targets) def get_boards(self, id_=None): From 42c25257ad9673dcfc344c990bead4be098ea27d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Sep 2022 11:43:43 +0200 Subject: [PATCH 172/666] Release Core 2.0.5 one Platform versions --- platform.json | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 25429679f..55804ac90 100644 --- a/platform.json +++ b/platform.json @@ -36,7 +36,19 @@ "type": "framework", "optional": false, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32.zip" + }, + "framework-arduino-solo1": { + "type": "framework", + "optional": false, + "owner": "tasmota", + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32-solo1.zip" + }, + "framework-arduino-ITEAD": { + "type": "framework", + "optional": false, + "owner": "tasmota", + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32-ITEAD.zip" }, "framework-arduino-solo1": { "type": "framework", From de7baa45fa8bd61be36eb002013b2c3a180147d2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Sep 2022 16:22:33 +0200 Subject: [PATCH 173/666] rm duplicate entrys --- platform.json | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/platform.json b/platform.json index 55804ac90..6dfdd476e 100644 --- a/platform.json +++ b/platform.json @@ -49,18 +49,6 @@ "optional": false, "owner": "tasmota", "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32-ITEAD.zip" - }, - "framework-arduino-solo1": { - "type": "framework", - "optional": false, - "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1014/framework-arduinoespressif32-solo1-IDF_Arduino-d772747b2.zip" - }, - "framework-arduino-ITEAD": { - "type": "framework", - "optional": false, - "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1013/framework-arduinoespressif32-ITEAD-IDF_Arduino-d772747b2.zip" }, "framework-espidf": { "type": "framework", From 886a38cbd97f49e0e6c620b6de70f019e210a454 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 24 Sep 2022 16:35:33 +0200 Subject: [PATCH 174/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c6e51125..4bf8df35b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid ```ini [env:stable] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5/platform-espressif32-2.0.5.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.1/platform-espressif32-2.0.5.1.zip board = ... ... ``` From 9cd4f1fd823f8690c44d6546acc9291dbc31e63a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Sep 2022 19:44:05 +0200 Subject: [PATCH 175/666] ulp update * ULP CI test Linux * install ulp toolchain always for s2, s3 * new ulp examples * use `toolchain-riscv32-esp` for riscv ulp projects * rm example `SPIFFS` * rm `mbcwb` support --- .github/workflows/examples.yml | 2 +- builder/frameworks/ulp.py | 11 +-- platform.py | 134 --------------------------------- 3 files changed, 4 insertions(+), 143 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 0f765c7bc..3e0696799 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest] example: - "examples/arduino-ble5-advertising" - "examples/arduino-blink" diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 7f16e7f94..1ec152cd3 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -34,16 +34,10 @@ def prepare_ulp_env_vars(env): ulp_env.PrependENVPath("IDF_PATH", FRAMEWORK_DIR) - mcu = "32" - if "esp32s2" in idf_variant: - mcu = "32s2" - elif "esp32s3" in idf_variant: - mcu = "32s3" - additional_packages = [ os.path.join( platform.get_package_dir( - "toolchain-xtensa-esp%s" % mcu + "toolchain-xtensa-%s" % (idf_variant) ), "bin", ), @@ -85,7 +79,7 @@ def get_component_includes(target_config): def generate_ulp_config(target_config): - riscv_ulp_enabled = sdk_config.get("ESP32S2_ULP_COPROC_RISCV", False) + riscv_ulp_enabled = sdk_config.get((idf_variant).upper() + "_ULP_COPROC_RISCV", False) ulp_sources = collect_ulp_sources() cmd = ( @@ -104,6 +98,7 @@ def generate_ulp_config(target_config): "-DULP_APP_NAME=ulp_main", "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), '-DCOMPONENT_INCLUDES="%s"' % ";".join(get_component_includes(target_config)), + "-DIDF_TARGET=" + idf_variant, "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), "-DPYTHON=" + env.subst("$PYTHONEXE"), diff --git a/platform.py b/platform.py index 9ac1ed554..0f22a46b3 100644 --- a/platform.py +++ b/platform.py @@ -49,42 +49,6 @@ def configure_default_packages(self, variables, targets): "board_build.core", board_config.get("build.core", "arduino") ).lower() - if len(frameworks) == 1 and "arduino" in frameworks and build_core == "esp32": - # In case the upstream Arduino framework is specified in the configuration - # file then we need to dynamically extract toolchain versions from the - # Arduino index file. This feature can be disabled via a special option: - if ( - variables.get( - "board_build.arduino.upstream_packages", - board_config.get("build.arduino.upstream_packages", "yes"), - ).lower() - == "yes" - ): - package_version = self.packages["framework-arduinoespressif32"][ - "version" - ] - - url_items = urllib.parse.urlparse(package_version) - # Only GitHub repositories support dynamic packages - if ( - url_items.scheme in ("http", "https") - and url_items.netloc.startswith("github") - and url_items.path.endswith(".git") - ): - try: - self.configure_upstream_arduino_packages(url_items) - except Exception as e: - sys.stderr.write( - "Error! Failed to extract upstream toolchain" - "configurations:\n%s\n" % str(e) - ) - sys.stderr.write( - "You can disable this feature via the " - "`board_build.arduino.upstream_packages = no` setting in " - "your `platformio.ini` file.\n" - ) - sys.exit(1) - if "espidf" in frameworks: # Common packages for IDF and mixed Arduino+IDF projects self.packages["toolchain-esp32ulp"]["optional"] = False @@ -244,101 +208,3 @@ def configure_debug_session(self, debug_config): ) ) debug_config.load_cmds = load_cmds - - @staticmethod - def extract_toolchain_versions(tool_deps): - def _parse_version(original_version): - assert original_version - match = re.match(r"^gcc(\d+)_(\d+)_(\d+)\-esp\-(.+)$", original_version) - if not match: - raise ValueError("Bad package version `%s`" % original_version) - assert len(match.groups()) == 4 - return "%s.%s.%s+%s" % (match.groups()) - - if not tool_deps: - raise ValueError( - ("Failed to extract tool dependencies from the remote package file") - ) - - toolchain_remap = { - "xtensa-esp32-elf-gcc": "toolchain-xtensa-esp32", - "xtensa-esp32s2-elf-gcc": "toolchain-xtensa-esp32s2", - "xtensa-esp32s3-elf-gcc": "toolchain-xtensa-esp32s3", - "riscv32-esp-elf-gcc": "toolchain-riscv32-esp", - } - - result = dict() - for tool in tool_deps: - if tool["name"] in toolchain_remap: - result[toolchain_remap[tool["name"]]] = _parse_version(tool["version"]) - - return result - - @staticmethod - def parse_tool_dependencies(index_data): - for package in index_data.get("packages", []): - if package["name"] == "esp32": - for platform in package["platforms"]: - if platform["name"] == "esp32": - return platform["toolsDependencies"] - - return [] - - @staticmethod - def download_remote_package_index(url_items): - def _prepare_url_for_index_file(url_items): - tag = "master" - if url_items.fragment: - tag = url_items.fragment - return ( - "https://raw.githubusercontent.com/%s/" - "%s/package/package_esp32_index.template.json" - % (url_items.path.replace(".git", ""), tag) - ) - - index_file_url = _prepare_url_for_index_file(url_items) - r = requests.get(index_file_url, timeout=10) - if r.status_code != 200: - raise ValueError( - ( - "Failed to download package index file due to a bad response (%d) " - "from the remote `%s`" - ) - % (r.status_code, index_file_url) - ) - return r.json() - - def configure_arduino_toolchains(self, package_index): - if not package_index: - return - - toolchain_packages = self.extract_toolchain_versions( - self.parse_tool_dependencies(package_index) - ) - for toolchain_package, version in toolchain_packages.items(): - if toolchain_package not in self.packages: - self.packages[toolchain_package] = dict() - self.packages[toolchain_package]["version"] = version - self.packages[toolchain_package]["owner"] = "espressif" - self.packages[toolchain_package]["type"] = "toolchain" - - def configure_upstream_arduino_packages(self, url_items): - framework_index_file = os.path.join( - self.get_package_dir("framework-arduinoespressif32") or "", - "package", - "package_esp32_index.template.json", - ) - - # Detect whether the remote is already cloned - if os.path.isfile(framework_index_file) and os.path.isdir( - os.path.join( - self.get_package_dir("framework-arduinoespressif32") or "", ".git" - ) - ): - with open(framework_index_file) as fp: - self.configure_arduino_toolchains(json.load(fp)) - else: - print("Configuring toolchain packages from a remote source...") - self.configure_arduino_toolchains( - self.download_remote_package_index(url_items) - ) From e3aa7a4c77d495208ed39602d1138c3a3cf2dac1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 25 Sep 2022 20:58:33 +0200 Subject: [PATCH 176/666] refactore From 290dedef9c569d513393e9de4936e295c2dc7831 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 27 Sep 2022 14:15:37 +0200 Subject: [PATCH 177/666] espota path fix * add solo1 / ITEAD to CI * fix `espota.py` path --- builder/frameworks/arduino.py | 15 +++++---------- builder/main.py | 20 +++++++++++++++----- examples/arduino-blink/platformio.ini | 12 ++++++++++++ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index eb8e8c447..18e79cedd 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -23,17 +23,12 @@ """ from os.path import join - from SCons.Script import DefaultEnvironment, SConscript env = DefaultEnvironment() -board = env.BoardConfig() -extra_flags = board.get("build.extra_flags", "") -extra_flags = [element.replace("-D", " ") for element in extra_flags] -extra_flags = ''.join(extra_flags) -build_flags = env.GetProjectOption("build_flags") -build_flags = [element.replace("-D", " ") for element in build_flags] -build_flags = ''.join(build_flags) + +extra_flags = ''.join([element.replace("-D", " ") for element in env.BoardConfig().get("build.extra_flags", "")]) +build_flags = ''.join([element.replace("-D", " ") for element in env.GetProjectOption("build_flags")]) SConscript("_embed_files.py", exports="env") @@ -43,13 +38,13 @@ "framework-arduino-solo1"), "tools", "platformio-build.py")) env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) -elif "arduino" in env.subst("$PIOFRAMEWORK") and "FRAMEWORK_ARDUINO_ITEAD" in build_flags and "espidf" not in env.subst("$PIOFRAMEWORK"): +elif ("CORE32ITEAD" in extra_flags or "FRAMEWORK_ARDUINO_ITEAD" in build_flags) and ("arduino" in env.subst("$PIOFRAMEWORK") and "espidf" not in env.subst("$PIOFRAMEWORK")): SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduino-ITEAD"), "tools", "platformio-build.py")) env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) -elif "arduino" in env.subst("$PIOFRAMEWORK") and "CORE32SOLO1" not in extra_flags and "FRAMEWORK_ARDUINO_ITEAD" not in build_flags and "espidf" not in env.subst("$PIOFRAMEWORK"): +elif "arduino" in env.subst("$PIOFRAMEWORK") and "CORE32SOLO1" not in extra_flags and "FRAMEWORK_ARDUINO_SOLO1" not in build_flags and "CORE32ITEAD" not in extra_flags and "FRAMEWORK_ARDUINO_ITEAD" not in build_flags and "espidf" not in env.subst("$PIOFRAMEWORK"): SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) diff --git a/builder/main.py b/builder/main.py index 80ba655ac..66affa180 100644 --- a/builder/main.py +++ b/builder/main.py @@ -22,10 +22,24 @@ from platformio.util import get_serial_ports +env = DefaultEnvironment() +platform = env.PioPlatform() + # # Helpers # +extra_flags = ''.join([element.replace("-D", " ") for element in env.BoardConfig().get("build.extra_flags", "")]) +build_flags = ''.join([element.replace("-D", " ") for element in env.GetProjectOption("build_flags")]) + +if "CORE32SOLO1" in extra_flags or "FRAMEWORK_ARDUINO_SOLO1" in build_flags: + FRAMEWORK_DIR = platform.get_package_dir("framework-arduino-solo1") + print ("Solo1 framework will be used") +elif "CORE32ITEAD" in extra_flags or "FRAMEWORK_ARDUINO_ITEAD" in build_flags: + FRAMEWORK_DIR = platform.get_package_dir("framework-arduino-ITEAD") + print ("ITEAD framework will be used") +else: + FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") def BeforeUpload(target, source, env): upload_options = {} @@ -167,8 +181,6 @@ def __fetch_fs_size(target, source, env): return (target, source) -env = DefaultEnvironment() -platform = env.PioPlatform() board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") toolchain_arch = "xtensa-%s" % mcu @@ -356,9 +368,7 @@ def __fetch_fs_size(target, source, env): "See https://docs.platformio.org/page/platforms/" "espressif32.html#over-the-air-ota-update\n") env.Replace( - UPLOADER=join( - platform.get_package_dir("framework-arduinoespressif32") or "", - "tools", "espota.py"), + UPLOADER=join(FRAMEWORK_DIR,"tools", "espota.py"), UPLOADERFLAGS=["--debug", "--progress", "-i", "$UPLOAD_PORT"], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS -f $SOURCE' ) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index b9bd7f537..78d55726c 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -22,6 +22,18 @@ framework = arduino board = esp32doit-devkit-v1 monitor_speed = 115200 +[env:esp32-solo1] +platform = espressif32 +framework = arduino +board = esp32doit-devkit-v1 +build_flags = -DFRAMEWORK_ARDUINO_SOLO1 + +[env:esp32-ITEAD] +platform = espressif32 +framework = arduino +board = esp32doit-devkit-v1 +build_flags = -DFRAMEWORK_ARDUINO_ITEAD + [env:lolin32] platform = espressif32 framework = arduino From a55e9a8abf1aafa09a33e90ce16454db63f102b0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 28 Sep 2022 11:23:59 +0200 Subject: [PATCH 178/666] ulp official --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 6dfdd476e..fdd23f2ba 100644 --- a/platform.json +++ b/platform.json @@ -83,8 +83,8 @@ "toolchain-esp32ulp": { "type": "toolchain", "optional": true, - "owner": "jason2866", - "version": "https://github.com/Jason2866/crosstool-NG/releases/download/v8.4.0/esp32ulp-elf-2.35_20220830-linux_x86_64.zip" + "owner": "espressif", + "version": "~2" }, "tool-esptoolpy": { "type": "uploader", From 330f895bca7850bdea4e9b871443400bd6c92f70 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 28 Sep 2022 11:24:37 +0200 Subject: [PATCH 179/666] Update examples.yml --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 3e0696799..0f765c7bc 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [ubuntu-latest, windows-latest, macos-latest] example: - "examples/arduino-ble5-advertising" - "examples/arduino-blink" From 7b6ceb6468c6bf1aae3d9f01234d7b5dac306277 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 30 Sep 2022 21:38:33 +0200 Subject: [PATCH 180/666] integrate changes from upstream (#37) * align upstream * rm adapter speed (defaults are set in OCD) --- builder/main.py | 31 ++++++++++++++++++++++++++----- platform.py | 3 ++- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/builder/main.py b/builder/main.py index 66affa180..252c1866f 100644 --- a/builder/main.py +++ b/builder/main.py @@ -56,6 +56,23 @@ def BeforeUpload(target, source, env): env.Replace(UPLOAD_PORT=env.WaitForNewSerialPort(before_ports)) +def _get_board_memory_type(env): + board_config = env.BoardConfig() + default_type = "%s_%s" % ( + board_config.get("build.flash_mode", "dio"), + board_config.get("build.psram_type", "qspi"), + ) + + return board_config.get( + "build.memory_type", + board_config.get( + "build.%s.memory_type" + % env.subst("$PIOFRAMEWORK").strip().replace(" ", "_"), + default_type, + ), + ) + + def _get_board_f_flash(env): frequency = env.subst("$BOARD_F_FLASH") frequency = str(frequency).replace("L", "") @@ -63,19 +80,22 @@ def _get_board_f_flash(env): def _get_board_flash_mode(env): - memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi") - mode = env.subst("$BOARD_FLASH_MODE") - if memory_type in ("opi_opi", "opi_qspi"): + if ["arduino"] == env.get("PIOFRAMEWORK") and _get_board_memory_type(env) in ( + "opi_opi", + "opi_qspi", + ): return "dout" + + mode = env.subst("$BOARD_FLASH_MODE") if mode in ("qio", "qout"): return "dio" return mode def _get_board_boot_mode(env): - memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi") + memory_type = env.BoardConfig().get("build.arduino.memory_type", "") build_boot = env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE") - if memory_type in ("opi_opi", "opi_qspi"): + if ["arduino"] == env.get("PIOFRAMEWORK") and memory_type in ("opi_opi", "opi_qspi"): build_boot = "opi" return build_boot @@ -195,6 +215,7 @@ def __fetch_fs_size(target, source, env): __get_board_boot_mode=_get_board_boot_mode, __get_board_f_flash=_get_board_f_flash, __get_board_flash_mode=_get_board_flash_mode, + __get_board_memory_type=_get_board_memory_type, AR="%s-elf-gcc-ar" % toolchain_arch, AS="%s-elf-as" % toolchain_arch, diff --git a/platform.py b/platform.py index 0f22a46b3..5aae48548 100644 --- a/platform.py +++ b/platform.py @@ -21,8 +21,10 @@ from platformio.public import PlatformBase, to_unix_path + IS_WINDOWS = sys.platform.startswith("win") + class Espressif32Platform(PlatformBase): def configure_default_packages(self, variables, targets): if not variables.get("board"): @@ -110,7 +112,6 @@ def _add_dynamic_options(self, board): if board.get("build.mcu", "") in ("esp32c3", "esp32s3"): supported_debug_tools.append("esp-builtin") - upload_protocol = board.manifest.get("upload", {}).get("protocol") upload_protocols = board.manifest.get("upload", {}).get("protocols", []) if debug: From a8381b1d716669fb49f111571e6a34c646e92492 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 30 Sep 2022 21:46:25 +0200 Subject: [PATCH 181/666] cmake v3.21 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index fdd23f2ba..94484b4ef 100644 --- a/platform.json +++ b/platform.json @@ -116,7 +116,7 @@ "tool-cmake": { "optional": true, "owner": "platformio", - "version": "~3.16.0" + "version": "~3.21.0" }, "tool-ninja": { "optional": true, From dc52ca62b967e4f5f269427f9def702d7dff1c7c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 1 Oct 2022 17:36:40 +0200 Subject: [PATCH 182/666] Boards update --- boards/adafruit_feather_esp32_v2.json | 4 +- boards/adafruit_feather_esp32s3.json | 3 +- boards/adafruit_feather_esp32s3_nopsram.json | 3 +- boards/adafruit_itsybitsy_esp32.json | 43 +++++++++++++ boards/adafruit_qtpy_esp32.json | 4 +- boards/adafruit_qtpy_esp32c3.json | 2 +- boards/adafruit_qtpy_esp32s3.json | 61 ------------------- boards/alksesp32.json | 6 +- ...uit_qtpy_esp32-s2.json => bee_motion.json} | 25 +++++--- boards/bee_motion_mini.json | 38 ++++++++++++ boards/bee_motion_s3.json | 45 ++++++++++++++ boards/bee_s3.json | 45 ++++++++++++++ boards/bpi-bit.json | 4 +- boards/d-duino-32.json | 4 +- boards/deneyapkart.json | 6 +- boards/deneyapkart1A.json | 6 +- boards/deneyapkartg.json | 38 ++++++++++++ boards/dfrobot_beetle_esp32c3.json | 3 +- boards/dpu_esp32.json | 4 +- boards/esp32-devkitlipo.json | 4 +- boards/esp32-s3-devkitc-1.json | 2 +- boards/esp32s3box.json | 2 - boards/esp32s3camlcd.json | 2 +- boards/espectro32.json | 4 +- boards/featheresp32-s2.json | 2 +- boards/featheresp32.json | 2 +- boards/frogboard.json | 4 +- boards/kb32-ft.json | 4 +- boards/labplus_mpython.json | 4 +- boards/lolin_c3_mini.json | 2 +- boards/lolin_s3.json | 49 +++++++++++++++ boards/m5stack-core-esp32.json | 4 +- boards/m5stack-core2.json | 2 +- boards/m5stack-station.json | 34 +++++++++++ boards/mgbot-iotik32a.json | 4 +- boards/mgbot-iotik32b.json | 4 +- boards/minimain_esp32s2.json | 48 +++++++++++++++ .../{qtpy-esp32-s2.json => nodemcu-32s2.json} | 14 ++--- boards/nscreen-32.json | 4 +- boards/odroid_esp32.json | 4 +- boards/sparkfun_esp32_iot_redboard.json | 39 ++++++++++++ boards/sparkfun_esp32micromod.json | 4 +- boards/sparkfun_esp32s2_thing_plus_c.json | 38 ++++++++++++ boards/sparkfun_lora_gateway_1-channel.json | 4 +- boards/tamc_termod_s3.json | 46 ++++++++++++++ boards/tinypico.json | 4 +- boards/trueverit-iot-driver-mk3.json | 4 +- boards/ttgo-t-simcam.json | 47 ++++++++++++++ boards/ttgo-t7-v13-mini32.json | 4 +- boards/ttgo-t7-v14-mini32.json | 4 +- boards/um_feathers3.json | 3 +- boards/um_pros3.json | 3 +- boards/um_tinys3.json | 3 +- boards/unphone7.json | 40 ++++++++++++ boards/unphone8.json | 42 +++++++++++++ boards/unphone9.json | 48 +++++++++++++++ boards/upesy_wroom.json | 4 +- boards/upesy_wrover.json | 4 +- ...qt_py_esp32-c3.json => wifiduino32c3.json} | 15 +++-- boards/wifiduino32s3.json | 43 +++++++++++++ boards/wt32-eth01.json | 4 +- boards/xinabox_cw02.json | 4 +- 62 files changed, 795 insertions(+), 155 deletions(-) create mode 100644 boards/adafruit_itsybitsy_esp32.json delete mode 100644 boards/adafruit_qtpy_esp32s3.json rename boards/{adafruit_qtpy_esp32-s2.json => bee_motion.json} (53%) create mode 100644 boards/bee_motion_mini.json create mode 100644 boards/bee_motion_s3.json create mode 100644 boards/bee_s3.json create mode 100644 boards/deneyapkartg.json create mode 100644 boards/lolin_s3.json create mode 100644 boards/m5stack-station.json create mode 100644 boards/minimain_esp32s2.json rename boards/{qtpy-esp32-s2.json => nodemcu-32s2.json} (67%) create mode 100644 boards/sparkfun_esp32_iot_redboard.json create mode 100644 boards/sparkfun_esp32s2_thing_plus_c.json create mode 100644 boards/tamc_termod_s3.json create mode 100644 boards/ttgo-t-simcam.json create mode 100644 boards/unphone7.json create mode 100644 boards/unphone8.json create mode 100644 boards/unphone9.json rename boards/{adafruit_qt_py_esp32-c3.json => wifiduino32c3.json} (65%) create mode 100644 boards/wifiduino32s3.json diff --git a/boards/adafruit_feather_esp32_v2.json b/boards/adafruit_feather_esp32_v2.json index a45636e4d..78333e8d7 100644 --- a/boards/adafruit_feather_esp32_v2.json +++ b/boards/adafruit_feather_esp32_v2.json @@ -1,6 +1,6 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld" }, "core": "esp32", @@ -11,7 +11,7 @@ "-mfix-esp32-psram-cache-strategy=memw" ], "f_cpu": "240000000L", - "f_flash": "40000000L", + "f_flash": "80000000L", "flash_mode": "dio", "mcu": "esp32", "variant": "adafruit_feather_esp32_v2" diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json index f9e795ceb..9778ec20b 100644 --- a/boards/adafruit_feather_esp32s3.json +++ b/boards/adafruit_feather_esp32s3.json @@ -7,7 +7,8 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DBOARD_HAS_PSRAM" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/adafruit_feather_esp32s3_nopsram.json b/boards/adafruit_feather_esp32s3_nopsram.json index 39bc7eabb..da2550184 100644 --- a/boards/adafruit_feather_esp32s3_nopsram.json +++ b/boards/adafruit_feather_esp32s3_nopsram.json @@ -1,7 +1,8 @@ { "build": { "arduino":{ - "ldscript": "esp32s3_out.ld" + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": [ diff --git a/boards/adafruit_itsybitsy_esp32.json b/boards/adafruit_itsybitsy_esp32.json new file mode 100644 index 000000000..821b285fa --- /dev/null +++ b/boards/adafruit_itsybitsy_esp32.json @@ -0,0 +1,43 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_ITSYBITSY_ESP32", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "adafruit_itsybitsy_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit ItsyBitsy ESP32", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4363", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32.json b/boards/adafruit_qtpy_esp32.json index 39896da9d..9cc3aec42 100644 --- a/boards/adafruit_qtpy_esp32.json +++ b/boards/adafruit_qtpy_esp32.json @@ -1,6 +1,6 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld" }, "core": "esp32", @@ -11,7 +11,7 @@ "-mfix-esp32-psram-cache-strategy=memw" ], "f_cpu": "240000000L", - "f_flash": "40000000L", + "f_flash": "80000000L", "flash_mode": "dio", "mcu": "esp32", "variant": "adafruit_qtpy_esp32" diff --git a/boards/adafruit_qtpy_esp32c3.json b/boards/adafruit_qtpy_esp32c3.json index 9ec2dbf05..7c870e019 100644 --- a/boards/adafruit_qtpy_esp32c3.json +++ b/boards/adafruit_qtpy_esp32c3.json @@ -11,7 +11,7 @@ ], "f_cpu": "160000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "hwids": [ [ "0X303A", diff --git a/boards/adafruit_qtpy_esp32s3.json b/boards/adafruit_qtpy_esp32s3.json deleted file mode 100644 index 6413a7ef3..000000000 --- a/boards/adafruit_qtpy_esp32s3.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x8119" - ], - [ - "0x239A", - "0x0119" - ], - [ - "0x239A", - "0x811A" - ] - ], - "mcu": "esp32s3", - "variant": "adafruit_qtpy_esp32s3_nopsram" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit QT Py ESP32-S3 No PSRAM", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x410000", - "variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin" - ] - ] - }, - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5426", - "vendor": "Adafruit" -} diff --git a/boards/alksesp32.json b/boards/alksesp32.json index 6a4ae15ad..d94ec71fa 100644 --- a/boards/alksesp32.json +++ b/boards/alksesp32.json @@ -1,13 +1,13 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld" }, "core": "esp32", "extra_flags": "-DARDUINO_ALKS", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "alksesp32" }, diff --git a/boards/adafruit_qtpy_esp32-s2.json b/boards/bee_motion.json similarity index 53% rename from boards/adafruit_qtpy_esp32-s2.json rename to boards/bee_motion.json index 9ef92b3e2..c8577902b 100644 --- a/boards/adafruit_qtpy_esp32-s2.json +++ b/boards/bee_motion.json @@ -1,15 +1,24 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1", + "extra_flags": [ + "-DARDUINO_Bee_Motion", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x810D" + ] + ], "mcu": "esp32s2", - "variant": "adafruit_qtpy_esp32s2" + "variant": "Bee_Motion" }, "connectivity": [ "wifi" @@ -21,14 +30,16 @@ "arduino", "espidf" ], - "name": "Adafruit QT Py ESP32-S2", + "name": "Smart Bee Motion", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, "require_upload_port": true, - "speed": 921600 + "speed": 460800 }, - "url": "https://www.adafruit.com/product/5325", - "vendor": "Adafruit" + "url": "https://github.com/strid3r21/Bee-Motion", + "vendor": "Smart Bee" } diff --git a/boards/bee_motion_mini.json b/boards/bee_motion_mini.json new file mode 100644 index 000000000..d24163ec8 --- /dev/null +++ b/boards/bee_motion_mini.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": [ + "-DARDUINO_Bee_Motion_Mini", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "mcu": "esp32c3", + "variant": "Bee_Motion_Mini" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Smart Bee Motion Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/strid3r21/BeeMotionMini", + "vendor": "Smart Bee" +} diff --git a/boards/bee_motion_s3.json b/boards/bee_motion_s3.json new file mode 100644 index 000000000..e5f3a1700 --- /dev/null +++ b/boards/bee_motion_s3.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_BeeMotionS3", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8113" + ] + ], + "mcu": "esp32s3", + "variant": "Bee_Motion_S3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Smart Bee Motion S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/strid3r21/BeeMotionS3/", + "vendor": "Smart Bee" +} diff --git a/boards/bee_s3.json b/boards/bee_s3.json new file mode 100644 index 000000000..d4bfb9b38 --- /dev/null +++ b/boards/bee_s3.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_Bee_S3", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8110" + ] + ], + "mcu": "esp32s3", + "variant": "Bee_S3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Smart Bee S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/strid3r21/BeeS3", + "vendor": "Smart Bee" +} diff --git a/boards/bpi-bit.json b/boards/bpi-bit.json index 5414abc7d..ec5c0dc73 100644 --- a/boards/bpi-bit.json +++ b/boards/bpi-bit.json @@ -1,12 +1,12 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld" }, "core": "esp32", "extra_flags": "-DARDUINO_BPI_BIT", "f_cpu": "160000000L", - "f_flash": "40000000L", + "f_flash": "80000000L", "flash_mode": "dio", "mcu": "esp32", "variant": "bpi-bit" diff --git a/boards/d-duino-32.json b/boards/d-duino-32.json index 43bc24a40..e4d92e3df 100644 --- a/boards/d-duino-32.json +++ b/boards/d-duino-32.json @@ -1,12 +1,12 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld" }, "core": "esp32", "extra_flags": "-DARDUINO_D_DUINO_32", "f_cpu": "240000000L", - "f_flash": "40000000L", + "f_flash": "80000000L", "flash_mode": "dio", "mcu": "esp32", "variant": "d-duino-32" diff --git a/boards/deneyapkart.json b/boards/deneyapkart.json index 3114c0399..018813d78 100644 --- a/boards/deneyapkart.json +++ b/boards/deneyapkart.json @@ -1,6 +1,6 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld" }, "core": "esp32", @@ -11,8 +11,8 @@ "-mfix-esp32-psram-cache-strategy=memw" ], "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "deneyapkart" }, diff --git a/boards/deneyapkart1A.json b/boards/deneyapkart1A.json index 436950859..8aac1883f 100644 --- a/boards/deneyapkart1A.json +++ b/boards/deneyapkart1A.json @@ -1,6 +1,6 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld" }, "core": "esp32", @@ -11,8 +11,8 @@ "-mfix-esp32-psram-cache-strategy=memw" ], "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "deneyapkart1A" }, diff --git a/boards/deneyapkartg.json b/boards/deneyapkartg.json new file mode 100644 index 000000000..8b0bb333a --- /dev/null +++ b/boards/deneyapkartg.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": [ + "-DARDUINO_DYG", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "mcu": "esp32c3", + "variant": "deneyapkartg" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart G", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/en/", + "vendor": "Deneyap" +} diff --git a/boards/dfrobot_beetle_esp32c3.json b/boards/dfrobot_beetle_esp32c3.json index a5b884f2f..ab0b4c92c 100644 --- a/boards/dfrobot_beetle_esp32c3.json +++ b/boards/dfrobot_beetle_esp32c3.json @@ -6,7 +6,8 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ESP32C3_DEV", - "-DARDUINO_USB_MODE=1" + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "160000000L", "f_flash": "80000000L", diff --git a/boards/dpu_esp32.json b/boards/dpu_esp32.json index 1d6ed4eb3..1f5b89a67 100644 --- a/boards/dpu_esp32.json +++ b/boards/dpu_esp32.json @@ -12,8 +12,8 @@ "-mfix-esp32-psram-cache-strategy=memw" ], "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "dpu_esp32" }, diff --git a/boards/esp32-devkitlipo.json b/boards/esp32-devkitlipo.json index cbc926b17..419edfd79 100644 --- a/boards/esp32-devkitlipo.json +++ b/boards/esp32-devkitlipo.json @@ -1,12 +1,12 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld" }, "core": "esp32", "extra_flags": "-DARDUINO_ESP32_DEVKIT_LIPO", "f_cpu": "240000000L", - "f_flash": "40000000L", + "f_flash": "80000000L", "flash_mode": "qio", "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32", diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json index f5a9757b9..31b2ab4da 100644 --- a/boards/esp32-s3-devkitc-1.json +++ b/boards/esp32-s3-devkitc-1.json @@ -14,7 +14,7 @@ "flash_mode": "qio", "hwids": [ [ - "0X303A", + "0x303A", "0x1001" ] ], diff --git a/boards/esp32s3box.json b/boards/esp32s3box.json index 6e31df298..8a7bfa907 100644 --- a/boards/esp32s3box.json +++ b/boards/esp32s3box.json @@ -6,8 +6,6 @@ }, "core": "esp32", "extra_flags": [ - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", "-DBOARD_HAS_PSRAM", "-DARDUINO_ESP32_S3_BOX", "-DARDUINO_USB_MODE=1", diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index 623ee77aa..d35f26798 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -36,7 +36,7 @@ ], "name": "ESP32S3 CAM LCD", "upload": { - "flash_size": "16MB", + "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 16777216, "require_upload_port": true, diff --git a/boards/espectro32.json b/boards/espectro32.json index 7a88b3b06..973c6080e 100644 --- a/boards/espectro32.json +++ b/boards/espectro32.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_ESPECTRO32", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "espectro32" }, diff --git a/boards/featheresp32-s2.json b/boards/featheresp32-s2.json index f645bf629..6933ccb57 100644 --- a/boards/featheresp32-s2.json +++ b/boards/featheresp32-s2.json @@ -11,7 +11,7 @@ ], "f_cpu": "240000000L", "f_flash": "80000000L", - "flash_mode": "dio", + "flash_mode": "qio", "hwids": [ [ "0x239A", diff --git a/boards/featheresp32.json b/boards/featheresp32.json index d6d3b185d..ac922db5a 100644 --- a/boards/featheresp32.json +++ b/boards/featheresp32.json @@ -6,7 +6,7 @@ "core": "esp32", "extra_flags": "-DARDUINO_FEATHER_ESP32", "f_cpu": "240000000L", - "f_flash": "40000000L", + "f_flash": "80000000L", "flash_mode": "dio", "mcu": "esp32", "variant": "feather_esp32" diff --git a/boards/frogboard.json b/boards/frogboard.json index b19e80244..93a772920 100644 --- a/boards/frogboard.json +++ b/boards/frogboard.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_FROG_ESP32", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "frog32" }, diff --git a/boards/kb32-ft.json b/boards/kb32-ft.json index 586494f38..4bfab5e8d 100644 --- a/boards/kb32-ft.json +++ b/boards/kb32-ft.json @@ -11,8 +11,8 @@ "-mfix-esp32-psram-cache-strategy=memw" ], "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "esp32" }, diff --git a/boards/labplus_mpython.json b/boards/labplus_mpython.json index 255edcc9b..3d3a4ff4e 100644 --- a/boards/labplus_mpython.json +++ b/boards/labplus_mpython.json @@ -7,8 +7,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_ESP32_DEV", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "mpython" }, diff --git a/boards/lolin_c3_mini.json b/boards/lolin_c3_mini.json index 76304465f..63afade2c 100644 --- a/boards/lolin_c3_mini.json +++ b/boards/lolin_c3_mini.json @@ -19,7 +19,7 @@ ] ], "mcu": "esp32c3", - "variant": "esp32c3" + "variant": "lolin_c3_mini" }, "connectivity": [ "wifi" diff --git a/boards/lolin_s3.json b/boards/lolin_s3.json new file mode 100644 index 000000000..30f360e0c --- /dev/null +++ b/boards/lolin_s3.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_LOLIN_S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "lolin_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc/en/latest/s3/index.html", + "vendor": "WEMOS" +} diff --git a/boards/m5stack-core-esp32.json b/boards/m5stack-core-esp32.json index c80f228f5..8d015f417 100644 --- a/boards/m5stack-core-esp32.json +++ b/boards/m5stack-core-esp32.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_M5Stack_Core_ESP32", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "m5stack_core_esp32" }, diff --git a/boards/m5stack-core2.json b/boards/m5stack-core2.json index 4154831c4..c860124e2 100644 --- a/boards/m5stack-core2.json +++ b/boards/m5stack-core2.json @@ -7,7 +7,7 @@ "core": "esp32", "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM", "f_cpu": "240000000L", - "f_flash": "40000000L", + "f_flash": "80000000L", "flash_mode": "qio", "mcu": "esp32", "variant": "m5stack_core2" diff --git a/boards/m5stack-station.json b/boards/m5stack-station.json new file mode 100644 index 000000000..31693d501 --- /dev/null +++ b/boards/m5stack-station.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5Stack_Station", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stack_station" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack Station", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 4521984, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/mgbot-iotik32a.json b/boards/mgbot-iotik32a.json index 7cab2a56e..b4dc416f5 100644 --- a/boards/mgbot-iotik32a.json +++ b/boards/mgbot-iotik32a.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_MGBOT_IOTIK32A", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "mgbot-iotik32a" }, diff --git a/boards/mgbot-iotik32b.json b/boards/mgbot-iotik32b.json index 86e1cce2c..15f3d8535 100644 --- a/boards/mgbot-iotik32b.json +++ b/boards/mgbot-iotik32b.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_MGBOT_IOTIK32B", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "mgbot-iotik32b" }, diff --git a/boards/minimain_esp32s2.json b/boards/minimain_esp32s2.json new file mode 100644 index 000000000..0f537fd7b --- /dev/null +++ b/boards/minimain_esp32s2.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DEPARTMENT_OF_ALCHEMY_MINIMAIN_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80FF" + ] + ], + "mcu": "esp32s2", + "variant": "department_of_alchemy_minimain_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deparment of Alchemy MiniMain ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/DepartmentOfAlchemy/minimain-esp32-s2", + "vendor": "Deparment of Alchemy" +} diff --git a/boards/qtpy-esp32-s2.json b/boards/nodemcu-32s2.json similarity index 67% rename from boards/qtpy-esp32-s2.json rename to boards/nodemcu-32s2.json index 73d927da5..984b90d2b 100644 --- a/boards/qtpy-esp32-s2.json +++ b/boards/nodemcu-32s2.json @@ -1,15 +1,15 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM", + "extra_flags": "-DARDUINO_ESP32S2_DEV", "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", "mcu": "esp32s2", - "variant": "adafruit_qtpy_esp32s2" + "variant": "esp32s2" }, "connectivity": [ "wifi" @@ -21,14 +21,14 @@ "arduino", "espidf" ], - "name": "Adafruit QT Py ESP32-S2", + "name": "Ai-Thinker NodeMCU-32S2 (ESP-12K)", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, "require_upload_port": true, - "speed": 921600 + "speed": 460800 }, - "url": "https://www.adafruit.com/product/5325", - "vendor": "Adafruit" + "url": "https://docs.ai-thinker.com/en/esp32s2", + "vendor": "Ai-Thinker" } diff --git a/boards/nscreen-32.json b/boards/nscreen-32.json index 07cfcc83b..d9b3a40af 100644 --- a/boards/nscreen-32.json +++ b/boards/nscreen-32.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_ESP32_DEV", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "hwids": [ [ "0x0403", diff --git a/boards/odroid_esp32.json b/boards/odroid_esp32.json index 74a9398c3..0634df32a 100644 --- a/boards/odroid_esp32.json +++ b/boards/odroid_esp32.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_ODROID_ESP32 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "odroid_esp32" }, diff --git a/boards/sparkfun_esp32_iot_redboard.json b/boards/sparkfun_esp32_iot_redboard.json new file mode 100644 index 000000000..b451c8812 --- /dev/null +++ b/boards/sparkfun_esp32_iot_redboard.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_IOT_REDBOARD" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "sparkfun_esp32_iot_redboard" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32 IoT RedBoard", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/19177", + "vendor": "SparkFun" +} diff --git a/boards/sparkfun_esp32micromod.json b/boards/sparkfun_esp32micromod.json index 2d0f52e8a..16fb0f168 100644 --- a/boards/sparkfun_esp32micromod.json +++ b/boards/sparkfun_esp32micromod.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_ESP32_MICROMOD", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "esp32micromod" }, diff --git a/boards/sparkfun_esp32s2_thing_plus_c.json b/boards/sparkfun_esp32s2_thing_plus_c.json new file mode 100644 index 000000000..01aaed7cb --- /dev/null +++ b/boards/sparkfun_esp32s2_thing_plus_c.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_THING_PLUS_C", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32thing_plus_c" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32 Thing Plus C", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/18018", + "vendor": "SparkFun" +} diff --git a/boards/sparkfun_lora_gateway_1-channel.json b/boards/sparkfun_lora_gateway_1-channel.json index 8d6cc7152..16eb8438c 100644 --- a/boards/sparkfun_lora_gateway_1-channel.json +++ b/boards/sparkfun_lora_gateway_1-channel.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_ESP32_DEV", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "sparkfun_lora_gateway_1-channel" }, diff --git a/boards/tamc_termod_s3.json b/boards/tamc_termod_s3.json new file mode 100644 index 000000000..a0301e12c --- /dev/null +++ b/boards/tamc_termod_s3.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TAMC_TERMOD_S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "tamc_termod_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TAMC Termod S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://termod-s3.readthedocs.io/en/latest/", + "vendor": "TAMC" +} diff --git a/boards/tinypico.json b/boards/tinypico.json index 9f3deeabb..0b1302e8a 100644 --- a/boards/tinypico.json +++ b/boards/tinypico.json @@ -11,8 +11,8 @@ "-mfix-esp32-psram-cache-strategy=memw" ], "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "um_tinypico" }, diff --git a/boards/trueverit-iot-driver-mk3.json b/boards/trueverit-iot-driver-mk3.json index c74f96011..0b394a723 100644 --- a/boards/trueverit-iot-driver-mk3.json +++ b/boards/trueverit-iot-driver-mk3.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver_MK_III", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "esp32-trueverit-iot-driver-mkiii" }, diff --git a/boards/ttgo-t-simcam.json b/boards/ttgo-t-simcam.json new file mode 100644 index 000000000..1f3314e05 --- /dev/null +++ b/boards/ttgo-t-simcam.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_ESP32S3_CAM_LCD", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "LilyGo T-SIMCAM ESP32-S3 16M QIO Flash 8MB OPI PSRAM", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "before_reset": "usb_reset", + "speed": 460800 + }, + "url": "https://github.com/Xinyuan-LilyGO/LilyGo-Camera-Series", + "vendor": "LilyGo" +} diff --git a/boards/ttgo-t7-v13-mini32.json b/boards/ttgo-t7-v13-mini32.json index 531dbb78b..21552df94 100644 --- a/boards/ttgo-t7-v13-mini32.json +++ b/boards/ttgo-t7-v13-mini32.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_TTGO_T7_V13_Mini32", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "ttgo-t7-v13-mini32" }, diff --git a/boards/ttgo-t7-v14-mini32.json b/boards/ttgo-t7-v14-mini32.json index a5d5a7aaa..23d327196 100644 --- a/boards/ttgo-t7-v14-mini32.json +++ b/boards/ttgo-t7-v14-mini32.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_TTGO_T7_V14_Mini32", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "ttgo-t7-v14-mini32" }, diff --git a/boards/um_feathers3.json b/boards/um_feathers3.json index a0d393510..5a3402f47 100644 --- a/boards/um_feathers3.json +++ b/boards/um_feathers3.json @@ -2,7 +2,8 @@ "build": { "arduino":{ "ldscript": "esp32s3_out.ld", - "partitions": "default_16MB.csv" + "partitions": "default_16MB.csv", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": [ diff --git a/boards/um_pros3.json b/boards/um_pros3.json index 14cbdac16..28476b69a 100644 --- a/boards/um_pros3.json +++ b/boards/um_pros3.json @@ -2,7 +2,8 @@ "build": { "arduino": { "ldscript": "esp32s3_out.ld", - "partitions": "default_16MB.csv" + "partitions": "default_16MB.csv", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": [ diff --git a/boards/um_tinys3.json b/boards/um_tinys3.json index 294733c7d..bb9ebc4d0 100644 --- a/boards/um_tinys3.json +++ b/boards/um_tinys3.json @@ -2,7 +2,8 @@ "build": { "arduino":{ "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" + "partitions": "default_8MB.csv", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": [ diff --git a/boards/unphone7.json b/boards/unphone7.json new file mode 100644 index 000000000..4204c79da --- /dev/null +++ b/boards/unphone7.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DUNPHONE_SPIN=7", + "-DARDUINO_FEATHER_ESP32" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "feather_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "unPhone 7", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unphone.net/", + "vendor": "University of Sheffield" +} diff --git a/boards/unphone8.json b/boards/unphone8.json new file mode 100644 index 000000000..8eca3333f --- /dev/null +++ b/boards/unphone8.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DUNPHONE_SPIN=8", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s3", + "variant": "unphone8" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_board": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "unPhone 8", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 2424832, + "maximum_size": 8323072, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unphone.net/", + "vendor": "University of Sheffield" +} diff --git a/boards/unphone9.json b/boards/unphone9.json new file mode 100644 index 000000000..8715bb577 --- /dev/null +++ b/boards/unphone9.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DUNPHONE_SPIN=9", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x16D0", + "0x1178" + ] + ], + "mcu": "esp32s3", + "variant": "unphone9" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_board": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "unPhone 9", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 8716288, + "maximum_size": 8323072, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unphone.net/", + "vendor": "University of Sheffield" +} diff --git a/boards/upesy_wroom.json b/boards/upesy_wroom.json index 999cef7c2..5d2553225 100644 --- a/boards/upesy_wroom.json +++ b/boards/upesy_wroom.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_uPesy_WROOM", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "uPesy_esp32_wroom_devkit" }, diff --git a/boards/upesy_wrover.json b/boards/upesy_wrover.json index 38b2eb3e7..5eb0e0fd3 100644 --- a/boards/upesy_wrover.json +++ b/boards/upesy_wrover.json @@ -11,8 +11,8 @@ "-mfix-esp32-psram-cache-strategy=memw" ], "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "uPesy_esp32_wrover_devkit" }, diff --git a/boards/adafruit_qt_py_esp32-c3.json b/boards/wifiduino32c3.json similarity index 65% rename from boards/adafruit_qt_py_esp32-c3.json rename to boards/wifiduino32c3.json index 515397eac..5b5b61675 100644 --- a/boards/adafruit_qt_py_esp32-c3.json +++ b/boards/wifiduino32c3.json @@ -1,15 +1,18 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32c3_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1", "f_cpu": "160000000L", "f_flash": "80000000L", "flash_mode": "qio", + "extra_flags": [ + "-DARDUINO_WiFiduinoV2", + "-DARDUINO_USB_MODE=1" + ], "mcu": "esp32c3", - "variant": "esp32c3" + "variant": "wifiduinov2" }, "connectivity": [ "wifi" @@ -21,7 +24,7 @@ "arduino", "espidf" ], - "name": "Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT", + "name": "Blinker WiFiduinoV2 (ESP32-C3)", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, @@ -29,6 +32,6 @@ "require_upload_port": true, "speed": 460800 }, - "url": "https://www.adafruit.com/product/5405", - "vendor": "Adafruit" + "url": "https://diandeng.tech", + "vendor": "Blinker" } diff --git a/boards/wifiduino32s3.json b/boards/wifiduino32s3.json new file mode 100644 index 000000000..cb3637118 --- /dev/null +++ b/boards/wifiduino32s3.json @@ -0,0 +1,43 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_WiFiduino32S3", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "wifiduino32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Blinker WiFiduino32S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://diandeng.tech", + "vendor": "Blinker" +} diff --git a/boards/wt32-eth01.json b/boards/wt32-eth01.json index e5a5192cf..3fddb34a5 100644 --- a/boards/wt32-eth01.json +++ b/boards/wt32-eth01.json @@ -8,8 +8,8 @@ "-DARDUINO_WT32_ETH01" ], "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "wt32-eth01" }, diff --git a/boards/xinabox_cw02.json b/boards/xinabox_cw02.json index 88785abf0..527956b1e 100644 --- a/boards/xinabox_cw02.json +++ b/boards/xinabox_cw02.json @@ -6,8 +6,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_ESP32_DEV", "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32", "variant": "xinabox" }, From 6051bc51d84b0bfb486b7fe6621a088e24ce57db Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 1 Oct 2022 18:31:42 +0200 Subject: [PATCH 183/666] Update README.md --- README.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4bf8df35b..6958ca19d 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,20 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -## Stable version - -```ini -[env:stable] +### Stable Release (including ESP32-solo1) +based on Arduino Core 2.0.5 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C3, ESP32S2 and ESP32S3 +``` +[platformio] platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.1/platform-espressif32-2.0.5.1.zip -board = ... -... +framework = arduino, espidf +``` +to use the ESP32 Solo1 Arduino framework add in your env +``` +[env:esp32solo1] +board = esp32-solo1 +build_flags = -DFRAMEWORK_ARDUINO_SOLO1 ``` +The frameworks are here [https://github.com/tasmota/arduino-esp32/releases](https://github.com/tasmota/arduino-esp32/releases) # Configuration From bff7f923595771511f35555827e0c737e925846c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 1 Oct 2022 18:33:42 +0200 Subject: [PATCH 184/666] Update platformio.ini --- examples/arduino-blink/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 78d55726c..cd460664a 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -25,7 +25,7 @@ monitor_speed = 115200 [env:esp32-solo1] platform = espressif32 framework = arduino -board = esp32doit-devkit-v1 +board = esp32-solo1 build_flags = -DFRAMEWORK_ARDUINO_SOLO1 [env:esp32-ITEAD] From 3988f4f2d392a6ac37a4c347ff905c5ddf9d7141 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 1 Oct 2022 18:34:35 +0200 Subject: [PATCH 185/666] add solo1 --- boards/esp32-solo1.json | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 boards/esp32-solo1.json diff --git a/boards/esp32-solo1.json b/boards/esp32-solo1.json new file mode 100644 index 000000000..e87b7e13d --- /dev/null +++ b/boards/esp32-solo1.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV -DARDUINO_USB_CDC_ON_BOOT=0 -DCORE32SOLO1", + "f_cpu": "80000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_target": "esp32-solo-1.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif Generic ESP32-solo1 4M Flash", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Espressif" +} From 5969e220078125abc5a493db180d96d6394ee199 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 3 Oct 2022 14:16:33 +0200 Subject: [PATCH 186/666] Update platformio.ini --- examples/arduino-blink/platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index cd460664a..7f9d443e6 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -27,6 +27,7 @@ platform = espressif32 framework = arduino board = esp32-solo1 build_flags = -DFRAMEWORK_ARDUINO_SOLO1 + -DLED_BUILTIN=23 [env:esp32-ITEAD] platform = espressif32 From 66a16062eeb8b7aa85fb11fc8fd70341fadb20aa Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 3 Oct 2022 14:17:16 +0200 Subject: [PATCH 187/666] fix CI example --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index 252c1866f..6b6339aa7 100644 --- a/builder/main.py +++ b/builder/main.py @@ -123,7 +123,7 @@ def _parse_partitions(env): result = [] next_offset = 0 - bound = 0x10000 # default value + bound = int(board.get("upload.offset_address", "0x10000"), 16) # default 0x10000 with open(partitions_csv) as fp: for line in fp.readlines(): line = line.strip() From 704a6310a7ca4ae6cfb3fee13a61a5dd8c7901d1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Oct 2022 16:19:41 +0200 Subject: [PATCH 188/666] esp32 offset needed * Setting is needed for Debugger --- builder/main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index 6b6339aa7..79168c220 100644 --- a/builder/main.py +++ b/builder/main.py @@ -148,7 +148,7 @@ def _parse_partitions(env): bound = next_offset next_offset = (next_offset + bound - 1) & ~(bound - 1) #print("Main Firmware will be flashed to:", hex(bound)) - env["ESP32_APP_OFFSET"] = hex(bound) + env["ESP32_APP_OFFSET"] = str(hex(bound)) return result @@ -260,6 +260,8 @@ def __fetch_fs_size(target, source, env): "ESP32_FS_IMAGE_NAME", env.get("ESP32_SPIFFS_IMAGE_NAME", filesystem) ), + ESP32_APP_OFFSET=board.get("upload.offset_address", "0x10000"), + PROGSUFFIX=".elf" ) From 985e063fc8740a93031b5aee89b473b2b3ddd0f9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Oct 2022 15:56:57 +0200 Subject: [PATCH 189/666] Update main.py --- builder/main.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/builder/main.py b/builder/main.py index 79168c220..7f0f4f9a8 100644 --- a/builder/main.py +++ b/builder/main.py @@ -142,13 +142,13 @@ def _parse_partitions(env): } result.append(partition) next_offset = _parse_size(partition["offset"]) - #print("App start from .csv:", hex(next_offset)) - #print("Partition subtype from .csv:", partition["subtype"]) if (partition["subtype"] == "ota_0"): bound = next_offset next_offset = (next_offset + bound - 1) & ~(bound - 1) - #print("Main Firmware will be flashed to:", hex(bound)) - env["ESP32_APP_OFFSET"] = str(hex(bound)) + # Configure application partition offset + env.Replace(ESP32_APP_OFFSET=str(hex(bound))) + # Propagate application offset to debug configurations + env["INTEGRATION_EXTRA_DATA"].update({"application_offset": str(hex(bound))}) return result @@ -208,6 +208,7 @@ def __fetch_fs_size(target, source, env): if mcu == "esp32c3": toolchain_arch = "riscv32-esp" + if "INTEGRATION_EXTRA_DATA" not in env: env["INTEGRATION_EXTRA_DATA"] = {} @@ -222,8 +223,7 @@ def __fetch_fs_size(target, source, env): CC="%s-elf-gcc" % toolchain_arch, CXX="%s-elf-g++" % toolchain_arch, GDB="%s-elf-gdb" % toolchain_arch, - OBJCOPY=join( - platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), + OBJCOPY=join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), RANLIB="%s-elf-gcc-ranlib" % toolchain_arch, SIZETOOL="%s-elf-size" % toolchain_arch, @@ -260,11 +260,12 @@ def __fetch_fs_size(target, source, env): "ESP32_FS_IMAGE_NAME", env.get("ESP32_SPIFFS_IMAGE_NAME", filesystem) ), - ESP32_APP_OFFSET=board.get("upload.offset_address", "0x10000"), + ESP32_APP_OFFSET=env.get("INTEGRATION_EXTRA_DATA").get("application_offset"), PROGSUFFIX=".elf" ) + # Allow user to override via pre:script if env.get("PROGNAME", "program") == "program": env.Replace(PROGNAME="firmware") @@ -443,6 +444,7 @@ def __fetch_fs_size(target, source, env): elif upload_protocol in debug_tools: + _parse_partitions(env) openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)] openocd_args.extend( debug_tools.get(upload_protocol).get("server").get("arguments", [])) @@ -453,9 +455,7 @@ def __fetch_fs_size(target, source, env): % ( "$FS_START" if "uploadfs" in COMMAND_LINE_TARGETS - else board.get( - "upload.offset_address", "$ESP32_APP_OFFSET" - ) + else env.get("INTEGRATION_EXTRA_DATA").get("application_offset") ), ] ) @@ -510,12 +510,11 @@ def __fetch_fs_size(target, source, env): ) # -# Information about obsolete method of specifying linker scripts +# A temporary workaround to propagate additional data to the debug configuration routine # -if any("-Wl,-T" in f for f in env.get("LINKFLAGS", [])): - print("Warning! '-Wl,-T' option for specifying linker scripts is deprecated. " - "Please use 'board_build.ldscript' option in your 'platformio.ini' file.") +Import("projenv") +projenv["INTEGRATION_EXTRA_DATA"] = env.get("INTEGRATION_EXTRA_DATA") # # Default targets From 47b69fc3bd993f306dba376951f9d42b0f8d07b5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Oct 2022 15:57:40 +0200 Subject: [PATCH 190/666] Update arduino.py --- builder/frameworks/arduino.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 18e79cedd..3b96cd994 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -36,16 +36,13 @@ SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduino-solo1"), "tools", "platformio-build.py")) - env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) elif ("CORE32ITEAD" in extra_flags or "FRAMEWORK_ARDUINO_ITEAD" in build_flags) and ("arduino" in env.subst("$PIOFRAMEWORK") and "espidf" not in env.subst("$PIOFRAMEWORK")): SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduino-ITEAD"), "tools", "platformio-build.py")) - env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) elif "arduino" in env.subst("$PIOFRAMEWORK") and "CORE32SOLO1" not in extra_flags and "FRAMEWORK_ARDUINO_SOLO1" not in build_flags and "CORE32ITEAD" not in extra_flags and "FRAMEWORK_ARDUINO_ITEAD" not in build_flags and "espidf" not in env.subst("$PIOFRAMEWORK"): SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) - env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) From 56990ac91cbe94f4e90ff2284027297dddede87b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Oct 2022 15:58:09 +0200 Subject: [PATCH 191/666] Fix ESP32 Offset for OCD --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index 5aae48548..80c953181 100644 --- a/platform.py +++ b/platform.py @@ -205,7 +205,7 @@ def configure_debug_session(self, debug_config): 'monitor program_esp "{%s.bin}" %s verify' % ( to_unix_path(debug_config.build_data["prog_path"][:-4]), - build_extra_data.get("application_offset", "0x10000"), + build_extra_data.get("application_offset"), ) ) debug_config.load_cmds = load_cmds From 6f12883142879b2ba698a2dca7c0147c5793d9ca Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 7 Oct 2022 18:51:05 +0200 Subject: [PATCH 192/666] align with upstream --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index 80c953181..5aae48548 100644 --- a/platform.py +++ b/platform.py @@ -205,7 +205,7 @@ def configure_debug_session(self, debug_config): 'monitor program_esp "{%s.bin}" %s verify' % ( to_unix_path(debug_config.build_data["prog_path"][:-4]), - build_extra_data.get("application_offset"), + build_extra_data.get("application_offset", "0x10000"), ) ) debug_config.load_cmds = load_cmds From bd48023124c6221d6c438b7fb8ac4cc752a564df Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 7 Oct 2022 18:51:54 +0200 Subject: [PATCH 193/666] rm not needed `projenv` --- builder/main.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/builder/main.py b/builder/main.py index 7f0f4f9a8..e95eeca99 100644 --- a/builder/main.py +++ b/builder/main.py @@ -208,7 +208,6 @@ def __fetch_fs_size(target, source, env): if mcu == "esp32c3": toolchain_arch = "riscv32-esp" - if "INTEGRATION_EXTRA_DATA" not in env: env["INTEGRATION_EXTRA_DATA"] = {} @@ -265,7 +264,6 @@ def __fetch_fs_size(target, source, env): PROGSUFFIX=".elf" ) - # Allow user to override via pre:script if env.get("PROGNAME", "program") == "program": env.Replace(PROGNAME="firmware") @@ -509,13 +507,6 @@ def __fetch_fs_size(target, source, env): "Erase Flash", ) -# -# A temporary workaround to propagate additional data to the debug configuration routine -# - -Import("projenv") -projenv["INTEGRATION_EXTRA_DATA"] = env.get("INTEGRATION_EXTRA_DATA") - # # Default targets # From 40e5dc48ba2f7efea2e159df37073313c3b95be6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Oct 2022 13:57:04 +0200 Subject: [PATCH 194/666] Install and use only needed framework --- builder/main.py | 2 -- platform.json | 7 +++---- platform.py | 14 ++++++++++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/builder/main.py b/builder/main.py index e95eeca99..dc195c8e7 100644 --- a/builder/main.py +++ b/builder/main.py @@ -34,10 +34,8 @@ if "CORE32SOLO1" in extra_flags or "FRAMEWORK_ARDUINO_SOLO1" in build_flags: FRAMEWORK_DIR = platform.get_package_dir("framework-arduino-solo1") - print ("Solo1 framework will be used") elif "CORE32ITEAD" in extra_flags or "FRAMEWORK_ARDUINO_ITEAD" in build_flags: FRAMEWORK_DIR = platform.get_package_dir("framework-arduino-ITEAD") - print ("ITEAD framework will be used") else: FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") diff --git a/platform.json b/platform.json index 94484b4ef..2d120bb2f 100644 --- a/platform.json +++ b/platform.json @@ -34,19 +34,19 @@ "packages": { "framework-arduinoespressif32": { "type": "framework", - "optional": false, + "optional": true, "owner": "tasmota", "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", - "optional": false, + "optional": true, "owner": "tasmota", "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", - "optional": false, + "optional": true, "owner": "tasmota", "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32-ITEAD.zip" }, @@ -135,4 +135,3 @@ } } } - diff --git a/platform.py b/platform.py index 5aae48548..b0c582f6c 100644 --- a/platform.py +++ b/platform.py @@ -32,8 +32,18 @@ def configure_default_packages(self, variables, targets): board_config = self.board_config(variables.get("board")) mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32")) + core_variant_board = ''.join(variables.get("board_build.extra_flags", board_config.get("build.extra_flags", ""))) + core_variant_board = core_variant_board.replace("-D", " ") + core_variant_build = (''.join(variables.get("build_flags", []))).replace("-D", " ") frameworks = variables.get("pioframework", []) + if "CORE32SOLO1" in core_variant_board or "FRAMEWORK_ARDUINO_SOLO1" in core_variant_build: + self.packages["framework-arduino-solo1"]["optional"] = False + elif "CORE32ITEAD" in core_variant_board or "FRAMEWORK_ARDUINO_ITEAD" in core_variant_build: + self.packages["framework-arduino-ITEAD"]["optional"] = False + else: + self.packages["framework-arduinoespressif32"]["optional"] = False + if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "spiffs") if filesystem == "littlefs": @@ -47,10 +57,6 @@ def configure_default_packages(self, variables, targets): if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False - build_core = variables.get( - "board_build.core", board_config.get("build.core", "arduino") - ).lower() - if "espidf" in frameworks: # Common packages for IDF and mixed Arduino+IDF projects self.packages["toolchain-esp32ulp"]["optional"] = False From f53ca2d78dcf6d1573853a95abd05e9a066ef2ff Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Oct 2022 14:13:27 +0200 Subject: [PATCH 195/666] Install and use only needed framework (#43) --- builder/main.py | 2 -- platform.json | 7 +++---- platform.py | 14 ++++++++++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/builder/main.py b/builder/main.py index e95eeca99..dc195c8e7 100644 --- a/builder/main.py +++ b/builder/main.py @@ -34,10 +34,8 @@ if "CORE32SOLO1" in extra_flags or "FRAMEWORK_ARDUINO_SOLO1" in build_flags: FRAMEWORK_DIR = platform.get_package_dir("framework-arduino-solo1") - print ("Solo1 framework will be used") elif "CORE32ITEAD" in extra_flags or "FRAMEWORK_ARDUINO_ITEAD" in build_flags: FRAMEWORK_DIR = platform.get_package_dir("framework-arduino-ITEAD") - print ("ITEAD framework will be used") else: FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") diff --git a/platform.json b/platform.json index 94484b4ef..2d120bb2f 100644 --- a/platform.json +++ b/platform.json @@ -34,19 +34,19 @@ "packages": { "framework-arduinoespressif32": { "type": "framework", - "optional": false, + "optional": true, "owner": "tasmota", "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", - "optional": false, + "optional": true, "owner": "tasmota", "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", - "optional": false, + "optional": true, "owner": "tasmota", "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32-ITEAD.zip" }, @@ -135,4 +135,3 @@ } } } - diff --git a/platform.py b/platform.py index 5aae48548..b0c582f6c 100644 --- a/platform.py +++ b/platform.py @@ -32,8 +32,18 @@ def configure_default_packages(self, variables, targets): board_config = self.board_config(variables.get("board")) mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32")) + core_variant_board = ''.join(variables.get("board_build.extra_flags", board_config.get("build.extra_flags", ""))) + core_variant_board = core_variant_board.replace("-D", " ") + core_variant_build = (''.join(variables.get("build_flags", []))).replace("-D", " ") frameworks = variables.get("pioframework", []) + if "CORE32SOLO1" in core_variant_board or "FRAMEWORK_ARDUINO_SOLO1" in core_variant_build: + self.packages["framework-arduino-solo1"]["optional"] = False + elif "CORE32ITEAD" in core_variant_board or "FRAMEWORK_ARDUINO_ITEAD" in core_variant_build: + self.packages["framework-arduino-ITEAD"]["optional"] = False + else: + self.packages["framework-arduinoespressif32"]["optional"] = False + if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "spiffs") if filesystem == "littlefs": @@ -47,10 +57,6 @@ def configure_default_packages(self, variables, targets): if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False - build_core = variables.get( - "board_build.core", board_config.get("build.core", "arduino") - ).lower() - if "espidf" in frameworks: # Common packages for IDF and mixed Arduino+IDF projects self.packages["toolchain-esp32ulp"]["optional"] = False From de9f0f374cc178ddcb3a0e0d4672f327aefa1f37 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 15 Oct 2022 11:42:41 +0200 Subject: [PATCH 196/666] rm overlooked "mbctool" --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index b0c582f6c..3226e326b 100644 --- a/platform.py +++ b/platform.py @@ -100,7 +100,7 @@ def _add_dynamic_options(self, board): # debug tools debug = board.manifest.get("debug", {}) - non_debug_protocols = ["esptool", "espota", "mbctool"] + non_debug_protocols = ["esptool", "espota"] supported_debug_tools = [ "cmsis-dap", "esp-prog", From e60b7dfa768a5d6849b897e73e1cd2d2aba71161 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 16 Oct 2022 13:03:45 +0200 Subject: [PATCH 197/666] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6958ca19d..24ee05410 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,12 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -### Stable Release (including ESP32-solo1) +### Stable Release supporting Arduino and IDF (including ESP32-solo1) based on Arduino Core 2.0.5 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C3, ESP32S2 and ESP32S3 ``` [platformio] platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.1/platform-espressif32-2.0.5.1.zip -framework = arduino, espidf +framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env ``` From 57b4280b5095c34f374913cb26780042cb638fab Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 16 Oct 2022 13:04:48 +0200 Subject: [PATCH 198/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 24ee05410..885fbf0ed 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -### Stable Release supporting Arduino and IDF (including ESP32-solo1) +### Stable Release supporting Arduino and IDF based on Arduino Core 2.0.5 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C3, ESP32S2 and ESP32S3 ``` [platformio] From a8e3fe8e577e0ee8e917a3ee27fd93b50a6cc65a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 16 Oct 2022 13:42:06 +0200 Subject: [PATCH 199/666] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6958ca19d..885fbf0ed 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,12 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -### Stable Release (including ESP32-solo1) +### Stable Release supporting Arduino and IDF based on Arduino Core 2.0.5 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C3, ESP32S2 and ESP32S3 ``` [platformio] platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.1/platform-espressif32-2.0.5.1.zip -framework = arduino, espidf +framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env ``` From 8c192639bd8e12a6a1ef9edbed6b6c47a6adeb21 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 17 Oct 2022 18:16:04 +0200 Subject: [PATCH 200/666] esptool v4.3.1 increased flash speed for S2/S3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 2d120bb2f..c752c7527 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.3/esptool-4.3.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.3.1/esptool-4.3.1.zip" }, "tool-openocd-esp32": { "type": "debugger", From 5236895ad459932c90b0fb1090a1b915e00f7895 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 28 Oct 2022 10:52:10 +0200 Subject: [PATCH 201/666] 2.0.5.2 --- platform.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform.json b/platform.json index c752c7527..d7f02afe5 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.5", + "version": "2.0.5+2", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -36,25 +36,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/v2.0.5.2/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1038/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.1/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1037/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.5/esp-idf-v4.4.3.5.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.6/esp-idf-v4.4.3.6.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 81127ef24d3c2302cdfc849c5c3fc49cd6fa2be3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 28 Oct 2022 11:04:03 +0200 Subject: [PATCH 202/666] Update examples.yml --- .github/workflows/examples.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 0f765c7bc..5298cbc35 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -1,13 +1,18 @@ name: Examples -on: [push, pull_request] +on: + workflow_dispatch: # Manually start a workflow + push: + paths-ignore: + - '.github/**' # Ignore changes towards the .github directory + - '**.md' # Do no build if *.md files changes jobs: build: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest, windows-latest, macOS-12] example: - "examples/arduino-ble5-advertising" - "examples/arduino-blink" @@ -34,7 +39,7 @@ jobs: with: submodules: "recursive" - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: "3.9" - name: Install dependencies From d6a5467931000cca150de327391e5d3eae0e491c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 28 Oct 2022 11:23:10 +0200 Subject: [PATCH 203/666] Tasmota repo --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index d7f02afe5..a263c52a9 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/v2.0.5.2/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.2/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1038/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.2/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1037/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.2/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", From 43b3aec1bc75c66a765760c61ac81cff08c21c17 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 28 Oct 2022 11:33:37 +0200 Subject: [PATCH 204/666] Change readme to 2.0.5.2 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 885fbf0ed..b02ad818d 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid based on Arduino Core 2.0.5 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C3, ESP32S2 and ESP32S3 ``` [platformio] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.1/platform-espressif32-2.0.5.1.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.2/platform-espressif32-2.0.5.2.zip framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env From 4c98c14b61f35824b45d18f79f336f62b66c8cc0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 1 Nov 2022 13:28:23 +0100 Subject: [PATCH 205/666] Sort ULP Sources order via the filenames. --- builder/frameworks/ulp.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 1ec152cd3..c99dceebf 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -82,6 +82,7 @@ def generate_ulp_config(target_config): riscv_ulp_enabled = sdk_config.get((idf_variant).upper() + "_ULP_COPROC_RISCV", False) ulp_sources = collect_ulp_sources() + ulp_sources.sort() cmd = ( os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), "-DCMAKE_GENERATOR=Ninja", From f9bcd7d3c8ae6a798382cdcfe1525d6176e059d6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 4 Nov 2022 19:23:19 +0100 Subject: [PATCH 206/666] Flash mode correcting for IDF too --- builder/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index dc195c8e7..4291298ee 100644 --- a/builder/main.py +++ b/builder/main.py @@ -78,7 +78,7 @@ def _get_board_f_flash(env): def _get_board_flash_mode(env): - if ["arduino"] == env.get("PIOFRAMEWORK") and _get_board_memory_type(env) in ( + if _get_board_memory_type(env) in ( "opi_opi", "opi_qspi", ): @@ -93,7 +93,7 @@ def _get_board_flash_mode(env): def _get_board_boot_mode(env): memory_type = env.BoardConfig().get("build.arduino.memory_type", "") build_boot = env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE") - if ["arduino"] == env.get("PIOFRAMEWORK") and memory_type in ("opi_opi", "opi_qspi"): + if memory_type in ("opi_opi", "opi_qspi"): build_boot = "opi" return build_boot From 08c90790d0c225c791b8388a8534fad61c986c5c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 10 Nov 2022 11:40:00 +0100 Subject: [PATCH 207/666] Tasmota core 2.0.5.3 / IDF4.4.3 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index a263c52a9..ddf3f798b 100644 --- a/platform.json +++ b/platform.json @@ -36,25 +36,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.2/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.2/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.2/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.6/esp-idf-v4.4.3.6.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 01d743d82d84c270cd8dee42399a93fbf39564fd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 10 Nov 2022 11:41:10 +0100 Subject: [PATCH 208/666] Platformio 2.0.5+3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index ddf3f798b..283ea18e9 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.5+2", + "version": "2.0.5+3", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From 5c4b1590adbce295d66349113efa9c5cc1fbe79a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 10 Nov 2022 11:47:08 +0100 Subject: [PATCH 209/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b02ad818d..cbcd50ef0 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid based on Arduino Core 2.0.5 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C3, ESP32S2 and ESP32S3 ``` [platformio] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.2/platform-espressif32-2.0.5.2.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.3/platform-espressif32-2.0.5.3.zip framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env From 65ccd8d9edb2a2931fe768bcbfec77d605e11f3c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 23 Nov 2022 21:57:58 +0100 Subject: [PATCH 210/666] esptool v4.4 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 283ea18e9..939460e6b 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.3.1/esptool-4.3.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4/esptool-4.4.zip" }, "tool-openocd-esp32": { "type": "debugger", From 14abe1a834a0a69a951dac809a260c1ad2fdaa40 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 23 Nov 2022 22:00:22 +0100 Subject: [PATCH 211/666] esptool v4.4 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 283ea18e9..939460e6b 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.3.1/esptool-4.3.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4/esptool-4.4.zip" }, "tool-openocd-esp32": { "type": "debugger", From 4dab852b2cbc988bc839744adcf5f4edbe30f584 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 23 Nov 2022 22:12:43 +0100 Subject: [PATCH 212/666] Change Platform versioning version: 2.0.5+20221125 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 939460e6b..b5735696f 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.5+3", + "version": "2.0.5+20221125", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From f3c96764d2af0ad979b4215b1bc36df0ed4e4edb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 23 Nov 2022 22:18:23 +0100 Subject: [PATCH 213/666] Change versioning for Platform --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 939460e6b..b5735696f 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.5+3", + "version": "2.0.5+20221125", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From 94c9135697d320bc9b72838aa7a995723eaec968 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 23 Nov 2022 22:44:40 +0100 Subject: [PATCH 214/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cbcd50ef0..fe1e4d98f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid based on Arduino Core 2.0.5 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C3, ESP32S2 and ESP32S3 ``` [platformio] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.3/platform-espressif32-2.0.5.3.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/v.2.0.5/platform-espressif32-v.2.0.5.zip framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env From 4a36a6a89d2b0a031df0ac2f525c2cbf91600c70 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 24 Nov 2022 11:25:43 +0100 Subject: [PATCH 215/666] Update examples.yml --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 5298cbc35..e8696dfff 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -41,7 +41,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.9" + python-version: "3.11" - name: Install dependencies run: | pip install -U https://github.com/platformio/platformio/archive/develop.zip From 45409e0487a0390b21ade1a30bcf82947c66fa46 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 24 Nov 2022 11:49:46 +0100 Subject: [PATCH 216/666] Ubuntu 22.04 --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index e8696dfff..feb3e7a24 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macOS-12] + os: [ubuntu-22.04, windows-2022, macOS-12] example: - "examples/arduino-ble5-advertising" - "examples/arduino-blink" From 5cff9b08bdabd44a06d0e104f6d27f90afcdb319 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 24 Nov 2022 12:03:32 +0100 Subject: [PATCH 217/666] pip install wheel --- .github/workflows/examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index feb3e7a24..a4a33198a 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -44,6 +44,7 @@ jobs: python-version: "3.11" - name: Install dependencies run: | + pip install wheel pip install -U https://github.com/platformio/platformio/archive/develop.zip pio pkg install --global --platform symlink://. - name: Build examples From 0d4c8f2cfabf590bb93911d17239deedb89d3953 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 24 Nov 2022 21:23:09 +0100 Subject: [PATCH 218/666] use cdn.jsdelivr.net --- platform.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform.json b/platform.json index b5735696f..6a396bcd0 100644 --- a/platform.json +++ b/platform.json @@ -36,25 +36,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32.zip" + "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" + "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" + "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" + "version": "https://cdn.jsdelivr.net/gh/tasmota/esp-idf@releases/download/v4.4.3/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4/esptool-4.4.zip" + "version": "https://cdn.jsdelivr.net/gh/tasmota/esptool@releases/download/v4.4/esptool-4.4.zip" }, "tool-openocd-esp32": { "type": "debugger", From bd637aaad7305e6005ce86898884ef610ac8d519 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 24 Nov 2022 21:25:31 +0100 Subject: [PATCH 219/666] use cdn.jsdelivr.net --- platform.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform.json b/platform.json index b5735696f..6a396bcd0 100644 --- a/platform.json +++ b/platform.json @@ -36,25 +36,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32.zip" + "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" + "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" + "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" + "version": "https://cdn.jsdelivr.net/gh/tasmota/esp-idf@releases/download/v4.4.3/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4/esptool-4.4.zip" + "version": "https://cdn.jsdelivr.net/gh/tasmota/esptool@releases/download/v4.4/esptool-4.4.zip" }, "tool-openocd-esp32": { "type": "debugger", From 479fcdf189b8169f67e492e3c5a5fa21aebce9ba Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 24 Nov 2022 21:33:52 +0100 Subject: [PATCH 220/666] revert cdn --- platform.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform.json b/platform.json index 6a396bcd0..b5735696f 100644 --- a/platform.json +++ b/platform.json @@ -36,25 +36,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://cdn.jsdelivr.net/gh/tasmota/esp-idf@releases/download/v4.4.3/esp-idf-v4.4.3.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://cdn.jsdelivr.net/gh/tasmota/esptool@releases/download/v4.4/esptool-4.4.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4/esptool-4.4.zip" }, "tool-openocd-esp32": { "type": "debugger", From 421daed21ef4c8f4800aa6de71d074fab8dade21 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 24 Nov 2022 21:36:54 +0100 Subject: [PATCH 221/666] revert cdn --- platform.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform.json b/platform.json index 6a396bcd0..b5735696f 100644 --- a/platform.json +++ b/platform.json @@ -36,25 +36,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://cdn.jsdelivr.net/gh/tasmota/arduino-esp32@releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://cdn.jsdelivr.net/gh/tasmota/esp-idf@releases/download/v4.4.3/esp-idf-v4.4.3.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://cdn.jsdelivr.net/gh/tasmota/esptool@releases/download/v4.4/esptool-4.4.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4/esptool-4.4.zip" }, "tool-openocd-esp32": { "type": "debugger", From 04d66996b705c7200323f8677fac9f55f40a707c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 1 Dec 2022 13:53:24 +0100 Subject: [PATCH 222/666] Normalize path in the "IDF_PATH" variable --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 54c0cb382..f47c9f892 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -214,7 +214,7 @@ def get_cmake_code_model(src_dir, build_dir, extra_args=None): def populate_idf_env_vars(idf_env): - idf_env["IDF_PATH"] = FRAMEWORK_DIR + idf_env["IDF_PATH"] = fs.to_unix_path(FRAMEWORK_DIR) additional_packages = [ os.path.join(TOOLCHAIN_DIR, "bin"), platform.get_package_dir("tool-ninja"), From 856ee60a64ebccbaef6a5fc57f157e75fa7b7776 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 1 Dec 2022 13:59:53 +0100 Subject: [PATCH 223/666] fix HwID --- boards/um_pros3.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/um_pros3.json b/boards/um_pros3.json index 28476b69a..c73aa3686 100644 --- a/boards/um_pros3.json +++ b/boards/um_pros3.json @@ -16,8 +16,8 @@ "flash_mode": "qio", "hwids": [ [ - "0X303A", - "0x80D0" + "0x303A", + "0x1001" ] ], "mcu": "esp32s3", From 46d776ecf4e8cecdbdc150df27601af3a333a5cc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 1 Dec 2022 14:04:19 +0100 Subject: [PATCH 224/666] upgrade pip to latest --- .github/workflows/examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index a4a33198a..16914ac72 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -44,6 +44,7 @@ jobs: python-version: "3.11" - name: Install dependencies run: | + python -m pip install --upgrade pip pip install wheel pip install -U https://github.com/platformio/platformio/archive/develop.zip pio pkg install --global --platform symlink://. From ef292705c2dfc3afd77342f713d90d9e24bcebee Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 11 Dec 2022 16:18:57 +0100 Subject: [PATCH 225/666] use wheel to install pip dependencies --- builder/frameworks/espidf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index f47c9f892..9477160cd 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1042,6 +1042,7 @@ def _get_installed_pip_packages(): deps = { # https://github.com/platformio/platform-espressif32/issues/635 + "wheel": ">=0.35.1", "cryptography": ">=2.1.4,<35.0.0", "future": ">=0.15.2", "pyparsing": ">=2.0.3,<2.4.0", From 6b46d32ba1b8acb0cc6a1bc4da85d969e24018e5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 11 Dec 2022 16:48:28 +0100 Subject: [PATCH 226/666] esptool.py v4.4.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index b5735696f..29a051b7e 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4/esptool-4.4.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4.1/esptool-4.4.1.zip" }, "tool-openocd-esp32": { "type": "debugger", From b9fd95d3fad4c6925069f1f038d358d2873ae51a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 11 Dec 2022 16:53:49 +0100 Subject: [PATCH 227/666] esptool.py v4.4.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index b5735696f..29a051b7e 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4/esptool-4.4.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4.1/esptool-4.4.1.zip" }, "tool-openocd-esp32": { "type": "debugger", From 8546e882282968126f9349b3106d980b050d0700 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 17 Dec 2022 13:39:20 +0100 Subject: [PATCH 228/666] minor updates (#46) * esptool v4.4 * Change Platform versioning version: 2.0.5+20221125 * Update examples.yml * Ubuntu 22.04 * pip install wheel * use cdn.jsdelivr.net * revert cdn * Normalize path in the "IDF_PATH" variable * fix HwID * upgrade pip to latest * use wheel to install pip dependencies * esptool.py v4.4.1 --- .github/workflows/examples.yml | 6 ++++-- boards/um_pros3.json | 4 ++-- builder/frameworks/espidf.py | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 5298cbc35..16914ac72 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macOS-12] + os: [ubuntu-22.04, windows-2022, macOS-12] example: - "examples/arduino-ble5-advertising" - "examples/arduino-blink" @@ -41,9 +41,11 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.9" + python-version: "3.11" - name: Install dependencies run: | + python -m pip install --upgrade pip + pip install wheel pip install -U https://github.com/platformio/platformio/archive/develop.zip pio pkg install --global --platform symlink://. - name: Build examples diff --git a/boards/um_pros3.json b/boards/um_pros3.json index 28476b69a..c73aa3686 100644 --- a/boards/um_pros3.json +++ b/boards/um_pros3.json @@ -16,8 +16,8 @@ "flash_mode": "qio", "hwids": [ [ - "0X303A", - "0x80D0" + "0x303A", + "0x1001" ] ], "mcu": "esp32s3", diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 54c0cb382..9477160cd 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -214,7 +214,7 @@ def get_cmake_code_model(src_dir, build_dir, extra_args=None): def populate_idf_env_vars(idf_env): - idf_env["IDF_PATH"] = FRAMEWORK_DIR + idf_env["IDF_PATH"] = fs.to_unix_path(FRAMEWORK_DIR) additional_packages = [ os.path.join(TOOLCHAIN_DIR, "bin"), platform.get_package_dir("tool-ninja"), @@ -1042,6 +1042,7 @@ def _get_installed_pip_packages(): deps = { # https://github.com/platformio/platform-espressif32/issues/635 + "wheel": ">=0.35.1", "cryptography": ">=2.1.4,<35.0.0", "future": ">=0.15.2", "pyparsing": ">=2.0.3,<2.4.0", From a5ca72040ff6befd9ddc487f2b7a8dc4ec35355c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 17 Dec 2022 13:44:32 +0100 Subject: [PATCH 229/666] Version change --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 29a051b7e..985c9ce99 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.5+20221125", + "version": "2022.12.0", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", From bbb1759a3b2a8f22a1a7c5936dffb7aaf7294b16 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 17 Dec 2022 14:25:20 +0100 Subject: [PATCH 230/666] Tasmota Core 2.0.5.4 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 29a051b7e..985c9ce99 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2.0.5+20221125", + "version": "2022.12.0", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.3/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", From dc85603811749bec969bab72a4e2366822cae271 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 21 Dec 2022 23:52:02 +0100 Subject: [PATCH 231/666] Target: Erase Flash and Upload --- builder/main.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/builder/main.py b/builder/main.py index 4291298ee..2265e7018 100644 --- a/builder/main.py +++ b/builder/main.py @@ -491,6 +491,21 @@ def __fetch_fs_size(target, source, env): env.AddPlatformTarget( "uploadfsota", target_firm, upload_actions, "Upload Filesystem Image OTA") +# +# Target: Erase Flash and Upload +# + +env.AddPlatformTarget( + "erase_upload", + target_firm, + [ + env.VerboseAction(env.AutodetectUploadPort, "Looking for serial port..."), + env.VerboseAction("$ERASECMD", "Erasing..."), + env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE") + ], + "Erase Flash and Upload", +) + # # Target: Erase Flash # From a6853e52b52ce2ff722f1c644bfe946512f6c9e9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 22 Dec 2022 10:25:15 +0100 Subject: [PATCH 232/666] zopfli --- builder/frameworks/arduino.py | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 3b96cd994..0c450916d 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -46,3 +46,47 @@ SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) + +def install_python_deps(): + def _get_installed_pip_packages(): + result = {} + packages = {} + pip_output = subprocess.check_output( + [env.subst("$PYTHONEXE"), "-m", "pip", "list", "--format=json"] + ) + try: + packages = json.loads(pip_output) + except: + print("Warning! Couldn't extract the list of installed Python packages.") + return {} + for p in packages: + result[p["name"]] = pepver_to_semver(p["version"]) + + return result + + deps = { + "zopfli": ">=0.2.2" + } + + installed_packages = _get_installed_pip_packages() + packages_to_install = [] + for package, spec in deps.items(): + if package not in installed_packages: + packages_to_install.append(package) + else: + version_spec = semantic_version.Spec(spec) + if not version_spec.match(installed_packages[package]): + packages_to_install.append(package) + + if packages_to_install: + env.Execute( + env.VerboseAction( + ( + '"$PYTHONEXE" -m pip install -U --force-reinstall ' + + " ".join(['"%s%s"' % (p, deps[p]) for p in packages_to_install]) + ), + "Installing Python dependencies", + ) + ) + +install_python_deps() From 0279e34f7375ea429536f9c6ff2da950aadec384 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 22 Dec 2022 10:28:37 +0100 Subject: [PATCH 233/666] add missing imports --- builder/frameworks/arduino.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 0c450916d..ebbc269b5 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -22,8 +22,13 @@ http://arduino.cc/en/Reference/HomePage """ +import subprocess +import json +import semantic_version from os.path import join -from SCons.Script import DefaultEnvironment, SConscript + +from SCons.Script import COMMAND_LINE_TARGETS, DefaultEnvironment, SConscript +from platformio.package.version import pepver_to_semver env = DefaultEnvironment() From 1827814c451863201c0a31ddb5f194750b2bdbd9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 22 Dec 2022 10:31:19 +0100 Subject: [PATCH 234/666] "version": "2022.12.1" --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 985c9ce99..369154519 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2022.12.0", + "version": "2022.12.1", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From 7ba31d4554b8aceb84abadad1e2cb3613dd0f1a5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 22 Dec 2022 10:43:14 +0100 Subject: [PATCH 235/666] Target: Erase and Upload (#48) * Target: Erase Flash and Upload * zopfli * "version": "2022.12.1" --- builder/frameworks/arduino.py | 51 ++++++++++++++++++++++++++++++++++- builder/main.py | 15 +++++++++++ platform.json | 2 +- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 3b96cd994..ebbc269b5 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -22,8 +22,13 @@ http://arduino.cc/en/Reference/HomePage """ +import subprocess +import json +import semantic_version from os.path import join -from SCons.Script import DefaultEnvironment, SConscript + +from SCons.Script import COMMAND_LINE_TARGETS, DefaultEnvironment, SConscript +from platformio.package.version import pepver_to_semver env = DefaultEnvironment() @@ -46,3 +51,47 @@ SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) + +def install_python_deps(): + def _get_installed_pip_packages(): + result = {} + packages = {} + pip_output = subprocess.check_output( + [env.subst("$PYTHONEXE"), "-m", "pip", "list", "--format=json"] + ) + try: + packages = json.loads(pip_output) + except: + print("Warning! Couldn't extract the list of installed Python packages.") + return {} + for p in packages: + result[p["name"]] = pepver_to_semver(p["version"]) + + return result + + deps = { + "zopfli": ">=0.2.2" + } + + installed_packages = _get_installed_pip_packages() + packages_to_install = [] + for package, spec in deps.items(): + if package not in installed_packages: + packages_to_install.append(package) + else: + version_spec = semantic_version.Spec(spec) + if not version_spec.match(installed_packages[package]): + packages_to_install.append(package) + + if packages_to_install: + env.Execute( + env.VerboseAction( + ( + '"$PYTHONEXE" -m pip install -U --force-reinstall ' + + " ".join(['"%s%s"' % (p, deps[p]) for p in packages_to_install]) + ), + "Installing Python dependencies", + ) + ) + +install_python_deps() diff --git a/builder/main.py b/builder/main.py index 4291298ee..2265e7018 100644 --- a/builder/main.py +++ b/builder/main.py @@ -491,6 +491,21 @@ def __fetch_fs_size(target, source, env): env.AddPlatformTarget( "uploadfsota", target_firm, upload_actions, "Upload Filesystem Image OTA") +# +# Target: Erase Flash and Upload +# + +env.AddPlatformTarget( + "erase_upload", + target_firm, + [ + env.VerboseAction(env.AutodetectUploadPort, "Looking for serial port..."), + env.VerboseAction("$ERASECMD", "Erasing..."), + env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE") + ], + "Erase Flash and Upload", +) + # # Target: Erase Flash # diff --git a/platform.json b/platform.json index 985c9ce99..369154519 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2022.12.0", + "version": "2022.12.1", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From 5a264890b306d569aabdd577cfa1a629c817ebdf Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 23 Dec 2022 11:31:49 +0100 Subject: [PATCH 236/666] core 2.0.6 --- platform.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform.json b/platform.json index 369154519..92d6e3ca0 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2022.12.1", + "version": "2022.12.2", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -36,25 +36,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.6/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.6/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.6/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20222212/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 676462fd9edeb7a360f71e0af873c31596009fbb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 23 Dec 2022 11:49:47 +0100 Subject: [PATCH 237/666] core 2.0.6 --- platform.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform.json b/platform.json index 369154519..92d6e3ca0 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2022.12.1", + "version": "2022.12.2", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -36,25 +36,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.6/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.6/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.5.4/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.6/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3/esp-idf-v4.4.3.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20222212/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 0834881376ea8c29204bfca1b6e4f1b4b29a18d6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 23 Dec 2022 11:50:19 +0100 Subject: [PATCH 238/666] Tasmota core 2.0.6 From 22b7a8cc97ea5ef748d926e5448b4133e4ac4738 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 27 Dec 2022 22:57:12 +0100 Subject: [PATCH 239/666] v4.4.3.20221227 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 92d6e3ca0..dd013abc4 100644 --- a/platform.json +++ b/platform.json @@ -54,7 +54,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20222212/esp-idf-v4.4.3.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20221227/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 44dd6c0259353b8ac1764e5e3154e825ec2da1d7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 28 Dec 2022 14:24:02 +0100 Subject: [PATCH 240/666] Latest IDF 4.4.3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 92d6e3ca0..dd013abc4 100644 --- a/platform.json +++ b/platform.json @@ -54,7 +54,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20222212/esp-idf-v4.4.3.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20221227/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From a55f1c9a7d926d465101b18b468bac6c343469f9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 28 Dec 2022 17:05:08 +0100 Subject: [PATCH 241/666] Rerelease esptool v4.4.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index dd013abc4..2a34d5309 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4.1/esptool-4.4.1.zip" + "version": "https://github.com/Jason2866/esptool/releases/download/v4.4.1/esptool.zip" }, "tool-openocd-esp32": { "type": "debugger", From 2f94ceaef94510c66bdf3e8369ff40b8e8e7cb02 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 29 Dec 2022 11:32:06 +0100 Subject: [PATCH 242/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 2a34d5309..dd013abc4 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/Jason2866/esptool/releases/download/v4.4.1/esptool.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4.1/esptool-4.4.1.zip" }, "tool-openocd-esp32": { "type": "debugger", From 2e2beb7e59d07ef784d72df1ddf4e0b82a781229 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:30:24 +0100 Subject: [PATCH 243/666] minor change --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 9477160cd..ac560a5c6 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -222,7 +222,7 @@ def populate_idf_env_vars(idf_env): os.path.dirname(env.subst("$PYTHONEXE")), ] - if mcu not in ("esp32c3"): + if mcu != "esp32c3": additional_packages.append( os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), ) From ad16ef9c257fc7e1fd539f11d6a71d21b8b7822d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:34:23 +0100 Subject: [PATCH 244/666] minor changes --- builder/frameworks/ulp.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index c99dceebf..c66d1baa6 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -36,9 +36,7 @@ def prepare_ulp_env_vars(env): additional_packages = [ os.path.join( - platform.get_package_dir( - "toolchain-xtensa-%s" % (idf_variant) - ), + platform.get_package_dir("toolchain-xtensa-%s" % idf_variant), "bin", ), os.path.join( @@ -99,7 +97,7 @@ def generate_ulp_config(target_config): "-DULP_APP_NAME=ulp_main", "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), '-DCOMPONENT_INCLUDES="%s"' % ";".join(get_component_includes(target_config)), - "-DIDF_TARGET=" + idf_variant, + "-DIDF_TARGET=%s" % idf_variant, "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), "-DPYTHON=" + env.subst("$PYTHONEXE"), From 1a2f9f69674091b035086ca5d5da2bcd7760e9e3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:37:54 +0100 Subject: [PATCH 245/666] Create esp32-c3-m1i-kit.json --- boards/esp32-c3-m1i-kit.json | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 boards/esp32-c3-m1i-kit.json diff --git a/boards/esp32-c3-m1i-kit.json b/boards/esp32-c3-m1i-kit.json new file mode 100644 index 000000000..8e7d7cb08 --- /dev/null +++ b/boards/esp32-c3-m1i-kit.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": [ + "-DARDUINO_ESP32C3_M1_I_KIT", + "-DARDUINO_USB_MODE=1" + ], + "mcu": "esp32c3", + "variant": "esp_c3_m1_i_kit" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Ai-Thinker ESP-C3-M1-I-Kit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.ai-thinker.com/en/esp32c3", + "vendor": "Ai-Thinker" +} From 086d76432130ad9d3c6bc3714ea021aeba49c837 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:39:13 +0100 Subject: [PATCH 246/666] ULP "version": "~1.23500.0" --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index dd013abc4..e487250c4 100644 --- a/platform.json +++ b/platform.json @@ -84,7 +84,7 @@ "type": "toolchain", "optional": true, "owner": "espressif", - "version": "~2" + "version": "~1.23500.0" }, "tool-esptoolpy": { "type": "uploader", From 029b40931dc7e1226a4d536ed9356e813d9a1747 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:42:08 +0100 Subject: [PATCH 247/666] Create bpi_leaf_s3.json --- boards/bpi_leaf_s3.json | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 boards/bpi_leaf_s3.json diff --git a/boards/bpi_leaf_s3.json b/boards/bpi_leaf_s3.json new file mode 100644 index 000000000..c1d8a154c --- /dev/null +++ b/boards/bpi_leaf_s3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_BPI_LEAF_S3", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80DF" + ] + ], + "mcu": "esp32s3", + "variant": "bpi_leaf_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "BPI-Leaf-S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.banana-pi.org/BPI-Leaf-S3", + "vendor": "BPI Tech" +} From d23f2ce77fbda6e6e08bacde0b762ba8e4a3cc4f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:42:39 +0100 Subject: [PATCH 248/666] Create cytron_maker_feather_aiot_s3.json --- boards/cytron_maker_feather_aiot_s3.json | 56 ++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 boards/cytron_maker_feather_aiot_s3.json diff --git a/boards/cytron_maker_feather_aiot_s3.json b/boards/cytron_maker_feather_aiot_s3.json new file mode 100644 index 000000000..4b7a2704c --- /dev/null +++ b/boards/cytron_maker_feather_aiot_s3.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "partitions-8MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_CYTRON_MAKER_FEATHER_AIOT_S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80F8" + ] + ], + "mcu": "esp32s3", + "variant": "cytron_maker_feather_aiot_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Cytron Maker Feather AIoT S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/cytron_maker_feather_aiot_s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://sg.cytron.io/c-development-tools/c-maker-series/p-v-maker-feather-aiot-s3-simplifying-aiot-with-esp32", + "vendor": "Cytron Technologies" +} From 5366d6f455c715fcedeb49586596a720a49b56f3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:43:16 +0100 Subject: [PATCH 249/666] Create deneyapkart1Av2.json --- boards/deneyapkart1Av2.json | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 boards/deneyapkart1Av2.json diff --git a/boards/deneyapkart1Av2.json b/boards/deneyapkart1Av2.json new file mode 100644 index 000000000..b287551aa --- /dev/null +++ b/boards/deneyapkart1Av2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYDK1Av2", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8147" + ] + ], + "mcu": "esp32s3", + "variant": "deneyapkart1Av2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart 1A v2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.banana-pi.org/BPI-Leaf-S3", + "vendor": "Deneyap" +} From be3fc56eaf68d60ed8cab9bbad6fbad065719a58 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:44:07 +0100 Subject: [PATCH 250/666] Update deneyapmini.json --- boards/deneyapmini.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/boards/deneyapmini.json b/boards/deneyapmini.json index 02509684b..046fcba0b 100644 --- a/boards/deneyapmini.json +++ b/boards/deneyapmini.json @@ -4,14 +4,17 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_DYM", + "extra_flags": [ + "-DARDUINO_DYM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", "hwids": [ [ "0x303A", - "0x0002" + "0x8141" ] ], "mcu": "esp32s2", From 6b7f67b0036baa75e96f6d3006d7aea5784e05f3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:45:06 +0100 Subject: [PATCH 251/666] Create deneyapminiv2.json --- boards/deneyapminiv2.json | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 boards/deneyapminiv2.json diff --git a/boards/deneyapminiv2.json b/boards/deneyapminiv2.json new file mode 100644 index 000000000..b0c6cfdeb --- /dev/null +++ b/boards/deneyapminiv2.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_DYMv2", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8144" + ] + ], + "mcu": "esp32s2", + "variant": "deneyapminiv2" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Mini v2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/magaza/urun-deneyap-kart-mini.html", + "vendor": "Deneyap" +} From b9b89338d13e2b27317581d5a21ff0949fe81b89 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:45:38 +0100 Subject: [PATCH 252/666] Create redpill_esp32s3.json --- boards/redpill_esp32s3.json | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 boards/redpill_esp32s3.json diff --git a/boards/redpill_esp32s3.json b/boards/redpill_esp32s3.json new file mode 100644 index 000000000..8dff2ff49 --- /dev/null +++ b/boards/redpill_esp32s3.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_REDPILL_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80F8" + ] + ], + "mcu": "esp32s3", + "variant": "redpill_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Munich Labs RedPill ESP32-S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/redpill_esp32s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://munich-labs.com/index.php/redpill-esp32-s3/", + "vendor": "Munich Labs" +} From e242c39770a3074e110c618dac523fcb1540a6ad Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 3 Jan 2023 15:13:28 +0100 Subject: [PATCH 253/666] Use platformio registry for ULP --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index e487250c4..1d158681b 100644 --- a/platform.json +++ b/platform.json @@ -83,7 +83,7 @@ "toolchain-esp32ulp": { "type": "toolchain", "optional": true, - "owner": "espressif", + "owner": "platformio", "version": "~1.23500.0" }, "tool-esptoolpy": { From 4f8c340e465399979016d1bea2718fed987de178 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 4 Jan 2023 14:10:39 +0100 Subject: [PATCH 254/666] esptool v4.4.2 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 1d158681b..5bb7f82df 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4.1/esptool-4.4.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4.2/esptool-4.4.2.zip" }, "tool-openocd-esp32": { "type": "debugger", From 74339291cf66f4520dd2d178b1e8e1346cac6f2c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 6 Jan 2023 13:57:47 +0100 Subject: [PATCH 255/666] Take into account board flash mode when converting elf to bin --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index 2265e7018..36354b6e9 100644 --- a/builder/main.py +++ b/builder/main.py @@ -273,7 +273,7 @@ def __fetch_fs_size(target, source, env): '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", "--dont-append-digest", - "--flash_mode", "$BOARD_FLASH_MODE", + "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" From cfb0c316f5e7c9d8d2e44ffb4d978d89e7d4c77d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 7 Jan 2023 12:53:10 +0100 Subject: [PATCH 256/666] IDF5 with Tasmota Core 2.0.6 (#40) * Add support for IDF v5.0 * IDF 5.0 examples * Fix RISCV ULP detection --- builder/frameworks/espidf.py | 44 +- builder/frameworks/ulp.py | 2 +- examples/espidf-arduino-blink/.travis.yml | 67 + examples/espidf-arduino-blink/README.md | 2 +- examples/espidf-arduino-blink/platformio.ini | 19 +- .../espidf-arduino-blink/sdkconfig.defaults | 2 + examples/espidf-arduino-blink/src/Blink.cpp | 4 +- examples/espidf-arduino-wifiscan/.travis.yml | 67 + examples/espidf-arduino-wifiscan/README.md | 2 +- .../espidf-arduino-wifiscan/platformio.ini | 2 +- examples/espidf-arduino-wifiscan/src/main.cpp | 2 +- examples/espidf-aws-iot/.travis.yml | 67 + examples/espidf-aws-iot/README.md | 2 +- examples/espidf-aws-iot/platformio.ini | 11 +- examples/espidf-ble-eddystone/.travis.yml | 67 + examples/espidf-ble-eddystone/README.md | 2 +- examples/espidf-ble-eddystone/platformio.ini | 2 +- .../espidf-ble-eddystone/src/CMakeLists.txt | 3 +- .../src/esp_eddystone_api.c | 67 +- .../src/esp_eddystone_api.h | 15 +- .../src/esp_eddystone_demo.c | 18 +- .../src/esp_eddystone_protocol.h | 22 +- examples/espidf-blink/.travis.yml | 67 + examples/espidf-blink/README.md | 2 +- examples/espidf-blink/lib/README | 111 +- examples/espidf-blink/platformio.ini | 21 +- examples/espidf-blink/src/blink.c | 86 +- examples/espidf-coap-server/.travis.yml | 67 + examples/espidf-coap-server/README.md | 2 +- .../components/CMakeLists.txt | 41 + .../espidf-coap-server/components/Kconfig | 109 + .../espidf-coap-server/components/LICENSE | 85 + .../espidf-coap-server/components/README.md | 89 + .../components/idf_component.yml | 5 + .../.github/ISSUE_TEMPLATE/bug_report.md | 112 + .../libcoap/.github/ISSUE_TEMPLATE/config.yml | 14 + .../.github/ISSUE_TEMPLATE/feature_request.md | 26 + .../libcoap/.github/workflows/main.yml | 196 + .../components/libcoap/.gitignore | 116 + .../components/libcoap/.gitmodules | 4 + .../components/libcoap/.travis.yml | 70 + .../components/libcoap/AUTHORS | 8 + .../components/libcoap/BUILDING | 157 + .../components/libcoap/CMakeLists.txt | 723 +++ .../components/libcoap/CONTRIBUTE | 218 + .../components/libcoap/COPYING | 6 + .../components/libcoap/ChangeLog | 332 ++ .../components/libcoap/Dockerfile | 7 + .../components/libcoap/HOWTO.dual.gnutls | 98 + .../components/libcoap/HOWTO.dual.openssl | 50 + .../components/libcoap/HOWTO.dual.softhsm2 | 90 + .../components/libcoap/HOWTO.pkcs11 | 129 + .../components/libcoap/LICENSE | 85 + .../components/libcoap/Makefile.am | 281 + .../components/libcoap/Makefile.libcoap | 7 + .../components/libcoap/NEWS | 0 .../components/libcoap/README | 89 + .../components/libcoap/README.md | 89 + .../components/libcoap/TODO | 27 + .../components/libcoap/autogen.sh | 142 + .../libcoap/build-env/.dockerignore | 5 + .../libcoap/build-env/Dockerfile.build-env | 7 + .../libcoap/build-env/Dockerfile.develop | 36 + .../components/libcoap/build-env/build.sh | 16 + .../components/libcoap/build-env/imagename | 2 + .../components/libcoap/cmake-format.yaml | 25 + .../libcoap/cmake/FindMbedTLS.cmake | 35 + .../libcoap/cmake/FindTinyDTLS.cmake | 88 + .../components/libcoap/cmake_coap_config.h.in | 177 + .../components/libcoap/coap_config.h.contiki | 215 + .../components/libcoap/coap_config.h.lwip | 42 + .../components/libcoap/coap_config.h.lwip.in | 42 + .../components/libcoap/coap_config.h.riot | 143 + .../components/libcoap/coap_config.h.riot.in | 143 + .../components/libcoap/coap_config.h.windows | 118 + .../libcoap/coap_config.h.windows.in | 118 + .../components/libcoap/configure.ac | 1106 ++++ .../components/libcoap/doc/Doxyfile.in | 2612 +++++++++ .../components/libcoap/doc/Makefile.am | 288 + .../components/libcoap/doc/docbook.local.css | 47 + .../components/libcoap/doc/main.md | 69 + .../components/libcoap/doc/module_api_wrap.h | 21 + .../libcoap/doc/upgrade_4.2.1_4.3.0.txt | 431 ++ .../libcoap/doc/upgrade_4.3.0_4.3.1.txt | 6 + .../components/libcoap/examples/Makefile.am | 129 + .../libcoap/examples/README.etsi_iot | 43 + .../components/libcoap/examples/coap-client.c | 1944 +++++++ .../components/libcoap/examples/coap-rd.c | 879 +++ .../components/libcoap/examples/coap-server.c | 2980 ++++++++++ .../components/libcoap/examples/coap_list.c | 67 + .../components/libcoap/examples/coap_list.h | 52 + .../libcoap/examples/contiki/.gitignore | 7 + .../libcoap/examples/contiki/Makefile.contiki | 33 + .../libcoap/examples/contiki/README | 30 + .../libcoap/examples/contiki/coap-observer.c | 186 + .../examples/contiki/radvd.conf.sample | 14 + .../libcoap/examples/contiki/server.c | 222 + .../libcoap/examples/etsi_coaptest.sh | 210 + .../components/libcoap/examples/etsi_iot_01.c | 633 +++ .../examples/etsi_iot_01_largedata.txt | 7 + .../libcoap/examples/etsi_testcases.sh | 765 +++ .../components/libcoap/examples/getopt.c | 66 + .../libcoap/examples/lwip/.gitignore | 7 + .../components/libcoap/examples/lwip/README | 30 + .../libcoap/examples/lwip/lwipopts.h | 37 + .../libcoap/examples/lwip/server-coap.c | 147 + .../libcoap/examples/lwip/server-coap.h | 17 + .../components/libcoap/examples/lwip/server.c | 91 + .../examples/share.libcoap.examples.Makefile | 43 + .../examples/share.libcoap.examples.README | 9 + .../components/libcoap/examples/tiny.c | 183 + .../components/libcoap/ext/tinydtls/ABOUT.md | 60 + .../libcoap/ext/tinydtls/AutoConf.cmake | 101 + .../libcoap/ext/tinydtls/CMakeLists.txt | 85 + .../libcoap/ext/tinydtls/CONTRIBUTING.md | 144 + .../components/libcoap/ext/tinydtls/LICENSE | 12 + .../libcoap/ext/tinydtls/Makefile.riot | 7 + .../libcoap/ext/tinydtls/Makefile.tinydtls | 9 + .../components/libcoap/ext/tinydtls/README.md | 81 + .../libcoap/ext/tinydtls/aes/Makefile.riot | 5 + .../libcoap/ext/tinydtls/aes/rijndael.c | 1231 +++++ .../libcoap/ext/tinydtls/aes/rijndael.h | 69 + .../libcoap/ext/tinydtls/aes/rijndael_wrap.c | 69 + .../components/libcoap/ext/tinydtls/alert.h | 85 + .../libcoap/ext/tinydtls/autogen.sh | 21 + .../components/libcoap/ext/tinydtls/ccm.c | 303 ++ .../components/libcoap/ext/tinydtls/ccm.h | 61 + .../libcoap/ext/tinydtls/configure.ac | 153 + .../components/libcoap/ext/tinydtls/crypto.c | 641 +++ .../components/libcoap/ext/tinydtls/crypto.h | 434 ++ .../libcoap/ext/tinydtls/doc/Doxyfile.in | 1551 ++++++ .../ext/tinydtls/doc/DoxygenLayout.xml | 184 + .../components/libcoap/ext/tinydtls/dtls.c | 4780 +++++++++++++++++ .../components/libcoap/ext/tinydtls/dtls.h | 755 +++ .../ext/tinydtls/dtls_config.h.cmake.in | 162 + .../libcoap/ext/tinydtls/dtls_debug.c | 460 ++ .../libcoap/ext/tinydtls/dtls_debug.h | 123 + .../libcoap/ext/tinydtls/dtls_mutex.h | 68 + .../libcoap/ext/tinydtls/dtls_prng.c | 39 + .../libcoap/ext/tinydtls/dtls_prng.h | 56 + .../libcoap/ext/tinydtls/dtls_time.c | 98 + .../libcoap/ext/tinydtls/dtls_time.h | 96 + .../libcoap/ext/tinydtls/ecc/Makefile.contiki | 7 + .../libcoap/ext/tinydtls/ecc/Makefile.ecc | 3 + .../libcoap/ext/tinydtls/ecc/Makefile.riot | 5 + .../components/libcoap/ext/tinydtls/ecc/ecc.c | 727 +++ .../components/libcoap/ext/tinydtls/ecc/ecc.h | 86 + .../libcoap/ext/tinydtls/ecc/test_helper.c | 79 + .../libcoap/ext/tinydtls/ecc/test_helper.h | 51 + .../libcoap/ext/tinydtls/ecc/testecc.c | 234 + .../libcoap/ext/tinydtls/ecc/testfield.c | 303 ++ .../components/libcoap/ext/tinydtls/global.h | 143 + .../components/libcoap/ext/tinydtls/hmac.c | 107 + .../components/libcoap/ext/tinydtls/hmac.h | 151 + .../components/libcoap/ext/tinydtls/netq.c | 176 + .../components/libcoap/ext/tinydtls/netq.h | 122 + .../components/libcoap/ext/tinydtls/numeric.h | 134 + .../components/libcoap/ext/tinydtls/peer.c | 107 + .../components/libcoap/ext/tinydtls/peer.h | 168 + .../platform-specific/dtls_prng_contiki.c | 60 + .../platform-specific/dtls_prng_espidf.c | 42 + .../platform-specific/dtls_prng_posix.c | 73 + .../platform-specific/dtls_prng_riot.c | 35 + .../platform-specific/dtls_prng_zephyr.c | 35 + .../ext/tinydtls/platform-specific/platform.h | 90 + .../tinydtls/platform-specific/riot_boards.h | 152 + .../components/libcoap/ext/tinydtls/session.c | 152 + .../components/libcoap/ext/tinydtls/session.h | 129 + .../libcoap/ext/tinydtls/sha2/README | 272 + .../libcoap/ext/tinydtls/sha2/sha2.c | 1106 ++++ .../libcoap/ext/tinydtls/sha2/sha2.h | 216 + .../libcoap/ext/tinydtls/sha2/sha2prog.c | 134 + .../libcoap/ext/tinydtls/sha2/sha2speed.c | 176 + .../libcoap/ext/tinydtls/sha2/sha2test.pl | 358 ++ .../tinydtls/sha2/testvectors/vector001.dat | 1 + .../tinydtls/sha2/testvectors/vector001.info | 21 + .../tinydtls/sha2/testvectors/vector002.dat | 1 + .../tinydtls/sha2/testvectors/vector002.info | 21 + .../tinydtls/sha2/testvectors/vector003.dat | 1 + .../tinydtls/sha2/testvectors/vector003.info | 22 + .../tinydtls/sha2/testvectors/vector004.dat | 1 + .../tinydtls/sha2/testvectors/vector004.info | 22 + .../tinydtls/sha2/testvectors/vector005.dat | 0 .../tinydtls/sha2/testvectors/vector005.info | 23 + .../tinydtls/sha2/testvectors/vector006.dat | 1 + .../tinydtls/sha2/testvectors/vector006.info | 22 + .../tinydtls/sha2/testvectors/vector007.dat | 1 + .../tinydtls/sha2/testvectors/vector007.info | 22 + .../tinydtls/sha2/testvectors/vector008.dat | 1 + .../tinydtls/sha2/testvectors/vector008.info | 22 + .../tinydtls/sha2/testvectors/vector009.dat | 1 + .../tinydtls/sha2/testvectors/vector009.info | 22 + .../tinydtls/sha2/testvectors/vector010.dat | Bin 0 -> 320 bytes .../tinydtls/sha2/testvectors/vector010.info | 22 + .../tinydtls/sha2/testvectors/vector011.dat | Bin 0 -> 447 bytes .../tinydtls/sha2/testvectors/vector011.info | 22 + .../tinydtls/sha2/testvectors/vector012.dat | Bin 0 -> 640 bytes .../tinydtls/sha2/testvectors/vector012.info | 22 + .../tinydtls/sha2/testvectors/vector013.dat | Bin 0 -> 2175 bytes .../tinydtls/sha2/testvectors/vector013.info | 22 + .../tinydtls/sha2/testvectors/vector014.dat | Bin 0 -> 16384 bytes .../tinydtls/sha2/testvectors/vector014.info | 22 + .../tinydtls/sha2/testvectors/vector015.dat | 1 + .../tinydtls/sha2/testvectors/vector015.info | 21 + .../tinydtls/sha2/testvectors/vector016.dat | 1 + .../tinydtls/sha2/testvectors/vector016.info | 23 + .../tinydtls/sha2/testvectors/vector017.dat | Bin 0 -> 12271 bytes .../tinydtls/sha2/testvectors/vector017.info | 32 + .../tinydtls/sha2/testvectors/vector018.dat | Bin 0 -> 1079 bytes .../tinydtls/sha2/testvectors/vector018.info | 26 + .../components/libcoap/ext/tinydtls/state.h | 60 + .../libcoap/ext/tinydtls/tests/CMakeLists.txt | 37 + .../ext/tinydtls/tests/cbc_aes128-test.c | 60 + .../ext/tinydtls/tests/cbc_aes128-testdata.c | 66 + .../libcoap/ext/tinydtls/tests/ccm-test.c | 90 + .../libcoap/ext/tinydtls/tests/ccm-testdata.c | 449 ++ .../libcoap/ext/tinydtls/tests/dsrv-test.c | 110 + .../libcoap/ext/tinydtls/tests/dtls-client.c | 554 ++ .../libcoap/ext/tinydtls/tests/dtls-server.c | 402 ++ .../libcoap/ext/tinydtls/tests/netq-test.c | 123 + .../libcoap/ext/tinydtls/tests/pcap.c | 478 ++ .../ext/tinydtls/tests/unit-tests/test_ccm.c | 215 + .../ext/tinydtls/tests/unit-tests/test_ccm.h | 15 + .../ext/tinydtls/tests/unit-tests/test_ecc.c | 242 + .../ext/tinydtls/tests/unit-tests/test_ecc.h | 15 + .../ext/tinydtls/tests/unit-tests/test_prf.c | 287 + .../ext/tinydtls/tests/unit-tests/test_prf.h | 15 + .../tinydtls/tests/unit-tests/testdriver.c | 30 + .../libcoap/ext/tinydtls/tinydtls.h | 51 + .../libcoap/ext/tinydtls/tinydtls.pc.in | 26 + .../components/libcoap/ext/tinydtls/uthash.h | 1210 +++++ .../components/libcoap/ext/tinydtls/utlist.h | 1073 ++++ .../ext/tinydtls/zephyr/CMakeLists.txt | 43 + .../libcoap/ext/tinydtls/zephyr/Kconfig | 47 + .../components/libcoap/include/coap3/block.h | 431 ++ .../libcoap/include/coap3/coap.h.in | 65 + .../libcoap/include/coap3/coap.h.windows | 65 + .../libcoap/include/coap3/coap.h.windows.in | 65 + .../libcoap/include/coap3/coap_address.h | 213 + .../include/coap3/coap_asn1_internal.h | 90 + .../libcoap/include/coap3/coap_async.h | 128 + .../include/coap3/coap_async_internal.h | 69 + .../include/coap3/coap_block_internal.h | 231 + .../libcoap/include/coap3/coap_cache.h | 234 + .../include/coap3/coap_cache_internal.h | 115 + .../libcoap/include/coap3/coap_debug.h | 260 + .../libcoap/include/coap3/coap_dtls.h | 491 ++ .../include/coap3/coap_dtls_internal.h | 408 ++ .../libcoap/include/coap3/coap_event.h | 146 + .../include/coap3/coap_forward_decls.h | 107 + .../libcoap/include/coap3/coap_hashkey.h | 61 + .../libcoap/include/coap3/coap_internal.h | 80 + .../libcoap/include/coap3/coap_io.h | 77 + .../libcoap/include/coap3/coap_io_internal.h | 186 + .../libcoap/include/coap3/coap_mutex.h | 82 + .../libcoap/include/coap3/coap_net_internal.h | 386 ++ .../libcoap/include/coap3/coap_option.h | 440 ++ .../libcoap/include/coap3/coap_pdu_internal.h | 318 ++ .../libcoap/include/coap3/coap_prng.h | 114 + .../include/coap3/coap_resource_internal.h | 145 + .../libcoap/include/coap3/coap_riot.h | 39 + .../libcoap/include/coap3/coap_session.h | 624 +++ .../include/coap3/coap_session_internal.h | 436 ++ .../libcoap/include/coap3/coap_subscribe.h | 69 + .../include/coap3/coap_subscribe_internal.h | 162 + .../libcoap/include/coap3/coap_tcp_internal.h | 112 + .../libcoap/include/coap3/coap_time.h | 204 + .../components/libcoap/include/coap3/encode.h | 128 + .../libcoap/include/coap3/libcoap.h | 68 + .../libcoap/include/coap3/lwippools.h | 117 + .../components/libcoap/include/coap3/mem.h | 144 + .../components/libcoap/include/coap3/net.h | 825 +++ .../components/libcoap/include/coap3/pdu.h | 603 +++ .../libcoap/include/coap3/resource.h | 499 ++ .../components/libcoap/include/coap3/str.h | 210 + .../components/libcoap/include/coap3/uri.h | 182 + .../components/libcoap/include/coap3/uthash.h | 1136 ++++ .../components/libcoap/include/coap3/utlist.h | 1073 ++++ .../components/libcoap/libcoap-3.map | 252 + .../components/libcoap/libcoap-3.pc.in | 12 + .../components/libcoap/libcoap-3.sym | 247 + .../libcoap/m4/ac_check_cryptolibs.m4 | 84 + .../libcoap/m4/ax_check_a2x_to_man.m4 | 57 + .../libcoap/m4/ax_check_compile_flag.m4 | 74 + .../libcoap/m4/ax_check_link_flag.m4 | 74 + .../components/libcoap/man/Makefile.am | 162 + .../components/libcoap/man/coap-client.txt.in | 299 ++ .../components/libcoap/man/coap-rd.txt.in | 163 + .../components/libcoap/man/coap-server.txt.in | 268 + .../components/libcoap/man/coap.txt.in | 87 + .../components/libcoap/man/coap_async.txt.in | 203 + .../libcoap/man/coap_attribute.txt.in | 158 + .../components/libcoap/man/coap_block.txt.in | 534 ++ .../components/libcoap/man/coap_cache.txt.in | 390 ++ .../libcoap/man/coap_context.txt.in | 149 + .../libcoap/man/coap_encryption.txt.in | 1237 +++++ .../libcoap/man/coap_endpoint_client.txt.in | 421 ++ .../libcoap/man/coap_endpoint_server.txt.in | 584 ++ .../libcoap/man/coap_handler.txt.in | 348 ++ .../components/libcoap/man/coap_io.txt.in | 463 ++ .../libcoap/man/coap_keepalive.txt.in | 78 + .../libcoap/man/coap_logging.txt.in | 185 + .../libcoap/man/coap_observe.txt.in | 405 ++ .../libcoap/man/coap_pdu_access.txt.in | 393 ++ .../libcoap/man/coap_pdu_setup.txt.in | 721 +++ .../libcoap/man/coap_recovery.txt.in | 216 + .../libcoap/man/coap_resource.txt.in | 584 ++ .../libcoap/man/coap_session.txt.in | 238 + .../components/libcoap/man/coap_string.txt.in | 182 + .../libcoap/man/coap_tls_library.txt.in | 153 + .../libcoap/man/examples-code-check.c | 437 ++ .../libcoap/scripts/api-version-bump.sh | 60 + .../components/libcoap/scripts/build.sh | 86 + .../components/libcoap/scripts/dist.sh | 70 + .../components/libcoap/scripts/fix-cunit.sh | 15 + .../libcoap/scripts/format_cmake.sh | 23 + .../components/libcoap/scripts/github_dist.sh | 24 + .../libcoap/scripts/msbuild.sln.cmd | 16 + .../components/libcoap/src/block.c | 2451 +++++++++ .../components/libcoap/src/coap_address.c | 115 + .../components/libcoap/src/coap_asn1.c | 107 + .../components/libcoap/src/coap_async.c | 237 + .../components/libcoap/src/coap_cache.c | 281 + .../components/libcoap/src/coap_debug.c | 1052 ++++ .../components/libcoap/src/coap_event.c | 38 + .../components/libcoap/src/coap_gnutls.c | 2960 ++++++++++ .../components/libcoap/src/coap_hashkey.c | 33 + .../components/libcoap/src/coap_io.c | 1615 ++++++ .../components/libcoap/src/coap_io_lwip.c | 242 + .../components/libcoap/src/coap_io_riot.c | 286 + .../components/libcoap/src/coap_mbedtls.c | 2540 +++++++++ .../components/libcoap/src/coap_notls.c | 271 + .../components/libcoap/src/coap_openssl.c | 3527 ++++++++++++ .../components/libcoap/src/coap_option.c | 605 +++ .../components/libcoap/src/coap_prng.c | 113 + .../components/libcoap/src/coap_session.c | 1709 ++++++ .../components/libcoap/src/coap_subscribe.c | 25 + .../components/libcoap/src/coap_tcp.c | 324 ++ .../components/libcoap/src/coap_time.c | 141 + .../components/libcoap/src/coap_tinydtls.c | 1311 +++++ .../components/libcoap/src/encode.c | 93 + .../components/libcoap/src/mem.c | 477 ++ .../components/libcoap/src/net.c | 3885 ++++++++++++++ .../components/libcoap/src/pdu.c | 1301 +++++ .../components/libcoap/src/resource.c | 1170 ++++ .../components/libcoap/src/str.c | 112 + .../components/libcoap/src/uri.c | 679 +++ .../components/libcoap/tests/Makefile.am | 43 + .../libcoap/tests/oss-fuzz/Makefile.ci.in | 38 + .../libcoap/tests/oss-fuzz/Makefile.oss-fuzz | 15 + .../libcoap/tests/oss-fuzz/pdu_parse_target.c | 23 + .../libcoap/tests/oss-fuzz/split_uri_target.c | 8 + .../components/libcoap/tests/test_common.h.in | 12 + .../components/libcoap/tests/test_encode.c | 266 + .../components/libcoap/tests/test_encode.h | 13 + .../libcoap/tests/test_error_response.c | 366 ++ .../libcoap/tests/test_error_response.h | 13 + .../components/libcoap/tests/test_options.c | 1049 ++++ .../components/libcoap/tests/test_options.h | 19 + .../components/libcoap/tests/test_pdu.c | 1327 +++++ .../components/libcoap/tests/test_pdu.h | 13 + .../components/libcoap/tests/test_sendqueue.c | 367 ++ .../components/libcoap/tests/test_sendqueue.h | 13 + .../components/libcoap/tests/test_session.c | 226 + .../components/libcoap/tests/test_session.h | 13 + .../components/libcoap/tests/test_tls.c | 129 + .../components/libcoap/tests/test_tls.h | 13 + .../components/libcoap/tests/test_uri.c | 623 +++ .../components/libcoap/tests/test_uri.h | 13 + .../components/libcoap/tests/test_wellknown.c | 278 + .../components/libcoap/tests/test_wellknown.h | 13 + .../components/libcoap/tests/testdriver.c | 59 + .../libcoap/tests/valgrind_suppression | 12 + .../win32/coap-client/coap-client.vcxproj | 387 ++ .../coap-client/coap-client.vcxproj.filters | 22 + .../libcoap/win32/coap-rd/coap-rd.vcxproj | 377 ++ .../win32/coap-rd/coap-rd.vcxproj.filters | 22 + .../win32/coap-server/coap-server.vcxproj | 378 ++ .../coap-server/coap-server.vcxproj.filters | 22 + .../components/libcoap/win32/libcoap.props | 82 + .../components/libcoap/win32/libcoap.sln | 144 + .../components/libcoap/win32/libcoap.vcxproj | 629 +++ .../libcoap/win32/libcoap.vcxproj.filters | 204 + .../win32/testdriver/testdriver.vcxproj | 401 ++ .../testdriver/testdriver.vcxproj.filters | 72 + .../components/port/include/coap3/coap.h | 51 + .../components/port/include/coap_config.h | 59 + .../port/include/coap_config_posix.h | 61 + examples/espidf-coap-server/platformio.ini | 4 +- .../espidf-coap-server/sdkconfig.defaults | 4 +- .../espidf-coap-server/src/CMakeLists.txt | 3 +- .../espidf-coap-server/src/Kconfig.projbuild | 50 + .../src/coap_server_example_main.c | 34 +- examples/espidf-exceptions/.travis.yml | 67 + examples/espidf-exceptions/README.md | 2 +- examples/espidf-exceptions/platformio.ini | 2 +- examples/espidf-exceptions/src/CMakeLists.txt | 2 +- examples/espidf-hello-world/.travis.yml | 67 + examples/espidf-hello-world/README.md | 2 +- examples/espidf-hello-world/platformio.ini | 2 +- .../espidf-hello-world/src/CMakeLists.txt | 4 +- .../espidf-hello-world/src/hello_world_main.c | 44 +- .../test/test_dummy/test_dummy.c | 15 + examples/espidf-http-request/.travis.yml | 67 + examples/espidf-http-request/README.md | 2 +- examples/espidf-http-request/platformio.ini | 2 +- .../espidf-http-request/src/CMakeLists.txt | 2 +- .../src/http_request_example_main.c | 1 + examples/espidf-peripherals-uart/.travis.yml | 67 + examples/espidf-peripherals-uart/README.md | 2 +- .../espidf-peripherals-uart/platformio.ini | 2 +- .../src/CMakeLists.txt | 2 +- .../src/Kconfig.projbuild | 45 + .../src/uart_echo_example_main.c | 48 +- examples/espidf-peripherals-usb/.travis.yml | 67 + examples/espidf-peripherals-usb/README.md | 2 +- .../components/esp_tinyusb/.gitattributes | 25 + .../components/esp_tinyusb/.gitignore | 30 + .../components/esp_tinyusb/.readthedocs.yaml | 18 + .../components/esp_tinyusb/CMakeLists.txt | 73 + .../esp_tinyusb/CODE_OF_CONDUCT.rst | 88 + .../components/esp_tinyusb/CONTRIBUTORS.rst | 192 + .../components/esp_tinyusb/Kconfig | 163 + .../components/esp_tinyusb/LICENSE | 21 + .../components/esp_tinyusb/README.rst | 145 + .../esp_tinyusb/additions/include/tinyusb.h | 64 + .../additions/include/tinyusb_types.h | 24 + .../additions/include/tusb_cdc_acm.h | 195 + .../additions/include/tusb_config.h | 103 + .../additions/include/tusb_console.h | 33 + .../additions/include/tusb_tasks.h | 38 + .../additions/include/vfs_tinyusb.h | 34 + .../additions/include_private/cdc.h | 82 + .../include_private/descriptors_control.h | 23 + .../include_private/usb_descriptors.h | 27 + .../esp_tinyusb/additions/src/cdc.c | 109 + .../additions/src/descriptors_control.c | 150 + .../esp_tinyusb/additions/src/tinyusb.c | 93 + .../esp_tinyusb/additions/src/tusb_cdc_acm.c | 415 ++ .../esp_tinyusb/additions/src/tusb_console.c | 115 + .../esp_tinyusb/additions/src/tusb_tasks.c | 46 + .../additions/src/usb_descriptors.c | 186 + .../esp_tinyusb/additions/src/vfs_tinyusb.c | 289 + .../esp_tinyusb/hw/bsp/ansi_escape.h | 97 + .../components/esp_tinyusb/hw/bsp/board.c | 149 + .../components/esp_tinyusb/hw/bsp/board.h | 147 + .../components/esp_tinyusb/hw/bsp/board_mcu.h | 157 + .../hw/bsp/esp32s2/boards/CMakeLists.txt | 12 + .../adafruit_feather_esp32s2/board.cmake | 17 + .../boards/adafruit_feather_esp32s2/board.h | 45 + .../boards/adafruit_magtag_29gray/board.cmake | 17 + .../boards/adafruit_magtag_29gray/board.h | 45 + .../boards/adafruit_metro_esp32s2/board.cmake | 17 + .../boards/adafruit_metro_esp32s2/board.h | 43 + .../hw/bsp/esp32s2/boards/esp32s2.c | 148 + .../boards/espressif_kaluga_1/board.cmake | 17 + .../esp32s2/boards/espressif_kaluga_1/board.h | 44 + .../boards/espressif_saola_1/board.cmake | 17 + .../esp32s2/boards/espressif_saola_1/board.h | 45 + .../components/led_strip/CMakeLists.txt | 8 + .../components/led_strip/include/led_strip.h | 126 + .../led_strip/src/led_strip_rmt_ws2812.c | 171 + .../esp_tinyusb/hw/bsp/esp32s2/family.cmake | 7 + .../esp_tinyusb/hw/bsp/esp32s2/family.mk | 23 + .../hw/bsp/esp32s3/boards/CMakeLists.txt | 14 + .../hw/bsp/esp32s3/boards/esp32s3.c | 148 + .../boards/espressif_addax_1/board.cmake | 7 + .../esp32s3/boards/espressif_addax_1/board.h | 44 + .../boards/espressif_s3_devkitc/board.cmake | 7 + .../boards/espressif_s3_devkitc/board.h | 43 + .../boards/espressif_s3_devkitm/board.cmake | 7 + .../boards/espressif_s3_devkitm/board.h | 43 + .../components/led_strip/CMakeLists.txt | 8 + .../components/led_strip/include/led_strip.h | 126 + .../led_strip/src/led_strip_rmt_ws2812.c | 171 + .../esp_tinyusb/hw/bsp/esp32s3/family.cmake | 7 + .../esp_tinyusb/hw/bsp/esp32s3/family.mk | 26 + .../esp_tinyusb/hw/bsp/family_support.cmake | 100 + .../components/esp_tinyusb/idf_component.yml | 8 + .../esp_tinyusb/lib/SEGGER_RTT/License.txt | 34 + .../esp_tinyusb/lib/SEGGER_RTT/README.txt | 20 + .../lib/SEGGER_RTT/RTT/SEGGER_RTT.c | 2005 +++++++ .../lib/SEGGER_RTT/RTT/SEGGER_RTT.h | 321 ++ .../SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S | 235 + .../lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h | 384 ++ .../lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c | 500 ++ .../Syscalls/SEGGER_RTT_Syscalls_GCC.c | 120 + .../Syscalls/SEGGER_RTT_Syscalls_IAR.c | 115 + .../Syscalls/SEGGER_RTT_Syscalls_KEIL.c | 386 ++ .../Syscalls/SEGGER_RTT_Syscalls_SES.c | 247 + .../esp_tinyusb/lib/fatfs/00readme.txt | 138 + .../components/esp_tinyusb/lib/fatfs/ccsbcs.c | 543 ++ .../components/esp_tinyusb/lib/fatfs/diskio.c | 193 + .../components/esp_tinyusb/lib/fatfs/diskio.h | 95 + .../components/esp_tinyusb/lib/fatfs/ff.c | 4330 +++++++++++++++ .../components/esp_tinyusb/lib/fatfs/ff.h | 342 ++ .../components/esp_tinyusb/lib/fatfs/ffconf.h | 193 + .../esp_tinyusb/lib/fatfs/integer.h | 36 + .../esp_tinyusb/lib/networking/dhserver.c | 348 ++ .../esp_tinyusb/lib/networking/dhserver.h | 62 + .../esp_tinyusb/lib/networking/dnserver.c | 200 + .../esp_tinyusb/lib/networking/dnserver.h | 47 + .../esp_tinyusb/lib/networking/ndis.h | 266 + .../lib/networking/rndis_protocol.h | 307 ++ .../lib/networking/rndis_reports.c | 303 ++ .../components/esp_tinyusb/pkg.yml | 14 + .../components/esp_tinyusb/repository.yml | 15 + .../components/esp_tinyusb/sdkconfig.rename | 22 + .../esp_tinyusb/src/class/audio/audio.h | 933 ++++ .../src/class/audio/audio_device.c | 2294 ++++++++ .../src/class/audio/audio_device.h | 637 +++ .../esp_tinyusb/src/class/bth/bth_device.c | 258 + .../esp_tinyusb/src/class/bth/bth_device.h | 109 + .../esp_tinyusb/src/class/cdc/cdc.h | 409 ++ .../esp_tinyusb/src/class/cdc/cdc_device.c | 486 ++ .../esp_tinyusb/src/class/cdc/cdc_device.h | 260 + .../esp_tinyusb/src/class/cdc/cdc_host.c | 249 + .../esp_tinyusb/src/class/cdc/cdc_host.h | 134 + .../esp_tinyusb/src/class/cdc/cdc_rndis.h | 301 ++ .../src/class/cdc/cdc_rndis_host.c | 279 + .../src/class/cdc/cdc_rndis_host.h | 63 + .../esp_tinyusb/src/class/dfu/dfu.h | 119 + .../esp_tinyusb/src/class/dfu/dfu_device.c | 458 ++ .../esp_tinyusb/src/class/dfu/dfu_device.h | 98 + .../esp_tinyusb/src/class/dfu/dfu_rt_device.c | 128 + .../esp_tinyusb/src/class/dfu/dfu_rt_device.h | 54 + .../esp_tinyusb/src/class/hid/hid.h | 1119 ++++ .../esp_tinyusb/src/class/hid/hid_device.c | 417 ++ .../esp_tinyusb/src/class/hid/hid_device.h | 393 ++ .../esp_tinyusb/src/class/hid/hid_host.c | 636 +++ .../esp_tinyusb/src/class/hid/hid_host.h | 152 + .../esp_tinyusb/src/class/midi/midi.h | 212 + .../esp_tinyusb/src/class/midi/midi_device.c | 545 ++ .../esp_tinyusb/src/class/midi/midi_device.h | 173 + .../esp_tinyusb/src/class/msc/msc.h | 382 ++ .../esp_tinyusb/src/class/msc/msc_device.c | 939 ++++ .../esp_tinyusb/src/class/msc/msc_device.h | 159 + .../esp_tinyusb/src/class/msc/msc_host.c | 491 ++ .../esp_tinyusb/src/class/msc/msc_host.h | 119 + .../src/class/net/ecm_rndis_device.c | 445 ++ .../esp_tinyusb/src/class/net/ncm.h | 69 + .../esp_tinyusb/src/class/net/ncm_device.c | 510 ++ .../esp_tinyusb/src/class/net/net_device.h | 118 + .../esp_tinyusb/src/class/usbtmc/usbtmc.h | 316 ++ .../src/class/usbtmc/usbtmc_device.c | 858 +++ .../src/class/usbtmc/usbtmc_device.h | 116 + .../src/class/vendor/vendor_device.c | 257 + .../src/class/vendor/vendor_device.h | 136 + .../src/class/vendor/vendor_host.c | 146 + .../src/class/vendor/vendor_host.h | 67 + .../esp_tinyusb/src/class/video/video.h | 480 ++ .../src/class/video/video_device.c | 1149 ++++ .../src/class/video/video_device.h | 97 + .../esp_tinyusb/src/common/tusb_common.h | 406 ++ .../esp_tinyusb/src/common/tusb_compiler.h | 258 + .../esp_tinyusb/src/common/tusb_error.h | 75 + .../esp_tinyusb/src/common/tusb_fifo.c | 1007 ++++ .../esp_tinyusb/src/common/tusb_fifo.h | 151 + .../esp_tinyusb/src/common/tusb_timeout.h | 80 + .../esp_tinyusb/src/common/tusb_types.h | 546 ++ .../esp_tinyusb/src/common/tusb_verify.h | 181 + .../components/esp_tinyusb/src/device/dcd.h | 193 + .../esp_tinyusb/src/device/dcd_attr.h | 221 + .../components/esp_tinyusb/src/device/usbd.c | 1419 +++++ .../components/esp_tinyusb/src/device/usbd.h | 853 +++ .../esp_tinyusb/src/device/usbd_control.c | 233 + .../esp_tinyusb/src/device/usbd_pvt.h | 115 + .../components/esp_tinyusb/src/host/hcd.h | 179 + .../esp_tinyusb/src/host/hcd_attr.h | 105 + .../components/esp_tinyusb/src/host/hub.c | 388 ++ .../components/esp_tinyusb/src/host/hub.h | 196 + .../components/esp_tinyusb/src/host/usbh.c | 1204 +++++ .../components/esp_tinyusb/src/host/usbh.h | 99 + .../esp_tinyusb/src/host/usbh_classdriver.h | 83 + .../esp_tinyusb/src/host/usbh_control.c | 138 + .../components/esp_tinyusb/src/osal/osal.h | 111 + .../esp_tinyusb/src/osal/osal_freertos.h | 172 + .../esp_tinyusb/src/osal/osal_mynewt.h | 174 + .../esp_tinyusb/src/osal/osal_none.h | 204 + .../esp_tinyusb/src/osal/osal_pico.h | 187 + .../esp_tinyusb/src/osal/osal_rtthread.h | 130 + .../portable/espressif/esp32sx/dcd_esp32sx.c | 854 +++ .../components/esp_tinyusb/src/tusb.c | 245 + .../components/esp_tinyusb/src/tusb.h | 140 + .../components/esp_tinyusb/src/tusb_option.h | 382 ++ .../esp_tinyusb/tools/build_board.py | 100 + .../esp_tinyusb/tools/build_esp32sx.py | 101 + .../esp_tinyusb/tools/build_family.py | 113 + .../esp_tinyusb/tools/build_utils.py | 61 + .../components/esp_tinyusb/tools/iar_gen.py | 51 + .../esp_tinyusb/tools/iar_template.ipcf | 145 + .../components/esp_tinyusb/tools/top.mk | 30 + .../tools/usb_drivers/tinyusb_win_usbser.inf | 108 + .../components/esp_tinyusb/version.yml | 3 + .../espidf-peripherals-usb/platformio.ini | 2 +- .../espidf-peripherals-usb/sdkconfig.defaults | 7 +- .../espidf-peripherals-usb/src/CMakeLists.txt | 4 +- .../src/Kconfig.projbuild | 10 - .../src/tusb_sample_descriptor.c | 84 - .../src/tusb_serial_device_main.c | 83 + examples/espidf-storage-sdcard/.travis.yml | 67 + examples/espidf-storage-sdcard/README.md | 2 +- examples/espidf-storage-sdcard/platformio.ini | 2 +- .../espidf-storage-sdcard/src/CMakeLists.txt | 2 +- .../src/Kconfig.projbuild | 57 + .../src/sd_card_example_main.c | 152 +- examples/espidf-storage-spiffs/.gitignore | 1 + examples/espidf-storage-spiffs/CMakeLists.txt | 6 + examples/espidf-storage-spiffs/README.md | 24 + examples/espidf-storage-spiffs/data/hello.txt | 1 + examples/espidf-storage-spiffs/include/README | 39 + examples/espidf-storage-spiffs/lib/README | 46 + .../partitions_example.csv | 6 + examples/espidf-storage-spiffs/platformio.ini | 15 + .../espidf-storage-spiffs/sdkconfig.defaults | 3 + .../espidf-storage-spiffs/src/CMakeLists.txt | 2 + .../src/Kconfig.projbuild | 9 + .../src/spiffs_example_main.c | 127 + examples/espidf-storage-spiffs/test/README | 11 + .../main/ulp_riscv_example_main.c | 34 +- examples/espidf-ulp-riscv/sdkconfig.defaults | 4 + .../sdkconfig.defaults.esp32s2 | 4 - .../sdkconfig.defaults.esp32s3 | 4 - examples/espidf-ulp-riscv/ulp/main.c | 145 +- examples/espidf-ulp/main/CMakeLists.txt | 2 +- examples/espidf-ulp/main/ulp_example_main.c | 18 +- examples/espidf-ulp/sdkconfig.defaults | 4 + platform.json | 21 +- platform.py | 13 + 629 files changed, 146977 insertions(+), 500 deletions(-) create mode 100644 examples/espidf-arduino-blink/.travis.yml create mode 100644 examples/espidf-arduino-wifiscan/.travis.yml create mode 100644 examples/espidf-aws-iot/.travis.yml create mode 100644 examples/espidf-ble-eddystone/.travis.yml create mode 100644 examples/espidf-blink/.travis.yml create mode 100644 examples/espidf-coap-server/.travis.yml create mode 100644 examples/espidf-coap-server/components/CMakeLists.txt create mode 100644 examples/espidf-coap-server/components/Kconfig create mode 100644 examples/espidf-coap-server/components/LICENSE create mode 100644 examples/espidf-coap-server/components/README.md create mode 100644 examples/espidf-coap-server/components/idf_component.yml create mode 100644 examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/config.yml create mode 100644 examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 examples/espidf-coap-server/components/libcoap/.github/workflows/main.yml create mode 100644 examples/espidf-coap-server/components/libcoap/.gitignore create mode 100644 examples/espidf-coap-server/components/libcoap/.gitmodules create mode 100644 examples/espidf-coap-server/components/libcoap/.travis.yml create mode 100644 examples/espidf-coap-server/components/libcoap/AUTHORS create mode 100644 examples/espidf-coap-server/components/libcoap/BUILDING create mode 100644 examples/espidf-coap-server/components/libcoap/CMakeLists.txt create mode 100644 examples/espidf-coap-server/components/libcoap/CONTRIBUTE create mode 100644 examples/espidf-coap-server/components/libcoap/COPYING create mode 100644 examples/espidf-coap-server/components/libcoap/ChangeLog create mode 100644 examples/espidf-coap-server/components/libcoap/Dockerfile create mode 100644 examples/espidf-coap-server/components/libcoap/HOWTO.dual.gnutls create mode 100644 examples/espidf-coap-server/components/libcoap/HOWTO.dual.openssl create mode 100644 examples/espidf-coap-server/components/libcoap/HOWTO.dual.softhsm2 create mode 100644 examples/espidf-coap-server/components/libcoap/HOWTO.pkcs11 create mode 100644 examples/espidf-coap-server/components/libcoap/LICENSE create mode 100644 examples/espidf-coap-server/components/libcoap/Makefile.am create mode 100644 examples/espidf-coap-server/components/libcoap/Makefile.libcoap create mode 100644 examples/espidf-coap-server/components/libcoap/NEWS create mode 100644 examples/espidf-coap-server/components/libcoap/README create mode 100644 examples/espidf-coap-server/components/libcoap/README.md create mode 100644 examples/espidf-coap-server/components/libcoap/TODO create mode 100644 examples/espidf-coap-server/components/libcoap/autogen.sh create mode 100644 examples/espidf-coap-server/components/libcoap/build-env/.dockerignore create mode 100644 examples/espidf-coap-server/components/libcoap/build-env/Dockerfile.build-env create mode 100644 examples/espidf-coap-server/components/libcoap/build-env/Dockerfile.develop create mode 100644 examples/espidf-coap-server/components/libcoap/build-env/build.sh create mode 100644 examples/espidf-coap-server/components/libcoap/build-env/imagename create mode 100644 examples/espidf-coap-server/components/libcoap/cmake-format.yaml create mode 100644 examples/espidf-coap-server/components/libcoap/cmake/FindMbedTLS.cmake create mode 100644 examples/espidf-coap-server/components/libcoap/cmake/FindTinyDTLS.cmake create mode 100644 examples/espidf-coap-server/components/libcoap/cmake_coap_config.h.in create mode 100644 examples/espidf-coap-server/components/libcoap/coap_config.h.contiki create mode 100644 examples/espidf-coap-server/components/libcoap/coap_config.h.lwip create mode 100644 examples/espidf-coap-server/components/libcoap/coap_config.h.lwip.in create mode 100644 examples/espidf-coap-server/components/libcoap/coap_config.h.riot create mode 100644 examples/espidf-coap-server/components/libcoap/coap_config.h.riot.in create mode 100644 examples/espidf-coap-server/components/libcoap/coap_config.h.windows create mode 100644 examples/espidf-coap-server/components/libcoap/coap_config.h.windows.in create mode 100644 examples/espidf-coap-server/components/libcoap/configure.ac create mode 100644 examples/espidf-coap-server/components/libcoap/doc/Doxyfile.in create mode 100644 examples/espidf-coap-server/components/libcoap/doc/Makefile.am create mode 100644 examples/espidf-coap-server/components/libcoap/doc/docbook.local.css create mode 100644 examples/espidf-coap-server/components/libcoap/doc/main.md create mode 100644 examples/espidf-coap-server/components/libcoap/doc/module_api_wrap.h create mode 100644 examples/espidf-coap-server/components/libcoap/doc/upgrade_4.2.1_4.3.0.txt create mode 100644 examples/espidf-coap-server/components/libcoap/doc/upgrade_4.3.0_4.3.1.txt create mode 100644 examples/espidf-coap-server/components/libcoap/examples/Makefile.am create mode 100644 examples/espidf-coap-server/components/libcoap/examples/README.etsi_iot create mode 100644 examples/espidf-coap-server/components/libcoap/examples/coap-client.c create mode 100644 examples/espidf-coap-server/components/libcoap/examples/coap-rd.c create mode 100644 examples/espidf-coap-server/components/libcoap/examples/coap-server.c create mode 100644 examples/espidf-coap-server/components/libcoap/examples/coap_list.c create mode 100644 examples/espidf-coap-server/components/libcoap/examples/coap_list.h create mode 100644 examples/espidf-coap-server/components/libcoap/examples/contiki/.gitignore create mode 100644 examples/espidf-coap-server/components/libcoap/examples/contiki/Makefile.contiki create mode 100644 examples/espidf-coap-server/components/libcoap/examples/contiki/README create mode 100644 examples/espidf-coap-server/components/libcoap/examples/contiki/coap-observer.c create mode 100644 examples/espidf-coap-server/components/libcoap/examples/contiki/radvd.conf.sample create mode 100644 examples/espidf-coap-server/components/libcoap/examples/contiki/server.c create mode 100644 examples/espidf-coap-server/components/libcoap/examples/etsi_coaptest.sh create mode 100644 examples/espidf-coap-server/components/libcoap/examples/etsi_iot_01.c create mode 100644 examples/espidf-coap-server/components/libcoap/examples/etsi_iot_01_largedata.txt create mode 100644 examples/espidf-coap-server/components/libcoap/examples/etsi_testcases.sh create mode 100644 examples/espidf-coap-server/components/libcoap/examples/getopt.c create mode 100644 examples/espidf-coap-server/components/libcoap/examples/lwip/.gitignore create mode 100644 examples/espidf-coap-server/components/libcoap/examples/lwip/README create mode 100644 examples/espidf-coap-server/components/libcoap/examples/lwip/lwipopts.h create mode 100644 examples/espidf-coap-server/components/libcoap/examples/lwip/server-coap.c create mode 100644 examples/espidf-coap-server/components/libcoap/examples/lwip/server-coap.h create mode 100644 examples/espidf-coap-server/components/libcoap/examples/lwip/server.c create mode 100644 examples/espidf-coap-server/components/libcoap/examples/share.libcoap.examples.Makefile create mode 100644 examples/espidf-coap-server/components/libcoap/examples/share.libcoap.examples.README create mode 100644 examples/espidf-coap-server/components/libcoap/examples/tiny.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ABOUT.md create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/AutoConf.cmake create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/CMakeLists.txt create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/CONTRIBUTING.md create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/LICENSE create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/Makefile.riot create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/Makefile.tinydtls create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/README.md create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/Makefile.riot create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael_wrap.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/alert.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/autogen.sh create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ccm.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ccm.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/configure.ac create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/crypto.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/crypto.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/doc/Doxyfile.in create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/doc/DoxygenLayout.xml create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_config.h.cmake.in create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_debug.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_debug.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_mutex.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_prng.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_prng.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_time.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_time.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.contiki create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.ecc create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.riot create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/ecc.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/ecc.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/test_helper.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/test_helper.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/testecc.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/testfield.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/global.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/hmac.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/hmac.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/netq.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/netq.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/numeric.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/peer.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/peer.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_contiki.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_espidf.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_posix.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_riot.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_zephyr.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/platform.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/riot_boards.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/session.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/session.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/README create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2prog.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2speed.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2test.pl create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector001.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector001.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector002.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector002.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector003.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector003.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector004.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector004.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector005.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector005.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector006.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector006.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector007.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector007.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector008.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector008.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector009.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector009.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector010.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector010.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector011.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector011.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector012.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector012.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector013.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector013.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector014.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector014.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector015.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector015.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector016.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector016.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector017.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector017.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector018.dat create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector018.info create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/state.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/CMakeLists.txt create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/cbc_aes128-test.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/cbc_aes128-testdata.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/ccm-test.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/ccm-testdata.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dsrv-test.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dtls-client.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dtls-server.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/netq-test.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/pcap.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ccm.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ccm.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ecc.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ecc.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_prf.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_prf.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/testdriver.c create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tinydtls.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/tinydtls.pc.in create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/uthash.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/utlist.h create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/zephyr/CMakeLists.txt create mode 100644 examples/espidf-coap-server/components/libcoap/ext/tinydtls/zephyr/Kconfig create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/block.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.in create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.windows create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.windows.in create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_address.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_asn1_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_async.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_async_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_block_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_cache.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_cache_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_debug.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_dtls.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_dtls_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_event.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_forward_decls.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_hashkey.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_io.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_io_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_mutex.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_net_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_option.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_pdu_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_prng.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_resource_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_riot.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_session.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_session_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_subscribe.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_subscribe_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_tcp_internal.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/coap_time.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/encode.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/libcoap.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/lwippools.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/mem.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/net.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/pdu.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/resource.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/str.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/uri.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/uthash.h create mode 100644 examples/espidf-coap-server/components/libcoap/include/coap3/utlist.h create mode 100644 examples/espidf-coap-server/components/libcoap/libcoap-3.map create mode 100644 examples/espidf-coap-server/components/libcoap/libcoap-3.pc.in create mode 100644 examples/espidf-coap-server/components/libcoap/libcoap-3.sym create mode 100644 examples/espidf-coap-server/components/libcoap/m4/ac_check_cryptolibs.m4 create mode 100644 examples/espidf-coap-server/components/libcoap/m4/ax_check_a2x_to_man.m4 create mode 100644 examples/espidf-coap-server/components/libcoap/m4/ax_check_compile_flag.m4 create mode 100644 examples/espidf-coap-server/components/libcoap/m4/ax_check_link_flag.m4 create mode 100644 examples/espidf-coap-server/components/libcoap/man/Makefile.am create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap-client.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap-rd.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap-server.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_async.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_attribute.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_block.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_cache.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_context.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_encryption.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_endpoint_client.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_endpoint_server.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_handler.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_io.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_keepalive.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_logging.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_observe.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_pdu_access.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_pdu_setup.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_recovery.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_resource.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_session.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_string.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/coap_tls_library.txt.in create mode 100644 examples/espidf-coap-server/components/libcoap/man/examples-code-check.c create mode 100644 examples/espidf-coap-server/components/libcoap/scripts/api-version-bump.sh create mode 100644 examples/espidf-coap-server/components/libcoap/scripts/build.sh create mode 100644 examples/espidf-coap-server/components/libcoap/scripts/dist.sh create mode 100644 examples/espidf-coap-server/components/libcoap/scripts/fix-cunit.sh create mode 100644 examples/espidf-coap-server/components/libcoap/scripts/format_cmake.sh create mode 100644 examples/espidf-coap-server/components/libcoap/scripts/github_dist.sh create mode 100644 examples/espidf-coap-server/components/libcoap/scripts/msbuild.sln.cmd create mode 100644 examples/espidf-coap-server/components/libcoap/src/block.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_address.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_asn1.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_async.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_cache.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_debug.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_event.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_gnutls.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_hashkey.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_io.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_io_lwip.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_io_riot.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_mbedtls.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_notls.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_openssl.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_option.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_prng.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_session.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_subscribe.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_tcp.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_time.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/coap_tinydtls.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/encode.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/mem.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/net.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/pdu.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/resource.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/str.c create mode 100644 examples/espidf-coap-server/components/libcoap/src/uri.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/Makefile.am create mode 100644 examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/Makefile.ci.in create mode 100644 examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/Makefile.oss-fuzz create mode 100644 examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/pdu_parse_target.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/split_uri_target.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_common.h.in create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_encode.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_encode.h create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_error_response.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_error_response.h create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_options.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_options.h create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_pdu.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_pdu.h create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_sendqueue.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_sendqueue.h create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_session.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_session.h create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_tls.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_tls.h create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_uri.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_uri.h create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_wellknown.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/test_wellknown.h create mode 100644 examples/espidf-coap-server/components/libcoap/tests/testdriver.c create mode 100644 examples/espidf-coap-server/components/libcoap/tests/valgrind_suppression create mode 100644 examples/espidf-coap-server/components/libcoap/win32/coap-client/coap-client.vcxproj create mode 100644 examples/espidf-coap-server/components/libcoap/win32/coap-client/coap-client.vcxproj.filters create mode 100644 examples/espidf-coap-server/components/libcoap/win32/coap-rd/coap-rd.vcxproj create mode 100644 examples/espidf-coap-server/components/libcoap/win32/coap-rd/coap-rd.vcxproj.filters create mode 100644 examples/espidf-coap-server/components/libcoap/win32/coap-server/coap-server.vcxproj create mode 100644 examples/espidf-coap-server/components/libcoap/win32/coap-server/coap-server.vcxproj.filters create mode 100644 examples/espidf-coap-server/components/libcoap/win32/libcoap.props create mode 100644 examples/espidf-coap-server/components/libcoap/win32/libcoap.sln create mode 100644 examples/espidf-coap-server/components/libcoap/win32/libcoap.vcxproj create mode 100644 examples/espidf-coap-server/components/libcoap/win32/libcoap.vcxproj.filters create mode 100644 examples/espidf-coap-server/components/libcoap/win32/testdriver/testdriver.vcxproj create mode 100644 examples/espidf-coap-server/components/libcoap/win32/testdriver/testdriver.vcxproj.filters create mode 100644 examples/espidf-coap-server/components/port/include/coap3/coap.h create mode 100644 examples/espidf-coap-server/components/port/include/coap_config.h create mode 100644 examples/espidf-coap-server/components/port/include/coap_config_posix.h create mode 100644 examples/espidf-exceptions/.travis.yml create mode 100644 examples/espidf-hello-world/.travis.yml create mode 100644 examples/espidf-hello-world/test/test_dummy/test_dummy.c create mode 100644 examples/espidf-http-request/.travis.yml create mode 100644 examples/espidf-peripherals-uart/.travis.yml create mode 100644 examples/espidf-peripherals-uart/src/Kconfig.projbuild create mode 100644 examples/espidf-peripherals-usb/.travis.yml create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_cdc_acm.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_config.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_console.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_tasks.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/cdc.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/cdc.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tinyusb.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_cdc_acm.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_console.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/usb_descriptors.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/vfs_tinyusb.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb_option.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml delete mode 100644 examples/espidf-peripherals-usb/src/Kconfig.projbuild delete mode 100644 examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c create mode 100644 examples/espidf-peripherals-usb/src/tusb_serial_device_main.c create mode 100644 examples/espidf-storage-sdcard/.travis.yml create mode 100644 examples/espidf-storage-sdcard/src/Kconfig.projbuild create mode 100644 examples/espidf-storage-spiffs/.gitignore create mode 100644 examples/espidf-storage-spiffs/CMakeLists.txt create mode 100644 examples/espidf-storage-spiffs/README.md create mode 100644 examples/espidf-storage-spiffs/data/hello.txt create mode 100644 examples/espidf-storage-spiffs/include/README create mode 100644 examples/espidf-storage-spiffs/lib/README create mode 100644 examples/espidf-storage-spiffs/partitions_example.csv create mode 100644 examples/espidf-storage-spiffs/platformio.ini create mode 100644 examples/espidf-storage-spiffs/sdkconfig.defaults create mode 100644 examples/espidf-storage-spiffs/src/CMakeLists.txt create mode 100644 examples/espidf-storage-spiffs/src/Kconfig.projbuild create mode 100644 examples/espidf-storage-spiffs/src/spiffs_example_main.c create mode 100644 examples/espidf-storage-spiffs/test/README delete mode 100644 examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 delete mode 100644 examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index ac560a5c6..354ca3a0c 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -575,6 +575,15 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): ) +# A temporary workaround to avoid modifying CMake mainly for the "heap" library. +# The "tlsf.c" source file in this library has an include flag relative +# to CMAKE_CURRENT_SOURCE_DIR which breaks PlatformIO builds that have a +# different working directory +def _fix_component_relative_include(config, build_flags, source_index): + source_file_path = config["sources"][source_index]["path"] + build_flags = build_flags.replace("..", os.path.dirname(source_file_path) + "/..") + return build_flags + def prepare_build_envs(config, default_env, debug_allowed=True): build_envs = [] target_compile_groups = config.get("compileGroups") @@ -596,6 +605,10 @@ def prepare_build_envs(config, default_env, debug_allowed=True): for cc in compile_commands: build_flags = cc.get("fragment") if not build_flags.startswith("-D"): + if build_flags.startswith("-include") and ".." in build_flags: + source_index = cg.get("sourceIndexes")[0] + build_flags = _fix_component_relative_include( + config, build_flags, source_index) build_env.AppendUnique(**build_env.ParseFlags(build_flags)) build_env.AppendUnique(CPPDEFINES=defines, CPPPATH=includes) if sys_includes: @@ -638,9 +651,17 @@ def compile_source_files( else: obj_path = os.path.join(obj_path, os.path.basename(src_path)) + preserve_source_file_extension = board.get( + "build.esp-idf.preserve_source_file_extension", False + ) + objects.append( build_envs[compile_group_idx].StaticObject( - target=os.path.splitext(obj_path)[0] + ".o", + target=( + obj_path + if preserve_source_file_extension + else os.path.splitext(obj_path)[0] + ) + ".o", source=os.path.realpath(src_path), ) ) @@ -1028,7 +1049,14 @@ def _get_installed_pip_packages(): result = {} packages = {} pip_output = subprocess.check_output( - [env.subst("$PYTHONEXE"), "-m", "pip", "list", "--format=json"] + [ + env.subst("$PYTHONEXE"), + "-m", + "pip", + "list", + "--format=json", + "--disable-pip-version-check", + ] ) try: packages = json.loads(pip_output) @@ -1045,9 +1073,13 @@ def _get_installed_pip_packages(): "wheel": ">=0.35.1", "cryptography": ">=2.1.4,<35.0.0", "future": ">=0.15.2", - "pyparsing": ">=2.0.3,<2.4.0", + "pyparsing": ">=3" + if platform.get_package_version("framework-espidf") + .split(".")[1] + .startswith("5") + else ">=2.0.3,<2.4.0", "kconfiglib": "==13.7.1", - "idf-component-manager": "~=1.0" + "idf-component-manager": "~=1.0", } installed_packages = _get_installed_pip_packages() @@ -1471,4 +1503,6 @@ def _skip_prj_source_files(node): ) # Propagate application offset to debug configurations -env["INTEGRATION_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")}) +env["INTEGRATION_EXTRA_DATA"].update( + {"application_offset": env.subst("$ESP32_APP_OFFSET")} +) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index c66d1baa6..416b5b20d 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -77,7 +77,7 @@ def get_component_includes(target_config): def generate_ulp_config(target_config): - riscv_ulp_enabled = sdk_config.get((idf_variant).upper() + "_ULP_COPROC_RISCV", False) + riscv_ulp_enabled = sdk_config.get("ULP_COPROC_TYPE_RISCV", False) ulp_sources = collect_ulp_sources() ulp_sources.sort() diff --git a/examples/espidf-arduino-blink/.travis.yml b/examples/espidf-arduino-blink/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-arduino-blink/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-arduino-blink/README.md b/examples/espidf-arduino-blink/README.md index fe5ffeefb..0d26cd306 100644 --- a/examples/espidf-arduino-blink/README.md +++ b/examples/espidf-arduino-blink/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 823bb97a9..b92c49577 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -5,25 +5,20 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env] platform = espressif32 framework = arduino, espidf +build_flags = + -D CONFIG_BLINK_GPIO=2 monitor_speed = 115200 [env:esp32dev] board = esp32dev -build_flags = -DCONFIG_BLINK_GPIO=2 -[env:esp32-s2] -board = esp32-s2-saola-1 -build_flags = -DCONFIG_BLINK_GPIO=18 +[env:espea32] +board = espea32 -[env:esp32-s3] -board = esp32-s3-devkitc-1 -build_flags = -DCONFIG_BLINK_GPIO=48 - -[env:esp32-c3] -board = esp32-c3-devkitm-1 -build_flags = -DCONFIG_BLINK_GPIO=8 +[env:esp320] +board = esp320 diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index 2c9d60715..1af06b975 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -1,3 +1,5 @@ CONFIG_AUTOSTART_ARDUINO=y # CONFIG_WS2812_LED_ENABLE is not set CONFIG_FREERTOS_HZ=1000 +CONFIG_MBEDTLS_PSK_MODES=y +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y diff --git a/examples/espidf-arduino-blink/src/Blink.cpp b/examples/espidf-arduino-blink/src/Blink.cpp index 771ad748e..c69fd30f5 100644 --- a/examples/espidf-arduino-blink/src/Blink.cpp +++ b/examples/espidf-arduino-blink/src/Blink.cpp @@ -51,7 +51,7 @@ void arduinoTask(void *pvParameter) { } } -void app_main() +extern "C" void app_main() { // initialize arduino library before we start the tasks initArduino(); @@ -70,4 +70,4 @@ void loop() { Serial.println("Hello!"); delay(1000); } -#endif \ No newline at end of file +#endif diff --git a/examples/espidf-arduino-wifiscan/.travis.yml b/examples/espidf-arduino-wifiscan/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-arduino-wifiscan/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-arduino-wifiscan/README.md b/examples/espidf-arduino-wifiscan/README.md index f858f3a45..390736b68 100644 --- a/examples/espidf-arduino-wifiscan/README.md +++ b/examples/espidf-arduino-wifiscan/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-arduino-wifiscan/platformio.ini b/examples/espidf-arduino-wifiscan/platformio.ini index 79e7284f6..6f6d15335 100644 --- a/examples/espidf-arduino-wifiscan/platformio.ini +++ b/examples/espidf-arduino-wifiscan/platformio.ini @@ -5,7 +5,7 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env] platform = espressif32 diff --git a/examples/espidf-arduino-wifiscan/src/main.cpp b/examples/espidf-arduino-wifiscan/src/main.cpp index 3caa3b968..32d876806 100644 --- a/examples/espidf-arduino-wifiscan/src/main.cpp +++ b/examples/espidf-arduino-wifiscan/src/main.cpp @@ -51,7 +51,7 @@ void arduinoTask(void *pvParameter) { } } -void app_main() +extern "C" void app_main() { // initialize arduino library before we start the tasks initArduino(); diff --git a/examples/espidf-aws-iot/.travis.yml b/examples/espidf-aws-iot/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-aws-iot/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-aws-iot/README.md b/examples/espidf-aws-iot/README.md index 40a8ccfa2..da21cb256 100644 --- a/examples/espidf-aws-iot/README.md +++ b/examples/espidf-aws-iot/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-aws-iot/platformio.ini b/examples/espidf-aws-iot/platformio.ini index 015c8d4e1..5bf94f9d8 100644 --- a/examples/espidf-aws-iot/platformio.ini +++ b/examples/espidf-aws-iot/platformio.ini @@ -5,15 +5,22 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env:esp32dev] platform = espressif32 framework = espidf board = esp32dev monitor_speed = 115200 +monitor_filters = colorize -board_build.embed_txtfiles = +board_build.embed_txtfiles = src/certs/private.pem.key src/certs/certificate.pem.crt src/certs/aws-root-ca.pem + +# IDF v5 is not supported by ASW-IoT SDK +# https://github.com/espressif/esp-aws-iot/blob/bbaf03d7d1fbf8a3f91dc18489d7bd27d5b9e9df/README.md?plain=1#L21 +platform_packages = + framework-espidf @ ~3.40403.0 + toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5 diff --git a/examples/espidf-ble-eddystone/.travis.yml b/examples/espidf-ble-eddystone/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-ble-eddystone/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-ble-eddystone/README.md b/examples/espidf-ble-eddystone/README.md index 85cd58330..95ad3377c 100644 --- a/examples/espidf-ble-eddystone/README.md +++ b/examples/espidf-ble-eddystone/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-ble-eddystone/platformio.ini b/examples/espidf-ble-eddystone/platformio.ini index c3cc3d08e..6d6af7407 100644 --- a/examples/espidf-ble-eddystone/platformio.ini +++ b/examples/espidf-ble-eddystone/platformio.ini @@ -5,7 +5,7 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env:esp32dev] platform = espressif32 diff --git a/examples/espidf-ble-eddystone/src/CMakeLists.txt b/examples/espidf-ble-eddystone/src/CMakeLists.txt index cdd852c57..0820e85fc 100644 --- a/examples/espidf-ble-eddystone/src/CMakeLists.txt +++ b/examples/espidf-ble-eddystone/src/CMakeLists.txt @@ -1,3 +1,4 @@ idf_component_register(SRCS "esp_eddystone_api.c" "esp_eddystone_demo.c" - INCLUDE_DIRS "") \ No newline at end of file + INCLUDE_DIRS "") +target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") diff --git a/examples/espidf-ble-eddystone/src/esp_eddystone_api.c b/examples/espidf-ble-eddystone/src/esp_eddystone_api.c index 20fffb2e6..283211650 100644 --- a/examples/espidf-ble-eddystone/src/esp_eddystone_api.c +++ b/examples/espidf-ble-eddystone/src/esp_eddystone_api.c @@ -1,10 +1,8 @@ /* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ /**************************************************************************** @@ -62,21 +60,21 @@ Byte offset Field Description 0 Frame Type Value = 0x00 1 Ranging Data Calibrated Tx power at 0 m 2 NID[0] 10-byte Namespace - 3 NID[1] - 4 NID[2] - 5 NID[3] - 6 NID[4] - 7 NID[5] - 8 NID[6] - 9 NID[7] - 10 NID[8] - 11 NID[9] + 3 NID[1] + 4 NID[2] + 5 NID[3] + 6 NID[4] + 7 NID[5] + 8 NID[6] + 9 NID[7] + 10 NID[8] + 11 NID[9] 12 BID[0] 6-byte Instance - 13 BID[1] - 14 BID[2] - 15 BID[3] - 16 BID[4] - 17 BID[5] + 13 BID[1] + 14 BID[2] + 15 BID[3] + 16 BID[4] + 17 BID[5] 18 RFU Reserved for future use, must be0x00 19 RFU Reserved for future use, must be0x00 *********************************************/ @@ -135,7 +133,7 @@ static esp_err_t esp_eddystone_url_received(const uint8_t* buf, uint8_t len, esp //ERROR:too long url return -1; } - res->inform.url.tx_power = buf[pos++]; + res->inform.url.tx_power = buf[pos++]; url_res = esp_eddystone_resolve_url_scheme(buf+pos, buf+len-1); memcpy(&res->inform.url.url, url_res, strlen(url_res)); res->inform.url.url[strlen(url_res)] = '\0'; @@ -148,17 +146,17 @@ Byte offset Field Description 0 Frame Type Value = 0x20 1 Version TLM version, value = 0x00 2 VBATT[0] Battery voltage, 1 mV/bit - 3 VBATT[1] + 3 VBATT[1] 4 TEMP[0] Beacon temperature - 5 TEMP[1] + 5 TEMP[1] 6 ADV_CNT[0] Advertising PDU count - 7 ADV_CNT[1] - 8 ADV_CNT[2] - 9 ADV_CNT[3] + 7 ADV_CNT[1] + 8 ADV_CNT[2] + 9 ADV_CNT[3] 10 SEC_CNT[0] Time since power-on or reboot - 11 SEC_CNT[1] - 12 SEC_CNT[2] - 13 SEC_CNT[3] + 11 SEC_CNT[1] + 12 SEC_CNT[2] + 13 SEC_CNT[3] ************************************************/ /* decode and store received TLM */ static esp_err_t esp_eddystone_tlm_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res) @@ -211,14 +209,14 @@ esp_err_t esp_eddystone_decode(const uint8_t* buf, uint8_t len, esp_eddystone_re return -1; } uint8_t pos=0; - while(res->common.srv_data_type != EDDYSTONE_SERVICE_UUID) + while(res->common.srv_data_type != EDDYSTONE_SERVICE_UUID) { pos++; - if(pos >= len ) { + if(pos >= len ) { return -1; } uint8_t ad_type = buf[pos++]; - switch(ad_type) + switch(ad_type) { case ESP_BLE_AD_TYPE_FLAG: { res->common.flags = buf[pos++]; @@ -227,7 +225,7 @@ esp_err_t esp_eddystone_decode(const uint8_t* buf, uint8_t len, esp_eddystone_re case ESP_BLE_AD_TYPE_16SRV_CMPL: { uint16_t uuid = little_endian_read_16(buf, pos); if(uuid != EDDYSTONE_SERVICE_UUID) { - return -1; + return -1; } res->common.srv_uuid = uuid; pos += 2; @@ -237,7 +235,7 @@ esp_err_t esp_eddystone_decode(const uint8_t* buf, uint8_t len, esp_eddystone_re uint16_t type = little_endian_read_16(buf, pos); pos += 2; uint8_t frame_type = buf[pos++]; - if(type != EDDYSTONE_SERVICE_UUID || !(frame_type == EDDYSTONE_FRAME_TYPE_UID || frame_type == EDDYSTONE_FRAME_TYPE_URL || + if(type != EDDYSTONE_SERVICE_UUID || !(frame_type == EDDYSTONE_FRAME_TYPE_UID || frame_type == EDDYSTONE_FRAME_TYPE_URL || frame_type == EDDYSTONE_FRAME_TYPE_TLM)) { return -1; } @@ -251,4 +249,3 @@ esp_err_t esp_eddystone_decode(const uint8_t* buf, uint8_t len, esp_eddystone_re } return esp_eddystone_get_inform(buf+pos, len-pos, res); } - diff --git a/examples/espidf-ble-eddystone/src/esp_eddystone_api.h b/examples/espidf-ble-eddystone/src/esp_eddystone_api.h index 41ad278e8..752044f67 100644 --- a/examples/espidf-ble-eddystone/src/esp_eddystone_api.h +++ b/examples/espidf-ble-eddystone/src/esp_eddystone_api.h @@ -1,10 +1,8 @@ /* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ #ifndef __ESP_EDDYSTONE_API_H__ @@ -57,8 +55,8 @@ static inline uint32_t big_endian_read_32(const uint8_t *buffer, uint8_t pos) } /* - * The esp eddystone API. - * This function is called to decode eddystone information from adv_data. + * The esp eddystone API. + * This function is called to decode eddystone information from adv_data. * The res points to the result struct. * */ @@ -67,4 +65,3 @@ esp_err_t esp_eddystone_decode(const uint8_t* buf, uint8_t len, esp_eddystone_re //bool esp_eddystone_is_eddystone_packet(.....); #endif /* __ESP_EDDYSTONE_API_H__ */ - diff --git a/examples/espidf-ble-eddystone/src/esp_eddystone_demo.c b/examples/espidf-ble-eddystone/src/esp_eddystone_demo.c index 525bcd2ae..76c1025dc 100644 --- a/examples/espidf-ble-eddystone/src/esp_eddystone_demo.c +++ b/examples/espidf-ble-eddystone/src/esp_eddystone_demo.c @@ -1,10 +1,8 @@ /* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ /**************************************************************************** @@ -110,7 +108,7 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* par // error:The received data is not an eddystone frame packet or a correct eddystone frame packet. // just return return; - } else { + } else { // The received adv data is a correct eddystone frame packet. // Here, we get the eddystone infomation in eddystone_res, we can use the data in res to do other things. // For example, just print them: @@ -143,7 +141,7 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* par void esp_eddystone_appRegister(void) { esp_err_t status; - + ESP_LOGI(DEMO_TAG,"Register callback"); /* +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-blink/README.md b/examples/espidf-blink/README.md index 7d32f6177..1fbbba65a 100644 --- a/examples/espidf-blink/README.md +++ b/examples/espidf-blink/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-blink/lib/README b/examples/espidf-blink/lib/README index 6debab1e8..bb6727c81 100644 --- a/examples/espidf-blink/lib/README +++ b/examples/espidf-blink/lib/README @@ -1,46 +1,77 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include +# Blink Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example demonstrates how to blink a LED using GPIO or using the [led_strip](https://components.espressif.com/component/espressif/led_strip) component for the addressable LED, i.e. [WS2812](http://www.world-semi.com/Certifications/WS2812B.html). + +The `led_strip` is installed via [component manager](main/idf_component.yml). + +## How to Use Example + +Before project configuration and build, be sure to set the correct chip target using `idf.py set-target `. + +### Hardware Required + +* A development board with Espressif SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) +* A USB cable for Power supply and programming + +Some development boards use an addressable LED instead of a regular one. These development boards include: + +| Board | LED type | Pin | +| -------------------- | -------------------- | -------------------- | +| ESP32-C3-DevKitC-1 | Addressable | GPIO8 | +| ESP32-C3-DevKitM-1 | Addressable | GPIO8 | +| ESP32-S2-DevKitM-1 | Addressable | GPIO18 | +| ESP32-S2-Saola-1 | Addressable | GPIO18 | +| ESP32-S3-DevKitC-1 | Addressable | GPIO48 | + +See [Development Boards](https://www.espressif.com/en/products/devkits) for more information about it. + +### Configure the Project -int main (void) -{ - ... -} +Open the project configuration menu (`idf.py menuconfig`). +In the `Example Configuration` menu: + +* Select the LED type in the `Blink LED type` option. + * Use `GPIO` for regular LED blink. +* Set the GPIO number used for the signal in the `Blink GPIO number` option. +* Set the blinking period in the `Blink period in ms` option. + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +As you run the example, you will see the LED blinking, according to the previously defined period. For the addressable LED, you can also change the LED color by setting the `led_strip_set_pixel(led_strip, 0, 16, 16, 16);` (LED Strip, Pixel Number, Red, Green, Blue) with values from 0 to 255 in the [source file](main/blink_example_main.c). + +```text +I (315) example: Example configured to blink addressable LED! +I (325) example: Turning the LED OFF! +I (1325) example: Turning the LED ON! +I (2325) example: Turning the LED OFF! +I (3325) example: Turning the LED ON! +I (4325) example: Turning the LED OFF! +I (5325) example: Turning the LED ON! +I (6325) example: Turning the LED OFF! +I (7325) example: Turning the LED ON! +I (8325) example: Turning the LED OFF! ``` -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. +Note: The color order could be different according to the LED model. + +The pixel number indicates the pixel position in the LED strip. For a single LED, use 0. + +## Troubleshooting + +* If the LED isn't blinking, check the GPIO or the LED type selection in the `Example Configuration` menu. -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. \ No newline at end of file diff --git a/examples/espidf-blink/platformio.ini b/examples/espidf-blink/platformio.ini index bb18e7640..d10e91722 100644 --- a/examples/espidf-blink/platformio.ini +++ b/examples/espidf-blink/platformio.ini @@ -5,7 +5,7 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env:esp32dev] platform = espressif32 @@ -15,21 +15,6 @@ monitor_speed = 115200 build_flags = ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led -D CONFIG_BLINK_GPIO=2 + -D CONFIG_BLINK_LED_GPIO=2 + -D CONFIG_BLINK_PERIOD=1000 -[env:esp32-s2] -platform = espressif32 -framework = espidf -board = esp32-s2-saola-1 -monitor_speed = 115200 -build_flags = - ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led - -D CONFIG_BLINK_GPIO=2 - -[env:esp32-s3] -platform = espressif32 -framework = espidf -board = esp32-s3-devkitc-1 -monitor_speed = 115200 -build_flags = - ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led - -D CONFIG_BLINK_GPIO=2 diff --git a/examples/espidf-blink/src/blink.c b/examples/espidf-blink/src/blink.c index 9c58645f9..a4cde01e7 100644 --- a/examples/espidf-blink/src/blink.c +++ b/examples/espidf-blink/src/blink.c @@ -10,32 +10,82 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" +#include "esp_log.h" +//#include "led_strip.h" #include "sdkconfig.h" -/* Can use project configuration menu (idf.py menuconfig) to choose the GPIO to blink, +static const char *TAG = "example"; + +/* Use project configuration menu (idf.py menuconfig) to choose the GPIO to blink, or you can edit the following line and set a number here. */ #define BLINK_GPIO CONFIG_BLINK_GPIO -void app_main() +static uint8_t s_led_state = 0; + +#ifdef CONFIG_BLINK_LED_RMT + +static led_strip_handle_t led_strip; + +static void blink_led(void) { - /* Configure the IOMUX register for pad BLINK_GPIO (some pads are - muxed to GPIO on reset already, but some default to other - functions and need to be switched to GPIO. Consult the - Technical Reference for a list of pads and their default - functions.) - */ - gpio_pad_select_gpio(BLINK_GPIO); + /* If the addressable LED is enabled */ + if (s_led_state) { + /* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */ + led_strip_set_pixel(led_strip, 0, 16, 16, 16); + /* Refresh the strip to send data */ + led_strip_refresh(led_strip); + } else { + /* Set all LED off to clear all pixels */ + led_strip_clear(led_strip); + } +} + +static void configure_led(void) +{ + ESP_LOGI(TAG, "Example configured to blink addressable LED!"); + /* LED strip initialization with the GPIO and pixels number*/ + led_strip_config_t strip_config = { + .strip_gpio_num = BLINK_GPIO, + .max_leds = 1, // at least one LED on board + }; + led_strip_rmt_config_t rmt_config = { + .resolution_hz = 10 * 1000 * 1000, // 10MHz + }; + ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip)); + /* Set all LED off to clear all pixels */ + led_strip_clear(led_strip); +} + +#elif CONFIG_BLINK_LED_GPIO + +static void blink_led(void) +{ + /* Set the GPIO level according to the state (LOW or HIGH)*/ + gpio_set_level(BLINK_GPIO, s_led_state); +} + +static void configure_led(void) +{ + ESP_LOGI(TAG, "Example configured to blink GPIO LED!"); + gpio_reset_pin(BLINK_GPIO); /* Set the GPIO as a push/pull output */ gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); - while(1) { - /* Blink off (output low) */ - printf("Turning off the LED\n"); - gpio_set_level(BLINK_GPIO, 0); - vTaskDelay(1000 / portTICK_PERIOD_MS); - /* Blink on (output high) */ - printf("Turning on the LED\n"); - gpio_set_level(BLINK_GPIO, 1); - vTaskDelay(1000 / portTICK_PERIOD_MS); +} + +#endif + +void app_main(void) +{ + + /* Configure the peripheral according to the LED type */ + configure_led(); + + while (1) { + ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "ON" : "OFF"); + blink_led(); + /* Toggle the LED state */ + s_led_state = !s_led_state; + vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS); } } diff --git a/examples/espidf-coap-server/.travis.yml b/examples/espidf-coap-server/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-coap-server/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-coap-server/README.md b/examples/espidf-coap-server/README.md index 63d4ec630..19328b4e5 100644 --- a/examples/espidf-coap-server/README.md +++ b/examples/espidf-coap-server/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-coap-server/components/CMakeLists.txt b/examples/espidf-coap-server/components/CMakeLists.txt new file mode 100644 index 000000000..f53f6b78a --- /dev/null +++ b/examples/espidf-coap-server/components/CMakeLists.txt @@ -0,0 +1,41 @@ +if(NOT CONFIG_LWIP_IPV6 AND NOT CMAKE_BUILD_EARLY_EXPANSION) + message(STATUS "IPV6 support is disabled so the coap component will not be built") + # note: the component is still included in the build so it can become visible again in config + # without needing to re-run CMake. However no source or header files are built. + idf_component_register() + return() +endif() + +set(include_dirs port/include port/include libcoap/include) + +set(srcs + "libcoap/src/block.c" + "libcoap/src/coap_address.c" + "libcoap/src/coap_asn1.c" + "libcoap/src/coap_async.c" + "libcoap/src/coap_cache.c" + "libcoap/src/coap_debug.c" + "libcoap/src/coap_event.c" + "libcoap/src/coap_hashkey.c" + "libcoap/src/coap_io.c" + "libcoap/src/coap_notls.c" + "libcoap/src/coap_option.c" + "libcoap/src/coap_prng.c" + "libcoap/src/coap_session.c" + "libcoap/src/coap_subscribe.c" + "libcoap/src/coap_tcp.c" + "libcoap/src/coap_time.c" + "libcoap/src/encode.c" + "libcoap/src/mem.c" + "libcoap/src/net.c" + "libcoap/src/pdu.c" + "libcoap/src/resource.c" + "libcoap/src/str.c" + "libcoap/src/uri.c" + "libcoap/src/coap_mbedtls.c") + +idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS "${include_dirs}" + REQUIRES lwip mbedtls) +target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") + diff --git a/examples/espidf-coap-server/components/Kconfig b/examples/espidf-coap-server/components/Kconfig new file mode 100644 index 000000000..9deb56ab8 --- /dev/null +++ b/examples/espidf-coap-server/components/Kconfig @@ -0,0 +1,109 @@ +menu "CoAP Configuration" + visible if LWIP_IPV6 + + choice COAP_MBEDTLS_ENCRYPTION_MODE + prompt "CoAP Encryption method" + default COAP_MBEDTLS_PSK + help + If the CoAP information is to be encrypted, the encryption environment + can be set up in one of two ways (default being Pre-Shared key mode) + + - Encrypt using defined Pre-Shared Keys (PSK if uri includes coaps://) + - Encrypt using defined Public Key Infrastructure (PKI if uri includes coaps://) + + config COAP_MBEDTLS_PSK + bool "Pre-Shared Keys" + + config COAP_MBEDTLS_PKI + bool "PKI Certificates" + + endchoice #COAP_MBEDTLS_ENCRYPTION_MODE + + config COAP_MBEDTLS_DEBUG + bool "Enable CoAP debugging" + default n + help + Enable CoAP debugging functions at compile time for the example code. + + If this option is enabled, call coap_set_log_level() + at runtime in order to enable CoAP debug output via the ESP + log mechanism. + + Note: The Mbed TLS library logging is controlled by the mbedTLS + configuration, but logging level mbedTLS must be set for CoAP + to log it. + + choice COAP_MBEDTLS_DEBUG_LEVEL + bool "Set CoAP debugging level" + depends on COAP_MBEDTLS_DEBUG + default COAP_LOG_WARNING + help + Set CoAP debugging level + + config COAP_LOG_EMERG + bool "Emergency" + config COAP_LOG_ALERT + bool "Alert" + config COAP_LOG_CRIT + bool "Critical" + config COAP_LOG_ERROR + bool "Error" + config COAP_LOG_WARNING + bool "Warning" + config COAP_LOG_NOTICE + bool "Notice" + config COAP_LOG_INFO + bool "Info" + config COAP_LOG_DEBUG + bool "Debug" + config COAP_LOG_MBEDTLS + bool "mbedTLS" + endchoice + + config COAP_LOG_DEFAULT_LEVEL + int + default 0 if !COAP_MBEDTLS_DEBUG + default 0 if COAP_LOG_EMERG + default 1 if COAP_LOG_ALERT + default 2 if COAP_LOG_CRIT + default 3 if COAP_LOG_ERROR + default 4 if COAP_LOG_WARNING + default 5 if COAP_LOG_NOTICE + default 6 if COAP_LOG_INFO + default 7 if COAP_LOG_DEBUG + default 9 if COAP_LOG_MBEDTLS + + config COAP_TCP_SUPPORT + bool "Enable TCP within CoAP" + default y + help + Enable TCP functionality for CoAP. This is required if TLS sessions + are to be used. + + If this option is disabled, redundent CoAP TCP code is removed. + + config COAP_CLIENT_SUPPORT + bool "Enable Client functionality within CoAP" + default n + help + Enable client functionality (ability to make requests and receive + responses) for CoAP. If the server is going to act as a proxy, then + this needs to be enabled to support the ongoing session going to + the next hop. + + If this option is disabled, redundent CoAP client only code is removed. + If both this option and COAP_SERVER_SUPPORT are disabled, then both + are automatically enabled for backwards compatability. + + config COAP_SERVER_SUPPORT + bool "Enable Server functionality within CoAP" + default n + help + Enable server functionality (ability to receive requests and send + responses) for CoAP. + + If this option is disabled, redundent CoAP server only code is removed. + If both this option and COAP_CLIENT_SUPPORT are disabled, then both + are automatically enabled for backwards compatability. + +endmenu diff --git a/examples/espidf-coap-server/components/LICENSE b/examples/espidf-coap-server/components/LICENSE new file mode 100644 index 000000000..78d2c5587 --- /dev/null +++ b/examples/espidf-coap-server/components/LICENSE @@ -0,0 +1,85 @@ +Copyright (c) 2010--2022, Olaf Bergmann and others +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + o Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + o 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. + +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 +HOLDER 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. + +======================================================================== +getopt.c + +License information for getopt.c. This file is only used on Windows +builds of the executables in the examples folder: + +/* + * This file was copied from the following newsgroup posting: + * + * Newsgroups: mod.std.unix + * Subject: public domain AT&T getopt source + * Date: 3 Nov 85 19:34:15 GMT + * + * Here's something you've all been waiting for: the AT&T public domain + * source for getopt(3). It is the code which was given out at the 1985 + * UNIFORUM conference in Dallas. I obtained it by electronic mail + * directly from AT&T. The people there assure me that it is indeed + * in the public domain. + */ + +======================================================================== +uthash + +libcoap uses uthash.h and utlist.h from Troy D. Hanson +(https://troydhanson.github.io/uthash/). These files use the revised +BSD license (BSD-1-Clause license) as included in these two source +files. + +======================================================================== +OpenSSL + +Binaries that are linked against OpenSSL include software developed +by the OpenSSL Project for use in the OpenSSL Toolkit. +(http://www.openssl.org/). Please consult the OpenSSL license +(https://www.openssl.org/source/license.html) for licensing terms. + +======================================================================== +GnuTLS + +When compiled with GnuTLS support, this software includes components +that are licensed under the terms of the the GNU Lesser General Public +License, version 2.1 +(https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html). + +======================================================================== +tinyDTLS + +When compiled with tinyDTLS support, this software includes components +that are licensed under the terms of the Eclipse Distribution License 1.0 +(http://www.eclipse.org/org/documents/edl-v10.php). + +======================================================================== +Mbed TLS + +When compiled with Mbed TLS support, this software includes components +that are licensed under the terms of the Apache 2.0 license +(http://www.apache.org/licenses/LICENSE-2.0). + diff --git a/examples/espidf-coap-server/components/README.md b/examples/espidf-coap-server/components/README.md new file mode 100644 index 000000000..faab2727e --- /dev/null +++ b/examples/espidf-coap-server/components/README.md @@ -0,0 +1,89 @@ +# libcoap: A C implementation of the Constrained Application Protocol (RFC 7252) + +[![Build Status: main](https://github.com/obgm/libcoap/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/obgm/libcoap/actions?query=branch:main) +[![Build Status: develop](https://github.com/obgm/libcoap/actions/workflows/main.yml/badge.svg?branch=develop)](https://github.com/obgm/libcoap/actions?query=branch:develop) +[![Static Analysis](https://scan.coverity.com/projects/10970/badge.svg?flat=1)](https://scan.coverity.com/projects/obgm-libcoap) +[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/libcoap.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:libcoap) + +Copyright (C) 2010—2022 by Olaf Bergmann and others + +ABOUT LIBCOAP +============= + +libcoap is a C implementation of a lightweight application-protocol +for devices that are constrained their resources such as computing +power, RF range, memory, bandwidth, or network packet sizes. This +protocol, CoAP, is standardized by the IETF as RFC 7252. For further +information related to CoAP, see . + +You might want to check out +[libcoap-minimal](https://github.com/obgm/libcoap-minimal) for usage +examples. + +DOCUMENTATION +============= + +Documentation and further information can be found at +. + +PACKAGE CONTENTS +================ + +This package contains a protocol parser and basic networking +functions for platforms with support for malloc() and BSD-style +sockets. In addition, there is support for Contiki, LwIP and +Espressif/ESP-IDF hosted environments. + +The following RFCs are supported + +* RFC7252: The Constrained Application Protocol (CoAP) + +* RFC7390: Group Communication for the Constrained Application Protocol (CoAP) + +* RFC7641: Observing Resources in the Constrained Application Protocol (CoAP) + +* RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP) + +* RFC7967: Constrained Application Protocol (CoAP) Option for No Server Response + +* RFC8132: PATCH and FETCH Methods for the Constrained Application Protocol (CoAP) + +* RFC8323: CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets + [No WebSockets support] + +* RFC8516: "Too Many Requests" Response Code for the Constrained Application Protocol + +* RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option + +* RFC9175: CoAP: Echo, Request-Tag, and Token Processing + +There is (D)TLS support for the following libraries + +* OpenSSL (Minimum version 1.1.0) [PKI, PSK and PKCS11] + +* GnuTLS (Minimum version 3.3.0) [PKI, PSK, RPK(3.6.6+) and PKCS11] + +* Mbed TLS (Minimum version 2.7.10) [PKI and PSK] + +* TinyDTLS [PSK and RPK] [DTLS Only] + +The examples directory contain a CoAP client, CoAP Resource Directory server +and a CoAP server to demonstrate the use of this library. + +BUILDING +======== + +Further information can be found at +and [BUILDING](https://raw.githubusercontent.com/obgm/libcoap/develop/BUILDING). + +LICENSE INFORMATION +=================== + +This library is published as open-source software without any warranty +of any kind. Use is permitted under the terms of the simplified BSD +license. It includes public domain software. libcoap binaries may also +include open-source software with their respective licensing terms. +Please refer to +[LICENSE](https://raw.githubusercontent.com/obgm/libcoap/develop/LICENSE) +for further details. + diff --git a/examples/espidf-coap-server/components/idf_component.yml b/examples/espidf-coap-server/components/idf_component.yml new file mode 100644 index 000000000..177c3ec3f --- /dev/null +++ b/examples/espidf-coap-server/components/idf_component.yml @@ -0,0 +1,5 @@ +dependencies: + idf: '>=4.4' +description: Constrained Application Protocol (CoAP) C Library +url: https://github.com/espressif/idf-extra-components/tree/master/coap +version: 4.3.1~1 diff --git a/examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/bug_report.md b/examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..7e8447a60 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,112 @@ +--- +name: Bug report +about: libcoap crashes, produces incorrect output, or has incorrect behavior +title: '' +labels: '' +assignees: '' + +--- + +----------------------------- Delete Below ----------------------------- + +INSTRUCTIONS +============ + +Before submitting a new issue, please follow the checklist and try to find the +answer. + +- [ ] I have read the documentation [libcoap Modules Documentation](https://libcoap.net/doc/reference/develop/modules.html) +and the issue is not addressed there. +- [ ] I have read the documentation [libcoap Manual Pages](https://libcoap.net/doc/reference/develop/manpage.html) +and the issue is not addressed there. +- [ ] I have updated my libcoap branch (develop) to the latest version and +checked that the issue is present there. +- [ ] I have searched the [Issue Tracker](https://github.com/obgm/libcoap/issues) +(both open and closed - overwrite `is:issue is:open`) for a similar issue and +not found a similar issue. +- [ ] I have checked the [Wiki](https://github.com/obgm/libcoap/wiki) to see if +the issue is reported there. +- [ ] I have read the HOWTOs provided with the source. +- [ ] I have read the [BUILDING](https://raw.githubusercontent.com/obgm/libcoap/develop/BUILDING) +on how to build from source. + +If the issue cannot be solved after checking through the steps above, please +follow these instructions so we can get the needed information to help you in a +quick and effective fashion. + +1. Fill in all the fields under **Environment** marked with [ ] by picking the +correct option for you in each case and deleting the others. +2. Describe your problem. +3. Include any debug logs (running the application with verbose logging). +4. Providing as much information as possible under **Other items if possible** +will help us locate and fix the problem. +5. Use [Markdown](https://guides.github.com/features/mastering-markdown/) (see +formatting buttons above) and the Preview tab to check what the issue will look +like. +6. Delete these instructions from the `Delete Below` to the `Delete Above` +marker lines before submitting this issue. + +**IMPORTANT: If you do not follow these instructions and provide the necessary +details, it may not be possible to resolve your issue.** + +----------------------------- Delete Above ----------------------------- + +## Environment + +- libcoap version (run ``git describe --tags`` to find it): + + // v4.3.0-rc3-41-g25fe796 +- Build System: [Make|CMake] +- Operating System: [Windows|Linux|macOS|FreeBSD|Cygwin|Solaris|RIOT|Other (which?)] +- Operating System Version: [ ] +- Hosted Environment: [None|Contiki|LwIP|ESP-IDF|Other (which?)] + +## Problem Description + +// Detailed problem description goes here. + +### Expected Behavior + +// Describe what you are expecting. + +### Actual Behavior + +// Describe what you are seeing. + +### Steps to reproduce + +1. step1 +2. ... + + +### Code to reproduce this issue + +```cpp +// the code should be wrapped in the ```cpp tag so that it will be displayed +better. +#include "coap3/coap.h" + +void main() +{ + +} + +``` +// If your code is longer than 30 lines, upload it as an attachment. Do not +include code that is proprietary or sensitive for your project. Try to reduce +your code as much as possible so that it only demonstrates the issue. + +## Debug Logs + +``` +Debug verbose logs go here. +Please copy the plain text here for us to search the error log. Or attach the +complete logs but leave the main part here if the log is *too* long. +``` + +## Other items if possible + +- [ ] Does what you are trying to do work under any configuration. Detail what +works. +- [ ] Network configuration that is not straightforward. Detail any networking +that may have NAT or firewalls that might affect what is going on. diff --git a/examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/config.yml b/examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..94f905ff1 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: false +contact_links: + - name: General libcoap Information + url: https://libcoap.net/ + about: General information about libcoap + - name: General libcoap Documentation + url: https://libcoap.net/documentation.html + about: Documentation information for libcoap + - name: Latest libcoap API Documentation + url: https://libcoap.net/doc/reference/develop/modules.html + about: Latest API information for libcoap + - name: Latest libcoap Manual Pages + url: https://libcoap.net/doc/reference/develop/manpage.html + about: Latest Manual Pages and Examples for libcoap diff --git a/examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/feature_request.md b/examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..d96b521e1 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,26 @@ +--- +name: Feature request +about: Suggest an idea for libcoap +title: '' +labels: 'Type: Feature Request' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** + +A clear and concise description of what the problem is. E.g. I'm always frustrated when [...] + +**Describe the solution you'd like** + +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** + +A clear and concise description of any alternative solutions or features you've considered. + +Please give as many details as you can. Include suggestions for useful APIs or interfaces if relevant. + +**Additional context** + +Add any other context or screenshots about the feature request here. diff --git a/examples/espidf-coap-server/components/libcoap/.github/workflows/main.yml b/examples/espidf-coap-server/components/libcoap/.github/workflows/main.yml new file mode 100644 index 000000000..0862f7cbf --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/.github/workflows/main.yml @@ -0,0 +1,196 @@ +name: Build Tests + +on: + push: + branches: + - main + - develop + - release-* + - gh-workflows + pull_request: + branches: + - main + - develop + +env: + PLATFORM: posix + TESTS: yes + OPENSSL_INSTALL_PATH: C:\Program Files\OpenSSL-Win64\ + +jobs: + build-linux: + runs-on: ubuntu-latest + strategy: + matrix: + CC: ["gcc", "clang"] + TLS: ["no", "openssl", "gnutls", "mbedtls"] + steps: + - uses: actions/checkout@v2 + - name: setup + run: | + sudo apt-get update && sudo apt-get install -y libcunit1-dev libmbedtls-dev libgnutls28-dev libtool libtool-bin exuberant-ctags valgrind + ./autogen.sh + - name: configure no-TLS + if: matrix.TLS == 'no' + run: | + mkdir build-${{matrix.TLS}}-${{matrix.CC}} + cd build-${{matrix.TLS}}-${{matrix.CC}} + $GITHUB_WORKSPACE/configure --disable-silent-rules --disable-documentation --enable-examples --enable-tests --disable-dtls CC=${{matrix.CC}} + - name: configure TLS + if: matrix.TLS != 'no' + run: | + mkdir build-${{matrix.TLS}}-${{matrix.CC}} + cd build-${{matrix.TLS}}-${{matrix.CC}} + "$GITHUB_WORKSPACE/configure" --disable-silent-rules --disable-documentation --enable-examples --enable-tests --with-${{matrix.TLS}} CC=${{matrix.CC}} + - name: compile + run: | + cd build-${{matrix.TLS}}-${{matrix.CC}} + make EXTRA_CFLAGS=-Werror && make check EXTRA_CFLAGS=-Werror + - name: test + run: | + cd build-${{matrix.TLS}}-${{matrix.CC}} + libtool --mode=execute valgrind --track-origins=yes --leak-check=yes --show-reachable=yes --error-exitcode=123 --quiet --suppressions=$GITHUB_WORKSPACE/tests/valgrind_suppression tests/testdriver + tinydtls-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: setup + run: | + sudo apt-get update && sudo apt-get install -y libcunit1-dev libtool libtool-bin exuberant-ctags valgrind + ./autogen.sh + - name: configure + run: | + $GITHUB_WORKSPACE/configure --disable-silent-rules --disable-documentation --enable-examples --enable-tests --with-tinydtls + - name: compile + run: | + make EXTRA_CFLAGS=-Werror && make check EXTRA_CFLAGS=-Werror + - name: test + run: | + LD_LIBRARY_PATH=ext/tinydtls libtool --mode=execute valgrind --track-origins=yes --leak-check=yes --show-reachable=yes --error-exitcode=123 --quiet --suppressions=$GITHUB_WORKSPACE/tests/valgrind_suppression tests/testdriver + cmake-build: + runs-on: ubuntu-latest + strategy: + matrix: + TLS: ["no", "openssl", "gnutls", "mbedtls", "tinydtls"] + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: setup + run: | + sudo apt-get update && sudo apt-get install -y libcunit1-dev libmbedtls-dev libgnutls28-dev + cmake -E make_directory $GITHUB_WORKSPACE}/build-${{matrix.TLS}}-cmake + - name: configure no-TLS + if: matrix.TLS == 'no' + run: | + cd $GITHUB_WORKSPACE}/build-${{matrix.TLS}}-cmake + cmake $GITHUB_WORKSPACE -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON -DENABLE_DTLS=OFF -DENABLE_DOCS=OFF + - name: configure TLS + if: matrix.TLS != 'no' + run: | + cd $GITHUB_WORKSPACE}/build-${{matrix.TLS}}-cmake + cmake $GITHUB_WORKSPACE -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON -DENABLE_DTLS=ON -DENABLE_DOCS=OFF -DDTLS_BACKEND=${{matrix.TLS}} + - name: build + run: | + cd $GITHUB_WORKSPACE}/build-${{matrix.TLS}}-cmake + cmake --build . + other-build: + runs-on: ubuntu-latest + strategy: + matrix: + OS: ["contiki", "lwip"] + steps: + - uses: actions/checkout@v2 + - name: setup + run: | + ./autogen.sh + - name: configure + run: | + $GITHUB_WORKSPACE/configure --disable-documentation --disable-examples --disable-tests --disable-dtls + - name: compile + run: | + make -C examples/${{matrix.OS}} + ms-build: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v1 + + - name: Install OpenSSL on Windows (choco) + run: | + choco install openssl + shell: cmd + + - name: Build sln + shell: cmd + run: call .\scripts\msbuild.sln.cmd + + additional-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: setup + run: | + sudo apt-get update && sudo apt-get install -y libgnutls28-dev libtool libtool-bin exuberant-ctags + ./autogen.sh + - name: configure + run: ./configure --disable-tests --disable-documentation + - name: build + run: | + make + make -C tests/oss-fuzz -f Makefile.ci check clean + documentation: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: setup + run: | + sudo apt-get update && sudo apt-get install -y libtool libtool-bin exuberant-ctags graphviz doxygen libxml2-utils xsltproc docbook-xml docbook-xsl asciidoc + ./autogen.sh + - name: configure + run: ./configure --disable-tests --enable-documentation --prefix $GITHUB_WORKSPACE/test-install + - name: manuals check + run: | + make -C man + - name: manual page examples check + run: | + man/examples-code-check man + - name: doxygen check + run: | + make -C doc + - name: installation check + run: | + make install && ls -lR $GITHUB_WORKSPACE/test-install + distribution: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: setup + run: | + sudo apt-get update && sudo apt-get install -y libcunit1-dev libtool libtool-bin exuberant-ctags graphviz doxygen libxml2-utils xsltproc docbook-xml docbook-xsl asciidoc + ./autogen.sh + - name: configure + run: | + mkdir build-dist + cd build-dist + $GITHUB_WORKSPACE/configure --enable-silent-rules --enable-documentation --enable-examples --disable-dtls + - name: build distribution + run: | + cd build-dist + make dist + - name: check distribution build + run: | + cd build-dist + $GITHUB_WORKSPACE/scripts/github_dist.sh + shell: bash diff --git a/examples/espidf-coap-server/components/libcoap/.gitignore b/examples/espidf-coap-server/components/libcoap/.gitignore new file mode 100644 index 000000000..65dde4b1c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/.gitignore @@ -0,0 +1,116 @@ +# .gitignore for libcoap + +# autosave files +*~ +\#*# + +# ignoring autogenerated files and directories by autoreconf +INSTALL +Makefile +Makefile.in +aclocal.m4 +ar-lib +autom4te.cache/ +coap_config.h +coap_config.h.in +compile +config.* +!config.yml +configure +debian/ +depcomp +install-sh +libcoap-*.tar.bz2 +libtool +ltmain.sh +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +missing +stamp-h1 + +# ignoring more files generated by the configure script or the make actions +.libs/ +libcoap*.la +libcoap*.pc +src/**/.deps/ +src/**/.dirstamp +src/**/.libs/ +src/**/*.o +src/**/*.lo +src/*.lo +src/*.o +src/.deps/ +src/.dirstamp +src/.libs/ +build/ + +# the doc/ folder +doc/Doxyfile +doc/Makefile.in +doc/docbook-xsl.css +doc/doxyfile.stamp +doc/doxygen_sqlite3.db +doc/DoxygenLayout.xml +doc/upgrade_*.html +doc/html/ +doc/man_html/ +doc/man_tmp/ + +# the man/ folder +man/docbook-xsl.css +man/examples-code-check +man/examples-code-check.exe +man/examples-code-check.o +man/Makefile +man/Makefile.in +man/tmp +man/.deps/ +man/*.html +man/*.txt +man/*.xml +man/*.3 +man/*.5 +man/*.7 + +# the examples/ folder +examples/.deps/ +examples/*.o +examples/coap-client +examples/coap-client-* +examples/coap-etsi_iot_01 +examples/coap-rd +examples/coap-rd-* +examples/coap-server +examples/coap-server-* +examples/coap-tiny +examples/*.exe + +# the include/ folder +include/coap3/coap.h + +# the tests/ folder +tests/.deps +tests/oss-fuzz/Makefile.ci +tests/testdriver +tests/*.o +tests/test_common.h + +# ctags - Sublime plugin +tags +.tags* +TAGS + +# ignore gcov-generated files +**/*.gcda +**/*.gcno +**/*.gcov + +# IDE files +CMakeLists.txt.user +/.vs/ +/out/ +/.vscode/ +/_build/ diff --git a/examples/espidf-coap-server/components/libcoap/.gitmodules b/examples/espidf-coap-server/components/libcoap/.gitmodules new file mode 100644 index 000000000..fb96bfdaf --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/.gitmodules @@ -0,0 +1,4 @@ +[submodule "ext/tinydtls"] + path = ext/tinydtls + url = https://github.com/eclipse/tinydtls.git + ignore = dirty diff --git a/examples/espidf-coap-server/components/libcoap/.travis.yml b/examples/espidf-coap-server/components/libcoap/.travis.yml new file mode 100644 index 000000000..ec9e71d7e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/.travis.yml @@ -0,0 +1,70 @@ +os: + - linux + +language: c + +compiler: + - gcc + - clang + +services: + - docker + +env: + - PLATFORM=posix TESTS=yes TLS=no + - PLATFORM=posix TESTS=yes TLS=gnutls SMALL_STACK=yes + - PLATFORM=posix TESTS=yes TLS=gnutls SMALL_STACK=no + - PLATFORM=posix TESTS=yes TLS=gnutls SMALL_STACK=yes EPOLL=no + - PLATFORM=posix TESTS=yes TLS=gnutls SMALL_STACK=no EPOLL=no + - PLATFORM=posix TESTS=yes TLS=openssl + - PLATFORM=posix TESTS=yes TLS=tinydtls + - PLATFORM=posix TESTS=yes TLS=mbedtls + +before_install: + - docker build -t obgm/libcoap:travis-env . + +branches: + only: + - main + - develop + - /^release-.*$/ + - travis-test + +stages: + - test + - other platforms + - dist + +jobs: + include: + - stage: other platforms + env: PLATFORM=contiki TLS=no + before_script: + script: + - docker run --privileged -e CC -e PLATFORM -e TLS obgm/libcoap:travis-env /bin/sh -c "scripts/build.sh" + - stage: other platforms + env: PLATFORM=lwip TLS=no + before_script: + script: + - docker run --privileged -e CC -e PLATFORM -e TLS obgm/libcoap:travis-env /bin/sh -c "scripts/build.sh" + - stage: dist + env: PLATFORM=posix TESTS=yes TLS=no DOCS=yes + before_script: + script: + - docker run --privileged -e CC -e PLATFORM -e TESTS -e DOCS -e TLS obgm/libcoap:travis-env /bin/sh -c "scripts/dist.sh" + +# Docker disables IPv6 in containers by default, so re-enable it. +before_script: + # `daemon.json` is normally missing, but let's log it in case that changes. + - sudo touch /etc/docker/daemon.json + - sudo cat /etc/docker/daemon.json + - sudo service docker stop + # This needs YAML quoting because of the curly braces. + - 'echo ''{"ipv6": true, "fixed-cidr-v6": "2001:db8:1::/64"}'' | sudo tee /etc/docker/daemon.json' + - sudo service docker start + # Fail early if docker failed on start -- add `- sudo dockerd` to debug. + - sudo docker info + # Paranoia log: what if our config got overwritten? + - sudo cat /etc/docker/daemon.json +script: + - docker run --privileged -e CC -e PLATFORM -e TESTS -e DOCS -e TLS -e EPOLL -e SMALL_STACK obgm/libcoap:travis-env /bin/sh -c "scripts/build.sh" diff --git a/examples/espidf-coap-server/components/libcoap/AUTHORS b/examples/espidf-coap-server/components/libcoap/AUTHORS new file mode 100644 index 000000000..d59fb8687 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/AUTHORS @@ -0,0 +1,8 @@ +Olaf Bergmann +Carsten Sch�nert +Jon Shallow +Jean-Claude Michelou +Christian Ams�ss + +For additional contributors, see +https://github.com/obgm/libcoap/graphs/contributors \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/BUILDING b/examples/espidf-coap-server/components/libcoap/BUILDING new file mode 100644 index 000000000..4a38182aa --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/BUILDING @@ -0,0 +1,157 @@ +For Windows builds - see the Windows Section + +Obtaining the Libcoap Source +============================ + +To get the libcoap library source, you need to do either the following + +* Obtain the latest distribution package file from + https://github.com/obgm/libcoap/archive/develop.zip + [There is a stable version at + https://github.com/obgm/libcoap/archive/main.zip] +* Change to the directory that you want to install the libcoap sub-directory + into +* Unpack the distribution package file +* Change into the top level directory of the unpackaged files + +or alternatively, clone the libcoap git repository from github + +* Change to the directory that you want to install the libcoap sub-directory + into. +* Then clone the latest (develop) version of the code:- + git clone https://github.com/obgm/libcoap.git +* Change into the top level directory of the cloned files +* Optionally, change the branch from develop to the stable main branch:- + git checkout main + +Building Libcoap Libraries and Examples +======================================= + +Follow the appropriate sections below + + +TinyDTLS Only +============= + +It is possible that you may need to execute the following two commands once to +get the TinyDTLS code into your project, so the TinyDTLS library can be used. + + git submodule init + git submodule update + +General Building with cmake for linux/windows/macos/android (not for LwIP or Contiki - see below) +================ + + cmake -E remove_directory build + cmake -E make_directory build + cd build + cmake .. -DENABLE_TESTS=ON + cmake --build . + [sudo] cmake --build . -- install + cd .. + + Note: to see possible options (TLS lib, doc, tests, examples etc.): + cmake -LH build + + Note: For Windows, this is supported by Visual Studio Code with CMake extension + Note: You must use cmake version >=3.10. + + Note: you can use cmake's find package after installation: find_package(libcoap-2 REQUIRED), + and target_link_libraries(myTarget PRIVATE libcoap::coap-2) + + Note: Shared Library support is not currently available for Windows. + +General Building with autoconf (not for LwIP or Contiki - see below) +================ + + ./autogen.sh + ./configure + make + sudo make install + +./autogen.sh will fail if there is a required package for buildling libcoap +that is missing. Install the missing package and try ./autogen.sh again. + +It is possible that you may need to provide some options to ./configure +to customize your installation. + +In particular you may need to define which (D)TLS library to use as well as +disable some building of documentation. + +General configure instructions can be found in INSTALL, which is built +by ./autogen.sh + + ./configure --help +gives the specific options available to libcoap. + +Some examples are:- + +# No DTLS + ./configure --enable-tests --disable-documentation --enable-examples --disable-dtls --enable-shared + +# With TinyDTLS + ./configure --enable-tests --disable-documentation --enable-examples --with-tinydtls --enable-shared + +Note: FreeBSD requires gmake instead of make when building TinyDTLS - i.e. + gmake + sudo gmake install + +# With OpenSSL + ./configure --with-openssl --enable-tests --enable-shared + +# With GnuTLS + ./configure --with-gnutls --enable-tests --enable-shared + +Note: --disable-documentation disables the building of doxygen and man page +files. If you want to only disable one of them, use --disable-doxygen or +--disable-manpages. Doxygen requires the program doxygen and man pages require +the program a2x to build the appropriate files. + +If you need to rebuild the libcoap-*.{map,sym} files to update any exposed +function changes, run + + make update-map-file + +prior to running 'make'. + +LwIP +==== + + ./autogen.sh + ./configure --disable-tests --disable-documentation --disable-examples --disable-dtls + cd examples/lwip + make + +Executable is ./server. See examples/lwip/README for further information + +Contiki +======= + + ./autogen.sh + ./configure --disable-tests --disable-documentation --disable-examples --disable-dtls + cd examples/contiki + make + +Executable is ./server.minimal-net. See examples/contiki/README for further +information + +Windows +======= + +Install OpenSSL (minimum version 1.1.0) including the development libraries if +not already installed. + +Within Visual Studio, "Clone or check out code" using the repository +https://github.com/obgm/libcoap.git + +You may need to update the SDK version of the libcoap Windows Project files to +match that of the SDK version of the Visual Studio you are using. In Solution +Explorer with the view set to libcoap.sln, right click "Solution 'libcoap'" +and then "Retarget solution". + +You may need to edit win32\libcoap.props to update the OpenSSLRootDir and +OpenSSLRootDirDbg variables to point to the top level directory where OpenSSL +is installed so that the include, lib etc. directories are correctly set up. +Note: Make sure that you include a trailing \ in the variable definitions. + +Alternatively you can build everything in Visual Studio with CMake. diff --git a/examples/espidf-coap-server/components/libcoap/CMakeLists.txt b/examples/espidf-coap-server/components/libcoap/CMakeLists.txt new file mode 100644 index 000000000..606e1dd63 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/CMakeLists.txt @@ -0,0 +1,723 @@ +# CMakeLists.txt for libcoap +# +# Copyright (C) 2020 Carlos Gomes Martinho +# Copyright (C) 2020-2022 Jon Shallow +# +# SPDX-License-Identifier: BSD-2-Clause +# +# This file is part of the CoAP library libcoap. Please see README for terms +# of use. + +cmake_minimum_required(VERSION 3.10) + +project( + libcoap + VERSION 4.3.1 + LANGUAGES CXX C) + +set(LIBCOAP_API_VERSION 3) +set(COAP_LIBRARY_NAME "coap-${LIBCOAP_API_VERSION}") + +option( + BUILD_SHARED_LIBS + "Build shared libs" + OFF) + +add_library(${COAP_LIBRARY_NAME}) + +# +# options to tweak the library +# + +option( + ENABLE_DTLS + "Enable building with DTLS support" + ON) +set(DTLS_BACKEND + "default" + CACHE + STRING + "\ +Name of the dtls backend, only relevant if `ENABLE_DTLS` is ON which is default. \ +Possible values: default, gnutls, openssl, tinydtls and mbedtls. \ +If specified then this library will be searched and if found also used. \ +If not found then the cmake configuration will stop with an error. \ +If not specified, then cmake will try to use the first one found in the following order: \ +gnutls, openssl, tinydtls, mbedtls \ + ") +set_property( + CACHE DTLS_BACKEND + PROPERTY STRINGS + default + openssl + gnutls + tinydtls + mbedtls) +option( + USE_VENDORED_TINYDTLS + "compile with the tinydtls project in the submodule if on, otherwise try to find the compiled lib with find_package" + ON) +option( + ENABLE_CLIENT_MODE + "compile with support for client mode code" + ON) +option( + ENABLE_SERVER_MODE + "compile with support for server mode code" + ON) +option( + WITH_EPOLL + "compile with epoll support" + ON) +option( + ENABLE_SMALL_STACK + "Define if the system has small stack size" + OFF) +option( + ENABLE_TCP + "Enable building with TCP support" + ON) +option( + ENABLE_TESTS + "build also tests" + OFF) +option( + ENABLE_EXAMPLES + "build also examples" + ON) +option( + ENABLE_DOCS + "build also doxygen documentation" + ON) + +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 11) +endif() + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug) +endif() + +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +endif() + +if(APPLE) + add_definitions(-D__APPLE_USE_RFC_3542=1) +endif() + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_BINARY_DIR}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + +include(CheckCSourceCompiles) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckSymbolExists) +include(CheckTypeSize) +include(TestBigEndian) + +# check for headers +check_include_file(byteswap.h HAVE_BYTESWAP_H) +check_include_file(inttypes.h HAVE_INTTYPES_H) +check_include_file(limits.h HAVE_LIMITS_H) +check_include_file(memory.h HAVE_MEMORY_H) +check_include_file(strings.h HAVE_STRINGS_H) +check_include_file(string.h HAVE_STRING_H) +check_include_file(sys/sysctl.h HAVE_SYS_SYSCTL_H) +check_include_file(net/if.h HAVE_NET_IF_H) +check_include_file(netinet/in.h HAVE_NETINET_IN_H) +check_include_file(sys/epoll.h HAVE_EPOLL_H) +check_include_file(sys/timerfd.h HAVE_TIMERFD_H) +check_include_file(arpa/inet.h HAVE_ARPA_INET_H) +check_include_file(stdbool.h HAVE_STDBOOL_H) +check_include_file(netdb.h HAVE_NETDB_H) +check_include_file(pthread.h HAVE_PTHREAD_H) +check_include_file(stdlib.h HAVE_STDINT_H) +check_include_file(stdint.h HAVE_STDLIB_H) +check_include_file(syslog.h HAVE_SYSLOG_H) +check_include_file(sys/ioctl.h HAVE_SYS_IOCTL_H) +check_include_file(sys/socket.h HAVE_SYS_SOCKET_H) +check_include_file(sys/stat.h HAVE_SYS_STAT_H) +check_include_file(sys/time.h HAVE_SYS_TIME_H) +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(sys/unistd.h HAVE_SYS_UNISTD_H) +check_include_file(time.h HAVE_TIME_H) +check_include_file(unistd.h HAVE_UNISTD_H) +check_include_file(float.h HAVE_FLOAT_H) +check_include_file(stddef.h HAVE_STDDEF_H) +check_include_file(winsock2.h HAVE_WINSOCK2_H) +check_include_file(ws2tcpip.h HAVE_WS2TCPIP_H) + +# check for functions +check_function_exists(malloc HAVE_MALLOC) +check_function_exists(memset HAVE_MEMSET) +check_function_exists(select HAVE_SELECT) +check_function_exists(socket HAVE_SOCKET) +check_function_exists(strcasecmp HAVE_STRCASECMP) +check_function_exists(pthread_mutex_lock HAVE_PTHREAD_MUTEX_LOCK) +check_function_exists(getaddrinfo HAVE_GETADDRINFO) +check_function_exists(strnlen HAVE_STRNLEN) +check_function_exists(strrchr HAVE_STRRCHR) +check_function_exists(getrandom HAVE_GETRANDOM) +check_function_exists(if_nametoindex HAVE_IF_NAMETOINDEX) + +# check for symbols +if(WIN32) + set(HAVE_STRUCT_CMSGHDR 1) +else() + check_symbol_exists( + CMSG_FIRSTHDR + sys/socket.h + HAVE_STRUCT_CMSGHDR) +endif() + +if(${ENABLE_CLIENT_MODE}) + set(COAP_CLIENT_SUPPORT "1") + message(STATUS "compiling with client support") +else() + message(STATUS "compiling without client support") +endif() + +if(${ENABLE_SERVER_MODE}) + set(COAP_SERVER_SUPPORT "1") + message(STATUS "compiling with server support") +else() + message(STATUS "compiling without server support") +endif() + +if(${WITH_EPOLL} + AND ${HAVE_EPOLL_H} + AND ${HAVE_TIMERFD_H}) + set(COAP_EPOLL_SUPPORT "1") + message(STATUS "compiling with epoll support") +else() + message(STATUS "compiling without epoll support") +endif() + +if(ENABLE_SMALL_STACK) + set(ENABLE_SMALL_STACK "${ENABLE_SMALL_STACK}") + message(STATUS "compiling with small stack support") +endif() + +set(WITH_GNUTLS OFF) +set(WITH_OPENSSL OFF) +set(WITH_TINYDTLS OFF) +set(WITH_MBEDTLS OFF) + +function(compile_tinydtls) + set(TINYDTLS_SOURCES_DIR ${CMAKE_CURRENT_LIST_DIR}/ext/tinydtls) + set(TINYDTLS_SOURCES_GENERATED ${TINYDTLS_SOURCES_DIR}/dtls_config.h) + + message(STATUS "compiling the tinydtls lib") + + include(ExternalProject) + + externalproject_add( + external_tinydtls + SOURCE_DIR "${TINYDTLS_SOURCES_DIR}" + BUILD_IN_SOURCE 1 + DOWNLOAD_COMMAND "" + UPDATE_COMMAND "" + CONFIGURE_COMMAND + ${TINYDTLS_SOURCES_DIR}/configure + --disable-manpages + --prefix=${CMAKE_BINARY_DIR} + BUILD_COMMAND make install + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1) + + externalproject_add_step( + external_tinydtls autoreconf + COMMAND autoreconf --force --install + ALWAYS 1 + WORKING_DIRECTORY "${TINYDTLS_SOURCES_DIR}" + DEPENDERS configure + DEPENDEES download) + + # Let cmake know that it needs to execute the external_tinydtls target to generate those files. + add_custom_command( + OUTPUT ${TINYDTLS_SOURCES_GENERATED} + WORKING_DIRECTORY "${TINYDTLS_SOURCES_DIR}" + COMMAND "make install" + DEPENDS external_tinydtls) + + add_dependencies(${COAP_LIBRARY_NAME} external_tinydtls) + + if(BUILD_SHARED_LIBS) + set(LIBTINYDTLS_PATH "${CMAKE_CURRENT_BINARY_DIR}/lib/libtinydtls.so") + else() + set(LIBTINYDTLS_PATH "${CMAKE_CURRENT_BINARY_DIR}/lib/libtinydtls.a") + endif() + + add_library( + tinydtls + UNKNOWN + IMPORTED) + set_target_properties( + tinydtls + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${CMAKE_CURRENT_BINARY_DIR}/include" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${LIBTINYDTLS_PATH}") + +endfunction() + +if(ENABLE_DTLS) + message(STATUS "compiling with DTLS support") + message(STATUS "DTLS_BACKEND: ${DTLS_BACKEND}") + + if(DTLS_BACKEND + STREQUAL + "default") + # try to find a crypto lib and use it, use the first one found + + # libgnutls (e.g. debian libgnutls28-dev) + find_package(GnuTLS) + if(GnuTLS_FOUND) + set(WITH_GNUTLS ON) + message(STATUS "compiling with gnutls support") + set(HAVE_LIBGNUTLS 1) + else() + # gnutls not found + find_package(OpenSSL) + if(OpenSSL_FOUND) + set(WITH_OPENSSL ON) + message(STATUS "compiling with openssl support") + set(HAVE_OPENSSL 1) + else() + # openssl not found + # libmbedtls (e.g. debian libmbedtls-dev) + find_package(MbedTLS) + if(MbedTLS_FOUND) + set(WITH_MBEDTLS ON) + message(STATUS "compiling with mbedtls support") + set(HAVE_MBEDTLS 1) + else() + # mbedtls not found + if(USE_VENDORED_TINYDTLS) + compile_tinydtls() + else() + find_package(TinyDTLS) + if(TINYDTLS_FOUND) + + else() + # no cryto lib found + message( + FATAL_ERROR + "cannot find any cryto lib, either install one or compile without DTLS support" + ) + endif() + + endif() + + set(WITH_TINYDTLS ON) + message(STATUS "compiling with tinydtls support") + set(HAVE_LIBTINYDTLS 1) + + endif() + + endif() + + endif() + + else() + # DTLS_BACKEND variable is not empty, so set all to false and set the only right to true + set(WITH_GNUTLS OFF) + set(WITH_TINYDTLS OFF) + set(WITH_MBEDTLS OFF) + set(WITH_OPENSSL OFF) + + if(DTLS_BACKEND + STREQUAL + "gnutls") + # libgnutls (e.g. debian libgnutls28-dev) + find_package(GnuTLS REQUIRED) + set(WITH_GNUTLS ON) + message(STATUS "compiling with gnutls support") + set(HAVE_LIBGNUTLS 1) + endif() + + if(DTLS_BACKEND + STREQUAL + "openssl") + # libssl (e.g. debian libssl1.0-dev) + find_package(OpenSSL REQUIRED) + set(WITH_OPENSSL ON) + message(STATUS "compiling with openssl support") + set(HAVE_OPENSSL 1) + endif() + + if(DTLS_BACKEND + STREQUAL + "mbedtls") + # libmbedtls (e.g. debian libmbedtls-dev) + find_package(MbedTLS REQUIRED) + set(WITH_MBEDTLS ON) + message(STATUS "compiling with mbedtls support") + set(HAVE_MBEDTLS 1) + endif() + + if(DTLS_BACKEND + STREQUAL + "tinydtls") + + if(USE_VENDORED_TINYDTLS) + compile_tinydtls() + else(USE_VENDORED_TINYDTLS) + find_package(TinyDTLS REQUIRED) + endif(USE_VENDORED_TINYDTLS) + + message(STATUS "compiling with tinydtls support") + set(WITH_TINYDTLS ON) + set(HAVE_LIBTINYDTLS 1) + + endif() + + endif() + +endif() + +execute_process(COMMAND git describe --tags --dirty --always + RESULT_VARIABLE USING_GIT + OUTPUT_VARIABLE LIBCOAP_PACKAGE_BUILD + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) +if(NOT ${USING_GIT} EQUAL 0) + set(LIBCOAP_PACKAGE_BUILD ${PROJECT_VERSION}) +else() + set(LIBCOAP_PACKAGE_BUILD "${LIBCOAP_PACKAGE_BUILD}") +endif() + +set(PACKAGE_URL "https://libcoap.net/") +set(PACKAGE_NAME "${PROJECT_NAME}") +set(PACKAGE_TARNAME "${PROJECT_NAME}") +set(PACKAGE_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") +set(PACKAGE_VERSION "${PROJECT_VERSION}") +set(PACKAGE_BUGREPORT "libcoap-developers@lists.sourceforge.net") +set(LIBCOAP_PACKAGE_VERSION "${PACKAGE_VERSION}") +set(LIBCOAP_PACKAGE_URL "${PACKAGE_URL}") +set(LIBCOAP_PACKAGE_NAME "${PACKAGE_NAME}") +set(LIBCOAP_PACKAGE_STRING "${PACKAGE_STRING}") +set(LIBCOAP_PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}") + +message(STATUS "PACKAGE VERSION..................${PACKAGE_VERSION}") +message(STATUS "PACKAGE BUILD....................${LIBCOAP_PACKAGE_BUILD}") +message(STATUS "ENABLE_DTLS:.....................${ENABLE_DTLS}") +message(STATUS "ENABLE_TCP:......................${ENABLE_TCP}") +message(STATUS "ENABLE_CLIENT_MODE:..............${ENABLE_CLIENT_MODE}") +message(STATUS "ENABLE_SERVER_MODE:..............${ENABLE_SERVER_MODE}") +message(STATUS "ENABLE_DOCS:.....................${ENABLE_DOCS}") +message(STATUS "ENABLE_EXAMPLES:.................${ENABLE_EXAMPLES}") +message(STATUS "DTLS_BACKEND:....................${DTLS_BACKEND}") +message(STATUS "WITH_GNUTLS:.....................${WITH_GNUTLS}") +message(STATUS "WITH_TINYDTLS:...................${WITH_TINYDTLS}") +message(STATUS "WITH_OPENSSL:....................${WITH_OPENSSL}") +message(STATUS "WITH_MBEDTLS:....................${WITH_MBEDTLS}") +message(STATUS "HAVE_LIBTINYDTLS:................${HAVE_LIBTINYDTLS}") +message(STATUS "HAVE_LIBGNUTLS:..................${HAVE_LIBGNUTLS}") +message(STATUS "HAVE_OPENSSL:....................${HAVE_OPENSSL}") +message(STATUS "HAVE_MBEDTLS:....................${HAVE_MBEDTLS}") +message(STATUS "WITH_EPOLL:......................${WITH_EPOLL}") +message(STATUS "CMAKE_C_COMPILER:................${CMAKE_C_COMPILER}") +message(STATUS "BUILD_SHARED_LIBS:...............${BUILD_SHARED_LIBS}") +message(STATUS "CMAKE_BUILD_TYPE:................${CMAKE_BUILD_TYPE}") +message(STATUS "CMAKE_SYSTEM_PROCESSOR:..........${CMAKE_SYSTEM_PROCESSOR}") + +set(top_srcdir "${CMAKE_CURRENT_LIST_DIR}") +set(top_builddir "${CMAKE_CURRENT_BINARY_DIR}") +if(ENABLE_TCP) + set(COAP_DISABLE_TCP 0) +else(ENABLE_TCP) + set(COAP_DISABLE_TCP 1) +endif(ENABLE_TCP) + +# creates config header file in build directory +configure_file(${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap.h.in + ${CMAKE_CURRENT_BINARY_DIR}/include/coap${LIBCOAP_API_VERSION}/coap.h) + +configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake_coap_config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/coap_config.h) + +configure_file(${CMAKE_CURRENT_LIST_DIR}/tests/test_common.h.in + ${CMAKE_CURRENT_LIST_DIR}/tests/test_common.h) + +# +# sources +# + +target_sources( + ${COAP_LIBRARY_NAME} + PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/coap_address.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_asn1.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_async.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_cache.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_debug.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_event.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_hashkey.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_io.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_notls.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_option.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_prng.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_session.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_subscribe.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_tcp.c + ${CMAKE_CURRENT_LIST_DIR}/src/coap_time.c + ${CMAKE_CURRENT_LIST_DIR}/src/block.c + ${CMAKE_CURRENT_LIST_DIR}/src/encode.c + ${CMAKE_CURRENT_LIST_DIR}/src/mem.c + ${CMAKE_CURRENT_LIST_DIR}/src/net.c + ${CMAKE_CURRENT_LIST_DIR}/src/pdu.c + ${CMAKE_CURRENT_LIST_DIR}/src/resource.c + ${CMAKE_CURRENT_LIST_DIR}/src/str.c + ${CMAKE_CURRENT_LIST_DIR}/src/uri.c + # no need to parse those files if we do not need them + $<$:${CMAKE_CURRENT_LIST_DIR}/src/coap_openssl.c> + $<$:${CMAKE_CURRENT_LIST_DIR}/src/coap_tinydtls.c> + $<$:${CMAKE_CURRENT_LIST_DIR}/src/coap_gnutls.c> + $<$:${CMAKE_CURRENT_LIST_DIR}/src/coap_mbedtls.c> + # headers + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_address.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_async.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_cache.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_debug.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_dtls.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_event.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_hashkey.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_io.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_option.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_prng.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_session.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_subscribe.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/coap_time.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/block.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/encode.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/libcoap.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/lwippools.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/mem.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/net.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/pdu.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/resource.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/str.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/uri.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/uthash.h + ${CMAKE_CURRENT_LIST_DIR}/include/coap${LIBCOAP_API_VERSION}/utlist.h) +target_include_directories( + ${COAP_LIBRARY_NAME} + PUBLIC # config headers are generated during configuration time + $ + $ + $ + $ + $<$,$>:${CMAKE_BINARY_DIR}/include/tinydtls> + $<$:${GNUTLS_INCLUDE_DIR}> + $<$:${MBEDTLS_INCLUDE_DIRS}>) +target_link_libraries( + ${COAP_LIBRARY_NAME} + PUBLIC $<$:OpenSSL::SSL> + $<$:OpenSSL::Crypto> + $<$:${GNUTLS_LIBRARIES}> + $<$:tinydtls> + $<$:${MBEDTLS_LIBRARY}> + $<$:${MBEDX509_LIBRARY}> + $<$:${MBEDCRYPTO_LIBRARY}>) + +target_compile_options( + ${COAP_LIBRARY_NAME} + PUBLIC -DLIBCOAP_PACKAGE_BUILD="${LIBCOAP_PACKAGE_BUILD}") + +add_library( + ${PROJECT_NAME}::${COAP_LIBRARY_NAME} + ALIAS + ${COAP_LIBRARY_NAME}) + +# +# compiler options +# + +add_compile_options( + $<$,$>:-pedantic> + $<$,$>:-Wall> + $<$,$>:-Wcast-qual> + $<$,$>:-Wextra> + $<$,$>:-Wformat-security> + $<$,$>:-Winline> + $<$,$>:-Wmissing-declarations> + $<$,$>:-Wmissing-prototypes> + $<$,$>:-Wnested-externs> + $<$,$>:-Wpointer-arith> + $<$,$>:-Wshadow> + $<$,$>:-Wstrict-prototypes> + $<$,$>:-Wswitch-default> + $<$,$>:-Wswitch-enum> + $<$,$>:-Wunused> + $<$,$>:-Wwrite-strings>) + +# +# tests +# + +if(ENABLE_TESTS) + add_executable( + testdriver + ${CMAKE_CURRENT_LIST_DIR}/tests/testdriver.c + ${CMAKE_CURRENT_LIST_DIR}/tests/test_common.h + ${CMAKE_CURRENT_LIST_DIR}/tests/test_encode.c + ${CMAKE_CURRENT_LIST_DIR}/tests/test_encode.h + ${CMAKE_CURRENT_LIST_DIR}/tests/test_error_response.c + ${CMAKE_CURRENT_LIST_DIR}/tests/test_error_response.h + ${CMAKE_CURRENT_LIST_DIR}/tests/test_options.c + ${CMAKE_CURRENT_LIST_DIR}/tests/test_options.h + ${CMAKE_CURRENT_LIST_DIR}/tests/test_pdu.c + ${CMAKE_CURRENT_LIST_DIR}/tests/test_pdu.h + ${CMAKE_CURRENT_LIST_DIR}/tests/test_sendqueue.c + ${CMAKE_CURRENT_LIST_DIR}/tests/test_sendqueue.h + ${CMAKE_CURRENT_LIST_DIR}/tests/test_session.c + ${CMAKE_CURRENT_LIST_DIR}/tests/test_session.h + ${CMAKE_CURRENT_LIST_DIR}/tests/test_tls.c + ${CMAKE_CURRENT_LIST_DIR}/tests/test_tls.h + ${CMAKE_CURRENT_LIST_DIR}/tests/test_uri.c + ${CMAKE_CURRENT_LIST_DIR}/tests/test_uri.h + ${CMAKE_CURRENT_LIST_DIR}/tests/test_wellknown.c + ${CMAKE_CURRENT_LIST_DIR}/tests/test_wellknown.h) + # tests require libcunit (e.g. debian libcunit1-dev) + target_link_libraries(testdriver PUBLIC ${PROJECT_NAME}::${COAP_LIBRARY_NAME} + -lcunit) +endif() + +# +# examples +# + +if(ENABLE_EXAMPLES) + add_executable(coap-client ${CMAKE_CURRENT_LIST_DIR}/examples/coap-client.c) + target_link_libraries(coap-client + PUBLIC ${PROJECT_NAME}::${COAP_LIBRARY_NAME}) + + add_executable(coap-rd ${CMAKE_CURRENT_LIST_DIR}/examples/coap-rd.c) + target_include_directories(coap-rd + PRIVATE + $) + target_link_libraries(coap-rd PUBLIC ${PROJECT_NAME}::${COAP_LIBRARY_NAME}) + + add_executable(coap-server ${CMAKE_CURRENT_LIST_DIR}/examples/coap-server.c) + target_link_libraries(coap-server + PUBLIC ${PROJECT_NAME}::${COAP_LIBRARY_NAME}) + + if(NOT WIN32) + add_executable(etsi_iot_01 ${CMAKE_CURRENT_LIST_DIR}/examples/etsi_iot_01.c) + target_link_libraries(etsi_iot_01 + PUBLIC ${PROJECT_NAME}::${COAP_LIBRARY_NAME}) + + add_executable(tiny ${CMAKE_CURRENT_LIST_DIR}/examples/tiny.c) + target_link_libraries(tiny PUBLIC ${PROJECT_NAME}::${COAP_LIBRARY_NAME}) + endif() +endif() + +# +# docs +# + +if(ENABLE_DOCS) + find_package(Doxygen) + + if(Doxygen_FOUND) + # set input and output files + set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in) + set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + + # Make necessary temporary directories + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/doc/man_tmp) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/doc/man_html) + + # request to configure the file + configure_file( + ${DOXYGEN_IN} + ${DOXYGEN_OUT} + @ONLY) + + # note the option ALL which allows to build the docs together with the + # application + add_custom_target( + doc_doxygen ALL + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" + VERBATIM) + + message(STATUS "Setup up the Doxygen documention build") + + else(Doxygen_FOUND) + message( + WARNING + "Doxygen need to be installed to generate the doxygen documentation") + endif(Doxygen_FOUND) + +endif() + +# +# install +# + +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +set(LIBCOAP_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) +install( + TARGETS ${COAP_LIBRARY_NAME} + EXPORT ${PROJECT_NAME}Targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib) + +install( + EXPORT ${PROJECT_NAME}Targets + DESTINATION ${LIBCOAP_CONFIG_INSTALL_DIR} + NAMESPACE ${PROJECT_NAME}:: + COMPONENT dev) + +configure_package_config_file( + cmake/Config.cmake.in + ${PROJECT_NAME}Config.cmake + INSTALL_DESTINATION + ${LIBCOAP_CONFIG_INSTALL_DIR}) +write_basic_package_version_file( + ${PROJECT_NAME}ConfigVersion.cmake + COMPATIBILITY SameMajorVersion) +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + DESTINATION ${LIBCOAP_CONFIG_INSTALL_DIR} + COMPONENT dev) + +install( + DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + COMPONENT dev + FILES_MATCHING + PATTERN "*.h" + PATTERN "coap.h" EXCLUDE + PATTERN "coap_riot.h" EXCLUDE + PATTERN "lwippools.h" EXCLUDE + PATTERN "utlist.h" EXCLUDE + PATTERN "uthash.h" EXCLUDE + PATTERN "*_internal.h" EXCLUDE) +install( + DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + COMPONENT dev + FILES_MATCHING + PATTERN "*.h") +if(ENABLE_EXAMPLES) + install( + TARGETS coap-server coap-client coap-rd + DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT dev) + if(NOT WIN32) + install( + TARGETS etsi_iot_01 tiny + DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT dev) + endif() +endif() diff --git a/examples/espidf-coap-server/components/libcoap/CONTRIBUTE b/examples/espidf-coap-server/components/libcoap/CONTRIBUTE new file mode 100644 index 000000000..d7319e9be --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/CONTRIBUTE @@ -0,0 +1,218 @@ + ####################################################### + # Developer information for contributing to libcoap # + ####################################################### + +1. The basics +~~~~~~~~~~~~~ +The libcoap project is a FOSS project that is dual licensed. The maintainer +for the libcoap is Olaf Bergmann . +Any contributions have to be made under the terms of the +license + + * BSD 2-Clause (The BSD 2-Clause License) + +Contributions made up to 2017-06-01 have been made under the dual +license model BSD 2-Clause and GPL v2+ (The GNU General Public License +2.0 or later). + +The used VCS for libcoap is Git, the main repository is living on GitHub. +You can clone (or fork directly on GitHub) on the repository site: + + https://github.com/obgm/libcoap + +Please refer also to the libcoap website for additional information + + https://libcoap.net/ + +The build environment is grounded on the classical autotools, the GNU GCC and +the LLVM C-compiler (CLang) are supported. The Windows systems are not +currently supported (until someone is creating support for it). + +Doxygen is used for creating a HTML based online documentation of the +libcoap library. + +2. Communications +~~~~~~~~~~~~~~~~~ +The main discussion and development platform for libcoap is the mailing list +on Sourceforge. +No matter if you just have a simple question, some specific problem or +want to discuss some patches, please write it to the mailing list. Please +avoid personal mailings to the maintainer (or some other contributor) if +your questions will probably be in the interest of other users too. +You can subscribe to the list here: + + https://lists.sourceforge.net/lists/listinfo/libcoap-developers + +The archive of the list can be found on: + + https://sourceforge.net/p/libcoap/mailman/libcoap-developers + +3. Starting contributing +~~~~~~~~~~~~~~~~~~~~~~~~ +As written above libcoap is maintained with the Git tools so you should be +familiar with the various git commands. +The libcoap project is using just two main branches, the 'main' branch is +holding the point releases, all the development process is going on in the +'develop' branch. +To start any contributing you first have to clone the git tree from the main +repository on GitHub: + + git clone https://github.com/obgm/libcoap.git + +4. Working on the source +~~~~~~~~~~~~~~~~~~~~~~~~ +As one golden rule you should work on improvements within *your* own local +development branch! To do so you have to first checkout the 'develop' branch +as local branch and then start on top on this branch your own branch. So +create (or better say checkout) the local 'develop' branch: + + cd libcoap + git checkout develop origin/develop + +Now you can simply start your own local branch (for example 'my-develop') +with the 'origin/develop' as parent so you can later create the patches +against the the upstream development branch: + + git checkout -b my-develop + +At this point you can now work as known with git, modify the source, commit +the changes, amend if needed and test your work. +At some point you will have to generate patches to post them on the mailing +list (and/or push your changes into your public Git tree). It's a good idea to +post your patch series on the mailing list so other contributors will see your +work and give further suggestions or discuss your work. + +To be able to send a patch series you will now create the series itself as +single patches, this will be going easy with the 'git format-patch' command +against the 'develop' branch, remind this is the upstream main development +branch. +To not mix up your series with probably unrelated patches let git place the +patches within a defined directory. Also, while create the patches, tell git to +create a cover letter patch so you can append some introducing words that will +hold probably explanations why you create the patches in the way you have done. + + git format-patch --cover-letter -o ../patches4libcoap + +This command will create a patch series in ../patches4libcoap where you find a +patch named '0000-cover-letter.patch'. Please modify this patch with some +useful information's for the mailing list. After finish this you now can send +your patches to libcoap-developers@lists.sourceforge.net + + git send-email ../patches4libcoap/* --to=libcoap-developers@lists.sourceforge.net + +5. Coding rules +~~~~~~~~~~~~~~~ +As every FOSS project the libcoap project needs also some rules for coding. +There are loss but the main of them are important! + +5.1 License and Copyright +------------------------- +Every new file must contain a license and the copyright holder(s). Please +take a look into existing files and adopt the needed changes to your new +file(s). + +5.2 Source Code Indentation +--------------------------- +* For better reading the indentation is set to 2 characters as spaces, this + is depended on the often used nested functions like 'if-else'. Don't use + TABs any there! Avoid trailing white spaces at the end of a line. + It's appropriate to set up a modline like this one at first line within + the source file: + +--8<---- +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +--->8-- + +* Single lines within the source code should not be longer then 78 + characters. + +* If there a functions with a lot of parameters that do not fit into the above + rule split the declaration (in the *.h) and the implementation (in the *.c) + into single lines per parameter. For example like this (from src/block.c): + +--8<---- +int +coap_add_block(coap_pdu_t *pdu, + unsigned int len, + const unsigned char *data, + unsigned int block_num, + unsigned char block_szx); +--->8-- + +5.3 Source Code Documentation +----------------------------- +* A useful source code documentation is mandatory. Mostly to be done within the + source code files, but more complex description should be done in extra + README files. + +* Please set up/adjust the doxygen documentation if you create new functions or + change existing functions. The doxygen documentation has to be done in the + header files as they are the public part of the libcoap and only use the + @-syntax for doxygen commands (akin to javadoc). + +5.4 API Changes +--------------- +* Never break the API! + Don't remove old functions and if there some changes are needed in some kind + always provide a wrapper for the old call to let the library be backward + compatible and mark the old function as @deprecated in the doxygen comment. + Please discuss needed changes on the mailing list. + +5.5 Patches and Commits +----------------------- +* Git commits must be atomic and contain a declarative subject line (max 50 + characters if possible) and a body for a statement if needed. + Use the possibility to write a good explanation why your patch/commit is + handle the changes in the way you have done. Remind that other user can + read your code but not necessary understand why the code is written this + way. Don't use something to generic like "bugfix commit". + +* A patch/commit or a series of patches/commits have to ensure that the + whole project is able to build up every thing, in short: Do not break + any make target and test your work. + +* Every patch/commit should handle one single logical change. If more than + one patch/commit is needed for a change explain it, respect the point + above. If your subject line become much larger than 50 characters then + typically your patch is to big for one single commit. + +* Commit message should begin with a submodule or unit the commit is for. By + this your commit message helps to find thematic other changes. If you have + to search and find something with 'git log | grep [foo]' you will see why + this is useful. Examples: + + rd.c: Fixed type-specifier warning + Makefile.am: Added missing src/address.c + address.[hc]: make coap_address_equals() not inline on POSIX + +6. Where to start contributing? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +There are various things you could starting on to contribute, the best +is you simply pick up an issue you blindly see and just improve the +situation. Please take also a look into the file TODO and choose a point +from there or point the maintainer to add other things here too. + +* Documentation +We are always lacking on a better documentation on the source code, so +maybe you can improve the doxygen documentation. +Also a good documentation on the usage of the libcoap and the example +binaries is always improvable. So we appreciate any help on this. + +* Manual Pages +The source is providing some example binaries which originally just should show +how the libcoap can be used. Right now these binaries are fully usable and +quite more than simple examples on a system. There are man pages for these +binaries available, if you found there is a improvement needed please do so and +write to the mailing list explained in section 2. +Maybe you can write up some good HowTo's on the usage for these binaries. + +* HowTo's +The libcoap library has now a lot of functions you can use. +Unfortunately there is no good user guide on how to use the libcoap in +any external project. This means there is no HowTo or CheatSheet for a +programming person available. You want to write up something? + +* Missing functionality +There are some features that are still missing inside the libcoap. For +example some DTLS implementations and proxy functionality. + diff --git a/examples/espidf-coap-server/components/libcoap/COPYING b/examples/espidf-coap-server/components/libcoap/COPYING new file mode 100644 index 000000000..c64ad639a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/COPYING @@ -0,0 +1,6 @@ +libcoap is published as open-source software without any warranty of any kind. + +Use is permitted under the terms of the simplified BSD 2-Clause license. +It includes public domain software. libcoap binaries may also +include open-source software with their respective licensing terms. +Please refer to LICENSE for further details. diff --git a/examples/espidf-coap-server/components/libcoap/ChangeLog b/examples/espidf-coap-server/components/libcoap/ChangeLog new file mode 100644 index 000000000..5ae73a517 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ChangeLog @@ -0,0 +1,332 @@ +2022-08-17 Olaf Bergmann + + Change summary for version 4.3.1: + + * Support for Server only and Client only libcoap builds. + * Add support for repeating requests in coap-client. + * Add in support for defining resources that support multicast. + * Add in more support for async delayed requests. + * Add in support for not closing down Observe when closing session. + * Support for RFC7390, RFC8516 and RFC9175. + * Warn when Tokens are re-used. + * Warn when Options are repeated that are not defined as being + repeatable. + * Support for TLS when using Mbed TLS library. + * support for Mbed TLS 3.1 + * Add in BERT support for block handling. + * More rigorous error handling for Block transfers. + * Support for using external or submodule TinyDTLS. + * Cmake - add in Apple build support. + * Source files renamed to be more consistent in naming. + * Update native Windows VC builds to use libcoap-3 instead of libcoap-2. + * Reported bugs fixed. + * Example applications Help report include build version. + * Documentation added and updated (Doxygen and man). + +2021-05-04 Olaf Bergmann + + Change summary for version 4.3.0: + + * Include directory updated from include/coap2 to include/coap3 as + this is a major version change. + * Other code references updated from coap2 to coap3. + * Examples now have the underlying (D)TLS library name as a suffix. + E.g. coap-server-openssl + * Examples and libraries can be installed with default names using + ./configure --enable-add-default-names + * Many call-back handlers have had their parameter lists changed, some + variables are made const and other ones removed as they can be easily + reconstructed if needed. + * Some functions have their parameters changed to const. + * Internal structures made opaque to applications, requiring the + applications to access the structure information via a new set of + functions. The new functions are of the form coap_X_get_Y() or + coap_X_set_Y() where X is the structure (e.g. session) and Y is + the variable. + * coap_async_state_t + * coap_attr_t + * coap_context_t + * coap_packet_t + * coap_pdu_t + * coap_resource_t + * coap_session_t + * coap_socket_t + * Header files are moved into libcoap space and so are accessed by coap + sub-directory - e.g. #include . + * RFC7959 (Block handling) moved into libcoap from application code + considerably simplifying application code. See coap_block(3) man page. + * CoAP Cache Key support. + * Support for cmake builds. + * Support for RIOT builds. + * Support for Cygwin builds. + * Proxy support for coap-server, enhanced coap-client capabilities + * Updated async support. + * Multicast requests now randomly delayed befor ethe response is + sent. + * Additional RFC support - RFC8768. + * Mbed TLS DTLS library support. + * (D)TLS support for RPK and PKCS11. + * Additional (D)TLS support for PSK (e.g. Identity Hints). + * PKI support consistent across all supported (D)TLS libraries. + * Support for disabling TCP for code reduction. + * More rigorous checking and appropriate rejection of inbound PDU + options. + * Additional unit tests. + * Reported bugs fixed. + * Example applications help reports on (D)TLS library capabilities + and versions. + * Documentation added and updated (Doxygen and man). + +2019-11-05 Olaf Bergmann + + Change summary for version 4.2.1: + + * Builds now support silent rules + * Support building with TinyDTLS as a shared library + * Added in EPOLL support + * Added in support for constrained stacks + * Server sessions hashed for performance lookup + * coap_endpoint_t and coap_subscription_t made opaque to applications + * Documentation updated + +2019-02-11 Olaf Bergmann + + Change summary for version 4.2.0: + + * DTLS support improvements (OpenSSL, GnuTLS, tinydtls) + * Pre-shared keys, X.509 certificates + * new session abstraction + * TCP and TLS support + * improved documentation; manual pages + * changes in internal PDU structure + * improved examples (DTLS usage, block-wise transfer) + * docker images for continuous integration + * support for Google OSS fuzzer + * MS Visual Studio project for Windows builds + +2017-07-10 Olaf Bergmann + + * DTLS support (OpenSSL, tinyDTLS) by Jean-Claude Michelou + * Win32 support by Jean-Claude Michelou + * New Session API by Jean-Claude Michelou + +2016-02-16 Olaf Bergmann + + * Fixed build for Contiki3 and LwIP + * .travis.yml: Enabled continuous integration for platforms + POSIX and Contiki + +2015-03-11 Olaf Bergmann + + * include/coap/resource.h: Replaced custom list structures by + utlist macros. + +2015-03-09 Olaf Bergmann + + * src/uri.c (coap_split_path): Fixed URI parser bug and + removed broken parse iterator. + +2015-03-05 Olaf Bergmann + + * src/coap_time.c (coap_ticks): Changed POSIX implementation + to fixed point arithmetic and removed clock_offset. + +2015-02-21 Olaf Bergmann + + * net.c (coap_send_confirmed): Use fixed point arithmetic + to calculate retransmission timeout. + +2015-02-20 Olaf Bergmann + + * coap_list.[hc]: Moved old list implementation into + sub-directory examples and replaced by linked lists + from utlist.h. As a result, the list must be sorted + explicitly with LL_SORT). + +2015-02-19 Olaf Bergmann + + * net.c (coap_send_confirmed): Fixed retransmission timeout + calculation and renamed transmission parameters according to + Section 4.8 of RFC 7252. + +2015-02-17 Olaf Bergmann + + * major rework to get Contiki and lwip running + * many fixed bugs and warnings + +2014-06-18 Olaf Bergmann + + * mem.c (coap_malloc_type): New functions for allocating memory. + On POSIX systems, coap_malloc_type() and coap_free_type() are just + wrapper functions for malloc() and free(), while on Contiki and + LWIP distinct arrays are used for each type. + +2014-03-09 Olaf Bergmann + + * net.c (coap_cancel): Removed 7.31 again and implemented new + method for cancelling observe relationships. + +2014-02-25 Olaf Bergmann + + * net.c (coap_cancel): Handling of 7.31 responses to cancel + notifications (see Section 4.6 of draft-ietf-core-observe-12) + +2014-02-04 Olaf Bergmann + + * resource.c (coap_print_link): This function now takes an offset + where printing starts. This is used for generating blocks on the + fly. + + * net.c (wellknown_response): Added support for Block2 options + when generating a response for .well-known/core. + + * block.h (coap_opt_block_num): Fixed handling of zero-length + options. COAP_OPT_BLOCK_LAST now returns NULL when the option + value's length is zero. + +2014-01-07 Olaf Bergmann + + * resource.c (coap_print_link): Output partial resource + descriptions. The function now provides a sliding window over the + textual representation of the resource. Output starts at the given + offset and ends at the buffer's upper bound. The meaning of the + return value has changed to allow distinguishing whether or not + the resource description has been truncated at the buffer's upper + bound. + (print_wellknown): Support for the new coap_print_link(). An + additional parameter now is used to provide the offset into the + resource description. The meaning of the return value has been + adjusted accordingly. + +2013-12-23 Olaf Bergmann + + * configure.in: merged with LWIP port from chrysn + . This + introduces new compiler flags WITH_POSIX and WITH_LWIP to + distinguish target platforms. + +2013-09-03 Olaf Bergmann + + * option.h (coap_option_setb): increased size of option type + argument + + * tests/test_error_response.c (t_init_error_response_tests): new + tests for error response generation + + * tests/test_pdu.c (t_encode_pdu5): fixed number for option Accept + + * net.c (coap_new_error_response): fixed option size calculation + +2013-07-04 Olaf Bergmann + + * net.c (coap_new_context): register critical Accept option + + * pdu.c: option codes for Accept and Size1 according to coap-18 + +2013-02-01 Olaf Bergmann + + * coap_time.h (coap_clock_init_impl): fix invalid preprocessor + directive. #warning is now only used for gcc only (close sf bug #15) + + * net.c (wellknown_response): applied patch from chrysn to + fix bug in generation of .well-known/core representation + +2013-01-21 Olaf Bergmann + + * option.h: renamed option field in coap_opt_iterator_t to + next_option to detect erroneous use in old code + +2013-01-18 Olaf Bergmann + + * configure.in: new option --with-tests to enable unit tests + + * tests/testdriver.c: unit tests for parser functions + + * pdu.c (coap_pdu_parse): new PDU parser for Klaus-encoding + according to coap-13 + + * net.c (coap_read): call coap_pdu_parse() to check PDU integrity + + * option.c: Klaus-encoding for coap-13, including new option + iterator interface + +2012-11-20 Olaf Bergmann + + * net.c (next_option_safe): made option parsing more robust in + presence of option jumps + + * pdu.h: new option codes from draft-ietf-core-coap-12 + + * option.c (coap_opt_setlength): new function to set option length + + * uri.c (make_decoded_option): use coap_opt_setlength() instead of + obsolete macro COAP_OPT_SETLENGTH. + +2012-11-19 Olaf Bergmann + + * uri.c (make_decoded_option): use coap_opt_encode() instead of writing + +2012-11-03 Olaf Bergmann + + * net.c (coap_read): read new option encoding + +2012-11-01 Olaf Bergmann + + * option.c (coap_opt_size, coap_opt_value, coap_opt_length): + several functions to access fields of options (possibly preceeded + by option jump) + +2012-10-25 Olaf Bergmann + + * option.c (coap_opt_encode): new function for option encoding + with option jumps + +2012-03-23 Olaf Bergmann + + * examples/client.c (clear_obs): clear observation relationship after + user-specified duration + +2012-03-21 Olaf Bergmann + + * resource.c (print_wellknown): filtering by attributes + +2012-03-19 Olaf Bergmann + + * pdu.c (coap_add_option): allow more than 15 options. + +2012-03-15 Olaf Bergmann + + * examples/client.c (cmdline_uri): split path and query here to + make it easier to include these options in subsequent requests for + block transfer. + +2012-03-14 Olaf Bergmann + + * examples/etsi_iot_01.c: Support for POST, PUT, DELETE on /test + +2012-03-13 Olaf Bergmann + + * encode.c (coap_encode_var_bytes): more efficient coding for 0 + +2012-03-11 Olaf Bergmann + + * examples/etsi_iot_01.c: Test cases for 1st ETSI CoAP Plugtest, + March 24/25, 2012 in Paris, France. + +2012-03-10 Olaf Bergmann + + * block.c: support for block transfer. + +2012-03-07 Olaf Bergmann + + * examples/client.c (usage): new command line options + -B to set timeout after which the main loop is left. + -e to specify a payload (incompatible with -f) + (message_handler): bugfixes + + * resource.h: (coap_method_handler_t): new API for method handlers. + + +Copyright 2012 Olaf Bergmann, TZI +Copying and distribution of this file, with or without modification, are +permitted provided the copyright notice and this notice are preserved. diff --git a/examples/espidf-coap-server/components/libcoap/Dockerfile b/examples/espidf-coap-server/components/libcoap/Dockerfile new file mode 100644 index 000000000..41b7fc8a1 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/Dockerfile @@ -0,0 +1,7 @@ +FROM obgm/libcoap:build-env + +ENV libcoap_dir=/libcoap +ADD . $libcoap_dir +WORKDIR $libcoap_dir + +RUN ./autogen.sh --clean && ./autogen.sh diff --git a/examples/espidf-coap-server/components/libcoap/HOWTO.dual.gnutls b/examples/espidf-coap-server/components/libcoap/HOWTO.dual.gnutls new file mode 100644 index 000000000..e2fc0e19d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/HOWTO.dual.gnutls @@ -0,0 +1,98 @@ +############################################################################ +# +# GnuTLS dual versions +# +# Works with CentOS 7 +# +############################################################################ +# +# Add in alternative GnuTLS support into /usr/local, and put all the +# libraries into /usr/local/lib. +# +# Need the latest of the following packages +# +# gmp (used 6.2.0) https://gmplib.org/#DOWNLOAD +# nettle (used 3.6) https://ftp.gnu.org/gnu/nettle/ +# gnutls (used 3.6.13) https://www.gnutls.org/download.html +# + +GMP_VER=6.2.0 +NETTLE_VER=3.6 +GNUTLS_VER=3.6.13 + +# +# gmp +# +tar xovf gmp-${GMP_VER}.tar.xz +cd gmp-${GMP_VER} +./configure +make +sudo make install +cd .. + +# +# nettle (by default wants to go into /usr/local/lib64 which gets messy) +# +tar zxovf nettle-${NETTLE_VER}.tar.gz +cd nettle-${NETTLE_VER} +PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --libdir=/usr/local/lib \ + LDFLAGS="-L/usr/local/lib" +make +sudo make install +cd .. + +tar xovf gnutls-${GNUTLS_VER}.tar.xz +cd gnutls-${GNUTLS_VER} +# +# +# You may need to make the following change if you have an old version of +# p11-kit +# +# $ diff -Nau a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c +# --- a/lib/pkcs11_privkey.c 2020-05-26 11:49:27.374385645 +0100 +# +++ b/lib/pkcs11_privkey.c 2020-05-26 11:58:24.300510455 +0100 +# @@ -265,13 +265,13 @@ +# # define CKG_MGF1_SHA384 0x00000003UL +# # define CKG_MGF1_SHA512 0x00000004UL +# +# +#endif +# struct ck_rsa_pkcs_pss_params { +# ck_mechanism_type_t hash_alg; +# /* ck_rsa_pkcs_mgf_type_t is not defined in old versions of p11-kit */ +# unsigned long mgf; +# unsigned long s_len; +# }; +# -#endif +# +# static const struct hash_mappings_st hash_mappings[] = +# { +# +# +PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --with-included-unistring \ + --disable-hardware-acceleration --disable-tests --with-included-libtasn1 \ + --disable-doc LDFLAGS="-L/usr/local/lib" +make +sudo make install +cd .. + +############################################################################ +# +# libcoap build with updated GnuTLS +# +############################################################################ + +# Get the latest libcoap +git clone https://github.com/obgm/libcoap.git + +# Build code +cd libcoap +./autogen.sh +# Update --enable- / --disable- options as appropriate +# libcoap libraries are put into /usr/lib64 for ease of linking +PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --libdir=/usr/lib64 \ + --with-gnutls --enable-tests --enable-examples --disable-doxygen \ + --enable-manpages +make +sudo make install +cd .. + diff --git a/examples/espidf-coap-server/components/libcoap/HOWTO.dual.openssl b/examples/espidf-coap-server/components/libcoap/HOWTO.dual.openssl new file mode 100644 index 000000000..6168c3edd --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/HOWTO.dual.openssl @@ -0,0 +1,50 @@ +############################################################################ +# +# OpenSSL dual versions +# +# Works with CentOS 7 +# +############################################################################ +# +# Add in alternative OpenSSL support into /opt/openssl. /opt/openssl is +# chosen instead of the default of /usr/local so that existing utilities +# continue to use the original version of OpenSSL and so only specific +# applications that requires the newer version of OpenSSL will pick up the +# new code. +# +# Download latest stable version of openssl.X.Y.Z.tar.gz from +# https://www.openssl.org/source/ + +tar zxovf openssl.X.Y.Z.tar.gz +cd openssl.X.Y.X +./config --prefix=/opt/openssl --openssldir=/opt/openssl +make +sudo make install_sw + +# The following should not clash the existing OpenSSL lib*.so.1.0 usage unless +# the previous OpenSSL version is 1.1.0 or later. +# It just makes things for running executables a lot simpler. +sudo cp /opt/openssl/lib/lib*.so.1.1 /lib64 +cd .. + +############################################################################ +# +# libcoap build with updated OpenSSL +# +############################################################################ + +# Get the latest libcoap +git clone https://github.com/obgm/libcoap.git + +# Build code +cd libcoap +./autogen.sh +# Update --enable- / --disable- options as appropriate +# libcoap libraries are put into /usr/lib64 for ease of linking +PKG_CONFIG_PATH=/opt/openssl/lib/pkgconfig ./configure --libdir=/usr/lib64 \ + --with-openssl --enable-tests --enable-examples --disable-doxygen \ + --disable-manpages +make +sudo make install +cd .. + diff --git a/examples/espidf-coap-server/components/libcoap/HOWTO.dual.softhsm2 b/examples/espidf-coap-server/components/libcoap/HOWTO.dual.softhsm2 new file mode 100644 index 000000000..2eee889a1 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/HOWTO.dual.softhsm2 @@ -0,0 +1,90 @@ +############################################################################ +# +# SoftHSMv2 dual versions +# +# Works with CentOS 7 +# +# The opensc package needs to be installed. +# +############################################################################ +# +# Install a software HSM module for doing the PKCS11 testing of libcoap. +# Real hardware can be used if you have the appropriate library module. +# +# It is assumed that the opensc package is installed. +# +# When installing SoftHSMv2 from your system's package manager, check that the +# OpenSSL version is at least 1.1.0. If not, then you will need to dual +# install SoftHSMv2 as below; otherwise you can use the existing SoftHSMv2. +# +# SoftHSMv2 is built using OpenSSL, but GnuTLS can use the PKCS11 interface. +# Note that if the default OpenSSL version is less than 1.1.0, you will need +# to install a dual stack version of OpenSSL as per HOWTO.dual.openssl. +# +# Creates module /usr/local/lib/softhsm/libsofthsm2.so +# + +# Add line below to /etc/security/limits.conf to support memory locking + +* - memlock unlimited + +# Get the latest SoftHSM +git clone https://github.com/opendnssec/SoftHSMv2.git + +# Build code +cd SoftHSMv2/ +sh autogen.sh +PKG_CONFIG_PATH=/opt/openssl/lib/pkgconfig ./configure --enable-silent-rules \ + --with-crypto-backend=openssl --disable-gost LDFLAGS=-L/opt/openssl/lib \ + CPPFLAGS=-I/opt/openssl/include --with-openssl=/opt/openssl +make +# You may need to comment out constexpr lines (fixes for gcc10) in +# src/lib/crypto/PublicKey.h src/lib/crypto/PrivateKey.h if you get +# compile errors. +sudo make install +cd .. + +# Make sure p11-kit softhsm modules have the correct module: fully qualified +# path where the entry is of the form (in particular for GnuTLS) :- +# /usr/share/p11-kit/modules/softhsm* +# +# module: /usr/local/lib/softhsm/libsofthsm2.so + +# The user you are running this as needs to be in the group defined for +# /var/lib/softhsm/tokens/. E.g. +# $ sudo ls -ld /var/lib/softhsm/tokens/ +# drwxrws--- 3 root softhsm 4096 May 3 09:52 /var/lib/softhsm/tokens/ +# which is softhsm in this case (It could be ods). To verify if you are in +# the correct group +# $ id +# To add user to this group +# $ sudo usermod -a -G softhsm +# and log out and back in again. +# + +############################################################################ +# +# libp11 (needed for OpenSSL as it provides the PKCS11 engine) +# +############################################################################ +# +# Install a pkcs11 library for OpenSSL to use as an engine. +# [GnuTLS has this built in] +# + +# Get the latest libp11 +git clone https://github.com/OpenSC/libp11.git + +# Build code +cd libp11 +./bootstrap +PKG_CONFIG_PATH=/opt/openssl/lib/pkgconfig ./configure \ + --with-pkcs11-module=/usr/local/lib/softhsm/libsofthsm2.so +make +sudo make install +cd .. + +# Verify that pkcs11 is available + +/opt/openssl/bin/openssl engine pkcs11 -t + diff --git a/examples/espidf-coap-server/components/libcoap/HOWTO.pkcs11 b/examples/espidf-coap-server/components/libcoap/HOWTO.pkcs11 new file mode 100644 index 000000000..64c01f993 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/HOWTO.pkcs11 @@ -0,0 +1,129 @@ +# +# Using PKCS11 with libcoap. +# +# This HOWTO works for CentOS 7. +# +# As CentOS 7 uses OpenSSL prior to 1.1.0, dual OpenSSL support needs to be +# set up and used for libcoap. See HOWTO.dual.openssl for setting this up. +# +# It also is possible that you want to use GnuTLS - and want to use a later +# version. HOWTO.dual.gnutls for setting this up. +# +# OpenSSL and GnuTLS are currently supported +# + +############################################################################ +# +# Testing examples +# +############################################################################ +# +# Update PKCS11 token with certificates and keys +# +# Assumption is that you already have the following PEM files +# ca-cert.pem - The certificate of the CA that signed Server and Client +# server-cert.pem - Contains the server certificate in PEM format +# server-key.pem - Contains the server private key in PEM format +# client-cert.pem - Contains the server certificate in PEM format +# client-key.pem - Contains the server private key in PEM format +# +# Tokens will be stored under /var/lib/softhsm/tokens/ +# +# The user you are running this as needs to be in the group defined for +# /var/lib/softhsm/tokens/. E.g. +# $ sudo ls -ld /var/lib/softhsm/tokens/ +# drwxrws--- 3 root softhsm 4096 May 3 09:52 /var/lib/softhsm/tokens/ +# which is softhsm in this case (It could be ods). To verify if you are in +# the correct group +# $ id +# To add user to this group +# $ sudo usermod -a -G softhsm +# and log out and back in again. +# + +# Set libsofthsm2.so to use (may be /usr/lib/softhsm/libsofthsm2.so) +LIBSOFTHSM=/usr/local/lib/softhsm/libsofthsm2.so + +# Initialize Soft HSM token +# Note: slot 0 is re-allocated to slot XXX. This is presented as a decimal +# number, the hex equivalent (leading 0x) can be used for any slot options.. +# Set SO PIN to 4321, user PIN to 1234 +softhsm2-util --init-token --slot 0 --label "token-0" --pin 1234 --so-pin 4321 + +# CA Certificate (different id to Server/Client Public Certificate) +# (GnuTLS requires this to be trusted) +p11tool --so-login --load-certificate ca-cert.pem --write --label ca-cert \ + --set-so-pin 4321 --id cc00 --mark-trusted "pkcs11:token=token-0" + +# Server Private Key +openssl pkcs8 -topk8 -inform PEM -outform PEM -in server-key.pem \ + -out server-key.pk8 -nocrypt +softhsm2-util --import server-key.pk8 --label "server-key" --id aa00 \ + --pin 1234 --token "token-0" + +# Server Public Certificate +# (Use different id to private key, but not the same as CA/Client cert) +openssl x509 -in server-cert.pem -out server-cert.der -outform DER +pkcs11-tool --module $LIBSOFTHSM --pin 1234 \ + --write-object ./server-cert.der --type cert --id aa01 \ + --label "server-cert" --token-label "token-0" + +# Client Private Key +openssl pkcs8 -topk8 -inform PEM -outform PEM -in client-key.pem \ + -out client-key.pk8 -nocrypt +softhsm2-util --import client-key.pk8 --label "client-key" --id bb00 \ + --pin 1234 --token "token-0" + +# Client Public Certificate +# (Use different id to private key, but not the same as CA/Client cert) +openssl x509 -in client-cert.pem -out client-cert.der -outform DER +pkcs11-tool --module $LIBSOFTHSM --pin 1234 \ + --write-object ./client-cert.der --type cert --id bb01 \ + --label "client-cert" --token-label "token-0" + +# Verify token is correctly populated +pkcs11-tool --module=$LIBSOFTHSM -t +pkcs11-tool --module=$LIBSOFTHSM --list-objects \ + --pin 1234 --token-label "token-0" +p11tool --list-all pkcs11:model=SoftHSM%20v2 + +# +# Run coap-server using PKCS11 (-C option may need to be -C cert.der) +# +coap-server -C 'pkcs11:token=token-0;id=%cc%00?pin-value=1234' \ + -c 'pkcs11:token=token-0;id=%aa%01?pin-value=1234' \ + -j 'pkcs11:token=token-0;id=%aa%00?pin-value=1234' -v9 + +# or +coap-server -C 'pkcs11:token=token-0;id=%cc%00' \ + -c 'pkcs11:token=token-0;id=%aa%01' \ + -j 'pkcs11:token=token-0;id=%aa%00' -J 1234 -v9 + +# or +coap-server -C 'pkcs11:token=token-0;object=ca-cert' \ + -c 'pkcs11:token=token-0;object=server-cert' \ + -j 'pkcs11:token=token-0;object=server-key' -J 1234 -v9 + +# +# Run coap-client using PKCS11 (-C option may need to be -C cert.der) +# +coap-client -C 'pkcs11:token=token-0;id=%cc%00?pin-value=1234' \ + -c 'pkcs11:token=token-0;id=%bb%01?pin-value=1234' \ + -j 'pkcs11:token=token-0;id=%bb%00?pin-value=1234' -v9 coaps://[::1] + +# or +coap-client -C 'pkcs11:token=token-0;id=%cc%00' \ + -c 'pkcs11:token=token-0;id=%bb%01' \ + -j 'pkcs11:token=token-0;id=%bb%00' -J 1234 -v9 coaps://[::1] + +# or +coap-client -C 'pkcs11:token=token-0;object=ca-cert' \ + -c 'pkcs11:token=token-0;object=client-cert' \ + -j 'pkcs11:token=token-0;object=client-key' -J 1234 -v9 coaps://[::1] + +# +# Client and Server using RPK (GnuTLS only) +# +coap-server -M 'pkcs11:token=token-0;object=server-key' -J 1234 -v9 +# and +coap-client -M 'pkcs11:token=token-0;object=client-key' -J 1234 -v9 coaps://[::1] diff --git a/examples/espidf-coap-server/components/libcoap/LICENSE b/examples/espidf-coap-server/components/libcoap/LICENSE new file mode 100644 index 000000000..78d2c5587 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/LICENSE @@ -0,0 +1,85 @@ +Copyright (c) 2010--2022, Olaf Bergmann and others +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + o Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + o 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. + +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 +HOLDER 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. + +======================================================================== +getopt.c + +License information for getopt.c. This file is only used on Windows +builds of the executables in the examples folder: + +/* + * This file was copied from the following newsgroup posting: + * + * Newsgroups: mod.std.unix + * Subject: public domain AT&T getopt source + * Date: 3 Nov 85 19:34:15 GMT + * + * Here's something you've all been waiting for: the AT&T public domain + * source for getopt(3). It is the code which was given out at the 1985 + * UNIFORUM conference in Dallas. I obtained it by electronic mail + * directly from AT&T. The people there assure me that it is indeed + * in the public domain. + */ + +======================================================================== +uthash + +libcoap uses uthash.h and utlist.h from Troy D. Hanson +(https://troydhanson.github.io/uthash/). These files use the revised +BSD license (BSD-1-Clause license) as included in these two source +files. + +======================================================================== +OpenSSL + +Binaries that are linked against OpenSSL include software developed +by the OpenSSL Project for use in the OpenSSL Toolkit. +(http://www.openssl.org/). Please consult the OpenSSL license +(https://www.openssl.org/source/license.html) for licensing terms. + +======================================================================== +GnuTLS + +When compiled with GnuTLS support, this software includes components +that are licensed under the terms of the the GNU Lesser General Public +License, version 2.1 +(https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html). + +======================================================================== +tinyDTLS + +When compiled with tinyDTLS support, this software includes components +that are licensed under the terms of the Eclipse Distribution License 1.0 +(http://www.eclipse.org/org/documents/edl-v10.php). + +======================================================================== +Mbed TLS + +When compiled with Mbed TLS support, this software includes components +that are licensed under the terms of the Apache 2.0 license +(http://www.apache.org/licenses/LICENSE-2.0). + diff --git a/examples/espidf-coap-server/components/libcoap/Makefile.am b/examples/espidf-coap-server/components/libcoap/Makefile.am new file mode 100644 index 000000000..dba0e6123 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/Makefile.am @@ -0,0 +1,281 @@ +# Makefile.am for libcoap +# +# Copyright (C) 2010-2022 Olaf Bergmann +# Copyright (C) 2015-2017 Carsten Schoenert +# Copyright (C) 2018-2022 Jon Shallow +# +# SPDX-License-Identifier: BSD-2-Clause +# +# This file is part of the CoAP C library libcoap. Please see README and +# COPYING for terms of use. + +## Place generated object files (.o) into the same directory as their source +## files, in order to avoid collisions when non-recursive make is used. +AUTOMAKE_OPTIONS = subdir-objects + +ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4 + +LIBCOAP_PACKAGE_BUILD = @DOLLAR_SIGN@(shell git describe --tags --dirty --always 2>/dev/null || echo @PACKAGE_VERSION@) + +## Additional files for the distribution archive +EXTRA_DIST = \ + BUILDING \ + CONTRIBUTE \ + TODO \ + LICENSE \ + CMakeLists.txt \ + cmake_coap_config.h.in \ + cmake/Config.cmake.in \ + cmake/FindMbedTLS.cmake \ + cmake/FindTinyDTLS.cmake \ + coap_config.h.lwip \ + coap_config.h.riot \ + coap_config.h.windows \ + libcoap-$(LIBCOAP_API_VERSION).pc.in \ + libcoap-$(LIBCOAP_API_VERSION).map \ + libcoap-$(LIBCOAP_API_VERSION).sym \ + examples/coap_list.h \ + examples/getopt.c \ + include/coap$(LIBCOAP_API_VERSION)/coap_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_riot.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_asn1_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_async_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_block_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_cache_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_dtls_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_io_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_net_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_pdu_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_resource_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_session_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_subscribe_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_tcp_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap.h.in \ + include/coap$(LIBCOAP_API_VERSION)/coap.h.windows \ + include/coap$(LIBCOAP_API_VERSION)/coap.h.windows.in \ + include/coap$(LIBCOAP_API_VERSION)/lwippools.h \ + include/coap$(LIBCOAP_API_VERSION)/uthash.h \ + include/coap$(LIBCOAP_API_VERSION)/utlist.h \ + src/coap_io_riot.c \ + tests/test_error_response.h \ + tests/test_encode.h \ + tests/test_options.h \ + tests/test_pdu.h \ + tests/test_sendqueue.h \ + tests/test_session.h \ + tests/test_tls.h \ + tests/test_uri.h \ + tests/test_wellknown.h \ + win32/coap-client/coap-client.vcxproj \ + win32/coap-client/coap-client.vcxproj.filters \ + win32/coap-rd/coap-rd.vcxproj \ + win32/coap-rd/coap-rd.vcxproj.filters \ + win32/coap-server/coap-server.vcxproj \ + win32/coap-server/coap-server.vcxproj.filters \ + win32/libcoap.sln \ + win32/libcoap.vcxproj \ + win32/libcoap.vcxproj.filters \ + win32/testdriver/testdriver.vcxproj \ + win32/testdriver/testdriver.vcxproj.filters \ + win32/testdriver/testdriver.vcxproj.user + +AM_CFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include $(WARNING_CFLAGS) \ + $(DTLS_CFLAGS) -std=c99 $(EXTRA_CFLAGS) \ + -DLIBCOAP_PACKAGE_BUILD='"$(LIBCOAP_PACKAGE_BUILD)"' + +SUBDIRS = $(subdirs) . man doc tests examples + +## Define a libtool archive target "libcoap-@LIBCOAP_NAME_SUFFIX@.la", with +## @LIBCOAP_NAME_SUFFIX@ substituted into the generated Makefile at configure +## time. +## The libtool archive file (.la) will be installed into the directory named +## by the predefined variable $(bindir), along with the actual shared library +## file (.so). +lib_LTLIBRARIES = libcoap-@LIBCOAP_NAME_SUFFIX@.la + +libcoap_@LIBCOAP_NAME_SUFFIX@_la_CFLAGS = \ + -fPIC \ + -fPIE \ + $(AM_CFLAGS) + +## Define the source file list for the "libcoap.la" target. +## Note that it is not necessary to list header files which are already listed +## elsewhere in a _HEADERS variable assignment. +libcoap_@LIBCOAP_NAME_SUFFIX@_la_SOURCES = \ + src/block.c \ + src/coap_address.c \ + src/coap_asn1.c \ + src/coap_async.c \ + src/coap_cache.c \ + src/coap_debug.c \ + src/coap_event.c \ + src/coap_hashkey.c \ + src/coap_gnutls.c \ + src/coap_io.c \ + src/coap_mbedtls.c \ + src/coap_notls.c \ + src/coap_openssl.c \ + src/coap_option.c \ + src/coap_prng.c \ + src/coap_session.c \ + src/coap_subscribe.c \ + src/coap_tcp.c \ + src/coap_time.c \ + src/coap_tinydtls.c \ + src/encode.c \ + src/mem.c \ + src/net.c \ + src/pdu.c \ + src/resource.c \ + src/str.c \ + src/uri.c + +## Define the list of public header files and their install location. +## The API version is appended to the install folder to being able to +## co-install various versions of libcoap. +libcoap_includedir = $(includedir)/coap$(LIBCOAP_API_VERSION)/ + +# If there is a API change to something $(LIBCOAP_API_VERSION) > 1 the install +# prefix for the header files has to change to not conflict the older version +# if the user want's to install both versions. There will be something used like +# libcoap_include_HEADERS = \ +# $(top_srcdir)/include/coap-$(LIBCOAP_API_VERSION)/* + +libcoap_include_HEADERS = \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/block.h \ + $(top_builddir)/include/coap$(LIBCOAP_API_VERSION)/coap.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_address.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_async.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_cache.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_debug.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_dtls.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_event.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_forward_decls.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_hashkey.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_io.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_mutex.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_option.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_session.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_subscribe.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_time.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/encode.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/libcoap.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/mem.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/net.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/pdu.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/coap_prng.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/resource.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/str.h \ + $(top_srcdir)/include/coap$(LIBCOAP_API_VERSION)/uri.h + +## Instruct libtool to include API version information in the generated shared +## library file (.so). The library ABI version will later defined in configure.ac, +## so that all version information is kept in one place. +libcoap_@LIBCOAP_NAME_SUFFIX@_la_LDFLAGS = \ + -version-info $(LT_LIBCOAP_CURRENT):$(LT_LIBCOAP_REVISION):$(LT_LIBCOAP_AGE) \ + @libcoap_SYMBOLS@ \ + $(DTLS_LIBS) \ + -pie + +## Collect symbols here we want to ignore while building the helper files +## libcoap-$(LIBCOAP_API_VERSION).{map,sym} for the linker. +CTAGS_IGNORE=-I " \ +coap_pdu_from_pbuf \ +" + +# This helper is called by libcoap-$(LIBCOAP_API_VERSION).{map,sym} to see if +# configure has detected a usable version of the ctags program and aborts if not. +check_ctags: + @if [ "$(CTAGS_PROG)" = "" ]; then \ + echo ;\ + echo "There was no ctags program found by the configure script!" ;\ + echo "ctags is needed for running this target! Please note the warning about the missed ctags program of the configure script." ;\ + echo ;\ + exit 1;\ + fi + +## Helper target to generate the symbol table needed by libtool. +## The .map format is used when ld supports linker scripts, otherwise +## it must fall back to a plain symbol file. +update-map-file: libcoap-$(LIBCOAP_API_VERSION).map libcoap-$(LIBCOAP_API_VERSION).sym + +libcoap-$(LIBCOAP_API_VERSION).map: check_ctags $(libcoap_include_HEADERS) + ( echo "VER_$(LIBCOAP_API_VERSION) {" ; \ + echo "global:" ; \ + $(CTAGS_PROG) $(CTAGS_IGNORE) -f - --c-kinds=p $(libcoap_include_HEADERS) | awk '/^coap_/ { print " " $$1 ";" }' | sort -u ; \ + echo "local:" ; \ + echo " *;" ; \ + echo "};" ) > $(top_builddir)/$@.new + mv $(top_builddir)/$@.new $(top_builddir)/$@ + +libcoap-$(LIBCOAP_API_VERSION).sym: check_ctags $(libcoap_include_HEADERS) + ( $(CTAGS_PROG) $(CTAGS_IGNORE) -f - --c-kinds=p $(libcoap_include_HEADERS) | awk '/^coap_/ { print $$1 }' | sort -u ) \ + > $(top_builddir)/$@.new + mv $(top_builddir)/$@.new $(top_builddir)/$@ + +## Install the generated pkg-config file (.pc) into the expected location for +## architecture-dependent package configuration information. Occasionally, +## pkg-config files are also used for architecture-independent data packages, +## in which case the correct install location would be $(datadir)/pkgconfig. +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libcoap-$(LIBCOAP_NAME_SUFFIX).pc + +## Define an independent executable script for inclusion in the distribution +## archive. However, it will not be installed on an end user's system due to +## the noinst_ prefix. +dist_noinst_SCRIPTS = autogen.sh + +## Set up a common library that causes linking against the common library +## to link with the actual library with (D)TLS support +if BUILD_ADD_DEFAULT_NAMES +install-exec-hook: + (cd $(DESTDIR)$(libdir) ; \ + if [ -f libcoap-$(LIBCOAP_NAME_SUFFIX).so ] ; then \ + rm -f libcoap-$(LIBCOAP_API_VERSION).so ; \ + $(LN_S) libcoap-$(LIBCOAP_NAME_SUFFIX).so libcoap-$(LIBCOAP_API_VERSION).so ; \ + fi ; \ + rm -f libcoap-$(LIBCOAP_API_VERSION).a ; \ + rm -f libcoap-$(LIBCOAP_API_VERSION).la ; \ + $(LN_S) libcoap-$(LIBCOAP_NAME_SUFFIX).a libcoap-$(LIBCOAP_API_VERSION).a ; \ + $(LN_S) libcoap-$(LIBCOAP_NAME_SUFFIX).la libcoap-$(LIBCOAP_API_VERSION).la ; \ + $(MKDIR_P) $(DESTDIR)$(pkgconfigdir) ; \ + cd $(DESTDIR)$(pkgconfigdir) ; \ + rm -f libcoap-$(LIBCOAP_API_VERSION).pc ; \ + $(LN_S) libcoap-$(LIBCOAP_NAME_SUFFIX).pc libcoap-$(LIBCOAP_API_VERSION).pc) + +uninstall-hook: + (cd $(DESTDIR)$(libdir) ; \ + rm -f libcoap-$(LIBCOAP_API_VERSION).a ; \ + rm -f libcoap-$(LIBCOAP_API_VERSION).la ; \ + rm -f libcoap-$(LIBCOAP_API_VERSION).so ; \ + cd $(DESTDIR)$(pkgconfigdir) ; \ + rm -f libcoap-$(LIBCOAP_API_VERSION).pc) +endif # BUILD_ADD_DEFAULT_NAMES + +## various *-local targets +## Remove the helper files for the linker and the pkg-config file if there +## is 'make distclean' called. NOTE: To re create the *.{map,sym} files you +## need to call the target update-map-file after the configure script was +## running! +clean-local: + -find \( -name '*.gcda' -o -name '*.gcno' -o -name '*.gcov' \) -delete + +distclean-local: + @rm -f src/*.o src/*.lo + rm -f libcoap-$(LIBCOAP_API_VERSION).map + rm -f libcoap-$(LIBCOAP_API_VERSION).sym + rm -f libcoap-$(LIBCOAP_NAME_SUFFIX).pc + @echo + @echo " ---> Please note the following important advice! <---" + @echo " The files libcoap-$(LIBCOAP_API_VERSION).{map,sym} are removed by the distclean target!" + @echo " To regenerate this two files you need to call 'make update-map-file' first before any" + @echo " other Make target. Otherwise the build of libcoap will fail!" + @echo + +## Ensure we have actual *.{map,sym} files if we create a release tarball. +dist-local: update-map-file + +## Finaly some phony targets, just to ensure those targets are always buildable +## no matter if the user has created same called files. +.PHONY: update-map-file check_ctags + diff --git a/examples/espidf-coap-server/components/libcoap/Makefile.libcoap b/examples/espidf-coap-server/components/libcoap/Makefile.libcoap new file mode 100644 index 000000000..88199d49c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/Makefile.libcoap @@ -0,0 +1,7 @@ +libcoap_src = pdu.c net.c coap_cache.c coap_debug.c encode.c uri.c coap_subscribe.c resource.c str.c coap_option.c coap_async.c block.c mem.c coap_io.c coap_session.c coap_notls.c coap_hashkey.c coap_address.c coap_tcp.c + +libcoap_dir := $(filter %libcoap,$(APPDS)) +vpath %c $(libcoap_dir)/src + +# set include path for coap sources +CFLAGS += -I$(libcoap_dir)/include diff --git a/examples/espidf-coap-server/components/libcoap/NEWS b/examples/espidf-coap-server/components/libcoap/NEWS new file mode 100644 index 000000000..e69de29bb diff --git a/examples/espidf-coap-server/components/libcoap/README b/examples/espidf-coap-server/components/libcoap/README new file mode 100644 index 000000000..faab2727e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/README @@ -0,0 +1,89 @@ +# libcoap: A C implementation of the Constrained Application Protocol (RFC 7252) + +[![Build Status: main](https://github.com/obgm/libcoap/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/obgm/libcoap/actions?query=branch:main) +[![Build Status: develop](https://github.com/obgm/libcoap/actions/workflows/main.yml/badge.svg?branch=develop)](https://github.com/obgm/libcoap/actions?query=branch:develop) +[![Static Analysis](https://scan.coverity.com/projects/10970/badge.svg?flat=1)](https://scan.coverity.com/projects/obgm-libcoap) +[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/libcoap.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:libcoap) + +Copyright (C) 2010—2022 by Olaf Bergmann and others + +ABOUT LIBCOAP +============= + +libcoap is a C implementation of a lightweight application-protocol +for devices that are constrained their resources such as computing +power, RF range, memory, bandwidth, or network packet sizes. This +protocol, CoAP, is standardized by the IETF as RFC 7252. For further +information related to CoAP, see . + +You might want to check out +[libcoap-minimal](https://github.com/obgm/libcoap-minimal) for usage +examples. + +DOCUMENTATION +============= + +Documentation and further information can be found at +. + +PACKAGE CONTENTS +================ + +This package contains a protocol parser and basic networking +functions for platforms with support for malloc() and BSD-style +sockets. In addition, there is support for Contiki, LwIP and +Espressif/ESP-IDF hosted environments. + +The following RFCs are supported + +* RFC7252: The Constrained Application Protocol (CoAP) + +* RFC7390: Group Communication for the Constrained Application Protocol (CoAP) + +* RFC7641: Observing Resources in the Constrained Application Protocol (CoAP) + +* RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP) + +* RFC7967: Constrained Application Protocol (CoAP) Option for No Server Response + +* RFC8132: PATCH and FETCH Methods for the Constrained Application Protocol (CoAP) + +* RFC8323: CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets + [No WebSockets support] + +* RFC8516: "Too Many Requests" Response Code for the Constrained Application Protocol + +* RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option + +* RFC9175: CoAP: Echo, Request-Tag, and Token Processing + +There is (D)TLS support for the following libraries + +* OpenSSL (Minimum version 1.1.0) [PKI, PSK and PKCS11] + +* GnuTLS (Minimum version 3.3.0) [PKI, PSK, RPK(3.6.6+) and PKCS11] + +* Mbed TLS (Minimum version 2.7.10) [PKI and PSK] + +* TinyDTLS [PSK and RPK] [DTLS Only] + +The examples directory contain a CoAP client, CoAP Resource Directory server +and a CoAP server to demonstrate the use of this library. + +BUILDING +======== + +Further information can be found at +and [BUILDING](https://raw.githubusercontent.com/obgm/libcoap/develop/BUILDING). + +LICENSE INFORMATION +=================== + +This library is published as open-source software without any warranty +of any kind. Use is permitted under the terms of the simplified BSD +license. It includes public domain software. libcoap binaries may also +include open-source software with their respective licensing terms. +Please refer to +[LICENSE](https://raw.githubusercontent.com/obgm/libcoap/develop/LICENSE) +for further details. + diff --git a/examples/espidf-coap-server/components/libcoap/README.md b/examples/espidf-coap-server/components/libcoap/README.md new file mode 100644 index 000000000..faab2727e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/README.md @@ -0,0 +1,89 @@ +# libcoap: A C implementation of the Constrained Application Protocol (RFC 7252) + +[![Build Status: main](https://github.com/obgm/libcoap/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/obgm/libcoap/actions?query=branch:main) +[![Build Status: develop](https://github.com/obgm/libcoap/actions/workflows/main.yml/badge.svg?branch=develop)](https://github.com/obgm/libcoap/actions?query=branch:develop) +[![Static Analysis](https://scan.coverity.com/projects/10970/badge.svg?flat=1)](https://scan.coverity.com/projects/obgm-libcoap) +[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/libcoap.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:libcoap) + +Copyright (C) 2010—2022 by Olaf Bergmann and others + +ABOUT LIBCOAP +============= + +libcoap is a C implementation of a lightweight application-protocol +for devices that are constrained their resources such as computing +power, RF range, memory, bandwidth, or network packet sizes. This +protocol, CoAP, is standardized by the IETF as RFC 7252. For further +information related to CoAP, see . + +You might want to check out +[libcoap-minimal](https://github.com/obgm/libcoap-minimal) for usage +examples. + +DOCUMENTATION +============= + +Documentation and further information can be found at +. + +PACKAGE CONTENTS +================ + +This package contains a protocol parser and basic networking +functions for platforms with support for malloc() and BSD-style +sockets. In addition, there is support for Contiki, LwIP and +Espressif/ESP-IDF hosted environments. + +The following RFCs are supported + +* RFC7252: The Constrained Application Protocol (CoAP) + +* RFC7390: Group Communication for the Constrained Application Protocol (CoAP) + +* RFC7641: Observing Resources in the Constrained Application Protocol (CoAP) + +* RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP) + +* RFC7967: Constrained Application Protocol (CoAP) Option for No Server Response + +* RFC8132: PATCH and FETCH Methods for the Constrained Application Protocol (CoAP) + +* RFC8323: CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets + [No WebSockets support] + +* RFC8516: "Too Many Requests" Response Code for the Constrained Application Protocol + +* RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option + +* RFC9175: CoAP: Echo, Request-Tag, and Token Processing + +There is (D)TLS support for the following libraries + +* OpenSSL (Minimum version 1.1.0) [PKI, PSK and PKCS11] + +* GnuTLS (Minimum version 3.3.0) [PKI, PSK, RPK(3.6.6+) and PKCS11] + +* Mbed TLS (Minimum version 2.7.10) [PKI and PSK] + +* TinyDTLS [PSK and RPK] [DTLS Only] + +The examples directory contain a CoAP client, CoAP Resource Directory server +and a CoAP server to demonstrate the use of this library. + +BUILDING +======== + +Further information can be found at +and [BUILDING](https://raw.githubusercontent.com/obgm/libcoap/develop/BUILDING). + +LICENSE INFORMATION +=================== + +This library is published as open-source software without any warranty +of any kind. Use is permitted under the terms of the simplified BSD +license. It includes public domain software. libcoap binaries may also +include open-source software with their respective licensing terms. +Please refer to +[LICENSE](https://raw.githubusercontent.com/obgm/libcoap/develop/LICENSE) +for further details. + diff --git a/examples/espidf-coap-server/components/libcoap/TODO b/examples/espidf-coap-server/components/libcoap/TODO new file mode 100644 index 000000000..52df83af3 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/TODO @@ -0,0 +1,27 @@ +This is a simple file for all kinds of stuff related on development for +libcoap. Please append (and remove) any issue you think its worthy. + +Classification of issues: + Critical -> Break the library in some kind or a missing feature, maybe not + directly but later + Serious -> No regression on the user side, more likly on the libcoap + development + Minor -> Things that are nice to have, but they are not time critical + +================= +* CRITICAL ISSUES +================= + +================ +* SERIOUS ISSUES +================ +-> Create some development rules like: + --> How to submit patches? What about pull requests? + --> How to implement/change platform related code? +-> Further improve the API documentation + +============== +* MINOR ISSUES +============== +-> Adding a logo for libcoap + diff --git a/examples/espidf-coap-server/components/libcoap/autogen.sh b/examples/espidf-coap-server/components/libcoap/autogen.sh new file mode 100644 index 000000000..0b97905fa --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/autogen.sh @@ -0,0 +1,142 @@ +#!/bin/sh -e + +# uncomment the set command for debugging +#set -x + +# function to check for needed helper tools +check_helper() { +#echo "Checking for $1 ..." +TOOL=`which "$1" || echo none` + +if [ "$TOOL" = "none" ]; then + echo + echo "Couldn't find '$1'!" + RET=1 +else + RET=0 +fi +} + +PROJECT="libcoap" + +AUTOGEN_FILES=" +INSTALL +aclocal.m4 ar-lib +coap_config.h coap_config.h.in* compile config.guess config.h* config.log config.status config.sub configure +depcomp +doc/Doxyfile doc/doxyfile.stamp doc/doxygen_sqlite3.db doc/Makefile doc/Makefile.in +examples/*.o examples/coap-client examples/coap-server examples/coap-rd +examples/Makefile examples/Makefile.in +include/coap3/coap.h +install-sh +libcoap-*.pc libtool ltmain.sh +man/coap*.[357] man/coap*.txt man/Makefile man/Makefile.in +missing +Makefile Makefile.in +stamp-h1 src/.dirstamp libcoap*.la* src/*.*o +tests/*.o tests/Makefile tests/Makefile.in tests/testdriver tests/test_common.h +tests/oss-fuzz/Makefile.ci +m4/libtool.m4 m4/lt~obsolete.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 +" + +AUTOGEN_DIRS=" +.deps +.libs autom4te.cache/ +doc/html/ +examples/.deps/ examples/.libs +man/.deps +man/tmp +src/.deps/ src/.libs/ +tests/.deps/ +" + +# checking for cleaner argument +echo +if [ "$1" = "--clean" ]; then + echo "removing autogenerated files ..." + rm -rf $AUTOGEN_FILES $AUTOGEN_DIRS + echo "done" + exit +else + echo "[HINT] You can run 'autogen.sh --clean' to remove all generated files by the autotools." + echo +fi + +# checking for autoreconf +check_helper autoconf +if [ "$RET" = "1" ]; then + echo "You probably need to install the package 'autoconf'." + ERROR=1 +else + echo "Found 'autoconf'." +fi + +# checking for aclocal +check_helper aclocal +if [ "$RET" = "1" ]; then + echo "You probably need to install the package 'automake'." + ERROR=1 +else + echo "Found 'aclocal'." +fi + +# checking for pkg-config +check_helper pkg-config +if [ "$RET" = "1" ]; then + echo "You probably need to install the package 'pkg-config|pkgconf'." + ERROR=1 +else + echo "Found 'pkg-config'." +fi + +# checking for libtool +# The libtool helper maybe installed as 'libtoolize', checking for 'libtool' first. +check_helper libtool +if [ "$RET" = "1" ]; then + # O.k. libtool not found, searching for libtoolize. + check_helper libtoolize + if [ "$RET" = "1" ]; then + echo "You probably need to install the package 'libtool'." + # That's bad, we found nothing! + ERROR=1 + else + echo "Found 'libtoolize'." + break + fi +else + echo "Found 'libtool'." +fi + +# exit if one tool isn't available +if [ "$ERROR" = "1" ]; then + echo + echo "One or more needed tools are missing, exiting ..." + echo "Please install the needed software packages and restart 'autogen.sh' again." + echo + exit 1 +fi + +echo +echo " ---> Found all needed tools! That's fine." +echo + +# countinue otherwise +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. + +# Creating the directory m4 before calling autoreconf to +# not struggle with old versions of aclocal. +mkdir -p $srcdir/m4 + +# create ar-lib if not present to avoid autoreconf throwing an error +# when the file is missing. As autoreconf is called with --force +# the file will get updated with the proper contents afterwards. +touch ar-lib + +echo "Generating needed autotools files for $PROJECT by running autoreconf ..." +autoreconf --force --install --verbose "$srcdir" + +echo +echo "You can now run './configure --help' to see possible configuration options." +echo "Otherwise process the configure script to create the makefiles and generated helper files." +echo diff --git a/examples/espidf-coap-server/components/libcoap/build-env/.dockerignore b/examples/espidf-coap-server/components/libcoap/build-env/.dockerignore new file mode 100644 index 000000000..73b67f9b6 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/build-env/.dockerignore @@ -0,0 +1,5 @@ +imagename +build.sh +*~ +.*.swp +\#*# diff --git a/examples/espidf-coap-server/components/libcoap/build-env/Dockerfile.build-env b/examples/espidf-coap-server/components/libcoap/build-env/Dockerfile.build-env new file mode 100644 index 000000000..1cf6079a2 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/build-env/Dockerfile.build-env @@ -0,0 +1,7 @@ +FROM debian:testing-slim + +RUN apt-get update && apt-get install -y autoconf automake gcc clang \ + libtool libtool-bin make pkg-config libcunit1-dev libssl-dev \ + libgnutls28-dev libmbedtls-dev exuberant-ctags git valgrind \ + graphviz doxygen libxml2-utils xsltproc docbook-xml docbook-xsl asciidoc +RUN apt-get clean diff --git a/examples/espidf-coap-server/components/libcoap/build-env/Dockerfile.develop b/examples/espidf-coap-server/components/libcoap/build-env/Dockerfile.develop new file mode 100644 index 000000000..3f83e0ab2 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/build-env/Dockerfile.develop @@ -0,0 +1,36 @@ +FROM obgm/libcoap:build-env + +RUN apt-get update && apt-get install -y cmake git g++ +RUN apt-get clean + +ENV libcoap_dir=/home/libcoap +ADD . $libcoap_dir +WORKDIR $libcoap_dir + +RUN ./autogen.sh --clean && ./autogen.sh +RUN ./configure --disable-documentation --enable-tests --enable-examples --with-openssl && make install clean + +WORKDIR /home +RUN git clone --depth 1 https://github.com/cabo/cn-cbor.git && cd cn-cbor && ./build.sh all doc install + +# The image for development with libcoap +FROM debian:testing-slim + +RUN apt-get update && apt-get install -y autoconf automake gcc g++ gdb libtool libtool-bin make \ + pkg-config libssl-dev libgnutls28-dev libmbedtls-dev +RUN apt-get install -y iproute2 lsof net-tools inetutils-ping netcat-openbsd less vim +RUN apt-get clean + +COPY --from=0 /usr/local/include/coap3 /usr/local/include/coap3 +COPY --from=0 /usr/local/lib /usr/local/lib +COPY --from=0 /usr/local/bin/coap-client /usr/local/bin/ +COPY --from=0 /usr/local/include/cn-cbor /usr/local/include/cn-cbor +RUN echo "/usr/local/lib" >>/etc/ld.so.conf.d/usr_local.conf && ldconfig /usr/local/lib + +ARG user=user +RUN adduser --disabled-password --gecos '' $user +RUN chown -R $user:$user /home/$user +WORKDIR /home/$user +USER $user + +EXPOSE 5683 5684 diff --git a/examples/espidf-coap-server/components/libcoap/build-env/build.sh b/examples/espidf-coap-server/components/libcoap/build-env/build.sh new file mode 100644 index 000000000..5cf4bc260 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/build-env/build.sh @@ -0,0 +1,16 @@ +#! /usr/bin/env bash + +pushd $(dirname $0) +. ./imagename + +# see https://stackoverflow.com/a/2924755 for switching boldface on/off +bold=$(tput bold) +normal=$(tput sgr0) + +echo "${bold}**** Creating build-env image ****${normal}" +docker build -f Dockerfile.build-env -t $USER/$IMAGE:build-env . + +echo "${bold}**** Creating develop image ****${normal}" +docker build -f Dockerfile.develop -t $USER/$IMAGE:develop .. + +popd diff --git a/examples/espidf-coap-server/components/libcoap/build-env/imagename b/examples/espidf-coap-server/components/libcoap/build-env/imagename new file mode 100644 index 000000000..8d69844eb --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/build-env/imagename @@ -0,0 +1,2 @@ +USER=obgm +IMAGE=libcoap diff --git a/examples/espidf-coap-server/components/libcoap/cmake-format.yaml b/examples/espidf-coap-server/components/libcoap/cmake-format.yaml new file mode 100644 index 000000000..3e255423a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/cmake-format.yaml @@ -0,0 +1,25 @@ +# to format cmake files we use cmake-format: +# pip install cmake-format --upgrade +# information about the configuration here: +# https://github.com/cheshirekow/cmake_format + +# How wide to allow formatted cmake files +line_width: 80 + +# How many spaces to tab for indent +tab_size: 2 + +# Format command names consistently as 'lower' or 'upper' case +command_case: "lower" + +first_comment_is_literal: False + +# enable comment markup parsing and reflow +enable_markup: False + +# If arglists are longer than this, break them always +max_subargs_per_line: 1 + +max_subgroups_hwrap: 2 + +max_pargs_hwrap: 2 diff --git a/examples/espidf-coap-server/components/libcoap/cmake/FindMbedTLS.cmake b/examples/espidf-coap-server/components/libcoap/cmake/FindMbedTLS.cmake new file mode 100644 index 000000000..75d8598d4 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/cmake/FindMbedTLS.cmake @@ -0,0 +1,35 @@ +find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) + +find_library(MBEDTLS_LIBRARY mbedtls) +find_library(MBEDX509_LIBRARY mbedx509) +find_library(MBEDCRYPTO_LIBRARY mbedcrypto) + +set(MBEDTLS_LIBRARIES + "${MBEDTLS_LIBRARY}" + "${MBEDX509_LIBRARY}" + "${MBEDCRYPTO_LIBRARY}") + +if(MBEDTLS_LIBRARY) + set(MbedTLS_FOUND TRUE) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + MBEDTLS + DEFAULT_MSG + MBEDTLS_INCLUDE_DIRS + MBEDTLS_LIBRARY + MBEDX509_LIBRARY + MBEDCRYPTO_LIBRARY) + +mark_as_advanced( + MBEDTLS_INCLUDE_DIRS + MBEDTLS_LIBRARY + MBEDX509_LIBRARY + MBEDCRYPTO_LIBRARY) + +message(STATUS "MBEDTLS_INCLUDE_DIRS: ${MBEDTLS_INCLUDE_DIRS}") +message(STATUS "MBEDTLS_LIBRARY: ${MBEDTLS_LIBRARY}") +message(STATUS "MBEDX509_LIBRARY: ${MBEDX509_LIBRARY}") +message(STATUS "MBEDCRYPTO_LIBRARY: ${MBEDCRYPTO_LIBRARY}") +message(STATUS "MBEDTLS_LIBRARIES: ${MBEDTLS_LIBRARIES}") diff --git a/examples/espidf-coap-server/components/libcoap/cmake/FindTinyDTLS.cmake b/examples/espidf-coap-server/components/libcoap/cmake/FindTinyDTLS.cmake new file mode 100644 index 000000000..99557321c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/cmake/FindTinyDTLS.cmake @@ -0,0 +1,88 @@ +# FindTinyDTLS +# ----------- +# +# Find the tinyDTLS encryption library. +# +# Imported Targets +# ^^^^^^^^^^^^^^^^ +# +# This module defines the following :prop_tgt:`IMPORTED` targets: +# +# ``tinydtls`` +# The tinyDTLS ``tinydtls`` library, if found. +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# This module will set the following variables in your project: +# +# ``TINYDTLS_FOUND`` +# System has the tinyDTLS library. +# ``TINYDTLS_INCLUDE_DIR`` +# The tinyDTLS include directory. +# ``TINYDTLS_LIBRARIES`` +# All tinyDTLS libraries. +# +# Hints +# ^^^^^ +# +# Set ``TINYDTLS_ROOT_DIR`` to the root directory of an tinyDTLS installation. + +if(TINYDTLS_ROOT_DIR) + set(_EXTRA_FIND_ARGS "NO_CMAKE_FIND_ROOT_PATH") +endif() + +find_path( + TINYDTLS_INCLUDE_DIR + NAMES tinydtls/dtls.h + PATH_SUFFIXES include + HINTS ${PROJECT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${TINYDTLS_ROOT_DIR} + ${_EXTRA_FIND_ARGS}) + +find_library( + TINYDTLS_LIBRARIES + NAMES tinydtls + PATH_SUFFIXES lib + HINTS ${PROJECT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${TINYDTLS_ROOT_DIR} + ${_EXTRA_FIND_ARGS}) + +if(TINYDTLS_LIBRARIES) + set(TINYDTLS_FOUND TRUE) +else() + set(TINYDTLS_FOUND FALSE) + if(TinyDTLS_FIND_REQUIRED) + message(FATAL_ERROR "Tinydtls could not be found") + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + tinyDTLS + FOUND_VAR + TINYDTLS_FOUND + REQUIRED_VARS + TINYDTLS_INCLUDE_DIR + TINYDTLS_LIBRARIES + VERSION_VAR) + +if(NOT + TARGET + tinydtls) + add_library( + tinydtls + UNKNOWN + IMPORTED) + set_target_properties( + tinydtls + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${TINYDTLS_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${TINYDTLS_LIBRARIES}") +endif() + +message(STATUS "TINYDTLS_INCLUDE_DIR: ${TINYDTLS_INCLUDE_DIR}") +message(STATUS "TINYDTLS_LIBRARIES: ${TINYDTLS_LIBRARIES}") +message(STATUS "TINYDTLS_ROOT_DIR: ${TINYDTLS_ROOT_DIR}") diff --git a/examples/espidf-coap-server/components/libcoap/cmake_coap_config.h.in b/examples/espidf-coap-server/components/libcoap/cmake_coap_config.h.in new file mode 100644 index 000000000..d01ab53d1 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/cmake_coap_config.h.in @@ -0,0 +1,177 @@ +/* + * cmake_coap_config.h -- cmake configuration for libcoap + * + * Copyright (C) 2020 Carlos Gomes Martinho + * Copyright (C) 2021-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef COAP_CONFIG_H_ +#define COAP_CONFIG_H_ + +#if ! defined(_WIN32) +#define _GNU_SOURCE +#endif + +/* Define to 1 if you have header file. */ +#cmakedefine HAVE_WS2TCPIP_H @HAVE_WS2TCPIP_H@ + +/* Define if the system has small stack size */ +#cmakedefine COAP_CONSTRAINED_STACK @COAP_CONSTRAINED_STACK@ + +/* Define to 1 if you have header file. */ +#cmakedefine HAVE_WINSOCK2_H @HAVE_WINSOCK2_H@ + +/* Define if the library has client support */ +#cmakedefine COAP_CLIENT_SUPPORT @COAP_CLIENT_SUPPORT@ + +/* Define if the library has server support */ +#cmakedefine COAP_SERVER_SUPPORT @COAP_SERVER_SUPPORT@ + +/* Define if the system has epoll support */ +#cmakedefine COAP_EPOLL_SUPPORT @COAP_EPOLL_SUPPORT@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARPA_INET_H @HAVE_ARPA_INET_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ASSERT_H @HAVE_ASSERT_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H @HAVE_DLFCN_H@ + +/* Define to 1 if you have the `getaddrinfo' function. */ +#cmakedefine HAVE_GETADDRINFO @HAVE_GETADDRINFO@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H @HAVE_INTTYPES_H@ + +/* Define if the system has openssl */ +#cmakedefine HAVE_OPENSSL @HAVE_OPENSSL@ + +/* Define if the system has libgnutls28 */ +#cmakedefine HAVE_LIBGNUTLS @HAVE_LIBGNUTLS@ + +/* Define if the system has libtinydtls */ +#cmakedefine HAVE_LIBTINYDTLS @HAVE_LIBTINYDTLS@ + +/* Define if the system has libmbedtls */ +#cmakedefine HAVE_MBEDTLS @HAVE_MBEDTLS@ + +/* Define to 1 to build without TCP support. */ +#cmakedefine01 COAP_DISABLE_TCP + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H @HAVE_LIMITS_H@ + +/* Define to 1 if you have the `malloc' function. */ +#cmakedefine HAVE_MALLOC @HAVE_MALLOC@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H @HAVE_MEMORY_H@ + +/* Define to 1 if you have the `memset' function. */ +#cmakedefine HAVE_MEMSET @HAVE_MEMSET@ + +/* Define to 1 if you have the `if_nametoindex' function. */ +#cmakedefine HAVE_IF_NAMETOINDEX @HAVE_IF_NAMETOINDEX@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETDB_H @HAVE_NETDB_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NET_IF_H @HAVE_NET_IF_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_IN_H @HAVE_NETINET_IN_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PTHREAD_H @HAVE_PTHREAD_H@ + +/* Define to 1 if you have the `pthread_mutex_lock' function. */ +#cmakedefine HAVE_PTHREAD_MUTEX_LOCK @HAVE_PTHREAD_MUTEX_LOCK@ + +/* Define to 1 if you have the `select' function. */ +#cmakedefine HAVE_SELECT @HAVE_SELECT@ + +/* Define to 1 if you have the `socket' function. */ +#cmakedefine HAVE_SOCKET @HAVE_SOCKET@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H @HAVE_STDLIB_H@ + +/* Define to 1 if you have the `strcasecmp' function. */ +#cmakedefine HAVE_STRCASECMP @HAVE_STRCASECMP@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H @HAVE_STRINGS_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H @HAVE_STRING_H@ + +/* Define to 1 if you have the `strnlen' function. */ +#cmakedefine HAVE_STRNLEN @HAVE_STRNLEN@ + +/* Define to 1 if you have the `strrchr' function. */ +#cmakedefine HAVE_STRRCHR @HAVE_STRRCHR@ + +/* Define to 1 if the system has the type `struct cmsghdr'. */ +#cmakedefine HAVE_STRUCT_CMSGHDR @HAVE_STRUCT_CMSGHDR@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYSLOG_H @HAVE_SYSLOG_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_IOCTL_H @HAVE_SYS_IOCTL_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SOCKET_H @HAVE_SYS_SOCKET_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H @HAVE_SYS_STAT_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H @HAVE_SYS_TIME_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UNISTD_H @HAVE_SYS_UNISTD_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TIME_H @HAVE_TIME_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@ + +/* Define to the address where bug reports for this package should be sent. */ +#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define to the full name of this package. */ +#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define to the full name and version of this package. */ +#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@" + +/* Define to the one symbol short name of this package. */ +#cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@" + +/* Define to the home page for this package. */ +#cmakedefine PACKAGE_URL "@PACKAGE_URL@" + +/* Define to the version of this package. */ +#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@" + +#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(snprintf) +#define snprintf _snprintf +#endif + +#endif /* COAP_CONFIG_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/coap_config.h.contiki b/examples/espidf-coap-server/components/libcoap/coap_config.h.contiki new file mode 100644 index 000000000..6e4f54157 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/coap_config.h.contiki @@ -0,0 +1,215 @@ +#ifndef COAP_CONFIG_H_ +#define COAP_CONFIG_H_ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#define WITH_CONTIKI 1 + +#ifndef COAP_CONSTRAINED_STACK +#define COAP_CONSTRAINED_STACK 1 +#endif + +#ifndef COAP_DISABLE_TCP +#define COAP_DISABLE_TCP 1 +#endif + +#define PACKAGE_STRING "libcoap" +#define PACKAGE_NAME "libcoap" + +#ifndef COAP_DEFAULT_PDU_SIZE +#define COAP_DEFAULT_PDU_SIZE 64 +#endif /* COAP_DEFAULT_PDU_SIZE */ +#ifndef COAP_RXBUFFER_SIZE +#define COAP_RXBUFFER_SIZE 64 +#endif /* COAP_RXBUFFER_SIZE */ + +/** Number of resources that can be handled by a CoAP server in addition to + * @c /.well-known/core */ +#ifndef COAP_MAX_RESOURCES +#define COAP_MAX_RESOURCES 3 +#endif /* COAP_MAX_RESOURCES */ + +/** Number of attributes that can be handled (should be at least + * @c 2 * COAP_MAX_RESOURCES. to carry the content type and the + * resource type. */ +#ifndef COAP_MAX_ATTRIBUTES +#define COAP_MAX_ATTRIBUTES 4 +#endif /* COAP_MAX_ATTRIBUTES */ + +/** + * Number of PDUs that can be stored simultaneously. This number + * includes both, the PDUs stored for retransmission as well as the + * PDUs received. Beware that choosing a too small value can lead to + * many retransmissions to be dealt with. + */ +#ifndef COAP_PDU_MAXCNT +#define COAP_PDU_MAXCNT 4 +#endif /* COAP_PDU_MAXCNT */ + +/** + * Maximum number of sessions. + */ +#ifndef COAP_MAX_SESSIONS +#define COAP_MAX_SESSIONS 2 +#endif /* COAP_MAX_SESSIONS */ + +/** + * Maximum number of subscriptions. Every additional subscriber costs + * 36 B. + */ +#ifndef COAP_MAX_SUBSCRIBERS +#define COAP_MAX_SUBSCRIBERS 3 +#endif /* COAP_MAX_SUBSCRIBERS */ + +/** + * The maximum number of cache-key entries that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_CACHE_KEYS +#define COAP_MAX_CACHE_KEYS (2U) +#endif /* COAP_MAX_CACHE_KEYS */ + +/** + * The maximum number of cache-entry entries that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_CACHE_ENTRIES +#define COAP_MAX_CACHE_ENTRIES (2U) +#endif /* COAP_MAX_CACHE_ENTRIES */ + +/** + * Maximum number of large body transmissions. + */ +#ifndef COAP_MAX_LG_XMIT +#define COAP_MAX_LG_XMIT 2 +#endif /* COAP_MAX_LG_XMIT */ + +/** + * Maximum number of large body client receives. + */ +#ifndef COAP_MAX_LG_CRCV +#define COAP_MAX_LG_CRCV 2 +#endif /* COAP_MAX_LG_CRCV */ + +/** + * Maximum number of large body server receives. + */ +#ifndef COAP_MAX_LG_SRCV +#define COAP_MAX_LG_SRCV 2 +#endif /* COAP_MAX_LG_SRCV */ + +/** + * Number of notifications that may be sent non-confirmable before a confirmable + * message is sent to detect if observers are alive. The maximum allowed value + * here is @c 255. + */ +#ifndef COAP_OBS_MAX_NON +#define COAP_OBS_MAX_NON 5 +#endif /* COAP_OBS_MAX_NON */ +#if COAP_OBS_MAX_NON > 255 +#error COAP_OBS_MAX_NON is too large +#endif /* COAP_OBS_MAX_NON > 255 */ + +/** + * Number of different confirmable notifications that may fail (i.e. those + * that have hit MAX_RETRANSMIT multiple times) before an observer is removed. + * The maximum value for COAP_OBS_MAX_FAIL is @c 255. + */ +#ifndef COAP_OBS_MAX_FAIL +#define COAP_OBS_MAX_FAIL 1 +#endif /* COAP_OBS_MAX_FAIL */ +#if COAP_OBS_MAX_FAIL > 255 +#error COAP_OBS_MAX_FAIL is too large +#endif /* COAP_OBS_MAX_FAIL > 255 */ + +#ifndef DEBUG +# define DEBUG DEBUG_PRINT +#endif + +#define HAVE_STRNLEN 1 +#define HAVE_SNPRINTF 1 +#define HAVE_STRINGS_H 1 + +/* there is no file-oriented output */ +#define COAP_DEBUG_FD NULL +#define COAP_ERR_FD NULL + +#include "contiki-conf.h" + +#if (defined(PLATFORM) && PLATFORM == PLATFORM_MC1322X) || defined(CONTIKI_TARGET_ECONOTAG) +/* Redbee econotags get a special treatment here: endianness is set + * explicitly, and + */ + +#define BYTE_ORDER UIP_LITTLE_ENDIAN + +#define HAVE_ASSERT_H +#define HAVE_UNISTD_H +#define HAVE_SYS_TYPES_H +#define HAVE_LIMITS_H +#endif /* PLATFORM_MC1322X || CONTIKI_TARGET_ECONOTAG */ + +#if defined(TMOTE_SKY) || defined(CONTIKI_TARGET_SKY) || defined(CONTIKI_TARGET_WISMOTE) +/* Need to set the byte order for TMote Sky explicitely */ + +#define BYTE_ORDER UIP_LITTLE_ENDIAN +#undef COAP_DEFAULT_PDU_SIZE +#undef COAP_RXBUFFER_SIZE +#define COAP_DEFAULT_PDU_SIZE 100 +#define COAP_RXBUFFER_SIZE 100 + +#define COAP_MAX_BLOCK_SZX 2 + +typedef int ssize_t; +typedef void FILE; + +#define HAVE_LIMITS_H 1 +#undef HAVE_ASSERT_H +#define HAVE_VPRINTF 1 +#endif /* defined(TMOTE_SKY) */ + +#ifdef CONTIKI_TARGET_MINIMAL_NET +#undef COAP_DEFAULT_PDU_SIZE +#undef COAP_RXBUFFER_SIZE +#define COAP_DEFAULT_PDU_SIZE 1152 +#define COAP_RXBUFFER_SIZE 1472 +#define HAVE_ASSERT_H 1 +#define HAVE_VPRINTF 1 +#define HAVE_SYS_TYPES_H 1 +#endif /* CONTIKI_TARGET_MINIMAL_NET */ + +#ifdef CONTIKI_TARGET_CC2538DK +#define BYTE_ORDER UIP_LITTLE_ENDIAN +#undef COAP_DEFAULT_PDU_SIZE +#undef COAP_RXBUFFER_SIZE +#define COAP_DEFAULT_PDU_SIZE 100 +#define COAP_RXBUFFER_SIZE 100 + +#undef COAP_MAX_BLOCK_SZX +#define COAP_MAX_BLOCK_SZX 2 + +#define HAVE_LIMITS_H 1 +#endif /* CONTIKI_TARGET_CC2538DK */ + +#ifndef BYTE_ORDER +# ifdef UIP_CONF_BYTE_ORDER +# define BYTE_ORDER UIP_CONF_BYTE_ORDER +# else +# error "UIP_CONF_BYTE_ORDER not defined" +# endif /* UIP_CONF_BYTE_ORDER */ +#endif /* BYTE_ORDER */ + +/* Define assert() as empty directive unless HAVE_ASSERT_H is given. */ +#ifndef HAVE_ASSERT_H +# define assert(x) +#endif + +#define ntohs uip_ntohs + +#include +#define coap_log(fd, ...) printf(__VA_ARGS__) + +#endif /* COAP_CONFIG_H_ */ + diff --git a/examples/espidf-coap-server/components/libcoap/coap_config.h.lwip b/examples/espidf-coap-server/components/libcoap/coap_config.h.lwip new file mode 100644 index 000000000..265e89233 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/coap_config.h.lwip @@ -0,0 +1,42 @@ +/* + * coap_config.h.lwip -- LwIP configuration for libcoap + * + * Copyright (C) 2021-2022 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef COAP_CONFIG_H_ +#define COAP_CONFIG_H_ + +#include +#include +#include /* provide ntohs, htons */ + +#define WITH_LWIP 1 + +#ifndef COAP_CONSTRAINED_STACK +#define COAP_CONSTRAINED_STACK 1 +#endif + +#ifndef COAP_DISABLE_TCP +#define COAP_DISABLE_TCP 1 +#endif + +#define PACKAGE_NAME "libcoap" +#define PACKAGE_VERSION "4.3.1" +#define PACKAGE_STRING "libcoap 4.3.1" + +#define assert(x) LWIP_ASSERT("CoAP assert failed", x) + +/* it's just provided by libc. i hope we don't get too many of those, as + * actually we'd need autotools again to find out what environment we're + * building in */ +#define HAVE_STRNLEN 1 + +#define HAVE_LIMITS_H + +#endif /* COAP_CONFIG_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/coap_config.h.lwip.in b/examples/espidf-coap-server/components/libcoap/coap_config.h.lwip.in new file mode 100644 index 000000000..2fcf3cb66 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/coap_config.h.lwip.in @@ -0,0 +1,42 @@ +/* + * coap_config.h.lwip -- LwIP configuration for libcoap + * + * Copyright (C) 2021-2022 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef COAP_CONFIG_H_ +#define COAP_CONFIG_H_ + +#include +#include +#include /* provide ntohs, htons */ + +#define WITH_LWIP 1 + +#ifndef COAP_CONSTRAINED_STACK +#define COAP_CONSTRAINED_STACK 1 +#endif + +#ifndef COAP_DISABLE_TCP +#define COAP_DISABLE_TCP 1 +#endif + +#define PACKAGE_NAME "@PACKAGE_NAME@" +#define PACKAGE_VERSION "@PACKAGE_VERSION@" +#define PACKAGE_STRING "@PACKAGE_STRING@" + +#define assert(x) LWIP_ASSERT("CoAP assert failed", x) + +/* it's just provided by libc. i hope we don't get too many of those, as + * actually we'd need autotools again to find out what environment we're + * building in */ +#define HAVE_STRNLEN 1 + +#define HAVE_LIMITS_H + +#endif /* COAP_CONFIG_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/coap_config.h.riot b/examples/espidf-coap-server/components/libcoap/coap_config.h.riot new file mode 100644 index 000000000..58f3f2795 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/coap_config.h.riot @@ -0,0 +1,143 @@ +/* + * coap_config.h.riot -- RIOT configuration for libcoap + * + * Copyright (C) 2021-2022 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef COAP_CONFIG_H_RIOT_ +#define COAP_CONFIG_H_RIOT_ + +#define WITH_POSIX 1 + +#ifndef COAP_CONSTRAINED_STACK +#define COAP_CONSTRAINED_STACK 1 +#endif + +#ifndef COAP_DISABLE_TCP +#define COAP_DISABLE_TCP 1 +#endif + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +/* #undef HAVE_GETADDRINFO */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIMITS_H */ + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MEMORY_H */ + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETDB_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the `select' function. */ +/* #undef HAVE_SELECT */ + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strnlen' function. */ +/* #undef HAVE_STRNLEN */ + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_STAT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "libcoap-developers@lists.sourceforge.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libcoap" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "4.3.1" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libcoap 4.3.1" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ + +#endif /* COAP_CONFIG_H_RIOT_ */ diff --git a/examples/espidf-coap-server/components/libcoap/coap_config.h.riot.in b/examples/espidf-coap-server/components/libcoap/coap_config.h.riot.in new file mode 100644 index 000000000..d0fecd625 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/coap_config.h.riot.in @@ -0,0 +1,143 @@ +/* + * coap_config.h.riot -- RIOT configuration for libcoap + * + * Copyright (C) 2021-2022 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef COAP_CONFIG_H_RIOT_ +#define COAP_CONFIG_H_RIOT_ + +#define WITH_POSIX 1 + +#ifndef COAP_CONSTRAINED_STACK +#define COAP_CONSTRAINED_STACK 1 +#endif + +#ifndef COAP_DISABLE_TCP +#define COAP_DISABLE_TCP 1 +#endif + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +/* #undef HAVE_GETADDRINFO */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIMITS_H */ + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MEMORY_H */ + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETDB_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the `select' function. */ +/* #undef HAVE_SELECT */ + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strnlen' function. */ +/* #undef HAVE_STRNLEN */ + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_STAT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "@PACKAGE_STRING@" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ + +#endif /* COAP_CONFIG_H_RIOT_ */ diff --git a/examples/espidf-coap-server/components/libcoap/coap_config.h.windows b/examples/espidf-coap-server/components/libcoap/coap_config.h.windows new file mode 100644 index 000000000..161fe183e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/coap_config.h.windows @@ -0,0 +1,118 @@ +#ifndef COAP_CONFIG_H_ +#define COAP_CONFIG_H_ + +#if defined(_WIN32) + +/* Define to 1 if you have header file. */ +#define HAVE_WS2TCPIP_H 1 + +/* Define to 1 if you have header file. */ +#define HAVE_WINSOCK2_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the `malloc' function. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strnlen' function. */ +#define HAVE_STRNLEN 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if the system has the type `struct cmsghdr'. */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(snprintf) +#define snprintf _snprintf +#endif + +#ifndef COAP_DISABLE_TCP +#define COAP_DISABLE_TCP 0 +#endif + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "libcoap-developers@lists.sourceforge.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libcoap" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libcoap 4.3.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libcoap" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "https://libcoap.net/" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "4.3.1" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define this to 1 for ancillary data on MacOS */ +/* #undef __APPLE_USE_RFC_3542 */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ + +#endif + +#endif /* COAP_CONFIG_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/coap_config.h.windows.in b/examples/espidf-coap-server/components/libcoap/coap_config.h.windows.in new file mode 100644 index 000000000..84ef458cf --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/coap_config.h.windows.in @@ -0,0 +1,118 @@ +#ifndef COAP_CONFIG_H_ +#define COAP_CONFIG_H_ + +#if defined(_WIN32) + +/* Define to 1 if you have header file. */ +#define HAVE_WS2TCPIP_H 1 + +/* Define to 1 if you have header file. */ +#define HAVE_WINSOCK2_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the `malloc' function. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strnlen' function. */ +#define HAVE_STRNLEN 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if the system has the type `struct cmsghdr'. */ +#define HAVE_STRUCT_CMSGHDR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(snprintf) +#define snprintf _snprintf +#endif + +#ifndef COAP_DISABLE_TCP +#define COAP_DISABLE_TCP 0 +#endif + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "@PACKAGE_STRING@" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "@PACKAGE_TARNAME@" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "@PACKAGE_URL@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define this to 1 for ancillary data on MacOS */ +/* #undef __APPLE_USE_RFC_3542 */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ + +#endif + +#endif /* COAP_CONFIG_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/configure.ac b/examples/espidf-coap-server/components/libcoap/configure.ac new file mode 100644 index 000000000..5c46cc6ea --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/configure.ac @@ -0,0 +1,1106 @@ +# configure.ac for the libcoap package +# +# Copyright (C) 2010-2022 Olaf Bergmann +# Copyright (C) 2015-2018 Carsten Schoenert +# Copyright (C) 2018-2022 Jon Shallow +# +# SPDX-License-Identifier: BSD-2-Clause +# +# This file is part of the CoAP library libcoap. Please see README for terms +# of use. +# +# Please run 'autogen.sh' to let autoconf produce a configure script. + +# Define the libcoap software version here. Note! The libtool versions are +# defined later. +m4_define([libcoap_major_version], [4]) +m4_define([libcoap_minor_version], [3]) +m4_define([libcoap_micro_version], [1]) + +# define an appending release state if needed, for example for pre-releases +# like 'alpha' or 'rc1', for a full release keep the value empty! +m4_define([libcoap_release_state], []) + +# concatenate the full libcoap version string +m4_define([libcoap_version], [m4_format([%s.%s.%s%s], libcoap_major_version, libcoap_minor_version, libcoap_micro_version, libcoap_release_state)]) + +AC_INIT([libcoap], [libcoap_version], [libcoap-developers@lists.sourceforge.net], [libcoap], [https://libcoap.net/]) +AC_PREREQ([2.64]) +AM_INIT_AUTOMAKE([1.10 -Wall no-define no-dist-gzip dist-bzip2]) +PKG_PROG_PKG_CONFIG([0.20]) +AM_SILENT_RULES([yes]) +AC_HEADER_ASSERT + +# Generate one configuration header file for building the library itself with +# an auto generated template. We need later a second one +# (include/coap$LIBCOAP_API_VERSION/libcoap.h) that will be installed alongside the library. +AC_CONFIG_HEADERS([coap_config.h]) + +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_SED +AC_CONFIG_MACRO_DIR([m4]) +m4_pattern_allow([AM_PROG_AR]) +AM_PROG_AR +AC_PROG_LN_S +AC_PROG_MKDIR_P + +AC_C_BIGENDIAN + +# enable the automatically build of shared and static libraries +LT_INIT([shared static]) + +# Setting the libtool versioning +################################################################################### +# # +# To set the version of the library, libtool provides the -version-info # +# parameter, which accepts three numbers, separated by colons, that are called # +# respectively, current, revision and age. Both their name and their behavior, # +# nowadays, have to be considered fully arbitrary, as the explanation provided # +# in the official documentation is confusing to say the least, and can be, in # +# some cases, considered completely wrong. # +# https://autotools.io/libtool/version.html # +# # +################################################################################### +# +# How to work with the libtool versioning? +# +# Follow the following steps from top to bottom. This means always start at point 1 +# if you plan to make a release and change the values. +# Every new library starts with a version 'current' (short 'c') = 0 +# 'revision' (short 'r') = 0 +# 'age' (short 'a') = 0 +# +# Update the libtool versioning only after the release of a public release of libcoap. +# Go through the following checklist from top to bottom and check your needs, following +# the reminded changes if you can say "Yes" for specific check. +# +# 1. Only existing code has changed, no functional changes +# If the library source code has changed but *no* new symbols were added at all +# since the last update, then increment revision (c:r:a becomes c:r+1:a). +# This is usually happen if the existing source of a function was changed for +# bug fixing e.g. +# +# --> Increase the 'LT_LIBCOAP_REVISION' value with *every* new software release +# within one release cycle. +# +# 2. Interfaces were added, functions have changed or are removed +# If any interfaces [exported functions or data] have been added, got internal +# changes that implies a different behavior or removed and by this the visible +# symbols have changed since the last update, increment current, and set +# revision to 0 (c:r:a becomes c+1:r=0:a). +# +# --> Increase the 'LT_LIBCOAP_CURRENT' value whenever as an interface has been added +# or removed. This implies also a API change! You mostly have to change the +# 'libcoap_major_version' or at least 'libcoap_minor_version' then too! +# --> Set 'LT_LIBCOAP_REVISION' to 0. +# +# 3. Interfaces were added but none removed or changed +# If any interfaces have been added since the last public release and non of the +# existing interfaces were removed and existing interfaces have not changed internal +# functionality then the new library is backward compatible. Existing binaries can +# use the new library the same than as the existing old library without loosing +# existing functionality or breakage. +# Increase age by 1 (c:r:a becomes c:r:a+1). +# +# --> Increase the 'LT_LIBCOAP_AGE' value only if the changes made to the ABI are +# backward compatible. +# +# 4. Interfaces were removed or have functional changes +# If any interfaces within the library have been removed since the last public +# release or got some internal changes that let the interface act different than +# before, then set age to 0. The library isn't backwards compatible. +# +# --> Set 'LT_LIBCOAP_AGE' to 0. + +LT_LIBCOAP_CURRENT=3 +LT_LIBCOAP_REVISION=0 +LT_LIBCOAP_AGE=0 +LIBCOAP_SO_VERSION=$LT_LIBCOAP_CURRENT.$LT_LIBCOAP_REVISION.$LT_LIBCOAP_AGE + +# Announce the libtool version +AC_SUBST(LT_LIBCOAP_CURRENT) +AC_SUBST(LT_LIBCOAP_REVISION) +AC_SUBST(LT_LIBCOAP_AGE) +AC_SUBST(LIBCOAP_SO_VERSION) + +# Defining the API Version +LIBCOAP_API_VERSION=3 +AC_SUBST(LIBCOAP_API_VERSION) + +# Define a numeric version string +m4_define([version_number], + [m4_format([%u%03u%03u], + libcoap_major_version, + libcoap_minor_version, + libcoap_micro_version)]) +LIBCOAP_VERSION=version_number +AC_SUBST(LIBCOAP_VERSION) + +# Adding some default warning options for code QS +# see https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html +# and http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html +WARNING_CFLAGS="\ +-pedantic \ +-Wall \ +-Wcast-qual \ +-Wextra \ +-Wformat-security \ +-Winline \ +-Wmissing-declarations \ +-Wmissing-prototypes \ +-Wnested-externs \ +-Wpointer-arith \ +-Wshadow \ +-Wstrict-prototypes \ +-Wswitch-default \ +-Wswitch-enum \ +-Wunused \ +-Wwrite-strings \ +" + +# check whether or not the compiler supports -Wlogical-op (clang does not...) +AX_CHECK_COMPILE_FLAG([-Wlogical-op], [WARNING_CFLAGS="$WARNING_CFLAGS -Wlogical-op"],,[-Werror]) +AX_CHECK_COMPILE_FLAG([-fdiagnostics-color], [CFLAGS="$CFLAGS -fdiagnostics-color"],,[-Werror]) +AX_CHECK_COMPILE_FLAG([-Wunused-result], [WARNING_CFLAGS="$WARNING_CFLAGS -Wunused-result"]) + +AC_SUBST([WARNING_CFLAGS]) + +AX_CHECK_LINK_FLAG([-Wl,--version-script=${srcdir}/libcoap-${LIBCOAP_API_VERSION}.map], + [libcoap_SYMBOLS="-Wl,--version-script=\$(srcdir)/libcoap-\$(LIBCOAP_API_VERSION).map"], + [libcoap_SYMBOLS="-export-symbols \$(top_builddir)/libcoap-\$(LIBCOAP_API_VERSION).sym"]) + +AC_SUBST(libcoap_SYMBOLS) + +# configure options +# __documentation__ + +AC_ARG_ENABLE([documentation], + [AS_HELP_STRING([--enable-documentation], + [Enable building all the documentation [default=yes]])], + [build_documentation="$enableval"], + [build_documentation="yes"]) + +AM_CONDITIONAL(BUILD_DOCUMENTATION, [test "x$build_documentation" = "xyes"]) + +doxygen_version_required=1.7.0 +dot_version_required=2.26.0 + +AC_ARG_ENABLE([doxygen], + [AS_HELP_STRING([--enable-doxygen], + [Enable building the doxygen documentation [default=yes]])], + [build_doxygen="$enableval"], + [build_doxygen="yes"]) + +if test -z "$enable_doxygen"; then + if test "x$enable_documentation" = "xno"; then + build_doxygen="no" + fi +fi + +if test "x$build_doxygen" = "xyes"; then + # Check for doxygen + AC_PATH_PROGS([DOXYGEN], [doxygen]) + if test -z "$DOXYGEN"; then + if test "x$build_doxygen" = "xyes"; then + AC_MSG_WARN([==> You want to build the doxygen documentation but doxygen was not found!]) + AC_MSG_ERROR([==> Install the package that contains doxygen or disable the doxygen documentation using '--disable-doxygen'.]) + fi + else + AC_MSG_CHECKING([for compatible doxygen version (>= $doxygen_version_required)]) + doxygen_version=`$DOXYGEN --version` + AS_VERSION_COMPARE([$doxygen_version], + [$doxygen_version_required], + [AC_MSG_RESULT([no]) + DOXYGEN=""], + [AC_MSG_RESULT([yes $doxygen_version])], + [AC_MSG_RESULT([yes $doxygen_version])]) + if test "x$DOXYGEN" = "x" -a "x$build_doxygen" = "xyes"; then + AC_MSG_WARN([==> Doxygen $doxygen_version too old. Doxygen >= $doxygen_version_required required for documentation build.]) + AC_MSG_ERROR([==> Install required doxygen version or disable the doxygen documentation using '--disable-doxygen'.]) + else + # we found doxygen and the version is valid + # now checking dot (needed for graphics) + AC_PATH_PROG([DOT], [dot]) + if test "x$DOT" = "x"; then + AC_MSG_WARN([==> dot not found - continuing without DOT support]) + AC_MSG_WARN([==> The libcoap html documentation will be build without DOT graphics!]) + HAVE_DOT="NO" + USE_CALL_GRAPH="NO" + else + AC_MSG_CHECKING([for compatible dot version (>= $dot_version_required)]) + case $host in + *-freebsd1*) + # csh and tcsh have a different output redirection than more recent shells + # cmd >& file # Redirect both stdout and stderr to file. + # cmd >>& file # Append both stdout and stderr to file. + # cmd1 | cmd2 # pipe stdout to cmd2 + # cmd1 |& cmd2 # pipe stdout and stderr to cmd2 + # Using an explicit call with the default always available C-shell on FreeBSD, + # the user may have installed another shell from a port which we don't know here + dot_version=`export DOT=$DOT && csh -c '$DOT -V |& cut -f5 -d" "'` + ;; + + *) + dot_version=`$DOT -V 2>&1 | cut -f5 -d" "` + ;; + + esac + AS_VERSION_COMPARE([$dot_version], + [$dot_version_required], + [AC_MSG_RESULT([no]) + DOT=""], + [AC_MSG_RESULT([yes $dot_version])], + [AC_MSG_RESULT([yes $dot_version])]) + if test "x$DOT" = "x" -a "x$build_doxygen" = "xyes"; then + AC_MSG_WARN([==> Graphviz dot $dot_version too old. Graphviz >= $dot_version_required required for doxygen build.]) + AC_MSG_ERROR([==> Install required graphviz version or disable the doxygen documentation using '--disable-doxygen'.]) + fi + # we found dot and the version is valid + HAVE_DOT="YES" + # let doxygen create caller graphics + # see http://www.stack.nl/~dimitri/doxygen/manual/config.html#cfg_call_graph + USE_CALL_GRAPH="YES" + # exporting the tests to doc/Doxygen(.in) + AC_SUBST(HAVE_DOT) + AC_SUBST(USE_CALL_GRAPH) + fi + fi + fi +fi +AM_CONDITIONAL(BUILD_DOXYGEN, [test "x$build_doxygen" = "xyes"]) + +AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"]) +AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile])]) + +# __manpages__ + +AC_ARG_ENABLE([manpages], + [AS_HELP_STRING([--enable-manpages], + [Enable building the manpages [default=yes]])], + [build_manpages="$enableval"], + [build_manpages="yes"]) + +if test -z "$enable_manpages"; then + if test "x$enable_documentation" = "xno"; then + build_manpages="no" + fi +fi + +if test "x$build_manpages" = "xyes"; then + AC_ARG_VAR([A2X], [a2x command]) + AC_PATH_PROG([A2X], [a2x]) + if test "x$A2X" = "x"; then + AC_MSG_WARN([==> You want to build the manpages, but a2x was not found!]) + AC_MSG_ERROR([==> Install the package that contains a2x (mostly asciidoc) or disable the build of the manpages using '--disable-manpages'.]) + build_manpages="no" + else + AX_CHECK_A2X_TO_MANPAGE([], [ + AC_MSG_RESULT([no]) + AC_MSG_WARN([==> You want to build the manpages with a2x, but manpage formatting does not work!]) + AC_MSG_ERROR([==> Install the packages that contains the docbook DTD and XSL stylesheets (presumably docbook, docbook-xml) or disable the build of the manpages using '--disable-manpages'.]) + build_manpages="no" + ]) + fi +fi +AM_CONDITIONAL(BUILD_MANPAGES, [test "x$build_manpages" = "xyes"]) + +# configure options +# __dtls__ +# The Datagram Transport Layer Security (DTLS) feature needs cryptography +# functions. +# We currently support the GnuTLS and OpenSSL library. The user can preselect +# the cryptography library that should be used by adding '--with-gnutls' or +# '--with-openssl'. +# If the user isn't using a selection we first search for GnuTLS and fallback +# to OpenSSL if the GnuTLS library couldn't be found. + +gnutls_version_required=3.3.0 +openssl_version_required=1.1.0 +mbedtls_version_required=2.7.10 +tinydtls_version_required=0.8.6 + +AC_ARG_ENABLE([dtls], + [AS_HELP_STRING([--enable-dtls], + [Enable building with DTLS support [default=yes]])], + [build_dtls="$enableval"], + [build_dtls="yes"]) + +AC_ARG_WITH([gnutls], + [AS_HELP_STRING([--with-gnutls], + [Use GnuTLS for DTLS functions])], + [with_gnutls="$withval"], + [with_gnutls="no"]) + +AC_ARG_WITH([openssl], + [AS_HELP_STRING([--with-openssl], + [Use OpenSSL for DTLS functions])], + [with_openssl="$withval"], + [with_openssl="no"]) + +AC_ARG_WITH([mbedtls], + [AS_HELP_STRING([--with-mbedtls], + [Use Mbed TLS for DTLS functions])], + [with_mbedtls="$withval"], + [with_mbedtls="no"]) + +AC_ARG_WITH([tinydtls], + [AS_HELP_STRING([--with-tinydtls], + [Use TinyDTLS for DTLS functions])], + [with_tinydtls="$withval"], + [with_tinydtls="no"]) + +AC_ARG_WITH([submodule-tinydtls], + [AS_HELP_STRING([--with-submodule-tinydtls], + [Use the TinyDTLS provided in the git submodule over the system-provided version [default=fallback to submodule if --with-tinydtls is explicitly set and no system-provided version was found])])], + [with_submodule_tinydtls="$withval"], + [with_submodule_tinydtls="explicit_fallback"]) + +if test "x$with_gnutls" = "xyes" -o "x$with_openssl" = "xyes" -o "x$with_mbedtls" = "xyes" -o "x$with_tinydtls" = "xyes"; then + if test "x$build_dtls" = "xno"; then + # Give an advice that '--with_gnutls', '--with_openssl', '--with-mbedtls' or '--with-tinydtls' was used but + # DTLS support isn't configured. + AC_MSG_WARN([==> Using the configure options '--with-gnutls', '--with-openssl', '--with-mbedtls' or '--with-tinydtls' without '--enable-dtls' is useless and will be ignored.]) + fi +fi +if test "x$with_submodule_tinydtls" = "xyes"; then + if test "x$with_tinydtls" = "xno"; then + # Give an advice that '--with-submodule-tinydtls' is useless if tinydtls is not also enabled. + AC_MSG_WARN([==> Using the configure option '--with-submodule-tinydtls' without '--with-tinydtls' is useless and it will be ignored.]) + fi +fi + +# O.K. the user hasn't de-selected DTLS +if test "x$build_dtls" = "xyes"; then + # The user can't select multiple crypto libraries. + TLSCOUNT=0 + if test "x$with_gnutls" = "xyes"; then + TLSCOUNT=`expr $TLSCOUNT + 1` + fi + if test "x$with_openssl" = "xyes"; then + TLSCOUNT=`expr $TLSCOUNT + 1` + fi + if test "x$with_mbedtls" = "xyes"; then + TLSCOUNT=`expr $TLSCOUNT + 1` + fi + if test "x$with_tinydtls" = "xyes"; then + TLSCOUNT=`expr $TLSCOUNT + 1` + fi + if test "$TLSCOUNT" -gt 1; then + AC_MSG_ERROR([==> You can't use more than 1 of the options '--with-gnutls', '--with-openssl', '--with-mbedtls' or '--with-tinydtls' at the same time while '--enable-dtls' is selected! + ==> Please note, the option '--enable-dtls' is turned on by default if not explicitly disabled!]) + fi + + # Check for all possible usable and supported SSL crypto libraries + # GnuTLS + PKG_CHECK_MODULES([GnuTLS], + [gnutls], + [have_gnutls="yes"], + [have_gnutls="no"]) + + # OpenSSL + PKG_CHECK_MODULES([OpenSSL], + [openssl], + [have_openssl="yes"], + [have_openssl="no"]) + + # Mbed TLS [does not have mbedtls.pc pkg-config file] + AC_CHECK_LIB(mbedtls, mbedtls_version_get_string, + [have_mbedtls="yes"; MbedTLS_CFLAGS="" ; MbedTLS_LIBS="-lmbedtls -lmbedcrypto -lmbedx509"], + [have_mbedtls="no"], -lmbedx509 -lmbedcrypto) + if test "x$have_mbedtls" = "xyes"; then + if test "x$cross_compiling" = "xyes" ; then + # Have no option but to do this + mbedtls_version=$mbedtls_version_required + else + # Get actual library version + AC_LANG_PUSH(C) + local_MbedTLS_save_LIBS=$LIBS + LIBS="$MbedTLS_LIBS $LIBS" + AC_LINK_IFELSE([dnl + AC_LANG_SOURCE( + [[#include + #include + int main () { + char str[20]; + mbedtls_version_get_string(str); + fprintf(stdout,"%s\n",str); + return 0; + }]])], + [mbedtls_version=$(./conftest$EXEEXT)], + [AC_MSG_WARN(Failed to determine Mbed TLS version) + have_mbedtls=no]) + LIBS=$local_MbedTLS_save_LIBS + AC_LANG_POP(C) + fi + fi + + if test "${TinyDTLS_CFLAGS+set}" = "set"; then + tinydtls_cflags_overridden="yes" + fi + if test "${TinyDTLS_LIBS+set}" = "set"; then + tinydtls_libs_overridden="yes" + fi + # TinyDTLS + PKG_CHECK_MODULES([TinyDTLS], + [tinydtls], + [have_tinydtls="yes"], + [have_tinydtls="no"]) + + # TBD ? + + # The user wants to use explicit GnuTLS if '--with-gnutls' was set. + if test "x$with_gnutls" = "xyes"; then + # Some more sanity checking. + if test "x$have_gnutls" != "xyes"; then + AC_MSG_ERROR([==> You want to build libcoap with DTLS support by the GnuTLS library but pkg-config file 'gnutls.pc' could not be found! + Install the package(s) that contains the development files for GnuTLS, + or select a different TLS library or disable the DTLS support using '--disable-dtls'.]) + fi + AC_MSG_NOTICE([The use of GnuTLS was explicitly requested with configure option '--with-gnutls'!]) + + # check for valid GnuTLS version + gnutls_version=`$PKG_CONFIG --modversion gnutls` + AX_CHECK_GNUTLS_VERSION + have_openssl="no" # don't confuse AC_MSG_RESULT at the end of the script + have_mbedtls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_tinydtls="no" # don't confuse AC_MSG_RESULT at the end of the script + fi + + # The user wants to use explicit OpenSSL if '--with-openssl was set'. + if test "x$with_openssl" = "xyes"; then + # Some more sanity checking. + if test "x$have_openssl" != "xyes"; then + AC_MSG_ERROR([==> You want to build libcoap with DTLS support by the OpenSSL library but pkg-config file 'openssl.pc' could not be found! + Install the package(s) that contains the development files for OpenSSL, + or select a different TLS library or disable the DTLS support using '--disable-dtls'.]) + fi + AC_MSG_NOTICE([The use of OpenSSL was explicitly requested with configure option '--with-openssl'!]) + + # check for valid OpenSSL version + openssl_version=`$PKG_CONFIG --modversion openssl` + AX_CHECK_OPENSSL_VERSION + have_gnutls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_mbedtls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_tinydtls="no" # don't confuse AC_MSG_RESULT at the end of the script + fi + + # The user wants to use explicit Mbed TLS if '--with-mbedtls was set'. + if test "x$with_mbedtls" = "xyes"; then + # Some more sanity checking. + if test "x$have_mbedtls" != "xyes"; then + AC_MSG_ERROR([==> You want to build libcoap with DTLS support by the Mbed TLS library but library 'mbedtls' could not be found! + Install the package(s) that contains the development files for Mbed TLS, + or select a different TLS library or disable the DTLS support using '--disable-dtls'.]) + fi + AC_MSG_NOTICE([The use of Mbed TLS was explicitly requested with configure option '--with-mbedtls'!]) + + # check for valid Mbed TLS version (mbedtls.pc does not exist - hmm) + # mbedtls_version determined previously + AX_CHECK_MBEDTLS_VERSION + have_gnutls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_openssl="no" # don't confuse AC_MSG_RESULT at the end of the script + have_tinydtls="no" # don't confuse AC_MSG_RESULT at the end of the script + fi + + # The user wants to use explicit TinyDTLS if '--with-tinydtls was set'. + if test "x$with_tinydtls" = "xyes" ; then + AC_MSG_NOTICE([The use of TinyDTLS was explicitly requested with configure option '--with-tinydtls'!]) + if [ test "x$have_tinydtls" = "xno" ] && [ test "x$with_submodule_tinydtls" = "xexplicit_fallback" ] || [ test "x$with_submodule_tinydtls" = "xyes" ]; then + AC_MSG_NOTICE([Using TinyDTLS submodule over system-provided version because either "--with-submodule-tinydtls" was set or no system-provided TinyDTLS was found.]) + if test -e "$srcdir/ext/tinydtls/dtls.h"; then + AC_CONFIG_SUBDIRS([ext/tinydtls]) + if test "x$enable_shared" = "xyes"; then + auto_TinyDTLS_LIBS="-L\$(top_builddir)/ext/tinydtls -ltinydtls" + else + # Needed as TinyDTLS compiling does not recognize --disable-shared + # and still builds libtinydtls.so which gets linked in otherwise + auto_TinyDTLS_LIBS="-L\$(top_builddir)/ext/tinydtls -l:libtinydtls.a" + fi + have_submodule_tinydtls="yes" + + auto_TinyDTLS_CFLAGS="-I \$(top_srcdir)/ext -I \$(top_srcdir)/ext/tinydtls" + + if test "x$tinydtls_cflags_overridden" != "xyes"; then + TinyDTLS_CFLAGS="$auto_TinyDTLS_CFLAGS" + fi + if test "x$tinydtls_libs_overridden" != "xyes"; then + TinyDTLS_LIBS="$auto_TinyDTLS_LIBS" + fi + else + AC_MSG_ERROR([==> You want to build libcoap with DTLS support using the TinyDTLS submodule library but no suitable version could be found! + Check whether you have updated the TinyDTLS git submodule, use the system-provided version if available (set '--with-submodule-tinydtls=no'), + select a different TLS library or disable the DTLS support using '--disable-dtls'.]) + have_tinydtls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_submodule_tinydtls="no" # don't confuse AC_MSG_RESULT at the end of the script + fi + elif test "x$have_tinydtls" = "xyes"; then + AC_MSG_NOTICE([Using system-provided TinyDTLS]) + tinydtls_version=`$PKG_CONFIG --modversion tinydtls` + AX_CHECK_TINYDTLS_VERSION + have_gnutls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_mbedtls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_openssl="no" # don't confuse AC_MSG_RESULT at the end of the script + else + AC_MSG_ERROR([==> You want to build libcoap with DTLS support using the TinyDTLS library but no suitable version could be found! + Use the submodule TinyDTLS version (set '--with-submodule-tinydtls=yes' and update the git submodule), + ensure that you have a system-provided version of TinyDTLS that can be found using pkg-config (older versions can not), + select a different TLS library or disable the DTLS support using '--disable-dtls'.]) + have_tinydtls="no" # don't confuse AC_MSG_RESULT at the end of the script + fi + + have_gnutls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_openssl="no" # don't confuse AC_MSG_RESULT at the end of the script + have_mbedtls="no" # don't confuse AC_MSG_RESULT at the end of the script + fi + + if test "$TLSCOUNT" -eq 0; then + # The user hasn't requested the use of a specific cryptography library + # we try first GnuTLS for usability ... + if test "x$have_gnutls" = "xyes"; then + gnutls_version=`$PKG_CONFIG --modversion gnutls` + AX_CHECK_GNUTLS_VERSION + AC_MSG_NOTICE([Using auto selected library GnuTLS for DTLS support!]) + with_gnutls_auto="yes" + have_openssl="no" # don't confuse AC_MSG_RESULT at the end of the script + have_mbedtls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_tinydtls="no" # don't confuse AC_MSG_RESULT at the end of the script + + # ... and if not found check OpenSSL is suitable. + elif test "x$have_openssl" = "xyes"; then + openssl_version=`$PKG_CONFIG --modversion openssl` + AX_CHECK_OPENSSL_VERSION + AC_MSG_NOTICE([Using auto selected library OpenSSL for DTLS support!]) + with_openssl_auto="yes" + have_gnutls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_mbedtls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_tinydtls="no" # don't confuse AC_MSG_RESULT at the end of the script + + # ... and if not found check Mbed TLS is suitable. + elif test "x$have_mbedtls" = "xyes"; then + # Mbed TLS [does not have mbedtls.pc pkg-config file] + # mbedtls_version determined previously + AX_CHECK_MBEDTLS_VERSION + AC_MSG_NOTICE([Using auto selected library Mbed TLS for DTLS support!]) + with_mbedtls_auto="yes" + have_gnutls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_openssl="no" # don't confuse AC_MSG_RESULT at the end of the script + have_tinydtls="no" # don't confuse AC_MSG_RESULT at the end of the script + + elif [ test "x$with_tinydtls" = "xyes" ] && [ test "x$have_tinydtls" = "xyes" ]; then + AC_MSG_NOTICE([Using auto selected library TinyDTLS for DTLS support!]) + tinydtls_version=`$PKG_CONFIG --modversion tinydtls` + AX_CHECK_TINYDTLS_VERSION + with_tinydtls_auto="yes" + have_gnutls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_mbedtls="no" # don't confuse AC_MSG_RESULT at the end of the script + have_openssl="no" # don't confuse AC_MSG_RESULT at the end of the script + + + # Note that the TinyDTLS submodule is used only when explicitly requested. + # Giving out an error message if we haven't found at least one crypto library. + else + AC_MSG_ERROR([==> Option '--enable-dtls' is set but none of the needed cryptography libraries GnuTLS, OpenSSL, Mbed TLS or TinyDTLS could be found! + Install at least one of the package(s) that contains the development files for GnuTLS (>= $gnutls_version_required), OpenSSL(>= $openssl_version_required), Mbed TLS(>= $mbedtls_version_required), or TinyDTLS(>= $tinydtls_version_required) + or disable the DTLS support using '--disable-dtls'.]) + fi + fi + + # Saving the DTLS related Compiler flags. + if test "x$with_gnutls" = "xyes" -o "x$with_gnutls_auto" = "xyes"; then + DTLS_CFLAGS="$GnuTLS_CFLAGS" + DTLS_LIBS="$GnuTLS_LIBS" + AC_DEFINE(HAVE_LIBGNUTLS, [1], [Define if the system has libgnutls28]) + fi + if test "x$with_openssl" = "xyes" -o "x$with_openssl_auto" = "xyes"; then + DTLS_CFLAGS="$OpenSSL_CFLAGS" + DTLS_LIBS="$OpenSSL_LIBS" + AC_DEFINE(HAVE_OPENSSL, [1], [Define if the system has libssl1.1]) + fi + if test "x$with_mbedtls" = "xyes" -o "x$with_mbedtls_auto" = "xyes"; then + DTLS_CFLAGS="$MbedTLS_CFLAGS" + DTLS_LIBS="$MbedTLS_LIBS" + AC_DEFINE(HAVE_MBEDTLS, [1], [Define if the system has libmbedtls2.7.10]) + fi + if test "x$with_tinydtls" = "xyes" -o "x$with_tinydtls_auto" = "xyes"; then + DTLS_CFLAGS="$TinyDTLS_CFLAGS" + DTLS_LIBS="$TinyDTLS_LIBS" + AC_DEFINE(HAVE_LIBTINYDTLS, [1], [Define if the system has libtinydtls]) + fi + AC_SUBST(DTLS_CFLAGS) + AC_SUBST(DTLS_LIBS) +fi + +# Define the Library name extension for the TLS the library was linked against +if test "x$with_openssl" = "xyes" -o "x$with_openssl_auto" = "xyes"; then + LIBCOAP_DTLS_LIB_EXTENSION_NAME=-openssl +elif test "x$with_gnutls" = "xyes" -o "x$with_gnutls_auto" = "xyes"; then + LIBCOAP_DTLS_LIB_EXTENSION_NAME=-gnutls +elif test "x$with_mbedtls" = "xyes" -o "x$with_mbedtls_auto" = "xyes"; then + LIBCOAP_DTLS_LIB_EXTENSION_NAME=-mbedtls +elif test "x$with_tinydtls" = "xyes"; then + LIBCOAP_DTLS_LIB_EXTENSION_NAME=-tinydtls +else + LIBCOAP_DTLS_LIB_EXTENSION_NAME=-notls +fi + +LIBCOAP_NAME_SUFFIX="$LIBCOAP_API_VERSION$LIBCOAP_DTLS_LIB_EXTENSION_NAME" + +AC_SUBST(LIBCOAP_NAME_SUFFIX) +AC_SUBST(LIBCOAP_DTLS_LIB_EXTENSION_NAME) +AC_SUBST([DOLLAR_SIGN],[$]) + +# configure options +# __tests__ +AC_ARG_ENABLE([tests], + [AS_HELP_STRING([--enable-tests], + [Enable building the binary testsuite. Requires --enable-static [default=no]])], + [build_tests="$enableval"], + [build_tests="no"]) + +if test "x$build_tests" = "xyes"; then + PKG_CHECK_MODULES([CUNIT], + [cunit], + [have_cunit=yes + AC_DEFINE(HAVE_LIBCUNIT, [1], [Define if the system has libcunit])], + [have_cunit=no + AC_MSG_WARN([==> You want to build the testing binary but the pkg-config file cunit.pc could not be found or installed CUnit version is too old!]) + AC_MSG_ERROR([==> Install the package(s) that contains the development files for CUnit or disable the testing binary using '--disable-tests'.]) + ]) + if test "x$enable_static" = "xno"; then + enable_static=yes + AC_MSG_WARN([--enable-tests requires --enable-static which is now enabled.]) + fi +fi +AM_CONDITIONAL(HAVE_CUNIT, [test "x$CUNIT_LIBS" != "x"]) + +# configure options +# __examples__ +AC_ARG_ENABLE([examples], + [AS_HELP_STRING([--enable-examples], + [Enable building the example binaries [default=yes]])], + [build_examples="$enableval"], + [build_examples="yes"]) + +AM_CONDITIONAL(BUILD_EXAMPLES, [test "x$build_examples" = "xyes"]) + +# configure options +# __examples-source +AC_ARG_ENABLE([examples-source], + [AS_HELP_STRING([--enable-examples-source], + [Enable installing example source to DATAROOTDIR/libcoap/examples [default=yes]])], + [build_examples_source="$enableval"], + [build_examples_source="yes"]) + +AM_CONDITIONAL(BUILD_EXAMPLES_SOURCE, [test "x$build_examples_source" = "xyes"]) + +# configure options +# __gcov__ +AC_ARG_ENABLE([gcov], + [AS_HELP_STRING([--enable-gcov], + [Enable building with gcov test coverage support [default=no]])], + [build_gcov="$enableval"], + [build_gcov="no" + AC_MSG_WARN([gcov is disabled]) + ]) + +if test "x$build_gcov" = "xyes"; then + if test "x$GCC" != "xyes"; then + AC_MSG_ERROR([Currently, gcov is assumed to work with GCC-compatible compilers only.]) + else + AX_CHECK_COMPILE_FLAG([-fprofile-arcs], [CFLAGS="$CFLAGS -fprofile-arcs"]) + AX_CHECK_COMPILE_FLAG([-ftest-coverage], [CFLAGS="$CFLAGS -ftest-coverage"]) + # FIXME: clang complains about '--coverage' + AX_CHECK_COMPILE_FLAG([--coverage], [CFLAGS="$CFLAGS --coverage -O0" LDFLAGS="$LDFLAGS --coverage"]) + fi +fi + +# configure options +# __license-install__ +AC_ARG_ENABLE([license-install], + [AS_HELP_STRING([--enable-license-install], + [Enable installing LICENSE to DOCDIR [default=yes]])], + [build_license_install="$enableval"], + [build_license_install="yes"]) + +AM_CONDITIONAL(BUILD_LICENSE_INSTALL, [test "x$build_license_install" = "xyes"]) + +# configure options +# __tcp__ +AC_ARG_ENABLE([tcp], + [AS_HELP_STRING([--enable-tcp], + [Enable building with TCP support [default=yes]])], + [build_tcp="$enableval"], + [build_tcp="yes"]) + +AC_DEFINE(COAP_DISABLE_TCP, [0], [Define to 1 to build without TCP support.]) +AS_IF([test "x$build_tcp" != "xyes"], [AC_DEFINE(COAP_DISABLE_TCP, [1])]) +AC_SUBST(COAP_DISABLE_TCP) + +# configure options +# __async__ +AC_ARG_ENABLE([async], + [AS_HELP_STRING([--enable-async], + [Enable building with support for separate responses [default=yes]])], + [build_async="$enableval"], + [build_async="yes"]) + +AS_IF([test "x$build_async" != "xyes"], + [AC_DEFINE(WITHOUT_ASYNC, [1], [Define to build without support for separate responses.])]) + +# configure options +# __add_default_names__ +AC_ARG_ENABLE([add-default-names], + [AS_HELP_STRING([--enable-add-default-names], + [Enable adding libraries / examples with default names [default=yes]])], + [build_add_default_names="$enableval"], + [build_add_default_names="yes"]) + +AM_CONDITIONAL(BUILD_ADD_DEFAULT_NAMES, [test "x$build_add_default_names" = "xyes"]) + +# end configure options +####################### + +########################################### +# from configure options independent checks + +# Check for (ex)ctags binary +# The needed ctags binary name differs on FreeBSD and Linux, on Linux +# systems we search for 'ctags', on FreeBSD for 'exctags' +case $host in + # FreeBSD has exctags from the ctags port + *-freebsd1*) + AC_ARG_VAR([CTAGS_PROG],[the 'exctags' program to use for make target 'update-map-file']) + AC_PATH_PROG([CTAGS_PROG],[exctags]) + ;; + + *) + # Linux distributions have exuberant-ctags + AC_ARG_VAR([CTAGS_PROG],[the 'ctags' program to use for make target 'update-map-file']) + AC_PATH_PROG([CTAGS_PROG],[ctags]) + ;; + +esac + +if test "x$CTAGS_PROG" = "x"; then + AC_MSG_NOTICE([==> Note: '(ex)ctags' command not found!]) + AC_MSG_WARN([==> Without ctags you will be unable to run the target 'update-map-file'!]) + AC_MSG_WARN([==> This is no problem if you just want to build the library libcoap.]) +else + if test "`$CTAGS_PROG --help | grep '\---kinds'`" = ""; then + AC_MSG_NOTICE([==> Note: Your ctags binary does not support '--c-kinds'!]) + AC_MSG_NOTICE([==> Most likely, you are using the GNU Emacs ctag and not exuberant ctag.]) + AC_MSG_WARN([==> This option is required for the target 'update-map-file'.]) + AC_MSG_WARN([==> which is not a problem if you just want to build the library libcoap.]) + fi +fi + +# Checks for header files. +AC_CHECK_HEADERS([assert.h arpa/inet.h limits.h netdb.h netinet/in.h \ + pthread.h \ + stdlib.h string.h strings.h sys/socket.h sys/time.h \ + time.h unistd.h sys/unistd.h syslog.h sys/ioctl.h net/if.h]) + +# For epoll, need two headers (sys/epoll.h sys/timerfd.h), but set up one #define +AC_CHECK_HEADER([sys/epoll.h]) +AC_CHECK_HEADER([sys/timerfd.h]) +if test "x$ac_cv_header_sys_epoll_h" = "xyes" -a "x$ac_cv_header_sys_timerfd_h" = "xyes"; then + have_epoll="yes" + AC_ARG_WITH([epoll], + [AS_HELP_STRING([--with-epoll], + [Use epoll for I/O handling [if O/S supports it]])], + [with_epoll="$withval"], + [with_epoll="yes"]) +else + have_epoll="no" + if test "x$with_epoll" = "xyes"; then + AC_MSG_WARN([==> Underlying O/S does not support epoll - --with-epoll ignored.]) + with_epoll="no" + fi +fi + +if test "x$with_epoll" = "xyes"; then + AC_DEFINE(COAP_EPOLL_SUPPORT, 1, [Define if the system has epoll support]) +fi + +AC_ARG_ENABLE([small-stack], + [AS_HELP_STRING([--enable-small-stack], + [Use small-stack if the available stack space is restricted [default=no]])], + [enable_small_stack="$enableval"], + [enable_small_stack="no"]) + +if test "x$enable_small_stack" = "xyes"; then + AC_DEFINE(COAP_CONSTRAINED_STACK, 1, [Define if the system has small stack size]) +fi + +AC_ARG_ENABLE([server-mode], + [AS_HELP_STRING([--enable-server-mode], + [Enable CoAP server mode supporting code [default=yes]])], + [enable_server_mode="$enableval"], + [enable_server_mode="yes"]) + +if test "x$enable_server_mode" = "xyes"; then + AC_DEFINE(COAP_SERVER_SUPPORT, 1, [Define if libcoap supports server mode code]) +fi +AM_CONDITIONAL(HAVE_SERVER_SUPPORT, [test "x$enable_server_mode" = "xyes"]) + +AC_ARG_ENABLE([client-mode], + [AS_HELP_STRING([--enable-client-mode], + [Enable CoAP client mode supporting code [default=yes]])], + [enable_client_mode="$enableval"], + [enable_client_mode="yes"]) + +if test "x$enable_client_mode" = "xyes"; then + AC_DEFINE(COAP_CLIENT_SUPPORT, 1, [Define if libcoap supports client mode code]) +fi +AM_CONDITIONAL(HAVE_CLIENT_SUPPORT, [test "x$enable_client_mode" = "xyes"]) +if test "x$enable_server_mode" != "xyes" -a "x$enable_client_mode" != "xyes" ; then + AC_MSG_ERROR([==> One or both of '--enable-server-mode' and '--enable-client-mode' need to be set!]) +fi + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T + +# Checks for library functions. +AC_CHECK_FUNCS([memset select socket strcasecmp strrchr getaddrinfo \ + strnlen malloc pthread_mutex_lock getrandom if_nametoindex]) + +# Check if -lsocket -lnsl is required (specifically Solaris) +AC_SEARCH_LIBS([socket], [socket]) +AC_SEARCH_LIBS([inet_ntop], [nsl]) + +# Check if clock_gettime() requires librt, when available +AC_SEARCH_LIBS([clock_gettime], [rt]) + +#check for struct cmsghdr +AC_CHECK_TYPES([struct cmsghdr],,,[ +AC_INCLUDES_DEFAULT +#include ]) + +AC_MSG_CHECKING([operating system]) + +# Set up here some extra platform depended defines and variables. +# The "ADDITIONAL_CFLAGS" is need as this stand-alone definition +# for the doxygen part. +case $host in + *-linux* | *-uclinux*) + AC_MSG_RESULT([Linux]) + ADDITIONAL_CFLAGS="-D_GNU_SOURCE" + + # Not yet needed but if some code definitions have to depend on the platform. + #AC_DEFINE(OS_LINUX, 1, [Linux backend]) + #AC_SUBST(OS_LINUX) + ;; + + *-cygwin*) + AC_MSG_RESULT([Cygwin]) + ADDITIONAL_CFLAGS="-D_GNU_SOURCE -D_CYGWIN_ENV" + LDFLAGS="-no-undefined $LDFLAGS" + ;; + + *-solaris*) + AC_MSG_RESULT([Solaris]) + # set _XOPEN_SOURCE and _XOPEN_SOURCE_EXTENDED to enable XPG4v2 (POSIX 2004) + # set __EXTENSION__ to shut up feature test macros that restrict -std=c99 + # to only C99 (and nothing newer) + ADDITIONAL_CFLAGS="-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=600 -D__EXTENSIONS__=1" + ;; + + *-darwin*) + AC_MSG_RESULT([Darwin]) + ADDITIONAL_CFLAGS="-D_GNU_SOURCE" + + AC_DEFINE(__APPLE_USE_RFC_3542, 1, [Define this to 1 for ancillary data on MacOS]) + + # Not yet needed but if some code definitions have to depend on the platform. + #AC_DEFINE(OS_MACOS, 1, [MacOS backend]) + #AC_SUBST(OS_MACOS) + ;; + + *-freebsd1*) + AC_MSG_RESULT([FreeBSD-1x]) + ADDITIONAL_CFLAGS="-D_GNU_SOURCE" + ;; + + *kfreebsd*) + AC_MSG_RESULT([kFreeBSD]) + ADDITIONAL_CFLAGS="-D_GNU_SOURCE" + ;; + + *) + AC_MSG_WARN([==> Currently unsupported operating system '${host}' !]) + AC_MSG_ERROR([==> If you can provide patches to support your operating system please write to 'libcoap-developers@lists.sourceforge.net'.]) +esac + +# Exporting the PREDEFINED_CFLAGS definition +PREDEFINED_CFLAGS=`echo $ADDITIONAL_CFLAGS | $SED -e 's/-D//g'` +AC_SUBST(PREDEFINED_CFLAGS) + +# And finally combining the CFLAGS together ... +CFLAGS="$CFLAGS $ADDITIONAL_CFLAGS" + +# Override the various template files, currently just makefiles and the +# pkgconfig *.pc file. +# Later if the API version is changing don't forget to change the +# libcoap-$LIBCOAP_API_VERSION.pc.in file too!! You will have to change +# the 'Cflags' variable to something like +# Cflags: -I${includedir}/coap-@LIBCOAP_API_VERSION@ +# +AC_CONFIG_FILES([ +Makefile +coap_config.h.lwip +coap_config.h.riot +coap_config.h.windows +doc/Makefile +examples/Makefile +include/coap$LIBCOAP_API_VERSION/coap.h +include/coap$LIBCOAP_API_VERSION/coap.h.windows +man/coap.txt +man/coap_async.txt +man/coap_attribute.txt +man/coap_block.txt +man/coap_cache.txt +man/coap_context.txt +man/coap_encryption.txt +man/coap_endpoint_client.txt +man/coap_endpoint_server.txt +man/coap_handler.txt +man/coap_io.txt +man/coap_keepalive.txt +man/coap_logging.txt +man/coap_observe.txt +man/coap_pdu_access.txt +man/coap_pdu_setup.txt +man/coap_recovery.txt +man/coap_resource.txt +man/coap_session.txt +man/coap_string.txt +man/coap_tls_library.txt +man/coap-client.txt +man/coap-server.txt +man/coap-rd.txt +man/Makefile +tests/test_common.h +tests/Makefile +tests/oss-fuzz/Makefile.ci +libcoap-$LIBCOAP_NAME_SUFFIX.pc:libcoap-$LIBCOAP_API_VERSION.pc.in +]) + +AC_OUTPUT + +AC_MSG_RESULT([ +libcoap configuration summary: + libcoap package version : "$PACKAGE_VERSION" + libcoap library version : "$LIBCOAP_SO_VERSION" + libcoap API version : "$LIBCOAP_API_VERSION" + libcoap DTLS lib extn : "$LIBCOAP_DTLS_LIB_EXTENSION_NAME" + host system : "$host"]); +if test "x$enable_server_mode" = "xyes"; then + AC_MSG_RESULT([ build with server support: "yes"]) +else + AC_MSG_RESULT([ build with server support: "no"]) +fi +if test "x$enable_client_mode" = "xyes"; then + AC_MSG_RESULT([ build with client support: "yes"]) +else + AC_MSG_RESULT([ build with client support: "no"]) +fi +if test "x$build_tcp" != "xno"; then + AC_MSG_RESULT([ build with TCP support : "yes"]) +else + AC_MSG_RESULT([ build with TCP support : "no"]) +fi +if test "x$with_gnutls" = "xyes" -o "x$with_gnutls_auto" = "xyes"; then + AC_MSG_RESULT([ build DTLS support : "yes"]) + AC_MSG_RESULT([ --> GnuTLS around : "yes" (found GnuTLS $gnutls_version)]) + AC_MSG_RESULT([ GNUTLS_CFLAGS : "$GnuTLS_CFLAGS"]) + AC_MSG_RESULT([ GNUTLS_LIBS : "$GnuTLS_LIBS"]) +fi +if test "x$with_openssl" = "xyes" -o "x$with_openssl_auto" = "xyes"; then + AC_MSG_RESULT([ build DTLS support : "yes"]) + AC_MSG_RESULT([ --> OpenSSL around : "yes" (found OpenSSL $openssl_version)]) + AC_MSG_RESULT([ OPENSSL_CFLAGS : "$OpenSSL_CFLAGS"]) + AC_MSG_RESULT([ OPENSSL_LIBS : "$OpenSSL_LIBS"]) +fi +if test "x$with_mbedtls" = "xyes" -o "x$with_mbedtls_auto" = "xyes"; then + AC_MSG_RESULT([ build DTLS support : "yes"]) + AC_MSG_RESULT([ --> Mbed TLS around : "yes" (found Mbed TLS $mbedtls_version)]) + AC_MSG_RESULT([ MBEDTLS_CFLAGS : "$MbedTLS_CFLAGS"]) + AC_MSG_RESULT([ MBEDTLS_LIBS : "$MbedTLS_LIBS"]) +fi +if test "x$with_tinydtls" = "xyes"; then + AC_MSG_RESULT([ build DTLS support : "yes"]) + if test "x$have_submodule_tinydtls" = "xyes"; then + AC_MSG_RESULT([ --> TinyDTLS around : "yes" (submodule)]) + else + AC_MSG_RESULT([ --> TinyDTLS around : "yes (found TinyDTLS $tinydtls_version)"]) + fi + AC_MSG_RESULT([ TinyDTLS_CFLAGS : "$DTLS_CFLAGS"]) + AC_MSG_RESULT([ TinyDTLS_LIBS : "$DTLS_LIBS"]) +fi +if test "x$build_dtls" != "xyes"; then + AC_MSG_RESULT([ build DTLS support : "no"]) +fi +if test "x$build_add_default_names" = "xyes"; then + AC_MSG_RESULT([ add default names : "yes"]) +else + AC_MSG_RESULT([ add default names : "no"]) +fi +if test "x$have_epoll" = "xyes"; then + AC_MSG_RESULT([ build using epoll : "$with_epoll"]) +fi +AC_MSG_RESULT([ enable small stack size : "$enable_small_stack"]) +if test "x$build_async" != "xno"; then + AC_MSG_RESULT([ enable separate responses: "yes"]) +else + AC_MSG_RESULT([ enable separate responses: "no"]) +fi +if test "x$build_doxygen" = "xyes"; then + AC_MSG_RESULT([ build doxygen pages : "yes"]) + AC_MSG_RESULT([ --> Doxygen around : "yes" ($DOXYGEN $doxygen_version)]) + if test "x$DOT" = "x"; then + AC_MSG_RESULT([ --> dot around : "no" (DOT not found!)]) + else + AC_MSG_RESULT([ --> dot around : "yes" ($DOT $dot_version)]) + fi +else + if test "x$build_doxygen" = "xno"; then + AC_MSG_RESULT([ build doxygen pages : "no"]) + fi +fi +if test "x$build_manpages" = "xyes"; then + AC_MSG_RESULT([ build man pages : "yes"]) +else + AC_MSG_RESULT([ build man pages : "no"]) +fi +if test "x$build_tests" = "xyes"; then + AC_MSG_RESULT([ build unit test binary : "yes"]) +else + AC_MSG_RESULT([ build unit test binary : "no"]) +fi +if test "x$build_examples" = "xyes"; then + AC_MSG_RESULT([ build examples : "yes"]) +else + AC_MSG_RESULT([ build examples : "no"]) +fi +if test "x$build_examples_source" = "xyes"; then + AC_MSG_RESULT([ install examples source : "yes"]) +else + AC_MSG_RESULT([ install examples source : "no"]) +fi +if test "x$build_gcov" = "xyes"; then + AC_MSG_RESULT([ build with gcov support : "yes"]) +else + AC_MSG_RESULT([ build with gcov support : "no"]) +fi +if test "x$enable_shared" = "xyes"; then + AC_MSG_RESULT([ build shared library : "yes"]) +else + AC_MSG_RESULT([ build shared library : "no"]) +fi +if test "x$enable_static" = "xyes"; then + AC_MSG_RESULT([ build static library : "yes"]) +else + AC_MSG_RESULT([ build static library : "no"]) +fi diff --git a/examples/espidf-coap-server/components/libcoap/doc/Doxyfile.in b/examples/espidf-coap-server/components/libcoap/doc/Doxyfile.in new file mode 100644 index 000000000..782410d88 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/doc/Doxyfile.in @@ -0,0 +1,2612 @@ +# Doxyfile 1.9.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = @PACKAGE_NAME@ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = NO + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which efficively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = YES + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# The default value is: NO. + +WARN_AS_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = @top_srcdir@/doc/main.md \ + @top_srcdir@/doc/module_api_wrap.h \ + @top_srcdir@/src \ + @top_srcdir@/include/coap@LIBCOAP_API_VERSION@ \ + @top_builddir@/doc/man_tmp + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, +# *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = @top_srcdir@/src/coap_io_lwip.c \ + @top_srcdir@/src/coap_io_riot.c \ + @top_srcdir@/include/coap@LIBCOAP_API_VERSION@/lwippools.h \ + @top_srcdir@/include/coap@LIBCOAP_API_VERSION@/uthash.h \ + @top_srcdir@/include/coap@LIBCOAP_API_VERSION@/utlist.h + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = @top_builddir@/doc/man_html + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to +# YES then doxygen will add the directory of each input to the include path. +# The default value is: YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = YES + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = "libcoap build system" + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: +# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /

^

^' $(top_builddir)/doc/man_html/$${BASE}.html ;\ + else \ + echo "ERROR: $(top_builddir)/doc/$${BASE}.html not found!";\ + exit 1 ;\ + fi \ + done ;\ + ## + ## Close off the upgrading tab + ## + echo ' ' >> $(top_builddir)/doc/man_tmp/upgrading.dox ;\ + echo ' */' >> $(top_builddir)/doc/man_tmp/upgrading.dox ;\ + ## + ## Close off the insert file list + ## + echo ' ' >> $(top_builddir)/doc/insert_file ;\ + ## + ## Create and Update the DoxygenLayout.xml file + ## + $(DOXYGEN) -l ;\ + $(SED) -i 's/\)\(coap[_-][0-9a-z_]*\)\((\|(\)^\1\2\3^g" $(top_builddir)/doc/man_html/$${ENTRY}.html ;\ + ## The SYNOPSIS entries + $(SED) -i "s^\(

[a-z0-9_ \*]*\)\(coap_[0-9a-z_]*\)\([(;]\)^\1\2\3^g" $(top_builddir)/doc/man_html/$${ENTRY}.html ;\ + ## Function in NAME and Examples + $(SED) -i "s^\([ =,] \|[(!>]\|\^\)\(coap_[0-9a-z_]*\)\([(,]\| \-\| \xe2\x80\x94\)^\1\2\3^g" $(top_builddir)/doc/man_html/$${ENTRY}.html ;\ + ## Do for a second time in case of overlaps + $(SED) -i "s^\([ =,] \|[(!>]\|\^\)\(coap_[0-9a-z_]*\)\([(,]\| \-\| \xe2\x80\x94\)^\1\2\3^g" $(top_builddir)/doc/man_html/$${ENTRY}.html ;\ + done ;\ + ## + ## Do the highlighting + ## + for ENTRY in `cat $(top_builddir)/doc/scratch_insert_file` ; do \ + ${SED} -i "s/\($${ENTRY}\)\([<(\*, ]\)/\1<\/span>\2/g" $(top_builddir)/doc/man_html/$${ENTRY}.html ;\ + done + +if BUILD_MANPAGES +UPG_LIST = upgrade_4.2.1_4.3.0.txt upgrade_4.3.0_4.3.1.txt + +upg-page-build: + @for FILE in $(UPG_LIST) ; do \ + $(A2X) -d article --format xhtml -D $(top_builddir)/doc/ $(top_srcdir)/doc/$${FILE} ;\ + done + +all: man-page-build + $(DOXYGEN) Doxyfile + @$(RM) $(top_builddir)/doc/insert_file $(top_builddir)/doc/scratch_insert_file + @cp -f $(top_srcdir)/doc/docbook.local.css $(top_builddir)/doc/html/docbook-xsl.css + +else +# +# Need to make sure the man directories are in place, but empty +all: man-page-prepare + $(DOXYGEN) Doxyfile +endif # BUILD_MANPAGES + +clean-local: + -rm -rf $(top_builddir)/doc/html $(top_builddir)/doc/man_tmp $(top_builddir)/doc/man_html $(top_builddir)/doc/DoxygenLayout.xml $(top_builddir)/doc/docbook-xsl.css $(top_builddir)/doc/*.html + +distclean-local: clean-local + +endif # HAVE_DOXYGEN + +install-data-hook: +if HAVE_DOXYGEN + @if [ ! -d $(top_builddir)/doc/html ]; then \ + echo ;\ + echo " No install data in '$(top_builddir)/doc/html' found! Please run 'make all' first." ;\ + echo ;\ + exit 1 ;\ + fi + $(MKDIR_P) $(DESTDIR)$(htmldir)/html || exit 1 + cp -a -f $(top_builddir)/doc/html $(DESTDIR)$(htmldir) + find $(DESTDIR)$(htmldir) -type f -name "*.md5" -delete +endif # HAVE_DOXYGEN +if BUILD_LICENSE_INSTALL + $(MKDIR_P) $(DESTDIR)$(docdir) || exit 1 + $(INSTALL_DATA) $(top_srcdir)/LICENSE $(DESTDIR)$(docdir) + $(INSTALL_DATA) $(top_srcdir)/COPYING $(DESTDIR)$(docdir) + $(INSTALL_DATA) $(top_srcdir)/README $(DESTDIR)$(docdir) +endif # BUILD_LICENSE_INSTALL + +uninstall-hook: +if BUILD_LICENSE_INSTALL + @if [ -d $(DESTDIR)$(docdir) ] ; then \ + (cd $(DESTDIR)$(docdir) ; rm -f LICENSE README COPYING) ; \ + fi +endif # BUILD_LICENSE_INSTALL +if HAVE_DOXYGEN + -rm -rf $(DESTDIR)$(htmldir)/html +endif # HAVE_DOXYGEN + +.PHONY: man-page-cleanup man-page-prepare man-page-start man-page-build diff --git a/examples/espidf-coap-server/components/libcoap/doc/docbook.local.css b/examples/espidf-coap-server/components/libcoap/doc/docbook.local.css new file mode 100644 index 000000000..3246f8219 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/doc/docbook.local.css @@ -0,0 +1,47 @@ +body pre { + margin: 0.5em 10% 0.5em 1em; + line-height: 1.0; + color: navy; +} +dl { + margin: .2em 0; + line-height: 1.2; +} + +dt { + margin-top: 0.1em; +} + +span.man-highlight { background: yellow; } + +a.st-desc { + font-weight: bold; + color: black; + text-decoration: none; +} + +a.st-desc:visited { + font-weight: bold; + color: black; + text-decoration: none; +} + +a.st-desc:hover { + text-decoration: underline; +} + +a.st-synopsis { + font-weight: bold; + color: black; + text-decoration: none; +} + +a.st-synopsis:visited { + font-weight: bold; + color: black; + text-decoration: none; +} + +a.st-synopsis:hover { + text-decoration: underline; +} diff --git a/examples/espidf-coap-server/components/libcoap/doc/main.md b/examples/espidf-coap-server/components/libcoap/doc/main.md new file mode 100644 index 000000000..abd6a134c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/doc/main.md @@ -0,0 +1,69 @@ +libcoap {#mainpage} +======= + +A C implementation of the Constrained Application Protocol (RFC 7252) +===================================================================== + +Copyright (C) 2010--2022 by Olaf Bergmann and others + +About libcoap +============= + +libcoap is a C implementation of a lightweight application-protocol +for devices that are constrained their resources such as computing +power, RF range, memory, bandwidth, or network packet sizes. This +protocol, CoAP, is standardized by the IETF as RFC 7252. For further +information related to CoAP, see . + +You might want to check out +[libcoap-minimal](https://github.com/obgm/libcoap-minimal) for usage +examples. + +The following RFCs are supported + +* RFC7252: The Constrained Application Protocol (CoAP) + +* RFC7390: Group Communication for the Constrained Application Protocol (CoAP) + +* RFC7641: Observing Resources in the Constrained Application Protocol (CoAP) + +* RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP) + +* RFC7967: Constrained Application Protocol (CoAP) Option for No Server Response + +* RFC8132: PATCH and FETCH Methods for the Constrained Application Protocol (CoAP) + +* RFC8323: CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets + [No WebSockets support] + +* RFC8516: "Too Many Requests" Response Code for the Constrained Application Protocol + +* RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option + +* RFC9175: CoAP: Echo, Request-Tag, and Token Processing + +There is (D)TLS support for the following libraries + +* OpenSSL (Minimum version 1.1.0) [PKI, PSK and PKCS11] + +* GnuTLS (Minimum version 3.3.0) [PKI, PSK, RPK(3.6.6+) and PKCS11] + +* Mbed TLS (Minimum version 2.7.10) [PKI and PSK] + +* TinyDTLS [PSK and RPK] [DTLS Only] + +Documentation +============= + +This set of pages contains the current set of documention for the libcoap APIs. + +License Information +=================== + +This library is published as open-source software without any warranty +of any kind. Use is permitted under the terms of the simplified BSD +license. It includes public domain software. libcoap binaries may also +include open-source software with their respective licensing terms. +Please refer to +[LICENSE](https://raw.githubusercontent.com/obgm/libcoap/develop/LICENSE) +for further details in the source. diff --git a/examples/espidf-coap-server/components/libcoap/doc/module_api_wrap.h b/examples/espidf-coap-server/components/libcoap/doc/module_api_wrap.h new file mode 100644 index 000000000..76eda34ec --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/doc/module_api_wrap.h @@ -0,0 +1,21 @@ +/* doc/module_api_wrap.h + * + * Copyright (C) 2021-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP C library libcoap. Please see README and + * COPYING for terms of use. + */ + +/** + * @file module_api_wrap.h + * @brief Doxygen specific wrapper for Modules layout + */ + +/** + * @defgroup application_api Application API + * Application API Structures, Macros, Typedefs, Enums and Functions + * @defgroup internal_api Libcoap Internal API + * libcoap Internal API Structures, Macros, Typedefs, Enums and Functions + */ diff --git a/examples/espidf-coap-server/components/libcoap/doc/upgrade_4.2.1_4.3.0.txt b/examples/espidf-coap-server/components/libcoap/doc/upgrade_4.2.1_4.3.0.txt new file mode 100644 index 000000000..0a7f2c7b7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/doc/upgrade_4.2.1_4.3.0.txt @@ -0,0 +1,431 @@ += Upgrade from 4.2.1 to 4.3.0 + +== Summary + +When compiling 4.2.1 based code with a 4.3.0 environment, this will initially +throw up many errors as the API has been updated to make future coding simpler, +adds more functionality and adds more rigorous coding checks. Updating your +code with the following steps will significantly reduce the reported issues. + +The examples are now also named with the (D)TLS library type as a suffix. +E.g. coap-client is now coap-client-openssl. + +== Include directory changes + +Because of the API changes, the libcoap's include file directory has changed from `coap2/` to `coap3/`. Also, there is now no need to define additional include paths to the compiler options such as `-I include/coap3`. + +=== Update coap2 to coap3 + +Example +---- +4.2.1 + #include +4.3.0 + #include +---- +No other libcoap include files need to be included in your application. + +== Call-back handler updates + +Infrequently used parameters (which can easily be recreated) have been removed +and others have been made const. These call-back handlers are those +registered with the `coap_register_*()` functions as follows: + +=== coap_register_handler() + +The definition of `coap_method_handler_t` has been updated, so all the +functions registered by `coap_register_handler()` need to be updated. Any +application functions called by these functions may need to include `const` in +their calling parameters. + +Example +---- +4.2.1 +static void + hnd_get_time(coap_context_t *context, + coap_resource_t *resource, + coap_session_t *session, + coap_pdu_t *request, + coap_binary_t *token, + coap_string_t *query, + coap_pdu_t *response) { +4.3.0 + static void + hnd_get_time(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response) { +---- +If `context` or `token` need to be recreated, this is done by +---- + coap_context_t *context = coap_session_get_context(session); + coap_bin_const_t rcvd_token = coap_pdu_get_token(request); +---- + +=== coap_register_response_handler() + +The definition of `coap_response_handler_t` has been updated, so all the +functions registered by `coap_register_response_handler()` need to be updated. +Any application functions called by these functions may need to include `const` +in their calling parameters. There is a new handler function exit code +`COAP_RESPONSE_FAIL` (if the response is not liked and needs to be rejected +with a `RST` packet) or `COAP_RESPONSE_OK`. Note that `coap_tid_t` has been +replaced with `coap_mid_t` to reflect the parameter is the message id. + +Example +---- +4.2.1 + static void + message_handler(struct coap_context_t *context, + coap_session_t *session, + coap_pdu_t *sent, + coap_pdu_t *received, + const coap_tid_t id) { +4.3.0 + static coap_response_t + message_handler(coap_session_t *session, + const coap_pdu_t *sent, + const coap_pdu_t *received, + const coap_mid_t mid) { +---- +If `context` needs to be recreated, this is done by +---- + coap_context_t *context = coap_session_get_context(session); +---- + +=== coap_register_nack_handler() + +The definition of `coap_nack_handler_t` has been updated, so all the functions +registered by `coap_register_nack_handler()` need to be updated. Any +application functions called by these functions may need to include `const` in +their calling parameters. Note that `coap_tid_t` has been replaced with +`coap_mid_t` to reflect the parameter is the message id. + +Example +---- +4.2.1 + static void + nack_handler(coap_context_t *context, + coap_session_t *session, + coap_pdu_t *sent, + coap_nack_reason_t reason, + const coap_tid_t id) { +4.3.0 + static void + nack_handler(coap_session_t *session, + const coap_pdu_t *sent, + const coap_nack_reason_t reason, + const coap_mid_t mid) { +---- +If `context` needs to be recreated, this is done by +---- + coap_context_t *context = coap_session_get_context(session); +---- + +=== coap_register_event_handler() + +The definition of `coap_event_handler_t` been updated, so all the functions +registered by `coap_register_event_handler()` need to be updated. Any +application functions called by these functions may need to include `const` in +their calling parameters. + +Example +---- +4.2.1 + static int + event_handler(coap_context_t *context, + coap_event_t event, + struct coap_session_t *session) { +4.3.0 + static int + event_handler(coap_session_t *session, + const coap_event_t event) { +---- +Note the reversed order of the parameters. If `context` needs to be +recreated, this is done by +---- + coap_context_t *context = coap_session_get_context(session); +---- + +=== coap_register_ping_handler() + +The definition of `coap_ping_handler_t` been updated, so all the functions +registered by `coap_register_ping_handler()` need to be updated. Any +application functions called by these functions may need to include `const` in +their calling parameters. Note that `coap_tid_t` has been replaced with +`coap_mid_t` to reflect the parameter is the message id. + +Example + +---- +4.2.1 + void + ping_handler(coap_context_t *context, + coap_session_t *session, + coap_pdu_t *received, + const coap_tid_t id); +4.3.0 + void + ping_handler(coap_session_t *session, + const coap_pdu_t *received, + const coap_mid_t mid); +---- +If `context` needs to be recreated, this is done by +---- + coap_context_t *context = coap_session_get_context(session); +---- + +=== coap_register_pong_handler() + +The definition of `coap_pong_handler_t` been updated, so all the functions +registered by `coap_register_pong_handler()` need to be updated. Any +application functions called by these functions may need to include `const` in +their calling parameters. Note that `coap_tid_t` has been replaced with +`coap_mid_t` to reflect the parameter is the message id. + +Example +---- +4.2.1 + void + pong_handler(coap_context_t *context, + coap_session_t *session, + coap_pdu_t *received, + const coap_tid_t id); +4.3.0 + void + pong_handler(coap_session_t *session, + const coap_pdu_t *received, + const coap_mid_t mid); +---- +If `context` needs to be recreated, this is done by +---- + coap_context_t *context = coap_session_get_context(session); +---- + +== libcoap structures no longer directly accessible + +Many of the structures internally used by libcoap are no longer exposed to +applications. Additional functions of the form `coap_X_get_Y()` and +`coap_X_set_Y()` where `X` is the structure type and `Y` is the variable. Below +is a non exhaustive set of examples, + +=== coap_pdu_t code variable + + +Example +---- +4.2.1 + if (received->code == +4.3.0 + coap_pdu_code_t rcvd_code = coap_pdu_get_code(received); + ... + if (rcvd_code == +---- + +Example +---- +4.2.1 + response->code = COAP_RESPONSE_CODE(404); +4.3.0 + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); +---- +Note that more descriptive names are now supported for the response codes, but +the old form can still be used. + +=== coap_pdu_t type variable + + +Example +---- +4.2.1 + if (received->type == +4.3.0 + coap_pdu_code_t rcvd_type = coap_pdu_get_type(received); + ... + if (rcvd_type == +---- + +Example +---- +4.2.1 + request->type = COAP_MESSAGE_NON; +4.3.0 + coap_pdu_set_type(request, COAP_MESSAGE_NON); +---- + +=== coap_pdu_t token variable + + +Example +---- +4.2.1 + static inline int + check_token(coap_pdu_t *received) { + return received->token_length == the_token.length && + memcmp(received->token, the_token.s, the_token.length) == 0; + } +4.3.0 + static inline int + check_token(const coap_pdu_t *received) { + coap_bin_const_t rcvd_token = coap_pdu_get_token(received); + + return rcvd_token.length == the_token.length && + memcmp(rcvd_token.s, the_token.s, the_token.length) == 0; + } +---- + +=== coap_session_t context variable + + +Example +---- +4.2.1 + if (session->context == +4.3.0 + coap_context_t context = coap_session_get_context(session); + ... + if (context == +---- + +=== coap_session_t proto variable + + +Example +---- +4.2.1 + if (session->proto == +4.3.0 + coap_proto_t proto = coap_session_get_proto(session); + ... + if (proto == +---- + + +== Functions with changed parameters + +Some functions have had the parameters updated. Below are some of the more common ones. + +=== coap_pdu_init() + +The definition of the second parameter has changed from `coap_request_t` to +`coap_pdu_code_t`. + +Example +---- +4.2.1 + pdu = coap_pdu_init(msgtype, + COAP_REQUEST_GET, + coap_new_message_id(session), + coap_session_max_pdu_size(session)); +4.3.0 + pdu = coap_pdu_init(msgtype, + COAP_REQUEST_CODE_GET, + coap_new_message_id(session), + coap_session_max_pdu_size(session)); +---- +Note that the second parameter (`COAP_REQUEST_CODE_GET`) goes further than +just request codes and includes the possibility of response codes (e.g. +`COAP_RESPONSE_CODE_CREATED`) from the `enum coap_pdu_code_t`. Hence the +addition of `_CODE` in the parameter value. + +=== coap_get_data() + +The definition of the third parameter has been changed to be `const` + +Example +---- +4.2.1 + uint8_t *data; + ... + ret = coap_get_data(pdu, &length, &data); +4.3.0 + const uint8_t *data; + ... + ret = coap_get_data(pdu, &length, &data); +---- + +== Large Data Handling + +Splitting up large data transmission into blocks (RFC7959) can now all be +handled by internally by libcoap, removing the need for applications to know +anything about how to work with blocks, or need to do any block packet loss +recovery. In simple terms, `coap_context_set_block_mode()` must be called, +`coap_add_data()` (or `coap_add_data_blocked_response()`) is replaced by +`coap_add_data_large_response()` or `coap_add_data_large_request()`, and +`coap_get_data_large()` used instead of `coap_get_data()`. See man page +`coap_block(3)` for further information. + +There are 3 ways of handling the block transfers + +=== Application does all the work + +This is how things were done in 4.2.1. The application recognizes the next +block request coming in and then generates the next block response (including +setting up the PDU if client). To continue using this method, +`coap_context_set_block_mode()` must not be called and none of the `_large` +functions used. + +=== Application sees individual blocks + +By calling `coap_context_set_block_mode(context, COAP_BLOCK_USE_LIBCOAP)` and +using the `_large` functions, all the existing code that builds the next block +response is no longer needed (and must be removed to prevent packet +request/response duplication) as libcoap does this for the application. + +By calling `coap_get_data_large()`, the application can determine if this is +the first block or not (using `offset` value), whether the first block is all +the data (`offset` = `0`, `length` = `total`) and whether this is the last +block (`offset` + `length` = `total`). It is the responsibility of the +application to re-assemble the individual blocks into a single body of data. + +If this is the request handler in a server, the server still needs to return a +`2.31 (Continue)` response code if the received data is not for the final block, +otherwise a `2.01 (Created)` or `2.04 (Changed)` should be returned. + +=== Application only sees all the data + +By calling `coap_context_set_block_mode(context, +COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY)` and using the `_large` +functions, all the existing code that builds the next block response is no +longer needed (and must be removed to prevent request/response packet +duplication) as libcoap does this for the application. + +`coap_get_data_large()` will only return the entire body of data (`offset` +always `0`, `length` = `total`) and there is no need to re-assemble individual +blocks into a large body of data. + +In RAM constrained environments, option 2 may be the preferred method. + +== Observe Handling + +In the server's request handler's call-back, there is no longer any need to +check whether this is an Observe call (or Observe triggered requesting +additional response call) and add in the Observe Option into the response pdu. +This is now added by libcoap, and trying to add in the Observe Option for the +second time in the call-back handler will throw up a Informational warning. + +For the client, there is a new function `coap_cancel_observe()` that can be +called to cancel an observation on the server. To use it, +`coap_context_set_block_mode()` has to be called prior to sending the initial +request containing the Observe option. + +== Unused function parameters + +`UNUSED_PARAM` has been replaced with `COAP_UNUSED`. If `COAP_UNUSED` is used, +then the definition for `UNUSED_PARAM` can be removed. + +== CoAP Message IDs + +`coap_tid_t` has been replaced with `coap_mid_t`, as well as `COAP_TID_INVALID` +has been replaced with `COAP_MID_INVALID`. This is so that the Message ID aligns +with the definition in RFC7252. + +== Async Support + +The `async` support has been re-written to simplify usage, and allows the +underlying libcoap to do the main management / work. A primary change is to +register the async request with a defined delay time before triggering - which +if set to 0 is an infinite time and the delay time subsequently updated if +required. Consequently the `coap_async_*()` functions now have different +parameters. diff --git a/examples/espidf-coap-server/components/libcoap/doc/upgrade_4.3.0_4.3.1.txt b/examples/espidf-coap-server/components/libcoap/doc/upgrade_4.3.0_4.3.1.txt new file mode 100644 index 000000000..70aa92d08 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/doc/upgrade_4.3.0_4.3.1.txt @@ -0,0 +1,6 @@ += Upgrade from 4.3.0 to 4.3.1 + +== Summary + +The source and binary APIs are the same for 4.3.0 and 4.3.1 with just extra +functionality making it forward, but not necessarily backward compatible. diff --git a/examples/espidf-coap-server/components/libcoap/examples/Makefile.am b/examples/espidf-coap-server/components/libcoap/examples/Makefile.am new file mode 100644 index 000000000..6c4d3c132 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/Makefile.am @@ -0,0 +1,129 @@ +# examples/Makefile.am +# +# Copyright (C) 2015 Carsten Schoenert +# Copyright (C) 2018-2022 Jon Shallow +# +# SPDX-License-Identifier: BSD-2-Clause +# +# This file is part of the CoAP C library libcoap. Please see README and +# COPYING for terms of use. + +EXTRA_DIST = share.libcoap.examples.Makefile share.libcoap.examples.README + +# just do nothing if 'BUILD_EXAMPLES' isn't defined +if BUILD_EXAMPLES + +# picking up the default warning CFLAGS into AM_CFLAGS +AM_CFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include \ + $(WARNING_CFLAGS) $(DTLS_CFLAGS) -std=c99 $(EXTRA_CFLAGS) + +# + +bin_PROGRAMS = +noinst_PROGRAMS = +check_PROGRAMS = + +if HAVE_CLIENT_SUPPORT + +bin_PROGRAMS += coap-client@LIBCOAP_DTLS_LIB_EXTENSION_NAME@ +check_PROGRAMS += coap-tiny + +if BUILD_ADD_DEFAULT_NAMES +noinst_PROGRAMS += coap-client +endif # BUILD_ADD_DEFAULT_NAMES + +endif # HAVE_CLIENT_SUPPORT + +if HAVE_SERVER_SUPPORT + +bin_PROGRAMS += coap-server@LIBCOAP_DTLS_LIB_EXTENSION_NAME@ \ + coap-rd@LIBCOAP_DTLS_LIB_EXTENSION_NAME@ +check_PROGRAMS += coap-etsi_iot_01 + +if BUILD_ADD_DEFAULT_NAMES +noinst_PROGRAMS += coap-server coap-rd +endif # BUILD_ADD_DEFAULT_NAMES + +if ! HAVE_CLIENT_SUPPORT +coap_server_CPPFLAGS=-DSERVER_CAN_PROXY=0 +coap_server@LIBCOAP_DTLS_LIB_EXTENSION_NAME@_CPPFLAGS=-DSERVER_CAN_PROXY=0 +endif # HAVE_CLIENT_SUPPORT + +endif # HAVE_SERVER_SUPPORT + +coap_client_SOURCES = coap-client.c +coap_client_LDADD = $(DTLS_LIBS) \ + $(top_builddir)/.libs/libcoap-$(LIBCOAP_NAME_SUFFIX).la + +coap_server_SOURCES = coap-server.c +coap_server_LDADD = $(DTLS_LIBS) \ + $(top_builddir)/.libs/libcoap-$(LIBCOAP_NAME_SUFFIX).la + +coap_rd_SOURCES = coap-rd.c +coap_rd_LDADD = $(DTLS_LIBS) \ + $(top_builddir)/.libs/libcoap-$(LIBCOAP_NAME_SUFFIX).la + +coap_client@LIBCOAP_DTLS_LIB_EXTENSION_NAME@_SOURCES = coap-client.c +coap_client@LIBCOAP_DTLS_LIB_EXTENSION_NAME@_LDADD = $(DTLS_LIBS) \ + $(top_builddir)/.libs/libcoap-$(LIBCOAP_NAME_SUFFIX).la + +coap_server@LIBCOAP_DTLS_LIB_EXTENSION_NAME@_SOURCES = coap-server.c +coap_server@LIBCOAP_DTLS_LIB_EXTENSION_NAME@_LDADD = $(DTLS_LIBS) \ + $(top_builddir)/.libs/libcoap-$(LIBCOAP_NAME_SUFFIX).la + +coap_rd@LIBCOAP_DTLS_LIB_EXTENSION_NAME@_SOURCES = coap-rd.c +coap_rd@LIBCOAP_DTLS_LIB_EXTENSION_NAME@_LDADD = $(DTLS_LIBS) \ + $(top_builddir)/.libs/libcoap-$(LIBCOAP_NAME_SUFFIX).la + +coap_etsi_iot_01_SOURCES = etsi_iot_01.c +coap_etsi_iot_01_LDADD = $(DTLS_LIBS) \ + $(top_builddir)/.libs/libcoap-$(LIBCOAP_NAME_SUFFIX).la + +coap_tiny_SOURCES = tiny.c +coap_tiny_LDADD = $(DTLS_LIBS) \ + $(top_builddir)/.libs/libcoap-$(LIBCOAP_NAME_SUFFIX).la + +endif # BUILD_EXAMPLES + +if BUILD_EXAMPLES_SOURCE +EXAMPLES_DIR = $(DESTDIR)$(datadir)/libcoap/examples +EXAMPLES_SRC = coap-client.c coap-server.c +endif # BUILD_EXAMPLES_SOURCE + +## Install example files +install-exec-hook: +if BUILD_EXAMPLES_SOURCE + $(MKDIR_P) $(EXAMPLES_DIR) + (cd $(top_srcdir)/examples ; \ + $(INSTALL_DATA) $(EXAMPLES_SRC) ../LICENSE ../COPYING $(EXAMPLES_DIR) ; \ + $(INSTALL_DATA) share.libcoap.examples.Makefile $(EXAMPLES_DIR)/Makefile; \ + $(INSTALL_DATA) share.libcoap.examples.README $(EXAMPLES_DIR)/README) +endif # BUILD_EXAMPLES_SOURCE +if BUILD_ADD_DEFAULT_NAMES + if [ -d "$(DESTDIR)$(bindir)" ] ; then \ + (cd $(DESTDIR)$(bindir) && \ + (if [ -f coap-client@LIBCOAP_DTLS_LIB_EXTENSION_NAME@ ] ; then \ + rm -f coap-client ; \ + $(LN_S) coap-client@LIBCOAP_DTLS_LIB_EXTENSION_NAME@ coap-client ; \ + fi ; \ + if [ -f coap-server@LIBCOAP_DTLS_LIB_EXTENSION_NAME@ ] ; then \ + rm -f coap-server ; \ + $(LN_S) coap-server@LIBCOAP_DTLS_LIB_EXTENSION_NAME@ coap-server ; \ + fi ; \ + if [ -f coap-rd@LIBCOAP_DTLS_LIB_EXTENSION_NAME@ ] ; then \ + rm -f coap-rd ; \ + $(LN_S) coap-rd@LIBCOAP_DTLS_LIB_EXTENSION_NAME@ coap-rd ; \ + fi) \ + ) ; \ + fi +endif # BUILD_ADD_DEFAULT_NAMES + +uninstall-hook: +if BUILD_EXAMPLES_SOURCE + rm -rf $(DESTDIR)$(datadir)/libcoap/examples +endif # BUILD_EXAMPLES_SOURCE +if BUILD_ADD_DEFAULT_NAMES + rm -f $(DESTDIR)$(bindir)/coap-client + rm -f $(DESTDIR)$(bindir)/coap-server + rm -f $(DESTDIR)$(bindir)/coap-rd +endif # BUILD_ADD_DEFAULT_NAMES diff --git a/examples/espidf-coap-server/components/libcoap/examples/README.etsi_iot b/examples/espidf-coap-server/components/libcoap/examples/README.etsi_iot new file mode 100644 index 000000000..5d37a58f7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/README.etsi_iot @@ -0,0 +1,43 @@ +This README documents the test cases supported for the 1st ETSI CoAP +plugtest on March 24/25 in Paris, France. + + +Legend: + [+] full support + [o] partial support + [-] no support + [?] needs check + [ ] has open issues + +Mandatory Tests + +[+] TD_COAP_CORE_01 Perform GET transaction (CON mode) +[+] TD_COAP_CORE_02 Perform POST transaction (CON mode) +[+] TD_COAP_CORE_03 Perform PUT transaction (CON mode) +[+] TD_COAP_CORE_04 Perform DELETE transaction (CON mode) +[+] TD_COAP_CORE_05 Perform GET transaction (NON mode) +[+] TD_COAP_CORE_06 Perform POST transaction (NON mode) +[+] TD_COAP_CORE_07 Perform PUT transaction (NON mode) +[+] TD_COAP_CORE_08 Perform DELETE transaction (NON mode) +[+] TD_COAP_CORE_09 Perform GET transaction with delayed response (CON mode, no piggyback) +[+] TD_COAP_CORE_10 Handle request containing Token option +[+] TD_COAP_CORE_11 Handle request not containing Token option +[+] TD_COAP_CORE_12 Handle request containing several Uri-Path options +[+] TD_COAP_CORE_13 Handle request containing several Uri-Query options +[?] TD_COAP_CORE_14 Interoperate in lossy context (CON mode, piggybacked response) +[?] TD_COAP_CORE_15 Interoperate in lossy context (CON mode, delayed response) + +Optional Tests + +[ ] TD_COAP_LINK_01 Access to well-known interface for resource discovery +[-] TD_COAP_LINK_02 Use filtered requests for limiting discovery results +[+] TD_COAP_BLOCK_01 Handle GET blockwise transfer for large resource (early negotiation) +[+] TD_COAP_BLOCK_02 Handle GET blockwise transfer for large resource (late negotiation) +[-] TD_COAP_BLOCK_03 Handle PUT blockwise transfer for large resource +[-] TD_COAP_BLOCK_04 Handle POST blockwise transfer for large resource +[-] TD_COAP_OBS_01 Handle resource observation +[-] TD_COAP_OBS_02 Stop resource observation +[-] TD_COAP_OBS_03 Client detection of deregistration (Max-Age) +[-] TD_COAP_OBS_04 Server detection of deregistration (client OFF) +[-] TD_COAP_OBS_05 Server detection of deregistration (explicit RST) + diff --git a/examples/espidf-coap-server/components/libcoap/examples/coap-client.c b/examples/espidf-coap-server/components/libcoap/examples/coap-client.c new file mode 100644 index 000000000..82320dead --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/coap-client.c @@ -0,0 +1,1944 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* coap-client -- simple CoAP client + * + * Copyright (C) 2010--2022 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms of + * use. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define fileno _fileno +#include "getopt.c" +#if !defined(S_ISDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif +static char* strndup(const char* s1, size_t n) +{ + char* copy = (char*)malloc(n + 1); + if (copy) { + memcpy(copy, s1, n); + copy[n] = 0; + } + return copy; +}; +#else +#include +#include +#include +#include +#include +#include +#endif + +#include + +#define MAX_USER 128 /* Maximum length of a user name (i.e., PSK + * identity) in bytes. */ +#define MAX_KEY 64 /* Maximum length of a key (i.e., PSK) in bytes. */ + +int flags = 0; + +static unsigned char _token_data[8]; +coap_binary_t base_token = { 0, _token_data }; + +typedef struct { + coap_binary_t *token; + int observe; +} track_token; + +track_token *tracked_tokens = NULL; +size_t tracked_tokens_count = 0; + +#define FLAGS_BLOCK 0x01 + +static coap_optlist_t *optlist = NULL; +/* Request URI. + * TODO: associate the resources with transaction id and make it expireable */ +static coap_uri_t uri; +static coap_uri_t proxy = { {0, NULL}, 0, {0, NULL}, {0, NULL}, 0 }; +static int proxy_scheme_option = 0; +static int uri_host_option = 0; +static unsigned int ping_seconds = 0; + +#define REPEAT_DELAY_MS 1000 +static size_t repeat_count = 1; + +/* reading is done when this flag is set */ +static int ready = 0; + +/* processing a block response when this flag is set */ +static int doing_getting_block = 0; +static int single_block_requested = 0; +static uint32_t block_mode = COAP_BLOCK_USE_LIBCOAP; + +static coap_string_t output_file = { 0, NULL }; /* output file name */ +static FILE *file = NULL; /* output file stream */ + +static coap_string_t payload = { 0, NULL }; /* optional payload to send */ + +static int reliable = 0; + +static int add_nl = 0; +static int is_mcast = 0; +static uint32_t csm_max_message_size = 0; + +unsigned char msgtype = COAP_MESSAGE_CON; /* usually, requests are sent confirmable */ + +static char *cert_file = NULL; /* certificate and optional private key in PEM, + or PKCS11 URI*/ +static char *key_file = NULL; /* private key in PEM, DER or PKCS11 URI */ +static char *pkcs11_pin = NULL; /* PKCS11 pin to unlock access to token */ +static char *ca_file = NULL; /* CA for cert_file - for cert checking in PEM, + DER or PKCS11 URI */ +static char *root_ca_file = NULL; /* List of trusted Root CAs in PEM */ +static int is_rpk_not_cert = 0; /* Cert is RPK if set */ +static uint8_t *cert_mem = NULL; /* certificate and private key in PEM_BUF */ +static uint8_t *key_mem = NULL; /* private key in PEM_BUF */ +static uint8_t *ca_mem = NULL; /* CA for cert checking in PEM_BUF */ +static size_t cert_mem_len = 0; +static size_t key_mem_len = 0; +static size_t ca_mem_len = 0; +static int verify_peer_cert = 1; /* PKI granularity - by default set */ + +typedef struct ih_def_t { + char* hint_match; + coap_bin_const_t *new_identity; + coap_bin_const_t *new_key; +} ih_def_t; + +typedef struct valid_ihs_t { + size_t count; + ih_def_t *ih_list; +} valid_ihs_t; + +static valid_ihs_t valid_ihs = {0, NULL}; + +typedef unsigned char method_t; +method_t method = 1; /* the method we are using in our requests */ + +coap_block_t block = { .num = 0, .m = 0, .szx = 6 }; +uint16_t last_block1_mid = 0; + +#define DEFAULT_WAIT_TIME 90 + +unsigned int wait_seconds = DEFAULT_WAIT_TIME; /* default timeout in seconds */ +unsigned int wait_ms = 0; +int obs_started = 0; +unsigned int obs_seconds = 30; /* default observe time */ +unsigned int obs_ms = 0; /* timeout for current subscription */ +int obs_ms_reset = 0; +int doing_observe = 0; + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +static int quit = 0; + +/* SIGINT handler: set quit to 1 for graceful termination */ +static void +handle_sigint(int signum COAP_UNUSED) { + quit = 1; +} + +static int +append_to_output(const uint8_t *data, size_t len) { + size_t written; + + if (!file) { + if (!output_file.s || (output_file.length && output_file.s[0] == '-')) + file = stdout; + else { + if (!(file = fopen((char *)output_file.s, "w"))) { + perror("fopen"); + return -1; + } + } + } + + do { + written = fwrite(data, 1, len, file); + len -= written; + data += written; + } while ( written && len ); + fflush(file); + + return 0; +} + +static void +close_output(void) { + if (file) { + + /* add a newline before closing if no option '-o' was specified */ + if (!output_file.s) + fwrite("\n", 1, 1, file); + + fflush(file); + fclose(file); + } +} + +static void +free_xmit_data(coap_session_t *session COAP_UNUSED, void *app_ptr) { + coap_free(app_ptr); + return; +} + +static void +track_new_token(size_t tokenlen, uint8_t *token) +{ + track_token *new_list = realloc(tracked_tokens, + (tracked_tokens_count + 1) * sizeof(tracked_tokens[0])); + if (!new_list) { + coap_log(LOG_INFO, "Unable to track new token\n"); + return; + } + tracked_tokens = new_list; + tracked_tokens[tracked_tokens_count].token = coap_new_binary(tokenlen); + if (!tracked_tokens[tracked_tokens_count].token) + return; + memcpy(tracked_tokens[tracked_tokens_count].token->s, token, tokenlen); + tracked_tokens[tracked_tokens_count].observe = doing_observe; + tracked_tokens_count++; +} + +static int +track_check_token(coap_bin_const_t *token) +{ + size_t i; + + for (i = 0; i < tracked_tokens_count; i++) { + if (coap_binary_equal(token, tracked_tokens[i].token)) { + return 1; + } + } + return 0; +} + +static void +track_flush_token(coap_bin_const_t *token) +{ + size_t i; + + for (i = 0; i < tracked_tokens_count; i++) { + if (coap_binary_equal(token, tracked_tokens[i].token)) { + if (!tracked_tokens[i].observe || !obs_started) { + /* Only remove if not Observing */ + coap_delete_binary(tracked_tokens[i].token); + if (tracked_tokens_count-i > 1) { + memmove (&tracked_tokens[i], + &tracked_tokens[i+1], + (tracked_tokens_count-i-1) * sizeof (tracked_tokens[0])); + } + tracked_tokens_count--; + } + break; + } + } +} + + +static coap_pdu_t * +coap_new_request(coap_context_t *ctx, + coap_session_t *session, + method_t m, + coap_optlist_t **options, + unsigned char *data, + size_t length) { + coap_pdu_t *pdu; + uint8_t token[8]; + size_t tokenlen; + (void)ctx; + + if (!(pdu = coap_new_pdu(msgtype, m, session))) { + free_xmit_data(session, data); + return NULL; + } + + /* + * Create unique token for this request for handling unsolicited / + * delayed responses + */ + coap_session_new_token(session, &tokenlen, token); + track_new_token(tokenlen, token); + if (!coap_add_token(pdu, tokenlen, token)) { + coap_log(LOG_DEBUG, "cannot add token to request\n"); + } + + if (options) + coap_add_optlist_pdu(pdu, options); + + if (length) { + /* Let the underlying libcoap decide how this data should be sent */ + coap_add_data_large_request(session, pdu, length, data, + free_xmit_data, data); + } + + return pdu; +} + +static int +resolve_address(const coap_str_const_t *server, struct sockaddr *dst) { + + struct addrinfo *res, *ainfo; + struct addrinfo hints; + static char addrstr[256]; + int error, len=-1; + + memset(addrstr, 0, sizeof(addrstr)); + if (server->length) + memcpy(addrstr, server->s, server->length); + else + memcpy(addrstr, "localhost", 9); + + memset ((char *)&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_UNSPEC; + + error = getaddrinfo(addrstr, NULL, &hints, &res); + + if (error != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); + return error; + } + + for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) { + switch (ainfo->ai_family) { + case AF_INET6: + case AF_INET: + len = (int)ainfo->ai_addrlen; + memcpy(dst, ainfo->ai_addr, len); + goto finish; + default: + ; + } + } + + finish: + freeaddrinfo(res); + return len; +} + +#define HANDLE_BLOCK1(Pdu) \ + ((method == COAP_REQUEST_PUT || method == COAP_REQUEST_POST) && \ + ((flags & FLAGS_BLOCK) == 0) && \ + ((Pdu)->hdr->code == COAP_RESPONSE_CODE_CREATED || \ + (Pdu)->hdr->code == COAP_RESPONSE_CODE_CHANGED)) + +static int +event_handler(coap_session_t *session COAP_UNUSED, + const coap_event_t event) { + + switch(event) { + case COAP_EVENT_DTLS_CLOSED: + case COAP_EVENT_TCP_CLOSED: + case COAP_EVENT_SESSION_CLOSED: + quit = 1; + break; + case COAP_EVENT_DTLS_CONNECTED: + case COAP_EVENT_DTLS_RENEGOTIATE: + case COAP_EVENT_DTLS_ERROR: + case COAP_EVENT_TCP_CONNECTED: + case COAP_EVENT_TCP_FAILED: + case COAP_EVENT_SESSION_CONNECTED: + case COAP_EVENT_SESSION_FAILED: + case COAP_EVENT_PARTIAL_BLOCK: + case COAP_EVENT_XMIT_BLOCK_FAIL: + case COAP_EVENT_SERVER_SESSION_NEW: + case COAP_EVENT_SERVER_SESSION_DEL: + default: + break; + } + return 0; +} + +static void +nack_handler(coap_session_t *session COAP_UNUSED, + const coap_pdu_t *sent COAP_UNUSED, + const coap_nack_reason_t reason, + const coap_mid_t id COAP_UNUSED) { + + switch(reason) { + case COAP_NACK_TOO_MANY_RETRIES: + case COAP_NACK_NOT_DELIVERABLE: + case COAP_NACK_RST: + case COAP_NACK_TLS_FAILED: + coap_log(LOG_ERR, "cannot send CoAP pdu\n"); + quit = 1; + break; + case COAP_NACK_ICMP_ISSUE: + default: + ; + } + return; +} + +/* + * Response handler used for coap_send() responses + */ +static coap_response_t +message_handler(coap_session_t *session COAP_UNUSED, + const coap_pdu_t *sent, + const coap_pdu_t *received, + const coap_mid_t id COAP_UNUSED) { + + coap_opt_t *block_opt; + coap_opt_iterator_t opt_iter; + size_t len; + const uint8_t *databuf; + size_t offset; + size_t total; + coap_pdu_code_t rcv_code = coap_pdu_get_code(received); + coap_pdu_type_t rcv_type = coap_pdu_get_type(received); + coap_bin_const_t token = coap_pdu_get_token(received); + + coap_log(LOG_DEBUG, "** process incoming %d.%02d response:\n", + COAP_RESPONSE_CLASS(rcv_code), rcv_code & 0x1F); + if (coap_get_log_level() < LOG_DEBUG) + coap_show_pdu(LOG_INFO, received); + + /* check if this is a response to our original request */ + if (!track_check_token(&token)) { + /* drop if this was just some message, or send RST in case of notification */ + if (!sent && (rcv_type == COAP_MESSAGE_CON || + rcv_type == COAP_MESSAGE_NON)) { + /* Cause a CoAP RST to be sent */ + return COAP_RESPONSE_FAIL; + } + return COAP_RESPONSE_OK; + } + + if (rcv_type == COAP_MESSAGE_RST) { + coap_log(LOG_INFO, "got RST\n"); + return COAP_RESPONSE_OK; + } + + /* output the received data, if any */ + if (COAP_RESPONSE_CLASS(rcv_code) == 2) { + + /* set obs timer if we have successfully subscribed a resource */ + if (doing_observe && !obs_started && + coap_check_option(received, COAP_OPTION_OBSERVE, &opt_iter)) { + coap_log(LOG_DEBUG, + "observation relationship established, set timeout to %d\n", + obs_seconds); + obs_started = 1; + obs_ms = obs_seconds * 1000; + obs_ms_reset = 1; + } + + if (coap_get_data_large(received, &len, &databuf, &offset, &total)) { + append_to_output(databuf, len); + if ((len + offset == total) && add_nl) + append_to_output((const uint8_t*)"\n", 1); + } + + /* Check if Block2 option is set */ + block_opt = coap_check_option(received, COAP_OPTION_BLOCK2, &opt_iter); + if (!single_block_requested && block_opt) { /* handle Block2 */ + + /* TODO: check if we are looking at the correct block number */ + if (coap_opt_block_num(block_opt) == 0) { + /* See if observe is set in first response */ + ready = doing_observe ? coap_check_option(received, + COAP_OPTION_OBSERVE, &opt_iter) == NULL : 1; + } + if(COAP_OPT_BLOCK_MORE(block_opt)) { + doing_getting_block = 1; + } + else { + doing_getting_block = 0; + track_flush_token(&token); + } + return COAP_RESPONSE_OK; + } + } else { /* no 2.05 */ + /* check if an error was signaled and output payload if so */ + if (COAP_RESPONSE_CLASS(rcv_code) >= 4) { + fprintf(stderr, "%d.%02d", COAP_RESPONSE_CLASS(rcv_code), + rcv_code & 0x1F); + if (coap_get_data_large(received, &len, &databuf, &offset, &total)) { + fprintf(stderr, " "); + while(len--) { + fprintf(stderr, "%c", isprint(*databuf) ? *databuf : '.'); + databuf++; + } + } + fprintf(stderr, "\n"); + } + + } + if (!is_mcast) + track_flush_token(&token); + + /* our job is done, we can exit at any time */ + ready = doing_observe ? coap_check_option(received, + COAP_OPTION_OBSERVE, &opt_iter) == NULL : 1; + return COAP_RESPONSE_OK; +} + +static void +usage( const char *program, const char *version) { + const char *p; + char buffer[72]; + const char *lib_build = coap_package_build(); + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf( stderr, "%s v%s -- a small CoAP implementation\n" + "Copyright (C) 2010-2022 Olaf Bergmann and others\n\n" + "Build: %s\n" + "%s\n" + , program, version, lib_build, + coap_string_tls_version(buffer, sizeof(buffer))); + fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer))); + fprintf(stderr, "\n" + "Usage: %s [-a addr] [-b [num,]size] [-e text] [-f file] [-l loss]\n" + "\t\t[-m method] [-o file] [-p port] [-r] [-s duration] [-t type]\n" + "\t\t[-v num] [-w] [-A type] [-B seconds] [G count] [-H hoplimit]\n" + "\t\t[-K interval] [-N] [-O num,text] [-P scheme://address[:port]]\n" + "\t\t[-T token] [-U] [-X size]\n" + "\t\t[[-h match_hint_file] [-k key] [-u user]]\n" + "\t\t[[-c certfile] [-j keyfile] [-n] [-C cafile]\n" + "\t\t[-J pkcs11_pin] [-M raw_pk] [-R trust_casfile]\n" + "\t\t[-S match_pki_sni_file]] URI\n" + "\tURI can be an absolute URI or a URI prefixed with scheme and host\n\n" + "General Options\n" + "\t-a addr\t\tThe local interface address to use\n" + "\t-b [num,]size\tBlock size to be used in GET/PUT/POST requests\n" + "\t \t\t(value must be a multiple of 16 not larger than 1024)\n" + "\t \t\tIf num is present, the request chain will start at\n" + "\t \t\tblock num\n" + "\t-e text\t\tInclude text as payload (use percent-encoding for\n" + "\t \t\tnon-ASCII characters)\n" + "\t-f file\t\tFile to send with PUT/POST (use '-' for STDIN)\n" + "\t-l list\t\tFail to send some datagrams specified by a comma\n" + "\t \t\tseparated list of numbers or number ranges\n" + "\t \t\t(for debugging only)\n" + "\t-l loss%%\tRandomly fail to send datagrams with the specified\n" + "\t \t\tprobability - 100%% all datagrams, 0%% no datagrams\n" + "\t-m method\tRequest method (get|put|post|delete|fetch|patch|ipatch),\n" + "\t \t\tdefault is 'get'\n" + "\t-o file\t\tOutput received data to this file (use '-' for STDOUT)\n" + "\t-p port\t\tListen on specified port\n" + "\t-r \t\tUse reliable protocol (TCP or TLS); requires TCP support\n" + "\t-s duration\tSubscribe to / Observe resource for given duration\n" + "\t \t\tin seconds\n" + "\t-t type\t\tContent format for given resource for PUT/POST\n" + "\t-v num \t\tVerbosity level (default 3, maximum is 9). Above 7,\n" + "\t \t\tthere is increased verbosity in GnuTLS logging\n" + "\t-w \t\tAppend a newline to received data\n" + "\t-A type\t\tAccepted media type\n" + "\t-B seconds\tBreak operation after waiting given seconds\n" + "\t \t\t(default is %d)\n" + "\t-G count\tRepeat the Request 'count' times with a second delay\n" + "\t \t\tbetween each one. Must have a value between 1 and 255\n" + "\t \t\tinclusive. Default is '1'\n" + "\t-H hoplimit\tSet the Hop Limit count to hoplimit for proxies. Must\n" + "\t \t\thave a value between 1 and 255 inclusive.\n" + "\t \t\tDefault is '16'\n" + "\t-K interval\tSend a ping after interval seconds of inactivity\n" + "\t-L value\tSum of one or more COAP_BLOCK_* flag valuess for block\n" + "\t \t\thandling methods. Default is 1 (COAP_BLOCK_USE_LIBCOAP)\n" + "\t \t\t(Sum of one or more of 1,2,4 and 8)\n" + "\t-N \t\tSend NON-confirmable message\n" + "\t-O num,text\tAdd option num with contents text to request. If the\n" + "\t \t\ttext begins with 0x, then the hex text (two [0-9a-f] per\n" + "\t \t\tbyte) is converted to binary data\n" + "\t-P scheme://address[:port]\tScheme, address and optional port to\n" + "\t \t\tdefine how to connect to a CoAP proxy (automatically adds\n" + "\t \t\tProxy-Uri option to request) to forward the request to.\n" + "\t \t\tScheme is one of coap, coaps, coap+tcp and coaps+tcp\n" + "\t-T token\tDefine the initial starting token\n" + "\t-U \t\tNever include Uri-Host or Uri-Port options\n" + "\t-X size\t\tMaximum message size to use for TCP based connections\n" + "\t \t\t(default is 8388864). Maximum value of 2^32 -1\n" + ,program, wait_seconds); + fprintf( stderr, + "PSK Options (if supported by underlying (D)TLS library)\n" + "\t-h match_hint_file\n" + "\t \t\tThis is a file that contains one or more lines of\n" + "\t \t\treceived Identity Hints to match to use different\n" + "\t \t\tuser identity and associated pre-shared key (PSK) (comma\n" + "\t \t\tseparated) instead of the '-k key' and '-u user'\n" + "\t \t\toptions. E.g., per line\n" + "\t \t\t hint_to_match,use_user,with_key\n" + "\t \t\tNote: -k and -u still need to be defined for the default\n" + "\t \t\tin case there is no match\n" + "\t-k key \t\tPre-shared key for the specified user identity\n" + "\t-u user\t\tUser identity to send for pre-shared key mode\n" + "PKI Options (if supported by underlying (D)TLS library)\n" + "\tNote: If any one of '-c certfile', '-j keyfile' or '-C cafile' is in\n" + "\tPKCS11 URI naming format (pkcs11: prefix), then any remaining non\n" + "\tPKCS11 URI file definitions have to be in DER, not PEM, format.\n" + "\tOtherwise all of '-c certfile', '-j keyfile' or '-C cafile' are in\n" + "\tPEM format.\n\n" + "\t-c certfile\tPEM file or PKCS11 URI for the certificate. The private\n" + "\t \t\tkey can also be in the PEM file, or has the same PKCS11\n" + "\t \t\tURI. If not, the private key is defined by '-j keyfile'\n" + "\t-j keyfile\tPEM file or PKCS11 URI for the private key for the\n" + "\t \t\tcertificate in '-c certfile' if the parameter is\n" + "\t \t\tdifferent from certfile in '-c certfile'\n" + "\t-n \t\tDisable remote peer certificate checking\n" + "\t-C cafile\tPEM file or PKCS11 URI for the CA certificate that was\n" + "\t \t\tused to sign the server certfile. Ideally the client\n" + "\t \t\tcertificate should be signed by the same CA so that\n" + "\t \t\tmutual authentication can take place. The contents of\n" + "\t \t\tcafile are added to the trusted store of root CAs.\n" + "\t \t\tUsing the -C or -R options will trigger the\n" + "\t \t\tvalidation of the server certificate unless overridden\n" + "\t \t\tby the -n option\n" + "\t-J pkcs11_pin\tThe user pin to unlock access to the PKCS11 token\n" + "\t-M rpk_file\tRaw Public Key (RPK) PEM file or PKCS11 URI that\n" + "\t \t\tcontains both PUBLIC KEY and PRIVATE KEY or just\n" + "\t \t\tEC PRIVATE KEY. (GnuTLS and TinyDTLS(PEM) support only).\n" + "\t \t\t'-C cafile' or '-R trust_casfile' are not required\n" + "\t-R trust_casfile\tPEM file containing the set of trusted root CAs\n" + "\t \t\tthat are to be used to validate the server certificate.\n" + "\t \t\tAlternatively, this can point to a directory containing\n" + "\t \t\ta set of CA PEM files.\n" + "\t \t\tUsing '-R trust_casfile' disables common CA mutual\n" + "\t \t\tauthentication which can only be done by using\n" + "\t \t\t'-C cafile'.\n" + "\t \t\tUsing the -C or -R options will will trigger the\n" + "\t \t\tvalidation of the server certificate unless overridden\n" + "\t \t\tby the -n option\n" + ); + fprintf( stderr, + "Examples:\n" + "\tcoap-client -m get coap://[::1]/\n" + "\tcoap-client -m get coap://[::1]/.well-known/core\n" + "\tcoap-client -m get coap+tcp://[::1]/.well-known/core\n" + "\tcoap-client -m get coaps://[::1]/.well-known/core\n" + "\tcoap-client -m get coaps+tcp://[::1]/.well-known/core\n" + "\tcoap-client -m get -T cafe coap://[::1]/time\n" + "\techo -n 1000 | coap-client -m put -T cafe coap://[::1]/time -f -\n" + ); +} + +typedef struct { + unsigned char code; + const char *media_type; +} content_type_t; + +static void +cmdline_content_type(char *arg, uint16_t key) { + static content_type_t content_types[] = { + { 0, "plain" }, + { 0, "text/plain" }, + { 40, "link" }, + { 40, "link-format" }, + { 40, "application/link-format" }, + { 41, "xml" }, + { 41, "application/xml" }, + { 42, "binary" }, + { 42, "octet-stream" }, + { 42, "application/octet-stream" }, + { 47, "exi" }, + { 47, "application/exi" }, + { 50, "json" }, + { 50, "application/json" }, + { 60, "cbor" }, + { 60, "application/cbor" }, + { 255, NULL } + }; + coap_optlist_t *node; + unsigned char i; + uint16_t value; + uint8_t buf[2]; + + if (isdigit((int)arg[0])) { + value = atoi(arg); + } else { + for (i=0; + content_types[i].media_type && + strncmp(arg, content_types[i].media_type, strlen(arg)) != 0 ; + ++i) + ; + + if (content_types[i].media_type) { + value = content_types[i].code; + } else { + coap_log(LOG_WARNING, "W: unknown content-format '%s'\n",arg); + return; + } + } + + node = coap_new_optlist(key, coap_encode_var_safe(buf, sizeof(buf), value), buf); + if (node) { + coap_insert_optlist(&optlist, node); + } +} + +static int +cmdline_hop_limit(char *arg) { + coap_optlist_t *node; + uint32_t value; + uint8_t buf[4]; + + value = strtol(arg, NULL, 10); + if (value < 1 || value > 255) { + return 0; + } + node = coap_new_optlist(COAP_OPTION_HOP_LIMIT, coap_encode_var_safe(buf, sizeof(buf), value), buf); + if (node) { + coap_insert_optlist(&optlist, node); + } + return 1; +} + + +static uint16_t +get_default_port(const coap_uri_t *u) { + return coap_uri_scheme_is_secure(u) ? COAPS_DEFAULT_PORT : COAP_DEFAULT_PORT; +} + +/** + * Sets global URI options according to the URI passed as @p arg. + * This function returns 0 on success or -1 on error. + * + * @param arg The URI string. + * @param create_uri_opts Flags that indicate whether Uri-Host and + * Uri-Port should be suppressed. + * @return 0 on success, -1 otherwise + */ +static int +cmdline_uri(char *arg, int create_uri_opts) { + unsigned char portbuf[2]; +#define BUFSIZE 100 + unsigned char _buf[BUFSIZE]; + unsigned char *buf = _buf; + size_t buflen; + int res; + + if (!proxy_scheme_option && proxy.host.length) { + /* create Proxy-Uri from argument */ + size_t len = strlen(arg); + if (len > 1034) { + coap_log(LOG_ERR, "Absolute URI length must be <= 1034 bytes for a proxy\n"); + return -1; + } + + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_PROXY_URI, + len, + (unsigned char *)arg)); + + } else { /* split arg into Uri-* options */ + if (coap_split_uri((unsigned char *)arg, strlen(arg), &uri) < 0) { + coap_log(LOG_ERR, "invalid CoAP URI\n"); + return -1; + } + + if (uri.scheme==COAP_URI_SCHEME_COAPS && !reliable && !coap_dtls_is_supported()) { + coap_log(LOG_EMERG, + "coaps URI scheme not supported in this version of libcoap\n"); + return -1; + } + + if ((uri.scheme==COAP_URI_SCHEME_COAPS_TCP || (uri.scheme==COAP_URI_SCHEME_COAPS && reliable)) && !coap_tls_is_supported()) { + coap_log(LOG_EMERG, + "coaps+tcp URI scheme not supported in this version of libcoap\n"); + return -1; + } + + if (uri.scheme==COAP_URI_SCHEME_COAP_TCP && !coap_tcp_is_supported()) { + /* coaps+tcp caught above */ + coap_log(LOG_EMERG, + "coap+tcp URI scheme not supported in this version of libcoap\n"); + return -1; + } + + if (uri.port != get_default_port(&uri) && create_uri_opts) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_PORT, + coap_encode_var_safe(portbuf, sizeof(portbuf), + (uri.port & 0xffff)), + portbuf)); + } + + if (uri.path.length) { + buflen = BUFSIZE; + if (uri.path.length > BUFSIZE) + coap_log(LOG_WARNING, "URI path will be truncated (max buffer %d)\n", BUFSIZE); + res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + + while (res--) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_PATH, + coap_opt_length(buf), + coap_opt_value(buf))); + + buf += coap_opt_size(buf); + } + } + + if (uri.query.length) { + buflen = BUFSIZE; + buf = _buf; + res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); + + while (res--) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_QUERY, + coap_opt_length(buf), + coap_opt_value(buf))); + + buf += coap_opt_size(buf); + } + } + } + + return 0; +} + +static int +cmdline_blocksize(char *arg) { + uint16_t size; + + again: + size = 0; + while(*arg && *arg != ',') + size = size * 10 + (*arg++ - '0'); + + if (*arg == ',') { + arg++; + block.num = size; + if (size != 0) { + /* Random access selection - only handle single response */ + single_block_requested = 1; + } + goto again; + } + + if (size) + block.szx = (coap_fls(size >> 4) - 1) & 0x07; + + flags |= FLAGS_BLOCK; + return 1; +} + +/* Called after processing the options from the commandline to set + * Block1 or Block2 depending on method. */ +static void +set_blocksize(void) { + static unsigned char buf[4]; /* hack: temporarily take encoded bytes */ + uint16_t opt; + unsigned int opt_length; + + if (method != COAP_REQUEST_DELETE) { + if (method == COAP_REQUEST_GET || method == COAP_REQUEST_FETCH) { + opt = COAP_OPTION_BLOCK2; + } + else { + opt = COAP_OPTION_BLOCK1; + } + + block.m = (opt == COAP_OPTION_BLOCK1) && + ((1ull << (block.szx + 4)) < payload.length); + + opt_length = coap_encode_var_safe(buf, sizeof(buf), + (block.num << 4 | block.m << 3 | block.szx)); + + coap_insert_optlist(&optlist, coap_new_optlist(opt, opt_length, buf)); + } +} + +static void +cmdline_subscribe(char *arg) { + uint8_t buf[4]; + + obs_seconds = atoi(arg); + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_OBSERVE, + coap_encode_var_safe(buf, sizeof(buf), + COAP_OBSERVE_ESTABLISH), buf) + ); + doing_observe = 1; +} + +static int +cmdline_proxy(char *arg) { + if (coap_split_uri((unsigned char *)arg, strlen(arg), &proxy) < 0 || + proxy.path.length != 0 || proxy.query.length != 0) { + coap_log(LOG_ERR, "invalid CoAP Proxy definition\n"); + return 0; + } + return 1; +} + +static inline void +cmdline_token(char *arg) { + base_token.length = min(sizeof(_token_data), strlen(arg)); + if (base_token.length > 0) { + memcpy((char *)base_token.s, arg, base_token.length); + } +} + +/** + * Utility function to convert a hex digit to its corresponding + * numerical value. + * + * param c The hex digit to convert. Must be in [0-9A-Fa-f]. + * + * return The numerical representation of @p c. + */ +static uint8_t +hex2char(char c) { + assert(isxdigit(c)); + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + else if ('A' <= c && c <= 'F') + return c - 'A' + 10; + else + return c - '0'; +} + +/** + * Converts the sequence of hex digits in src to a sequence of bytes. + * + * This function returns the number of bytes that have been written to + * @p dst. + * + * param[in] src The null-terminated hex string to convert. + * param[out] dst Conversion result. + * + * return The length of @p dst. + */ +static size_t +convert_hex_string(const char *src, uint8_t *dst) { + uint8_t *p = dst; + while (isxdigit((int)src[0]) && isxdigit((int)src[1])) { + *p++ = (hex2char(src[0]) << 4) + hex2char(src[1]); + src += 2; + } + if (src[0] != '\0') { /* error in hex input */ + coap_log(LOG_WARNING, "invalid hex string in option '%s'\n", src); + } + return p - dst; +} + +static void +cmdline_option(char *arg) { + unsigned int num = 0; + + while (*arg && *arg != ',') { + num = num * 10 + (*arg - '0'); + ++arg; + } + if (*arg == ',') + ++arg; + + /* read hex string when arg starts with "0x" */ + if (arg[0] == '0' && arg[1] == 'x') { + /* As the command line option is part of our environment we can do + * the conversion in place. */ + size_t len = convert_hex_string(arg + 2, (uint8_t *)arg); + + /* On success, 2 * len + 2 == strlen(arg) */ + coap_insert_optlist(&optlist, + coap_new_optlist(num, len, (unsigned char *)arg)); + } else { /* null-terminated character string */ + coap_insert_optlist(&optlist, + coap_new_optlist(num, strlen(arg), (unsigned char *)arg)); + } + if (num == COAP_OPTION_PROXY_SCHEME) { + proxy_scheme_option = 1; + if (strcasecmp(arg, "coaps+tcp") == 0) { + proxy.scheme = COAP_URI_SCHEME_COAPS_TCP; + proxy.port = COAPS_DEFAULT_PORT; + } + else if (strcasecmp(arg, "coap+tcp") == 0) { + proxy.scheme = COAP_URI_SCHEME_COAP_TCP; + proxy.port = COAP_DEFAULT_PORT; + } + else if (strcasecmp(arg, "coaps") == 0) { + proxy.scheme = COAP_URI_SCHEME_COAPS; + proxy.port = COAPS_DEFAULT_PORT; + } + else if (strcasecmp(arg, "coap") == 0) { + proxy.scheme = COAP_URI_SCHEME_COAP; + proxy.port = COAP_DEFAULT_PORT; + } + else { + coap_log(LOG_WARNING, "%s is not a supported CoAP Proxy-Scheme\n", arg); + } + } + if (num == COAP_OPTION_URI_HOST) { + uri_host_option = 1; + } +} + +/** + * Calculates decimal value from hexadecimal ASCII character given in + * @p c. The caller must ensure that @p c actually represents a valid + * heaxdecimal character, e.g. with isxdigit(3). + * + * @hideinitializer + */ +#define hexchar_to_dec(c) ((c) & 0x40 ? ((c) & 0x0F) + 9 : ((c) & 0x0F)) + +/** + * Decodes percent-encoded characters while copying the string @p seg + * of size @p length to @p buf. The caller of this function must + * ensure that the percent-encodings are correct (i.e. the character + * '%' is always followed by two hex digits. and that @p buf provides + * sufficient space to hold the result. This function is supposed to + * be called by make_decoded_option() only. + * + * @param seg The segment to decode and copy. + * @param length Length of @p seg. + * @param buf The result buffer. + */ +static void +decode_segment(const uint8_t *seg, size_t length, unsigned char *buf) { + + while (length--) { + + if (*seg == '%') { + *buf = (hexchar_to_dec(seg[1]) << 4) + hexchar_to_dec(seg[2]); + + seg += 2; length -= 2; + } else { + *buf = *seg; + } + + ++buf; ++seg; + } +} + +/** + * Runs through the given path (or query) segment and checks if + * percent-encodings are correct. This function returns @c -1 on error + * or the length of @p s when decoded. + */ +static int +check_segment(const uint8_t *s, size_t length) { + + int n = 0; + + while (length) { + if (*s == '%') { + if (length < 2 || !(isxdigit(s[1]) && isxdigit(s[2]))) + return -1; + + s += 2; + length -= 2; + } + + ++s; ++n; --length; + } + + return n; +} + +static int +cmdline_input(char *text, coap_string_t *buf) { + int len; + len = check_segment((unsigned char *)text, strlen(text)); + + if (len < 0) + return 0; + + buf->s = (unsigned char *)coap_malloc(len); + if (!buf->s) + return 0; + + buf->length = len; + decode_segment((unsigned char *)text, strlen(text), buf->s); + return 1; +} + +static int +cmdline_input_from_file(char *filename, coap_string_t *buf) { + FILE *inputfile = NULL; + ssize_t len; + int result = 1; + struct stat statbuf; + + if (!filename || !buf) + return 0; + + if (filename[0] == '-' && !filename[1]) { /* read from stdin */ + buf->length = 20000; + buf->s = (unsigned char *)coap_malloc(buf->length); + if (!buf->s) + return 0; + + inputfile = stdin; + } else { + /* read from specified input file */ + inputfile = fopen(filename, "r"); + if ( !inputfile ) { + perror("cmdline_input_from_file: fopen"); + return 0; + } + + if (fstat(fileno(inputfile), &statbuf) < 0) { + perror("cmdline_input_from_file: stat"); + fclose(inputfile); + return 0; + } + + buf->length = statbuf.st_size; + buf->s = (unsigned char *)coap_malloc(buf->length); + if (!buf->s) { + fclose(inputfile); + return 0; + } + } + + len = fread(buf->s, 1, buf->length, inputfile); + + if (len < 0 || ((size_t)len < buf->length)) { + if (ferror(inputfile) != 0) { + perror("cmdline_input_from_file: fread"); + coap_free(buf->s); + buf->length = 0; + buf->s = NULL; + result = 0; + } else { + buf->length = len; + } + } + + if (inputfile != stdin) + fclose(inputfile); + + return result; +} + +static method_t +cmdline_method(char *arg) { + static const char *methods[] = + { 0, "get", "post", "put", "delete", "fetch", "patch", "ipatch", 0}; + unsigned char i; + + for (i=1; methods[i] && strcasecmp(arg,methods[i]) != 0 ; ++i) + ; + + return i; /* note that we do not prevent illegal methods */ +} + +static ssize_t +cmdline_read_user(char *arg, unsigned char **buf, size_t maxlen) { + size_t len = strnlen(arg, maxlen); + if (len) { + *buf = (unsigned char *)arg; + /* len is the size or less, so 0 terminate to maxlen */ + (*buf)[len] = '\000'; + } + /* 0 length Identity is valid */ + return len; +} + +static ssize_t +cmdline_read_key(char *arg, unsigned char **buf, size_t maxlen) { + size_t len = strnlen(arg, maxlen); + if (len) { + *buf = (unsigned char *)arg; + return len; + } + /* Need at least one byte for the pre-shared key */ + coap_log( LOG_CRIT, "Invalid Pre-Shared Key specified\n" ); + return -1; +} + +static int cmdline_read_hint_check(const char *arg) { + FILE *fp = fopen(arg, "r"); + static char tmpbuf[256]; + if (fp == NULL) { + coap_log(LOG_ERR, "Hint file: %s: Unable to open\n", arg); + return 0; + } + while (fgets(tmpbuf, sizeof(tmpbuf), fp) != NULL) { + char *cp = tmpbuf; + char *tcp = strchr(cp, '\n'); + + if (tmpbuf[0] == '#') + continue; + if (tcp) + *tcp = '\000'; + + tcp = strchr(cp, ','); + if (tcp) { + ih_def_t *new_ih_list; + new_ih_list = realloc(valid_ihs.ih_list, + (valid_ihs.count + 1)*sizeof (valid_ihs.ih_list[0])); + if (new_ih_list == NULL) { + break; + } + valid_ihs.ih_list = new_ih_list; + valid_ihs.ih_list[valid_ihs.count].hint_match = strndup(cp, tcp-cp); + cp = tcp+1; + tcp = strchr(cp, ','); + if (tcp) { + valid_ihs.ih_list[valid_ihs.count].new_identity = + coap_new_bin_const((const uint8_t *)cp, tcp-cp); + cp = tcp+1; + valid_ihs.ih_list[valid_ihs.count].new_key = + coap_new_bin_const((const uint8_t *)cp, strlen(cp)); + valid_ihs.count++; + } + else { + /* Badly formatted */ + free(valid_ihs.ih_list[valid_ihs.count].hint_match); + } + } + } + fclose(fp); + return valid_ihs.count > 0; +} + +static uint8_t *read_file_mem(const char* filename, size_t *length) { + FILE *f; + uint8_t *buf; + struct stat statbuf; + + *length = 0; + if (!filename || !(f = fopen(filename, "r"))) + return NULL; + + if (fstat(fileno(f), &statbuf) == -1) { + fclose(f); + return NULL; + } + + buf = coap_malloc(statbuf.st_size+1); + if (!buf) { + fclose(f); + return NULL; + } + + if (fread(buf, 1, statbuf.st_size, f) != (size_t)statbuf.st_size) { + fclose(f); + coap_free(buf); + return NULL; + } + buf[statbuf.st_size] = '\000'; + *length = (size_t)(statbuf.st_size + 1); + fclose(f); + return buf; +} + +static int +verify_cn_callback(const char *cn, + const uint8_t *asn1_public_cert COAP_UNUSED, + size_t asn1_length COAP_UNUSED, + coap_session_t *session COAP_UNUSED, + unsigned depth, + int validated COAP_UNUSED, + void *arg COAP_UNUSED +) { + coap_log(LOG_INFO, "CN '%s' presented by server (%s)\n", + cn, depth ? "CA" : "Certificate"); + return 1; +} + +static const coap_dtls_cpsk_info_t * +verify_ih_callback(coap_str_const_t *hint, + coap_session_t *c_session COAP_UNUSED, + void *arg +) { + coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg; + char lhint[COAP_DTLS_HINT_LENGTH]; + static coap_dtls_cpsk_info_t psk_identity_info; + size_t i; + + snprintf(lhint, sizeof(lhint), "%.*s", (int)hint->length, hint->s); + coap_log(LOG_INFO, "Identity Hint '%s' provided\n", lhint); + + /* Test for hint to possibly change identity + key */ + for (i = 0; i < valid_ihs.count; i++) { + if (strcmp(lhint, valid_ihs.ih_list[i].hint_match) == 0) { + /* Preset */ + psk_identity_info = *psk_info; + if (valid_ihs.ih_list[i].new_key) { + psk_identity_info.key = *valid_ihs.ih_list[i].new_key; + } + if (valid_ihs.ih_list[i].new_identity) { + psk_identity_info.identity = *valid_ihs.ih_list[i].new_identity; + } + coap_log(LOG_INFO, "Switching to using '%s' identity + '%s' key\n", + psk_identity_info.identity.s, psk_identity_info.key.s); + return &psk_identity_info; + } + } + /* Just use the defined key for now as passed in by arg */ + return psk_info; +} + +static coap_dtls_pki_t * +setup_pki(coap_context_t *ctx) { + static coap_dtls_pki_t dtls_pki; + static char client_sni[256]; + + /* If general root CAs are defined */ + if (root_ca_file) { + struct stat stbuf; + if ((stat(root_ca_file, &stbuf) == 0) && S_ISDIR(stbuf.st_mode)) { + coap_context_set_pki_root_cas(ctx, NULL, root_ca_file); + } else { + coap_context_set_pki_root_cas(ctx, root_ca_file, NULL); + } + } + + memset(client_sni, 0, sizeof(client_sni)); + memset (&dtls_pki, 0, sizeof(dtls_pki)); + dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; + if (ca_file || root_ca_file) { + /* + * Add in additional certificate checking. + * This list of enabled can be tuned for the specific + * requirements - see 'man coap_encryption'. + * + * Note: root_ca_file is setup separately using + * coap_context_set_pki_root_cas(), but this is used to define what + * checking actually takes place. + */ + dtls_pki.verify_peer_cert = verify_peer_cert; + dtls_pki.check_common_ca = !root_ca_file; + dtls_pki.allow_self_signed = 1; + dtls_pki.allow_expired_certs = 1; + dtls_pki.cert_chain_validation = 1; + dtls_pki.cert_chain_verify_depth = 2; + dtls_pki.check_cert_revocation = 1; + dtls_pki.allow_no_crl = 1; + dtls_pki.allow_expired_crl = 1; + } + else if (is_rpk_not_cert) { + dtls_pki.verify_peer_cert = verify_peer_cert; + } + dtls_pki.is_rpk_not_cert = is_rpk_not_cert; + dtls_pki.validate_cn_call_back = verify_cn_callback; + if ((uri.host.length == 3 && memcmp(uri.host.s, "::1", 3) != 0) || + (uri.host.length == 9 && memcmp(uri.host.s, "127.0.0.1", 9) != 0)) + memcpy(client_sni, uri.host.s, min(uri.host.length, sizeof(client_sni)-1)); + else + memcpy(client_sni, "localhost", 9); + + dtls_pki.client_sni = client_sni; + if ((key_file && strncasecmp (key_file, "pkcs11:", 7) == 0) || + (cert_file && strncasecmp (cert_file, "pkcs11:", 7) == 0) || + (ca_file && strncasecmp (ca_file, "pkcs11:", 7) == 0)) { + dtls_pki.pki_key.key_type = COAP_PKI_KEY_PKCS11; + dtls_pki.pki_key.key.pkcs11.public_cert = cert_file; + dtls_pki.pki_key.key.pkcs11.private_key = key_file ? + key_file : cert_file; + dtls_pki.pki_key.key.pkcs11.ca = ca_file; + dtls_pki.pki_key.key.pkcs11.user_pin = pkcs11_pin; + } + else if (!is_rpk_not_cert) { + dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM; + dtls_pki.pki_key.key.pem.public_cert = cert_file; + dtls_pki.pki_key.key.pem.private_key = key_file ? key_file : cert_file; + dtls_pki.pki_key.key.pem.ca_file = ca_file; + } + else { + /* Map file into memory */ + if (ca_mem == 0 && cert_mem == 0 && key_mem == 0) { + ca_mem = read_file_mem(ca_file, &ca_mem_len); + cert_mem = read_file_mem(cert_file, &cert_mem_len); + key_mem = read_file_mem(key_file, &key_mem_len); + } + dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM_BUF; + dtls_pki.pki_key.key.pem_buf.ca_cert = ca_mem; + dtls_pki.pki_key.key.pem_buf.public_cert = cert_mem; + dtls_pki.pki_key.key.pem_buf.private_key = key_mem ? key_mem : cert_mem; + dtls_pki.pki_key.key.pem_buf.ca_cert_len = ca_mem_len; + dtls_pki.pki_key.key.pem_buf.public_cert_len = cert_mem_len; + dtls_pki.pki_key.key.pem_buf.private_key_len = key_mem ? + key_mem_len : cert_mem_len; + } + return &dtls_pki; +} + +static coap_dtls_cpsk_t * +setup_psk( + const uint8_t *identity, + size_t identity_len, + const uint8_t *key, + size_t key_len +) { + static coap_dtls_cpsk_t dtls_psk; + static char client_sni[256]; + + memset(client_sni, 0, sizeof(client_sni)); + memset (&dtls_psk, 0, sizeof(dtls_psk)); + dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION; + dtls_psk.validate_ih_call_back = verify_ih_callback; + dtls_psk.ih_call_back_arg = &dtls_psk.psk_info; + if (uri.host.length) + memcpy(client_sni, uri.host.s, + min(uri.host.length, sizeof(client_sni) - 1)); + else + memcpy(client_sni, "localhost", 9); + dtls_psk.client_sni = client_sni; + dtls_psk.psk_info.identity.s = identity; + dtls_psk.psk_info.identity.length = identity_len; + dtls_psk.psk_info.key.s = key; + dtls_psk.psk_info.key.length = key_len; + return &dtls_psk; +} + +#ifdef _WIN32 +#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR) +#endif + +static coap_session_t* +open_session( + coap_context_t *ctx, + coap_proto_t proto, + coap_address_t *bind_addr, + coap_address_t *dst, + const uint8_t *identity, + size_t identity_len, + const uint8_t *key, + size_t key_len +) { + coap_session_t *session; + + if (proto == COAP_PROTO_DTLS || proto == COAP_PROTO_TLS) { + /* Encrypted session */ + if (root_ca_file || ca_file || cert_file) { + /* Setup PKI session */ + coap_dtls_pki_t *dtls_pki = setup_pki(ctx); + session = coap_new_client_session_pki(ctx, bind_addr, dst, proto, dtls_pki); + } + else if (identity || key) { + /* Setup PSK session */ + coap_dtls_cpsk_t *dtls_psk = setup_psk(identity, identity_len, + key, key_len); + session = coap_new_client_session_psk2(ctx, bind_addr, dst, proto, + dtls_psk); + } + else { + /* No PKI or PSK defined, as encrypted, use PKI */ + coap_dtls_pki_t *dtls_pki = setup_pki(ctx); + session = coap_new_client_session_pki(ctx, bind_addr, dst, proto, dtls_pki); + } + } + else { + /* Non-encrypted session */ + session = coap_new_client_session(ctx, bind_addr, dst, proto); + } + return session; +} + +static coap_session_t * +get_session( + coap_context_t *ctx, + const char *local_addr, + const char *local_port, + coap_proto_t proto, + coap_address_t *dst, + const uint8_t *identity, + size_t identity_len, + const uint8_t *key, + size_t key_len +) { + coap_session_t *session = NULL; + + is_mcast = coap_is_mcast(dst); + if ( local_addr ) { + int s; + struct addrinfo hints; + struct addrinfo *result = NULL, *rp; + + memset( &hints, 0, sizeof( struct addrinfo ) ); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = COAP_PROTO_RELIABLE(proto) ? SOCK_STREAM : SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL; + + s = getaddrinfo( local_addr, local_port, &hints, &result ); + if ( s != 0 ) { + fprintf( stderr, "getaddrinfo: %s\n", gai_strerror( s ) ); + return NULL; + } + + /* iterate through results until success */ + for ( rp = result; rp != NULL; rp = rp->ai_next ) { + coap_address_t bind_addr; + if ( rp->ai_addrlen <= (socklen_t)sizeof( bind_addr.addr ) ) { + coap_address_init( &bind_addr ); + bind_addr.size = (socklen_t)rp->ai_addrlen; + memcpy( &bind_addr.addr, rp->ai_addr, rp->ai_addrlen ); + session = open_session(ctx, proto, &bind_addr, dst, + identity, identity_len, key, key_len); + if ( session ) + break; + } + } + freeaddrinfo( result ); + } else if (local_port) { + coap_address_t bind_addr; + + coap_address_init(&bind_addr); + bind_addr.size = dst->size; + bind_addr.addr.sa.sa_family = dst->addr.sa.sa_family; + /* port is in same place for IPv4 and IPv6 */ + bind_addr.addr.sin.sin_port = ntohs(atoi(local_port)); + session = open_session(ctx, proto, &bind_addr, dst, + identity, identity_len, key, key_len); + } else { + session = open_session(ctx, proto, NULL, dst, + identity, identity_len, key, key_len); + } + return session; +} + +int +main(int argc, char **argv) { + coap_context_t *ctx = NULL; + coap_session_t *session = NULL; + coap_address_t dst; + static char addr[INET6_ADDRSTRLEN]; + void *addrptr = NULL; + int result = -1; + coap_pdu_t *pdu; + static coap_str_const_t server; + uint16_t port = COAP_DEFAULT_PORT; + char port_str[NI_MAXSERV] = "0"; + char node_str[NI_MAXHOST] = ""; + int opt, res; + coap_log_t log_level = LOG_WARNING; + unsigned char *user = NULL, *key = NULL; + ssize_t user_length = -1, key_length = 0; + int create_uri_opts = 1; + size_t i; + coap_uri_scheme_t scheme; + uint32_t repeat_ms = REPEAT_DELAY_MS; + uint8_t *data = NULL; + size_t data_len = 0; +#ifndef _WIN32 + struct sigaction sa; +#endif + + while ((opt = getopt(argc, argv, "a:b:c:e:f:h:j:k:l:m:no:p:rs:t:u:v:wA:B:C:G:H:J:K:L:M:NO:P:R:T:UX:")) != -1) { + switch (opt) { + case 'a': + strncpy(node_str, optarg, NI_MAXHOST - 1); + node_str[NI_MAXHOST - 1] = '\0'; + break; + case 'b': + cmdline_blocksize(optarg); + break; + case 'B': + wait_seconds = atoi(optarg); + break; + case 'c': + cert_file = optarg; + break; + case 'C': + ca_file = optarg; + break; + case 'R': + root_ca_file = optarg; + break; + case 'e': + if (!cmdline_input(optarg, &payload)) + payload.length = 0; + break; + case 'f': + if (!cmdline_input_from_file(optarg, &payload)) + payload.length = 0; + break; + case 'j' : + key_file = optarg; + break; + case 'J' : + pkcs11_pin = optarg; + break; + case 'k': + key_length = cmdline_read_key(optarg, &key, MAX_KEY); + break; + case 'L': + block_mode = strtoul(optarg, NULL, 0); + if (!(block_mode & COAP_BLOCK_USE_LIBCOAP)) { + fprintf(stderr, "Block mode must include COAP_BLOCK_USE_LIBCOAP (1)\n"); + exit(-1); + } + break; + case 'p': + strncpy(port_str, optarg, NI_MAXSERV - 1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'm': + method = cmdline_method(optarg); + break; + case 'w': + add_nl = 1; + break; + case 'N': + msgtype = COAP_MESSAGE_NON; + break; + case 's': + cmdline_subscribe(optarg); + break; + case 'o': + output_file.length = strlen(optarg); + output_file.s = (unsigned char *)coap_malloc(output_file.length + 1); + + if (!output_file.s) { + fprintf(stderr, "cannot set output file: insufficient memory\n"); + exit(-1); + } else { + /* copy filename including trailing zero */ + memcpy(output_file.s, optarg, output_file.length + 1); + } + break; + case 'A': + cmdline_content_type(optarg, COAP_OPTION_ACCEPT); + break; + case 't': + cmdline_content_type(optarg, COAP_OPTION_CONTENT_TYPE); + break; + case 'M': + cert_file = optarg; + is_rpk_not_cert = 1; + break; + case 'O': + cmdline_option(optarg); + break; + case 'P': + if (!cmdline_proxy(optarg)) { + fprintf(stderr, "error specifying proxy address\n"); + exit(-1); + } + break; + case 'T': + cmdline_token(optarg); + break; + case 'u': + user_length = cmdline_read_user(optarg, &user, MAX_USER); + break; + case 'U': + create_uri_opts = 0; + break; + case 'v': + log_level = strtol(optarg, NULL, 10); + break; + case 'l': + if (!coap_debug_set_packet_loss(optarg)) { + usage(argv[0], LIBCOAP_PACKAGE_VERSION); + exit(1); + } + break; + case 'r': + reliable = coap_tcp_is_supported(); + break; + case 'K': + ping_seconds = atoi(optarg); + break; + case 'h': + if (!cmdline_read_hint_check(optarg)) { + usage(argv[0], LIBCOAP_PACKAGE_VERSION); + exit(1); + } + break; + case 'H': + if (!cmdline_hop_limit(optarg)) + fprintf(stderr, "Hop Limit has to be > 0 and < 256\n"); + break; + case 'n': + verify_peer_cert = 0; + break; + case 'G': + repeat_count = atoi(optarg); + if (!repeat_count || repeat_count > 255) { + fprintf(stderr, "'-G count' has to be > 0 and < 256\n"); + repeat_count = 1; + } + break; + case 'X': + csm_max_message_size = strtol(optarg, NULL, 10); + break; + default: + usage( argv[0], LIBCOAP_PACKAGE_VERSION ); + exit( 1 ); + } + } + +#ifdef _WIN32 + signal(SIGINT, handle_sigint); +#else + memset (&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = handle_sigint; + sa.sa_flags = 0; + sigaction (SIGINT, &sa, NULL); + sigaction (SIGTERM, &sa, NULL); + /* So we do not exit on a SIGPIPE */ + sa.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &sa, NULL); +#endif + + coap_startup(); + coap_dtls_set_log_level(log_level); + coap_set_log_level(log_level); + + if (optind < argc) { + if (cmdline_uri(argv[optind], create_uri_opts) < 0) { + exit(1); + } + } else { + usage( argv[0], LIBCOAP_PACKAGE_VERSION ); + exit( 1 ); + } + + if (key_length < 0) { + coap_log( LOG_CRIT, "Invalid pre-shared key specified\n" ); + goto finish; + } + + if (proxy.host.length) { + server = proxy.host; + port = proxy.port; + scheme = proxy.scheme; + } else { + server = uri.host; + port = proxy_scheme_option ? proxy.port : uri.port; + scheme = proxy_scheme_option ? proxy.scheme : uri.scheme; + } + + /* resolve destination address where server should be sent */ + res = resolve_address(&server, &dst.addr.sa); + + if (res < 0) { + fprintf(stderr, "failed to resolve address\n"); + exit(-1); + } + + ctx = coap_new_context( NULL ); + if ( !ctx ) { + coap_log( LOG_EMERG, "cannot create context\n" ); + goto finish; + } + + coap_context_set_keepalive(ctx, ping_seconds); + coap_context_set_block_mode(ctx, block_mode); + if (csm_max_message_size) + coap_context_set_csm_max_message_size(ctx, csm_max_message_size); + coap_register_response_handler(ctx, message_handler); + coap_register_event_handler(ctx, event_handler); + coap_register_nack_handler(ctx, nack_handler); + + dst.size = res; + dst.addr.sin.sin_port = htons( port ); + + session = get_session( + ctx, + node_str[0] ? node_str : NULL, port_str, + scheme==COAP_URI_SCHEME_COAP_TCP ? COAP_PROTO_TCP : + scheme==COAP_URI_SCHEME_COAPS_TCP ? COAP_PROTO_TLS : + (reliable ? + scheme==COAP_URI_SCHEME_COAPS ? COAP_PROTO_TLS : COAP_PROTO_TCP + : scheme==COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_UDP), + &dst, + user_length >= 0 ? user : NULL, + user_length >= 0 ? user_length : 0, + key_length > 0 ? key : NULL, + key_length > 0 ? key_length : 0 + ); + + if ( !session ) { + coap_log( LOG_ERR, "cannot create client session\n" ); + goto finish; + } + /* + * Prime the base token value, which coap_session_new_token() will increment + * every time it is called to get an unique token. + * [Option '-T token' is used to seed a different value] + */ + coap_session_init_token(session, base_token.length, base_token.s); + + /* add Uri-Host if server address differs from uri.host */ + + switch (dst.addr.sa.sa_family) { + case AF_INET: + addrptr = &dst.addr.sin.sin_addr; + /* create context for IPv4 */ + break; + case AF_INET6: + addrptr = &dst.addr.sin6.sin6_addr; + break; + default: + ; + } + + /* construct CoAP message */ + + if (!uri_host_option && (!proxy.host.length && addrptr + && (inet_ntop(dst.addr.sa.sa_family, addrptr, addr, sizeof(addr)) != 0) + && (strlen(addr) != uri.host.length + || memcmp(addr, uri.host.s, uri.host.length) != 0) + && create_uri_opts)) { + /* add Uri-Host */ + + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_HOST, + uri.host.length, + uri.host.s)); + } + + /* set block option if requested at commandline */ + if (flags & FLAGS_BLOCK) + set_blocksize(); + + /* Send the first (and may be only PDU) */ + if (payload.length) { + /* Create some new data to use for this iteration */ + data = coap_malloc(payload.length); + if (data == NULL) + goto finish; + memcpy(data, payload.s, payload.length); + data_len = payload.length; + } + if (!(pdu = coap_new_request(ctx, session, method, &optlist, data, + data_len))) { + goto finish; + } + + if (is_mcast && wait_seconds == DEFAULT_WAIT_TIME) + /* Allow for other servers to respond within DEFAULT_LEISURE RFC7252 8.2 */ + wait_seconds = coap_session_get_default_leisure(session).integer_part + 1; + + wait_ms = wait_seconds * 1000; + coap_log(LOG_DEBUG, "timeout is set to %u seconds\n", wait_seconds); + + coap_log(LOG_DEBUG, "sending CoAP request:\n"); + if (coap_get_log_level() < LOG_DEBUG) + coap_show_pdu(LOG_INFO, pdu); + + if (coap_send(session, pdu) == COAP_INVALID_MID) { + coap_log(LOG_ERR, "cannot send CoAP pdu\n"); + quit = 1; + } + repeat_count--; + + while(!quit && + !(ready && !tracked_tokens_count && !is_mcast && !repeat_count && + coap_can_exit(ctx)) ) { + uint32_t timeout_ms; + /* + * 3 factors determine how long to wait in coap_io_process() + * Remaining overall wait time (wait_ms) + * Remaining overall observe unsolicited response time (obs_ms) + * Delay of up to one second before sending off the next request + */ + if (obs_ms) { + timeout_ms = min(wait_ms, obs_ms); + } else { + timeout_ms = wait_ms; + } + if (repeat_count) { + timeout_ms = min(timeout_ms, repeat_ms); + } + + result = coap_io_process(ctx, timeout_ms); + + if ( result >= 0 ) { + if (wait_ms > 0) { + if ( (unsigned)result >= wait_ms ) { + coap_log(LOG_INFO, "timeout\n"); + break; + } else { + wait_ms -= result; + } + } + if ( obs_ms > 0 && !obs_ms_reset ) { + if ( (unsigned)result >= obs_ms ) { + coap_log(LOG_DEBUG, "clear observation relationship\n" ); + for (i = 0; i < tracked_tokens_count; i++) { + if (tracked_tokens[i].observe) { + coap_cancel_observe(session, tracked_tokens[i].token, msgtype); + } + } + doing_observe = 0; + quit = 1; + + /* make sure that the obs timer does not fire again */ + obs_ms = 0; + obs_seconds = 0; + } else { + obs_ms -= result; + } + } + if (ready && repeat_count) { + /* Send off next request if appropriate */ + if (repeat_ms > (unsigned)result) { + repeat_ms -= (unsigned)result; + } else { + /* Doing this once a second */ + repeat_ms = REPEAT_DELAY_MS; + if (payload.length) { + /* Create some new data to use for this iteration */ + data = coap_malloc(payload.length); + if (data == NULL) + goto finish; + memcpy(data, payload.s, payload.length); + data_len = payload.length; + } + if (!(pdu = coap_new_request(ctx, session, method, &optlist, + data, data_len))) { + goto finish; + } + coap_log(LOG_DEBUG, "sending CoAP request:\n"); + if (coap_get_log_level() < LOG_DEBUG) + coap_show_pdu(LOG_INFO, pdu); + + ready = 0; + if (coap_send(session, pdu) == COAP_INVALID_MID) { + coap_log(LOG_ERR, "cannot send CoAP pdu\n"); + quit = 1; + } + repeat_count--; + } + } + obs_ms_reset = 0; + } + } + + result = 0; + + finish: + + coap_free(ca_mem); + coap_free(cert_mem); + coap_free(key_mem); + coap_free(payload.s); + for (i = 0; i < valid_ihs.count; i++) { + free(valid_ihs.ih_list[i].hint_match); + coap_delete_bin_const(valid_ihs.ih_list[i].new_identity); + coap_delete_bin_const(valid_ihs.ih_list[i].new_key); + } + if (valid_ihs.count) + free(valid_ihs.ih_list); + for (i = 0; i < tracked_tokens_count; i++) { + coap_delete_binary(tracked_tokens[i].token); + } + free(tracked_tokens); + coap_delete_optlist(optlist); + coap_session_release( session ); + coap_free_context( ctx ); + coap_cleanup(); + close_output(); + + return result; +} diff --git a/examples/espidf-coap-server/components/libcoap/examples/coap-rd.c b/examples/espidf-coap-server/components/libcoap/examples/coap-rd.c new file mode 100644 index 000000000..33ad39579 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/coap-rd.c @@ -0,0 +1,879 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ + +/* coap -- simple implementation of the Constrained Application Protocol (CoAP) + * as defined in RFC 7252 + * + * Copyright (C) 2010--2015,2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms of + * use. + */ + + +/** + * @file coap-rd.c + * @brief CoRE resource directory + * + * @see https://tools.ietf.org/html/draft-ietf-core-resource-directory + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#define strcasecmp _stricmp +#include "getopt.c" +#if !defined(S_ISDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +#include + +#define COAP_RESOURCE_CHECK_TIME 2 + +#define RD_ROOT_STR "rd" +#define RD_ROOT_SIZE 2 + +static char *cert_file = NULL; /* Combined certificate and private key in PEM */ +static char *ca_file = NULL; /* CA for cert_file - for cert checking in PEM */ +static char *root_ca_file = NULL; /* List of trusted Root CAs in PEM */ +static int verify_peer_cert = 1; /* PKI granularity - by default set */ +#define MAX_KEY 64 /* Maximum length of a pre-shared key in bytes. */ +static uint8_t key[MAX_KEY]; +static ssize_t key_length = 0; +static int key_defined = 0; +static const char *hint = "CoAP"; + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +typedef struct rd_t { + size_t etag_len; /**< actual length of @c etag */ + unsigned char etag[8]; /**< ETag for current description */ + + coap_string_t data; /**< points to the resource description */ +} rd_t; + +rd_t *resources = NULL; + +static ssize_t +cmdline_read_key(char *arg, unsigned char *buf, size_t maxlen) { + size_t len = strnlen(arg, maxlen); + if (len) { + memcpy(buf, arg, len); + return len; + } + return -1; +} + +static inline rd_t * +rd_new(void) { + rd_t *rd; + rd = (rd_t *)coap_malloc(sizeof(rd_t)); + if (rd) + memset(rd, 0, sizeof(rd_t)); + + return rd; +} + +static void +rd_delete(rd_t *rd) { + if (rd) { + coap_free(rd->data.s); + coap_free(rd); + } +} + +static void +resource_rd_delete(void *ptr) { + rd_delete(ptr); +} + +static int quit = 0; + +/* SIGINT handler: set quit to 1 for graceful termination */ +static void +handle_sigint(int signum COAP_UNUSED) { + quit = 1; +} + +static void +hnd_get_resource(coap_resource_t *resource, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request COAP_UNUSED, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + rd_t *rd = coap_resource_get_userdata(resource); + unsigned char buf[3]; + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + + coap_add_option(response, + COAP_OPTION_CONTENT_TYPE, + coap_encode_var_safe(buf, sizeof(buf), + COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), + buf); + + if (rd && rd->etag_len) + coap_add_option(response, COAP_OPTION_ETAG, rd->etag_len, rd->etag); + + if (rd && rd->data.s) + coap_add_data(response, rd->data.length, rd->data.s); +} + +static void +hnd_put_resource(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request COAP_UNUSED, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { +#if 1 + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_IMPLEMENTED); +#else /* FIXME */ + coap_opt_iterator_t opt_iter; + coap_opt_t *token, *etag; + coap_pdu_t *response; + size_t size = sizeof(coap_hdr_t); + int type = (request->hdr->type == COAP_MESSAGE_CON) + ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; + rd_t *rd = NULL; + unsigned char code; /* result code */ + const uint8_t *data; + coap_string_t tmp; + + HASH_FIND(hh, resources, resource->uri_path.s, resource->uri_path.length, rd); + if (rd) { + /* found resource object, now check Etag */ + etag = coap_check_option(request, COAP_OPTION_ETAG, &opt_iter); + if (!etag || (COAP_OPT_LENGTH(etag) != rd->etag_len) + || memcmp(COAP_OPT_VALUE(etag), rd->etag, rd->etag_len) != 0) { + + if (coap_get_data(request, &tmp.length, &data)) { + + tmp.s = (unsigned char *)coap_malloc(tmp.length); + if (!tmp.s) { + coap_log(LOG_DEBUG, + "hnd_put_rd: cannot allocate storage for new rd\n"); + code = COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE; + goto finish; + } + + coap_free(rd->data.s); + rd->data.s = tmp.s; + rd->data.length = tmp.length; + memcpy(rd->data.s, data, rd->data.length); + } + } + + if (etag) { + rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag)); + memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len); + } + + code = COAP_RESPONSE_CODE_CHANGED; + /* FIXME: update lifetime */ + + } else { + + code = COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE; + } + + finish: + /* FIXME: do not create a new response but use the old one instead */ + response = coap_pdu_init(type, code, request->hdr->id, size); + + if (!response) { + coap_log(LOG_DEBUG, "cannot create response for mid=0x%x\n", + request->hdr->id); + return; + } + + if (request->hdr->token_length) + coap_add_token(response, request->hdr->token_length, request->hdr->token); + + if (coap_send(ctx, peer, response) == COAP_INVALID_MID) { + coap_log(LOG_DEBUG, "hnd_get_rd: cannot send response for mid=0x%x\n", + request->hdr->id); + } +#endif +} + +static void +hnd_delete_resource(coap_resource_t *resource, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request COAP_UNUSED, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + rd_t *rd = coap_resource_get_userdata(resource); + + if (rd) { + rd_delete(rd); + } + /* FIXME: link attributes for resource have been created dynamically + * using coap_malloc() and must be released. */ + coap_delete_resource(NULL, resource); + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); +} + +static void +hnd_get_rd(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request COAP_UNUSED, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + unsigned char buf[3]; + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + + coap_add_option(response, + COAP_OPTION_CONTENT_TYPE, + coap_encode_var_safe(buf, sizeof(buf), + COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), + buf); + + coap_add_option(response, + COAP_OPTION_MAXAGE, + coap_encode_var_safe(buf, sizeof(buf), 0x2ffff), buf); +} + +static int +parse_param(const uint8_t *search, + size_t search_len, + unsigned char *data, + size_t data_len, + coap_string_t *result) { + + if (result) + memset(result, 0, sizeof(coap_string_t)); + + if (!search_len) + return 0; + + while (search_len <= data_len) { + + /* handle parameter if found */ + if (memcmp(search, data, search_len) == 0) { + data += search_len; + data_len -= search_len; + + /* key is only valid if we are at end of string or delimiter follows */ + if (!data_len || *data == '=' || *data == '&') { + while (data_len && *data != '=') { + ++data; --data_len; + } + + if (data_len > 1 && result) { + /* value begins after '=' */ + + result->s = ++data; + while (--data_len && *data != '&') { + ++data; result->length++; + } + } + + return 1; + } + } + + /* otherwise proceed to next */ + while (--data_len && *data++ != '&') + ; + } + + return 0; +} + +static void +add_source_address(coap_resource_t *resource, + const coap_address_t *peer) { +#define BUFSIZE 64 + char *buf; + size_t n = 1; + coap_str_const_t attr_val; + + buf = (char *)coap_malloc(BUFSIZE); + if (!buf) + return; + + buf[0] = '"'; + + switch(peer->addr.sa.sa_family) { + + case AF_INET: + /* FIXME */ + break; + + case AF_INET6: + n += snprintf(buf + n, BUFSIZE - n, + "[%02x%02x:%02x%02x:%02x%02x:%02x%02x" \ + ":%02x%02x:%02x%02x:%02x%02x:%02x%02x]", + peer->addr.sin6.sin6_addr.s6_addr[0], + peer->addr.sin6.sin6_addr.s6_addr[1], + peer->addr.sin6.sin6_addr.s6_addr[2], + peer->addr.sin6.sin6_addr.s6_addr[3], + peer->addr.sin6.sin6_addr.s6_addr[4], + peer->addr.sin6.sin6_addr.s6_addr[5], + peer->addr.sin6.sin6_addr.s6_addr[6], + peer->addr.sin6.sin6_addr.s6_addr[7], + peer->addr.sin6.sin6_addr.s6_addr[8], + peer->addr.sin6.sin6_addr.s6_addr[9], + peer->addr.sin6.sin6_addr.s6_addr[10], + peer->addr.sin6.sin6_addr.s6_addr[11], + peer->addr.sin6.sin6_addr.s6_addr[12], + peer->addr.sin6.sin6_addr.s6_addr[13], + peer->addr.sin6.sin6_addr.s6_addr[14], + peer->addr.sin6.sin6_addr.s6_addr[15]); + + if (peer->addr.sin6.sin6_port != htons(COAP_DEFAULT_PORT)) { + n += + snprintf(buf + n, BUFSIZE - n, ":%d", peer->addr.sin6.sin6_port); + } + break; + default: + ; + } + + if (n < BUFSIZE) + buf[n++] = '"'; + + attr_val.s = (const uint8_t *)buf; + attr_val.length = n; + coap_add_attr(resource, + coap_make_str_const("A"), + &attr_val, + 0); + coap_free(buf); +#undef BUFSIZE +} + +static rd_t * +make_rd(const coap_pdu_t *pdu) { + rd_t *rd; + const uint8_t *data; + coap_opt_iterator_t opt_iter; + coap_opt_t *etag; + + rd = rd_new(); + + if (!rd) { + coap_log(LOG_DEBUG, "hnd_get_rd: cannot allocate storage for rd\n"); + return NULL; + } + + if (coap_get_data(pdu, &rd->data.length, &data)) { + rd->data.s = (unsigned char *)coap_malloc(rd->data.length); + if (!rd->data.s) { + coap_log(LOG_DEBUG, "hnd_get_rd: cannot allocate storage for rd->data\n"); + rd_delete(rd); + return NULL; + } + memcpy(rd->data.s, data, rd->data.length); + } + + etag = coap_check_option(pdu, COAP_OPTION_ETAG, &opt_iter); + if (etag) { + rd->etag_len = min(coap_opt_length(etag), sizeof(rd->etag)); + memcpy(rd->etag, coap_opt_value(etag), rd->etag_len); + } + + return rd; +} + +static void +hnd_post_rd(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + coap_resource_t *r; +#define LOCSIZE 68 + unsigned char *loc; + size_t loc_size; + coap_string_t h = {0, NULL}, ins = {0, NULL}, rt = {0, NULL}, lt = {0, NULL}; /* store query parameters */ + unsigned char *buf; + coap_str_const_t attr_val; + coap_str_const_t resource_val; + + loc = (unsigned char *)coap_malloc(LOCSIZE); + if (!loc) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + return; + } + memcpy(loc, RD_ROOT_STR, RD_ROOT_SIZE); + + loc_size = RD_ROOT_SIZE; + loc[loc_size++] = '/'; + + /* store query parameters for later use */ + if (query) { + parse_param((const uint8_t *)"h", 1, query->s, query->length, &h); + parse_param((const uint8_t *)"ins", 3, query->s, query->length, &ins); + parse_param((const uint8_t *)"lt", 2, query->s, query->length, <); + parse_param((const uint8_t *)"rt", 2, query->s, query->length, &rt); + } + + if (h.length) { /* client has specified a node name */ + memcpy(loc + loc_size, h.s, min(h.length, LOCSIZE - loc_size - 1)); + loc_size += min(h.length, LOCSIZE - loc_size - 1); + + if (ins.length && loc_size > 1) { + loc[loc_size++] = '-'; + memcpy((char *)(loc + loc_size), + ins.s, min(ins.length, LOCSIZE - loc_size - 1)); + loc_size += min(ins.length, LOCSIZE - loc_size - 1); + } + + } else { /* generate node identifier */ + loc_size += + snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1, + "%x", coap_pdu_get_mid(request)); + + if (loc_size > 1) { + if (ins.length) { + loc[loc_size++] = '-'; + memcpy((char *)(loc + loc_size), + ins.s, + min(ins.length, LOCSIZE - loc_size - 1)); + loc_size += min(ins.length, LOCSIZE - loc_size - 1); + } else { + coap_tick_t now; + coap_ticks(&now); + + loc_size += snprintf((char *)(loc + loc_size), + LOCSIZE - loc_size - 1, + "-%x", + (unsigned int)(now & (unsigned int)-1)); + } + } + } + + /* TODO: + * - use lt to check expiration + */ + + resource_val.s = loc; + resource_val.length = loc_size; + r = coap_resource_init(&resource_val, 0); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_resource); + coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_resource); + coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); + + if (ins.s) { + buf = (unsigned char *)coap_malloc(ins.length + 2); + if (buf) { + /* add missing quotes */ + buf[0] = '"'; + memcpy(buf + 1, ins.s, ins.length); + buf[ins.length + 1] = '"'; + attr_val.s = buf; + attr_val.length = ins.length + 2; + coap_add_attr(r, + coap_make_str_const("ins"), + &attr_val, + 0); + coap_free(buf); + } + } + + if (rt.s) { + buf = (unsigned char *)coap_malloc(rt.length + 2); + if (buf) { + /* add missing quotes */ + buf[0] = '"'; + memcpy(buf + 1, rt.s, rt.length); + buf[rt.length + 1] = '"'; + attr_val.s = buf; + attr_val.length = rt.length + 2; + coap_add_attr(r, + coap_make_str_const("rt"), + &attr_val, + 0); + coap_free(buf); + } + } + + add_source_address(r, coap_session_get_addr_remote(session)); + + { + rd_t *rd; + rd = make_rd(request); + if (rd) { + coap_resource_set_userdata(r, rd); + } else { + /* FIXME: send error response and delete r */ + } + } + + coap_add_resource(coap_session_get_context(session), r); + + + /* create response */ + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); + + { /* split path into segments and add Location-Path options */ + unsigned char _b[LOCSIZE]; + unsigned char *b = _b; + size_t buflen = sizeof(_b); + int nseg; + + nseg = coap_split_path(loc, loc_size, b, &buflen); + while (nseg--) { + coap_add_option(response, + COAP_OPTION_LOCATION_PATH, + coap_opt_length(b), + coap_opt_value(b)); + b += coap_opt_size(b); + } + } + coap_free(loc); +} + +static void +init_resources(coap_context_t *ctx) { + coap_resource_t *r; + + r = coap_resource_init(coap_make_str_const(RD_ROOT_STR), 0); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_rd); + coap_register_request_handler(r, COAP_REQUEST_POST, hnd_post_rd); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("40"), 0); + coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"core.rd\""), 0); + coap_add_attr(r, coap_make_str_const("ins"), coap_make_str_const("\"default\""), 0); + + coap_add_resource(ctx, r); + + coap_resource_release_userdata_handler(ctx, resource_rd_delete); +} + +static void +usage( const char *program, const char *version) { + const char *p; + char buffer[72]; + const char *lib_build = coap_package_build(); + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf( stderr, "%s v%s -- CoRE Resource Directory implementation\n" + "(c) 2011-2012,2019-2022 Olaf Bergmann and others\n\n" + "Build: %s\n" + "%s\n" + , program, version, lib_build, + coap_string_tls_version(buffer, sizeof(buffer))); + fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer))); + fprintf(stderr, "\n" + "Usage: %s [-g group] [-G group_if] [-p port] [-v num] [-A address]\n" + "\t [[-h hint] [-k key]]\n" + "\t [[-c certfile] [-C cafile] [-n] [-R trust_casfile]]\n" + "General Options\n" + "\t-g group\tJoin the given multicast group.\n" + "\t \t\tNote: DTLS over multicast is not currently supported\n" + "\t-G group_if\tUse this interface for listening for the multicast\n" + "\t \t\tgroup. This can be different from the implied interface\n" + "\t \t\tif the -A option is used\n" + "\t-p port\t\tListen on specified port\n" + "\t-v num \t\tVerbosity level (default 3, maximum is 9). Above 7,\n" + "\t \t\tthere is increased verbosity in GnuTLS and OpenSSL logging\n" + "\t-A address\tInterface address to bind to\n" + "PSK Options (if supported by underlying (D)TLS library)\n" + "\t-h hint\t\tIdentity Hint. Default is CoAP. Zero length is no hint\n" + "\t-k key \t\tPre-Shared Key. This argument requires (D)TLS with PSK\n" + "\t \t\tto be available. This cannot be empty if defined.\n" + "\t \t\tNote that both -c and -k need to be defined\n" + "\t \t\tfor both PSK and PKI to be concurrently supported\n" + "PKI Options (if supported by underlying (D)TLS library)\n" + "\t-c certfile\tPEM file containing both CERTIFICATE and PRIVATE KEY\n" + "\t \t\tThis argument requires (D)TLS with PKI to be available\n" + "\t-n \t\tDisable remote peer certificate checking. This gives\n" + "\t \t\tclients the ability to use PKI, but without any defined\n" + "\t \t\tcertificates\n" + "\t-C cafile\tPEM file that contains a list of one or\n" + "\t \t\tmore CAs that are to be passed to the client for the\n" + "\t \t\tclient to determine what client certificate to use.\n" + "\t \t\tNormally, this list of CAs would be the root CA and and\n" + "\t \t\tany intermediate CAs. Ideally the server certificate\n" + "\t \t\tshould be signed by the same CA so that mutual\n" + "\t \t\tauthentication can take place. The contents of cafile\n" + "\t \t\tare added to the trusted store of root CAs.\n" + "\t \t\tUsing the -C or -R options will will trigger the\n" + "\t \t\tvalidation of the client certificate unless overridden\n" + "\t \t\tby the -n option\n" + "\t-R trust_casfile\tPEM file containing the set of trusted root CAs\n" + "\t \t\tthat are to be used to validate the client certificate.\n" + "\t \t\tAlternatively, this can point to a directory containing\n" + "\t \t\ta set of CA PEM files.\n" + "\t \t\tUsing '-R trust_casfile' disables common CA mutual\n" + "\t \t\tauthentication which can only be done by using\n" + "\t \t\t'-C cafile'.\n" + "\t \t\tUsing the -C or -R options will will trigger the\n" + "\t \t\tvalidation of the client certificate unless overridden\n" + "\t \t\tby the -n option\n" + , + program); +} + +static void +fill_keystore(coap_context_t *ctx) { + if (cert_file == NULL && key_defined == 0) { + if (coap_dtls_is_supported() || coap_tls_is_supported()) { + coap_log(LOG_DEBUG, + "(D)TLS not enabled as neither -k or -c options specified\n"); + } + } + if (cert_file) { + coap_dtls_pki_t dtls_pki; + memset (&dtls_pki, 0, sizeof(dtls_pki)); + dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; + if (ca_file || root_ca_file) { + /* + * Add in additional certificate checking. + * This list of enabled can be tuned for the specific + * requirements - see 'man coap_encryption'. + */ + dtls_pki.verify_peer_cert = verify_peer_cert; + dtls_pki.check_common_ca = !root_ca_file; + dtls_pki.allow_self_signed = 1; + dtls_pki.allow_expired_certs = 1; + dtls_pki.cert_chain_validation = 1; + dtls_pki.cert_chain_verify_depth = 2; + dtls_pki.check_cert_revocation = 1; + dtls_pki.allow_no_crl = 1; + dtls_pki.allow_expired_crl = 1; + dtls_pki.validate_cn_call_back = NULL; + dtls_pki.cn_call_back_arg = NULL; + dtls_pki.validate_sni_call_back = NULL; + dtls_pki.sni_call_back_arg = NULL; + } + dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM; + dtls_pki.pki_key.key.pem.public_cert = cert_file; + dtls_pki.pki_key.key.pem.private_key = cert_file; + dtls_pki.pki_key.key.pem.ca_file = ca_file; + /* If general root CAs are defined */ + if (root_ca_file) { + struct stat stbuf; + if ((stat(root_ca_file, &stbuf) == 0) && S_ISDIR(stbuf.st_mode)) { + coap_context_set_pki_root_cas(ctx, NULL, root_ca_file); + } else { + coap_context_set_pki_root_cas(ctx, root_ca_file, NULL); + } + } + coap_context_set_pki(ctx, &dtls_pki); + } + if (key_defined) { + coap_dtls_spsk_t dtls_psk; + memset (&dtls_psk, 0, sizeof(dtls_psk)); + dtls_psk.version = COAP_DTLS_SPSK_SETUP_VERSION; + dtls_psk.validate_id_call_back = NULL; + dtls_psk.validate_sni_call_back = NULL; + dtls_psk.psk_info.hint.s = (const uint8_t *)hint; + dtls_psk.psk_info.hint.length = hint ? strlen(hint) : 0; + dtls_psk.psk_info.key.s = key; + dtls_psk.psk_info.key.length = key_length; + coap_context_set_psk2(ctx, &dtls_psk); + } +} + +static coap_context_t * +get_context(const char *node, const char *port) { + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + ctx = coap_new_context(NULL); + if (!ctx) { + return NULL; + } + /* Need PSK set up before we set up (D)TLS endpoints */ + fill_keystore(ctx); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + + s = getaddrinfo(node, port, &hints, &result); + if ( s != 0 ) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + coap_free_context(ctx); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) { + coap_address_t addr, addrs; + coap_endpoint_t *ep_udp = NULL, *ep_dtls = NULL, *ep_tcp = NULL, *ep_tls = NULL; + + if (rp->ai_addrlen <= (socklen_t)sizeof(addr.addr)) { + coap_address_init(&addr); + addr.size = (socklen_t)rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + addrs = addr; + if (addr.addr.sa.sa_family == AF_INET) { + uint16_t temp = ntohs(addr.addr.sin.sin_port) + 1; + addrs.addr.sin.sin_port = htons(temp); + } else if (addr.addr.sa.sa_family == AF_INET6) { + uint16_t temp = ntohs(addr.addr.sin6.sin6_port) + 1; + addrs.addr.sin6.sin6_port = htons(temp); + } else { + goto finish; + } + + ep_udp = coap_new_endpoint(ctx, &addr, COAP_PROTO_UDP); + if (ep_udp) { + if (coap_dtls_is_supported() && (key_defined || cert_file)) { + ep_dtls = coap_new_endpoint(ctx, &addrs, COAP_PROTO_DTLS); + if (!ep_dtls) + coap_log(LOG_CRIT, "cannot create DTLS endpoint\n"); + } + } else { + coap_log(LOG_CRIT, "cannot create UDP endpoint\n"); + continue; + } + ep_tcp = coap_new_endpoint(ctx, &addr, COAP_PROTO_TCP); + if (ep_tcp) { + if (coap_tls_is_supported() && (key_defined || cert_file)) { + ep_tls = coap_new_endpoint(ctx, &addrs, COAP_PROTO_TLS); + if (!ep_tls) + coap_log(LOG_CRIT, "cannot create TLS endpoint\n"); + } + } else { + coap_log(LOG_CRIT, "cannot create TCP endpoint\n"); + } + if (ep_udp) + goto finish; + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + +finish: + freeaddrinfo(result); + return ctx; +} + +int +main(int argc, char **argv) { + coap_context_t *ctx; + int result; + char addr_str[NI_MAXHOST] = "::"; + char port_str[NI_MAXSERV] = "5683"; + char *group = NULL; + char *group_if = NULL; + int opt; + coap_log_t log_level = LOG_WARNING; +#ifndef _WIN32 + struct sigaction sa; +#endif + + while ((opt = getopt(argc, argv, "A:c:C:g:G:h:k:n:R:p:v:")) != -1) { + switch (opt) { + case 'A' : + strncpy(addr_str, optarg, NI_MAXHOST-1); + addr_str[NI_MAXHOST - 1] = '\0'; + break; + case 'c' : + cert_file = optarg; + break; + case 'C' : + ca_file = optarg; + break; + case 'g' : + group = optarg; + break; + case 'G' : + group_if = optarg; + break; + case 'h' : + if (!optarg[0]) { + hint = NULL; + break; + } + hint = optarg; + break; + case 'k' : + key_length = cmdline_read_key(optarg, key, MAX_KEY); + if (key_length < 0) { + coap_log( LOG_CRIT, "Invalid Pre-Shared Key specified\n" ); + break; + } + key_defined = 1; + break; + case 'n': + verify_peer_cert = 0; + break; + case 'R' : + root_ca_file = optarg; + break; + case 'p' : + strncpy(port_str, optarg, NI_MAXSERV-1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'v' : + log_level = strtol(optarg, NULL, 10); + break; + default: + usage( argv[0], LIBCOAP_PACKAGE_VERSION ); + exit( 1 ); + } + } + + coap_startup(); + coap_dtls_set_log_level(log_level); + coap_set_log_level(log_level); + + ctx = get_context(addr_str, port_str); + if (!ctx) + return -1; + + if (group) + coap_join_mcast_group_intf(ctx, group, group_if); + + init_resources(ctx); + +#ifdef _WIN32 + signal(SIGINT, handle_sigint); +#else + memset (&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = handle_sigint; + sa.sa_flags = 0; + sigaction (SIGINT, &sa, NULL); + sigaction (SIGTERM, &sa, NULL); + /* So we do not exit on a SIGPIPE */ + sa.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &sa, NULL); +#endif + + while ( !quit ) { + result = coap_io_process( ctx, COAP_RESOURCE_CHECK_TIME * 1000 ); + if ( result >= 0 ) { + /* coap_check_resource_list( ctx ); */ + } + } + + coap_free_context( ctx ); + coap_cleanup(); + + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/examples/coap-server.c b/examples/espidf-coap-server/components/libcoap/examples/coap-server.c new file mode 100644 index 000000000..76e8941b3 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/coap-server.c @@ -0,0 +1,2980 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* coap -- simple implementation of the Constrained Application Protocol (CoAP) + * as defined in RFC 7252 + * + * Copyright (C) 2010--2022 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#include "getopt.c" +#if !defined(S_ISDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif +#ifndef R_OK +#define R_OK 4 +#endif +static char* strndup(const char* s1, size_t n) +{ + char* copy = (char*)malloc(n + 1); + if (copy) { + memcpy(copy, s1, n); + copy[n] = 0; + } + return copy; +}; +#include +#define access _access +#define fileno _fileno +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +/* + * SERVER_CAN_PROXY=0 can be set by build system if + * "./configure --disable-client-mode" is used. + */ +#ifndef SERVER_CAN_PROXY +#define SERVER_CAN_PROXY 1 +#endif + +/* Need to refresh time once per sec */ +#define COAP_RESOURCE_CHECK_TIME 1 + +#include + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* set to 1 to request clean server shutdown */ +static int quit = 0; + +/* changeable clock base (see handle_put_time()) */ +static time_t clock_offset; +static time_t my_clock_base = 0; + +coap_resource_t *time_resource = NULL; + +static int resource_flags = COAP_RESOURCE_FLAGS_NOTIFY_CON; + +/* + * For PKI, if one or more of cert_file, key_file and ca_file is in PKCS11 URI + * format, then the remainder of cert_file, key_file and ca_file are treated + * as being in DER format to provide consistency across the underlying (D)TLS + * libraries. + */ +static char *cert_file = NULL; /* certificate and optional private key in PEM, + or PKCS11 URI*/ +static char *key_file = NULL; /* private key in PEM, DER or PKCS11 URI */ +static char *pkcs11_pin = NULL; /* PKCS11 pin to unlock access to token */ +static char *ca_file = NULL; /* CA for cert_file - for cert checking in PEM, + DER or PKCS11 URI */ +static char *root_ca_file = NULL; /* List of trusted Root CAs in PEM */ +static int use_pem_buf = 0; /* Map these cert/key files into memory to test + PEM_BUF logic if set */ +static int is_rpk_not_cert = 0; /* Cert is RPK if set */ +/* Used to hold initial PEM_BUF setup */ +static uint8_t *cert_mem_base = NULL; /* certificate and private key in PEM_BUF */ +static uint8_t *key_mem_base = NULL; /* private key in PEM_BUF */ +static uint8_t *ca_mem_base = NULL; /* CA for cert checking in PEM_BUF */ +/* Used for verify_pki_sni_callback PEM_BUF temporary holding */ +static uint8_t *cert_mem = NULL; /* certificate and private key in PEM_BUF */ +static uint8_t *key_mem = NULL; /* private key in PEM_BUF */ +static uint8_t *ca_mem = NULL; /* CA for cert checking in PEM_BUF */ +static size_t cert_mem_len = 0; +static size_t key_mem_len = 0; +static size_t ca_mem_len = 0; +static int verify_peer_cert = 1; /* PKI granularity - by default set */ +#define MAX_KEY 64 /* Maximum length of a pre-shared key in bytes. */ +static uint8_t *key = NULL; +static ssize_t key_length = 0; +int key_defined = 0; +static const char *hint = "CoAP"; +static int support_dynamic = 0; +static uint32_t block_mode = COAP_BLOCK_USE_LIBCOAP; +static int echo_back = 0; +static uint32_t csm_max_message_size = 0; + +static coap_dtls_pki_t * +setup_pki(coap_context_t *ctx, coap_dtls_role_t role, char *sni); + +typedef struct psk_sni_def_t { + char* sni_match; + coap_bin_const_t *new_key; + coap_bin_const_t *new_hint; +} psk_sni_def_t; + +typedef struct valid_psk_snis_t { + size_t count; + psk_sni_def_t *psk_sni_list; +} valid_psk_snis_t; + +static valid_psk_snis_t valid_psk_snis = {0, NULL}; + +typedef struct id_def_t { + char *hint_match; + coap_bin_const_t *identity_match; + coap_bin_const_t *new_key; +} id_def_t; + +typedef struct valid_ids_t { + size_t count; + id_def_t *id_list; +} valid_ids_t; + +static valid_ids_t valid_ids = {0, NULL}; +typedef struct pki_sni_def_t { + char* sni_match; + char *new_cert; + char *new_ca; +} pki_sni_def_t; + +typedef struct valid_pki_snis_t { + size_t count; + pki_sni_def_t *pki_sni_list; +} valid_pki_snis_t; + +static valid_pki_snis_t valid_pki_snis = {0, NULL}; + +typedef struct transient_value_t { + coap_binary_t *value; + size_t ref_cnt; +} transient_value_t; + +/* temporary storage for dynamic resource representations */ +static transient_value_t *example_data_value = NULL; +static int example_data_media_type = COAP_MEDIATYPE_TEXT_PLAIN; + +/* SIGINT handler: set quit to 1 for graceful termination */ +static void +handle_sigint(int signum COAP_UNUSED) { + quit = 1; +} + +/* + * This will return a correctly formed transient_value_t *, or NULL. + * If an error, the passed in coap_binary_t * will get deleted. + * Note: transient_value->value will never be returned as NULL. + */ +static transient_value_t * +alloc_resource_data(coap_binary_t *value) { + transient_value_t *transient_value; + if (!value) + return NULL; + transient_value = coap_malloc(sizeof(transient_value_t)); + if (!transient_value) { + coap_delete_binary(value); + return NULL; + } + transient_value->ref_cnt = 1; + transient_value->value = value; + return transient_value; +} + +/* + * Need to handle race conditions of data being updated (by PUT) and + * being read by a blocked response to GET. + */ +static void +release_resource_data(coap_session_t *session COAP_UNUSED, + void *app_ptr) { + transient_value_t *transient_value = (transient_value_t *)app_ptr; + + if (!transient_value) + return; + + if (--transient_value->ref_cnt > 0) + return; + coap_delete_binary(transient_value->value); + coap_free(transient_value); +} + +/* + * Bump the reference count and return reference to data + */ +static coap_binary_t +reference_resource_data(transient_value_t *entry) { + coap_binary_t body; + if (entry) { + /* Bump reference so not removed elsewhere */ + entry->ref_cnt++; + assert(entry->value); + body.length = entry->value->length; + body.s = entry->value->s; + } + else { + body.length = 0; + body.s = NULL; + } + return body; +} + +#define INDEX "This is a test server made with libcoap (see https://libcoap.net)\n" \ + "Copyright (C) 2010--2022 Olaf Bergmann and others\n\n" + +static void +hnd_get_index(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, + 0x2ffff, 0, strlen(INDEX), + (const uint8_t *)INDEX, NULL, NULL); +} + +static void +hnd_get_fetch_time(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response) { + unsigned char buf[40]; + size_t len; + time_t now; + coap_tick_t t; + (void)request; + coap_pdu_code_t code = coap_pdu_get_code(request); + size_t size; + const uint8_t *data; + coap_str_const_t *ticks = coap_make_str_const("ticks"); + + if (my_clock_base) { + + /* calculate current time */ + coap_ticks(&t); + now = my_clock_base + (t / COAP_TICKS_PER_SECOND); + + /* coap_get_data() sets size to 0 on error */ + (void)coap_get_data(request, &size, &data); + + if (code == COAP_REQUEST_CODE_GET && query != NULL && + coap_string_equal(query, ticks)) { + /* parameter is in query, output ticks */ + len = snprintf((char *)buf, sizeof(buf), "%u", (unsigned int)now); + } + else if (code == COAP_REQUEST_CODE_FETCH && size == ticks->length && + memcmp(data, ticks->s, ticks->length) == 0) { + /* parameter is in data, output ticks */ + len = snprintf((char *)buf, sizeof(buf), "%u", (unsigned int)now); + } else { /* output human-readable time */ + struct tm *tmp; + tmp = gmtime(&now); + if (!tmp) { + /* If 'now' is not valid */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + else { + len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp); + } + } + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0, + len, + buf, NULL, NULL); + } + else { + /* if my_clock_base was deleted, we pretend to have no such resource */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + } +} + +static void +hnd_put_time(coap_resource_t *resource, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + coap_tick_t t; + size_t size; + const uint8_t *data; + + /* FIXME: re-set my_clock_base to clock_offset if my_clock_base == 0 + * and request is empty. When not empty, set to value in request payload + * (insist on query ?ticks). Return Created or Ok. + */ + + /* if my_clock_base was deleted, we pretend to have no such resource */ + coap_pdu_set_code(response, my_clock_base ? COAP_RESPONSE_CODE_CHANGED : + COAP_RESPONSE_CODE_CREATED); + + coap_resource_notify_observers(resource, NULL); + + /* coap_get_data() sets size to 0 on error */ + (void)coap_get_data(request, &size, &data); + + if (size == 0) /* re-init */ + my_clock_base = clock_offset; + else { + my_clock_base = 0; + coap_ticks(&t); + while(size--) + my_clock_base = my_clock_base * 10 + *data++; + my_clock_base -= t / COAP_TICKS_PER_SECOND; + + /* Sanity check input value */ + if (!gmtime(&my_clock_base)) { + unsigned char buf[3]; + coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); + coap_add_option(response, + COAP_OPTION_CONTENT_FORMAT, + coap_encode_var_safe(buf, sizeof(buf), + COAP_MEDIATYPE_TEXT_PLAIN), buf); + coap_add_data(response, 22, (const uint8_t*)"Invalid set time value"); + /* re-init as value is bad */ + my_clock_base = clock_offset; + } + } +} + +static void +hnd_delete_time(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request COAP_UNUSED, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response COAP_UNUSED) { + my_clock_base = 0; /* mark clock as "deleted" */ + + /* type = request->hdr->type == COAP_MESSAGE_CON */ + /* ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; */ +} + +/* + * This logic is used to test out that the client correctly handles a + * "separate" response (empty ACK followed by data response at a later stage). + */ +static void +hnd_get_async(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response) { + unsigned long delay = 4; /* Less than COAP_DEFAULT_LEISURE */ + size_t size; + coap_async_t *async; + coap_bin_const_t token = coap_pdu_get_token(request); + + /* + * See if this is the initial, or delayed request + */ + + async = coap_find_async(session, token); + if (!async) { + /* Set up an async request to trigger delay in the future */ + if (query) { + const uint8_t *p = query->s; + + delay = 0; + for (size = query->length; size; --size, ++p) + delay = delay * 10 + (*p - '0'); + if (delay == 0) { + coap_log(LOG_INFO, "async: delay of 0 not supported\n"); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); + return; + } + } + async = coap_register_async(session, + request, + COAP_TICKS_PER_SECOND * delay); + if (async == NULL) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE); + return; + } + /* + * Not setting response code will cause empty ACK to be sent + * if Confirmable + */ + return; + } + /* no request (observe) or async set up, so this is the delayed request */ + + /* Send back the appropriate data */ + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, -1, 0, 4, + (const uint8_t *)"done", NULL, NULL); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + + /* async is automatically removed by libcoap on return from this handler */ +} + +/* + * Large Data GET handler + */ + +#ifndef INITIAL_EXAMPLE_SIZE +#define INITIAL_EXAMPLE_SIZE 1500 +#endif +static void +hnd_get_example_data(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response +) { + coap_binary_t body; + if (!example_data_value) { + /* Initialise for the first time */ + int i; + coap_binary_t *value = coap_new_binary(INITIAL_EXAMPLE_SIZE); + if (value) { + for (i = 0; i < INITIAL_EXAMPLE_SIZE; i++) { + if ((i % 10) == 0) { + value->s[i] = 'a' + (i/10) % 26; + } + else { + value->s[i] = '0' + i%10; + } + } + } + example_data_value = alloc_resource_data(value); + } + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + body = reference_resource_data(example_data_value); + coap_add_data_large_response(resource, session, request, response, + query, example_data_media_type, -1, 0, + body.length, + body.s, + release_resource_data, example_data_value); +} + +static void +cache_free_app_data(void *data) { + coap_binary_t *bdata = (coap_binary_t*)data; + coap_delete_binary(bdata); +} + +/* + * Large Data PUT handler + */ + +static void +hnd_put_example_data(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response +) { + size_t size; + const uint8_t *data; + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + size_t offset; + size_t total; + coap_binary_t *data_so_far; + + if (coap_get_data_large(request, &size, &data, &offset, &total) && + size != total) { + /* + * A part of the data has been received (COAP_BLOCK_SINGLE_BODY not set). + * However, total unfortunately is only an indication, so it is not safe to + * allocate a block based on total. As per + * https://tools.ietf.org/html/rfc7959#section-4 + * o In a request carrying a Block1 Option, to indicate the current + * estimate the client has of the total size of the resource + * representation, measured in bytes ("size indication"). + * + * coap_cache_ignore_options() must have previously been called with at + * least COAP_OPTION_BLOCK1 set as the option value will change per block. + */ + coap_cache_entry_t *cache_entry = coap_cache_get_by_pdu(session, + request, + COAP_CACHE_IS_SESSION_BASED); + + if (offset == 0) { + if (!cache_entry) { + /* + * Set idle_timeout parameter to COAP_MAX_TRANSMIT_WAIT if you want + * early removal on transmission failure. 0 means only delete when + * the session is deleted as session_based is set here. + */ + cache_entry = coap_new_cache_entry(session, request, + COAP_CACHE_NOT_RECORD_PDU, + COAP_CACHE_IS_SESSION_BASED, 0); + } + else { + data_so_far = coap_cache_get_app_data(cache_entry); + if (data_so_far) { + coap_delete_binary(data_so_far); + data_so_far = NULL; + } + coap_cache_set_app_data(cache_entry, NULL, NULL); + } + } + if (!cache_entry) { + if (offset == 0) { + coap_log(LOG_WARNING, "Unable to create a new cache entry\n"); + } + else { + coap_log(LOG_WARNING, + "No cache entry available for the non-first BLOCK\n"); + } + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + return; + } + + if (size) { + /* Add in the new data to cache entry */ + data_so_far = coap_cache_get_app_data(cache_entry); + data_so_far = coap_block_build_body(data_so_far, size, data, + offset, total); + /* Yes, data_so_far can be NULL if error */ + coap_cache_set_app_data(cache_entry, data_so_far, cache_free_app_data); + } + if (offset + size == total) { + /* All the data is now in */ + data_so_far = coap_cache_get_app_data(cache_entry); + coap_cache_set_app_data(cache_entry, NULL, NULL); + } + else { + /* Give us the next block response */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTINUE); + return; + } + } + else { + /* single body of data received */ + data_so_far = coap_new_binary(size); + if (data_so_far) { + memcpy(data_so_far->s, data, size); + } + } + + if (example_data_value) { + /* pre-existed response */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); + /* Need to de-reference as value may be in use elsewhere */ + release_resource_data(session, example_data_value); + } + else + /* just generated response */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); + + example_data_value = alloc_resource_data(data_so_far); + if (!example_data_value) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + return; + } + if ((option = coap_check_option(request, COAP_OPTION_CONTENT_FORMAT, + &opt_iter)) != NULL) { + example_data_media_type = + coap_decode_var_bytes (coap_opt_value (option), + coap_opt_length (option)); + } + else { + example_data_media_type = COAP_MEDIATYPE_TEXT_PLAIN; + } + + coap_resource_notify_observers(resource, NULL); + if (echo_back) { + coap_binary_t body; + + body = reference_resource_data(example_data_value); + coap_add_data_large_response(resource, session, request, response, + query, example_data_media_type, -1, 0, + body.length, + body.s, + release_resource_data, example_data_value); + } +} + +#if SERVER_CAN_PROXY +static int +resolve_address(const coap_str_const_t *server, struct sockaddr *dst) { + + struct addrinfo *res, *ainfo; + struct addrinfo hints; + static char addrstr[256]; + int error, len=-1; + + memset(addrstr, 0, sizeof(addrstr)); + if (server->length) + memcpy(addrstr, server->s, server->length); + else + memcpy(addrstr, "localhost", 9); + + memset ((char *)&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_UNSPEC; + + error = getaddrinfo(addrstr, NULL, &hints, &res); + + if (error != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); + return error; + } + + for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) { + switch (ainfo->ai_family) { + case AF_INET6: + case AF_INET: + len = (int)ainfo->ai_addrlen; + memcpy(dst, ainfo->ai_addr, len); + goto finish; + default: + ; + } + } + + finish: + freeaddrinfo(res); + return len; +} + +#define MAX_USER 128 /* Maximum length of a user name (i.e., PSK + * identity) in bytes. */ +static unsigned char *user = NULL; +static ssize_t user_length = -1; + +static coap_uri_t proxy = { {0, NULL}, 0, {0, NULL}, {0, NULL}, 0 }; +static size_t proxy_host_name_count = 0; +static const char **proxy_host_name_list = NULL; + +typedef struct proxy_list_t { + coap_session_t *ongoing; /* Ongoing session */ + coap_session_t *incoming; /* Incoming session */ + coap_binary_t *token; /* Incoming token */ + coap_string_t *query; /* Incoming query */ + coap_pdu_code_t req_code; /* Incoming request code */ + coap_pdu_type_t req_type; /* Incoming request type */ +} proxy_list_t; + +static proxy_list_t *proxy_list = NULL; +static size_t proxy_list_count = 0; +static coap_resource_t *proxy_resource = NULL; + +static int +get_uri_proxy_scheme_info(const coap_pdu_t *request, + coap_opt_t *opt, + coap_uri_t *uri, + coap_string_t **uri_path, + coap_string_t **uri_query) { + + const char *opt_val = (const char*)coap_opt_value(opt); + int opt_len = coap_opt_length(opt); + coap_opt_iterator_t opt_iter; + + if (opt_len == 9 && + strncasecmp(opt_val, "coaps+tcp", 9) == 0) { + uri->scheme = COAP_URI_SCHEME_COAPS_TCP; + uri->port = COAPS_DEFAULT_PORT; + } + else if (opt_len == 8 && + strncasecmp(opt_val, "coap+tcp", 8) == 0) { + uri->scheme = COAP_URI_SCHEME_COAP_TCP; + uri->port = COAP_DEFAULT_PORT; + } + else if (opt_len == 5 && + strncasecmp(opt_val, "coaps", 5) == 0) { + uri->scheme = COAP_URI_SCHEME_COAPS; + uri->port = COAPS_DEFAULT_PORT; + } + else if (opt_len == 4 && + strncasecmp(opt_val, "coap", 4) == 0) { + uri->scheme = COAP_URI_SCHEME_COAP; + uri->port = COAP_DEFAULT_PORT; + } + else { + coap_log(LOG_WARNING, "Unsupported Proxy Scheme '%*.*s'\n", + opt_len, opt_len, opt_val); + return 0; + } + + opt = coap_check_option(request, COAP_OPTION_URI_HOST, &opt_iter); + if (opt) { + uri->host.length = coap_opt_length(opt); + uri->host.s = coap_opt_value(opt); + } + else { + coap_log(LOG_WARNING, "Proxy Scheme requires Uri-Host\n"); + return 0; + } + opt = coap_check_option(request, COAP_OPTION_URI_PORT, &opt_iter); + if (opt) { + uri->port = + coap_decode_var_bytes (coap_opt_value (opt), + coap_opt_length (opt)); + } + *uri_path = coap_get_uri_path(request); + if (*uri_path) { + uri->path.s = (*uri_path)->s; + uri->path.length = (*uri_path)->length; + } + *uri_query = coap_get_query(request); + if (*uri_query) { + uri->query.s = (*uri_query)->s; + uri->query.length = (*uri_query)->length; + } + return 1; +} + +static int +verify_proxy_scheme_supported(coap_uri_scheme_t scheme) { + + /* Sanity check that the connection can be forwarded on */ + switch (scheme) { + case COAP_URI_SCHEME_HTTP: + case COAP_URI_SCHEME_HTTPS: + coap_log(LOG_WARNING, "Proxy URI http or https not supported\n"); + return 0; + case COAP_URI_SCHEME_COAP: + break; + case COAP_URI_SCHEME_COAPS: + if (!coap_dtls_is_supported()) { + coap_log(LOG_WARNING, + "coaps URI scheme not supported for proxy\n"); + return 0; + } + break; + case COAP_URI_SCHEME_COAP_TCP: + if (!coap_tcp_is_supported()) { + coap_log(LOG_WARNING, + "coap+tcp URI scheme not supported for proxy\n"); + return 0; + } + break; + case COAP_URI_SCHEME_COAPS_TCP: + if (!coap_tls_is_supported()) { + coap_log(LOG_WARNING, + "coaps+tcp URI scheme not supported for proxy\n"); + return 0; + } + break; + default: + coap_log(LOG_WARNING, + "%d URI scheme not supported\n", scheme); + break; + } + return 1; +} + +static coap_dtls_cpsk_t * +setup_cpsk(char *client_sni) { + static coap_dtls_cpsk_t dtls_cpsk; + + memset (&dtls_cpsk, 0, sizeof(dtls_cpsk)); + dtls_cpsk.version = COAP_DTLS_CPSK_SETUP_VERSION; + dtls_cpsk.client_sni = client_sni; + dtls_cpsk.psk_info.identity.s = user; + dtls_cpsk.psk_info.identity.length = user_length; + dtls_cpsk.psk_info.key.s = key; + dtls_cpsk.psk_info.key.length = key_length; + return &dtls_cpsk; +} + +static proxy_list_t * +get_proxy_session(coap_session_t *session, coap_pdu_t *response, + const coap_bin_const_t *token, const coap_string_t *query, + coap_pdu_code_t req_code, coap_pdu_type_t req_type) { + + size_t i; + proxy_list_t *new_proxy_list; + + /* Locate existing forwarding relationship */ + for (i = 0; i < proxy_list_count; i++) { + if (proxy_list[i].incoming == session) { + return &proxy_list[i]; + } + } + + /* Need to create a new forwarding mapping */ + new_proxy_list = realloc(proxy_list, (i+1)*sizeof(proxy_list[0])); + + if (new_proxy_list == NULL) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + return NULL; + } + proxy_list = new_proxy_list; + proxy_list[i].incoming = session; + if (token) { + proxy_list[i].token = coap_new_binary(token->length); + if (!proxy_list[i].token) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + return NULL; + } + memcpy(proxy_list[i].token->s, token->s, token->length); + } + else + proxy_list[i].token = NULL; + + if (query) { + proxy_list[i].query = coap_new_string(query->length); + if (!proxy_list[i].query) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + return NULL; + } + memcpy(proxy_list[i].query->s, query->s, query->length); + } + else + proxy_list[i].query = NULL; + + proxy_list[i].ongoing = NULL; + proxy_list[i].req_code = req_code; + proxy_list[i].req_type = req_type; + proxy_list_count++; + return &proxy_list[i]; +} + +static void +remove_proxy_association(coap_session_t *session, int send_failure) { + + size_t i; + + for (i = 0; i < proxy_list_count; i++) { + if (proxy_list[i].incoming == session) { + coap_session_release(proxy_list[i].ongoing); + break; + } + if (proxy_list[i].ongoing == session && send_failure) { + coap_pdu_t *response; + + coap_session_release(proxy_list[i].ongoing); + + /* Need to send back a gateway failure */ + response = coap_pdu_init(proxy_list[i].req_type, + COAP_RESPONSE_CODE_BAD_GATEWAY, + coap_new_message_id(proxy_list[i].incoming), + coap_session_max_pdu_size(proxy_list[i].incoming)); + if (!response) { + coap_log(LOG_INFO, "PDU creation issue\n"); + return; + } + + if (proxy_list[i].token && + !coap_add_token(response, proxy_list[i].token->length, + proxy_list[i].token->s)) { + coap_log(LOG_DEBUG, + "Cannot add token to incoming proxy response PDU\n"); + } + + if (coap_send(proxy_list[i].incoming, response) == + COAP_INVALID_MID) { + coap_log(LOG_INFO, "Failed to send PDU with 5.02 gateway issue\n"); + } + break; + } + } + if (i != proxy_list_count) { + coap_delete_binary(proxy_list[i].token); + coap_delete_string(proxy_list[i].query); + if (proxy_list_count-i > 1) { + memmove (&proxy_list[i], + &proxy_list[i+1], + (proxy_list_count-i-1) * sizeof (proxy_list[0])); + } + proxy_list_count--; + } +} + + +static coap_session_t * +get_ongoing_proxy_session(coap_session_t *session, + coap_pdu_t *response, const coap_bin_const_t *token, + const coap_string_t *query, coap_pdu_code_t req_code, + coap_pdu_type_t req_type, const coap_uri_t *uri) { + + coap_address_t dst; + coap_uri_scheme_t scheme; + static char client_sni[256]; + coap_str_const_t server; + uint16_t port = COAP_DEFAULT_PORT; + proxy_list_t *new_proxy_list; + coap_context_t *context = coap_session_get_context(session); + + new_proxy_list = get_proxy_session(session, response, token, query, req_code, + req_type); + if (!new_proxy_list) + return NULL; + + if (new_proxy_list->ongoing) + return new_proxy_list->ongoing; + + coap_address_init(&dst); + + if (proxy.host.length) { + server = proxy.host; + port = proxy.port; + scheme = proxy.scheme; + } else { + server = uri->host; + port = uri->port; + scheme = uri->scheme; + } + if (resolve_address(&server, &dst.addr.sa) < 0) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_GATEWAY); + remove_proxy_association(session, 0); + return NULL; + } + switch (dst.addr.sa.sa_family) { + case AF_INET: + dst.addr.sin.sin_port = ntohs(port); + break; + case AF_INET6: + dst.addr.sin6.sin6_port = ntohs(port); + break; + default: + break; + } + switch (scheme) { + case COAP_URI_SCHEME_COAP: + case COAP_URI_SCHEME_COAP_TCP: + new_proxy_list->ongoing = + coap_new_client_session(context, NULL, &dst, + scheme == COAP_URI_SCHEME_COAP ? + COAP_PROTO_UDP : COAP_PROTO_TCP); + break; + case COAP_URI_SCHEME_COAPS: + case COAP_URI_SCHEME_COAPS_TCP: + memset(client_sni, 0, sizeof(client_sni)); + if ((server.length == 3 && memcmp(server.s, "::1", 3) != 0) || + (server.length == 9 && memcmp(server.s, "127.0.0.1", 9) != 0)) + memcpy(client_sni, server.s, min(server.length, sizeof(client_sni)-1)); + else + memcpy(client_sni, "localhost", 9); + + if (!key_defined) { + /* Use our defined PKI certs (or NULL) */ + coap_dtls_pki_t *dtls_pki = setup_pki(context, COAP_DTLS_ROLE_CLIENT, + client_sni); + new_proxy_list->ongoing = + coap_new_client_session_pki(context, NULL, &dst, + scheme == COAP_URI_SCHEME_COAPS ? + COAP_PROTO_DTLS : COAP_PROTO_TLS, + dtls_pki); + } + else { + /* Use our defined PSK */ + coap_dtls_cpsk_t *dtls_cpsk = setup_cpsk(client_sni); + + new_proxy_list->ongoing = + coap_new_client_session_psk2(context, NULL, &dst, + scheme == COAP_URI_SCHEME_COAPS ? + COAP_PROTO_DTLS : COAP_PROTO_TLS, + dtls_cpsk); + } + break; + case COAP_URI_SCHEME_HTTP: + case COAP_URI_SCHEME_HTTPS: + default: + assert(0); + break; + } + if (new_proxy_list->ongoing == NULL) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); + remove_proxy_association(session, 0); + return NULL; + } + return new_proxy_list->ongoing; +} + +static void +release_proxy_body_data(coap_session_t *session COAP_UNUSED, + void *app_ptr) { + coap_delete_binary(app_ptr); +} + +static void +hnd_proxy_uri(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response) { + coap_opt_iterator_t opt_iter; + coap_opt_t *opt; + coap_opt_t *proxy_uri; + int proxy_scheme_option = 0; + coap_uri_t uri; + coap_string_t *uri_path = NULL; + coap_string_t *uri_query = NULL; + coap_session_t *ongoing = NULL; + size_t size; + size_t offset; + size_t total; + coap_binary_t *body_data = NULL; + const uint8_t *data; + coap_pdu_t *pdu; + coap_optlist_t *optlist = NULL; + coap_opt_t *option; + unsigned char portbuf[2]; +#define BUFSIZE 100 + unsigned char _buf[BUFSIZE]; + unsigned char *buf = _buf; + size_t buflen; + int res; + coap_bin_const_t token = coap_pdu_get_token(request); + + memset(&uri, 0, sizeof(uri)); + /* + * See if Proxy-Scheme + */ + opt = coap_check_option(request, COAP_OPTION_PROXY_SCHEME, &opt_iter); + if (opt) { + if (!get_uri_proxy_scheme_info(request, opt, &uri, &uri_path, + &uri_query)) { + coap_pdu_set_code(response, + COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); + goto cleanup; + } + proxy_scheme_option = 1; + } + /* + * See if Proxy-Uri + */ + proxy_uri = coap_check_option(request, COAP_OPTION_PROXY_URI, &opt_iter); + if (proxy_uri) { + coap_log(LOG_INFO, "Proxy URI '%.*s'\n", + coap_opt_length(proxy_uri), + (const char*)coap_opt_value(proxy_uri)); + if (coap_split_proxy_uri(coap_opt_value(proxy_uri), + coap_opt_length(proxy_uri), + &uri) < 0) { + /* Need to return a 5.05 RFC7252 Section 5.7.2 */ + coap_log(LOG_WARNING, "Proxy URI not decodable\n"); + coap_pdu_set_code(response, + COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); + goto cleanup; + } + } + + if (!(proxy_scheme_option || proxy_uri)) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + goto cleanup; + } + + if (uri.host.length == 0) { + /* Ongoing connection not well formed */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); + goto cleanup; + } + + if (!verify_proxy_scheme_supported(uri.scheme)) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED); + goto cleanup; + } + + /* Handle the CoAP forwarding mapping */ + if (uri.scheme == COAP_URI_SCHEME_COAP || + uri.scheme == COAP_URI_SCHEME_COAPS || + uri.scheme == COAP_URI_SCHEME_COAP_TCP || + uri.scheme == COAP_URI_SCHEME_COAPS_TCP) { + coap_pdu_code_t req_code = coap_pdu_get_code(request); + coap_pdu_type_t req_type = coap_pdu_get_type(request); + + if (!get_proxy_session(session, response, &token, query, req_code, req_type)) + goto cleanup; + + if (coap_get_data_large(request, &size, &data, &offset, &total)) { + /* COAP_BLOCK_SINGLE_BODY is set, so single body should be given */ + assert(size == total); + body_data = coap_new_binary(total); + if (!body_data) { + coap_log(LOG_DEBUG, "body build memory error\n"); + goto cleanup; + } + memcpy(body_data->s, data, size); + data = body_data->s; + } + + /* Send data on (opening session if appropriate) */ + + ongoing = get_ongoing_proxy_session(session, response, &token, + query, req_code, req_type, &uri); + /* + * Build up the ongoing PDU that we are going to send + */ + pdu = coap_pdu_init(req_type, req_code, + coap_new_message_id(ongoing), + coap_session_max_pdu_size(ongoing)); + if (!pdu) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + goto cleanup; + } + + if (!coap_add_token(pdu, token.length, token.s)) { + coap_log(LOG_DEBUG, "cannot add token to proxy request\n"); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + coap_delete_pdu(pdu); + goto cleanup; + } + + if (proxy.host.length == 0) { + /* Use Uri-Path and Uri-Query - direct session */ + proxy_uri = NULL; + proxy_scheme_option = 0; + + if (uri.port != (coap_uri_scheme_is_secure(&uri) ? + COAPS_DEFAULT_PORT : COAP_DEFAULT_PORT)) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_PORT, + coap_encode_var_safe(portbuf, sizeof(portbuf), + (uri.port & 0xffff)), + portbuf)); + } + + if (uri.path.length) { + buflen = BUFSIZE; + if (uri.path.length > BUFSIZE) + coap_log(LOG_WARNING, + "URI path will be truncated (max buffer %d)\n", BUFSIZE); + res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + + while (res--) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_PATH, + coap_opt_length(buf), + coap_opt_value(buf))); + + buf += coap_opt_size(buf); + } + } + + if (uri.query.length) { + buflen = BUFSIZE; + buf = _buf; + res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); + + while (res--) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_QUERY, + coap_opt_length(buf), + coap_opt_value(buf))); + + buf += coap_opt_size(buf); + } + } + } + + /* Copy the remaining options across */ + coap_option_iterator_init(request, &opt_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_iter))) { + switch (opt_iter.number) { + case COAP_OPTION_PROXY_URI: + if (proxy_uri) { + /* Need to add back in */ + goto add_in; + } + break; + case COAP_OPTION_PROXY_SCHEME: + case COAP_OPTION_URI_PATH: + case COAP_OPTION_URI_PORT: + case COAP_OPTION_URI_QUERY: + if (proxy_scheme_option) { + /* Need to add back in */ + goto add_in; + } + break; + case COAP_OPTION_BLOCK1: + case COAP_OPTION_BLOCK2: + /* These are not passed on */ + break; + default: +add_in: + coap_insert_optlist(&optlist, + coap_new_optlist(opt_iter.number, + coap_opt_length(option), + coap_opt_value(option))); + break; + } + } + + /* Update pdu with options */ + coap_add_optlist_pdu(pdu, &optlist); + coap_delete_optlist(optlist); + + if (size) { + if (!coap_add_data_large_request(ongoing, pdu, size, data, + release_proxy_body_data, body_data)) { + coap_log(LOG_DEBUG, "cannot add data to proxy request\n"); + } + else { + body_data = NULL; + } + } + + if (coap_get_log_level() < LOG_DEBUG) + coap_show_pdu(LOG_INFO, pdu); + + coap_send(ongoing, pdu); + /* + * Do not update with response code (hence empty ACK) as will be sending + * separate response when response comes back from upstream server + */ + goto cleanup; + } + else { + /* TODO http & https */ + coap_log(LOG_ERR, "Proxy-Uri scheme %d unknown\n", uri.scheme); + } +cleanup: + coap_delete_string(uri_path); + coap_delete_string(uri_query); + coap_delete_binary(body_data); +} + +#endif /* SERVER_CAN_PROXY */ + +typedef struct dynamic_resource_t { + coap_string_t *uri_path; + transient_value_t *value; + coap_resource_t *resource; + int created; + uint16_t media_type; +} dynamic_resource_t; + +static int dynamic_count = 0; +static dynamic_resource_t *dynamic_entry = NULL; + +/* + * Regular DELETE handler - used by resources created by the + * Unknown Resource PUT handler + */ + +static void +hnd_delete(coap_resource_t *resource, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response +) { + int i; + coap_string_t *uri_path; + + /* get the uri_path */ + uri_path = coap_get_uri_path(request); + if (!uri_path) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + + for (i = 0; i < dynamic_count; i++) { + if (coap_string_equal(uri_path, dynamic_entry[i].uri_path)) { + /* Dynamic entry no longer required - delete it */ + release_resource_data(session, dynamic_entry[i].value); + coap_delete_string(dynamic_entry[i].uri_path); + if (dynamic_count-i > 1) { + memmove (&dynamic_entry[i], + &dynamic_entry[i+1], + (dynamic_count-i-1) * sizeof (dynamic_entry[0])); + } + dynamic_count--; + break; + } + } + + /* Dynamic resource no longer required - delete it */ + coap_delete_resource(NULL, resource); + coap_delete_string(uri_path); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); +} + +/* + * Regular GET handler - used by resources created by the + * Unknown Resource PUT handler + */ + +static void +hnd_get(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response +) { + coap_str_const_t *uri_path; + int i; + dynamic_resource_t *resource_entry = NULL; + coap_binary_t body; + /* + * request will be NULL if an Observe triggered request, so the uri_path, + * if needed, must be abstracted from the resource. + * The uri_path string is a const pointer + */ + + uri_path = coap_resource_get_uri_path(resource); + if (!uri_path) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + + for (i = 0; i < dynamic_count; i++) { + if (coap_string_equal(uri_path, dynamic_entry[i].uri_path)) { + break; + } + } + if (i == dynamic_count) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + + resource_entry = &dynamic_entry[i]; + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + body = reference_resource_data(resource_entry->value); + coap_add_data_large_response(resource, session, request, response, + query, resource_entry->media_type, -1, 0, + body.length, + body.s, + release_resource_data, resource_entry->value); +} + +/* + * Regular PUT or POST handler - used by resources created by the + * Unknown Resource PUT/POST handler + */ + +static void +hnd_put_post(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response +) { + coap_string_t *uri_path; + int i; + size_t size; + const uint8_t *data; + size_t offset; + size_t total; + dynamic_resource_t *resource_entry = NULL; + unsigned char buf[6]; /* space to hold encoded/decoded uints */ + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_binary_t *data_so_far; + transient_value_t *transient_value; + + /* get the uri_path */ + uri_path = coap_get_uri_path(request); + if (!uri_path) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + + /* + * Locate the correct dynamic block for this request + */ + for (i = 0; i < dynamic_count; i++) { + if (coap_string_equal(uri_path, dynamic_entry[i].uri_path)) { + break; + } + } + if (i == dynamic_count) { + if (dynamic_count >= support_dynamic) { + /* Should have been caught hnd_put_post_unknown() */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_ACCEPTABLE); + coap_delete_string(uri_path); + return; + } + dynamic_count++; + dynamic_entry = realloc (dynamic_entry, + dynamic_count * sizeof(dynamic_entry[0])); + if (dynamic_entry) { + dynamic_entry[i].uri_path = uri_path; + dynamic_entry[i].value = NULL; + dynamic_entry[i].resource = resource; + dynamic_entry[i].created = 1; + if ((option = coap_check_option(request, COAP_OPTION_CONTENT_FORMAT, + &opt_iter)) != NULL) { + dynamic_entry[i].media_type = + coap_decode_var_bytes (coap_opt_value (option), + coap_opt_length (option)); + } + else { + dynamic_entry[i].media_type = COAP_MEDIATYPE_TEXT_PLAIN; + } + /* Store media type of new resource in ct. We can use buf here + * as coap_add_attr() will copy the passed string. */ + memset(buf, 0, sizeof(buf)); + snprintf((char *)buf, sizeof(buf), "%d", dynamic_entry[i].media_type); + /* ensure that buf is always zero-terminated */ + assert(buf[sizeof(buf) - 1] == '\0'); + buf[sizeof(buf) - 1] = '\0'; + coap_add_attr(resource, + coap_make_str_const("ct"), + coap_make_str_const((char*)buf), + 0); + } else { + dynamic_count--; + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + coap_delete_string(uri_path); + return; + } + } else { + /* Need to do this as coap_get_uri_path() created it */ + coap_delete_string(uri_path); + } + + resource_entry = &dynamic_entry[i]; + + if (coap_get_data_large(request, &size, &data, &offset, &total) && + size != total) { + /* + * A part of the data has been received (COAP_BLOCK_SINGLE_BODY not set). + * However, total unfortunately is only an indication, so it is not safe to + * allocate a block based on total. As per + * https://tools.ietf.org/html/rfc7959#section-4 + * o In a request carrying a Block1 Option, to indicate the current + * estimate the client has of the total size of the resource + * representation, measured in bytes ("size indication"). + * + * coap_cache_ignore_options() must have previously been called with at + * least COAP_OPTION_BLOCK1 set as the option value will change per block. + */ + coap_cache_entry_t *cache_entry = coap_cache_get_by_pdu(session, + request, + COAP_CACHE_IS_SESSION_BASED); + + if (offset == 0) { + if (!cache_entry) { + cache_entry = coap_new_cache_entry(session, request, + COAP_CACHE_NOT_RECORD_PDU, + COAP_CACHE_IS_SESSION_BASED, 0); + } + else { + data_so_far = coap_cache_get_app_data(cache_entry); + if (data_so_far) { + coap_delete_binary(data_so_far); + data_so_far = NULL; + } + coap_cache_set_app_data(cache_entry, NULL, NULL); + } + } + if (!cache_entry) { + if (offset == 0) { + coap_log(LOG_WARNING, "Unable to create a new cache entry\n"); + } + else { + coap_log(LOG_WARNING, + "No cache entry available for the non-first BLOCK\n"); + } + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + return; + } + + if (size) { + /* Add in the new data to cache entry */ + data_so_far = coap_cache_get_app_data(cache_entry); + if (!data_so_far) { + data_so_far = coap_new_binary(size); + if (data_so_far) + memcpy(data_so_far->s, data, size); + } + else { + /* Add in new block to end of current data */ + coap_binary_t *new = coap_resize_binary(data_so_far, offset + size); + + if (new) { + data_so_far = new; + memcpy(&data_so_far->s[offset], data, size); + } + else { + /* Insufficient space to extend data_so_far */ + coap_delete_binary(data_so_far); + data_so_far = NULL; + } + } + /* Yes, data_so_far can be NULL */ + coap_cache_set_app_data(cache_entry, data_so_far, cache_free_app_data); + } + if (offset + size == total) { + /* All the data is now in */ + data_so_far = coap_cache_get_app_data(cache_entry); + coap_cache_set_app_data(cache_entry, NULL, NULL); + } + else { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTINUE); + return; + } + } + else { + /* single body of data received */ + data_so_far = coap_new_binary(size); + if (data_so_far && size) { + memcpy(data_so_far->s, data, size); + } + } + /* Need to de-reference as value may be in use elsewhere */ + release_resource_data(session, resource_entry->value); + transient_value = alloc_resource_data(data_so_far); + if (!transient_value) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + return; + } + resource_entry->value = transient_value; + + if (resource_entry->created) { + coap_pdu_code_t code = coap_pdu_get_code(request); + + resource_entry->created = 0; + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); + if (code == COAP_REQUEST_CODE_POST) { + /* Add in Location-Path / Location-Query Options */ + coap_option_iterator_init(request, &opt_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_iter))) { + switch (opt_iter.number) { + case COAP_OPTION_URI_PATH: + if (!coap_add_option(response, COAP_OPTION_LOCATION_PATH, + coap_opt_length(option), + coap_opt_value(option))) + goto fail; + break; + case COAP_OPTION_URI_QUERY: + if (!coap_add_option(response, COAP_OPTION_LOCATION_QUERY, + coap_opt_length(option), + coap_opt_value(option))) + goto fail; + break; + default: + break; + } + } + } + } + else { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); + coap_resource_notify_observers(resource_entry->resource, NULL); + } + + if (echo_back) { + coap_binary_t body; + + body = reference_resource_data(resource_entry->value); + coap_add_data_large_response(resource, session, request, response, + query, resource_entry->media_type, -1, 0, + body.length, + body.s, + release_resource_data, resource_entry->value); + } + return; + +fail: + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + return; +} + +/* + * Unknown Resource PUT handler + */ + +static void +hnd_put_post_unknown(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response +) { + coap_resource_t *r; + coap_string_t *uri_path; + + /* check if creating a new resource is allowed */ + if (dynamic_count >= support_dynamic) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_ACCEPTABLE); + return; + } + + /* get the uri_path - will get used by coap_resource_init() */ + uri_path = coap_get_uri_path(request); + if (!uri_path) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + + /* + * Create a resource to handle the new URI + * uri_path will get deleted when the resource is removed + */ + r = coap_resource_init((coap_str_const_t*)uri_path, + COAP_RESOURCE_FLAGS_RELEASE_URI | resource_flags); + coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"Dynamic\""), 0); + coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_post); + coap_register_request_handler(r, COAP_REQUEST_POST, hnd_put_post); + coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete); + /* We possibly want to Observe the GETs */ + coap_resource_set_get_observable(r, 1); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get); + coap_add_resource(coap_session_get_context(session), r); + + /* Do the PUT/POST for this first call */ + hnd_put_post(r, session, request, query, response); +} + +#if SERVER_CAN_PROXY +static int +proxy_event_handler(coap_session_t *session, + coap_event_t event) { + + switch(event) { + case COAP_EVENT_DTLS_CLOSED: + case COAP_EVENT_TCP_CLOSED: + case COAP_EVENT_SESSION_CLOSED: + /* Need to remove any proxy associations */ + remove_proxy_association(session, 0); + break; + case COAP_EVENT_DTLS_CONNECTED: + case COAP_EVENT_DTLS_RENEGOTIATE: + case COAP_EVENT_DTLS_ERROR: + case COAP_EVENT_TCP_CONNECTED: + case COAP_EVENT_TCP_FAILED: + case COAP_EVENT_SESSION_CONNECTED: + case COAP_EVENT_SESSION_FAILED: + case COAP_EVENT_PARTIAL_BLOCK: + case COAP_EVENT_XMIT_BLOCK_FAIL: + case COAP_EVENT_SERVER_SESSION_NEW: + case COAP_EVENT_SERVER_SESSION_DEL: + default: + break; + } + return 0; +} + +static coap_response_t +proxy_response_handler(coap_session_t *session, + const coap_pdu_t *sent COAP_UNUSED, + const coap_pdu_t *received, + const coap_mid_t id COAP_UNUSED) { + + coap_pdu_t *pdu = NULL; + coap_session_t *incoming = NULL; + size_t i; + size_t size; + const uint8_t *data; + coap_optlist_t *optlist = NULL; + coap_opt_t *option; + coap_opt_iterator_t opt_iter; + size_t offset; + size_t total; + proxy_list_t *proxy_entry = NULL; + uint16_t media_type = COAP_MEDIATYPE_TEXT_PLAIN; + int maxage = -1; + uint64_t etag = 0; + coap_pdu_code_t rcv_code = coap_pdu_get_code(received); + coap_bin_const_t rcv_token = coap_pdu_get_token(received); + coap_binary_t *body_data = NULL; + + for (i = 0; i < proxy_list_count; i++) { + if (proxy_list[i].ongoing == session) { + proxy_entry = &proxy_list[i]; + incoming = proxy_entry->incoming; + break; + } + } + if (i == proxy_list_count) { + coap_log(LOG_DEBUG, "Unknown proxy ongoing session response received\n"); + return COAP_RESPONSE_OK; + } + + coap_log(LOG_DEBUG, "** process upstream incoming %d.%02d response:\n", + COAP_RESPONSE_CLASS(rcv_code), rcv_code & 0x1F); + if (coap_get_log_level() < LOG_DEBUG) + coap_show_pdu(LOG_INFO, received); + + if (coap_get_data_large(received, &size, &data, &offset, &total)) { + /* COAP_BLOCK_SINGLE_BODY is set, so single body should be given */ + assert(size == total); + body_data = coap_new_binary(total); + if (!body_data) { + coap_log(LOG_DEBUG, "body build memory error\n"); + return COAP_RESPONSE_OK; + } + memcpy(body_data->s, data, size); + data = body_data->s; + } + + /* + * Build up the ongoing PDU that we are going to send to proxy originator + * as separate response + */ + pdu = coap_pdu_init(proxy_entry->req_type, rcv_code, + coap_new_message_id(incoming), + coap_session_max_pdu_size(incoming)); + if (!pdu) { + coap_log(LOG_DEBUG, "Failed to create ongoing proxy response PDU\n"); + return COAP_RESPONSE_OK; + } + + if (!coap_add_token(pdu, rcv_token.length, rcv_token.s)) { + coap_log(LOG_DEBUG, "cannot add token to ongoing proxy response PDU\n"); + } + + /* + * Copy the options across, skipping those needed for + * coap_add_data_response_large() + */ + coap_option_iterator_init(received, &opt_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_iter))) { + switch (opt_iter.number) { + case COAP_OPTION_CONTENT_FORMAT: + media_type = coap_decode_var_bytes(coap_opt_value (option), + coap_opt_length (option)); + break; + case COAP_OPTION_MAXAGE: + maxage = coap_decode_var_bytes(coap_opt_value (option), + coap_opt_length (option)); + break; + case COAP_OPTION_ETAG: + etag = coap_decode_var_bytes8(coap_opt_value (option), + coap_opt_length (option)); + break; + case COAP_OPTION_BLOCK2: + case COAP_OPTION_SIZE2: + break; + default: + coap_insert_optlist(&optlist, + coap_new_optlist(opt_iter.number, + coap_opt_length(option), + coap_opt_value(option))); + break; + } + } + coap_add_optlist_pdu(pdu, &optlist); + coap_delete_optlist(optlist); + + if (size > 0) { + coap_pdu_t *dummy_pdu = coap_pdu_init(proxy_entry->req_type, + proxy_entry->req_code, 0, + coap_session_max_pdu_size(incoming)); + + coap_add_data_large_response(proxy_resource, incoming, dummy_pdu, pdu, + proxy_entry->query, + media_type, maxage, etag, size, data, + release_proxy_body_data, + body_data); + coap_delete_pdu(dummy_pdu); + } + + if (coap_get_log_level() < LOG_DEBUG) + coap_show_pdu(LOG_INFO, pdu); + + coap_send(incoming, pdu); + return COAP_RESPONSE_OK; +} + +static void +proxy_nack_handler(coap_session_t *session, + const coap_pdu_t *sent COAP_UNUSED, + const coap_nack_reason_t reason, + const coap_mid_t id COAP_UNUSED) { + + switch(reason) { + case COAP_NACK_TOO_MANY_RETRIES: + case COAP_NACK_NOT_DELIVERABLE: + case COAP_NACK_RST: + case COAP_NACK_TLS_FAILED: + /* Need to remove any proxy associations */ + remove_proxy_association(session, 1); + break; + case COAP_NACK_ICMP_ISSUE: + default: + break; + } + return; +} + +#endif /* SERVER_CAN_PROXY */ + +static void +init_resources(coap_context_t *ctx) { + coap_resource_t *r; + + r = coap_resource_init(NULL, COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_index); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"General Info\""), 0); + coap_add_resource(ctx, r); + + /* store clock base to use in /time */ + my_clock_base = clock_offset; + + r = coap_resource_init(coap_make_str_const("time"), resource_flags); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_fetch_time); + coap_register_request_handler(r, COAP_REQUEST_FETCH, hnd_get_fetch_time); + coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_time); + coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_time); + coap_resource_set_get_observable(r, 1); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"Internal Clock\""), 0); + coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"ticks\""), 0); + coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""), 0); + + coap_add_resource(ctx, r); + time_resource = r; + + if (support_dynamic > 0) { + /* Create a resource to handle PUTs to unknown URIs */ + r = coap_resource_unknown_init2(hnd_put_post_unknown, 0); + /* Add in handling POST as well */ + coap_register_handler(r, COAP_REQUEST_POST, hnd_put_post_unknown); + coap_add_resource(ctx, r); + } + + if (coap_async_is_supported()) { + r = coap_resource_init(coap_make_str_const("async"), + resource_flags | + COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT | + COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_DELAYS); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_async); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_resource(ctx, r); + } + + r = coap_resource_init(coap_make_str_const("example_data"), resource_flags); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_example_data); + coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_example_data); + coap_resource_set_get_observable(r, 1); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"Example Data\""), 0); + coap_add_resource(ctx, r); + +#if SERVER_CAN_PROXY + if (proxy_host_name_count) { + r = coap_resource_proxy_uri_init2(hnd_proxy_uri, proxy_host_name_count, + proxy_host_name_list, 0); + coap_add_resource(ctx, r); + coap_register_event_handler(ctx, proxy_event_handler); + coap_register_response_handler(ctx, proxy_response_handler); + coap_register_nack_handler(ctx, proxy_nack_handler); + proxy_resource = r; + } +#endif /* SERVER_CAN_PROXY */ +} + +static int +verify_cn_callback(const char *cn, + const uint8_t *asn1_public_cert COAP_UNUSED, + size_t asn1_length COAP_UNUSED, + coap_session_t *session COAP_UNUSED, + unsigned depth, + int validated COAP_UNUSED, + void *arg +) { + union { + coap_dtls_role_t r; + void *v; + } role = { .v = arg }; + + coap_log(LOG_INFO, "CN '%s' presented by %s (%s)\n", + cn, role.r == COAP_DTLS_ROLE_SERVER ? "client" : "server", + depth ? "CA" : "Certificate"); + return 1; +} + +static uint8_t *read_file_mem(const char* file, size_t *length) { + FILE *f; + uint8_t *buf; + struct stat statbuf; + + *length = 0; + if (!file || !(f = fopen(file, "r"))) + return NULL; + + if (fstat(fileno(f), &statbuf) == -1) { + fclose(f); + return NULL; + } + + buf = coap_malloc(statbuf.st_size+1); + if (!buf) { + fclose(f); + return NULL; + } + + if (fread(buf, 1, statbuf.st_size, f) != (size_t)statbuf.st_size) { + fclose(f); + coap_free(buf); + return NULL; + } + buf[statbuf.st_size] = '\000'; + *length = (size_t)(statbuf.st_size + 1); + fclose(f); + return buf; +} + +static void +update_pki_key(coap_dtls_key_t *dtls_key, const char *key_name, + const char *cert_name, const char *ca_name) {; + memset (dtls_key, 0, sizeof(*dtls_key)); + if ((key_name && strncasecmp (key_name, "pkcs11:", 7) == 0) || + (cert_name && strncasecmp (cert_name, "pkcs11:", 7) == 0) || + (ca_name && strncasecmp (ca_name, "pkcs11:", 7) == 0)) { + dtls_key->key_type = COAP_PKI_KEY_PKCS11; + dtls_key->key.pkcs11.public_cert = cert_name; + dtls_key->key.pkcs11.private_key = key_name ? key_name : cert_name; + dtls_key->key.pkcs11.ca = ca_name; + dtls_key->key.pkcs11.user_pin = pkcs11_pin; + } + else if (!use_pem_buf && !is_rpk_not_cert) { + dtls_key->key_type = COAP_PKI_KEY_PEM; + dtls_key->key.pem.public_cert = cert_name; + dtls_key->key.pem.private_key = key_name ? key_name : cert_name; + dtls_key->key.pem.ca_file = ca_name; + } + else { + /* Map file into memory */ + coap_free(ca_mem); + coap_free(cert_mem); + coap_free(key_mem); + ca_mem = read_file_mem(ca_name, &ca_mem_len); + cert_mem = read_file_mem(cert_name, &cert_mem_len); + key_mem = read_file_mem(key_name, &key_mem_len); + + dtls_key->key_type = COAP_PKI_KEY_PEM_BUF; + dtls_key->key.pem_buf.ca_cert = ca_mem; + dtls_key->key.pem_buf.public_cert = cert_mem; + dtls_key->key.pem_buf.private_key = key_mem ? key_mem : cert_mem; + dtls_key->key.pem_buf.ca_cert_len = ca_mem_len; + dtls_key->key.pem_buf.public_cert_len = cert_mem_len; + dtls_key->key.pem_buf.private_key_len = key_mem ? + key_mem_len : cert_mem_len; + } +} + +static coap_dtls_key_t * +verify_pki_sni_callback(const char *sni, + void *arg COAP_UNUSED +) { + static coap_dtls_key_t dtls_key; + + update_pki_key(&dtls_key, key_file, cert_file, ca_file); + + if (sni[0]) { + size_t i; + coap_log(LOG_INFO, "SNI '%s' requested\n", sni); + for (i = 0; i < valid_pki_snis.count; i++) { + /* Test for SNI to change cert + ca */ + if (strcasecmp(sni, valid_pki_snis.pki_sni_list[i].sni_match) == 0) { + coap_log(LOG_INFO, "Switching to using cert '%s' + ca '%s'\n", + valid_pki_snis.pki_sni_list[i].new_cert, + valid_pki_snis.pki_sni_list[i].new_ca); + update_pki_key(&dtls_key, valid_pki_snis.pki_sni_list[i].new_cert, + valid_pki_snis.pki_sni_list[i].new_cert, + valid_pki_snis.pki_sni_list[i].new_ca); + break; + } + } + } + else { + coap_log(LOG_DEBUG, "SNI not requested\n"); + } + return &dtls_key; +} + +static const coap_dtls_spsk_info_t * +verify_psk_sni_callback(const char *sni, + coap_session_t *c_session COAP_UNUSED, + void *arg COAP_UNUSED +) { + static coap_dtls_spsk_info_t psk_info; + + /* Preset with the defined keys */ + memset (&psk_info, 0, sizeof(psk_info)); + psk_info.hint.s = (const uint8_t *)hint; + psk_info.hint.length = hint ? strlen(hint) : 0; + psk_info.key.s = key; + psk_info.key.length = key_length; + if (sni) { + size_t i; + coap_log(LOG_INFO, "SNI '%s' requested\n", sni); + for (i = 0; i < valid_psk_snis.count; i++) { + /* Test for identity match to change key */ + if (strcasecmp(sni, + valid_psk_snis.psk_sni_list[i].sni_match) == 0) { + coap_log(LOG_INFO, "Switching to using '%.*s' hint + '%.*s' key\n", + (int)valid_psk_snis.psk_sni_list[i].new_hint->length, + valid_psk_snis.psk_sni_list[i].new_hint->s, + (int)valid_psk_snis.psk_sni_list[i].new_key->length, + valid_psk_snis.psk_sni_list[i].new_key->s); + psk_info.hint = *valid_psk_snis.psk_sni_list[i].new_hint; + psk_info.key = *valid_psk_snis.psk_sni_list[i].new_key; + break; + } + } + } + else { + coap_log(LOG_DEBUG, "SNI not requested\n"); + } + return &psk_info; +} + +static const coap_bin_const_t * +verify_id_callback(coap_bin_const_t *identity, + coap_session_t *c_session, + void *arg COAP_UNUSED +) { + static coap_bin_const_t psk_key; + const coap_bin_const_t *s_psk_hint = coap_session_get_psk_hint(c_session); + const coap_bin_const_t *s_psk_key; + size_t i; + + coap_log(LOG_INFO, "Identity '%.*s' requested, current hint '%.*s'\n", (int)identity->length, + identity->s, + s_psk_hint ? (int)s_psk_hint->length : 0, + s_psk_hint ? (const char *)s_psk_hint->s : ""); + + for (i = 0; i < valid_ids.count; i++) { + /* Check for hint match */ + if (s_psk_hint && + strcmp((const char *)s_psk_hint->s, + valid_ids.id_list[i].hint_match)) { + continue; + } + /* Test for identity match to change key */ + if (coap_binary_equal(identity, valid_ids.id_list[i].identity_match)) { + coap_log(LOG_INFO, "Switching to using '%.*s' key\n", + (int)valid_ids.id_list[i].new_key->length, + valid_ids.id_list[i].new_key->s); + return valid_ids.id_list[i].new_key; + } + } + + s_psk_key = coap_session_get_psk_key(c_session); + if (s_psk_key) { + /* Been updated by SNI callback */ + psk_key = *s_psk_key; + return &psk_key; + } + + /* Just use the defined key for now */ + psk_key.s = key; + psk_key.length = key_length; + return &psk_key; +} + +static coap_dtls_pki_t * +setup_pki(coap_context_t *ctx, coap_dtls_role_t role, char *client_sni) { + static coap_dtls_pki_t dtls_pki; + + /* If general root CAs are defined */ + if (role == COAP_DTLS_ROLE_SERVER && root_ca_file) { + struct stat stbuf; + if ((stat(root_ca_file, &stbuf) == 0) && S_ISDIR(stbuf.st_mode)) { + coap_context_set_pki_root_cas(ctx, NULL, root_ca_file); + } else { + coap_context_set_pki_root_cas(ctx, root_ca_file, NULL); + } + } + + memset (&dtls_pki, 0, sizeof(dtls_pki)); + dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; + if (ca_file || root_ca_file) { + /* + * Add in additional certificate checking. + * This list of enabled can be tuned for the specific + * requirements - see 'man coap_encryption'. + * + * Note: root_ca_file is setup separately using + * coap_context_set_pki_root_cas(), but this is used to define what + * checking actually takes place. + */ + dtls_pki.verify_peer_cert = verify_peer_cert; + dtls_pki.check_common_ca = !root_ca_file; + dtls_pki.allow_self_signed = 1; + dtls_pki.allow_expired_certs = 1; + dtls_pki.cert_chain_validation = 1; + dtls_pki.cert_chain_verify_depth = 2; + dtls_pki.check_cert_revocation = 1; + dtls_pki.allow_no_crl = 1; + dtls_pki.allow_expired_crl = 1; + } + else if (is_rpk_not_cert) { + dtls_pki.verify_peer_cert = verify_peer_cert; + } + dtls_pki.is_rpk_not_cert = is_rpk_not_cert; + dtls_pki.validate_cn_call_back = verify_cn_callback; + dtls_pki.cn_call_back_arg = (void*)role; + dtls_pki.validate_sni_call_back = role == COAP_DTLS_ROLE_SERVER ? + verify_pki_sni_callback : NULL; + dtls_pki.sni_call_back_arg = NULL; + + if (role == COAP_DTLS_ROLE_CLIENT) { + dtls_pki.client_sni = client_sni; + } + + update_pki_key(&dtls_pki.pki_key, key_file, cert_file, ca_file); + /* Need to keep base initialization copies of any COAP_PKI_KEY_PEM_BUF */ + ca_mem_base = ca_mem; + cert_mem_base = cert_mem; + key_mem_base = key_mem; + ca_mem = NULL; + cert_mem = NULL; + key_mem = NULL; + return &dtls_pki; +} + +static coap_dtls_spsk_t * +setup_spsk(void) { + static coap_dtls_spsk_t dtls_spsk; + + memset (&dtls_spsk, 0, sizeof(dtls_spsk)); + dtls_spsk.version = COAP_DTLS_SPSK_SETUP_VERSION; + dtls_spsk.validate_id_call_back = valid_ids.count ? + verify_id_callback : NULL; + dtls_spsk.validate_sni_call_back = valid_psk_snis.count ? + verify_psk_sni_callback : NULL; + dtls_spsk.psk_info.hint.s = (const uint8_t *)hint; + dtls_spsk.psk_info.hint.length = hint ? strlen(hint) : 0; + dtls_spsk.psk_info.key.s = key; + dtls_spsk.psk_info.key.length = key_length; + return &dtls_spsk; +} + +static void +fill_keystore(coap_context_t *ctx) { + + if (cert_file == NULL && key_defined == 0) { + if (coap_dtls_is_supported() || coap_tls_is_supported()) { + coap_log(LOG_DEBUG, + "(D)TLS not enabled as neither -k or -c options specified\n"); + } + return; + } + if (cert_file) { + coap_dtls_pki_t *dtls_pki = setup_pki(ctx, + COAP_DTLS_ROLE_SERVER, NULL); + if (!coap_context_set_pki(ctx, dtls_pki)) { + coap_log(LOG_INFO, "Unable to set up %s keys\n", + is_rpk_not_cert ? "RPK" : "PKI"); + /* So we do not set up DTLS */ + cert_file = NULL; + } + } + if (key_defined) { + coap_dtls_spsk_t *dtls_spsk = setup_spsk(); + + coap_context_set_psk2(ctx, dtls_spsk); + } +} + +static void +usage( const char *program, const char *version) { + const char *p; + char buffer[72]; + const char *lib_build = coap_package_build(); + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf( stderr, "%s v%s -- a small CoAP implementation\n" + "(c) 2010,2011,2015-2022 Olaf Bergmann and others\n\n" + "Build: %s\n" + "%s\n" + , program, version, lib_build, + coap_string_tls_version(buffer, sizeof(buffer))); + fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer))); + fprintf(stderr, "\n" + "Usage: %s [-d max] [-e] [-g group] [-G group_if] [-l loss] [-p port]\n" + "\t\t[-r] [-v num] [-A address] [-L value] [-N]\n" + "\t\t[-P scheme://address[:port],[name1[,name2..]]] [-X size]\n" + "\t\t[[-h hint] [-i match_identity_file] [-k key]\n" + "\t\t[-s match_psk_sni_file] [-u user]]\n" + "\t\t[[-c certfile] [-j keyfile] [-m] [-n] [-C cafile]\n" + "\t\t[-J pkcs11_pin] [-M rpk_file] [-R trust_casfile]\n" + "\t\t[-S match_pki_sni_file]]\n" + "General Options\n" + "\t-d max \t\tAllow dynamic creation of up to a total of max\n" + "\t \t\tresources. If max is reached, a 4.06 code is returned\n" + "\t \t\tuntil one of the dynamic resources has been deleted\n" + "\t-e \t\tEcho back the data sent with a PUT\n" + "\t-g group\tJoin the given multicast group\n" + "\t \t\tNote: DTLS over multicast is not currently supported\n" + "\t-G group_if\tUse this interface for listening for the multicast\n" + "\t \t\tgroup. This can be different from the implied interface\n" + "\t \t\tif the -A option is used\n" + "\t-l list\t\tFail to send some datagrams specified by a comma\n" + "\t \t\tseparated list of numbers or number ranges\n" + "\t \t\t(for debugging only)\n" + "\t-l loss%%\tRandomly fail to send datagrams with the specified\n" + "\t \t\tprobability - 100%% all datagrams, 0%% no datagrams\n" + "\t \t\t(for debugging only)\n" + "\t-p port\t\tListen on specified port for UDP and TCP. If (D)TLS is\n" + "\t \t\tenabled, then the coap-server will also listen on\n" + "\t \t\t 'port'+1 for DTLS and TLS. The default port is 5683\n" + "\t-r \t\tEnable multicast per resource support. If enabled,\n" + "\t \t\tonly '/', '/async' and '/.well-known/core' are enabled\n" + "\t \t\tfor multicast requests support, otherwise all\n" + "\t \t\tresources are enabled\n" + "\t-v num \t\tVerbosity level (default 3, maximum is 9). Above 7,\n" + "\t \t\tthere is increased verbosity in GnuTLS and OpenSSL\n" + "\t \t\tlogging\n" + "\t-A address\tInterface address to bind to\n" + "\t-L value\tSum of one or more COAP_BLOCK_* flag valuess for block\n" + "\t \t\thandling methods. Default is 1 (COAP_BLOCK_USE_LIBCOAP)\n" + "\t \t\t(Sum of one or more of 1,2 and 4)\n" + "\t-N \t\tMake \"observe\" responses NON-confirmable. Even if set\n" + "\t \t\tevery fifth response will still be sent as a confirmable\n" + "\t \t\tresponse (RFC 7641 requirement)\n" + , program); + fprintf( stderr, + "\t-P scheme://address[:port],[name1[,name2[,name3..]]]\n" + "\t \t\tScheme, address, optional port of how to connect to the\n" + "\t \t\tnext proxy server and zero or more names (comma\n" + "\t \t\tseparated) that this proxy server is known by. The\n" + "\t \t\t, (comma) is required. If there is no name1 or if the\n" + "\t \t\thostname of the incoming proxy request matches one of\n" + "\t \t\tthese names, then this server is considered to be the\n" + "\t \t\tfinal endpoint. If scheme://address[:port] is not\n" + "\t \t\tdefined before the leading , (comma) of the first name,\n" + "\t \t\tthen the ongoing connection will be a direct connection.\n" + "\t \t\tScheme is one of coap, coaps, coap+tcp and coaps+tcp\n" + "\t-X size\t\tMaximum message size to use for TCP based connections\n" + "\t \t\t(default is 8388864). Maximum value of 2^32 -1\n" + "PSK Options (if supported by underlying (D)TLS library)\n" + "\t-h hint\t\tIdentity Hint to send. Default is CoAP. Zero length is\n" + "\t \t\tno hint\n" + "\t-i match_identity_file\n" + "\t \t\tThis is a file that contains one or more lines of\n" + "\t \t\tIdentity Hints and (user) Identities to match for\n" + "\t \t\ta different new Pre-Shared Key (PSK) (comma separated)\n" + "\t \t\tto be used. E.g., per line\n" + "\t \t\t hint_to_match,identity_to_match,use_key\n" + "\t \t\tNote: -k still needs to be defined for the default case\n" + "\t \t\tNote: A match using the -s option may mean that the\n" + "\t \t\tcurrent Identity Hint is different to that defined by -h\n" + "\t-k key \t\tPre-Shared Key. This argument requires (D)TLS with PSK\n" + "\t \t\tto be available. This cannot be empty if defined.\n" + "\t \t\tNote that both -c and -k need to be defined for both\n" + "\t \t\tPSK and PKI to be concurrently supported\n" + "\t-s match_psk_sni_file\n" + "\t \t\tThis is a file that contains one or more lines of\n" + "\t \t\treceived Subject Name Identifier (SNI) to match to use\n" + "\t \t\ta different Identity Hint and associated Pre-Shared Key\n" + "\t \t\t(PSK) (comma separated) instead of the '-h hint' and\n" + "\t \t\t'-k key' options. E.g., per line\n" + "\t \t\t sni_to_match,use_hint,with_key\n" + "\t \t\tNote: -k still needs to be defined for the default case\n" + "\t \t\tif there is not a match\n" + "\t \t\tNote: The associated Pre-Shared Key will get updated if\n" + "\t \t\tthere is also a -i match. The update checking order is\n" + "\t \t\t-s followed by -i\n" + "\t-u user\t\tUser identity for pre-shared key mode (only used if\n" + "\t \t\toption -P is set)\n" + ); + fprintf(stderr, + "PKI Options (if supported by underlying (D)TLS library)\n" + "\tNote: If any one of '-c certfile', '-j keyfile' or '-C cafile' is in\n" + "\tPKCS11 URI naming format (pkcs11: prefix), then any remaining non\n" + "\tPKCS11 URI file definitions have to be in DER, not PEM, format.\n" + "\tOtherwise all of '-c certfile', '-j keyfile' or '-C cafile' are in\n" + "\tPEM format.\n\n" + "\t-c certfile\tPEM file or PKCS11 URI for the certificate. The private\n" + "\t \t\tkey can also be in the PEM file, or has the same PKCS11\n" + "\t \t\tURI. If not, the private key is defined by '-j keyfile'.\n" + "\t \t\tNote that both -c and -k need to be defined for both\n" + "\t \t\tPSK and PKI to be concurrently supported\n" + "\t-j keyfile\tPEM file or PKCS11 URI for the private key for the\n" + "\t \t\tcertificate in '-c certfile' if the parameter is\n" + "\t \t\tdifferent from certfile in '-c certfile'\n" + "\t-m \t\tUse COAP_PKI_KEY_PEM_BUF instead of COAP_PKI_KEY_PEM i/f\n" + "\t \t\tby reading into memory the Cert / CA file (for testing)\n" + "\t-n \t\tDisable remote peer certificate checking. This gives\n" + "\t \t\tclients the ability to use PKI, but without any defined\n" + "\t \t\tcertificates\n" + "\t-C cafile\tPEM file or PKCS11 URI that contains a list of one or\n" + "\t \t\tmore CAs that are to be passed to the client for the\n" + "\t \t\tclient to determine what client certificate to use.\n" + "\t \t\tNormally, this list of CAs would be the root CA and and\n" + "\t \t\tany intermediate CAs. Ideally the server certificate\n" + "\t \t\tshould be signed by the same CA so that mutual\n" + "\t \t\tauthentication can take place. The contents of cafile\n" + "\t \t\tare added to the trusted store of root CAs.\n" + "\t \t\tUsing the -C or -R options will will trigger the\n" + "\t \t\tvalidation of the client certificate unless overridden\n" + "\t \t\tby the -n option\n" + "\t-J pkcs11_pin\tThe user pin to unlock access to the PKCS11 token\n" + "\t-M rpk_file\tRaw Public Key (RPK) PEM file or PKCS11 URI that\n" + "\t \t\tcontains both PUBLIC KEY and PRIVATE KEY or just\n" + "\t \t\tEC PRIVATE KEY. (GnuTLS and TinyDTLS(PEM) support only).\n" + "\t \t\t'-C cafile' or '-R trust_casfile' are not required\n" + "\t-R trust_casfile\tPEM file containing the set of trusted root CAs\n" + "\t \t\tthat are to be used to validate the client certificate.\n" + "\t \t\tAlternatively, this can point to a directory containing\n" + "\t \t\ta set of CA PEM files.\n" + "\t \t\tUsing '-R trust_casfile' disables common CA mutual\n" + "\t \t\tauthentication which can only be done by using\n" + "\t \t\t'-C cafile'.\n" + "\t \t\tUsing the -C or -R options will will trigger the\n" + "\t \t\tvalidation of the client certificate unless overridden\n" + "\t \t\tby the -n option\n" + "\t-S match_pki_sni_file\n" + "\t \t\tThis option denotes a file that contains one or more\n" + "\t \t\tlines of Subject Name Identifier (SNI) to match for new\n" + "\t \t\tCert file and new CA file (comma separated) to be used.\n" + "\t \t\tE.g., per line\n" + "\t \t\t sni_to_match,new_cert_file,new_ca_file\n" + "\t \t\tNote: -c and -C still need to be defined for the default\n" + "\t \t\tcase\n" + ); +} + +static coap_context_t * +get_context(const char *node, const char *port) { + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + ctx = coap_new_context(NULL); + if (!ctx) { + return NULL; + } + /* Need PKI/RPK/PSK set up before we set up (D)TLS endpoints */ + fill_keystore(ctx); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + + s = getaddrinfo(node, port, &hints, &result); + if ( s != 0 ) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + coap_free_context(ctx); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) { + coap_address_t addr, addrs; + coap_endpoint_t *ep_udp = NULL, *ep_dtls = NULL; + + if (rp->ai_addrlen <= (socklen_t)sizeof(addr.addr)) { + coap_address_init(&addr); + addr.size = (socklen_t)rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + addrs = addr; + if (addr.addr.sa.sa_family == AF_INET) { + uint16_t temp = ntohs(addr.addr.sin.sin_port) + 1; + addrs.addr.sin.sin_port = htons(temp); + } else if (addr.addr.sa.sa_family == AF_INET6) { + uint16_t temp = ntohs(addr.addr.sin6.sin6_port) + 1; + addrs.addr.sin6.sin6_port = htons(temp); + } else { + goto finish; + } + + ep_udp = coap_new_endpoint(ctx, &addr, COAP_PROTO_UDP); + if (ep_udp) { + if (coap_dtls_is_supported() && (key_defined || cert_file)) { + ep_dtls = coap_new_endpoint(ctx, &addrs, COAP_PROTO_DTLS); + if (!ep_dtls) + coap_log(LOG_CRIT, "cannot create DTLS endpoint\n"); + } + } else { + coap_log(LOG_CRIT, "cannot create UDP endpoint\n"); + continue; + } + if (coap_tcp_is_supported()) { + coap_endpoint_t *ep_tcp; + ep_tcp = coap_new_endpoint(ctx, &addr, COAP_PROTO_TCP); + if (ep_tcp) { + if (coap_tls_is_supported() && (key_defined || cert_file)) { + coap_endpoint_t *ep_tls; + ep_tls = coap_new_endpoint(ctx, &addrs, COAP_PROTO_TLS); + if (!ep_tls) + coap_log(LOG_CRIT, "cannot create TLS endpoint\n"); + } + } else { + coap_log(LOG_CRIT, "cannot create TCP endpoint\n"); + } + } + if (ep_udp) + goto finish; + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + coap_free_context(ctx); + ctx = NULL; + +finish: + freeaddrinfo(result); + return ctx; +} + +#if SERVER_CAN_PROXY +static int +cmdline_proxy(char *arg) { + char *host_start = strchr(arg, ','); + char *next_name = host_start; + size_t ofs; + + if (!host_start) { + coap_log(LOG_WARNING, "Zero or more proxy host names not defined\n"); + return 0; + } + *host_start = '\000'; + + if (host_start != arg) { + /* Next upstream proxy is defined */ + if (coap_split_uri((unsigned char *)arg, strlen(arg), &proxy) < 0 || + proxy.path.length != 0 || proxy.query.length != 0) { + coap_log(LOG_ERR, "invalid CoAP Proxy definition\n"); + return 0; + } + } + proxy_host_name_count = 0; + while (next_name) { + proxy_host_name_count++; + next_name = strchr(next_name+1, ','); + } + proxy_host_name_list = coap_malloc(proxy_host_name_count * sizeof(char*)); + next_name = host_start; + ofs = 0; + while (next_name) { + proxy_host_name_list[ofs++] = next_name+1; + next_name = strchr(next_name+1, ','); + if (next_name) + *next_name = '\000'; + } + return 1; +} + +static ssize_t +cmdline_read_user(char *arg, unsigned char **buf, size_t maxlen) { + size_t len = strnlen(arg, maxlen); + if (len) { + *buf = (unsigned char *)arg; + /* len is the size or less, so 0 terminate to maxlen */ + (*buf)[len] = '\000'; + } + /* 0 length Identity is valid */ + return len; +} +#endif /* SERVER_CAN_PROXY */ + +static ssize_t +cmdline_read_key(char *arg, unsigned char **buf, size_t maxlen) { + size_t len = strnlen(arg, maxlen); + if (len) { + *buf = (unsigned char *)arg; + return len; + } + /* Need at least one byte for the pre-shared key */ + coap_log( LOG_CRIT, "Invalid Pre-Shared Key specified\n" ); + return -1; +} + +static int cmdline_read_psk_sni_check(char *arg) { + FILE *fp = fopen(arg, "r"); + static char tmpbuf[256]; + if (fp == NULL) { + coap_log(LOG_ERR, "SNI file: %s: Unable to open\n", arg); + return 0; + } + while (fgets(tmpbuf, sizeof(tmpbuf), fp) != NULL) { + char *cp = tmpbuf; + char *tcp = strchr(cp, '\n'); + + if (tmpbuf[0] == '#') + continue; + if (tcp) + *tcp = '\000'; + + tcp = strchr(cp, ','); + if (tcp) { + psk_sni_def_t *new_psk_sni_list; + new_psk_sni_list = realloc(valid_psk_snis.psk_sni_list, + (valid_psk_snis.count + 1)*sizeof (valid_psk_snis.psk_sni_list[0])); + if (new_psk_sni_list == NULL) { + break; + } + valid_psk_snis.psk_sni_list = new_psk_sni_list; + valid_psk_snis.psk_sni_list[valid_psk_snis.count].sni_match = strndup(cp, tcp-cp); + cp = tcp+1; + tcp = strchr(cp, ','); + if (tcp) { + valid_psk_snis.psk_sni_list[valid_psk_snis.count].new_hint = + coap_new_bin_const((const uint8_t *)cp, tcp-cp); + cp = tcp+1; + valid_psk_snis.psk_sni_list[valid_psk_snis.count].new_key = + coap_new_bin_const((const uint8_t *)cp, strlen(cp)); + valid_psk_snis.count++; + } + else { + free(valid_psk_snis.psk_sni_list[valid_psk_snis.count].sni_match); + } + } + } + fclose(fp); + return valid_psk_snis.count > 0; +} + +static int cmdline_read_identity_check(char *arg) { + FILE *fp = fopen(arg, "r"); + static char tmpbuf[256]; + if (fp == NULL) { + coap_log(LOG_ERR, "Identity file: %s: Unable to open\n", arg); + return 0; + } + while (fgets(tmpbuf, sizeof(tmpbuf), fp) != NULL) { + char *cp = tmpbuf; + char *tcp = strchr(cp, '\n'); + + if (tmpbuf[0] == '#') + continue; + if (tcp) + *tcp = '\000'; + + tcp = strchr(cp, ','); + if (tcp) { + id_def_t *new_id_list; + new_id_list = realloc(valid_ids.id_list, + (valid_ids.count + 1)*sizeof (valid_ids.id_list[0])); + if (new_id_list == NULL) { + break; + } + valid_ids.id_list = new_id_list; + valid_ids.id_list[valid_ids.count].hint_match = strndup(cp, tcp-cp); + cp = tcp+1; + tcp = strchr(cp, ','); + if (tcp) { + valid_ids.id_list[valid_ids.count].identity_match = + coap_new_bin_const((const uint8_t *)cp, tcp-cp); + cp = tcp+1; + valid_ids.id_list[valid_ids.count].new_key = + coap_new_bin_const((const uint8_t *)cp, strlen(cp)); + valid_ids.count++; + } + else { + free(valid_ids.id_list[valid_ids.count].hint_match); + } + } + } + fclose(fp); + return valid_ids.count > 0; +} + +static int cmdline_read_pki_sni_check(char *arg) { + FILE *fp = fopen(arg, "r"); + static char tmpbuf[256]; + if (fp == NULL) { + coap_log(LOG_ERR, "SNI file: %s: Unable to open\n", arg); + return 0; + } + while (fgets(tmpbuf, sizeof(tmpbuf), fp) != NULL) { + char *cp = tmpbuf; + char *tcp = strchr(cp, '\n'); + + if (tmpbuf[0] == '#') + continue; + if (tcp) + *tcp = '\000'; + + tcp = strchr(cp, ','); + if (tcp) { + pki_sni_def_t *new_pki_sni_list; + new_pki_sni_list = realloc(valid_pki_snis.pki_sni_list, + (valid_pki_snis.count + 1)*sizeof (valid_pki_snis.pki_sni_list[0])); + if (new_pki_sni_list == NULL) { + break; + } + valid_pki_snis.pki_sni_list = new_pki_sni_list; + valid_pki_snis.pki_sni_list[valid_pki_snis.count].sni_match = + strndup(cp, tcp-cp); + cp = tcp+1; + tcp = strchr(cp, ','); + if (tcp) { + int fail = 0; + valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_cert = + strndup(cp, tcp-cp); + cp = tcp+1; + valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_ca = + strndup(cp, strlen(cp)); + if (access(valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_cert, + R_OK)) { + coap_log(LOG_ERR, "SNI file: Cert File: %s: Unable to access\n", + valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_cert); + fail = 1; + } + if (access(valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_ca, + R_OK)) { + coap_log(LOG_ERR, "SNI file: CA File: %s: Unable to access\n", + valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_ca); + fail = 1; + } + if (fail) { + free(valid_pki_snis.pki_sni_list[valid_pki_snis.count].sni_match); + free(valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_cert); + free(valid_pki_snis.pki_sni_list[valid_pki_snis.count].new_ca); + } + else { + valid_pki_snis.count++; + } + } + else { + coap_log(LOG_ERR, + "SNI file: SNI_match,Use_Cert_file,Use_CA_file not defined\n"); + free(valid_pki_snis.pki_sni_list[valid_pki_snis.count].sni_match); + } + } + } + fclose(fp); + return valid_pki_snis.count > 0; +} + +int +main(int argc, char **argv) { + coap_context_t *ctx; + char *group = NULL; + char *group_if = NULL; + coap_tick_t now; + char addr_str[NI_MAXHOST] = "::"; + char port_str[NI_MAXSERV] = "5683"; + int opt; + int mcast_per_resource = 0; + coap_log_t log_level = LOG_WARNING; + unsigned wait_ms; + coap_time_t t_last = 0; + int coap_fd; + fd_set m_readfds; + int nfds = 0; + size_t i; + uint16_t cache_ignore_options[] = { COAP_OPTION_BLOCK1, + COAP_OPTION_BLOCK2, + /* See https://tools.ietf.org/html/rfc7959#section-2.10 */ + COAP_OPTION_MAXAGE, + /* See https://tools.ietf.org/html/rfc7959#section-2.10 */ + COAP_OPTION_IF_NONE_MATCH }; +#ifndef _WIN32 + struct sigaction sa; +#endif + + clock_offset = time(NULL); + + while ((opt = getopt(argc, argv, "c:d:eg:G:h:i:j:J:k:l:mnp:rs:u:v:A:C:L:M:NP:R:S:X:")) != -1) { + switch (opt) { + case 'A' : + strncpy(addr_str, optarg, NI_MAXHOST-1); + addr_str[NI_MAXHOST - 1] = '\0'; + break; + case 'c' : + cert_file = optarg; + break; + case 'C' : + ca_file = optarg; + break; + case 'd' : + support_dynamic = atoi(optarg); + break; + case 'e': + echo_back = 1; + break; + case 'g' : + group = optarg; + break; + case 'G' : + group_if = optarg; + break; + case 'h' : + if (!optarg[0]) { + hint = NULL; + break; + } + hint = optarg; + break; + case 'i': + if (!cmdline_read_identity_check(optarg)) { + usage(argv[0], LIBCOAP_PACKAGE_VERSION); + exit(1); + } + break; + case 'j' : + key_file = optarg; + break; + case 'J' : + pkcs11_pin = optarg; + break; + case 'k' : + key_length = cmdline_read_key(optarg, &key, MAX_KEY); + if (key_length < 0) { + break; + } + key_defined = 1; + break; + case 'l': + if (!coap_debug_set_packet_loss(optarg)) { + usage(argv[0], LIBCOAP_PACKAGE_VERSION); + exit(1); + } + break; + case 'L': + block_mode = strtoul(optarg, NULL, 0); + if (!(block_mode & COAP_BLOCK_USE_LIBCOAP)) { + fprintf(stderr, "Block mode must include COAP_BLOCK_USE_LIBCOAP (1)\n"); + exit(-1); + } + break; + case 'm': + use_pem_buf = 1; + break; + case 'M': + cert_file = optarg; + is_rpk_not_cert = 1; + break; + case 'n': + verify_peer_cert = 0; + break; + case 'N': + resource_flags = COAP_RESOURCE_FLAGS_NOTIFY_NON; + break; + case 'p' : + strncpy(port_str, optarg, NI_MAXSERV-1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'P': +#if SERVER_CAN_PROXY + if (!cmdline_proxy(optarg)) { + fprintf(stderr, "error specifying proxy address or host names\n"); + exit(-1); + } + block_mode |= COAP_BLOCK_SINGLE_BODY; +#else /* ! SERVER_CAN_PROXY */ + fprintf(stderr, "Proxy support not available as no Client mode code\n"); + exit(-1); +#endif /* ! SERVER_CAN_PROXY */ + break; + case 'r' : + mcast_per_resource = 1; + break; + case 'R' : + root_ca_file = optarg; + break; + case 's': + if (!cmdline_read_psk_sni_check(optarg)) { + usage(argv[0], LIBCOAP_PACKAGE_VERSION); + exit(1); + } + break; + case 'S': + if (!cmdline_read_pki_sni_check(optarg)) { + usage(argv[0], LIBCOAP_PACKAGE_VERSION); + exit(1); + } + break; + case 'u': +#if SERVER_CAN_PROXY + user_length = cmdline_read_user(optarg, &user, MAX_USER); +#else /* ! SERVER_CAN_PROXY */ + fprintf(stderr, "Proxy support not available as no Client mode code\n"); + exit(-1); +#endif /* ! SERVER_CAN_PROXY */ + break; + case 'v' : + log_level = strtol(optarg, NULL, 10); + break; + case 'X': + csm_max_message_size = strtol(optarg, NULL, 10); + break; + default: + usage( argv[0], LIBCOAP_PACKAGE_VERSION ); + exit( 1 ); + } + } + +#ifdef _WIN32 + signal(SIGINT, handle_sigint); +#else + memset (&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = handle_sigint; + sa.sa_flags = 0; + sigaction (SIGINT, &sa, NULL); + sigaction (SIGTERM, &sa, NULL); + /* So we do not exit on a SIGPIPE */ + sa.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &sa, NULL); +#endif + + coap_startup(); + coap_dtls_set_log_level(log_level); + coap_set_log_level(log_level); + + ctx = get_context(addr_str, port_str); + if (!ctx) + return -1; + + init_resources(ctx); + if (mcast_per_resource) + coap_mcast_per_resource(ctx); + coap_context_set_block_mode(ctx, block_mode); + if (csm_max_message_size) + coap_context_set_csm_max_message_size(ctx, csm_max_message_size); + + /* Define the options to ignore when setting up cache-keys */ + coap_cache_ignore_options(ctx, cache_ignore_options, + sizeof(cache_ignore_options)/sizeof(cache_ignore_options[0])); + /* join multicast group if requested at command line */ + if (group) + coap_join_mcast_group_intf(ctx, group, group_if); + + coap_fd = coap_context_get_coap_fd(ctx); + if (coap_fd != -1) { + /* if coap_fd is -1, then epoll is not supported within libcoap */ + FD_ZERO(&m_readfds); + FD_SET(coap_fd, &m_readfds); + nfds = coap_fd + 1; + } + + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; + + while ( !quit ) { + int result; + + if (coap_fd != -1) { + /* + * Using epoll. It is more usual to call coap_io_process() with wait_ms + * (as in the non-epoll branch), but doing it this way gives the + * flexibility of potentially working with other file descriptors that + * are not a part of libcoap. + */ + fd_set readfds = m_readfds; + struct timeval tv; + coap_tick_t begin, end; + + coap_ticks(&begin); + + tv.tv_sec = wait_ms / 1000; + tv.tv_usec = (wait_ms % 1000) * 1000; + /* Wait until any i/o takes place or timeout */ + result = select (nfds, &readfds, NULL, NULL, &tv); + if (result == -1) { + if (errno != EAGAIN) { + coap_log(LOG_DEBUG, "select: %s (%d)\n", coap_socket_strerror(), errno); + break; + } + } + if (result > 0) { + if (FD_ISSET(coap_fd, &readfds)) { + result = coap_io_process(ctx, COAP_IO_NO_WAIT); + } + } + if (result >= 0) { + coap_ticks(&end); + /* Track the overall time spent in select() and coap_io_process() */ + result = (int)(end - begin); + } + } + else { + /* + * epoll is not supported within libcoap + * + * result is time spent in coap_io_process() + */ + result = coap_io_process( ctx, wait_ms ); + } + if ( result < 0 ) { + break; + } else if ( result && (unsigned)result < wait_ms ) { + /* decrement if there is a result wait time returned */ + wait_ms -= result; + } else { + /* + * result == 0, or result >= wait_ms + * (wait_ms could have decremented to a small value, below + * the granularity of the timer in coap_io_process() and hence + * result == 0) + */ + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; + } + if (time_resource) { + coap_time_t t_now; + unsigned int next_sec_ms; + + coap_ticks(&now); + t_now = coap_ticks_to_rt(now); + if (t_last != t_now) { + /* Happens once per second */ + t_last = t_now; + coap_resource_notify_observers(time_resource, NULL); + } + /* need to wait until next second starts if wait_ms is too large */ + next_sec_ms = 1000 - (now % COAP_TICKS_PER_SECOND) * + 1000 / COAP_TICKS_PER_SECOND; + if (next_sec_ms && next_sec_ms < wait_ms) + wait_ms = next_sec_ms; + } + } + + coap_free(ca_mem); + coap_free(cert_mem); + coap_free(key_mem); + coap_free(ca_mem_base); + coap_free(cert_mem_base); + coap_free(key_mem_base); + for (i = 0; i < valid_psk_snis.count; i++) { + free(valid_psk_snis.psk_sni_list[i].sni_match); + coap_delete_bin_const(valid_psk_snis.psk_sni_list[i].new_hint); + coap_delete_bin_const(valid_psk_snis.psk_sni_list[i].new_key); + } + if (valid_psk_snis.count) + free(valid_psk_snis.psk_sni_list); + + for (i = 0; i < valid_ids.count; i++) { + free(valid_ids.id_list[i].hint_match); + coap_delete_bin_const(valid_ids.id_list[i].identity_match); + coap_delete_bin_const(valid_ids.id_list[i].new_key); + } + if (valid_ids.count) + free(valid_ids.id_list); + + for (i = 0; i < valid_pki_snis.count; i++) { + free(valid_pki_snis.pki_sni_list[i].sni_match); + free(valid_pki_snis.pki_sni_list[i].new_cert); + free(valid_pki_snis.pki_sni_list[i].new_ca); + } + if (valid_pki_snis.count) + free(valid_pki_snis.pki_sni_list); + + for (i = 0; i < (size_t)dynamic_count; i++) { + coap_delete_string(dynamic_entry[i].uri_path); + release_resource_data(NULL, dynamic_entry[i].value); + } + free(dynamic_entry); + release_resource_data(NULL, example_data_value); +#if SERVER_CAN_PROXY + for (i = 0; i < proxy_list_count; i++) { + coap_delete_binary(proxy_list[i].token); + coap_delete_string(proxy_list[i].query); + } + free(proxy_list); + proxy_list = NULL; + proxy_list_count = 0; +#ifdef _WIN32 +#pragma warning( disable : 4090 ) +#endif + coap_free(proxy_host_name_list); +#endif /* SERVER_CAN_PROXY */ + + coap_free_context(ctx); + coap_cleanup(); + + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/examples/coap_list.c b/examples/espidf-coap-server/components/libcoap/examples/coap_list.c new file mode 100644 index 000000000..1f71c5aab --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/coap_list.c @@ -0,0 +1,67 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ + +/* coap_list.c -- CoAP list structures + * + * Copyright (C) 2010,2011,2015 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms of + * use. + */ + +/* + * examples/coap_list.[ch] are DEPRECATED. You should be using + * struct coap_optlist_t instead with the following functions which are a part + * of libcoap. + * + * coap_new_optlist() + * coap_insert_optlist() + * coap_delete_optlist() + * coap_add_optlist_pdu() + * + * See 'man coap_pdu_setup' for further information. + * + * examples/coap_list.[ch] files will be removed in a future release + * They are left here to support building backward compatability of old versions + * of coap-client + */ + +#include +#include + +#include + +int +coap_insert(coap_list_t **head, coap_list_t *node) { + if (!node) { + coap_log(LOG_WARNING, "cannot create option Proxy-Uri\n"); + } else { + /* must append at the list end to avoid re-ordering of + * options during sort */ + LL_APPEND((*head), node); + } + + return node != NULL; +} + +int +coap_delete(coap_list_t *node) { + if (node) { + coap_free(node); + } + return 1; +} + +void +coap_delete_list(coap_list_t *queue) { + coap_list_t *elt, *tmp; + + if (!queue) + return; + + LL_FOREACH_SAFE(queue, elt, tmp) { + coap_delete(elt); + } +} + diff --git a/examples/espidf-coap-server/components/libcoap/examples/coap_list.h b/examples/espidf-coap-server/components/libcoap/examples/coap_list.h new file mode 100644 index 000000000..81b7839be --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/coap_list.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 * -*- */ + +/* coap_list.h -- CoAP list structures + * + * Copyright (C) 2010,2011,2015 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms of + * use. + */ + +/* + * examples/coap_list.[ch] are DEPRECATED. You should be using + * struct coap_optlist_t instead with the following functions which are a part + * of libcoap. + * + * coap_new_optlist() + * coap_insert_optlist() + * coap_delete_optlist() + * coap_add_optlist_pdu() + * + * See 'man coap_pdu_setup' for further information. + * + * examples/coap_list.[ch] files will be removed in a future release + * They are left here to support building backward compatibility of old versions + * of coap-client + */ + +#ifndef COAP_LIST_H_ +#define COAP_LIST_H_ + +#include + +typedef struct coap_list_t { + struct coap_list_t *next; + char data[]; +} coap_list_t; + +/** + * Adds node to given queue, ordered by specified order function. Returns 1 + * when insert was successful, 0 otherwise. + */ +int coap_insert(coap_list_t **queue, coap_list_t *node); + +/* destroys specified node */ +int coap_delete(coap_list_t *node); + +/* removes all items from given queue and frees the allocated storage */ +void coap_delete_list(coap_list_t *queue); + +#endif /* COAP_LIST_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/examples/contiki/.gitignore b/examples/espidf-coap-server/components/libcoap/examples/contiki/.gitignore new file mode 100644 index 000000000..6eab53964 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/contiki/.gitignore @@ -0,0 +1,7 @@ +contiki-minimal-net.a +contiki-minimal-net.map +contiki/ +obj_minimal-net/ +server.minimal-net +symbols.c +symbols.h diff --git a/examples/espidf-coap-server/components/libcoap/examples/contiki/Makefile.contiki b/examples/espidf-coap-server/components/libcoap/examples/contiki/Makefile.contiki new file mode 100644 index 000000000..8370a4322 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/contiki/Makefile.contiki @@ -0,0 +1,33 @@ +######################################################################## +# platform-specific options + +ifeq ($(TARGET), econotag) +CONTIKI_WITH_RPL=0 +CFLAGS += -DUIP_CONF_TCP=0 -DCOAP_MAX_BLOCK_SZX=1 +endif + +ifeq ($(TARGET), mbxxx) +CFLAGS += -DUIP_CONF_TCP=0 -DCOAP_MAX_BLOCK_SZX=1 -DHAVE_ASSERT_H -DHAVE_LIMITS_H +STM32W_CPUREV=CC +#STM32W_CPUREV=xB +endif + +# usually, you should not need changing anything beyond this line +######################################################################## + +CONTIKI?=../../../.. + +ifneq ($(NODE_ADDR),) + CFLAGS += -DNODE_ADDR=$(NODE_ADDR) +endif + +all: server + +CFLAGS += -Os -ffunction-sections +LDFLAGS += -Wl,--gc-sections,--undefined=_reset_vector__,--undefined=InterruptVectors,--undefined=_copy_data_init__,--undefined=_clear_bss_init__,--undefined=_end_of_init__ + +CFLAGS += #-DSHORT_ERROR_RESPONSE -DNDEBUG + +APPS += libcoap + +include $(CONTIKI)/Makefile.include diff --git a/examples/espidf-coap-server/components/libcoap/examples/contiki/README b/examples/espidf-coap-server/components/libcoap/examples/contiki/README new file mode 100644 index 000000000..e86dbb3e5 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/contiki/README @@ -0,0 +1,30 @@ +Example of libcoap running on contiki +===================================== + +To run the example, do + + $ make + $ sudo ./server.minimal-net + +(and in a second terminal) + + $ sudo ip -6 a a aaaa::1/64 dev tap0 + +and query `coap://[aaaa::1000]/time?ticks` with any coap tool, +or query `coap://[aaaa::1000]/.well-known/core` + +This will + +* download contiki from the upstream git sources +* build the server application +* run the server application, creating a virtual network device tap0 (unless + that exists) +* configure your network interface to make the server accessible. + +* return the appropriate response from the server to the client. + +The server creates a resource for 'time' with a query 'ticks'. This is +reported for `.well-known/core`. The work flow for adding more resources does +not differ from regular libcoap usage. If you seem to run out of memory +creating the resources, tweak the number of pre-allocated resources +in `coap_config.h.contiki`. diff --git a/examples/espidf-coap-server/components/libcoap/examples/contiki/coap-observer.c b/examples/espidf-coap-server/components/libcoap/examples/contiki/coap-observer.c new file mode 100644 index 000000000..68c74c7b2 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/contiki/coap-observer.c @@ -0,0 +1,186 @@ +/* coap-server.c -- Example CoAP server using Contiki and libcoap + * + * Copyright (C) 2011,2015,2018-2019 Olaf Bergmann and others + * + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the Contiki operating system. + * + */ + +#include "coap_config.h" +#include "net/uip-debug.h" + +#include + +#include "coap3/coap.h" + +static coap_context_t *coap_context; + +/* Where the resource to subscribe is hosted */ +static coap_address_t dst; + +/* The resource to observe */ +static char resource[] = "/s/light"; + +/* when did the last notify arrive? (0 == never) */ +static coap_tick_t last_seen = 0; + +PROCESS(coap_server_process, "CoAP server process"); +AUTOSTART_PROCESSES(&coap_server_process); +/*---------------------------------------------------------------------------*/ +void +init_coap() { + coap_address_t listen_addr; + + coap_address_init(&listen_addr); + listen_addr.port = UIP_HTONS(COAP_DEFAULT_PORT); + +#ifdef WITH_CONTIKI + /* initialize uIP address for SLAAC */ + uip_ip6addr(&listen_addr.addr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&listen_addr.addr, &uip_lladdr); + uip_ds6_addr_add(&listen_addr.addr, 0, ADDR_AUTOCONF); + + uip_debug_lladdr_print(&uip_lladdr); + printf("\r\n"); + uip_debug_ipaddr_print(&listen_addr.addr); + printf("\r\n"); +#endif /* WITH_CONTIKI */ + +#ifdef WITH_CONTIKI + printf("tentative address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", + listen_addr.addr.u8[0], listen_addr.addr.u8[1], + listen_addr.addr.u8[2], listen_addr.addr.u8[3], + listen_addr.addr.u8[4], listen_addr.addr.u8[5], + listen_addr.addr.u8[6], listen_addr.addr.u8[7], + listen_addr.addr.u8[8], listen_addr.addr.u8[9], + listen_addr.addr.u8[10], listen_addr.addr.u8[11], + listen_addr.addr.u8[12], listen_addr.addr.u8[13], + listen_addr.addr.u8[14], listen_addr.addr.u8[15] , + uip_ntohs(listen_addr.port)); +#endif + + coap_context = coap_new_context(&listen_addr); + + coap_set_log_level(LOG_DEBUG); + + if (!coap_context) + coap_log(LOG_CRIT, "cannot create CoAP context\r\n"); +} + +void +message_handler(coap_context_t *ctx, + const coap_address_t *remote, + coap_pdu_t *sent, + coap_pdu_t *received, + const coap_tid_t id) { + /* send ACK if received message is confirmable (i.e. a separate response) */ + coap_send_ack(ctx, remote, received); + + coap_log(LOG_DEBUG, "** process incoming %d.%02d response:\n", + (received->hdr->code >> 5), received->hdr->code & 0x1F); + coap_show_pdu(LOG_WARNING, received); + + coap_ticks(&last_seen); +} + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_server_process, ev, data) +{ + coap_pdu_t *request; + coap_uri_t uri; + PROCESS_BEGIN(); + + init_coap(); + + if (!coap_context) { + coap_log(LOG_EMERG, "cannot create context\n"); + PROCESS_EXIT(); + } + + coap_register_response_handler(coap_context, message_handler); + + /* setup subscription request */ + + coap_address_init(&dst); + dst.port = uip_htons(COAP_DEFAULT_PORT); + uip_ip6addr(&dst.addr, 0xaaaa, 0, 0, 0, 0x206, 0x98ff, 0xfe00, 0x232); + /* uip_ip6addr(&dst.addr, 0xfe80, 0, 0, 0, 0x206, 0x98ff, 0xfe00, 0x232); */ + + request = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_GET, + coap_new_message_id(coap_context), + COAP_DEFAULT_MTU); + + coap_split_uri((unsigned char *)resource, strlen(resource), &uri); + + if (uri.port != COAP_DEFAULT_PORT) { + unsigned char portbuf[2]; + coap_add_option(request, COAP_OPTION_URI_PORT, + coap_encode_var_safe(portbuf, sizeof(portbuf), + uri.port), + portbuf); + } + + if (uri.path.length) { +#define BUFSIZE 20 + unsigned char _buf[BUFSIZE]; + unsigned char *buf = _buf; + size_t buflen; + int res; + + buflen = BUFSIZE; +#undef BUFSIZE + res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + + while (res--) { + coap_add_option(request, COAP_OPTION_URI_PATH, + coap_opt_length(buf), coap_opt_value(buf)); + + buf += coap_opt_size(buf); + } + } + + coap_add_option(request, COAP_OPTION_OBSERVE, 0, NULL); + { + unsigned char buf[2]; + coap_prng(buf, 2); + coap_add_option(request, COAP_OPTION_TOKEN, 2, buf); + } + + if (COAP_INVALID_TID == coap_send_confirmed(coap_context, &dst, request)) + coap_delete_pdu(request); + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + coap_io_do_io(coap_context); /* read received data */ + coap_dispatch(coap_context); /* and dispatch PDUs from receivequeue */ + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/espidf-coap-server/components/libcoap/examples/contiki/radvd.conf.sample b/examples/espidf-coap-server/components/libcoap/examples/contiki/radvd.conf.sample new file mode 100644 index 000000000..33f2e8f3f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/contiki/radvd.conf.sample @@ -0,0 +1,14 @@ +interface tap0 +{ + AdvSendAdvert on; + MinRtrAdvInterval 3; + MaxRtrAdvInterval 20; + + prefix aaaa::/64 + { + AdvOnLink on; + AdvAutonomous on; + AdvRouterAddr on; + + }; +}; diff --git a/examples/espidf-coap-server/components/libcoap/examples/contiki/server.c b/examples/espidf-coap-server/components/libcoap/examples/contiki/server.c new file mode 100644 index 000000000..c469a1679 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/contiki/server.c @@ -0,0 +1,222 @@ +/* coap-server.c -- Example CoAP server using Contiki and libcoap + * + * Copyright (C) 2011 Olaf Bergmann + * + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the Contiki operating system. + * + */ + +#include "coap_config.h" + +#define DEBUG DEBUG_PRINT +#include "net/ip/uip-debug.h" +#include "net/net-debug.h" + +#include + +#include "coap3/coap.h" + +static coap_context_t *coap_context; + +static clock_time_t clock_offset; +/* changeable clock base (see handle_put_time()) */ +static clock_time_t my_clock_base = 0; +static coap_resource_t *time_resource = NULL; /* just for testing */ + +PROCESS(coap_server_process, "CoAP server process"); +AUTOSTART_PROCESSES(&coap_server_process); +/*---------------------------------------------------------------------------*/ +void +init_coap_server(coap_context_t **ctx) { + coap_address_t listen_addr; + uip_ipaddr_t gw_addr; + + assert(ctx); + + coap_set_log_level(LOG_DEBUG); + + coap_address_init(&listen_addr); + listen_addr.port = UIP_HTONS(COAP_DEFAULT_PORT); + + uip_ip6addr(&listen_addr.addr, 0xaaaa, 0, 0, 0, 0, 0, 0, NODE_ADDR); +#ifndef CONTIKI_TARGET_MINIMAL_NET + uip_ds6_prefix_add(&listen_addr.addr, 64, 0, 0, 0, 0); +#endif /* not CONTIKI_TARGET_MINIMAL_NET */ + + uip_ds6_addr_add(&listen_addr.addr, 0, ADDR_MANUAL); + + /* set default route to gateway aaaa::1 */ + uip_ip6addr(&gw_addr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0x0001); + uip_ds6_defrt_add(&gw_addr, 0); + + PRINTLLADDR(&uip_lladdr); + printf("\r\n"); + PRINT6ADDR(&listen_addr.addr); + printf("\r\n"); + + *ctx = coap_new_context(&listen_addr); + + if (!*ctx) { + coap_log(LOG_CRIT, "cannot create CoAP context\r\n"); + } +} + +/*---------------------------------------------------------------------------*/ +#ifndef min +# define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +void +hnd_get_time(coap_resource_t *resource, coap_session_t *session, + const coap_pdu_t *request, const coap_string_t *query, + coap_pdu_t *response) { + unsigned char buf[40]; + size_t len; + coap_tick_t now; + coap_tick_t t; + + if (my_clock_base) { + + /* calculate current time */ + coap_ticks(&t); + now = my_clock_base + (t / COAP_TICKS_PER_SECOND); + + if (query != NULL + && coap_string_equal(query, coap_make_str_const("ticks"))) { + /* output ticks */ + len = snprintf((char *)buf, sizeof(buf), "%u", (unsigned int)now); + + } else { /* output human-readable time */ + struct tm *tmp; + time_t tnow = now; + tmp = gmtime(&tnow); + if (!tmp) { + /* If 'tnow' is not valid */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + else { + len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp); + } + } + coap_add_data_blocked_response(request, response, + COAP_MEDIATYPE_TEXT_PLAIN, 1, + len, + buf); + } + else { + /* if my_clock_base was deleted, we pretend to have no such resource */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + } +} + +void +init_coap_resources(coap_context_t *ctx) { + coap_resource_t *r; +#if 0 + r = coap_resource_init(NULL, 0, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"General Info\""), 0); + coap_add_resource(ctx, r); +#endif + /* store clock base to use in /time */ + my_clock_base = clock_offset; + + r = coap_resource_init(coap_make_str_const("time"), 0); + if (!r) + goto error; + + coap_resource_set_get_observable(r, 1); + time_resource = r; + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time); +#if 0 + coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time); + coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time); +#endif + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + /* coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"Internal Clock\""), 0); */ + coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"ticks\""), 0); + coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""), 0); + + coap_add_resource(ctx, r); +#if 0 +#ifndef WITHOUT_ASYNC + r = coap_resource_init(coap_make_str_const("async"), 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_async); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_resource(ctx, r); +#endif /* WITHOUT_ASYNC */ +#endif + + return; + error: + coap_log(LOG_CRIT, "cannot create resource\n"); +} + +/* struct etimer notify_timer; */ +struct etimer dirty_timer; + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_server_process, ev, data) +{ + PROCESS_BEGIN(); + + clock_offset = clock_time(); + init_coap_server(&coap_context); + + if (!coap_context) { + coap_log(LOG_EMERG, "cannot create context\n"); + PROCESS_EXIT(); + } + + init_coap_resources(coap_context); + + if (!coap_context) { + coap_log(LOG_EMERG, "cannot create context\n"); + PROCESS_EXIT(); + } + + /* etimer_set(¬ify_timer, 5 * CLOCK_SECOND); */ + etimer_set(&dirty_timer, 30 * CLOCK_SECOND); + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + /* There is something to read on the endpoint */ + coap_io_process(coap_context, COAP_IO_WAIT); + } else if (ev == PROCESS_EVENT_TIMER && etimer_expired(&dirty_timer)) { + coap_resource_notify_observers(time_resource, NULL); + etimer_reset(&dirty_timer); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/espidf-coap-server/components/libcoap/examples/etsi_coaptest.sh b/examples/espidf-coap-server/components/libcoap/examples/etsi_coaptest.sh new file mode 100644 index 000000000..4049797f4 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/etsi_coaptest.sh @@ -0,0 +1,210 @@ +#!/bin/bash + +# test coap implementation for the ETSI CoAP Plugtest in March 2012 +# with test cases described in Plugtests Guide First Draft V0.0.16 + +COAP_CLIENT=./coap-client +tcpdump=/usr/sbin/tcpdump +DEFAULTPORT=5683 +CLIENTPORT=61701 +# directory for logging +LOGDIR=logs +# set client's verbose level +callopts=" -v 5" +longtimeout=180 +clienttimeout=$longtimeout +timeoutcmd=/usr/bin/timeout + +#URIREGEX=.*\/.* +# resembles approximately an ip address +IPADDRREGEX="^[1-2]?[0-9]{1,2}\.[1-2]?[0-9]{1,2}\.[1-2]?[0-9]{1,2}\.[1-2]?[0-9]{1,2}" +# FIXME IPV6 address +IP6REGEX=".*:.*:.*" + +# Testcase groups +CORE=( TD_COAP_CORE_01 TD_COAP_CORE_02 TD_COAP_CORE_03 +TD_COAP_CORE_04 TD_COAP_CORE_05 TD_COAP_CORE_06 TD_COAP_CORE_07 +TD_COAP_CORE_08 TD_COAP_CORE_09 TD_COAP_CORE_10 TD_COAP_CORE_11 +TD_COAP_CORE_12 TD_COAP_CORE_13 TD_COAP_CORE_14 TD_COAP_CORE_15 ) +LINK=( TD_COAP_LINK_01 TD_COAP_LINK_02 ) +BLOCK=( TD_COAP_BLOCK_01 TD_COAP_BLOCK_02 TD_COAP_BLOCK_03 TD_COAP_BLOCK_04 ) +OBS=( TD_COAP_OBS_01 TD_COAP_OBS_02 TD_COAP_OBS_03 TD_COAP_OBS_04 TD_COAP_OBS_05 ) + +testgroups=( CORE LINK BLOCK OBS ) + +# if no test cases are specified, we want to run all tests +testnumber=-1 +group='' + +source `dirname $0`/etsi_testcases.sh + +function usage { +echo "Usage: `basename $0` [-n testnumber] [-g groupname] [-t timeout] [-P server_port] [-p client port] [-d logdir] [-v] -i interface server_address" 1>&2 +echo "-n test case to be accomplished" 1>&2 +echo "-g group to be tested" 1>&2 +echo "-t time in seconds until timout for single test" 1>&2 +echo "-i interface to use for tcpdump" 1>&2 +echo "-P port of server" 1>&2 +echo "-p port client listens on" 1>&2 +echo "-d directory for logfiles" 1>&2 +echo "-v verbose level" 1>&2 +} + +function run_test { + tn=$1 + clientopts='' + if [ -z $1 ]; then + echo "missing argument for run_test" + exit 1 + fi + echo -e "running test: $tn" + if [ $(type -t $tn) ] ; then + $tn $tn + echo + else + echo "not implemented" + echo + fi +} + +while getopts "n:g:t:i:P:p:d:v" OPTION; +do +# A missing argument for an option leads getopts to take the next +# option as the parameter. We want to prevent that. +case $OPTARG in +-*) echo "Missing argument for option \"-$OPTION\"." +echo $USAGE +exit 1 +;; +esac + +case $OPTION in +n) # number of test case +testnumber=$((OPTARG-1)) +;; + +g) # name of test group +# is there a group with that name? +for i in "${testgroups[@]}" + do + # group doesn't have to be case sensitive + tmpgroup=$(echo $OPTARG | tr '[:lower:]' '[:upper:]') + if [ $i == $tmpgroup ] ; then + group=$tmpgroup + break + fi +done +if [ -z $group ] ; then + echo "No such group:" $OPTARG". Available groups are: ${testgroups[@]}" + exit 1 +fi +;; + +t) +# add timeout to client parameters +clienttimeout=$((OPTARG)) +callopts="$callopts -B $clienttimeout" +;; + +i) +# interface tcpdump listens on +INTERFACE=$OPTARG +;; + +P) +# port the server listens on +SERVERPORT=$((OPTARG)) +;; + +p) +# port the client listens on +CLIENTPORT=$((OPTARG)) +;; + +d) +# directory tcpdump writes the logfiles into +LOGDIR=$OPTARG +;; + +v) +verbose=1 +;; + +?) +# any other option is invalid +echo -e $USAGE 1>&2 +exit 1 +;; +esac +done + +# catch last argument: server address +ARGS=$(($#+1)) +SERVERADDRESS=${@: -1} + +if [[ ! $((ARGS-OPTIND)) -eq 1 ]]; then + echo -e "\nno server address specified" + usage + exit 1 +fi + +# if no port number was specified by user, the server address for the +# coap-client is $SERVERADDRESS + +if [ -z $SERVERPORT ]; then + SERVERPORT=$DEFAULTPORT + if [[ $SERVERADDRESS =~ $IP6REGEX ]]; then + SERVERTUP=\[$SERVERADDRESS\] + else + SERVERTUP=$SERVERADDRESS + fi +else + if [[ $SERVERADDRESS =~ $IP6REGEX ]]; then + SERVERTUP=\[$SERVERADDRESS\]:$SERVERPORT + else + SERVERTUP=$SERVERADDRESS:$SERVERPORT + fi +fi + +# create directory for logging, if it's not already there +if [[ ! -e $LOGDIR ]]; then + mkdir -p $LOGDIR + if [ $? ]; then + echo created directory \""$LOGDIR"\" for logging + fi +fi + +# the interface for tcpdump is mandatory +if [ -z $INTERFACE ]; then + echo -e "\nno interface given" + exit 1 +fi + +# determine which tests to run +if [ -n "$group" ] ; then + echo group: $group + if [[ ! $testnumber -eq -1 ]] ; then + groupsize=$(eval "echo \${#$(echo $group)[@]}") + # is there a testcase with number $testnumber in group $group + if [ $testnumber -ge $groupsize -o $testnumber -lt 0 ] ; then + echo "No such testcase number: $OPTARG. Test cases numbers are 1 to" $groupsize + exit 1 + else + # run test with group $group and number $testnumber + run_test $(eval "echo \${$(echo $group)[$testnumber]}") + fi + else + # if no testnumber was specified, we want to run all tests in that group + for i in $(eval "echo \${$(echo $group)[@]}") ; do + run_test $i + done + fi +else + # run all tests of all groups + for j in ${testgroups[@]} ; do + echo "group: $j" + for k in $(eval "echo \${$(echo $j)[@]}") ; do + run_test $k + done + done +fi diff --git a/examples/espidf-coap-server/components/libcoap/examples/etsi_iot_01.c b/examples/espidf-coap-server/components/libcoap/examples/etsi_iot_01.c new file mode 100644 index 000000000..be87edb5d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/etsi_iot_01.c @@ -0,0 +1,633 @@ +/* CoAP server for first ETSI CoAP plugtest, March 2012 + * + * Copyright (C) 2012--2013 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define COAP_RESOURCE_CHECK_TIME_SEC 1 + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* temporary storage for dynamic resource representations */ +static int quit = 0; + +#define COAP_OPT_BLOCK_SZX_MAX 6 /**< allowed maximum for block szx value */ + +#define REQUIRE_ETAG 0x01 /* flag for coap_payload_t: require ETag option */ +typedef struct { + unsigned int flags; /* some flags to control behavior */ + size_t max_data; /* maximum size allocated for @p data */ + uint16_t media_type; /* media type for this object */ + size_t length; /* length of data */ + unsigned char data[]; /* the actual contents */ +} coap_payload_t; + +/* SIGINT handler: set quit to 1 for graceful termination */ +static void +handle_sigint(int signum COAP_UNUSED) { + quit = 1; +} + +#define INDEX "libcoap server for ETSI CoAP Plugtest, March 2012, Paris\n" \ + "Copyright (C) 2012 Olaf Bergmann \n\n" + +static coap_payload_t * +coap_new_payload(size_t size) { + coap_payload_t *p; + p = (coap_payload_t *)coap_malloc(sizeof(coap_payload_t) + size); + if (p) { + memset(p, 0, sizeof(coap_payload_t)); + p->max_data = size; + } + + return p; +} + +static inline coap_payload_t * +coap_find_payload(coap_resource_t *resource) { + return coap_resource_get_userdata(resource); +} + +static void +coap_add_payload(coap_resource_t *resource, coap_payload_t *payload){ + assert(payload); + + coap_resource_set_userdata(resource, payload); +} + +static inline void +coap_delete_payload(coap_resource_t *resource) { + coap_free(coap_resource_get_userdata(resource)); + coap_resource_set_userdata(resource, NULL); +} + +static void +coap_free_userdata(void *data) { + coap_free(data); +} + +#if 0 +static void +hnd_get_index(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session COAP_UNUSED, + coap_pdu_t *request COAP_UNUSED, + coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + unsigned char buf[3]; + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_safe(buf, sizeof(buf), + COAP_MEDIATYPE_TEXT_PLAIN), + buf); + + coap_add_option(response, COAP_OPTION_MAXAGE, + coap_encode_var_safe(buf, sizeof(buf), 0x2ffff), buf); + + coap_add_data(response, strlen(INDEX), (const uint8_t *)INDEX); +} +#endif + +static void +hnd_get_resource(coap_resource_t *resource, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + coap_payload_t *test_payload; + + test_payload = coap_find_payload(resource); + if (!test_payload) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + + return; + } + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + + coap_add_data_blocked_response(request, response, + test_payload->media_type, -1, + test_payload->length, + test_payload->data); + return; +} + +/* DELETE handler for dynamic resources created by POST /test */ +static void +hnd_delete_resource(coap_resource_t *resource, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request COAP_UNUSED, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + coap_payload_t *payload; + + payload = coap_find_payload(resource); + + if (payload) + coap_delete_payload(resource); + + coap_delete_resource(NULL, resource); + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); +} + +static void +hnd_post_test(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_payload_t *test_payload; + size_t len; + coap_str_const_t *uri; + const uint8_t *data; + +#define BUFSIZE 20 + int res; + unsigned char _buf[BUFSIZE]; + unsigned char *buf = _buf; + size_t buflen = BUFSIZE; + + coap_get_data(request, &len, &data); + + /* allocate storage for resource and to hold URI */ + test_payload = coap_new_payload(len); + snprintf((char *)buf, buflen, "test/%p", (void *)test_payload); + uri = coap_new_str_const(buf, strlen((char *)buf)); + if (!(test_payload && uri)) { + coap_log(LOG_CRIT, "cannot allocate new resource under /test"); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + coap_free(test_payload); + coap_free(uri); + } else { + coap_resource_t *r; + + test_payload->length = len; + + memcpy(test_payload->data, data, len); + + r = coap_resource_init(uri, COAP_RESOURCE_FLAGS_RELEASE_URI); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_resource); + coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); + + /* set media_type if available */ + option = coap_check_option(request, COAP_OPTION_CONTENT_TYPE, &opt_iter); + if (option) { + test_payload->media_type = + coap_decode_var_bytes(coap_opt_value(option), coap_opt_length(option)); + } + + coap_add_resource(coap_session_get_context(session), r); + coap_add_payload(r, test_payload); + + /* add Location-Path */ + res = coap_split_path(uri->s, uri->length, buf, &buflen); + + while (res--) { + coap_add_option(response, COAP_OPTION_LOCATION_PATH, + coap_opt_length(buf), coap_opt_value(buf)); + + buf += coap_opt_size(buf); + } + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); + } + +} + +static void +hnd_put_test(coap_resource_t *resource, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_payload_t *payload; + size_t len; + const uint8_t *data; + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); + + coap_get_data(request, &len, &data); + + payload = coap_find_payload(resource); + if (payload && payload->max_data < len) { /* need more storage */ + coap_delete_payload(resource); + payload = NULL; + /* bug: when subsequent coap_new_payload() fails, our old contents + is gone */ + } + + if (!payload) { /* create new payload */ + payload = coap_new_payload(len); + if (!payload) + goto error; + + coap_add_payload(resource, payload); + } + payload->length = len; + memcpy(payload->data, data, len); + + option = coap_check_option(request, COAP_OPTION_CONTENT_TYPE, &opt_iter); + if (option) { + /* set media type given in request */ + payload->media_type = + coap_decode_var_bytes(coap_opt_value(option), coap_opt_length(option)); + } else { + /* set default value */ + payload->media_type = COAP_MEDIATYPE_TEXT_PLAIN; + } + /* FIXME: need to change attribute ct of resource. + To do so, we need dynamic management of the attribute value + */ + + return; + error: + coap_log(LOG_WARNING, "cannot modify resource\n"); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); +} + +static void +hnd_delete_test(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request COAP_UNUSED, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + /* the ETSI validation tool does not like empty resources... */ +#if 0 + coap_payload_t *payload; + payload = coap_find_payload(resource); + + if (payload) + payload->length = 0; +#endif + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); +} + +static void +hnd_get_query(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session COAP_UNUSED, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + coap_opt_iterator_t opt_iter; + coap_opt_filter_t f; + coap_opt_t *q; + size_t len, L; + unsigned char buf[70]; + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + + coap_add_option(response, COAP_OPTION_CONTENT_TYPE, + coap_encode_var_safe(buf, sizeof(buf), + COAP_MEDIATYPE_TEXT_PLAIN), + buf); + + coap_option_filter_clear(&f); + coap_option_filter_set(&f, COAP_OPTION_URI_QUERY); + + coap_option_iterator_init(request, &opt_iter, &f); + + len = 0; + while ((len < sizeof(buf)) && (q = coap_option_next(&opt_iter))) { + L = min(sizeof(buf) - len, 11); + memcpy(buf + len, "Uri-Query: ", L); + len += L; + + L = min(sizeof(buf) - len, coap_opt_length(q)); + memcpy(buf + len, coap_opt_value(q), L); + len += L; + + if (len < sizeof(buf)) + buf[len++] = '\n'; + } + + coap_add_data(response, len, buf); +} + +/* handler for TD_COAP_CORE_16 */ +static void +hnd_get_separate(coap_resource_t *resource COAP_UNUSED, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query COAP_UNUSED, + coap_pdu_t *response) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_opt_filter_t f; + unsigned long delay = 5; + + if (request) { + coap_async_t *async; + coap_bin_const_t token = coap_pdu_get_token(request); + + async = coap_find_async(session, token); + + if (!async) { + /* Set up an async request to trigger delay in the future */ + + /* search for option delay in query list */ + coap_option_filter_clear(&f); + coap_option_filter_set(&f, COAP_OPTION_URI_QUERY); + + coap_option_iterator_init(request, &opt_iter, &f); + + while ((option = coap_option_next(&opt_iter))) { + if (strncmp("delay=", (const char *)coap_opt_value(option), 6) == 0) { + unsigned int i; + unsigned long d = 0; + + for (i = 6; i < coap_opt_length(option); ++i) + d = d * 10 + coap_opt_value(option)[i] - '0'; + + /* don't allow delay to be less than COAP_RESOURCE_CHECK_TIME*/ + delay = d < COAP_RESOURCE_CHECK_TIME_SEC + ? COAP_RESOURCE_CHECK_TIME_SEC + : d; + coap_log(LOG_DEBUG, "set delay to %lu\n", delay); + break; + } + } + async = coap_register_async(session, + request, + COAP_TICKS_PER_SECOND * delay); + if (async == NULL) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE); + return; + } + /* Not setting response code will cause empty ACK to be sent + if Confirmable */ + return; + } + } + + /* no request (observe) or async set up, so this is the delayed request */ + coap_add_data(response, 4, (const uint8_t *)"done"); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + + /* async is automatically removed by libcoap */ +} + +static coap_payload_t * +make_large(const char *filename) { + coap_payload_t *payload; + FILE *inputfile = NULL; + struct stat statbuf; + + if (!filename) + return NULL; + + /* read from specified input file */ + if (stat(filename, &statbuf) < 0) { + coap_log(LOG_WARNING, "cannot stat file %s\n", filename); + return NULL; + } + + payload = coap_new_payload(statbuf.st_size); + if (!payload) + return NULL; + + inputfile = fopen(filename, "r"); + if ( !inputfile ) { + coap_log(LOG_WARNING, "cannot read file %s\n", filename); + coap_free(payload); + return NULL; + } + + payload->length = fread(payload->data, 1, statbuf.st_size, inputfile); + payload->media_type = 41; + + fclose(inputfile); + + return payload; +} + +static void +init_resources(coap_context_t *ctx) { + coap_resource_t *r; + coap_payload_t *test_payload; + + test_payload = coap_new_payload(200); + if (!test_payload) + coap_log(LOG_CRIT, "cannot allocate resource /test"); + else { + test_payload->length = 13; + memcpy(test_payload->data, "put data here", test_payload->length); + /* test_payload->media_type is 0 anyway */ + + r = coap_resource_init(coap_make_str_const("test"), 0); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_resource); + coap_register_request_handler(r, COAP_REQUEST_POST, hnd_post_test); + coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_test); + coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_test); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("test"), 0); + coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("core#b"), 0); +#if 0 + coap_add_attr(r, coap_make_str_const("obs"), NULL, 0); +#endif + coap_add_resource(ctx, r); + coap_resource_release_userdata_handler(ctx, coap_free_userdata); + coap_add_payload(r, test_payload); + } + + /* TD_COAP_BLOCK_01 + * TD_COAP_BLOCK_02 */ + test_payload = make_large("etsi_iot_01_largedata.txt"); + if (!test_payload) + coap_log(LOG_CRIT, "cannot allocate resource /large\n"); + else { + r = coap_resource_init(coap_make_str_const("large"), 0); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_resource); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("41"), 0); + coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("large"), 0); + coap_add_resource(ctx, r); + + test_payload->flags |= REQUIRE_ETAG; + + coap_add_payload(r, test_payload); + } + + /* For TD_COAP_CORE_12 */ + test_payload = coap_new_payload(20); + if (!test_payload) + coap_log(LOG_CRIT, "cannot allocate resource /seg1/seg2/seg3\n"); + else { + test_payload->length = 10; + memcpy(test_payload->data, "segsegseg!", test_payload->length); + /* test_payload->media_type is 0 anyway */ + + r = coap_resource_init(coap_make_str_const("seg1/seg2/seg3"), 0); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_resource); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_resource(ctx, r); + + coap_add_payload(r, test_payload); + } + + /* For TD_COAP_CORE_13 */ + r = coap_resource_init(coap_make_str_const("query"), 0); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_query); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_resource(ctx, r); + + /* For TD_COAP_CORE_16 */ + r = coap_resource_init(coap_make_str_const("separate"), 0); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_separate); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("seperate"), 0); + coap_add_resource(ctx, r); +} + +static void +usage( const char *program, const char *version) { + const char *p; + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf( stderr, "%s v%s -- ETSI CoAP plugtest server\n" + "(c) 2012 Olaf Bergmann \n\n" + "usage: %s [-A address] [-p port]\n\n" + "\t-A address\tinterface address to bind to\n" + "\t-p port\t\tlisten on specified port\n" + "\t-v num\t\tverbosity level (default: 3)\n", + program, version, program ); +} + +static coap_context_t * +get_context(const char *node, const char *port) { + coap_context_t *ctx = NULL; + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + + s = getaddrinfo(node, port, &hints, &result); + if ( s != 0 ) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) { + coap_address_t addr; + + if (rp->ai_addrlen <= (socklen_t)sizeof(addr.addr)) { + coap_address_init(&addr); + addr.size = rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + + ctx = coap_new_context(&addr); + if (ctx) { + /* TODO: output address:port for successful binding */ + goto finish; + } + } + } + + fprintf(stderr, "no context available for interface '%s'\n", node); + + finish: + freeaddrinfo(result); + return ctx; +} + +int +main(int argc, char **argv) { + coap_context_t *ctx; + int result; + char addr_str[NI_MAXHOST] = "::"; + char port_str[NI_MAXSERV] = "5683"; + int opt; + coap_log_t log_level = LOG_WARNING; + struct sigaction sa; + + while ((opt = getopt(argc, argv, "A:p:v:")) != -1) { + switch (opt) { + case 'A' : + strncpy(addr_str, optarg, NI_MAXHOST-1); + addr_str[NI_MAXHOST - 1] = '\0'; + break; + case 'p' : + strncpy(port_str, optarg, NI_MAXSERV-1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'v' : + log_level = strtol(optarg, NULL, 10); + break; + default: + usage( argv[0], LIBCOAP_PACKAGE_VERSION ); + exit( 1 ); + } + } + + coap_set_log_level(log_level); + + ctx = get_context(addr_str, port_str); + if (!ctx) + return -1; + + init_resources(ctx); + + memset (&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = handle_sigint; + sa.sa_flags = 0; + sigaction (SIGINT, &sa, NULL); + sigaction (SIGTERM, &sa, NULL); + /* So we do not exit on a SIGPIPE */ + sa.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &sa, NULL); + + while ( !quit ) { + result = coap_io_process( ctx, COAP_RESOURCE_CHECK_TIME * 1000 ); + if ( result >= 0 ) { + /* coap_check_resource_list( ctx ); */ + } + } + + coap_free_context( ctx ); + coap_cleanup(); + + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/examples/etsi_iot_01_largedata.txt b/examples/espidf-coap-server/components/libcoap/examples/etsi_iot_01_largedata.txt new file mode 100644 index 000000000..9f808f391 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/etsi_iot_01_largedata.txt @@ -0,0 +1,7 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet sapien ac leo bibendum suscipit at sed ipsum. Aliquam in mauris nec felis dictum lobortis a et erat. Pellentesque tempus urna vulputate purus faucibus ac pretium massa volutpat. Maecenas at tellus neque, quis elementum ante. Morbi molestie, elit placerat rhoncus faucibus, urna nunc accumsan diam, vel porta eros sem vel augue. Proin metus dolor, tristique a accumsan eget, suscipit vel ante. Suspendisse feugiat, nisl non viverra convallis, ante nibh congue lectus, sodales ultrices turpis massa sed elit. + +Praesent posuere laoreet nulla eu accumsan. Vestibulum consequat molestie erat, ut laoreet arcu mattis non. Maecenas viverra elementum mauris, vitae pretium elit ultrices sit amet. Sed sit amet elit sit amet dui imperdiet consequat. Donec viverra leo mollis lorem varius lacinia mollis nulla posuere. Phasellus felis odio, tempor et sodales non, facilisis fermentum eros. Duis dignissim massa at ante euismod vel laoreet mi tristique. Nulla libero dolor, pretium vitae vulputate eget, luctus at sapien. Praesent aliquam nisl ut urna pretium eu rhoncus ipsum eleifend. Sed lobortis vestibulum est eu eleifend. Sed vitae luctus erat. Sed vel dolor quam, tempor venenatis dolor. + +Vivamus a est a neque condimentum fermentum sed quis dui. Maecenas rhoncus imperdiet tortor, vitae viverra lectus ornare vulputate. Nam congue pulvinar faucibus. Vivamus id mauris at tortor porta volutpat. Donec non velit a tellus placerat iaculis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Suspendisse at felis ligula, vel euismod velit. Aliquam in odio urna. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ac risus ipsum. Donec vel purus risus, eu molestie nisi. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse consequat libero eu augue ornare volutpat mollis sed dui. Ut sed. diff --git a/examples/espidf-coap-server/components/libcoap/examples/etsi_testcases.sh b/examples/espidf-coap-server/components/libcoap/examples/etsi_testcases.sh new file mode 100644 index 000000000..63ba9a53d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/etsi_testcases.sh @@ -0,0 +1,765 @@ +#!/bin/bash + +function start_tcpdump { + testfunc=$1 + logfile=$LOGDIR/"$testfunc"_$(date +%s).dump + tcpdumpcmd="$tcpdump -i $INTERFACE host $SERVERADDRESS and (udp port $SERVERPORT or icmp) -s0 -n -w $logfile" + if [ $verbose ]; then + echo "$tcpdumpcmd" + $tcpdumpcmd& + else + $tcpdumpcmd 2>/dev/null& + fi + tcpdumppid=$! + # wait until tcpdump is ready to write + for t in {0..20} ; do + if [ ! -e $logfile ] ; then + sleep 0.1 + else + sleep 1 + if [ $verbose ]; then + echo "tcpdump started" + fi + break + fi + done +} + +function kill_tcpdump { + kill $tcpdumppid 2>/dev/null || ERROR=1 + if [ $ERROR ]; then + echo "tcpdump failed." + exit 1 + fi +} + +function start_coap_test { + if [ -z $1 ]; then + echo "missing argument for start_coap_test" + exit 1 + fi + start_tcpdump $1 + if [ $verbose ]; then + echo "client command: $COAP_CLIENT $clientopts $testaddress" + fi + echo -e "\nOutput of client:" + # for OBS + if [[ ! -z $2 ]]; then + testfifo=/tmp/tmpfifo$(date +%s) + mkfifo $testfifo + $COAP_CLIENT $clientopts "$testaddress" &> $testfifo & + clientpid=$! + ($timeoutcmd $clienttimeout cat $testfifo | if read -n 1 char; then echo "output: $char" ; fi) 2>/dev/null + # when client has written an output to fifo, kill client + kill $clientpid + rm $testfifo + if [[ $2 == "wait" ]] ; then + echo "Client killed. Waiting.." + sleep $longtimeout + fi + else + $COAP_CLIENT $clientopts "$testaddress" + fi + kill_tcpdump +} + + +## +# Perform GET (CON mode) on resource /test +# +# pre: resource /test exists and can handle GET with arbitrary payload +# +# client sends GET request with Type=0(CON) and Code=1(GET) +# +# check if sent request contains Type value indicating 0 and Code +# value indicating 1 +# +# check if server sends response containing Code = 69(2.05 Content), +# the same Message ID as that of previous request, content type option +# +# verify that server displays received information +# +function TD_COAP_CORE_01 { + clientopts="$callopts -m get" + testaddress=coap://$SERVERTUP/test + echo "perform GET (CON mode) on resource $testaddress" + start_coap_test $1 +} + +## +# Perform POST transaction (CON mode) on resource /test: create +# resource /test +# +# pre: resource /test doesn't exist but can be created on /test +# +# client sends POST with Type=0(CON), Code=2(POST), arbitrary payload, +# Content type option +# +# check: client sends request containing Type value indicating 0 and +# Code value indicating 2 +# +# verify: Server displays received information +# +# check: server sends response containing Code=69(2.01 Created), same +# message ID as that of the previous request, Content type option +# +# verify: client displays received information +# +function TD_COAP_CORE_02 { + # -t 0: content type text/plain + clientopts="$callopts -m post -t 0 -e sometext" + testaddress=coap://$SERVERTUP/test + echo "perform POST (CON) on resource $testaddress" + start_coap_test $1 +} + +## +# Perform PUT transaction (CON mode) on resource /test +# +# pre: resource /test exists which can handle PUT +# +# Client sends a PUT request with Type=0(CON), Code=3(PUT), arbitrary +# payload, content type option +# +# check: sent request contains Type value indicating 0 and Code value +# indicating 3 +# +# verify: server displays received information +# +# check: Server sends response containing Code=68(2.04 Changed), same +# Message ID as that of the previous request +# +# verify: client displays received response +# +function TD_COAP_CORE_03 { + clientopts="$callopts -m put -t 0 -e sometext" + testaddress=coap://$SERVERTUP/test + echo "perform PUT (CON) on resource $testaddress" + start_coap_test $1 +} + +## +# Perform DELETE transaction (CON mode) on resource /test +# +# pre: resource /test exists which can handle DELETE +# +# Client sends a DELETE request with Type=0(CON), Code=4(DELETE) +# +# check: sent request contains Type value indicating 0 and Code value +# indicating 4 +# +# check: Server sends response containing Code=66(2.02 Deleted), same +# Message ID as that of the previous request +# +# verify: client displays received response +# +function TD_COAP_CORE_04 { + clientopts="$callopts -m delete" + testaddress=coap://$SERVERTUP/test + echo "perform DELETE (CON) on resource $testaddress" + start_coap_test $1 +} + +## +# Perform GET transaction (NON mode) on resource /test +# +# pre: resource /test exits which can handle GET +# +# Client sends a GET request with Type=1(NON), Code=1(GET) +# +# check: sent request contains Type value indicating 1 and Code value +# indicating 1 +# +# check: Server sends response containing Type=1(NON), Code=69(2.05 +# Content), content type option +# +# verify: client displays received response +# +function TD_COAP_CORE_05 { + # -N: send non-confirmable message + clientopts="$callopts -m get -N" + testaddress=coap://$SERVERTUP/test + echo "perform GET (NON mode) on resource $testaddress" + start_coap_test $1 +} + +## +# Perform POST transaction (NON mode), create resource on /test +# +# pre: resource on /test doesn't exist but can be created +# +# Client sends a POST request with Type=1(NON), Code=2(POST), +# arbitrary payload, content type option +# +# check: sent request contains Type value indicating 1 and Code value +# indicating 2 +# +# verify: Server displays the received information +# +# check: Server sends response containing Type=1(NON), Code=65(2.01 +# Created) +# +# verify: client displays received response +# +function TD_COAP_CORE_06 { + clientopts="$callopts -m post -t 0 -e sometext -N" + testaddress=coap://$SERVERTUP/test + echo "perform POST (NON) on resource $testaddress" + start_coap_test $1 +} + +## +# Perform PUT transaction (NON mode) on resource /test +# +# pre: /test exists and can handle PUT +# +# Client sends a PUT request with Type=1(NON), Code=3(PUT), +# arbitrary payload, content type option +# +# check: sent request contains Type value indicating 1 and Code value +# indicating 3 +# +# verify: Server displays the received information +# +# check: Server sends response containing Type=1(NON), Code=68(2.04 +# Changed) +# +# verify: client displays received response +# +function TD_COAP_CORE_07 { + clientopts="$callopts -m put -t 0 -e sometext -N" + testaddress=coap://$SERVERTUP/test + echo "perform PUT (NON) on resource $testaddress" + start_coap_test $1 +} + +## +# Perform DELETE transaction (NON mode) on resource /test +# +# pre: /test exists and can handle DELETE +# +# Client sends a DELETE request with Type=1(NON), Code=4(DELETE) +# +# check: sent request contains Type value indicating 1 and Code value +# indicating 4 +# +# check: Server sends response containing Type=1(NON), Code=66(2.02 +# Deleted) +# +# verify: client displays received response +# +function TD_COAP_CORE_08 { + clientopts="$callopts -m delete -N" + testaddress=coap://$SERVERTUP/test + echo "perform DELETE (NON) on resource $testaddress" + start_coap_test $1 +} + +## +# Perform GET transaction with a separate response on resource /separate +# +# pre: resource /separate exists which cannot be served immediately and which +# cannot be acknowledged in a piggy-backed way +# +# Client sends a confirmable GET request to server's resource +# +# check: sent request contains Type=0(CON), Code=1(GET), client +# generated Message ID +# +# check: Server sends response containing Type=2(ACK), message ID same +# as the request, empty Payload +# +# check: Server sends response containing Type=0(CON), Code=69(2.05 +# content), Payload=Content of the requested resource, Content type option +# +# check: Client sends response containing Type=2(ACK), message ID same +# as the response, empty Payload +# +# verify: client displays received response +# +function TD_COAP_CORE_09 { + clientopts="$callopts -m get" + testaddress=coap://$SERVERTUP/separate + echo "perform GET (CON) on resource $testaddress which cannot be served immediately" + start_coap_test $1 +} + +## +# Perform GET transaction with Token on resource /test +# +# pre: resource /test exists which can handle GET requests +# +# Client sends a confirmable GET request to server's resource +# including Token option +# +# check: sent request contains Type=0(CON) and Code=1(GET), client +# generated Token value, length of the token which should be between 1 +# to 8 B, Option Type=Token +# +# check: Server sends response containing Code=69(2.05 content), +# length of the token should be between 1 to 8 B, Token value same as +# the requested, Payload=Content of the requested resource, Content +# type option +# +# verify: client displays received response +# +function TD_COAP_CORE_10 { + clientopts="$callopts -m get -T sometok" + testaddress=coap://$SERVERTUP/test + echo "perform GET (CON) on resource $testaddress with Token" + start_coap_test $1 +} + +## +# Perform GET transaction without Token on resource /test +# +# pre: resource /test exists which can handle GET requests +# +# Client sends a confirmable GET request to server's resource +# not containing Token option +# +# check: sent request contains Type=0(CON) and Code=1(GET), no Token +# option +# +# check: Server sends response containing Code=69(2.05 content), no +# Token option, Payload=Content of the requested resource, Content +# type option +# +# verify: client displays received response +# +function TD_COAP_CORE_11 { + clientopts="$callopts -m get" + testaddress=coap://$SERVERTUP/test + echo "perform GET (CON mode) without Token on resource $testaddress" + start_coap_test $1 +} + +## +# Perform GET transaction to resource /seg1/seg2/seg3 +# +# pre: resource /seg1/seg2/seg3 exists on server +# +# Client sends a confirmable GET request to server's resource +# +# check: sent request contains Type=0(CON) and Code=1(GET), Option +# type=URI-Path (one for each path segment) +# +# check: Server sends response containing Code=69(2.05 content), +# Payload=Content of the requested resource, Content type option +# +# verify: client displays received response +# +function TD_COAP_CORE_12 { + clientopts="$callopts -m get" + testaddress=coap://$SERVERTUP/seg1/seg2/seg3 + echo "perform GET (CON mode) on resource $testaddress" + start_coap_test $1 +} + +## +# Perform GET transaction to resource /query +# +# pre: resource /query exists on server +# +# Client sends a confirmable GET request with three Query parameters +# (e.g. ?first=1&second=2&third=3) to server's resource +# +# check: sent request contains Type=0(CON) and Code=1(GET), Option +# type=URI-Query (More than one query parameter) +# +# check: Server sends response containing Type=0/2(Con/ACK), +# Code=69(2.05 content), Payload=Content of the requested resource, +# Content type option +# +# verify: client displays received response +# +function TD_COAP_CORE_13 { + clientopts="$callopts -m get" + testaddress=coap://$SERVERTUP/query + query="?first=1&second=2&third=3" + echo -e "perform GET (CON mode) on resource $testaddress with query $query" + testaddress=$testaddress$query + start_coap_test $1 +} + +## +# Perform GET transaction to resource /test in lossy context +# +# pre: gateway is introduced and configured to produce packet loss, +# resource /test exists on server +# +# Configuration=CoAP_CFG_02 +# +# observe: One dropped request, one dropped request ACK, one dropped +# response, one dropped response ACK and its retransmission, test +# sequence should be executed several times +# +# Client sends a confirmable GET request to server's resource +# +# check: sent request contains Type=0(CON) and Code=1(GET), Client +# generated Message ID +# +# check: Server sends response containing Type=2(ACK), Code=69(2.05 +# content), Payload=Content of the requested resource, Content type +# option +# +# verify: client displays received response +# +function TD_COAP_CORE_14 { + clientopts="$callopts -m get" + #FIXME: address for lossy context? + testaddress=coap://$SERVERTUP/test + echo "perform GET (CON mode) on resource $testaddress in lossy context" + start_coap_test $1 +} + +## +# Perform GET transaction to resource /separate in lossy context +# +# pre: gateway is introduced and configured to produce packet loss, +# resource /separate exists which cannot be served immediately and +# which cannot be acknowledged in a piggy-backed way +# +# Configuration=CoAP_CFG_02 +# +# observe: One dropped request, one dropped request ACK, one dropped +# response, one dropped response ACK and its retransmission, test +# sequence should be executed several times +# +# Client sends a confirmable GET request to server's resource +# +# check: sent request contains Type=0(CON) and Code=1(GET), Client +# generated Message ID +# +# check: server sends response containing Type=2(ACK), Message ID same +# as the request, empty Payload +# +# check: Server sends response containing Type=0(CON), Code=69(2.05 +# content), Payload=Content of the requested resource, Content type +# option +# +# check: Client sends response containing Type=2(ACK), message ID same +# as the response, empty Payload +# +# verify: client displays received response +# +function TD_COAP_CORE_15 { + clientopts="$callopts -m get" + #FIXME: address for lossy context? + testaddress=coap://$SERVERTUP/separate + echo "perform GET (CON mode) on resource $testaddress in lossy context" + start_coap_test $1 +} + +### LINK ### + +## +# Access to well-known interface for resource discovery +# +# Pre: client supports CoRE Link Format, server supports +# /.well-known/core resource and the CoRE Link Format +# +# Client retrieves Server's list of resource +# +# check: client sends GET request for /.well-known/core resource +# +# check: server sends response containing content-type option +# indicating 40 (application/link-format), payload indicating all the +# links available on Server +# +# client displays the list of resources available on Server +# +function TD_COAP_LINK_01 { + clientopts="$callopts -m get" + testaddress=coap://$SERVERTUP/.well-known/core + echo "retrieve server's list of resource" + start_tcpdump $1 + if [ $verbose ]; then + echo "client command: $COAP_CLIENT $clientopts $testaddress" + fi + clientoutput=$($COAP_CLIENT $clientopts "$testaddress") + if [[ ! $(echo $clientoutput | grep rt) ]] ; then + echo "no resource with attribute rt found on server" + else + rt="${clientoutput##*rt=}" + rt="${rt%%;*}" + fi + echo -e "\nOutput of client:" + echo -e $clientoutput + echo + kill_tcpdump +} + +## +# Use filtered requests for limiting discovery results +# +# Pre: client supports CoRE Link Format, server supports CoRE Link +# Format and offers different types of resources (Type 1, Type 2 +# (extracted from /.well-knwon/core resource +# +# Client retrieves Server's list of resource of a specific Type 1 +# +# check: client sends GET request for /.well-known/core resource +# containing URI-Query indicating "rt=Type1" +# +# check: server sends response containing content-type option +# indicating 40 (application/link-format), payload indicating only the +# links of type Type1 available on server +# +# client displays the list of resources of type Type1 available on Server +# +function TD_COAP_LINK_02 { + clientopts="$callopts -m get" + echo "retrieve server's list of resource for appropriate type" + if [[ ! -z $rt ]]; then + testaddress="coap://$SERVERTUP/.well-known/core?rt=$rt" + else + echo "no appropriate resource found. Skipping test" + return + fi + start_coap_test $1 +} + +### BLOCK ### + +## +# Perform GET blockwise transfer for large resource (early negotiation) +# +# pre: Client supports Block transfers, Server supports Block +# transfers, Server offers a large resource /large, client knows +# /large requires block transfer +# +# Client is requested to retrieve resource /large +# +# check: client sends a GET request containing Block2 option indicating block +# number 0 and desired block size +# +# check: Each request contains Block2 option indicating block number +# of the next block and size of the last received block +# +# check: server sends further responses containing Block2 option +# indicating block number and size +# +# verify: client displays received response +# +function TD_COAP_BLOCK_01 { + clientopts="$callopts -m get -b 1024" + testaddress=coap://$SERVERTUP/large + echo "perform GET on large resource $testaddress (early negotiation)" + start_coap_test $1 +} + +## +# Perform GET blockwise transfer for large resource (late negotiation) +# +# pre: Client supports Block transfers, Server supports Block +# transfers, Server offers a large resource /large, client does not +# know /large requires block transfer +# +# Client is requested to retrieve resource /large +# +# check: client sends a GET request not containing Block2 option +# +# check: server sends response containing Block2 option indicating +# block number and size +# +# check: Each request contains Block2 option indicating block number +# of the next block and size of the last received block or the desired +# size of the next block +# +# check: server sends further responses containing Block2 option +# indicating block number and size +# +# verify: client displays received response +# +function TD_COAP_BLOCK_02 { + clientopts="$callopts -m get" + testaddress=coap://$SERVERTUP/large + echo "perform GET blockwise transfer for large resource (late negotiation) on resource $testaddress" + start_coap_test $1 stop +} + +## +# Perform PUT blockwise transfer for large resource +# +# pre: Client supports Block transfers, Server supports Block +# transfers, Server offers a large updatable resource /large-update +# +# Client is requested to retrieve resource /large-update on server +# +# check: client sends a PUT request containing Block1 option +# indicating block number 0 and block size +# +# check: client sends further request containing Block1 option +# indicating block number and size +# +# verify: server indicates presence of the complete updated resource +# /large-update +# +function TD_COAP_BLOCK_03 { + clientopts="$callopts -m put -b 1024" + testaddress=coap://$SERVERTUP/large-update + echo "perform PUT on large resource $testaddress" + start_coap_test $1 +} + +## +# Perform POST blockwise transfer for large resource +# +# pre: Client supports Block transfers, Server supports Block +# transfers, Server accepts creation of new resources on /large-create +# +# Client is requested to create a new resource on server +# +# check: client sends a POST request containing Block1 option +# indicating block number 0 and block size +# +# check: client sends further requests containing Block1 option +# indicating block number and size +# +# verify: server indicates presence of the complete new resource +# +function TD_COAP_BLOCK_04 { + clientopts="$callopts -m post -b 1024" + testaddress=coap://$SERVERTUP/large-create + echo "perform POST on large resource $testaddress" + start_coap_test $1 +} + +# # OBS + +## +# Handle observe option +# +# pre: client supports Observe option, server supports observe option, +# server offers an observable resource /obs which changes periodically +# (e.g. every 5s.) +# +# client is requested to observe resource /obs on server +# +# check: client sends a GET request containing observe option +# +# verify: client displays the received information +# +# check: server sends response containing observe option indicating +# increasing values, as resource changes +# +# verify: client displays the updated information +# +function TD_COAP_OBS_01 { + # we need some time to verify the correct behavior + clientopts="$callopts -s 0" #"-v 5 -B $longtimeout -s 0" + testaddress=coap://$SERVERTUP/obs + echo "observe resource $testaddress" + start_coap_test $1 +} + +## +# Stop resource observation +# +# pre: client supports Observe option, server supports observe option, +# server offers an observable resource /obs which changes periodically +# (e.g. every 5s.), client is observing /obs on server +# +# client is requested to stop observing resource /obs on server +# +# check: client sends a GET request not containing observe option +# +# verify: client displays the received information +# +# check: server does not send further response +# +# verify: client does not display the updated information +# +# function TD_COAP_OBS_02 { +# #FIXME: client does not support stopping yet + # we need some time to verify the correct behavior +# clientopts="-v 5 -B $longtimeout -s 1" +# testaddress=coap://$SERVERTUP/obs +# echo "stop observing resource $testaddress" +# start_coap_test $1 +# } + +## +# client detection of deregistration (Max-Age) +# +# pre: client supports Observe option, server supports observe option, +# server offers an observable resource /obs which changes periodically +# (e.g. every 5s.), client is observing /obs on server +# +# Server is rebooted +# +# check: Server does not send notifications +# +# verify: Client does not display updated information +# +# verify: After Max-Age expiration, client sends a new GET with observe +# option for Server's observable resource +# +# check: Sent request contains Observe option indicating 0 +# +# check: Server sends response containing Observe option +# +# verify: client displays the received information +# +# check: Server sends response containing Observe option indicating +# increasing values, as resource changes +# +# verify: Client displays the updated information +# +function TD_COAP_OBS_03 { + clientopts="$callopts -s 0"#"-v5 -B $longtimeout -s 0" + testaddress=coap://$SERVERTUP/obs + echo "client detection of deregistration (Max-Age)" + start_coap_test $1 +} + +## +# Server detection of deregistration (client OFF) +# +# pre: client supports Observe option, server supports observe option, +# server offers an observable resource /obs which changes periodically +# (e.g. every 5s.), client is observing /obs on server +# +# Client is switched off +# +# check: Server’s confirmable responses are not acknowledged +# +# verify: After some delay, Server does not send further responses +# +function TD_COAP_OBS_04 { + clientopts="$callopts -s 0" +#"-v 5 -B $longtimeout -s 0" + testaddress=coap://$SERVERTUP/obs + echo "server detection of deregistration (client off)" + start_coap_test $1 wait +} + +## +# Server detection of deregistration (explicit RST) +# +# pre: client supports Observe option, server supports observe option, +# server offers an observable resource /obs which changes periodically +# (e.g. every 5s.), client is observing /obs on server +# +# Client is rebooted +# +# check: Server sends response containing Observe option +# +# verify: Client discards response and does not display information +# +# check: Client sends RST to Server +# +# check: Server does not send further response +# +function TD_COAP_OBS_05 { + clientopts="$callopts -s 0 -p $CLIENTPORT" +#"-v 5 -B $longtimeout -p $CLIENTPORT -s 0" + testaddress=coap://$SERVERTUP/obs + echo "server detection of deregistration (explicit RST)" + start_coap_test $1 stop + clientopts="$callopts -p $CLIENTPORT -s 0 -N" +#"-v 5 -B $clienttimeout -p $CLIENTPORT -s 0 -N" + testaddress=coap://[::1]/obs + start_coap_test $1 +} diff --git a/examples/espidf-coap-server/components/libcoap/examples/getopt.c b/examples/espidf-coap-server/components/libcoap/examples/getopt.c new file mode 100644 index 000000000..6e09eeb6b --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/getopt.c @@ -0,0 +1,66 @@ +/* + * This file was copied from the following newsgroup posting: + * + * Newsgroups: mod.std.unix + * Subject: public domain AT&T getopt source + * Date: 3 Nov 85 19:34:15 GMT + * + * Here's something you've all been waiting for: the AT&T public domain + * source for getopt(3). It is the code which was given out at the 1985 + * UNIFORUM conference in Dallas. I obtained it by electronic mail + * directly from AT&T. The people there assure me that it is indeed + * in the public domain. + */ + +#include +#include + +static int opterr = 1; +static int optind = 1; +static int optopt; +static char *optarg; + +static int getopt(int argc, char *argv[], char *opts) +{ + static int sp = 1; + int c; + char *cp; + + if (sp == 1) { + if (optind >= argc || + argv[optind][0] != '-' || argv[optind][1] == '\0') + return EOF; + else if (!strcmp(argv[optind], "--")) { + optind++; + return EOF; + } + } + optopt = c = argv[optind][sp]; + if (c == ':' || !(cp = strchr(opts, c))) { + fprintf(stderr, ": illegal option -- %c\n", c); + if (argv[optind][++sp] == '\0') { + optind++; + sp = 1; + } + return '?'; + } + if (*++cp == ':') { + if (argv[optind][sp+1] != '\0') + optarg = &argv[optind++][sp+1]; + else if(++optind >= argc) { + fprintf(stderr, ": option requires an argument -- %c\n", c); + sp = 1; + return '?'; + } else + optarg = argv[optind++]; + sp = 1; + } else { + if (argv[optind][++sp] == '\0') { + sp = 1; + optind++; + } + optarg = NULL; + } + + return c; +} diff --git a/examples/espidf-coap-server/components/libcoap/examples/lwip/.gitignore b/examples/espidf-coap-server/components/libcoap/examples/lwip/.gitignore new file mode 100644 index 000000000..7905765c5 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/lwip/.gitignore @@ -0,0 +1,7 @@ +# not going for submodules here to keep things easy +lwip +lwip-contrib + +# never objects, and not the resulting binary +*.o +server diff --git a/examples/espidf-coap-server/components/libcoap/examples/lwip/README b/examples/espidf-coap-server/components/libcoap/examples/lwip/README new file mode 100644 index 000000000..c53695f78 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/lwip/README @@ -0,0 +1,30 @@ +Example of libcoap running on lwIP +================================== + +To run the example, do + + $ make + $ sudo ./server + +(and in a second terminal) + + $ sudo ip a a dev tap0 192.168.113.1/24 + +and query `coap://192.168.113.2/time?ticks` with any coap tool, +or query `coap://[aaaa::1000]/.well-known/core` + +This will + +* download lwip and lwip-contrib from the upstream git sources +* build the server application +* run the server application, creating a virtual network device tap0 (unless + that exists) +* configure your network interface to make the server accessible. + +* return the appropriate response from the server to the client. + +The server creates a resource for 'time' with a query 'ticks'. This is +reported for `.well-known/core`. The work flow for adding more resources does +not differ from regular libcoap usage. If you seem to run out of memory +creating the resources, tweak the number of pre-allocated resources +in `include/coap/lwippools.h`. diff --git a/examples/espidf-coap-server/components/libcoap/examples/lwip/lwipopts.h b/examples/espidf-coap-server/components/libcoap/examples/lwip/lwipopts.h new file mode 100644 index 000000000..2a86b8550 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/lwip/lwipopts.h @@ -0,0 +1,37 @@ +/* + * lwipopts.h -- LwIP example + * + * Copyright (C) 2013-2016 Christian Amsüss + * Copyright (C) 2018 John Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +typedef unsigned int sys_prot_t; + +#define NO_SYS 1 +#define LWIP_SOCKET (NO_SYS==0) +#define LWIP_NETCONN (NO_SYS==0) +#define LWIP_NETIF_API (NO_SYS==0) + +#define LWIP_IPV6 1 +#define LWIP_IPV6_REASS 0 + +#ifndef LWIP_RAND +#define LWIP_RAND() ((u32_t)rand()) +#endif + +#ifndef netif_get_index +#define netif_get_index(netif) ((u8_t)((netif)->num + 1)) +#endif + +#if NO_SYS +#include +extern pthread_mutex_t lwprot_mutex; +extern pthread_t lwprot_thread; +extern int lwprot_count; +#endif +#define MEMP_USE_CUSTOM_POOLS 1 diff --git a/examples/espidf-coap-server/components/libcoap/examples/lwip/server-coap.c b/examples/espidf-coap-server/components/libcoap/examples/lwip/server-coap.c new file mode 100644 index 000000000..2ffa612d8 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/lwip/server-coap.c @@ -0,0 +1,147 @@ +/* + * server-coap.h -- LwIP example + * + * Copyright (C) 2013-2016 Christian Amsüss + * Copyright (C) 2018-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#include "coap_config.h" +#include + +coap_context_t *main_coap_context; + +static coap_time_t clock_offset; +/* changeable clock base (see handle_put_time()) */ +static coap_time_t my_clock_base = 0; +static coap_resource_t *time_resource = NULL; /* just for testing */ + +#ifndef min +# define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +void +hnd_get_time(coap_resource_t *resource, coap_session_t *session, + const coap_pdu_t *request, const coap_string_t *query, + coap_pdu_t *response) { + unsigned char buf[40]; + size_t len; + coap_tick_t now; + coap_tick_t t; + + /* FIXME: return time, e.g. in human-readable by default and ticks + * when query ?ticks is given. */ + + /* if my_clock_base was deleted, we pretend to have no such resource */ + response->code = + my_clock_base ? COAP_RESPONSE_CODE(205) : COAP_RESPONSE_CODE(404); + + if (my_clock_base) + coap_add_option(response, COAP_OPTION_CONTENT_FORMAT, + coap_encode_var_safe(buf, sizeof(buf), + COAP_MEDIATYPE_TEXT_PLAIN), + buf); + + coap_add_option(response, COAP_OPTION_MAXAGE, + coap_encode_var_safe(buf, sizeof(buf), 0x01), buf); + + if (my_clock_base) { + + /* calculate current time */ + coap_ticks(&t); + now = my_clock_base + (t / COAP_TICKS_PER_SECOND); + + + if (query != NULL + && coap_string_equal(query, coap_make_str_const("ticks"))) { + /* output ticks */ + len = snprintf((char *)buf, sizeof(buf), "%u", (unsigned int)now); + coap_add_data(response, len, buf); + } + } +} + +void +init_coap_resources(coap_context_t *ctx) { + coap_resource_t *r; +#if 0 + r = coap_resource_init(NULL, 0, 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"General Info\""), 0); + coap_add_resource(ctx, r); +#endif + /* store clock base to use in /time */ + my_clock_base = clock_offset; + + r = coap_resource_init(coap_make_str_const("time"), 0); + if (!r) + goto error; + + coap_resource_set_get_observable(r, 1); + time_resource = r; + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time); +#if 0 + coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time); + coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time); +#endif + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + /* coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"Internal Clock\""), 0); */ + coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"ticks\""), 0); + coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""), 0); + + coap_add_resource(ctx, r); +#if 0 +#ifndef WITHOUT_ASYNC + r = coap_resource_init(coap_make_str_const("async"), 0); + coap_register_handler(r, COAP_REQUEST_GET, hnd_get_async); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_resource(ctx, r); +#endif /* WITHOUT_ASYNC */ +#endif + + return; + error: + coap_log(LOG_CRIT, "cannot create resource\n"); +} + +void server_coap_init(void) +{ + coap_address_t listenaddress; + + coap_address_init(&listenaddress); + + /* looks like a server address, but is used as end point for clients too */ + listenaddress.addr = *(IP_ANY_TYPE); + listenaddress.port = COAP_DEFAULT_PORT; + + coap_set_log_level(LOG_DEBUG); + main_coap_context = coap_new_context(&listenaddress); + + LWIP_ASSERT("Failed to initialize context", main_coap_context != NULL); + clock_offset = 1; /* Need a non-zero value */ + init_coap_resources(main_coap_context); +} + +void server_coap_poll(void) +{ + static coap_time_t last_time = 0; + coap_tick_t ticks_now; + coap_time_t time_now; + + coap_ticks(&ticks_now); + time_now = coap_ticks_to_rt(ticks_now); + + if (last_time != time_now) { + /* This takes place once a second */ + last_time = time_now; + coap_resource_notify_observers(time_resource, NULL); + } + coap_check_notify(main_coap_context); +} diff --git a/examples/espidf-coap-server/components/libcoap/examples/lwip/server-coap.h b/examples/espidf-coap-server/components/libcoap/examples/lwip/server-coap.h new file mode 100644 index 000000000..e45977553 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/lwip/server-coap.h @@ -0,0 +1,17 @@ +/* + * server-coap.h -- LwIP example + * + * Copyright (C) 2013-2016 Christian Amsüss + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#include "coap_config.h" +#include + +void server_coap_init(void); +/* call this when you think that resources could be dirty */ +void server_coap_poll(void); diff --git a/examples/espidf-coap-server/components/libcoap/examples/lwip/server.c b/examples/espidf-coap-server/components/libcoap/examples/lwip/server.c new file mode 100644 index 000000000..bbfb13379 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/lwip/server.c @@ -0,0 +1,91 @@ +/* + * Demo for libcoap on lwIP + * + * partially copied from lwip-contrib/ports/unix/proj/minimal/main.c + * + * + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. + * + * Author: Adam Dunkels + * RT timer modifications by Christiaan Simons + * lwip adaptions: chrysn + * also, https://savannah.nongnu.org/bugs/?40245 was applied */ + +#include "server-coap.h" + +#include +#include + +#include +#include + +#include + +static ip4_addr_t ipaddr, netmask, gw; + +int +main(int argc, char **argv) +{ + struct netif netif; + + /* startup defaults (may be overridden by one or more opts). this is + * hard-coded v4 even in presence of v6, which does auto-discovery and + * should thus wind up with an address of fe80::12:34ff:fe56:78ab%tap0 + * */ + IP4_ADDR(&gw, 192,168,113,1); + IP4_ADDR(&ipaddr, 192,168,113,2); + IP4_ADDR(&netmask, 255,255,255,0); + + lwip_init(); + + printf("TCP/IP initialized.\n"); + + netif_add(&netif, &ipaddr, &netmask, &gw, NULL, tapif_init, ethernet_input); + netif.flags |= NETIF_FLAG_ETHARP; + netif_set_default(&netif); + netif_set_up(&netif); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&netif, 1); +#endif + + /* start applications here */ + + server_coap_init(); + + printf("Applications started.\n"); + + + while (1) { + /* poll netif, pass packet to lwIP */ + tapif_select(&netif); + + sys_check_timeouts(); + + server_coap_poll(); + } + + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/examples/share.libcoap.examples.Makefile b/examples/espidf-coap-server/components/libcoap/examples/share.libcoap.examples.Makefile new file mode 100644 index 000000000..4801c9539 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/share.libcoap.examples.Makefile @@ -0,0 +1,43 @@ +# Makefile for libcoap standalone examples +# +# Copyright (C) 2021 Olaf Bergmann +# +# This file is part of the CoAP C library libcoap. Please see README and +# COPYING for terms of use. + +# Set external variable LIBCOAP if you need a specific libcoap library. +# E.g. libcoap-3-openssl, libcoap-3-gnutls, libcoap-3-mbedtls or libcoap-3-notls +# +LIBCOAP?=libcoap-3 + +WARNING_CFLAGS= \ + -pedantic \ + -Wall \ + -Wcast-qual \ + -Wextra \ + -Wformat-security \ + -Winline \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wnested-externs \ + -Wpointer-arith \ + -Wshadow \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wswitch-enum \ + -Wunused \ + -Wwrite-strings + +pkgconfig=$(shell pkg-config $(1) $(2)) + +CPPFLAGS=-D_GNU_SOURCE $(WARNING_CFLAGS) $(call pkgconfig,--cflags,$(LIBCOAP)) +CFLAGS=-std=c99 +LDLIBS=$(call pkgconfig,--libs-only-l,$(LIBCOAP)) +libdirs=$(call pkgconfig,--libs-only-L,$(LIBCOAP)) +rpath=$(shell echo "$(libdirs)" | sed -e 's/^-L/-Wl,--rpath /') +LDFLAGS=$(libdirs) $(rpath) + +all: coap-client coap-server + +clean: + rm -f *.o coap-client coap-server diff --git a/examples/espidf-coap-server/components/libcoap/examples/share.libcoap.examples.README b/examples/espidf-coap-server/components/libcoap/examples/share.libcoap.examples.README new file mode 100644 index 000000000..f4b586cc2 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/share.libcoap.examples.README @@ -0,0 +1,9 @@ +This directory contains some example libcoap code for a client or server which +can easily be modified as per your requirements. + +The provided code is the same as used to build the installed binaries +coap-client and coap-server. + +Simply 'cd' into this directory and then run 'make' to build the executables. + + diff --git a/examples/espidf-coap-server/components/libcoap/examples/tiny.c b/examples/espidf-coap-server/components/libcoap/examples/tiny.c new file mode 100644 index 000000000..e06388c8f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/examples/tiny.c @@ -0,0 +1,183 @@ +/* tiny -- tiny sender + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define Nn 8 /* duplicate definition of N if built on sky motes */ +#define ENCODE_HEADER_SIZE 4 +#define HIBIT (1 << (Nn - 1)) +#define EMASK ((1 << ENCODE_HEADER_SIZE) - 1) +#define MMASK ((1 << Nn) - 1 - EMASK) +#define MAX_VALUE ( (1 << Nn) - (1 << ENCODE_HEADER_SIZE) ) * (1 << ((1 << ENCODE_HEADER_SIZE) - 1)) + +#define COAP_PSEUDOFP_DECODE_8_4(r) (r < HIBIT ? r : (r & MMASK) << (r & EMASK)) + +/* ls and s must be integer variables */ +/* #define COAP_PSEUDOFP_ENCODE_8_4_DOWN(v,ls) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (v >> ls) & MMASK) + ls) */ +COAP_STATIC_INLINE unsigned char +COAP_PSEUDOFP_ENCODE_8_4_DOWN(unsigned int v, int *ls) { + if (v < HIBIT) return v; + *ls = coap_fls(v) - Nn; + return ((v >> *ls) & MMASK) + *ls; +} +#define COAP_PSEUDOFP_ENCODE_8_4_UP(v,ls,s) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (s = (((v + ((1<> ls) & MMASK)), s == 0 ? HIBIT + ls + 1 : s + ls)) + +static int quit = 0; + +/* SIGINT handler: set quit to 1 for graceful termination */ +static void +handle_sigint(int signum COAP_UNUSED) { + quit = 1; +} + +static coap_pdu_t * +make_pdu( coap_session_t *session, unsigned int value ) { + coap_pdu_t *pdu; + unsigned char enc; + static unsigned char buf[20]; + int len, ls; + + if (!(pdu = coap_pdu_init(COAP_MESSAGE_NON, COAP_REQUEST_CODE_POST, + coap_new_message_id(session), COAP_DEFAULT_MTU))) + return NULL; + + enc = COAP_PSEUDOFP_ENCODE_8_4_DOWN(value, &ls); + + len = sprintf((char *)buf, "%c%u", enc, COAP_PSEUDOFP_DECODE_8_4(enc)); + coap_add_data( pdu, len, buf ); + + return pdu; +} + +static void +usage( const char *program ) { + const char *p; + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf( stderr, "%s -- tiny fake sensor\n" + "(c) 2010 Olaf Bergmann \n\n" + "usage: %s [group address]\n" + "\n\nSends some fake sensor values to specified multicast group\n", + program, program ); +} + +static coap_session_t * +get_session(coap_context_t *ctx, const char *group) { + int s; + struct addrinfo hints; + struct addrinfo *result, *rp; + coap_session_t *session; + int hops = 16; + + if (!ctx) + return NULL; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL; + + s = getaddrinfo(group, NULL, &hints, &result); + if ( s != 0 ) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + return NULL; + } + + /* iterate through results until success */ + for (rp = result; rp != NULL; rp = rp->ai_next) { + coap_address_t addr; + coap_address_init(&addr); + addr.size = rp->ai_addrlen; + memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); + + session = coap_new_client_session(ctx, NULL, &addr, COAP_PROTO_UDP); + if (!session) + continue; + + if (IN6_IS_ADDR_MULTICAST(&addr.addr.sin6.sin6_addr) ) { + /* set socket options for multicast */ + if (!coap_mcast_set_hops(session, hops)) + perror("setsockopt: IPV6_MULTICAST_HOPS"); + + } + freeaddrinfo(result); + return session; + } + + fprintf(stderr, "no session available for group '%s'\n", group); + freeaddrinfo(result); + return NULL; +} + +int +main(int argc, char **argv) { + struct timeval tv; + coap_pdu_t *pdu; + coap_session_t *session; + struct sigaction sa; + coap_context_t *ctx; + + if ( argc > 1 && strncmp(argv[1], "-h", 2) == 0 ) { + usage( argv[0] ); + exit( 1 ); + } + + ctx = coap_new_context(NULL); + if (!ctx) + return -1; + + session = get_session(ctx, argc > 1 ? argv[1] : "::1"); + + if ( !session ) + return -1; + + memset (&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = handle_sigint; + sa.sa_flags = 0; + sigaction (SIGINT, &sa, NULL); + sigaction (SIGTERM, &sa, NULL); + /* So we do not exit on a SIGPIPE */ + sa.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &sa, NULL); + + while ( !quit ) { + + if (! (pdu = make_pdu( session, rand() & 0xfff ) ) ) + break; + + coap_send(session, pdu); + + tv.tv_sec = 5; tv.tv_usec = 0; + + select( 0, 0, 0, 0, &tv ); + + } + + coap_free_context(ctx); + + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ABOUT.md b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ABOUT.md new file mode 100644 index 000000000..894ab361a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ABOUT.md @@ -0,0 +1,60 @@ +# About This Content + +2015-12-18 + +# License + +The Eclipse Foundation makes available all content in this plug-in +("Content"). Unless otherwise indicated below, the Content is provided +to you under the terms and conditions of the Eclipse Public License +Version 1.0 ("EPL") and Eclipse Distribution License Version 1.0 +(“EDL”). A copy of the EPL is available at +http://www.eclipse.org/legal/epl-v10.html and a copy of the EDL is +available at http://www.eclipse.org/org/documents/edl-v10.php. For +purposes of the EPL, "Program" will mean the Content. + +If you did not receive this Content directly from the Eclipse +Foundation, the Content is being redistributed by another party +("Redistributor") and different terms and conditions may apply to your +use of any object code in the Content. Check the Redistributor’s +license that was provided with the Content. If no such license exists, +contact the Redistributor. Unless otherwise indicated below, the terms +and conditions of the EPL and EDL still apply to any source code in +the Content and such source code may be obtained at +http://www.eclipse.org. + +# Third Party Content + +The Content includes items that have been sourced from third parties +as set out below. If you did not receive this Content directly from +the Eclipse Foundation, the following is provided for informational +purposes only, and you should look to the Redistributor’s license for +terms and conditions of use. + +## Uthash 1.9.9 + +[Uthash](https://troydhanson.github.io/uthash/) is an implementation +of hash tables and linked lists for C structures by Troy D. Hanson. +Uthash is licensed under the BSD revised license, see +https://troydhanson.github.io/uthash/license.html, + +## rijndael 3.0 + +The library uses an implementation of the Rijndael algorithm (AES) +from [OpenBSD](http://www.openbsd.org/) by Vincent Rijmen, Antoon +Bosselaers, and Paulo Barreto. The authors have placed the code in the +public domain under the license included in the file rijndael.h (see +http://www.openbsd.org/cgi-bin/cvsweb). + +## SHA-256 1.0 + +The SHA-256 implementation from Aaron D. Gifford is available at +http://www.aarongifford.com/computers/sha2-1.0.1.tgz under a +3-clause BSD license. + +## ECC 1.0 + +The implementation of the ECC curve secp256r1 was originally developed +by Chris K Cockrum and has been put under MIT license for inclusion +with tinydtls. The original source is made available in +https://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/AutoConf.cmake b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/AutoConf.cmake new file mode 100644 index 000000000..083fd07f5 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/AutoConf.cmake @@ -0,0 +1,101 @@ +############################################################################### +# +# Copyright (c) 2022 Contributors to the Eclipse Foundation +# +# See the LICENSE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 1.0 +# which is available at https://www.eclipse.org/legal/epl-v10.html +# and the Eclipse Distribution License v. 1.0 +# available at http://www.eclipse.org/org/documents/edl-v10.php +# +# SPDX-License-Identifier: EPL-1.0 +# +# Contributors: +# Jimmy Björklund - initial version +# Achim Kraus - add getrandom and libcunit +# additional minor fixes +# +############################################################################### + +include(CheckIncludeFile) +include(CheckFunctionExists) +include(CheckLibraryExists) +include(TestBigEndian) +include(CheckCSourceCompiles) +include(CheckStructHasMember) + +check_include_file(assert.h HAVE_ASSERT_H) +check_include_file(arpa/inet.h HAVE_ARPA_INET_H) +check_include_file(fcntl.h HAVE_FCNTL_H) +check_include_file(inttypes.h HAVE_INTTYPES_H) +check_include_file(memory.h HAVE_MEMORY_H) +check_include_file(netdb.h HAVE_NETDB_H) +check_include_file(netinet/in.h HAVE_NETINET_IN_H) +check_include_file(stddef.h HAVE_STDDEF_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stdlib.h HAVE_STDLIB_H) +check_include_file(string.h HAVE_STRING_H) +check_include_file(strings.h HAVE_STRINGS_H) +check_include_file(time.h HAVE_TIME_H) +check_include_file(sys/param.h HAVE_SYS_PARAM_H) +check_include_file(sys/random.h HAVE_SYS_RANDOM_H) +check_include_file(sys/socket.h HAVE_SYS_SOCKET_H) +check_include_file(sys/stat.h HAVE_SYS_STAT_H) +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(unistd.h HAVE_UNISTD_H) +check_include_file(float.h HAVE_FLOAT_H) +check_include_file(dlfcn.h HAVE_DLFCN_H) + +if(NOT ZEPHYR_BASE) + # zephyr/ncs 1.9.1 has issues including this header + check_include_file(sys/time.h HAVE_SYS_TIME_H) +endif() + +if(ZEPHYR_BASE) + # zephyr/ncs 1.9.1 has issues with check_include_file + # https://github.com/zephyrproject-rtos/zephyr/issues/31193 + # zephyr/ncs 1.9.1 has net/socket.h instead of sys/socket.h + set(HAVE_NET_SOCKET_H 1) +endif() + +check_function_exists (memset HAVE_MEMSET) +check_function_exists (select HAVE_SELECT) +check_function_exists (socket HAVE_SOCKET) +check_function_exists (strdup HAVE_STRDUP) +check_function_exists (strerror HAVE_STRERROR) +check_function_exists (strnlen HAVE_STRNLEN) +check_function_exists (fls HAVE_FLS) +check_function_exists (vprintf HAVE_VPRINTF) +check_function_exists (inet_ntop HAVE_INET_NTOP) + +if(HAVE_SYS_RANDOM_H) + # zephyr/ncs 1.9.1 seems to link getrandom but doesn't offer a header + check_function_exists (getrandom HAVE_GETRANDOM) +endif() + +if( ${make_tests} ) + if(BUILD_SHARED_LIBS) + check_library_exists (libcunit.so CU_initialize_registry "" HAVE_LIBCUNIT) + else() + # this link options only intended to be used for the cunit tests + set(CMAKE_REQUIRED_LINK_OPTIONS -no-pie) + check_library_exists (libcunit.a CU_initialize_registry "" HAVE_LIBCUNIT) + endif() +endif() + +if( "${HAVE_STRING_H}" AND "${HAVE_STRINGS_H}" AND + "${HAVE_FLOAT_H}" AND "${HAVE_STDLIB_H}" AND + "${HAVE_STDDEF_H}" AND "${HAVE_STDINT_H}" AND + "${HAVE_INTTYPES_H}" AND "${HAVE_DLFCN_H}" ) + set( STDC_HEADERS 1) +endif() + +check_struct_has_member ("struct sockaddr_in6" sin6_len "netinet/in.h" HAVE_SOCKADDR_IN6_SIN6_LEN) + +TEST_BIG_ENDIAN(IS_BIG_ENDIAN) +if(IS_BIG_ENDIAN) + set(WORDS_BIGENDIAN 1) +endif() diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/CMakeLists.txt b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/CMakeLists.txt new file mode 100644 index 000000000..85165804e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/CMakeLists.txt @@ -0,0 +1,85 @@ +############################################################################### +# +# Copyright (c) 2022 Contributors to the Eclipse Foundation +# +# See the LICENSE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 1.0 +# which is available at https://www.eclipse.org/legal/epl-v10.html +# and the Eclipse Distribution License v. 1.0 +# available at http://www.eclipse.org/org/documents/edl-v10.php +# +# SPDX-License-Identifier: EPL-1.0 +# +# Contributors: +# Jimmy Björklund - initial version +# Achim Kraus - minor fixes +# +############################################################################### + +cmake_minimum_required(VERSION 3.5) + +project(tinydtls) + +include (AutoConf.cmake) + +option(BUILD_SHARED_LIBS "Link using shared libs" OFF) +option(make_tests "Make test programs and examples" OFF) + +if(NOT PLATFORM) + # PLATFORM seems to be not used + set(PLATFORM "posix" CACHE STRING "Choose platform." FORCE) + set_property(CACHE PLATFORM PROPERTY STRINGS "contiki" "espidf" "posix" "riot" "zephyr") +endif() + +set(PACKAGE_NAME "tinydtls") +set(PACKAGE_VERSION "0.8.6" ) +set(SOVERSION "0" ) + +option(DTLS_ECC "disable/enable support for TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8" ON ) +option(DTLS_PSK "disable/enable support for TLS_PSK_WITH_AES_128_CCM_8" ON) + +configure_file(dtls_config.h.cmake.in dtls_config.h ) + +add_library(tinydtls) + +target_sources(tinydtls PRIVATE + dtls.c + netq.c + peer.c + session.c + crypto.c + ccm.c + hmac.c + dtls_time.c + dtls_debug.c + dtls_prng.c + aes/rijndael.c + aes/rijndael_wrap.c + sha2/sha2.c + ecc/ecc.c) + +target_include_directories(tinydtls PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) +target_compile_definitions(tinydtls PUBLIC DTLSv12 WITH_SHA256 SHA2_USE_INTTYPES_H DTLS_CHECK_CONTENTTYPE) + +if(NOT ZEPHYR_BASE) + target_compile_options(tinydtls PRIVATE -fPIC -pedantic -std=c99 -Wall -Wextra -Wformat-security -Winline -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wshadow -Wstrict-prototypes -Wswitch-default -Wswitch-enum -Wunused) +endif() + +set_target_properties(tinydtls PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION ${SOVERSION}) + +if( ${make_tests} ) + add_subdirectory(tests) +endif() + +if(BUILD_SHARED_LIBS) + install(TARGETS tinydtls LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) +else() + install(TARGETS tinydtls DESTINATION ${CMAKE_INSTALL_LIBDIR} ) +endif() + +file(CONFIGURE OUTPUT .gitignore + NEWLINE_STYLE UNIX + CONTENT "*") diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/CONTRIBUTING.md b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/CONTRIBUTING.md new file mode 100644 index 000000000..4e4f5de69 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/CONTRIBUTING.md @@ -0,0 +1,144 @@ +Contributing to tinydtls +======================== + +Thanks for your interest in this project. + +Project description: +-------------------- + +tinydtls is a library for Datagram Transport Layer Security (DTLS) covering +both the client and the server state machine. It is implemented in C and +provides support for the mandatory cipher suites specified in CoAP. + +- https://projects.eclipse.org/projects/iot.tinydtls + +Developer resources: +-------------------- + +Information regarding source code management, builds, and more. + +- https://projects.eclipse.org/projects/iot.tinydtls/developer + +Eclipse Contributor Agreement +----------------------------- + +Before your contribution can be accepted by the project team contributors must +electronically sign the Eclipse Contributor Agreement (ECA). + +* http://www.eclipse.org/legal/ECA.php + +Commits that are provided by non-committers must have a Signed-off-by field in +the footer indicating that the author is aware of the terms by which the +contribution has been provided to the project. The non-committer must +additionally have an Eclipse Foundation account and must have a signed Eclipse +Contributor Agreement (ECA) on file. + +For more information, please see the Eclipse Committer Handbook: +https://www.eclipse.org/projects/handbook/#resources-commit + +Contact: +-------- + +Contact the project developers via the project's "dev" list. + +- https://dev.eclipse.org/mailman/listinfo/tinydtls-dev + +Search for bugs: +---------------- + +This project uses Bugzilla to track ongoing development and issues. + +- https://bugs.eclipse.org/bugs/buglist.cgi?product=tinydtls + +Create a new bug: +----------------- + +Be sure to search for existing bugs before you create another one. +Remember that contributions are always welcome! + +- https://bugs.eclipse.org/bugs/enter_bug.cgi?product=tinydtls + +Submit Patches via GitHub: +-------------------------- + +Patches must follow to the tinydtls coding style and must be submitted +as pull request at https://github.com/eclipse/tinydtls for review. To +submit a patch, the author needs to have a Eclipse Contributor Agreement +as explained above. + +Every new file must contain the Eclipse license information and the +copyright holder(s). Please take a look into existing files and adopt +the needed changes to your new file(s). + +Main and Develop: +----------------- + +Please prepare all patches against the "main" branch. + +It may take sometimes a little longer for a pull request to be processed +and merged to "main". Therefore some of the pending pull requests will be +available on the "develop" branch as preview. If you want to test a specific +pending pull request which is currently not on "develop", let us know by +adding a comment to that pull request. If a pull request is cherry-picked +to the "develop" branch, that doesn't grant that it is merged as-it-is. +For house-keeping, it may in some cases be required to push the "develop" +branch with "--force-with-lease" in order to adjust the branch for later +changes in a pull request before it gets merged into "main" or if "develop" +is rebased to "main". + +In some rare cases, it may be required to include another still pending pull +request/commit into your pull request additionally. If that other pull request +gets merged, please rebase then your pull request using the new "main". + +Currently (July 2022) this process change is in progress. Therefore some +pull requests are merged into "develop" and will be included in "main" +after the review finally completes. + +Tinydtls Coding style: +---------------------- + +* For better reading the indentation is set to 2 characters as spaces, + this is depended on the often used nested functions like + 'if-else'. Don't use TABs any there! Avoid trailing white spaces at + the end of a line. + +* Single lines within the source code should not be longer than 72 + characters and must not be longer than 80. + +* In the implementation (i.e., in files ending with '.c'), function + identifiers start on the first column of a line. The function's + return type preceeds the function identifier on a line of its + own. For example, in `dtls.c` the following definition is found: + +``` +dtls_peer_t * +dtls_get_peer(const dtls_context_t *ctx, const session_t *session) { +... +} +``` + +* Declarations in header files do not follow the previous rule. For + example, the declaration for `dtls_get_peer()` in `dtls.h` reads as + follows: + +``` +dtls_peer_t *dtls_get_peer(const dtls_context_t *context, + const session_t *session); +``` + +* A useful source code documentation is mandatory. Mostly to be done + within the source code files. + +* Please set up/adjust the doxygen documentation if you create new + functions or change existing functions. The doxygen documentation + has to be done in the header files as they are the public part of + tinydtls and only use the @-syntax for doxygen commands (akin to + javadoc). + +* Never break the API! + Do not remove old functions unless absolutely necessary. If changes + are needed in some kind always provide a wrapper for the old call to + let the library be backward compatible and mark the old function as + @deprecated in the doxygen comment. Please discuss needed changes + on the mailing list. + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/LICENSE b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/LICENSE new file mode 100644 index 000000000..f4111b7fd --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/LICENSE @@ -0,0 +1,12 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + *******************************************************************************/ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/Makefile.riot b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/Makefile.riot new file mode 100644 index 000000000..6d5593b7b --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/Makefile.riot @@ -0,0 +1,7 @@ +MODULE = tinydtls + +CFLAGS += -DDTLSv12 -DWITH_SHA256 + +SRC := ccm.c crypto.c dtls.c dtls_debug.c dtls_time.c hmac.c netq.c peer.c session.c dtls_prng.c + +include $(RIOTBASE)/Makefile.base diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/Makefile.tinydtls b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/Makefile.tinydtls new file mode 100644 index 000000000..e8cf956b8 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/Makefile.tinydtls @@ -0,0 +1,9 @@ +# This is a -*- Makefile -*- + +CFLAGS += -DDTLSv12 -DWITH_SHA256 +tinydtls_src = dtls.c crypto.c hmac.c rijndael.c rijndael_wrap.c sha2.c ccm.c netq.c ecc.c dtls_time.c peer.c session.c dtls_prng.c + +# This activates debugging support +# CFLAGS += -DNDEBUG +tinydtls_src += dtls_debug.c + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/README.md b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/README.md new file mode 100644 index 000000000..1f86266e0 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/README.md @@ -0,0 +1,81 @@ +# About tinydtls + +tinydtls is a library for Datagram Transport Layer Security (DTLS) +covering both the client and the server state machine. It is +implemented in C and provides support for a minimal set of cipher +suites suitable for the Internet of Things. + +This library contains functions and structures that can help +constructing a single-threaded UDP server with DTLS support in +C99. The following components are available: + +* dtls + Basic support for DTLS with pre-shared key mode and RPK mode with ECC. + +* tests + The subdirectory tests contains test programs that show how each + component is used. + +# BUILDING + +When using the code from the git +[repository](https://github.com/eclipse/tinydtls) at GitHub, invoke + + $ ./autogen.sh + $ ./configure + +to re-create the configure script. + +## Contiki + +On Contiki, place the tinydtls library into the apps folder. After +configuration, invoke make to build the library and associated test +programs. To add tinydtls as Contiki application, drop it into the +apps directory and add the following line to your Makefile: + + APPS += tinydtls/aes tinydtls/sha2 tinydtls/ecc tinydtls + +## RIOT + +On RIOT, you need to add the line `USEPKG += tinydtls`. +You can use `RIOT/examples/dtls-echo/` as a guide for integrating tinyDTLS +to your application. + +Also, if you need a specific commit of tinyDTLS you can modify +`RIOT/pkg/tinydtls/Makefile`. + +## CMake + +The current cmake support is experimental. Don't hesitate to report issues +and/or provided fixes for it. For general and more details on using CMake, +please consider [CMake - help](https://cmake.org/cmake/help/latest/index.html). + +Usage: + +``` +mkdir tinydtls_build +cd tinydtls_build +cmake -Dmake_tests=ON +cmake --build . +``` + +Available options: + +| Option | Description | Default | +| ------ | ----------- | ------- | +| BUILD_SHARED_LIBS | build shared libraries instead of static link library | OFF | +| make_tests | build tests including the examples | OFF | +| DTLS_ECC | enable/disable ECDHE_ECDSA cipher suites | ON | +| DTLS_PSK | enable/disable PSK cipher suites | ON | + +# License + +Copyright (c) 2011–2022 Olaf Bergmann (TZI) and others. +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +and Eclipse Distribution License v. 1.0 which accompanies this distribution. + +The Eclipse Public License is available at +http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution +License is available at +http://www.eclipse.org/org/documents/edl-v10.php. diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/Makefile.riot b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/Makefile.riot new file mode 100644 index 000000000..298e2fd82 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/Makefile.riot @@ -0,0 +1,5 @@ +MODULE := tinydtls_aes + +SRC := rijndael.c rijndael_wrap.c + +include $(RIOTBASE)/Makefile.base diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael.c new file mode 100644 index 000000000..19277694c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael.c @@ -0,0 +1,1231 @@ +/* $OpenBSD: rijndael.c,v 1.19 2008/06/09 07:49:45 djm Exp $ */ + +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + */ + +/* #include */ +/* #include */ + +#include "rijndael.h" + +#undef FULL_UNROLL + +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +static const aes_u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const aes_u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const aes_u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const aes_u32 Te3[256] = { + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; +static const aes_u32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; + +#ifdef WITH_AES_DECRYPT + +static const aes_u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const aes_u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const aes_u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const aes_u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const aes_u32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; + +#endif /* WITH_AES_DECRYPT */ + +static const aes_u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +#define GETU32(pt) (((aes_u32)(pt)[0] << 24) ^ ((aes_u32)(pt)[1] << 16) ^ ((aes_u32)(pt)[2] << 8) ^ ((aes_u32)(pt)[3])) +#define PUTU32(ct, st) { (ct)[0] = (aes_u8)((st) >> 24); (ct)[1] = (aes_u8)((st) >> 16); (ct)[2] = (aes_u8)((st) >> 8); (ct)[3] = (aes_u8)(st); } + +/** + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int +rijndaelKeySetupEnc(aes_u32 rk[/*4*(Nr + 1)*/], const aes_u8 cipherKey[], int keyBits) +{ + int i = 0; + aes_u32 temp; + + rk[0] = GETU32(cipherKey ); + rk[1] = GETU32(cipherKey + 4); + rk[2] = GETU32(cipherKey + 8); + rk[3] = GETU32(cipherKey + 12); + if (keyBits == 128) { + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 10; + } + rk += 4; + } + } + rk[4] = GETU32(cipherKey + 16); + rk[5] = GETU32(cipherKey + 20); + if (keyBits == 192) { + for (;;) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 12; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(cipherKey + 24); + rk[7] = GETU32(cipherKey + 28); + if (keyBits == 256) { + for (;;) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 14; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + rk += 8; + } + } + return 0; +} + +#ifdef WITH_AES_DECRYPT +/** + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int +rijndaelKeySetupDec(aes_u32 rk[/*4*(Nr + 1)*/], const aes_u8 cipherKey[], int keyBits) +{ + int Nr, i, j; + aes_u32 temp; + + /* expand the cipher key: */ + Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); + + /* invert the order of the round keys: */ + for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < Nr; i++) { + rk += 4; + rk[0] = + Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3] ) & 0xff] & 0xff]; + } + return Nr; +} +#endif + +void +rijndaelEncrypt(const aes_u32 rk[/*4*(Nr + 1)*/], int Nr, const aes_u8 pt[16], + aes_u8 ct[16]) +{ + aes_u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt ) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(ct , s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(ct + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(ct + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(ct + 12, s3); +} + +#ifdef WITH_AES_DECRYPT +void +rijndaelDecrypt(const aes_u32 rk[/*4*(Nr + 1)*/], int Nr, const aes_u8 ct[16], + aes_u8 pt[16]) +{ + aes_u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(ct ) ^ rk[0]; + s1 = GETU32(ct + 4) ^ rk[1]; + s2 = GETU32(ct + 8) ^ rk[2]; + s3 = GETU32(ct + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(pt , s0); + s1 = + (Td4[(t1 >> 24) ] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(pt + 4, s1); + s2 = + (Td4[(t2 >> 24) ] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(pt + 8, s2); + s3 = + (Td4[(t3 >> 24) ] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(pt + 12, s3); +} +#endif /* WITH_AES_DECRYPT */ + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael.h new file mode 100644 index 000000000..31338faf2 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael.h @@ -0,0 +1,69 @@ +/* $OpenBSD: rijndael.h,v 1.13 2008/06/09 07:49:45 djm Exp $ */ + +/** + * rijndael-alg-fst.h + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + */ +#ifndef __RIJNDAEL_H +#define __RIJNDAEL_H + +#include + +#define AES_MAXKEYBITS (256) +#define AES_MAXKEYBYTES (AES_MAXKEYBITS/8) +/* for 256-bit keys we need 14 rounds for a 128 we only need 10 round */ +#define AES_MAXROUNDS 10 + +/* bergmann: to avoid conflicts with typedefs from certain Contiki platforms, + * the following type names have been prefixed with "aes_": */ +typedef unsigned char u_char; +typedef uint8_t aes_u8; +typedef uint16_t aes_u16; +typedef uint32_t aes_u32; + +/* The structure for key information */ +typedef struct { +#ifdef WITH_AES_DECRYPT + int enc_only; /* context contains only encrypt schedule */ +#endif + int Nr; /* key-length-dependent number of rounds */ + aes_u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */ +#ifdef WITH_AES_DECRYPT + aes_u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */ +#endif +} rijndael_ctx; + +int rijndael_set_key(rijndael_ctx *, const u_char *, int); +int rijndael_set_key_enc_only(rijndael_ctx *, const u_char *, int); +void rijndael_decrypt(rijndael_ctx *, const u_char *, u_char *); +void rijndael_encrypt(rijndael_ctx *, const u_char *, u_char *); + +int rijndaelKeySetupEnc(aes_u32 rk[/*4*(Nr + 1)*/], const aes_u8 cipherKey[], int keyBits); +int rijndaelKeySetupDec(aes_u32 rk[/*4*(Nr + 1)*/], const aes_u8 cipherKey[], int keyBits); +void rijndaelEncrypt(const aes_u32 rk[/*4*(Nr + 1)*/], int Nr, const aes_u8 pt[16], aes_u8 ct[16]); +#ifdef WITH_AES_DECRYPT +void rijndaelDecrypt(const aes_u32 rk[/*4*(Nr + 1)*/], int Nr, const aes_u8 ct[16], aes_u8 pt[16]); +#endif + +#endif /* __RIJNDAEL_H */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael_wrap.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael_wrap.c new file mode 100644 index 000000000..9f7aafc16 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/aes/rijndael_wrap.c @@ -0,0 +1,69 @@ +/******************************************************************************* + * + * Copyright (c) 2019 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Jon Shallow - split out wrapper code to support external rijndael code + * + * + *******************************************************************************/ + +#include "rijndael.h" + +/* setup key context for encryption only */ +int +rijndael_set_key_enc_only(rijndael_ctx *ctx, const u_char *key, int bits) +{ + int rounds; + + rounds = rijndaelKeySetupEnc(ctx->ek, key, bits); + if (rounds == 0) + return -1; + + ctx->Nr = rounds; +#ifdef WITH_AES_DECRYPT + ctx->enc_only = 1; +#endif + + return 0; +} + +#ifdef WITH_AES_DECRYPT +/* setup key context for both encryption and decryption */ +int +rijndael_set_key(rijndael_ctx *ctx, const u_char *key, int bits) +{ + int rounds; + + rounds = rijndaelKeySetupEnc(ctx->ek, key, bits); + if (rounds == 0) + return -1; + if (rijndaelKeySetupDec(ctx->dk, key, bits) != rounds) + return -1; + + ctx->Nr = rounds; + ctx->enc_only = 0; + + return 0; +} + +void +rijndael_decrypt(rijndael_ctx *ctx, const u_char *src, u_char *dst) +{ + rijndaelDecrypt(ctx->dk, ctx->Nr, src, dst); +} +#endif + +void +rijndael_encrypt(rijndael_ctx *ctx, const u_char *src, u_char *dst) +{ + rijndaelEncrypt(ctx->ek, ctx->Nr, src, dst); +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/alert.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/alert.h new file mode 100644 index 000000000..a2de596a6 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/alert.h @@ -0,0 +1,85 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +/** + * @file alert.h + * @brief DTLS alert protocol + */ + +#ifndef _DTLS_ALERT_H_ +#define _DTLS_ALERT_H_ + +typedef enum { + DTLS_ALERT_LEVEL_WARNING=1, + DTLS_ALERT_LEVEL_FATAL=2 +} dtls_alert_level_t; + +typedef enum { + DTLS_ALERT_CLOSE_NOTIFY = 0, /* close_notify */ + DTLS_ALERT_UNEXPECTED_MESSAGE = 10, /* unexpected_message */ + DTLS_ALERT_BAD_RECORD_MAC = 20, /* bad_record_mac */ + DTLS_ALERT_RECORD_OVERFLOW = 22, /* record_overflow */ + DTLS_ALERT_DECOMPRESSION_FAILURE = 30, /* decompression_failure */ + DTLS_ALERT_HANDSHAKE_FAILURE = 40, /* handshake_failure */ + DTLS_ALERT_BAD_CERTIFICATE = 42, /* bad_certificate */ + DTLS_ALERT_UNSUPPORTED_CERTIFICATE = 43, /* unsupported_certificate */ + DTLS_ALERT_CERTIFICATE_REVOKED = 44, /* certificate_revoked */ + DTLS_ALERT_CERTIFICATE_EXPIRED = 45, /* certificate_expired */ + DTLS_ALERT_CERTIFICATE_UNKNOWN = 46, /* certificate_unknown */ + DTLS_ALERT_ILLEGAL_PARAMETER = 47, /* illegal_parameter */ + DTLS_ALERT_UNKNOWN_CA = 48, /* unknown_ca */ + DTLS_ALERT_ACCESS_DENIED = 49, /* access_denied */ + DTLS_ALERT_DECODE_ERROR = 50, /* decode_error */ + DTLS_ALERT_DECRYPT_ERROR = 51, /* decrypt_error */ + DTLS_ALERT_PROTOCOL_VERSION = 70, /* protocol_version */ + DTLS_ALERT_INSUFFICIENT_SECURITY = 71, /* insufficient_security */ + DTLS_ALERT_INTERNAL_ERROR = 80, /* internal_error */ + DTLS_ALERT_USER_CANCELED = 90, /* user_canceled */ + DTLS_ALERT_NO_RENEGOTIATION = 100, /* no_renegotiation */ + DTLS_ALERT_UNSUPPORTED_EXTENSION = 110 /* unsupported_extension */ +} dtls_alert_t; + +#define DTLS_EVENT_CONNECT 0x01DC /**< initiated handshake */ +#define DTLS_EVENT_CONNECTED 0x01DE /**< handshake or re-negotiation + * has finished */ +#define DTLS_EVENT_RENEGOTIATE 0x01DF /**< re-negotiation has started */ + +static inline int +dtls_alert_create(dtls_alert_level_t level, dtls_alert_t desc) +{ + return -((level << 8) | desc); +} + +static inline int +dtls_alert_fatal_create(dtls_alert_t desc) +{ + return dtls_alert_create(DTLS_ALERT_LEVEL_FATAL, desc); +} + +/** + * Test, if error code represents an alert. + * + * \param err error code + * \return 0 (false), if not, not 0 (true), if it represents an alert. + */ +static inline int +dtls_is_alert(int err) +{ + return (err < -(1 << 8) && err > -(3 << 8)); +} + +#endif /* _DTLS_ALERT_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/autogen.sh b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/autogen.sh new file mode 100644 index 000000000..9dfc36410 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/autogen.sh @@ -0,0 +1,21 @@ +#! /bin/sh -e + +srcdir=`dirname "$0"` + +GENERATED_FILES="aclocal.m4 ar-lib compile depcomp src/.dirstamp + Makefile aes/Makefile doc/Makefile ecc/Makefile + platform-specific/Makefile sha2/Makefile + tests/Makefile tests/unit-tests/Makefile + config.status configure config.log tinydtls.pc" + +GENERATED_DIRS="autom4te.cache src/.deps" + +if test "x$1" = "x--clean"; then + rm -f $GENERATED_FILES + rm -rf $GENERATED_DIRS + exit 0 +fi + +# create fake ar-lib if not present +test -e ar-lib || touch ar-lib +autoreconf --force --install --verbose "$srcdir" diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ccm.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ccm.c new file mode 100644 index 000000000..0a5e0ce58 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ccm.c @@ -0,0 +1,303 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#include + +#include "tinydtls.h" +#include "global.h" +#include "numeric.h" +#include "ccm.h" + +#ifdef HAVE_ASSERT_H +# include +#endif + +#define CCM_FLAGS(A,M,L) (((A > 0) << 6) | (((M - 2)/2) << 3) | (L - 1)) + +#define MASK_L(_L) ((1 << 8 * _L) - 1) + +#define SET_COUNTER(A,L,cnt,C) { \ + unsigned int i_; \ + memset((A) + DTLS_CCM_BLOCKSIZE - (L), 0, (L)); \ + (C) = (cnt) & MASK_L(L); \ + for (i_ = DTLS_CCM_BLOCKSIZE - 1; (C) && (i_ > (L)); --i_, (C) >>= 8) \ + (A)[i_] |= (C) & 0xFF; \ + } + +static inline void +block0(size_t M, /* number of auth bytes */ + size_t L, /* number of bytes to encode message length */ + size_t la, /* l(a) octets additional authenticated data */ + size_t lm, /* l(m) message length */ + const unsigned char nonce[DTLS_CCM_BLOCKSIZE], + unsigned char *result) { + unsigned int i; + + result[0] = CCM_FLAGS(la, M, L); + + /* copy the nonce */ + memcpy(result + 1, nonce, DTLS_CCM_BLOCKSIZE - L - 1); + + for (i=0; i < L; i++) { + result[15-i] = lm & 0xff; + lm >>= 8; + } +} + +/** + * Creates the CBC-MAC for the additional authentication data that + * is sent in cleartext. + * + * \param ctx The crypto context for the AES encryption. + * \param msg The message starting with the additional authentication data. + * \param la The number of additional authentication bytes in \p msg. + * \param B The input buffer for crypto operations. When this function + * is called, \p B must be initialized with \c B0 (the first + * authentication block. + * \param X The output buffer where the result of the CBC calculation + * is placed. + * \return The result is written to \p X. + */ +static void +add_auth_data(rijndael_ctx *ctx, const unsigned char *msg, uint64_t la, + unsigned char B[DTLS_CCM_BLOCKSIZE], + unsigned char X[DTLS_CCM_BLOCKSIZE]) { + uint64_t i,j; + + rijndael_encrypt(ctx, B, X); + + memset(B, 0, DTLS_CCM_BLOCKSIZE); + + if (!la) + return; + +#ifndef WITH_CONTIKI + if (la < 0xFF00) { /* 2^16 - 2^8 */ + j = 2; + dtls_int_to_uint16(B, la); + } else if (la <= UINT32_MAX) { + j = 6; + dtls_int_to_uint16(B, 0xFFFE); + dtls_int_to_uint32(B+2, la); + } else { + j = 10; + dtls_int_to_uint16(B, 0xFFFF); + dtls_int_to_uint64(B+2, la); + } +#else /* WITH_CONTIKI */ + /* With Contiki, we are building for small devices and thus + * anticipate that the number of additional authentication bytes + * will not exceed 65280 bytes (0xFF00) and we can skip the + * workarounds required for j=6 and j=10 on devices with a word size + * of 32 bits or 64 bits, respectively. + */ + + assert(la < 0xFF00); + j = 2; + dtls_int_to_uint16(B, la); +#endif /* WITH_CONTIKI */ + + i = min(DTLS_CCM_BLOCKSIZE - j, la); + memcpy(B + j, msg, i); + la -= i; + msg += i; + + memxor(B, X, DTLS_CCM_BLOCKSIZE); + + rijndael_encrypt(ctx, B, X); + + while (la > DTLS_CCM_BLOCKSIZE) { + for (i = 0; i < DTLS_CCM_BLOCKSIZE; ++i) + B[i] = X[i] ^ *msg++; + la -= DTLS_CCM_BLOCKSIZE; + + rijndael_encrypt(ctx, B, X); + } + + if (la) { + memset(B, 0, DTLS_CCM_BLOCKSIZE); + memcpy(B, msg, la); + memxor(B, X, DTLS_CCM_BLOCKSIZE); + + rijndael_encrypt(ctx, B, X); + } +} + +static inline void +encrypt(rijndael_ctx *ctx, size_t L, unsigned long counter, + unsigned char *msg, size_t len, + unsigned char A[DTLS_CCM_BLOCKSIZE], + unsigned char S[DTLS_CCM_BLOCKSIZE]) { + + static unsigned long counter_tmp; + + SET_COUNTER(A, L, counter, counter_tmp); + rijndael_encrypt(ctx, A, S); + memxor(msg, S, len); +} + +static inline void +mac(rijndael_ctx *ctx, + unsigned char *msg, size_t len, + unsigned char B[DTLS_CCM_BLOCKSIZE], + unsigned char X[DTLS_CCM_BLOCKSIZE]) { + size_t i; + + for (i = 0; i < len; ++i) + B[i] = X[i] ^ msg[i]; + + rijndael_encrypt(ctx, B, X); + +} + +long int +dtls_ccm_encrypt_message(rijndael_ctx *ctx, size_t M, size_t L, + const unsigned char nonce[DTLS_CCM_BLOCKSIZE], + unsigned char *msg, size_t lm, + const unsigned char *aad, size_t la) { + size_t i, len; + unsigned long counter_tmp; + unsigned long counter = 1; /* \bug does not work correctly on ia32 when + lm >= 2^16 */ + unsigned char A[DTLS_CCM_BLOCKSIZE]; /* A_i blocks for encryption input */ + unsigned char B[DTLS_CCM_BLOCKSIZE]; /* B_i blocks for CBC-MAC input */ + unsigned char S[DTLS_CCM_BLOCKSIZE]; /* S_i = encrypted A_i blocks */ + unsigned char X[DTLS_CCM_BLOCKSIZE]; /* X_i = encrypted B_i blocks */ + + len = lm; /* save original length */ + /* create the initial authentication block B0 */ + block0(M, L, la, lm, nonce, B); + add_auth_data(ctx, aad, la, B, X); + + /* initialize block template */ + A[0] = L-1; + + /* copy the nonce */ + memcpy(A + 1, nonce, DTLS_CCM_BLOCKSIZE - L - 1); + + while (lm >= DTLS_CCM_BLOCKSIZE) { + /* calculate MAC */ + mac(ctx, msg, DTLS_CCM_BLOCKSIZE, B, X); + + /* encrypt */ + encrypt(ctx, L, counter, msg, DTLS_CCM_BLOCKSIZE, A, S); + + /* update local pointers */ + lm -= DTLS_CCM_BLOCKSIZE; + msg += DTLS_CCM_BLOCKSIZE; + counter++; + } + + if (lm) { + /* Calculate MAC. The remainder of B must be padded with zeroes, so + * B is constructed to contain X ^ msg for the first lm bytes (done in + * mac() and X ^ 0 for the remaining DTLS_CCM_BLOCKSIZE - lm bytes + * (i.e., we can use memcpy() here). + */ + memcpy(B + lm, X + lm, DTLS_CCM_BLOCKSIZE - lm); + mac(ctx, msg, lm, B, X); + + /* encrypt */ + encrypt(ctx, L, counter, msg, lm, A, S); + + /* update local pointers */ + msg += lm; + } + + /* calculate S_0 */ + SET_COUNTER(A, L, 0, counter_tmp); + rijndael_encrypt(ctx, A, S); + + for (i = 0; i < M; ++i) + *msg++ = X[i] ^ S[i]; + + return len + M; +} + +long int +dtls_ccm_decrypt_message(rijndael_ctx *ctx, size_t M, size_t L, + const unsigned char nonce[DTLS_CCM_BLOCKSIZE], + unsigned char *msg, size_t lm, + const unsigned char *aad, size_t la) { + + size_t len; + unsigned long counter_tmp; + unsigned long counter = 1; /* \bug does not work correctly on ia32 when + lm >= 2^16 */ + unsigned char A[DTLS_CCM_BLOCKSIZE]; /* A_i blocks for encryption input */ + unsigned char B[DTLS_CCM_BLOCKSIZE]; /* B_i blocks for CBC-MAC input */ + unsigned char S[DTLS_CCM_BLOCKSIZE]; /* S_i = encrypted A_i blocks */ + unsigned char X[DTLS_CCM_BLOCKSIZE]; /* X_i = encrypted B_i blocks */ + + if (lm < M) + goto error; + + len = lm; /* save original length */ + lm -= M; /* detract MAC size*/ + + /* create the initial authentication block B0 */ + block0(M, L, la, lm, nonce, B); + add_auth_data(ctx, aad, la, B, X); + + /* initialize block template */ + A[0] = L-1; + + /* copy the nonce */ + memcpy(A + 1, nonce, DTLS_CCM_BLOCKSIZE - L - 1); + + while (lm >= DTLS_CCM_BLOCKSIZE) { + /* decrypt */ + encrypt(ctx, L, counter, msg, DTLS_CCM_BLOCKSIZE, A, S); + + /* calculate MAC */ + mac(ctx, msg, DTLS_CCM_BLOCKSIZE, B, X); + + /* update local pointers */ + lm -= DTLS_CCM_BLOCKSIZE; + msg += DTLS_CCM_BLOCKSIZE; + counter++; + } + + if (lm) { + /* decrypt */ + encrypt(ctx, L, counter, msg, lm, A, S); + + /* Calculate MAC. Note that msg ends in the MAC so we must + * construct B to contain X ^ msg for the first lm bytes (done in + * mac() and X ^ 0 for the remaining DTLS_CCM_BLOCKSIZE - lm bytes + * (i.e., we can use memcpy() here). + */ + memcpy(B + lm, X + lm, DTLS_CCM_BLOCKSIZE - lm); + mac(ctx, msg, lm, B, X); + + /* update local pointers */ + msg += lm; + } + + /* calculate S_0 */ + SET_COUNTER(A, L, 0, counter_tmp); + rijndael_encrypt(ctx, A, S); + + memxor(msg, S, M); + + /* return length if MAC is valid, otherwise continue with error handling */ + if (equals(X, msg, M)) + return len - M; + + error: + return -1; +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ccm.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ccm.h new file mode 100644 index 000000000..87eb5c935 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ccm.h @@ -0,0 +1,61 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#ifndef _DTLS_CCM_H_ +#define _DTLS_CCM_H_ + +#include "aes/rijndael.h" + +/* implementation of Counter Mode CBC-MAC, RFC 3610 */ + +#define DTLS_CCM_BLOCKSIZE 16 /**< size of hmac blocks */ +#define DTLS_CCM_MAX 16 /**< max number of bytes in digest */ +#define DTLS_CCM_NONCE_SIZE 12 /**< size of nonce */ + +/** + * Authenticates and encrypts a message using AES in CCM mode. Please + * see also RFC 3610 for the meaning of \p M, \p L, \p lm and \p la. + * + * \param ctx The initialized rijndael_ctx object to be used for AES operations. + * \param M The number of authentication octets. + * \param L The number of bytes used to encode the message length. + * \param N The nonce value to use. You must provide \c DTLS_CCM_BLOCKSIZE + * nonce octets, although only the first \c 16 - \p L - 1 are used. + * \param msg The message to encrypt. The first \p la octets are additional + * authentication data that will be cleartext. Note that the + * encryption operation modifies the contents of \p msg and adds + * \p M bytes MAC. Therefore, the buffer must be at least + * \p lm + \p M bytes large. + * \param lm The actual length of \p msg. + * \param aad A pointer to the additional authentication data (can be \c NULL if + * \p la is zero). + * \param la The number of additional authentication octets (may be zero). + * \return FIXME + */ +long int +dtls_ccm_encrypt_message(rijndael_ctx *ctx, size_t M, size_t L, + const unsigned char nonce[DTLS_CCM_BLOCKSIZE], + unsigned char *msg, size_t lm, + const unsigned char *aad, size_t la); + +long int +dtls_ccm_decrypt_message(rijndael_ctx *ctx, size_t M, size_t L, + const unsigned char nonce[DTLS_CCM_BLOCKSIZE], + unsigned char *msg, size_t lm, + const unsigned char *aad, size_t la); + +#endif /* _DTLS_CCM_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/configure.ac b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/configure.ac new file mode 100644 index 000000000..bb675331b --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/configure.ac @@ -0,0 +1,153 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. +# +# Copyright (c) 2011-2021 Olaf Bergmann (TZI) and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# and Eclipse Distribution License v. 1.0 which accompanies this distribution. +# +# The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +# and the Eclipse Distribution License is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# Contributors: +# Olaf Bergmann - initial API and implementation +# Hauke Mehrtens - memory optimization, ECC integration +# Hugo Damer - support for pkg-config + +AC_PREREQ([2.65]) +AC_INIT([tinydtls], [0.8.6], [], [], [https://projects.eclipse.org/projects/iot.tinydtls]) +AC_CONFIG_SRCDIR([dtls.c]) +dnl AC_CONFIG_HEADERS([config.h]) + +AC_PATH_PROG(DOXYGEN, doxygen, [:]) +AC_PATH_PROG(ETAGS, etags, [/bin/false]) + +# Make configure happy +test -e install-sh || touch install-sh + +# Checks for programs. +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_RANLIB +m4_ifdef([AM_PROG_AR], [AM_PROG_AR], [AR=ar]) + +AC_C_BIGENDIAN + +CFLAGS="${CFLAGS} -fPIC" + +# Adding some default warning options for code QS +# see https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html +# and http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html +WARNING_CFLAGS="\ +-pedantic \ +-Wall \ +-Wextra \ +-Wformat-security \ +-Winline \ +-Wmissing-declarations \ +-Wmissing-prototypes \ +-Wnested-externs \ +-Wpointer-arith \ +-Wshadow \ +-Wstrict-prototypes \ +-Wswitch-default \ +-Wswitch-enum \ +-Wunused \ +" + +AC_SUBST([WARNING_CFLAGS]) + +# Checks for libraries. +AC_SEARCH_LIBS([gethostbyname], [nsl]) +AC_SEARCH_LIBS([socket], [socket]) + +AC_ARG_WITH(debug, + [AS_HELP_STRING([--without-debug],[disable all debug output and assertions])], + [CPPFLAGS="${CPPFLAGS} -DNDEBUG" + NDEBUG=1], + []) + +AC_ARG_WITH(ecc, + [AS_HELP_STRING([--without-ecc],[disable support for TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8])], + [], + [AC_DEFINE(DTLS_ECC, 1, [Define to 1 if building with ECC support.]) + OPT_OBJS="${OPT_OBJS} ecc/ecc.o" + DTLS_ECC=1]) + +AC_ARG_WITH(psk, + [AS_HELP_STRING([--without-psk],[disable support for TLS_PSK_WITH_AES_128_CCM_8])], + [], + [AC_DEFINE(DTLS_PSK, 1, [Define to 1 if building with PSK support]) + DTLS_PSK=1]) + +# configure options +# __tests__ +AC_ARG_ENABLE([tests], + [AS_HELP_STRING([--enable-tests], + [Enable building the binary testsuite [default=no]])], + [build_tests="$enableval"], + [build_tests="no"]) + +if test "x$build_tests" = "xyes"; then + PKG_CHECK_MODULES([CUNIT], + [cunit], + [have_cunit=yes + AC_DEFINE(HAVE_LIBCUNIT, [1], [Define if the system has libcunit]) + AC_DEFINE(TEST_INCLUDE, [1], [Define to include test wrappers for static functions])], + [have_cunit=no]) +fi + +AC_SUBST(have_cunit) + +AC_ARG_ENABLE(shared, + [AS_HELP_STRING([--disable-shared],[disable build of shared library])], + [], + [enable_shared=yes]) +if test "$enable_shared" = "yes" ; then + ENABLE_SHARED=1 +fi + +CPPFLAGS="${CPPFLAGS} -DDTLSv12 -DWITH_SHA256" +OPT_OBJS="${OPT_OBJS} sha2/sha2.o" + +AC_SUBST(OPT_OBJS) +AC_SUBST(NDEBUG) +AC_SUBST(DTLS_ECC) +AC_SUBST(DTLS_PSK) +AC_SUBST(ENABLE_SHARED) +AC_SUBST(AR) + +# Checks for header files. +AC_CHECK_HEADERS([assert.h arpa/inet.h fcntl.h inttypes.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h strings.h sys/param.h sys/socket.h unistd.h]) + +AC_CHECK_HEADERS([sys/time.h time.h]) +AC_CHECK_HEADERS([sys/types.h sys/stat.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_INLINE +AC_TYPE_SIZE_T + +AC_CHECK_MEMBER([struct sockaddr_in6.sin6_len], + [AC_DEFINE(HAVE_SOCKADDR_IN6_SIN6_LEN, [1], + [Define to 1 if struct sockaddr_in6 has a member sin6_len.])], [], + [#include ]) + +# Checks for library functions. +AC_CHECK_FUNCS([memset select socket strdup strerror strnlen fls vprintf \ + getrandom inet_ntop]) + +AC_CONFIG_HEADERS([dtls_config.h]) + + +AC_CONFIG_FILES([Makefile + doc/Makefile + doc/Doxyfile + tests/Makefile + tests/unit-tests/Makefile + platform-specific/Makefile + tinydtls.pc + sha2/Makefile + aes/Makefile + ecc/Makefile]) +AC_OUTPUT diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/crypto.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/crypto.c new file mode 100644 index 000000000..8cfb7e683 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/crypto.c @@ -0,0 +1,641 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#include + +#include "tinydtls.h" + +#ifdef HAVE_ASSERT_H +#include +#else +#define assert(x) +#endif + +#include "global.h" +#include "dtls_debug.h" +#include "numeric.h" +#include "dtls.h" +#include "crypto.h" +#include "ccm.h" +#include "ecc/ecc.h" +#include "dtls_prng.h" +#include "netq.h" + +#include "dtls_mutex.h" + +#ifdef WITH_ZEPHYR +LOG_MODULE_DECLARE(TINYDTLS, CONFIG_TINYDTLS_LOG_LEVEL); +#endif /* WITH_ZEPHYR */ + +#if defined(RIOT_VERSION) +# include + +dtls_handshake_parameters_t handshake_storage_data[DTLS_HANDSHAKE_MAX]; +dtls_security_parameters_t security_storage_data[DTLS_SECURITY_MAX]; +dtls_handshake_parameters_t handshake_storage_data[DTLS_HANDSHAKE_MAX]; +dtls_security_parameters_t security_storage_data[DTLS_SECURITY_MAX]; + +memarray_t handshake_storage; +memarray_t security_storage; +memarray_t handshake_storage; +memarray_t security_storage; + +#endif /* RIOT_VERSION */ + +#define HMAC_UPDATE_SEED(Context,Seed,Length) \ + if (Seed) dtls_hmac_update(Context, (Seed), (Length)) + +static struct dtls_cipher_context_t cipher_context; +static dtls_mutex_t cipher_context_mutex = DTLS_MUTEX_INITIALIZER; + +static struct dtls_cipher_context_t *dtls_cipher_context_get(void) +{ + dtls_mutex_lock(&cipher_context_mutex); + return &cipher_context; +} + +static void dtls_cipher_context_release(void) +{ + dtls_mutex_unlock(&cipher_context_mutex); +} + +#if !(defined (WITH_CONTIKI)) && !(defined (RIOT_VERSION)) +void crypto_init(void) +{ +} + +static dtls_handshake_parameters_t *dtls_handshake_malloc(void) { + return malloc(sizeof(dtls_handshake_parameters_t)); +} + +static void dtls_handshake_dealloc(dtls_handshake_parameters_t *handshake) { + free(handshake); +} + +static dtls_security_parameters_t *dtls_security_malloc(void) { + return malloc(sizeof(dtls_security_parameters_t)); +} + +static void dtls_security_dealloc(dtls_security_parameters_t *security) { + free(security); +} +#elif defined (WITH_CONTIKI) /* WITH_CONTIKI */ + +#include "memb.h" +MEMB(handshake_storage, dtls_handshake_parameters_t, DTLS_HANDSHAKE_MAX); +MEMB(security_storage, dtls_security_parameters_t, DTLS_SECURITY_MAX); + +void crypto_init(void) { + memb_init(&handshake_storage); + memb_init(&security_storage); +} + +static dtls_handshake_parameters_t *dtls_handshake_malloc(void) { + return memb_alloc(&handshake_storage); +} + +static void dtls_handshake_dealloc(dtls_handshake_parameters_t *handshake) { + memb_free(&handshake_storage, handshake); +} + +static dtls_security_parameters_t *dtls_security_malloc(void) { + return memb_alloc(&security_storage); +} + +static void dtls_security_dealloc(dtls_security_parameters_t *security) { + memb_free(&security_storage, security); +} + +#elif defined (RIOT_VERSION) + +void crypto_init(void) { + memarray_init(&handshake_storage, handshake_storage_data, sizeof(dtls_handshake_parameters_t), DTLS_HANDSHAKE_MAX); + memarray_init(&security_storage, security_storage_data, sizeof(dtls_security_parameters_t), DTLS_SECURITY_MAX); +} + +static dtls_handshake_parameters_t *dtls_handshake_malloc(void) { + return memarray_alloc(&handshake_storage); +} + +static void dtls_security_dealloc(dtls_security_parameters_t *security) { + memarray_free(&security_storage, security); +} + +static dtls_security_parameters_t *dtls_security_malloc(void) { + return memarray_alloc(&security_storage); +} + +static void dtls_handshake_dealloc(dtls_handshake_parameters_t *handshake) { + memarray_free(&handshake_storage, handshake); +} + +#endif /* WITH_CONTIKI */ + +dtls_handshake_parameters_t *dtls_handshake_new(void) +{ + dtls_handshake_parameters_t *handshake; + + handshake = dtls_handshake_malloc(); + if (!handshake) { + dtls_crit("can not allocate a handshake struct\n"); + return NULL; + } + + memset(handshake, 0, sizeof(*handshake)); + + /* initialize the handshake hash wrt. the hard-coded DTLS version */ + dtls_debug("DTLSv12: initialize HASH_SHA256\n"); + /* TLS 1.2: PRF(secret, label, seed) = P_(secret, label + seed) */ + /* FIXME: we use the default SHA256 here, might need to support other + hash functions as well */ + dtls_hash_init(&handshake->hs_state.hs_hash); + return handshake; +} + +void dtls_handshake_free(dtls_handshake_parameters_t *handshake) +{ + if (!handshake) + return; + + netq_delete_all(&handshake->reorder_queue); + dtls_handshake_dealloc(handshake); +} + +dtls_security_parameters_t *dtls_security_new(void) +{ + dtls_security_parameters_t *security; + + security = dtls_security_malloc(); + if (!security) { + dtls_crit("can not allocate a security struct\n"); + return NULL; + } + + memset(security, 0, sizeof(*security)); + + security->cipher = TLS_NULL_WITH_NULL_NULL; + security->compression = TLS_COMPRESSION_NULL; + + return security; +} + +void dtls_security_free(dtls_security_parameters_t *security) +{ + if (!security) + return; + + dtls_security_dealloc(security); +} + +size_t +dtls_p_hash(dtls_hashfunc_t h, + const unsigned char *key, size_t keylen, + const unsigned char *label, size_t labellen, + const unsigned char *random1, size_t random1len, + const unsigned char *random2, size_t random2len, + unsigned char *buf, size_t buflen) { + dtls_hmac_context_t hmac; + + unsigned char A[DTLS_HMAC_DIGEST_SIZE]; + unsigned char tmp[DTLS_HMAC_DIGEST_SIZE]; + size_t dlen; /* digest length */ + size_t len = 0; /* result length */ + (void)h; + + dtls_hmac_init(&hmac, key, keylen); + + /* calculate A(1) from A(0) == seed */ + HMAC_UPDATE_SEED(&hmac, label, labellen); + HMAC_UPDATE_SEED(&hmac, random1, random1len); + HMAC_UPDATE_SEED(&hmac, random2, random2len); + + dlen = dtls_hmac_finalize(&hmac, A); + + while (len < buflen) { + dtls_hmac_init(&hmac, key, keylen); + dtls_hmac_update(&hmac, A, dlen); + + HMAC_UPDATE_SEED(&hmac, label, labellen); + HMAC_UPDATE_SEED(&hmac, random1, random1len); + HMAC_UPDATE_SEED(&hmac, random2, random2len); + + dlen = dtls_hmac_finalize(&hmac, tmp); + + if ((len + dlen) < buflen) { + memcpy(&buf[len], tmp, dlen); + len += dlen; + } + else { + memcpy(&buf[len], tmp, buflen - len); + break; + } + + /* calculate A(i+1) */ + dtls_hmac_init(&hmac, key, keylen); + dtls_hmac_update(&hmac, A, dlen); + dtls_hmac_finalize(&hmac, A); + } + + /* prevent exposure of sensible data */ + memset(&hmac, 0, sizeof(hmac)); + memset(tmp, 0, sizeof(tmp)); + memset(A, 0, sizeof(A)); + + return buflen; +} + +size_t +dtls_prf(const unsigned char *key, size_t keylen, + const unsigned char *label, size_t labellen, + const unsigned char *random1, size_t random1len, + const unsigned char *random2, size_t random2len, + unsigned char *buf, size_t buflen) { + + /* Clear the result buffer */ + memset(buf, 0, buflen); + return dtls_p_hash(HASH_SHA256, + key, keylen, + label, labellen, + random1, random1len, + random2, random2len, + buf, buflen); +} + +void +dtls_mac(dtls_hmac_context_t *hmac_ctx, + const unsigned char *record, + const unsigned char *packet, size_t length, + unsigned char *buf) { + uint16 L; + dtls_int_to_uint16(L, length); + + assert(hmac_ctx); + dtls_hmac_update(hmac_ctx, record +3, sizeof(uint16) + sizeof(uint48)); + dtls_hmac_update(hmac_ctx, record, sizeof(uint8) + sizeof(uint16)); + dtls_hmac_update(hmac_ctx, L, sizeof(uint16)); + dtls_hmac_update(hmac_ctx, packet, length); + + dtls_hmac_finalize(hmac_ctx, buf); +} + +static size_t +dtls_ccm_encrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src, size_t srclen, + unsigned char *buf, + const unsigned char *nonce, + const unsigned char *aad, size_t la) { + long int len; + (void)src; + + assert(ccm_ctx); + + len = dtls_ccm_encrypt_message(&ccm_ctx->ctx, + ccm_ctx->tag_length /* M */, + ccm_ctx->l /* L */, + nonce, + buf, srclen, + aad, la); + return len; +} + +static size_t +dtls_ccm_decrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src, + size_t srclen, unsigned char *buf, + const unsigned char *nonce, + const unsigned char *aad, size_t la) { + long int len; + (void)src; + + assert(ccm_ctx); + + len = dtls_ccm_decrypt_message(&ccm_ctx->ctx, + ccm_ctx->tag_length /* M */, + ccm_ctx->l /* L */, + nonce, + buf, srclen, + aad, la); + return len; +} + +#ifdef DTLS_PSK +int +dtls_psk_pre_master_secret(unsigned char *key, size_t keylen, + unsigned char *result, size_t result_len) { + unsigned char *p = result; + + if (result_len < (2 * (sizeof(uint16) + keylen))) { + return -1; + } + + dtls_int_to_uint16(p, keylen); + p += sizeof(uint16); + + memset(p, 0, keylen); + p += keylen; + + memcpy(p, result, sizeof(uint16)); + p += sizeof(uint16); + + memcpy(p, key, keylen); + + return 2 * (sizeof(uint16) + keylen); +} +#endif /* DTLS_PSK */ + +#ifdef DTLS_ECC +static void dtls_ec_key_to_uint32(const unsigned char *key, size_t key_size, + uint32_t *result) { + int i; + + for (i = (key_size / sizeof(uint32_t)) - 1; i >= 0 ; i--) { + *result = dtls_uint32_to_int(&key[i * sizeof(uint32_t)]); + result++; + } +} + +static void dtls_ec_key_from_uint32(const uint32_t *key, size_t key_size, + unsigned char *result) { + int i; + + for (i = (key_size / sizeof(uint32_t)) - 1; i >= 0 ; i--) { + dtls_int_to_uint32(result, key[i]); + result += 4; + } +} + +/* Build the EC KEY as a ASN.1 positive integer */ +/* + * The public EC key consists of two positive numbers. Converting them into + * ASN.1 INTEGER requires removing leading zeros, but special care must be + * taken of the resulting sign. If the first non-zero byte of the 32 byte + * ec-key has bit 7 set (highest bit), the resultant ASN.1 INTEGER would be + * interpreted as a negative number. In order to prevent this, a zero in the + * ASN.1 presentation is prepended if that bit 7 is set. +*/ +int dtls_ec_key_asn1_from_uint32(const uint32_t *key, size_t key_size, + uint8_t *buf) { + int i = 0; + uint8_t *lptr; + + /* ASN.1 Integer r */ + dtls_int_to_uint8(buf, 0x02); + buf += sizeof(uint8); + + lptr = buf; + /* Length will be filled in later */ + buf += sizeof(uint8); + + dtls_ec_key_from_uint32(key, key_size, buf); + + /* skip leading 0's */ + while (i < (int)key_size && buf[i] == 0) { + ++i; + } + assert(i != (int)key_size); + if (i == (int)key_size) { + dtls_alert("ec key is all zero\n"); + return 0; + } + if (buf[i] >= 0x80) { + /* + * Preserve unsigned by adding leading 0 (i may go negative which is + * explicitely handled below with the assumption that buf is at least 33 + * bytes in size). + */ + --i; + } + if (i > 0) { + /* remove leading 0's */ + key_size -= i; + memmove(buf, buf + i, key_size); + } else if (i == -1) { + /* add leading 0 */ + memmove(buf +1, buf, key_size); + buf[0] = 0; + key_size++; + } + /* Update the length of positive ASN.1 integer */ + dtls_int_to_uint8(lptr, key_size); + return key_size + 2; +} + +int dtls_ecdh_pre_master_secret(unsigned char *priv_key, + unsigned char *pub_key_x, + unsigned char *pub_key_y, + size_t key_size, + unsigned char *result, + size_t result_len) { + uint32_t priv[8]; + uint32_t pub_x[8]; + uint32_t pub_y[8]; + uint32_t result_x[8]; + uint32_t result_y[8]; + + if (result_len < key_size) { + return -1; + } + + dtls_ec_key_to_uint32(priv_key, key_size, priv); + dtls_ec_key_to_uint32(pub_key_x, key_size, pub_x); + dtls_ec_key_to_uint32(pub_key_y, key_size, pub_y); + + ecc_ecdh(pub_x, pub_y, priv, result_x, result_y); + + dtls_ec_key_from_uint32(result_x, key_size, result); + return key_size; +} + +void +dtls_ecdsa_generate_key(unsigned char *priv_key, + unsigned char *pub_key_x, + unsigned char *pub_key_y, + size_t key_size) { + uint32_t priv[8]; + uint32_t pub_x[8]; + uint32_t pub_y[8]; + + do { + dtls_prng((unsigned char *)priv, key_size); + } while (!ecc_is_valid_key(priv)); + + ecc_gen_pub_key(priv, pub_x, pub_y); + + dtls_ec_key_from_uint32(priv, key_size, priv_key); + dtls_ec_key_from_uint32(pub_x, key_size, pub_key_x); + dtls_ec_key_from_uint32(pub_y, key_size, pub_key_y); +} + +/* rfc4492#section-5.4 */ +void +dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size, + const unsigned char *sign_hash, size_t sign_hash_size, + uint32_t point_r[9], uint32_t point_s[9]) { + int ret; + uint32_t priv[8]; + uint32_t hash[8]; + uint32_t randv[8]; + + dtls_ec_key_to_uint32(priv_key, key_size, priv); + dtls_ec_key_to_uint32(sign_hash, sign_hash_size, hash); + do { + dtls_prng((unsigned char *)randv, key_size); + ret = ecc_ecdsa_sign(priv, hash, randv, point_r, point_s); + } while (ret); +} + +void +dtls_ecdsa_create_sig(const unsigned char *priv_key, size_t key_size, + const unsigned char *client_random, size_t client_random_size, + const unsigned char *server_random, size_t server_random_size, + const unsigned char *keyx_params, size_t keyx_params_size, + uint32_t point_r[9], uint32_t point_s[9]) { + dtls_hash_ctx data; + unsigned char sha256hash[DTLS_HMAC_DIGEST_SIZE]; + + dtls_hash_init(&data); + dtls_hash_update(&data, client_random, client_random_size); + dtls_hash_update(&data, server_random, server_random_size); + dtls_hash_update(&data, keyx_params, keyx_params_size); + dtls_hash_finalize(sha256hash, &data); + + dtls_ecdsa_create_sig_hash(priv_key, key_size, sha256hash, + sizeof(sha256hash), point_r, point_s); +} + +/* rfc4492#section-5.4 */ +int +dtls_ecdsa_verify_sig_hash(const unsigned char *pub_key_x, + const unsigned char *pub_key_y, size_t key_size, + const unsigned char *sign_hash, size_t sign_hash_size, + unsigned char *result_r, unsigned char *result_s) { + uint32_t pub_x[8]; + uint32_t pub_y[8]; + uint32_t hash[8]; + uint32_t point_r[8]; + uint32_t point_s[8]; + + dtls_ec_key_to_uint32(pub_key_x, key_size, pub_x); + dtls_ec_key_to_uint32(pub_key_y, key_size, pub_y); + dtls_ec_key_to_uint32(result_r, key_size, point_r); + dtls_ec_key_to_uint32(result_s, key_size, point_s); + dtls_ec_key_to_uint32(sign_hash, sign_hash_size, hash); + + return ecc_ecdsa_validate(pub_x, pub_y, hash, point_r, point_s); +} + +int +dtls_ecdsa_verify_sig(const unsigned char *pub_key_x, + const unsigned char *pub_key_y, size_t key_size, + const unsigned char *client_random, size_t client_random_size, + const unsigned char *server_random, size_t server_random_size, + const unsigned char *keyx_params, size_t keyx_params_size, + unsigned char *result_r, unsigned char *result_s) { + dtls_hash_ctx data; + unsigned char sha256hash[DTLS_HMAC_DIGEST_SIZE]; + + dtls_hash_init(&data); + dtls_hash_update(&data, client_random, client_random_size); + dtls_hash_update(&data, server_random, server_random_size); + dtls_hash_update(&data, keyx_params, keyx_params_size); + dtls_hash_finalize(sha256hash, &data); + + return dtls_ecdsa_verify_sig_hash(pub_key_x, pub_key_y, key_size, sha256hash, + sizeof(sha256hash), result_r, result_s); +} +#endif /* DTLS_ECC */ + +int +dtls_encrypt_params(const dtls_ccm_params_t *params, + const unsigned char *src, size_t length, + unsigned char *buf, + const unsigned char *key, size_t keylen, + const unsigned char *aad, size_t la) { + int ret; + struct dtls_cipher_context_t *ctx = dtls_cipher_context_get(); + ctx->data.tag_length = params->tag_length; + ctx->data.l = params->l; + + ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen); + if (ret < 0) { + /* cleanup everything in case the key has the wrong size */ + dtls_warn("cannot set rijndael key\n"); + goto error; + } + + if (src != buf) + memmove(buf, src, length); + ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, params->nonce, aad, la); + +error: + dtls_cipher_context_release(); + return ret; +} + +int +dtls_encrypt(const unsigned char *src, size_t length, + unsigned char *buf, + const unsigned char *nonce, + const unsigned char *key, size_t keylen, + const unsigned char *aad, size_t la) +{ + /* For backwards-compatibility, dtls_encrypt_params is called with + * M=8 and L=3. */ + const dtls_ccm_params_t params = { nonce, 8, 3 }; + + return dtls_encrypt_params(¶ms, src, length, buf, key, keylen, aad, la); +} + +int +dtls_decrypt_params(const dtls_ccm_params_t *params, + const unsigned char *src, size_t length, + unsigned char *buf, + const unsigned char *key, size_t keylen, + const unsigned char *aad, size_t la) +{ + int ret; + struct dtls_cipher_context_t *ctx = dtls_cipher_context_get(); + ctx->data.tag_length = params->tag_length; + ctx->data.l = params->l; + + ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen); + if (ret < 0) { + /* cleanup everything in case the key has the wrong size */ + dtls_warn("cannot set rijndael key\n"); + goto error; + } + + if (src != buf) + memmove(buf, src, length); + ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, params->nonce, aad, la); + +error: + dtls_cipher_context_release(); + return ret; +} + +int +dtls_decrypt(const unsigned char *src, size_t length, + unsigned char *buf, + const unsigned char *nonce, + const unsigned char *key, size_t keylen, + const unsigned char *aad, size_t la) +{ + /* For backwards-compatibility, dtls_encrypt_params is called with + * M=8 and L=3. */ + const dtls_ccm_params_t params = { nonce, 8, 3 }; + + return dtls_decrypt_params(¶ms, src, length, buf, key, keylen, aad, la); +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/crypto.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/crypto.h new file mode 100644 index 000000000..5df6047a0 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/crypto.h @@ -0,0 +1,434 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#ifndef _DTLS_CRYPTO_H_ +#define _DTLS_CRYPTO_H_ + +#include /* for rand() and srand() */ +#include + +#include "aes/rijndael.h" + +#include "tinydtls.h" +#include "global.h" +#include "state.h" +#include "numeric.h" +#include "hmac.h" +#include "ccm.h" + +/* TLS_PSK_WITH_AES_128_CCM_8 */ +#define DTLS_MAC_KEY_LENGTH 0 +#define DTLS_KEY_LENGTH 16 /* AES-128 */ +#define DTLS_BLK_LENGTH 16 /* AES-128 */ +#define DTLS_MAC_LENGTH DTLS_HMAC_DIGEST_SIZE +#define DTLS_IV_LENGTH 4 /* length of nonce_explicit */ + +/** + * Maximum size of the generated keyblock. Note that MAX_KEYBLOCK_LENGTH must + * be large enough to hold the pre_master_secret, i.e. twice the length of the + * pre-shared key + 1. + */ +#define MAX_KEYBLOCK_LENGTH \ + (2 * DTLS_MAC_KEY_LENGTH + 2 * DTLS_KEY_LENGTH + 2 * DTLS_IV_LENGTH) + +/** Length of DTLS master_secret */ +#define DTLS_MASTER_SECRET_LENGTH 48 +#define DTLS_RANDOM_LENGTH 32 + +typedef enum { AES128=0 +} dtls_crypto_alg; + +typedef enum { + DTLS_ECDH_CURVE_SECP256R1 +} dtls_ecdh_curve; + +/** Crypto context for TLS_PSK_WITH_AES_128_CCM_8 cipher suite. */ +typedef struct { + rijndael_ctx ctx; /**< AES-128 encryption context */ + uint8_t tag_length; /**< length of MAC tag (=M) */ + uint8_t l; /**< number of bytes in length + * field (= L) */ +} aes128_ccm_t; + +typedef struct dtls_cipher_context_t { + /** numeric identifier of this cipher suite in host byte order. */ + aes128_ccm_t data; /**< The crypto context */ +} dtls_cipher_context_t; + +typedef struct { + uint8 own_eph_priv[32]; + uint8 other_eph_pub_x[32]; + uint8 other_eph_pub_y[32]; + uint8 other_pub_x[32]; + uint8 other_pub_y[32]; +} dtls_handshake_parameters_ecdsa_t; + +/* This is the maximal supported length of the psk client identity and psk + * server identity hint */ +#ifndef DTLS_PSK_MAX_CLIENT_IDENTITY_LEN +#define DTLS_PSK_MAX_CLIENT_IDENTITY_LEN 32 +#endif /* DTLS_PSK_MAX_CLIENT_IDENTITY_LEN */ + +/* This is the maximal supported length of the pre-shared key. */ +#define DTLS_PSK_MAX_KEY_LEN DTLS_KEY_LENGTH + +typedef struct { + uint16_t id_length; + unsigned char identity[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN]; +} dtls_handshake_parameters_psk_t; + +typedef struct { + uint64_t cseq; /**< current read sequence number */ + /** + * bitfield of already received sequence numbers. + * B0 := cseqn, B1 := cseqn -1, ..., B63 := cseqn - 63 + * Initially 0, set to 1 (B0) with the first received message of the epoch, + * or -1 (B0..B63) with a verified ClientHello (server-side only) + */ + uint64_t bitfield; +} seqnum_t; + +typedef struct { + dtls_compression_t compression; /**< compression method */ + + dtls_cipher_t cipher; /**< cipher type */ + uint16_t epoch; /**< counter for cipher state changes*/ + uint64_t rseq; /**< sequence number of last record sent */ + + /** + * The key block generated from PRF applied to client and server + * random bytes. The actual size is given by the selected cipher and + * can be calculated using dtls_kb_size(). Use \c dtls_kb_ macros to + * access the components of the key block. + */ + uint8 key_block[MAX_KEYBLOCK_LENGTH]; + + seqnum_t cseq; /**key_block) +#define dtls_kb_server_mac_secret(Param, Role) \ + (dtls_kb_client_mac_secret(Param, Role) + DTLS_MAC_KEY_LENGTH) +#define dtls_kb_remote_mac_secret(Param, Role) \ + ((Role) == DTLS_SERVER \ + ? dtls_kb_client_mac_secret(Param, Role) \ + : dtls_kb_server_mac_secret(Param, Role)) +#define dtls_kb_local_mac_secret(Param, Role) \ + ((Role) == DTLS_CLIENT \ + ? dtls_kb_client_mac_secret(Param, Role) \ + : dtls_kb_server_mac_secret(Param, Role)) +#define dtls_kb_mac_secret_size(Param, Role) DTLS_MAC_KEY_LENGTH +#define dtls_kb_client_write_key(Param, Role) \ + (dtls_kb_server_mac_secret(Param, Role) + DTLS_MAC_KEY_LENGTH) +#define dtls_kb_server_write_key(Param, Role) \ + (dtls_kb_client_write_key(Param, Role) + DTLS_KEY_LENGTH) +#define dtls_kb_remote_write_key(Param, Role) \ + ((Role) == DTLS_SERVER \ + ? dtls_kb_client_write_key(Param, Role) \ + : dtls_kb_server_write_key(Param, Role)) +#define dtls_kb_local_write_key(Param, Role) \ + ((Role) == DTLS_CLIENT \ + ? dtls_kb_client_write_key(Param, Role) \ + : dtls_kb_server_write_key(Param, Role)) +#define dtls_kb_key_size(Param, Role) DTLS_KEY_LENGTH +#define dtls_kb_client_iv(Param, Role) \ + (dtls_kb_server_write_key(Param, Role) + DTLS_KEY_LENGTH) +#define dtls_kb_server_iv(Param, Role) \ + (dtls_kb_client_iv(Param, Role) + DTLS_IV_LENGTH) +#define dtls_kb_remote_iv(Param, Role) \ + ((Role) == DTLS_SERVER \ + ? dtls_kb_client_iv(Param, Role) \ + : dtls_kb_server_iv(Param, Role)) +#define dtls_kb_local_iv(Param, Role) \ + ((Role) == DTLS_CLIENT \ + ? dtls_kb_client_iv(Param, Role) \ + : dtls_kb_server_iv(Param, Role)) +#define dtls_kb_iv_size(Param, Role) DTLS_IV_LENGTH + +#define dtls_kb_size(Param, Role) \ + (2 * (dtls_kb_mac_secret_size(Param, Role) + \ + dtls_kb_key_size(Param, Role) + dtls_kb_iv_size(Param, Role))) + +/* just for consistency */ +#define dtls_kb_digest_size(Param, Role) DTLS_MAC_LENGTH + +/** + * Expands the secret and key to a block of DTLS_HMAC_MAX + * size according to the algorithm specified in section 5 of + * RFC 4346. + * + * \param h Identifier of the hash function to use. + * \param key The secret. + * \param keylen Length of \p key. + * \param seed The seed. + * \param seedlen Length of \p seed. + * \param buf Output buffer where the result is XORed into + * The buffe must be capable to hold at least + * \p buflen bytes. + * \return The actual number of bytes written to \p buf or 0 + * on error. + */ +size_t dtls_p_hash(dtls_hashfunc_t h, + const unsigned char *key, size_t keylen, + const unsigned char *label, size_t labellen, + const unsigned char *random1, size_t random1len, + const unsigned char *random2, size_t random2len, + unsigned char *buf, size_t buflen); + +/** + * This function implements the TLS PRF for DTLS_VERSION. For version + * 1.0, the PRF is P_MD5 ^ P_SHA1 while version 1.2 uses + * P_SHA256. Currently, the actual PRF is selected at compile time. + */ +size_t dtls_prf(const unsigned char *key, size_t keylen, + const unsigned char *label, size_t labellen, + const unsigned char *random1, size_t random1len, + const unsigned char *random2, size_t random2len, + unsigned char *buf, size_t buflen); + +/** + * Calculates MAC for record + cleartext packet and places the result + * in \p buf. The given \p hmac_ctx must be initialized with the HMAC + * function to use and the proper secret. As the DTLS mac calculation + * requires data from the record header, \p record must point to a + * buffer of at least \c sizeof(dtls_record_header_t) bytes. Usually, + * the remaining packet will be encrypted, therefore, the cleartext + * is passed separately in \p packet. + * + * \param hmac_ctx The HMAC context to use for MAC calculation. + * \param record The record header. + * \param packet Cleartext payload to apply the MAC to. + * \param length Size of \p packet. + * \param buf A result buffer that is large enough to hold + * the generated digest. + */ +void dtls_mac(dtls_hmac_context_t *hmac_ctx, + const unsigned char *record, + const unsigned char *packet, size_t length, + unsigned char *buf); + +/** + * Represents AEAD parameters for dtls_encrypt_params(). + */ +typedef struct { + const uint8_t *nonce; /**< must be exactly 15 - l bytes */ + uint8_t tag_length; /**< the MAC tag length (M) */ + uint8_t l; /**< number of bytes in the length + * field (L) */ +} dtls_ccm_params_t; + +/** + * Encrypts the specified \p src of given \p length, writing the + * result to \p buf. The cipher implementation may add more data to + * the result buffer such as an initialization vector or padding + * (e.g. for block ciphers in CBC mode). The caller therefore must + * ensure that \p buf provides sufficient storage to hold the result. + * Usually this means ( 2 + \p length / blocksize ) * blocksize. The + * function returns a value less than zero on error or otherwise the + * number of bytes written. The provided \p src and \p buf may overlap. + * + * \param params AEAD parameters: Nonce, M and L. + * \param src The data to encrypt. + * \param length The actual size of of \p src. + * \param buf The result buffer. + * \param aad additional data for AEAD ciphers + * \param aad_length actual size of @p aad + * \return The number of encrypted bytes on success, less than zero + * otherwise. + */ +int dtls_encrypt_params(const dtls_ccm_params_t *params, + const unsigned char *src, size_t length, + unsigned char *buf, + const unsigned char *key, size_t keylen, + const unsigned char *aad, size_t aad_length); + +/** + * Encrypts the specified \p src of given \p length, writing the + * result to \p buf. The cipher implementation may add more data to + * the result buffer such as an initialization vector or padding + * (e.g. for block ciphers in CBC mode). The caller therefore must + * ensure that \p buf provides sufficient storage to hold the result. + * Usually this means ( 2 + \p length / blocksize ) * blocksize. The + * function returns a value less than zero on error or otherwise the + * number of bytes written. The provided \p src and \p buf may overlap. + * + * \param src The data to encrypt. + * \param length The actual size of of \p src. + * \param buf The result buffer. + * \param nonce The nonce used for encryption. Must be exactly 13 + * bytes, because L is set to 2. + * \param aad additional data for AEAD ciphers + * \param aad_length actual size of @p aad + * \return The number of encrypted bytes on success, less than zero + * otherwise. + * + * \deprecated dtls_encrypt() always sets M=8, L=2. Use + * dtls_encrypt_params() instead. + */ +int dtls_encrypt(const unsigned char *src, size_t length, + unsigned char *buf, + const unsigned char *nonce, + const unsigned char *key, size_t keylen, + const unsigned char *aad, size_t aad_length); + +/** + * Decrypts the given buffer \p src of given \p length, writing the + * result to \p buf. The function returns \c -1 in case of an error, + * or the number of bytes written. Note that for block ciphers, \p + * length must be a multiple of the cipher's block size. A return + * value between \c 0 and the actual length indicates that only \c n-1 + * block have been processed. The provided \p src and \p buf may overlap. + * + * \param params AEAD parameters: Nonce, M and L. + * \param src The buffer to decrypt. + * \param length The length of the input buffer. + * \param buf The result buffer. + * \param aad additional authentication data for AEAD ciphers + * \param aad_length actual size of @p aad + * \return Less than zero on error, the number of decrypted bytes + * otherwise. + */ +int dtls_decrypt_params(const dtls_ccm_params_t *params, + const unsigned char *src, size_t length, + unsigned char *buf, + const unsigned char *key, size_t keylen, + const unsigned char *aad, size_t aad_length); + +/** + * Decrypts the given buffer \p src of given \p length, writing the + * result to \p buf. The function returns \c -1 in case of an error, + * or the number of bytes written. Note that for block ciphers, \p + * length must be a multiple of the cipher's block size. A return + * value between \c 0 and the actual length indicates that only \c n-1 + * block have been processed. The provided \p src and \p buf may overlap. + * + * \param src The buffer to decrypt. + * \param length The length of the input buffer. + * \param buf The result buffer. + * \param nonce The nonce used for encryption. Must be exactly 13 + * bytes, because L is set to 2. + * \param aad additional authentication data for AEAD ciphers + * \param aad_length actual size of @p aad + * \return Less than zero on error, the number of decrypted bytes + * otherwise. + * + * \deprecated dtls_decrypt() always sets M=8, L=2. Use + * dtls_decrypt_params() instead. + */ +int dtls_decrypt(const unsigned char *src, size_t length, + unsigned char *buf, + const unsigned char *nonce, + const unsigned char *key, size_t keylen, + const unsigned char *a_data, size_t a_data_length); + +/* helper functions */ + +/** + * Generates pre_master_sercet from given PSK and fills the result + * according to the "plain PSK" case in section 2 of RFC 4279. + * Diffie-Hellman and RSA key exchange are currently not supported. + * + * @param key The shared key. + * @param keylen Length of @p key in bytes. + * @param result The derived pre master secret. + * @return The actual length of @p result. + */ +int dtls_psk_pre_master_secret(unsigned char *key, size_t keylen, + unsigned char *result, size_t result_len); + +#define DTLS_EC_KEY_SIZE 32 + +int dtls_ecdh_pre_master_secret(unsigned char *priv_key, + unsigned char *pub_key_x, + unsigned char *pub_key_y, + size_t key_size, + unsigned char *result, + size_t result_len); + +void dtls_ecdsa_generate_key(unsigned char *priv_key, + unsigned char *pub_key_x, + unsigned char *pub_key_y, + size_t key_size); + +void dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size, + const unsigned char *sign_hash, size_t sign_hash_size, + uint32_t point_r[9], uint32_t point_s[9]); + +void dtls_ecdsa_create_sig(const unsigned char *priv_key, size_t key_size, + const unsigned char *client_random, size_t client_random_size, + const unsigned char *server_random, size_t server_random_size, + const unsigned char *keyx_params, size_t keyx_params_size, + uint32_t point_r[9], uint32_t point_s[9]); + +int dtls_ecdsa_verify_sig_hash(const unsigned char *pub_key_x, + const unsigned char *pub_key_y, size_t key_size, + const unsigned char *sign_hash, size_t sign_hash_size, + unsigned char *result_r, unsigned char *result_s); + +int dtls_ecdsa_verify_sig(const unsigned char *pub_key_x, + const unsigned char *pub_key_y, size_t key_size, + const unsigned char *client_random, size_t client_random_size, + const unsigned char *server_random, size_t server_random_size, + const unsigned char *keyx_params, size_t keyx_params_size, + unsigned char *result_r, unsigned char *result_s); + +int dtls_ec_key_asn1_from_uint32(const uint32_t *key, size_t key_size, + unsigned char *buf); + + +dtls_handshake_parameters_t *dtls_handshake_new(void); + +void dtls_handshake_free(dtls_handshake_parameters_t *handshake); + +dtls_security_parameters_t *dtls_security_new(void); + +void dtls_security_free(dtls_security_parameters_t *security); +void crypto_init(void); + +#endif /* _DTLS_CRYPTO_H_ */ + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/doc/Doxyfile.in b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/doc/Doxyfile.in new file mode 100644 index 000000000..9f7ffdf59 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/doc/Doxyfile.in @@ -0,0 +1,1551 @@ +# Doxyfile 1.6.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = @PACKAGE_NAME@ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = .. + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DSRV_NO_DTLS DSRV_NO_PROTOCOL_DEMUX + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/doc/DoxygenLayout.xml b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/doc/DoxygenLayout.xml new file mode 100644 index 000000000..1c8525c36 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/doc/DoxygenLayout.xml @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls.c new file mode 100644 index 000000000..8552a00e2 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls.c @@ -0,0 +1,4780 @@ +/******************************************************************************* + * + * Copyright (c) 2011-2021 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * Achim Kraus - session recovery + * Sachin Agrawal - rehandshake support + * + *******************************************************************************/ + +#include "tinydtls.h" +#include "dtls_time.h" + +#include +#include +#ifdef HAVE_ASSERT_H +#include +#endif +#ifndef WITH_CONTIKI +#include +#include "global.h" +#endif /* WITH_CONTIKI */ +#ifdef HAVE_INTTYPES_H +#define __STDC_FORMAT_MACROS +#include +#else +# ifndef PRIu64 +# define PRIu64 "llu" +# endif +# ifndef PRIx64 +# define PRIx64 "llx" +# endif +#endif /* HAVE_INTTYPES_H */ + +#include "utlist.h" +#ifndef DTLS_PEERS_NOHASH +#include "uthash.h" +#endif /* DTLS_PEERS_NOHASH */ + +#include "dtls_debug.h" +#include "numeric.h" +#include "netq.h" +#include "dtls.h" + +#include "alert.h" +#include "session.h" +#include "dtls_prng.h" +#include "dtls_mutex.h" + +#ifdef WITH_SHA256 +# include "hmac.h" +#endif /* WITH_SHA256 */ + +#ifdef WITH_ZEPHYR +LOG_MODULE_DECLARE(TINYDTLS, CONFIG_TINYDTLS_LOG_LEVEL); +#endif /* WITH_ZEPHYR */ + +#define DTLS10_VERSION 0xfeff + +/* Flags for dtls_destroy_peer() + * + * DTLS_DESTROY_CLOSE indicates that the connection should be closed + * when applicable + */ +#define DTLS_DESTROY_CLOSE 0x02 + +#ifdef RIOT_VERSION +# include + +dtls_context_t dtlscontext_storage_data[DTLS_CONTEXT_MAX]; +memarray_t dtlscontext_storage; +#endif /* RIOT_VERSION */ + +#define dtls_set_version(H,V) dtls_int_to_uint16((H)->version, (V)) +#define dtls_set_content_type(H,V) ((H)->content_type = (V) & 0xff) +#define dtls_set_length(H,V) ((H)->length = (V)) + +#define dtls_get_content_type(H) ((H)->content_type & 0xff) +#define dtls_get_version(H) dtls_uint16_to_int((H)->version) +#define dtls_get_epoch(H) dtls_uint16_to_int((H)->epoch) +#define dtls_get_sequence_number(H) dtls_uint48_to_ulong((H)->sequence_number) +#define dtls_get_fragment_length(H) dtls_uint24_to_int((H)->fragment_length) + +#ifdef DTLS_PEERS_NOHASH +#define FIND_PEER(head,sess,out) \ + do { \ + dtls_peer_t * tmp; \ + (out) = NULL; \ + LL_FOREACH((head), tmp) { \ + if (dtls_session_equals(&tmp->session, (sess))) { \ + (out) = tmp; \ + break; \ + } \ + } \ + } while (0) +#define DEL_PEER(head,delptr) \ + if ((head) != NULL && (delptr) != NULL) { \ + LL_DELETE(head,delptr); \ + } +#define ADD_PEER(head,sess,add) \ + LL_PREPEND(ctx->peers, peer); +#else /* DTLS_PEERS_NOHASH */ +#define FIND_PEER(head,sess,out) \ + HASH_FIND(hh,head,sess,sizeof(session_t),out) +#define ADD_PEER(head,sess,add) \ + HASH_ADD(hh,head,sess,sizeof(session_t),add) +#define DEL_PEER(head,delptr) \ + if ((head) != NULL && (delptr) != NULL) { \ + HASH_DELETE(hh,head,delptr); \ + } +#endif /* DTLS_PEERS_NOHASH */ + +#define DTLS_RH_LENGTH sizeof(dtls_record_header_t) +#define DTLS_HS_LENGTH sizeof(dtls_handshake_header_t) +#define DTLS_CH_LENGTH sizeof(dtls_client_hello_t) /* no variable length fields! */ +#define DTLS_COOKIE_LENGTH_MAX 32 +#define DTLS_CH_LENGTH_MAX sizeof(dtls_client_hello_t) + DTLS_COOKIE_LENGTH_MAX + 12 + 26 + 12 +#define DTLS_HV_LENGTH sizeof(dtls_hello_verify_t) +#define DTLS_SH_LENGTH (2 + DTLS_RANDOM_LENGTH + 1 + 2 + 1) +#define DTLS_SKEXEC_LENGTH (1 + 2 + 1 + 1 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE + 1 + 1 + 2 + 70) +#define DTLS_SKEXECPSK_LENGTH_MIN 2 +#define DTLS_SKEXECPSK_LENGTH_MAX 2 + DTLS_PSK_MAX_CLIENT_IDENTITY_LEN +#define DTLS_CKXPSK_LENGTH_MIN 2 +#define DTLS_CKXEC_LENGTH (1 + 1 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE) +#define DTLS_CV_LENGTH (1 + 1 + 2 + 1 + 1 + 1 + 1 + DTLS_EC_KEY_SIZE + 1 + 1 + DTLS_EC_KEY_SIZE) +#define DTLS_FIN_LENGTH 12 + +#define DTLS_ALERT_LENGTH 2 /* length of the Alert message */ + +#define HS_HDR_LENGTH DTLS_RH_LENGTH + DTLS_HS_LENGTH +#define HV_HDR_LENGTH HS_HDR_LENGTH + DTLS_HV_LENGTH + +#define HIGH(V) (((V) >> 8) & 0xff) +#define LOW(V) ((V) & 0xff) + +#define DTLS_RECORD_HEADER(M) ((dtls_record_header_t *)(M)) +#define DTLS_HANDSHAKE_HEADER(M) ((dtls_handshake_header_t *)(M)) + +#define HANDSHAKE(M) ((dtls_handshake_header_t *)((M) + DTLS_RH_LENGTH)) +#define CLIENTHELLO(M) ((dtls_client_hello_t *)((M) + HS_HDR_LENGTH)) + +/* The length check here should work because dtls_*_to_int() works on + * unsigned char. Otherwise, broken messages could cause severe + * trouble. Note that this macro jumps out of the current program flow + * when the message is too short. Beware! + */ +#define SKIP_VAR_FIELD(P,L,T) { \ + if (L < dtls_ ## T ## _to_int(P) + sizeof(T)) \ + goto error; \ + L -= dtls_ ## T ## _to_int(P) + sizeof(T); \ + P += dtls_ ## T ## _to_int(P) + sizeof(T); \ + } + +/* some constants for the PRF */ +#define PRF_LABEL(Label) prf_label_##Label +#define PRF_LABEL_SIZE(Label) (sizeof(PRF_LABEL(Label)) - 1) + +static const unsigned char prf_label_master[] = "master secret"; +static const unsigned char prf_label_extended_master[] = "extended master secret"; +static const unsigned char prf_label_key[] = "key expansion"; +static const unsigned char prf_label_client[] = "client"; +static const unsigned char prf_label_server[] = "server"; +static const unsigned char prf_label_finished[] = " finished"; + +#ifdef DTLS_ECC +/* first part of Raw public key, the is the start of the Subject Public Key */ +static const unsigned char cert_asn1_header[] = { + 0x30, 0x59, /* SEQUENCE, length 89 bytes */ + 0x30, 0x13, /* SEQUENCE, length 19 bytes */ + 0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */ + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, + 0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */ + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, + 0x03, 0x42, 0x00, /* BIT STRING, length 66 bytes, 0 bits unused */ + 0x04 /* uncompressed, followed by the r und s values of the public key */ +}; +#endif /* DTLS_ECC */ + +#ifdef WITH_CONTIKI + +PROCESS(dtls_retransmit_process, "DTLS retransmit process"); + +static dtls_context_t the_dtls_context; + +static inline dtls_context_t * +malloc_context(void) { + return &the_dtls_context; +} + +static inline void +free_context(dtls_context_t *context) { +} + +#endif /* WITH_CONTIKI */ + +#ifdef RIOT_VERSION +static inline dtls_context_t * +malloc_context(void) { + return (dtls_context_t *) memarray_alloc(&dtlscontext_storage); +} + +static inline void free_context(dtls_context_t *context) { + memarray_free(&dtlscontext_storage, context); +} +#endif /* RIOT_VERSION */ + +#ifdef WITH_POSIX + +static inline dtls_context_t * +malloc_context(void) { + return (dtls_context_t *)malloc(sizeof(dtls_context_t)); +} + +static inline void +free_context(dtls_context_t *context) { + free(context); +} + +#endif /* WITH_POSIX */ + +void +dtls_init(void) { + dtls_clock_init(); + crypto_init(); + netq_init(); + peer_init(); + +#ifdef RIOT_VERSION +memarray_init(&dtlscontext_storage, dtlscontext_storage_data, + sizeof(dtls_context_t), DTLS_CONTEXT_MAX); +#endif /* RIOT_VERSION */ +} + +/* Calls cb_alert() with given arguments if defined, otherwise an + * error message is logged and the result is -1. This is just an + * internal helper. + */ +#define CALL(Context, which, ...) \ + ((Context)->h && (Context)->h->which \ + ? (Context)->h->which((Context), ##__VA_ARGS__) \ + : -1) + +static int +dtls_send_multi(dtls_context_t *ctx, dtls_peer_t *peer, + dtls_security_parameters_t *security , session_t *session, + unsigned char type, uint8 *buf_array[], + size_t buf_len_array[], size_t buf_array_len); + +static int +handle_alert(dtls_context_t *ctx, dtls_peer_t *peer, + uint8 *record_header, uint8 *data, size_t data_length); + +/** + * Sends the fragment of length \p buflen given in \p buf to the + * specified \p peer. The data will be MAC-protected and encrypted + * according to the selected cipher and split into one or more DTLS + * records of the specified \p type. This function returns the number + * of bytes that were sent, or \c -1 if an error occurred. + * + * \param ctx The DTLS context to use. + * \param peer The remote peer. + * \param type The content type of the record. + * \param buf The data to send. + * \param buflen The actual length of \p buf. + * \return Less than zero on error, the number of bytes written otherwise. + */ +static int +dtls_send(dtls_context_t *ctx, dtls_peer_t *peer, unsigned char type, + uint8 *buf, size_t buflen) { + return dtls_send_multi(ctx, peer, dtls_security_params(peer), &peer->session, + type, &buf, &buflen, 1); +} + +/** + * Stops ongoing retransmissions of handshake messages for @p peer. + */ +static void dtls_stop_retransmission(dtls_context_t *context, dtls_peer_t *peer); + +dtls_peer_t * +dtls_get_peer(const dtls_context_t *ctx, const session_t *session) { + dtls_peer_t *p; + FIND_PEER(ctx->peers, session, p); + return p; +} + +/** + * Adds @p peer to list of peers in @p ctx. This function returns @c 0 + * on success, or a negative value on error (e.g. due to insufficient + * storage). + */ +static int +dtls_add_peer(dtls_context_t *ctx, dtls_peer_t *peer) { + ADD_PEER(ctx->peers, session, peer); + return 0; +} + +int +dtls_write(struct dtls_context_t *ctx, + session_t *dst, uint8 *buf, size_t len) { + + dtls_peer_t *peer = dtls_get_peer(ctx, dst); + + /* Check if peer connection already exists */ + if (!peer) { /* no ==> create one */ + int res; + + /* dtls_connect() returns a value greater than zero if a new + * connection attempt is made, 0 for session reuse. */ + res = dtls_connect(ctx, dst); + + return (res >= 0) ? 0 : res; + } else { /* a session exists, check if it is in state connected */ + + if (peer->state != DTLS_STATE_CONNECTED) { + return 0; + } else { + return dtls_send(ctx, peer, DTLS_CT_APPLICATION_DATA, buf, len); + } + } +} + +static int +dtls_get_cookie(uint8 *msg, size_t msglen, uint8 **cookie) { + /* To access the cookie, we have to determine the session id's + * length and skip the whole thing. */ + if (msglen < DTLS_HS_LENGTH + DTLS_CH_LENGTH + sizeof(uint8)) + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + + if (dtls_uint16_to_int(msg + DTLS_HS_LENGTH) != DTLS_VERSION) + return dtls_alert_fatal_create(DTLS_ALERT_PROTOCOL_VERSION); + + msglen -= DTLS_HS_LENGTH + DTLS_CH_LENGTH; + msg += DTLS_HS_LENGTH + DTLS_CH_LENGTH; + + SKIP_VAR_FIELD(msg, msglen, uint8); /* skip session id */ + + if (msglen < (*msg & 0xff) + sizeof(uint8)) + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + + *cookie = msg + sizeof(uint8); + return dtls_uint8_to_int(msg); + + error: + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); +} + +static int +dtls_create_cookie(dtls_context_t *ctx, + session_t *session, + uint8 *msg, size_t msglen, + uint8 *cookie, int *clen) { + unsigned char buf[DTLS_HMAC_MAX]; + size_t e, fragment_length; + int len; + + /* create cookie with HMAC-SHA256 over: + * - SECRET + * - session parameters (only IP address?) + * - client version + * - random gmt and bytes + * - session id + * - cipher_suites + * - compression method + */ + + /* Note that the buffer size must fit with the default hash algorithm. */ + + dtls_hmac_context_t hmac_context; + dtls_hmac_init(&hmac_context, ctx->cookie_secret, DTLS_COOKIE_SECRET_LENGTH); + + dtls_hmac_update(&hmac_context, + (unsigned char *)&session->addr, session->size); + + /* feed in the beginning of the Client Hello up to and including the + session id */ + e = DTLS_CH_LENGTH; + if (e + DTLS_HS_LENGTH + sizeof(uint8_t) > msglen) + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + + e += dtls_uint8_to_int(msg + DTLS_HS_LENGTH + e) + sizeof(uint8_t); + + if (e + DTLS_HS_LENGTH > msglen) + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + + dtls_hmac_update(&hmac_context, msg + DTLS_HS_LENGTH, e); + + if (e + DTLS_HS_LENGTH + sizeof(uint8_t) > msglen) + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + /* skip cookie bytes and length byte */ + e += dtls_uint8_to_int(msg + DTLS_HS_LENGTH + e); + e += sizeof(uint8_t); + +#if 0 + /* skip cipher suites */ + if (e + DTLS_HS_LENGTH + sizeof(uint16_t) > msglen) + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + e += dtls_uint16_to_int(msg + DTLS_HS_LENGTH + e); + e += sizeof(uint16_t); + + /* skip compression methods */ + if (e + DTLS_HS_LENGTH + sizeof(uint8_t) > msglen) + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + e += dtls_uint8_to_int(msg + DTLS_HS_LENGTH + e); + e += sizeof(uint8_t); +#endif + + /* read fragment length and check for consistency */ + fragment_length = dtls_get_fragment_length(DTLS_HANDSHAKE_HEADER(msg)); + if ((fragment_length < e) || (e + DTLS_HS_LENGTH) > msglen) + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + + dtls_hmac_update(&hmac_context, + msg + DTLS_HS_LENGTH + e, + fragment_length - e); + + len = dtls_hmac_finalize(&hmac_context, buf); + + if (len < *clen) { + memset(cookie + len, 0, *clen - len); + *clen = len; + } + + memcpy(cookie, buf, *clen); + return 0; +} + +#ifdef DTLS_CHECK_CONTENTTYPE +/* used to check if a received datagram contains a DTLS message */ +static char const content_types[] = { + DTLS_CT_CHANGE_CIPHER_SPEC, + DTLS_CT_ALERT, + DTLS_CT_HANDSHAKE, + DTLS_CT_APPLICATION_DATA, + 0 /* end marker */ +}; + +/** + * Checks if the content type of \p msg is known. This function returns + * the found content type, or 0 otherwise. + */ +static int +known_content_type(const uint8_t *msg) { + unsigned int n; + assert(msg); + + for (n = 0; (content_types[n] != 0) && (content_types[n]) != msg[0]; n++) + ; + return content_types[n]; +} +#else /* DTLS_CHECK_CONTENTTYPE */ +static int +known_content_type(const uint8_t *msg) { + return msg[0]; +} +#endif /* DTLS_CHECK_CONTENTTYPE */ + +/** + * Checks if \p msg points to a valid DTLS record. If + * + */ +static unsigned int +is_record(uint8 *msg, size_t msglen) { + unsigned int rlen = 0; + + if (msglen >= DTLS_RH_LENGTH) { /* FIXME allow empty records? */ + uint16_t version = dtls_uint16_to_int(msg + 1); + if ((((version == DTLS_VERSION) || (version == DTLS10_VERSION)) + && known_content_type(msg))) { + rlen = DTLS_RH_LENGTH + + dtls_uint16_to_int(DTLS_RECORD_HEADER(msg)->length); + + /* we do not accept wrong length field in record header */ + if (rlen > msglen) + rlen = 0; + } + } + + return rlen; +} + +/** + * Initializes \p buf as record header. The caller must ensure that \p + * buf is capable of holding at least \c sizeof(dtls_record_header_t) + * bytes. Increments records sequence number counter. + * \return pointer to the next byte after the written header. + * The length will be set to 0 and has to be changed before sending. + */ +static inline uint8 * +dtls_set_record_header(uint8 type, + uint16_t epoch, + uint64_t *rseqn, + uint8 *buf) { + dtls_int_to_uint8(buf, type); + buf += sizeof(uint8); + + dtls_int_to_uint16(buf, DTLS_VERSION); + buf += sizeof(uint16); + + dtls_int_to_uint16(buf, epoch); + buf += sizeof(uint16); + + dtls_int_to_uint48(buf, *rseqn); + buf += sizeof(uint48); + + /* increment record sequence counter by 1 */ + (*rseqn)++; + + /* space for record size */ + memset(buf, 0, sizeof(uint16)); + return buf + sizeof(uint16); +} + +/** + * Initializes \p buf as handshake header. The caller must ensure that \p + * buf is capable of holding at least \c sizeof(dtls_handshake_header_t) + * bytes. Increments message sequence number counter. + * \return pointer to the next byte after \p buf + */ +static inline uint8 * +dtls_set_handshake_header(uint8 type, + uint16_t *mseqn, + int length, + int frag_offset, int frag_length, + uint8 *buf) { + + dtls_int_to_uint8(buf, type); + buf += sizeof(uint8); + + dtls_int_to_uint24(buf, length); + buf += sizeof(uint24); + + /* and copy the result to buf */ + dtls_int_to_uint16(buf, *mseqn); + buf += sizeof(uint16); + + /* increment handshake message sequence counter by 1 */ + (*mseqn)++; + + dtls_int_to_uint24(buf, frag_offset); + buf += sizeof(uint24); + + dtls_int_to_uint24(buf, frag_length); + buf += sizeof(uint24); + + return buf; +} + +/** only one compression method is currently defined */ +static uint8 compression_methods[] = { + TLS_COMPRESSION_NULL +}; + +/** returns true if the cipher matches TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */ +static inline int is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(dtls_cipher_t cipher) +{ +#ifdef DTLS_ECC + return cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; +#else + (void) cipher; + return 0; +#endif /* DTLS_ECC */ +} + +/** returns true if the cipher matches TLS_PSK_WITH_AES_128_CCM_8 */ +static inline int is_tls_psk_with_aes_128_ccm_8(dtls_cipher_t cipher) +{ + (void) cipher; + +#ifdef DTLS_PSK + return cipher == TLS_PSK_WITH_AES_128_CCM_8; +#else + return 0; +#endif /* DTLS_PSK */ +} + +/** returns true if the application is configured for psk */ +static inline int is_psk_supported(dtls_context_t *ctx) +{ +#ifdef DTLS_PSK + return ctx && ctx->h && ctx->h->get_psk_info; +#else + (void) ctx; + return 0; +#endif /* DTLS_PSK */ +} + +/** returns true if the application is configured for ecdhe_ecdsa */ +static inline int is_ecdsa_supported(dtls_context_t *ctx, int is_client) +{ +#ifdef DTLS_ECC + return ctx && ctx->h && ((!is_client && ctx->h->get_ecdsa_key) || + (is_client && ctx->h->verify_ecdsa_key)); +#else + (void) ctx; + (void) is_client; + return 0; +#endif /* DTLS_ECC */ +} + +/** Returns true if the application is configured for ecdhe_ecdsa with + * client authentication */ +static inline int is_ecdsa_client_auth_supported(dtls_context_t *ctx) +{ +#ifdef DTLS_ECC + return ctx && ctx->h && ctx->h->get_ecdsa_key && ctx->h->verify_ecdsa_key; +#else + (void) ctx; + return 0; +#endif /* DTLS_ECC */ +} + +/** + * Returns @c 1 if @p code is a cipher suite other than @c + * TLS_NULL_WITH_NULL_NULL that we recognize. + * + * @param ctx The current DTLS context + * @param code The cipher suite identifier to check + * @param is_client 1 for a dtls client, 0 for server + * @return @c 1 iff @p code is recognized, + */ +static int +known_cipher(dtls_context_t *ctx, dtls_cipher_t code, int is_client) { + int psk; + int ecdsa; + + psk = is_psk_supported(ctx); + ecdsa = is_ecdsa_supported(ctx, is_client); + return (psk && is_tls_psk_with_aes_128_ccm_8(code)) || + (ecdsa && is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(code)); +} + +/** Dump out the cipher keys and IVs used for the symmetric cipher. */ +static void dtls_debug_keyblock(dtls_security_parameters_t *config) +{ + dtls_debug("key_block (%d bytes):\n", dtls_kb_size(config, peer->role)); + dtls_debug_dump(" client_MAC_secret", + dtls_kb_client_mac_secret(config, peer->role), + dtls_kb_mac_secret_size(config, peer->role)); + + dtls_debug_dump(" server_MAC_secret", + dtls_kb_server_mac_secret(config, peer->role), + dtls_kb_mac_secret_size(config, peer->role)); + + dtls_debug_dump(" client_write_key", + dtls_kb_client_write_key(config, peer->role), + dtls_kb_key_size(config, peer->role)); + + dtls_debug_dump(" server_write_key", + dtls_kb_server_write_key(config, peer->role), + dtls_kb_key_size(config, peer->role)); + + dtls_debug_dump(" client_IV", + dtls_kb_client_iv(config, peer->role), + dtls_kb_iv_size(config, peer->role)); + + dtls_debug_dump(" server_IV", + dtls_kb_server_iv(config, peer->role), + dtls_kb_iv_size(config, peer->role)); +} + +/** returns the name of the given handshake type number. + * see IANA for a full list of types: + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-7 + */ +static const char * +dtls_handshake_type_to_name(int type) +{ + switch (type) { + case DTLS_HT_HELLO_REQUEST: + return "hello_request"; + case DTLS_HT_CLIENT_HELLO: + return "client_hello"; + case DTLS_HT_SERVER_HELLO: + return "server_hello"; + case DTLS_HT_HELLO_VERIFY_REQUEST: + return "hello_verify_request"; + case DTLS_HT_CERTIFICATE: + return "certificate"; + case DTLS_HT_SERVER_KEY_EXCHANGE: + return "server_key_exchange"; + case DTLS_HT_CERTIFICATE_REQUEST: + return "certificate_request"; + case DTLS_HT_SERVER_HELLO_DONE: + return "server_hello_done"; + case DTLS_HT_CERTIFICATE_VERIFY: + return "certificate_verify"; + case DTLS_HT_CLIENT_KEY_EXCHANGE: + return "client_key_exchange"; + case DTLS_HT_FINISHED: + return "finished"; + default: + return "unknown"; + } +} + +static const char * +dtls_message_type_to_name(int type) +{ + switch (type) { + case DTLS_CT_CHANGE_CIPHER_SPEC: + return "change_cipher_spec"; + case DTLS_CT_ALERT: + return "alert"; + case DTLS_CT_HANDSHAKE: + return "handshake"; + case DTLS_CT_APPLICATION_DATA: + return "application_data"; + default: + return NULL; + } +} + + +/** + * Calculate the pre master secret and after that calculate the master-secret. + */ +static int +calculate_key_block(dtls_context_t *ctx, + dtls_handshake_parameters_t *handshake, + dtls_peer_t *peer, + session_t *session, + dtls_peer_type role) { + (void) ctx; + (void) session; + unsigned char *pre_master_secret; + int pre_master_len = 0; + dtls_security_parameters_t *security = dtls_security_params_next(peer); + uint8 master_secret[DTLS_MASTER_SECRET_LENGTH]; + (void)role; /* The macro dtls_kb_size() does not use role. */ + + if (!security) { + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + pre_master_secret = security->key_block; + + switch (handshake->cipher) { +#ifdef DTLS_PSK + case TLS_PSK_WITH_AES_128_CCM_8: { + unsigned char psk[DTLS_PSK_MAX_KEY_LEN]; + int len; + + len = CALL(ctx, get_psk_info, session, DTLS_PSK_KEY, + handshake->keyx.psk.identity, + handshake->keyx.psk.id_length, + psk, DTLS_PSK_MAX_KEY_LEN); + if (len < 0) { + dtls_crit("no psk key for session available\n"); + return len; + } + /* Temporarily use the key_block storage space for the pre master secret. */ + pre_master_len = dtls_psk_pre_master_secret(psk, len, + pre_master_secret, + MAX_KEYBLOCK_LENGTH); + + dtls_debug_hexdump("psk", psk, len); + + memset(psk, 0, DTLS_PSK_MAX_KEY_LEN); + if (pre_master_len < 0) { + dtls_crit("the psk was too long, for the pre master secret\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + break; + } +#endif /* DTLS_PSK */ +#ifdef DTLS_ECC + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: { + pre_master_len = dtls_ecdh_pre_master_secret(handshake->keyx.ecdsa.own_eph_priv, + handshake->keyx.ecdsa.other_eph_pub_x, + handshake->keyx.ecdsa.other_eph_pub_y, + sizeof(handshake->keyx.ecdsa.own_eph_priv), + pre_master_secret, + MAX_KEYBLOCK_LENGTH); + if (pre_master_len < 0) { + dtls_crit("the curve was too long, for the pre master secret\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + break; + } +#endif /* DTLS_ECC */ + case TLS_NULL_WITH_NULL_NULL: + assert(!"calculate_key_block: tried to use NULL cipher\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INSUFFICIENT_SECURITY); + + /* The following cases cover the enum symbols that are not + * included in this build. These must be kept just above the + * default case as they do nothing but fall through. + */ +#ifndef DTLS_PSK + case TLS_PSK_WITH_AES_128_CCM_8: + /* fall through to default */ +#endif /* !DTLS_PSK */ + +#ifndef DTLS_ECC + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + /* fall through to default */ +#endif /* !DTLS_ECC */ + + default: + dtls_crit("calculate_key_block: unknown cipher %04x\n", handshake->cipher); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + dtls_debug_dump("client_random", handshake->tmp.random.client, DTLS_RANDOM_LENGTH); + dtls_debug_dump("server_random", handshake->tmp.random.server, DTLS_RANDOM_LENGTH); + dtls_debug_dump("pre_master_secret", pre_master_secret, pre_master_len); + + if (handshake->extended_master_secret) { + unsigned char sha256hash[DTLS_HMAC_DIGEST_SIZE]; + + dtls_hash_finalize(sha256hash, &peer->handshake_params->hs_state.ext_hash); + + dtls_prf(pre_master_secret, pre_master_len, + PRF_LABEL(extended_master), PRF_LABEL_SIZE(extended_master), + sha256hash, sizeof(sha256hash), + NULL, 0, + master_secret, + DTLS_MASTER_SECRET_LENGTH); + + dtls_debug_dump("extended_master_secret", master_secret, DTLS_MASTER_SECRET_LENGTH); + } + else { + dtls_prf(pre_master_secret, pre_master_len, + PRF_LABEL(master), PRF_LABEL_SIZE(master), + handshake->tmp.random.client, DTLS_RANDOM_LENGTH, + handshake->tmp.random.server, DTLS_RANDOM_LENGTH, + master_secret, + DTLS_MASTER_SECRET_LENGTH); + + dtls_debug_dump("master_secret", master_secret, DTLS_MASTER_SECRET_LENGTH); + } + + /* create key_block from master_secret + * key_block = PRF(master_secret, + "key expansion" + tmp.random.server + tmp.random.client) */ + + dtls_prf(master_secret, + DTLS_MASTER_SECRET_LENGTH, + PRF_LABEL(key), PRF_LABEL_SIZE(key), + handshake->tmp.random.server, DTLS_RANDOM_LENGTH, + handshake->tmp.random.client, DTLS_RANDOM_LENGTH, + security->key_block, + dtls_kb_size(security, role)); + + memcpy(handshake->tmp.master_secret, master_secret, DTLS_MASTER_SECRET_LENGTH); + dtls_debug_keyblock(security); + + security->cipher = handshake->cipher; + security->compression = handshake->compression; + security->rseq = 0; + + return 0; +} + +/* TODO: add a generic method which iterates over a list and searches for a specific key */ +static int verify_ext_eliptic_curves(uint8 *data, size_t data_length) { + int i, curve_name; + + /* length of curve list */ + i = dtls_uint16_to_int(data); + data += sizeof(uint16); + if (i + sizeof(uint16) != data_length) { + dtls_warn("the list of the supported elliptic curves should be tls extension length - 2\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + for (i = data_length - sizeof(uint16); i > 0; i -= sizeof(uint16)) { + /* check if this curve is supported */ + curve_name = dtls_uint16_to_int(data); + data += sizeof(uint16); + + if (curve_name == TLS_EXT_ELLIPTIC_CURVES_SECP256R1) + return 0; + } + + dtls_warn("no supported elliptic curve found\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); +} + +static int verify_ext_cert_type(uint8 *data, size_t data_length) { + int i, cert_type; + + /* length of cert type list */ + i = dtls_uint8_to_int(data); + data += sizeof(uint8); + if (i + sizeof(uint8) != data_length) { + dtls_warn("the list of the supported certificate types should be tls extension length - 1\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + for (i = data_length - sizeof(uint8); i > 0; i -= sizeof(uint8)) { + /* check if this cert type is supported */ + cert_type = dtls_uint8_to_int(data); + data += sizeof(uint8); + + if (cert_type == TLS_CERT_TYPE_RAW_PUBLIC_KEY) + return 0; + } + + dtls_warn("no supported certificate type found\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); +} + +static int verify_ext_ec_point_formats(uint8 *data, size_t data_length) { + int i, cert_type; + + /* length of ec_point_formats list */ + i = dtls_uint8_to_int(data); + data += sizeof(uint8); + if (i + sizeof(uint8) != data_length) { + dtls_warn("the list of the supported ec_point_formats should be tls extension length - 1\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + for (i = data_length - sizeof(uint8); i > 0; i -= sizeof(uint8)) { + /* check if this ec_point_format is supported */ + cert_type = dtls_uint8_to_int(data); + data += sizeof(uint8); + + if (cert_type == TLS_EXT_EC_POINT_FORMATS_UNCOMPRESSED) + return 0; + } + + dtls_warn("no supported ec_point_format found\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); +} + +static int verify_ext_sig_hash_algo(uint8 *data, size_t data_length) { + int i, hash_type, sig_type; + + /* length of sig_hash_algo list */ + i = dtls_uint16_to_int(data); + data += sizeof(uint16); + if (i + sizeof(uint16) != data_length) { + dtls_warn("the list of the supported signature_algorithms should be tls extension length - 2\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + for (i = data_length - sizeof(uint16); i > 0; i -= sizeof(uint16)) { + /* check if this _sig_hash_algo is supported */ + hash_type = dtls_uint8_to_int(data); + data += sizeof(uint8); + sig_type = dtls_uint8_to_int(data); + data += sizeof(uint8); + + if (hash_type == TLS_EXT_SIG_HASH_ALGO_SHA256 && + sig_type == TLS_EXT_SIG_HASH_ALGO_ECDSA) + return 0; + } + + dtls_warn("no supported signature_algorithms found\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); +} + +/* + * Check for some TLS Extensions used by the ECDHE_ECDSA cipher. + */ +static int +dtls_check_tls_extension(dtls_peer_t *peer, + uint8 *data, size_t data_length, int client_hello) +{ + uint16_t i, j; + int ext_elliptic_curve = 0; + int ext_client_cert_type = 0; + int ext_server_cert_type = 0; + int ext_ec_point_formats = 0; + dtls_handshake_parameters_t *handshake = peer->handshake_params; + + if (data_length < sizeof(uint16)) { + /* no tls extensions specified */ + if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher)) { + goto error; + } + return 0; + } + + /* get the length of the tls extension list */ + j = dtls_uint16_to_int(data); + data += sizeof(uint16); + data_length -= sizeof(uint16); + + if (data_length < j) + goto error; + + /* check for TLS extensions needed for this cipher */ + while (data_length) { + if (data_length < sizeof(uint16) * 2) + goto error; + + /* get the tls extension type */ + i = dtls_uint16_to_int(data); + data += sizeof(uint16); + data_length -= sizeof(uint16); + + /* get the length of the tls extension */ + j = dtls_uint16_to_int(data); + data += sizeof(uint16); + data_length -= sizeof(uint16); + + if (data_length < j) + goto error; + + switch (i) { + case TLS_EXT_ELLIPTIC_CURVES: + ext_elliptic_curve = 1; + if (verify_ext_eliptic_curves(data, j)) + goto error; + break; + case TLS_EXT_CLIENT_CERTIFICATE_TYPE: + ext_client_cert_type = 1; + if (client_hello) { + if (verify_ext_cert_type(data, j)) + goto error; + } else { + if (dtls_uint8_to_int(data) != TLS_CERT_TYPE_RAW_PUBLIC_KEY) + goto error; + } + break; + case TLS_EXT_SERVER_CERTIFICATE_TYPE: + ext_server_cert_type = 1; + if (client_hello) { + if (verify_ext_cert_type(data, j)) + goto error; + } else { + if (dtls_uint8_to_int(data) != TLS_CERT_TYPE_RAW_PUBLIC_KEY) + goto error; + } + break; + case TLS_EXT_EC_POINT_FORMATS: + ext_ec_point_formats = 1; + if (verify_ext_ec_point_formats(data, j)) + goto error; + break; + case TLS_EXT_ENCRYPT_THEN_MAC: + /* As only AEAD cipher suites are currently available, this + * extension can be skipped. + */ + dtls_info("skipped encrypt-then-mac extension\n"); + break; + case TLS_EXT_EXTENDED_MASTER_SECRET: + handshake->extended_master_secret = 1; + break; + case TLS_EXT_SIG_HASH_ALGO: + if (verify_ext_sig_hash_algo(data, j)) + goto error; + break; + default: + dtls_warn("unsupported tls extension: %i\n", i); + break; + } + data += j; + data_length -= j; + } + if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) && client_hello) { + if (!ext_elliptic_curve || !ext_client_cert_type || !ext_server_cert_type + || !ext_ec_point_formats) { + dtls_warn("not all required tls extensions found in client hello\n"); + goto error; + } + } else if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) && !client_hello) { + if (!ext_server_cert_type) { + dtls_warn("not all required tls extensions found in server hello\n"); + goto error; + } + } + return 0; + +error: + if (client_hello && peer->state == DTLS_STATE_CONNECTED) { + return dtls_alert_create(DTLS_ALERT_LEVEL_WARNING, DTLS_ALERT_NO_RENEGOTIATION); + } else { + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } +} + +/** + * Parses the ClientHello from the client and updates the internal handshake + * parameters with the new data for the given \p peer. When the ClientHello + * handshake message in \p data does not contain a cipher suite or + * compression method, it is copied from the the current security parameters. + * + * \param ctx The current DTLS context. + * \param peer The remote peer whose security parameters are about to change. + * \param data The handshake message with a ClientHello. + * \param data_length The actual size of \p data. + * \return \c -Something if an error occurred, \c 0 on success. + */ +static int +dtls_update_parameters(dtls_context_t *ctx, + dtls_peer_t *peer, + uint8 *data, size_t data_length) { + int i; + unsigned int j; + int ok; + dtls_handshake_parameters_t *config = peer->handshake_params; + + assert(config); + assert(data_length > DTLS_HS_LENGTH + DTLS_CH_LENGTH); + + /* skip the handshake header and client version information */ + data += DTLS_HS_LENGTH + sizeof(uint16); + data_length -= DTLS_HS_LENGTH + sizeof(uint16); + + /* store client random in config */ + memcpy(config->tmp.random.client, data, DTLS_RANDOM_LENGTH); + data += DTLS_RANDOM_LENGTH; + data_length -= DTLS_RANDOM_LENGTH; + + /* Caution: SKIP_VAR_FIELD may jump to error: */ + SKIP_VAR_FIELD(data, data_length, uint8); /* skip session id */ + SKIP_VAR_FIELD(data, data_length, uint8); /* skip cookie */ + + if (data_length < sizeof(uint16)) { + dtls_debug("cipher suites length exceeds record\n"); + goto error; + } + + i = dtls_uint16_to_int(data); + + if (i == 0) { + dtls_debug("cipher suites missing\n"); + goto error; + } + + if (data_length < i + sizeof(uint16)) { + dtls_debug("length for cipher suites exceeds record\n"); + goto error; + } + + if ((i % sizeof(uint16)) != 0) { + dtls_debug("odd length for cipher suites\n"); + goto error; + } + + data += sizeof(uint16); + data_length -= sizeof(uint16) + i; + + ok = 0; + while ((i >= (int)sizeof(uint16)) && !ok) { + config->cipher = dtls_uint16_to_int(data); + ok = known_cipher(ctx, config->cipher, 0); + i -= sizeof(uint16); + data += sizeof(uint16); + } + + /* skip remaining ciphers */ + data += i; + + if (!ok) { + /* reset config cipher to a well-defined value */ + config->cipher = TLS_NULL_WITH_NULL_NULL; + dtls_warn("No matching cipher found\n"); + goto error; + } + + if (data_length < sizeof(uint8)) { + dtls_debug("compression methods length exceeds record\n"); + goto error; + } + + i = dtls_uint8_to_int(data); + + if (i == 0) { + dtls_debug("compression methods missing\n"); + goto error; + } + + if (data_length < i + sizeof(uint8)) { + dtls_debug("length of compression methods exceeds record\n"); + goto error; + } + + data += sizeof(uint8); + data_length -= sizeof(uint8) + i; + + ok = 0; + while (i && !ok) { + for (j = 0; j < sizeof(compression_methods) / sizeof(uint8); ++j) { + if (dtls_uint8_to_int(data) == compression_methods[j]) { + config->compression = compression_methods[j]; + ok = 1; + } + } + i -= sizeof(uint8); + data += sizeof(uint8); + } + + /* skip remaining compression methods */ + data += i; + + if (!ok) { + /* reset config cipher to a well-defined value */ + goto error; + } + + return dtls_check_tls_extension(peer, data, data_length, 1); +error: + if (peer->state == DTLS_STATE_CONNECTED) { + return dtls_alert_create(DTLS_ALERT_LEVEL_WARNING, DTLS_ALERT_NO_RENEGOTIATION); + } else { + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } +} + +/** + * Parse the ClientKeyExchange and update the internal handshake state with + * the new data. + */ +static inline int +check_client_keyexchange(dtls_context_t *ctx, + dtls_handshake_parameters_t *handshake, + uint8 *data, size_t length) { + + (void) ctx; +#ifdef DTLS_ECC + if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher)) { + + if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) { + dtls_debug("The client key exchange is too short\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + data += DTLS_HS_LENGTH; + + if (dtls_uint8_to_int(data) != 1 + 2 * DTLS_EC_KEY_SIZE) { + dtls_alert("expected 65 bytes long public point\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + data += sizeof(uint8); + + if (dtls_uint8_to_int(data) != 4) { + dtls_alert("expected uncompressed public point\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + data += sizeof(uint8); + + memcpy(handshake->keyx.ecdsa.other_eph_pub_x, data, + sizeof(handshake->keyx.ecdsa.other_eph_pub_x)); + data += sizeof(handshake->keyx.ecdsa.other_eph_pub_x); + + memcpy(handshake->keyx.ecdsa.other_eph_pub_y, data, + sizeof(handshake->keyx.ecdsa.other_eph_pub_y)); + data += sizeof(handshake->keyx.ecdsa.other_eph_pub_y); + } +#endif /* DTLS_ECC */ +#ifdef DTLS_PSK + if (is_tls_psk_with_aes_128_ccm_8(handshake->cipher)) { + int id_length; + + if (length < DTLS_HS_LENGTH + DTLS_CKXPSK_LENGTH_MIN) { + dtls_debug("The client key exchange is too short\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + data += DTLS_HS_LENGTH; + + id_length = dtls_uint16_to_int(data); + data += sizeof(uint16); + + if (DTLS_HS_LENGTH + DTLS_CKXPSK_LENGTH_MIN + id_length != length) { + dtls_debug("The identity has a wrong length\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + if (id_length > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) { + dtls_warn("please use a smaller client identity\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + handshake->keyx.psk.id_length = id_length; + memcpy(handshake->keyx.psk.identity, data, id_length); + } +#endif /* DTLS_PSK */ + return 0; +} + +static void +update_hs_hash(dtls_peer_t *peer, uint8 *data, size_t length) { + dtls_debug_dump("add MAC data", data, length); + dtls_hash_update(&peer->handshake_params->hs_state.hs_hash, data, length); +} + +static void +copy_hs_hash(dtls_peer_t *peer, dtls_hash_ctx *hs_hash) { + memcpy(hs_hash, &peer->handshake_params->hs_state.hs_hash, + sizeof(peer->handshake_params->hs_state.hs_hash)); +} + +static inline size_t +finalize_hs_hash(dtls_peer_t *peer, uint8 *buf) { + return dtls_hash_finalize(buf, &peer->handshake_params->hs_state.hs_hash); +} + +static inline void +clear_hs_hash(dtls_peer_t *peer) { + assert(peer); + dtls_debug("clear MAC\n"); + dtls_hash_init(&peer->handshake_params->hs_state.hs_hash); +} + +/** + * Checks if \p record + \p data contain a Finished message with valid + * verify_data. + * + * \param ctx The current DTLS context. + * \param peer The remote peer of the security association. + * \param data The cleartext payload of the message. + * \param data_length Actual length of \p data. + * \return \c 0 if the Finished message is valid, \c negative number otherwise. + */ +static int +check_finished(dtls_context_t *ctx, dtls_peer_t *peer, + uint8 *data, size_t data_length) { + (void) ctx; + size_t digest_length, label_size; + const unsigned char *label; + unsigned char buf[DTLS_HMAC_MAX]; + (void)ctx; + + if (data_length < DTLS_HS_LENGTH + DTLS_FIN_LENGTH) + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + + /* Use a union here to ensure that sufficient stack space is + * reserved. As statebuf and verify_data are not used at the same + * time, we can re-use the storage safely. + */ + union { + unsigned char statebuf[DTLS_HASH_CTX_SIZE]; + unsigned char verify_data[DTLS_FIN_LENGTH]; + } b; + + /* temporarily store hash status for roll-back after finalize */ + memcpy(b.statebuf, &peer->handshake_params->hs_state.hs_hash, DTLS_HASH_CTX_SIZE); + + digest_length = finalize_hs_hash(peer, buf); + /* clear_hash(); */ + + /* restore hash status */ + memcpy(&peer->handshake_params->hs_state.hs_hash, b.statebuf, DTLS_HASH_CTX_SIZE); + + if (peer->role == DTLS_CLIENT) { + label = PRF_LABEL(server); + label_size = PRF_LABEL_SIZE(server); + } else { /* server */ + label = PRF_LABEL(client); + label_size = PRF_LABEL_SIZE(client); + } + + dtls_prf(peer->handshake_params->tmp.master_secret, + DTLS_MASTER_SECRET_LENGTH, + label, label_size, + PRF_LABEL(finished), PRF_LABEL_SIZE(finished), + buf, digest_length, + b.verify_data, sizeof(b.verify_data)); + + dtls_debug_dump("d:", data + DTLS_HS_LENGTH, sizeof(b.verify_data)); + dtls_debug_dump("v:", b.verify_data, sizeof(b.verify_data)); + + /* compare verify data and create DTLS alert code when they differ */ + return equals(data + DTLS_HS_LENGTH, b.verify_data, sizeof(b.verify_data)) + ? 0 + : dtls_alert_create(DTLS_ALERT_LEVEL_FATAL, DTLS_ALERT_DECRYPT_ERROR); +} + +/** + * Prepares the payload given in \p data for sending with + * dtls_send(). The \p data is encrypted and compressed according to + * the current security parameters of \p peer. The result of this + * operation is put into \p sendbuf with a prepended record header of + * type \p type ready for sending. As some cipher suites add a MAC + * before encryption, \p data must be large enough to hold this data + * as well (usually \c dtls_kb_digest_size(CURRENT_CONFIG(peer)). + * + * \param peer The remote peer the packet will be sent to. + * \param security The encryption paramater used to encrypt + * \param type The content type of this record. + * \param data_array Array with payloads in correct order. + * \param data_len_array Sizes of the payloads in correct order. + * \param data_array_len The number of payloads given. + * \param sendbuf The output buffer where the encrypted record + * will be placed. + * \param rlen This parameter must be initialized with the + * maximum size of \p sendbuf and will be updated + * to hold the actual size of the stored packet + * on success. On error, the value of \p rlen is + * undefined. + * \return Less than zero on error, or greater than zero success. + */ +static int +dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security, + unsigned char type, + uint8 *data_array[], size_t data_len_array[], + size_t data_array_len, + uint8 *sendbuf, size_t *rlen) { + uint8 *p, *start; + int res; + unsigned int i; + + if (*rlen < DTLS_RH_LENGTH) { + dtls_alert("The sendbuf (%zu bytes) is too small\n", *rlen); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + if (!peer || !security) { + dtls_alert("peer or security parameter missing\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + p = dtls_set_record_header(type, security->epoch, &(security->rseq), sendbuf); + start = p; + + if (security->cipher == TLS_NULL_WITH_NULL_NULL) { + /* no cipher suite */ + + res = 0; + for (i = 0; i < data_array_len; i++) { + /* check the minimum that we need for packets that are not encrypted */ + if (*rlen < res + DTLS_RH_LENGTH + data_len_array[i]) { + dtls_debug("dtls_prepare_record: send buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + memcpy(p, data_array[i], data_len_array[i]); + p += data_len_array[i]; + res += data_len_array[i]; + } + } else { /* TLS_PSK_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */ + /** + * length of additional_data for the AEAD cipher which consists of + * seq_num(2+6) + type(1) + version(2) + length(2) + */ +#define A_DATA_LEN 13 + unsigned char nonce[DTLS_CCM_BLOCKSIZE]; + unsigned char A_DATA[A_DATA_LEN]; + /* For backwards-compatibility, dtls_encrypt_params is called with + * M= and L=3. */ + const dtls_ccm_params_t params = { nonce, 8, 3 }; + + if (is_tls_psk_with_aes_128_ccm_8(security->cipher)) { + dtls_debug("dtls_prepare_record(): encrypt using TLS_PSK_WITH_AES_128_CCM_8\n"); + } else if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(security->cipher)) { + dtls_debug("dtls_prepare_record(): encrypt using TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n"); + } else { + dtls_debug("dtls_prepare_record(): encrypt using unknown cipher\n"); + } + + /* set nonce + from RFC 6655: + The "nonce" input to the AEAD algorithm is exactly that of [RFC5288]: + the "nonce" SHALL be 12 bytes long and is constructed as follows: + (this is an example of a "partially explicit" nonce; see Section + 3.2.1 in [RFC5116]). + + struct { + opaque salt[4]; + opaque nonce_explicit[8]; + } CCMNonce; + + [...] + + In DTLS, the 64-bit seq_num is the 16-bit epoch concatenated with the + 48-bit seq_num. + + When the nonce_explicit is equal to the sequence number, the CCMNonce + will have the structure of the CCMNonceExample given below. + + struct { + uint32 client_write_IV; // low order 32-bits + uint64 seq_num; // TLS sequence number + } CCMClientNonce. + + + struct { + uint32 server_write_IV; // low order 32-bits + uint64 seq_num; // TLS sequence number + } CCMServerNonce. + + + struct { + case client: + CCMClientNonce; + case server: + CCMServerNonce: + } CCMNonceExample; + */ + + memcpy(p, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8); + p += 8; + res = 8; + + for (i = 0; i < data_array_len; i++) { + /* check the minimum that we need for packets that are not encrypted */ + if (*rlen < res + DTLS_RH_LENGTH + data_len_array[i]) { + dtls_debug("dtls_prepare_record: send buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + memcpy(p, data_array[i], data_len_array[i]); + p += data_len_array[i]; + res += data_len_array[i]; + } + + memset(nonce, 0, DTLS_CCM_BLOCKSIZE); + memcpy(nonce, dtls_kb_local_iv(security, peer->role), + dtls_kb_iv_size(security, peer->role)); + memcpy(nonce + dtls_kb_iv_size(security, peer->role), start, 8); /* epoch + seq_num */ + + dtls_debug_dump("nonce:", nonce, DTLS_CCM_BLOCKSIZE); + dtls_debug_dump("key:", dtls_kb_local_write_key(security, peer->role), + dtls_kb_key_size(security, peer->role)); + + /* re-use N to create additional data according to RFC 5246, Section 6.2.3.3: + * + * additional_data = seq_num + TLSCompressed.type + + * TLSCompressed.version + TLSCompressed.length; + */ + memcpy(A_DATA, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8); /* epoch and seq_num */ + memcpy(A_DATA + 8, &DTLS_RECORD_HEADER(sendbuf)->content_type, 3); /* type and version */ + dtls_int_to_uint16(A_DATA + 11, res - 8); /* length */ + + res = dtls_encrypt_params(¶ms, start + 8, res - 8, start + 8, + dtls_kb_local_write_key(security, peer->role), + dtls_kb_key_size(security, peer->role), + A_DATA, A_DATA_LEN); + + if (res < 0) + return res; + + res += 8; /* increment res by size of nonce_explicit */ + dtls_debug_dump("message:", start, res); + } + + /* fix length of fragment in sendbuf */ + dtls_int_to_uint16(sendbuf + 11, res); + + *rlen = DTLS_RH_LENGTH + res; + return 0; +} + +/** + * Send Alert in stateless fashion. + * An Alert is sent to the peer (using the write callback function + * registered with \p ctx). The return value is the number of bytes sent, + * or less than 0 on error. + * + * \param ctx The DTLS context. + * \param ephemeral_peer The ephemeral remote party we are talking to. + * \param level Alert level. + * \param description Alert description. + * \return number of bytes sent, or less than 0 on error. + */ +static int +dtls_0_send_alert(dtls_context_t *ctx, + dtls_ephemeral_peer_t *ephemeral_peer, + dtls_alert_level_t level, + dtls_alert_t description) +{ + uint8 buf[DTLS_RH_LENGTH + DTLS_ALERT_LENGTH]; + uint8 *p = dtls_set_record_header(DTLS_CT_ALERT, 0, &(ephemeral_peer->rseq), buf); + + /* fix length of fragment in sendbuf */ + dtls_int_to_uint16(buf + 11, DTLS_ALERT_LENGTH); + + /* Alert */ + dtls_int_to_uint8(p, level); + dtls_int_to_uint8(p + 1, description); + + dtls_debug("send alert - protocol version packet\n"); + + dtls_debug_hexdump("send header", buf, DTLS_RH_LENGTH); + dtls_debug_hexdump("send unencrypted alert", p, DTLS_ALERT_LENGTH); + + return CALL(ctx, write, ephemeral_peer->session, buf, sizeof(buf)); +} + +static int +dtls_0_send_alert_from_err(dtls_context_t *ctx, + dtls_ephemeral_peer_t *ephemeral_peer, + int err) { + + assert(ephemeral_peer); + + if (dtls_is_alert(err)) { + dtls_alert_level_t level = ((-err) & 0xff00) >> 8; + dtls_alert_t desc = (-err) & 0xff; + return dtls_0_send_alert(ctx, ephemeral_peer, level, desc); + } else if (err == -1) { + return dtls_0_send_alert(ctx, ephemeral_peer, DTLS_ALERT_LEVEL_FATAL, DTLS_ALERT_INTERNAL_ERROR); + } + return -1; +} + +/** + * Send HelloVerifyRequest to initial challenge a peer in a stateless fashion. + * A HelloVerifyRequest is sent to the peer (using the write callback function + * registered with \p ctx). The return value is the number of bytes sent, + * or less than 0 on error. + * + * \param ctx The DTLS context. + * \param ephemeral_peer The ephemeral remote party we are talking to. + * \param data The received datagram. + * \param data_length Length of \p msg. + * \return number of bytes sent, or less than 0 on error. + */ +static int +dtls_0_send_hello_verify_request(dtls_context_t *ctx, + dtls_ephemeral_peer_t *ephemeral_peer, + uint8 *data, size_t data_length) +{ + uint8 buf[DTLS_RH_LENGTH + DTLS_HS_LENGTH + data_length]; + uint8 *p = dtls_set_record_header(DTLS_CT_HANDSHAKE, 0, &(ephemeral_peer->rseq), buf); + + /* Signal DTLS version 1.0 in the record layer of ClientHello and + * HelloVerifyRequest handshake messages according to Section 4.2.1 + * of RFC 6347. + * + * This does not apply to a renegotation ClientHello + */ + dtls_int_to_uint16(buf + 1, DTLS10_VERSION); + + /* fix length of fragment in sendbuf */ + dtls_int_to_uint16(buf + 11, DTLS_HS_LENGTH + data_length); + + p = dtls_set_handshake_header(DTLS_HT_HELLO_VERIFY_REQUEST, &(ephemeral_peer->mseq), data_length, 0, + data_length, p); + + memcpy(p, data, data_length); + + dtls_debug("send hello_verify_request packet\n"); + + dtls_debug_hexdump("send header", buf, DTLS_RH_LENGTH); + dtls_debug_hexdump("send unencrypted handshake header", buf + DTLS_RH_LENGTH, DTLS_HS_LENGTH); + dtls_debug_hexdump("send unencrypted cookie", data, data_length); + + return CALL(ctx, write, ephemeral_peer->session, buf, sizeof(buf)); +} + +static int +dtls_send_handshake_msg_hash(dtls_context_t *ctx, + dtls_peer_t *peer, + session_t *session, + uint8 header_type, + uint8 *data, size_t data_length, + int add_hash) +{ + uint8 buf[DTLS_HS_LENGTH]; + uint8 *data_array[2]; + size_t data_len_array[2]; + int i = 0; + dtls_security_parameters_t *security = dtls_security_params(peer); + + dtls_set_handshake_header(header_type, &(peer->handshake_params->hs_state.mseq_s), data_length, 0, + data_length, buf); + + if (add_hash) { + update_hs_hash(peer, buf, sizeof(buf)); + } + data_array[i] = buf; + data_len_array[i] = sizeof(buf); + i++; + + if (data != NULL) { + if (add_hash) { + update_hs_hash(peer, data, data_length); + } + data_array[i] = data; + data_len_array[i] = data_length; + i++; + } + dtls_debug("send handshake packet of type: %s (%i)\n", + dtls_handshake_type_to_name(header_type), header_type); + return dtls_send_multi(ctx, peer, security, session, DTLS_CT_HANDSHAKE, + data_array, data_len_array, i); +} + +static int +dtls_send_handshake_msg(dtls_context_t *ctx, + dtls_peer_t *peer, + uint8 header_type, + uint8 *data, size_t data_length) +{ + return dtls_send_handshake_msg_hash(ctx, peer, &peer->session, + header_type, data, data_length, 1); +} + +/** + * Returns true if the message @p Data is a handshake message that + * must be included in the calculation of verify_data in the Finished + * message. + * + * @param Type The message type. Only handshake messages but the initial + * Client Hello and Hello Verify Request are included in the hash, + * @param Data The PDU to examine. + * @param Length The length of @p Data. + * + * @return @c 1 if @p Data must be included in hash, @c 0 otherwise. + * + * @hideinitializer + */ +#define MUST_HASH(Type, Data, Length) \ + ((Type) == DTLS_CT_HANDSHAKE && \ + ((Data) != NULL) && ((Length) > 0) && \ + ((Data)[0] != DTLS_HT_HELLO_VERIFY_REQUEST) && \ + ((Data)[0] != DTLS_HT_CLIENT_HELLO || \ + ((Length) >= HS_HDR_LENGTH && \ + (dtls_uint16_to_int(DTLS_RECORD_HEADER(Data)->epoch > 0) || \ + (dtls_uint16_to_int(HANDSHAKE(Data)->message_seq) > 0))))) + + +#ifdef DTLS_CONSTRAINED_STACK +static dtls_mutex_t static_mutex = DTLS_MUTEX_INITIALIZER; +static unsigned char sendbuf[DTLS_MAX_BUF]; +#endif /* DTLS_CONSTRAINED_STACK */ + +/** + * Sends the data passed in @p buf as a DTLS record of type @p type to + * the given peer. The data will be encrypted and compressed according + * to the security parameters for @p peer. + * + * @param ctx The DTLS context in effect. + * @param peer The remote party where the packet is sent. + * @param security The encryption paramater used to encrypt. + * @param session The transport address of the remote peer. + * @param type The content type of this record. + * @param buf The data to send. + * @param buflen The number of bytes to send from @p buf. + * @return Less than zero in case of an error or the number of + * bytes that have been sent otherwise. + */ +static int +dtls_send_multi(dtls_context_t *ctx, dtls_peer_t *peer, + dtls_security_parameters_t *security , session_t *session, + unsigned char type, uint8 *buf_array[], + size_t buf_len_array[], size_t buf_array_len) +{ + /* We cannot use ctx->sendbuf here as it is reserved for collecting + * the input for this function, i.e. buf == ctx->sendbuf. + * + * TODO: check if we can use the receive buf here. This would mean + * that we might not be able to handle multiple records stuffed in + * one UDP datagram */ +#ifndef DTLS_CONSTRAINED_STACK + unsigned char sendbuf[DTLS_MAX_BUF]; +#endif /* ! DTLS_CONSTRAINED_STACK */ + size_t len = sizeof(sendbuf); + int res; + unsigned int i; + size_t overall_len = 0; + +#ifdef DTLS_CONSTRAINED_STACK + dtls_mutex_lock(&static_mutex); +#endif /* DTLS_CONSTRAINED_STACK */ + + res = dtls_prepare_record(peer, security, type, buf_array, buf_len_array, buf_array_len, sendbuf, &len); + + if (res < 0) + goto return_unlock; + + /* if (peer && MUST_HASH(peer, type, buf, buflen)) */ + /* update_hs_hash(peer, buf, buflen); */ + + + /* Signal DTLS version 1.0 in the record layer of ClientHello and + * HelloVerifyRequest handshake messages according to Section 4.2.1 + * of RFC 6347. + * + * This does not apply to a renegotation ClientHello + */ + if (security->epoch == 0) { + if (type == DTLS_CT_HANDSHAKE) { + if (buf_array[0][0] == DTLS_HT_CLIENT_HELLO) { + dtls_int_to_uint16(sendbuf + 1, DTLS10_VERSION); + } + } + } + + dtls_debug_hexdump("send header", sendbuf, sizeof(dtls_record_header_t)); + for (i = 0; i < buf_array_len; i++) { + dtls_debug_hexdump("send unencrypted", buf_array[i], buf_len_array[i]); + overall_len += buf_len_array[i]; + } + + if (type == DTLS_CT_HANDSHAKE || type == DTLS_CT_CHANGE_CIPHER_SPEC) { + /* copy messages of handshake into retransmit buffer */ + netq_t *n = netq_node_new(overall_len); + if (n) { + dtls_tick_t now; + dtls_ticks(&now); + n->t = now + 2 * CLOCK_SECOND; + n->retransmit_cnt = 0; + n->timeout = 2 * CLOCK_SECOND; + n->peer = peer; + n->epoch = (security) ? security->epoch : 0; + n->type = type; + n->job = RESEND; + n->length = 0; + for (i = 0; i < buf_array_len; i++) { + memcpy(n->data + n->length, buf_array[i], buf_len_array[i]); + n->length += buf_len_array[i]; + } + + if (!netq_insert_node(&ctx->sendqueue, n)) { + dtls_warn("cannot add packet to retransmit buffer\n"); + netq_node_free(n); +#ifdef WITH_CONTIKI + } else { + /* must set timer within the context of the retransmit process */ + PROCESS_CONTEXT_BEGIN(&dtls_retransmit_process); + etimer_set(&ctx->retransmit_timer, n->timeout); + PROCESS_CONTEXT_END(&dtls_retransmit_process); +#else /* WITH_CONTIKI */ + dtls_debug("copied to sendqueue\n"); +#endif /* WITH_CONTIKI */ + } + } else { + dtls_warn("retransmit buffer full\n"); + } + } + + /* FIXME: copy to peer's sendqueue (after fragmentation if + * necessary) and initialize retransmit timer */ + res = CALL(ctx, write, session, sendbuf, len); + +return_unlock: +#ifdef DTLS_CONSTRAINED_STACK + dtls_mutex_unlock(&static_mutex); +#endif /* DTLS_CONSTRAINED_STACK */ + + /* Guess number of bytes application data actually sent: + * dtls_prepare_record() tells us in len the number of bytes to + * send, res will contain the bytes actually sent. */ + return res <= 0 ? res : (int)(overall_len - (len - (unsigned int)res)); +} + +static inline int +dtls_send_alert(dtls_context_t *ctx, dtls_peer_t *peer, dtls_alert_level_t level, + dtls_alert_t description) { + uint8_t msg[] = { level, description }; + + dtls_send(ctx, peer, DTLS_CT_ALERT, msg, sizeof(msg)); + + /* copy close alert in retransmit buffer to emulate timeout */ + /* not resent, therefore don't copy the complete record */ + netq_t *n = netq_node_new(2); + if (n) { + dtls_tick_t now; + dtls_ticks(&now); + n->t = now + 2 * CLOCK_SECOND; + n->retransmit_cnt = 0; + n->timeout = 2 * CLOCK_SECOND; + n->peer = peer; + n->epoch = peer->security_params[0]->epoch; + n->type = DTLS_CT_ALERT; + n->length = 2; + n->data[0] = level; + n->data[1] = description; + n->job = TIMEOUT; + + if (!netq_insert_node(&ctx->sendqueue, n)) { + dtls_warn("cannot add alert to retransmit buffer\n"); + netq_node_free(n); + n = NULL; +#ifdef WITH_CONTIKI + } else { + /* must set timer within the context of the retransmit process */ + PROCESS_CONTEXT_BEGIN(&dtls_retransmit_process); + etimer_set(&ctx->retransmit_timer, n->timeout); + PROCESS_CONTEXT_END(&dtls_retransmit_process); +#else /* WITH_CONTIKI */ + dtls_debug("alert copied to retransmit buffer\n"); +#endif /* WITH_CONTIKI */ + } + } else { + dtls_warn("cannot add alert, retransmit buffer full\n"); + } + if (!n) { + /* timeout not registered */ + handle_alert(ctx, peer, NULL, msg, sizeof(msg)); + } + + return 0; +} + +int +dtls_close(dtls_context_t *ctx, const session_t *remote) { + int res = -1; + dtls_peer_t *peer; + + peer = dtls_get_peer(ctx, remote); + + if (peer) { + /* indicate tear down */ + peer->state = DTLS_STATE_CLOSING; + res = dtls_send_alert(ctx, peer, DTLS_ALERT_LEVEL_WARNING, + DTLS_ALERT_CLOSE_NOTIFY); + } + return res; +} + +static void +dtls_destroy_peer(dtls_context_t *ctx, dtls_peer_t *peer, int flags) { + if ((flags & DTLS_DESTROY_CLOSE) && + (peer->state != DTLS_STATE_CLOSED) && + (peer->state != DTLS_STATE_CLOSING)) { + dtls_close(ctx, &peer->session); + } + dtls_stop_retransmission(ctx, peer); + DEL_PEER(ctx->peers, peer); + dtls_dsrv_log_addr(DTLS_LOG_DEBUG, "removed peer", &peer->session); + dtls_free_peer(peer); +} + +/** + * Checks a received ClientHello message for a valid cookie. When the + * ClientHello contains no cookie, the function fails and a HelloVerifyRequest + * is sent to the peer (using the write callback function registered + * with \p ctx). The return value is \c -1 on error, \c 1 when + * undecided, and \c 0 if the ClientHello was good. + * + * \param ctx The DTLS context. + * \param ephemeral_peer The remote party we are talking to, if any. + * \param data The received datagram. + * \param data_length Length of \p msg. + * \return \c 0 if msg is a ClientHello with a valid cookie, \c 1 or + * \c -1 otherwise. + */ +static int +dtls_0_verify_peer(dtls_context_t *ctx, + dtls_ephemeral_peer_t *ephemeral_peer, + uint8 *data, size_t data_length) +{ + uint8 buf[DTLS_HV_LENGTH + DTLS_COOKIE_LENGTH]; + uint8 *p = buf; + int len = DTLS_COOKIE_LENGTH; + uint8 *cookie = NULL; + int err; +#undef mycookie +#define mycookie (buf + DTLS_HV_LENGTH) + + /* Store cookie where we can reuse it for the HelloVerifyRequest. */ + err = dtls_create_cookie(ctx, ephemeral_peer->session, data, data_length, mycookie, &len); + if (err < 0) + return err; + + dtls_debug_dump("create cookie", mycookie, len); + + assert(len == DTLS_COOKIE_LENGTH); + + /* Perform cookie check. */ + len = dtls_get_cookie(data, data_length, &cookie); + if (len < 0) { + dtls_warn("error while fetching the cookie, err: %i\n", len); + if (dtls_alert_fatal_create(DTLS_ALERT_PROTOCOL_VERSION) == len) { + dtls_0_send_alert(ctx, ephemeral_peer, DTLS_ALERT_LEVEL_FATAL, DTLS_ALERT_PROTOCOL_VERSION); + } + return len; + } + + dtls_debug_dump("compare with cookie", cookie, len); + + /* check if cookies match */ + if (len == DTLS_COOKIE_LENGTH && memcmp(cookie, mycookie, len) == 0) { + dtls_debug("found matching cookie\n"); + return 0; + } + + if (len > 0) { + dtls_debug_dump("invalid cookie", cookie, len); + } else { + dtls_debug("cookie len is 0!\n"); + } + + /* ClientHello did not contain any valid cookie, hence we send a + * HelloVerifyRequest. */ + + dtls_int_to_uint16(p, DTLS_VERSION); + p += sizeof(uint16); + + dtls_int_to_uint8(p, DTLS_COOKIE_LENGTH); + p += sizeof(uint8); + + assert(p == mycookie); + + p += DTLS_COOKIE_LENGTH; + + err = dtls_0_send_hello_verify_request(ctx, + ephemeral_peer, + buf, p - buf); + if (err < 0) { + dtls_warn("cannot send HelloVerify request\n"); + } + return err; /* HelloVerifyRequest is sent, now we cannot do anything but wait */ + +#undef mycookie +} + +#ifdef DTLS_ECC +/* + * Assumes that data_len is at least 1 */ +static size_t +dtls_asn1_len(uint8 **data, size_t *data_len) +{ + size_t len = 0; + + if ((**data) & 0x80) { + size_t octets = (**data) & 0x7f; + (*data)++; + (*data_len)--; + if (octets > *data_len) + return (size_t)-1; + while (octets > 0) { + len = (len << 8) + (**data); + (*data)++; + (*data_len)--; + octets--; + } + } + else { + len = (**data) & 0x7f; + (*data)++; + (*data_len)--; + } + return len; +} + +static int +dtls_asn1_integer_to_ec_key(uint8 *data, size_t data_len, uint8 *key, + size_t key_len) +{ + size_t length; + + if (data_len < 2) { + dtls_alert("signature data length short\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + if (dtls_uint8_to_int(data) != 0x02) { + dtls_alert("wrong ASN.1 struct, expected Integer\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + data += sizeof(uint8); + data_len -= sizeof(uint8); + + length = dtls_asn1_len(&data, &data_len); + if (length > data_len) { + dtls_alert("asn1 integer length too long\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + + if (length < key_len) { + /* pad with leading 0s */ + memset(key, 0, key_len - length); + memcpy(key + key_len - length, data, length); + } + else { + /* drop leading 0s if needed */ + memcpy(key, data + length - key_len, key_len); + } + return length + 2; +} + +static int +dtls_check_ecdsa_signature_elem(uint8 *data, size_t data_length, + unsigned char *result_r, + unsigned char *result_s) +{ + int ret; + uint8 *data_orig = data; + + /* + * 1 sig hash sha256 + * 1 sig hash ecdsa + * 2 data length + * 1 sequence + * 1 sequence length + */ + if (data_length < 1 + 1 + 2 + 1 + 1) { + dtls_alert("signature data length short\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + if (dtls_uint8_to_int(data) != TLS_EXT_SIG_HASH_ALGO_SHA256) { + dtls_alert("only sha256 is supported in certificate verify\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + data += sizeof(uint8); + data_length -= sizeof(uint8); + + if (dtls_uint8_to_int(data) != TLS_EXT_SIG_HASH_ALGO_ECDSA) { + dtls_alert("only ecdsa signature is supported in client verify\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + data += sizeof(uint8); + data_length -= sizeof(uint8); + + if (data_length < dtls_uint16_to_int(data)) { + dtls_alert("signature length wrong\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + data += sizeof(uint16); + data_length -= sizeof(uint16); + + if (dtls_uint8_to_int(data) != 0x30) { + dtls_alert("wrong ASN.1 struct, expected SEQUENCE\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + data += sizeof(uint8); + data_length -= sizeof(uint8); + + if (data_length < dtls_uint8_to_int(data)) { + dtls_alert("signature length wrong\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + data += sizeof(uint8); + data_length -= sizeof(uint8); + + ret = dtls_asn1_integer_to_ec_key(data, data_length, result_r, DTLS_EC_KEY_SIZE); + if (ret <= 0) + return ret; + data += ret; + data_length -= ret; + + ret = dtls_asn1_integer_to_ec_key(data, data_length, result_s, DTLS_EC_KEY_SIZE); + if (ret <= 0) + return ret; + data += ret; + data_length -= ret; + + return data - data_orig; +} + +static int +check_client_certificate_verify(dtls_context_t *ctx, + dtls_peer_t *peer, + uint8 *data, size_t data_length) +{ + (void) ctx; + dtls_handshake_parameters_t *config = peer->handshake_params; + int ret; + unsigned char result_r[DTLS_EC_KEY_SIZE]; + unsigned char result_s[DTLS_EC_KEY_SIZE]; + dtls_hash_ctx hs_hash; + unsigned char sha256hash[DTLS_HMAC_DIGEST_SIZE]; + + assert(is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(config->cipher)); + + data += DTLS_HS_LENGTH; + data_length -= DTLS_HS_LENGTH; + + if (data_length < DTLS_CV_LENGTH - 2 * DTLS_EC_KEY_SIZE) { + /* + * Some of the ASN.1 integer in the signature may be less than + * DTLS_EC_KEY_SIZE if leading bits are 0. + * dtls_check_ecdsa_signature_elem() knows how to handle this undersize. + */ + dtls_alert("the packet length does not match the expected\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + + ret = dtls_check_ecdsa_signature_elem(data, data_length, result_r, result_s); + if (ret < 0) { + return ret; + } + data += ret; + data_length -= ret; + + copy_hs_hash(peer, &hs_hash); + + dtls_hash_finalize(sha256hash, &hs_hash); + + ret = dtls_ecdsa_verify_sig_hash(config->keyx.ecdsa.other_pub_x, config->keyx.ecdsa.other_pub_y, + sizeof(config->keyx.ecdsa.other_pub_x), + sha256hash, sizeof(sha256hash), + result_r, result_s); + + if (ret < 0) { + dtls_alert("wrong signature err: %i\n", ret); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + return 0; +} +#endif /* DTLS_ECC */ + +static int +dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer) +{ + /* Ensure that the largest message to create fits in our source + * buffer. (The size of the destination buffer is checked by the + * encoding function, so we do not need to guess.) */ + uint8 buf[DTLS_SH_LENGTH + 2 + 5 + 5 + 8 + 6 + 4]; + uint8 *p; + int ecdsa; + uint8 extension_size; + dtls_handshake_parameters_t *handshake = peer->handshake_params; + + ecdsa = is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher); + + extension_size = (handshake->extended_master_secret ? 4 : 0) + + (ecdsa ? 5 + 5 + 6 : 0); + + /* Handshake header */ + p = buf; + + /* ServerHello */ + dtls_int_to_uint16(p, DTLS_VERSION); + p += sizeof(uint16); + + /* Set 32 bytes of server random data. */ + dtls_prng(handshake->tmp.random.server, DTLS_RANDOM_LENGTH); + + memcpy(p, handshake->tmp.random.server, DTLS_RANDOM_LENGTH); + p += DTLS_RANDOM_LENGTH; + + *p++ = 0; /* no session id */ + + if (handshake->cipher != TLS_NULL_WITH_NULL_NULL) { + /* selected cipher suite */ + dtls_int_to_uint16(p, handshake->cipher); + p += sizeof(uint16); + + /* selected compression method */ + *p++ = compression_methods[handshake->compression]; + } + + if (extension_size) { + /* length of the extensions */ + dtls_int_to_uint16(p, extension_size); + p += sizeof(uint16); + } + + if (ecdsa) { + /* client certificate type extension */ + dtls_int_to_uint16(p, TLS_EXT_CLIENT_CERTIFICATE_TYPE); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 1); + p += sizeof(uint16); + + dtls_int_to_uint8(p, TLS_CERT_TYPE_RAW_PUBLIC_KEY); + p += sizeof(uint8); + + /* client certificate type extension */ + dtls_int_to_uint16(p, TLS_EXT_SERVER_CERTIFICATE_TYPE); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 1); + p += sizeof(uint16); + + dtls_int_to_uint8(p, TLS_CERT_TYPE_RAW_PUBLIC_KEY); + p += sizeof(uint8); + + /* ec_point_formats */ + dtls_int_to_uint16(p, TLS_EXT_EC_POINT_FORMATS); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 2); + p += sizeof(uint16); + + /* number of supported formats */ + dtls_int_to_uint8(p, 1); + p += sizeof(uint8); + + dtls_int_to_uint8(p, TLS_EXT_EC_POINT_FORMATS_UNCOMPRESSED); + p += sizeof(uint8); + + } + if (handshake->extended_master_secret) { + /* extended master secret */ + dtls_int_to_uint16(p, TLS_EXT_EXTENDED_MASTER_SECRET); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 0); + p += sizeof(uint16); + } + + assert((buf <= p) && ((unsigned int)(p - buf) <= sizeof(buf))); + + /* TODO use the same record sequence number as in the ClientHello, + see 4.2.1. Denial-of-Service Countermeasures */ + return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_HELLO, + buf, p - buf); +} + +#ifdef DTLS_ECC +#define DTLS_EC_SUBJECTPUBLICKEY_SIZE (2 * DTLS_EC_KEY_SIZE + sizeof(cert_asn1_header)) + +static int +dtls_send_certificate_ecdsa(dtls_context_t *ctx, dtls_peer_t *peer, + const dtls_ecdsa_key_t *key) +{ + uint8 buf[sizeof(uint24) + DTLS_EC_SUBJECTPUBLICKEY_SIZE]; + uint8 *p; + + /* Certificate + * + * Start message construction at beginning of buffer. */ + p = buf; + + /* length of this certificate */ + dtls_int_to_uint24(p, DTLS_EC_SUBJECTPUBLICKEY_SIZE); + p += sizeof(uint24); + + memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header)); + p += sizeof(cert_asn1_header); + + memcpy(p, key->pub_key_x, DTLS_EC_KEY_SIZE); + p += DTLS_EC_KEY_SIZE; + + memcpy(p, key->pub_key_y, DTLS_EC_KEY_SIZE); + p += DTLS_EC_KEY_SIZE; + + assert(p <= (buf + sizeof(buf))); + + return dtls_send_handshake_msg(ctx, peer, DTLS_HT_CERTIFICATE, + buf, p - buf); +} + +static uint8 * +dtls_add_ecdsa_signature_elem(uint8 *p, uint32_t *point_r, uint32_t *point_s) +{ + int len_r; + int len_s; + +#define R_KEY_OFFSET (1 + 1 + 2 + 1 + 1) +#define S_KEY_OFFSET(len_a) (R_KEY_OFFSET + (len_a)) + /* store the pointer to the r component of the signature and make space */ + len_r = dtls_ec_key_asn1_from_uint32(point_r, DTLS_EC_KEY_SIZE, p + R_KEY_OFFSET); + len_s = dtls_ec_key_asn1_from_uint32(point_s, DTLS_EC_KEY_SIZE, p + S_KEY_OFFSET(len_r)); + +#undef R_KEY_OFFSET +#undef S_KEY_OFFSET + + /* sha256 */ + dtls_int_to_uint8(p, TLS_EXT_SIG_HASH_ALGO_SHA256); + p += sizeof(uint8); + + /* ecdsa */ + dtls_int_to_uint8(p, TLS_EXT_SIG_HASH_ALGO_ECDSA); + p += sizeof(uint8); + + /* length of signature */ + dtls_int_to_uint16(p, len_r + len_s + 2); + p += sizeof(uint16); + + /* ASN.1 SEQUENCE */ + dtls_int_to_uint8(p, 0x30); + p += sizeof(uint8); + + dtls_int_to_uint8(p, len_r + len_s); + p += sizeof(uint8); + + /* ASN.1 Integer r */ + + /* the point r ASN.1 integer was added here so skip */ + p += len_r; + + /* ASN.1 Integer s */ + + /* the point s ASN.1 integer was added here so skip */ + p += len_s; + + return p; +} + +static int +dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer, + const dtls_ecdsa_key_t *key) +{ + /* The ASN.1 Integer representation of an 32 byte unsigned int could be + * 33 bytes long add space for that */ + uint8 buf[DTLS_SKEXEC_LENGTH + 2]; + uint8 *p; + uint8 *key_params; + uint8 *ephemeral_pub_x; + uint8 *ephemeral_pub_y; + uint32_t point_r[9]; + uint32_t point_s[9]; + dtls_handshake_parameters_t *config = peer->handshake_params; + + /* ServerKeyExchange + * + * Start message construction at beginning of buffer. */ + p = buf; + + key_params = p; + /* ECCurveType curve_type: named_curve */ + dtls_int_to_uint8(p, 3); + p += sizeof(uint8); + + /* NamedCurve namedcurve: secp256r1 */ + dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES_SECP256R1); + p += sizeof(uint16); + + dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE); + p += sizeof(uint8); + + /* This should be an uncompressed point, but I do not have access to the spec. */ + dtls_int_to_uint8(p, 4); + p += sizeof(uint8); + + /* store the pointer to the x component of the pub key and make space */ + ephemeral_pub_x = p; + p += DTLS_EC_KEY_SIZE; + + /* store the pointer to the y component of the pub key and make space */ + ephemeral_pub_y = p; + p += DTLS_EC_KEY_SIZE; + + dtls_ecdsa_generate_key(config->keyx.ecdsa.own_eph_priv, + ephemeral_pub_x, ephemeral_pub_y, + DTLS_EC_KEY_SIZE); + + /* sign the ephemeral and its paramaters */ + dtls_ecdsa_create_sig(key->priv_key, DTLS_EC_KEY_SIZE, + config->tmp.random.client, DTLS_RANDOM_LENGTH, + config->tmp.random.server, DTLS_RANDOM_LENGTH, + key_params, p - key_params, + point_r, point_s); + + p = dtls_add_ecdsa_signature_elem(p, point_r, point_s); + + assert(p <= (buf + sizeof(buf))); + + return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_KEY_EXCHANGE, + buf, p - buf); +} +#endif /* DTLS_ECC */ + +#ifdef DTLS_PSK +static int +dtls_send_server_key_exchange_psk(dtls_context_t *ctx, dtls_peer_t *peer, + const unsigned char *psk_hint, size_t len) +{ + uint8 buf[DTLS_SKEXECPSK_LENGTH_MAX]; + uint8 *p; + + p = buf; + + assert(len <= DTLS_PSK_MAX_CLIENT_IDENTITY_LEN); + if (len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) { + /* should never happen */ + dtls_warn("psk identity hint is too long\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + dtls_int_to_uint16(p, len); + p += sizeof(uint16); + + memcpy(p, psk_hint, len); + p += len; + + assert((buf <= p) && ((unsigned int)(p - buf) <= sizeof(buf))); + + return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_KEY_EXCHANGE, + buf, p - buf); +} +#endif /* DTLS_PSK */ + +#ifdef DTLS_ECC +static int +dtls_send_server_certificate_request(dtls_context_t *ctx, dtls_peer_t *peer) +{ + uint8 buf[8]; + uint8 *p; + + /* ServerHelloDone + * + * Start message construction at beginning of buffer. */ + p = buf; + + /* certificate_types */ + dtls_int_to_uint8(p, 1); + p += sizeof(uint8); + + /* ecdsa_sign */ + dtls_int_to_uint8(p, TLS_CLIENT_CERTIFICATE_TYPE_ECDSA_SIGN); + p += sizeof(uint8); + + /* supported_signature_algorithms */ + dtls_int_to_uint16(p, 2); + p += sizeof(uint16); + + /* sha256 */ + dtls_int_to_uint8(p, TLS_EXT_SIG_HASH_ALGO_SHA256); + p += sizeof(uint8); + + /* ecdsa */ + dtls_int_to_uint8(p, TLS_EXT_SIG_HASH_ALGO_ECDSA); + p += sizeof(uint8); + + /* certificate_authoritiess */ + dtls_int_to_uint16(p, 0); + p += sizeof(uint16); + + assert(p <= (buf + sizeof(buf))); + + return dtls_send_handshake_msg(ctx, peer, DTLS_HT_CERTIFICATE_REQUEST, + buf, p - buf); +} +#endif /* DTLS_ECC */ + +static int +dtls_send_server_hello_done(dtls_context_t *ctx, dtls_peer_t *peer) +{ + + /* ServerHelloDone + * + * Start message construction at beginning of buffer. */ + + return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_HELLO_DONE, + NULL, 0); +} + +static int +dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer) +{ + int res; + + res = dtls_send_server_hello(ctx, peer); + + if (res < 0) { + dtls_debug("dtls_server_hello: cannot prepare ServerHello record\n"); + return res; + } + +#ifdef DTLS_ECC + if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)) { + const dtls_ecdsa_key_t *ecdsa_key; + + res = CALL(ctx, get_ecdsa_key, &peer->session, &ecdsa_key); + if (res < 0) { + dtls_crit("no ecdsa certificate to send in certificate\n"); + return res; + } + + res = dtls_send_certificate_ecdsa(ctx, peer, ecdsa_key); + + if (res < 0) { + dtls_debug("dtls_server_hello: cannot prepare Certificate record\n"); + return res; + } + + res = dtls_send_server_key_exchange_ecdh(ctx, peer, ecdsa_key); + + if (res < 0) { + dtls_debug("dtls_server_hello: cannot prepare Server Key Exchange record\n"); + return res; + } + + if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher) && + is_ecdsa_client_auth_supported(ctx)) { + res = dtls_send_server_certificate_request(ctx, peer); + + if (res < 0) { + dtls_debug("dtls_server_hello: cannot prepare certificate Request record\n"); + return res; + } + } + } +#endif /* DTLS_ECC */ + +#ifdef DTLS_PSK + if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) { + unsigned char psk_hint[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN]; + int len; + + /* The identity hint is optional, therefore we ignore the result + * and check psk only. */ + len = CALL(ctx, get_psk_info, &peer->session, DTLS_PSK_HINT, + NULL, 0, psk_hint, DTLS_PSK_MAX_CLIENT_IDENTITY_LEN); + + if (len < 0) { + dtls_debug("dtls_server_hello: cannot create ServerKeyExchange\n"); + return len; + } + + if (len > 0) { + res = dtls_send_server_key_exchange_psk(ctx, peer, psk_hint, (size_t)len); + + if (res < 0) { + dtls_debug("dtls_server_key_exchange_psk: cannot send server key exchange record\n"); + return res; + } + } + } +#endif /* DTLS_PSK */ + + res = dtls_send_server_hello_done(ctx, peer); + + if (res < 0) { + dtls_debug("dtls_server_hello: cannot prepare ServerHelloDone record\n"); + return res; + } + return 0; +} + +static inline int +dtls_send_ccs(dtls_context_t *ctx, dtls_peer_t *peer) { + uint8 buf[1] = {1}; + + return dtls_send(ctx, peer, DTLS_CT_CHANGE_CIPHER_SPEC, buf, 1); +} + + +static int +dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer) +{ + uint8 buf[DTLS_CKXEC_LENGTH]; + uint8 *p; + dtls_handshake_parameters_t *handshake = peer->handshake_params; + int ret; + + p = buf; + + memset(buf, 0, sizeof(buf)); + switch (handshake->cipher) { +#ifdef DTLS_PSK + case TLS_PSK_WITH_AES_128_CCM_8: { + int len; + + len = CALL(ctx, get_psk_info, &peer->session, DTLS_PSK_IDENTITY, + handshake->keyx.psk.identity, handshake->keyx.psk.id_length, + buf + sizeof(uint16), + min(sizeof(buf) - sizeof(uint16), + sizeof(handshake->keyx.psk.identity))); + if (len < 0) { + dtls_crit("no psk identity set in kx\n"); + return len; + } + + if (len + sizeof(uint16) > DTLS_CKXEC_LENGTH) { + memset(&handshake->keyx.psk, 0, sizeof(dtls_handshake_parameters_psk_t)); + dtls_warn("the psk identity is too long\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + handshake->keyx.psk.id_length = (unsigned int)len; + memcpy(handshake->keyx.psk.identity, p + sizeof(uint16), len); + + dtls_int_to_uint16(p, handshake->keyx.psk.id_length); + p += sizeof(uint16); + + memcpy(p, handshake->keyx.psk.identity, handshake->keyx.psk.id_length); + p += handshake->keyx.psk.id_length; + + break; + } +#endif /* DTLS_PSK */ +#ifdef DTLS_ECC + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: { + uint8 *ephemeral_pub_x; + uint8 *ephemeral_pub_y; + + dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE); + p += sizeof(uint8); + + /* This should be an uncompressed point, but I do not have access to the spec. */ + dtls_int_to_uint8(p, 4); + p += sizeof(uint8); + + ephemeral_pub_x = p; + p += DTLS_EC_KEY_SIZE; + ephemeral_pub_y = p; + p += DTLS_EC_KEY_SIZE; + + dtls_ecdsa_generate_key(peer->handshake_params->keyx.ecdsa.own_eph_priv, + ephemeral_pub_x, ephemeral_pub_y, + DTLS_EC_KEY_SIZE); + + break; + } +#endif /* DTLS_ECC */ + + case TLS_NULL_WITH_NULL_NULL: + assert(!"NULL cipher requested"); + return dtls_alert_fatal_create(DTLS_ALERT_INSUFFICIENT_SECURITY); + + /* The following cases cover the enum symbols that are not + * included in this build. These must be kept just above the + * default case as they do nothing but fall through. + */ +#ifndef DTLS_PSK + case TLS_PSK_WITH_AES_128_CCM_8: + /* fall through to default */ +#endif /* !DTLS_PSK */ + +#ifndef DTLS_ECC + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + /* fall through to default */ +#endif /* !DTLS_ECC */ + + default: + dtls_crit("cipher %04x not supported\n", handshake->cipher); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + assert((buf <= p) && ((unsigned int)(p - buf) <= sizeof(buf))); + + ret = dtls_send_handshake_msg(ctx, peer, DTLS_HT_CLIENT_KEY_EXCHANGE, + buf, p - buf); + + /* Keep hash information for extended master secret */ + memcpy(&peer->handshake_params->hs_state.ext_hash, + &peer->handshake_params->hs_state.hs_hash, + sizeof(peer->handshake_params->hs_state.ext_hash)); + + return ret; +} + +#ifdef DTLS_ECC +static int +dtls_send_certificate_verify_ecdh(dtls_context_t *ctx, dtls_peer_t *peer, + const dtls_ecdsa_key_t *key) +{ + /* The ASN.1 Integer representation of an 32 byte unsigned int could be + * 33 bytes long add space for that */ + uint8 buf[DTLS_CV_LENGTH + 2]; + uint8 *p; + uint32_t point_r[9]; + uint32_t point_s[9]; + dtls_hash_ctx hs_hash; + unsigned char sha256hash[DTLS_HMAC_DIGEST_SIZE]; + + /* ServerKeyExchange + * + * Start message construction at beginning of buffer. */ + p = buf; + + copy_hs_hash(peer, &hs_hash); + + dtls_hash_finalize(sha256hash, &hs_hash); + + /* sign the ephemeral and its paramaters */ + dtls_ecdsa_create_sig_hash(key->priv_key, DTLS_EC_KEY_SIZE, + sha256hash, sizeof(sha256hash), + point_r, point_s); + + p = dtls_add_ecdsa_signature_elem(p, point_r, point_s); + + assert(p <= (buf + sizeof(buf))); + + return dtls_send_handshake_msg(ctx, peer, DTLS_HT_CERTIFICATE_VERIFY, + buf, p - buf); +} +#endif /* DTLS_ECC */ + +static int +dtls_send_finished(dtls_context_t *ctx, dtls_peer_t *peer, + const unsigned char *label, size_t labellen) +{ + int length; + uint8 hash[DTLS_HMAC_MAX]; + uint8 buf[DTLS_FIN_LENGTH]; + dtls_hash_ctx hs_hash; + uint8 *p = buf; + + copy_hs_hash(peer, &hs_hash); + + length = dtls_hash_finalize(hash, &hs_hash); + + dtls_prf(peer->handshake_params->tmp.master_secret, + DTLS_MASTER_SECRET_LENGTH, + label, labellen, + PRF_LABEL(finished), PRF_LABEL_SIZE(finished), + hash, length, + p, DTLS_FIN_LENGTH); + + dtls_debug_dump("server finished MAC", p, DTLS_FIN_LENGTH); + + p += DTLS_FIN_LENGTH; + + assert((buf <= p) && ((unsigned int)(p - buf) <= sizeof(buf))); + + return dtls_send_handshake_msg(ctx, peer, DTLS_HT_FINISHED, + buf, p - buf); +} + +static int +dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer, + uint8 cookie[], size_t cookie_length) { + uint8 buf[DTLS_CH_LENGTH_MAX]; + uint8 *p = buf; + uint8_t cipher_size; + uint8_t extension_size; + int psk; + int ecdsa; + dtls_handshake_parameters_t *handshake = peer->handshake_params; + + psk = is_psk_supported(ctx); + ecdsa = is_ecdsa_supported(ctx, 1); + + cipher_size = 2 + ((ecdsa) ? 2 : 0) + ((psk) ? 2 : 0); + extension_size = 4 + ((ecdsa) ? 6 + 6 + 8 + 6 + 8: 0); + + if (cipher_size == 0) { + dtls_crit("no cipher callbacks implemented\n"); + } + + dtls_int_to_uint16(p, DTLS_VERSION); + p += sizeof(uint16); + + if (cookie_length > DTLS_COOKIE_LENGTH_MAX) { + dtls_warn("the cookie is too long\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + if (cookie_length == 0) { + /* Set 32 bytes of client random data */ + dtls_prng(handshake->tmp.random.client, DTLS_RANDOM_LENGTH); + } + /* we must use the same Client Random as for the previous request */ + memcpy(p, handshake->tmp.random.client, DTLS_RANDOM_LENGTH); + p += DTLS_RANDOM_LENGTH; + + /* session id (length 0) */ + dtls_int_to_uint8(p, 0); + p += sizeof(uint8); + + /* cookie */ + dtls_int_to_uint8(p, cookie_length); + p += sizeof(uint8); + if (cookie_length != 0) { + memcpy(p, cookie, cookie_length); + p += cookie_length; + } + + /* add known cipher(s) */ + dtls_int_to_uint16(p, cipher_size - 2); + p += sizeof(uint16); + + if (ecdsa) { + dtls_int_to_uint16(p, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8); + p += sizeof(uint16); + } + if (psk) { + dtls_int_to_uint16(p, TLS_PSK_WITH_AES_128_CCM_8); + p += sizeof(uint16); + } + + /* compression method */ + dtls_int_to_uint8(p, 1); + p += sizeof(uint8); + + dtls_int_to_uint8(p, TLS_COMPRESSION_NULL); + p += sizeof(uint8); + + /* length of the extensions */ + dtls_int_to_uint16(p, extension_size); + p += sizeof(uint16); + + if (ecdsa) { + /* client certificate type extension */ + dtls_int_to_uint16(p, TLS_EXT_CLIENT_CERTIFICATE_TYPE); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 2); + p += sizeof(uint16); + + /* length of the list */ + dtls_int_to_uint8(p, 1); + p += sizeof(uint8); + + dtls_int_to_uint8(p, TLS_CERT_TYPE_RAW_PUBLIC_KEY); + p += sizeof(uint8); + + /* client certificate type extension */ + dtls_int_to_uint16(p, TLS_EXT_SERVER_CERTIFICATE_TYPE); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 2); + p += sizeof(uint16); + + /* length of the list */ + dtls_int_to_uint8(p, 1); + p += sizeof(uint8); + + dtls_int_to_uint8(p, TLS_CERT_TYPE_RAW_PUBLIC_KEY); + p += sizeof(uint8); + + /* elliptic_curves */ + dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 4); + p += sizeof(uint16); + + /* length of the list */ + dtls_int_to_uint16(p, 2); + p += sizeof(uint16); + + dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES_SECP256R1); + p += sizeof(uint16); + + /* ec_point_formats */ + dtls_int_to_uint16(p, TLS_EXT_EC_POINT_FORMATS); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 2); + p += sizeof(uint16); + + /* number of supported formats */ + dtls_int_to_uint8(p, 1); + p += sizeof(uint8); + + dtls_int_to_uint8(p, TLS_EXT_EC_POINT_FORMATS_UNCOMPRESSED); + p += sizeof(uint8); + + /* signature algorithms extension */ + dtls_int_to_uint16(p, TLS_EXT_SIG_HASH_ALGO); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 4); + p += sizeof(uint16); + + /* supported_signature_algorithms */ + dtls_int_to_uint16(p, 2); + p += sizeof(uint16); + + /* sha256 */ + dtls_int_to_uint8(p, TLS_EXT_SIG_HASH_ALGO_SHA256); + p += sizeof(uint8); + + /* ecdsa */ + dtls_int_to_uint8(p, TLS_EXT_SIG_HASH_ALGO_ECDSA); + p += sizeof(uint8); + + } + /* extended master secret */ + dtls_int_to_uint16(p, TLS_EXT_EXTENDED_MASTER_SECRET); + p += sizeof(uint16); + + /* length of this extension type */ + dtls_int_to_uint16(p, 0); + p += sizeof(uint16); + handshake->extended_master_secret = 1; + + handshake->hs_state.read_epoch = dtls_security_params(peer)->epoch; + assert((buf <= p) && ((unsigned int)(p - buf) <= sizeof(buf))); + + clear_hs_hash(peer); + + return dtls_send_handshake_msg_hash(ctx, peer, &peer->session, + DTLS_HT_CLIENT_HELLO, + buf, p - buf, 1); +} + +static int +check_server_hello(dtls_context_t *ctx, + dtls_peer_t *peer, + uint8 *data, size_t data_length) +{ + dtls_handshake_parameters_t *handshake = peer->handshake_params; + + /* + * Check we have enough data for the ServerHello + * 2 bytes for the version number + * 1 byte for the session id length + * 2 bytes for the selected cipher suite + * 1 byte null compression + */ + if (data_length < DTLS_HS_LENGTH + 2 + DTLS_RANDOM_LENGTH + 1 + 2 + 1) { + dtls_alert("Insufficient length for ServerHello\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + + update_hs_hash(peer, data, data_length); + + /* Get the server's random data and store selected cipher suite + * and compression method (like dtls_update_parameters(). + * Then calculate master secret and wait for ServerHelloDone. When received, + * send ClientKeyExchange (?) and ChangeCipherSpec + ClientFinished. */ + + /* check server version */ + data += DTLS_HS_LENGTH; + data_length -= DTLS_HS_LENGTH; + + if (dtls_uint16_to_int(data) != DTLS_VERSION) { + dtls_alert("unknown DTLS version\n"); + return dtls_alert_fatal_create(DTLS_ALERT_PROTOCOL_VERSION); + } + + data += sizeof(uint16); /* skip version field */ + data_length -= sizeof(uint16); + + /* store server random data */ + memcpy(handshake->tmp.random.server, data, DTLS_RANDOM_LENGTH); + /* skip server random */ + data += DTLS_RANDOM_LENGTH; + data_length -= DTLS_RANDOM_LENGTH; + + SKIP_VAR_FIELD(data, data_length, uint8); /* skip session id */ + /* + * Need to re-check in case session id was not empty + * 2 bytes for the selected cipher suite + * 1 byte null compression + */ + if (data_length < 2 + 1) { + dtls_alert("Insufficient length for ServerHello\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + + /* Check cipher suite. As we offer all we have, it is sufficient + * to check if the cipher suite selected by the server is in our + * list of known cipher suites. Subsets are not supported. */ + handshake->cipher = dtls_uint16_to_int(data); + if (!known_cipher(ctx, handshake->cipher, 1)) { + dtls_alert("unsupported cipher 0x%02x 0x%02x\n", + data[0], data[1]); + return dtls_alert_fatal_create(DTLS_ALERT_INSUFFICIENT_SECURITY); + } + data += sizeof(uint16); + data_length -= sizeof(uint16); + + /* Check if NULL compression was selected. We do not know any other. */ + if (dtls_uint8_to_int(data) != TLS_COMPRESSION_NULL) { + dtls_alert("unsupported compression method 0x%02x\n", data[0]); + return dtls_alert_fatal_create(DTLS_ALERT_INSUFFICIENT_SECURITY); + } + data += sizeof(uint8); + data_length -= sizeof(uint8); + + /* Server may not support extended master secret */ + handshake->extended_master_secret = 0; + return dtls_check_tls_extension(peer, data, data_length, 0); + +error: + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); +} + +static int +check_server_hello_verify_request(dtls_context_t *ctx, + dtls_peer_t *peer, + uint8 *data, size_t data_length) +{ + dtls_hello_verify_t *hv; + int res; + + if (data_length < DTLS_HS_LENGTH + DTLS_HV_LENGTH) + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + + hv = (dtls_hello_verify_t *)(data + DTLS_HS_LENGTH); + if (data_length < DTLS_HS_LENGTH + DTLS_HV_LENGTH + hv->cookie_length) + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + + res = dtls_send_client_hello(ctx, peer, hv->cookie, hv->cookie_length); + + if (res < 0) + dtls_warn("cannot send ClientHello\n"); + + return res; +} + +#ifdef DTLS_ECC +static int +check_server_certificate(dtls_context_t *ctx, + dtls_peer_t *peer, + uint8 *data, size_t data_length) +{ + int err; + dtls_handshake_parameters_t *config = peer->handshake_params; + + update_hs_hash(peer, data, data_length); + + assert(is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(config->cipher)); + + data += DTLS_HS_LENGTH; + + if (dtls_uint24_to_int(data) != DTLS_EC_SUBJECTPUBLICKEY_SIZE) { + dtls_alert("expect length of %zu bytes for certificate\n", + DTLS_EC_SUBJECTPUBLICKEY_SIZE); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + data += sizeof(uint24); + + if (memcmp(data, cert_asn1_header, sizeof(cert_asn1_header))) { + dtls_alert("got an unexpected Subject public key format\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + data += sizeof(cert_asn1_header); + + memcpy(config->keyx.ecdsa.other_pub_x, data, + sizeof(config->keyx.ecdsa.other_pub_x)); + data += sizeof(config->keyx.ecdsa.other_pub_x); + + memcpy(config->keyx.ecdsa.other_pub_y, data, + sizeof(config->keyx.ecdsa.other_pub_y)); + data += sizeof(config->keyx.ecdsa.other_pub_y); + + err = CALL(ctx, verify_ecdsa_key, &peer->session, + config->keyx.ecdsa.other_pub_x, + config->keyx.ecdsa.other_pub_y, + sizeof(config->keyx.ecdsa.other_pub_x)); + if (err < 0) { + dtls_warn("The certificate was not accepted\n"); + return err; + } + + return 0; +} + +static int +check_server_key_exchange_ecdsa(dtls_context_t *ctx, + dtls_peer_t *peer, + uint8 *data, size_t data_length) +{ + (void) ctx; + dtls_handshake_parameters_t *config = peer->handshake_params; + int ret; + unsigned char result_r[DTLS_EC_KEY_SIZE]; + unsigned char result_s[DTLS_EC_KEY_SIZE]; + unsigned char *key_params; + + update_hs_hash(peer, data, data_length); + + assert(is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(config->cipher)); + + data += DTLS_HS_LENGTH; + data_length -= DTLS_HS_LENGTH; + + if (data_length < DTLS_SKEXEC_LENGTH - 2 * DTLS_EC_KEY_SIZE) { + /* + * Some of the ASN.1 integer in the signature may be less than + * DTLS_EC_KEY_SIZE if leading bits are 0. + * dtls_check_ecdsa_signature_elem() knows how to handle this undersize. + */ + dtls_alert("the packet length does not match the expected\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + key_params = data; + + if (dtls_uint8_to_int(data) != TLS_EC_CURVE_TYPE_NAMED_CURVE) { + dtls_alert("Only named curves supported\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + data += sizeof(uint8); + data_length -= sizeof(uint8); + + if (dtls_uint16_to_int(data) != TLS_EXT_ELLIPTIC_CURVES_SECP256R1) { + dtls_alert("secp256r1 supported\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + data += sizeof(uint16); + data_length -= sizeof(uint16); + + if (dtls_uint8_to_int(data) != 1 + 2 * DTLS_EC_KEY_SIZE) { + dtls_alert("expected 65 bytes long public point\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + data += sizeof(uint8); + data_length -= sizeof(uint8); + + if (dtls_uint8_to_int(data) != 4) { + dtls_alert("expected uncompressed public point\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + data += sizeof(uint8); + data_length -= sizeof(uint8); + + memcpy(config->keyx.ecdsa.other_eph_pub_x, data, sizeof(config->keyx.ecdsa.other_eph_pub_y)); + data += sizeof(config->keyx.ecdsa.other_eph_pub_y); + data_length -= sizeof(config->keyx.ecdsa.other_eph_pub_y); + + memcpy(config->keyx.ecdsa.other_eph_pub_y, data, sizeof(config->keyx.ecdsa.other_eph_pub_y)); + data += sizeof(config->keyx.ecdsa.other_eph_pub_y); + data_length -= sizeof(config->keyx.ecdsa.other_eph_pub_y); + + ret = dtls_check_ecdsa_signature_elem(data, data_length, result_r, result_s); + if (ret < 0) { + return ret; + } + data += ret; + data_length -= ret; + + ret = dtls_ecdsa_verify_sig(config->keyx.ecdsa.other_pub_x, config->keyx.ecdsa.other_pub_y, + sizeof(config->keyx.ecdsa.other_pub_x), + config->tmp.random.client, DTLS_RANDOM_LENGTH, + config->tmp.random.server, DTLS_RANDOM_LENGTH, + key_params, + 1 + 2 + 1 + 1 + (2 * DTLS_EC_KEY_SIZE), + result_r, result_s); + + if (ret < 0) { + dtls_alert("wrong signature\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + return 0; +} +#endif /* DTLS_ECC */ + +#ifdef DTLS_PSK +static int +check_server_key_exchange_psk(dtls_context_t *ctx, + dtls_peer_t *peer, + uint8 *data, size_t data_length) +{ + dtls_handshake_parameters_t *config = peer->handshake_params; + uint16_t len; + (void)ctx; + + update_hs_hash(peer, data, data_length); + + assert(is_tls_psk_with_aes_128_ccm_8(config->cipher)); + + data += DTLS_HS_LENGTH; + + if (data_length < DTLS_HS_LENGTH + DTLS_SKEXECPSK_LENGTH_MIN) { + dtls_alert("the packet length does not match the expected\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + + len = dtls_uint16_to_int(data); + data += sizeof(uint16); + + if (len != data_length - DTLS_HS_LENGTH - sizeof(uint16)) { + dtls_warn("the length of the server identity hint is worng\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + + if (len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) { + dtls_warn("please use a smaller server identity hint\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + /* store the psk_identity_hint in config->keyx.psk for later use */ + config->keyx.psk.id_length = len; + memcpy(config->keyx.psk.identity, data, len); + return 0; +} +#endif /* DTLS_PSK */ + +#ifdef DTLS_ECC + +static int +check_certificate_request(dtls_context_t *ctx, + dtls_peer_t *peer, + uint8 *data, size_t data_length) +{ + unsigned int i; + int auth_alg; + int sig_alg; + int hash_alg; + (void)ctx; + + update_hs_hash(peer, data, data_length); + + assert(is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)); + + data += DTLS_HS_LENGTH; + + if (data_length < DTLS_HS_LENGTH + 5) { + dtls_alert("the packet length does not match the expected\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + + i = dtls_uint8_to_int(data); + data += sizeof(uint8); + if (i + 1 > data_length) { + dtls_alert("the certificate types are too long\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + + auth_alg = 0; + for (; i > 0 ; i -= sizeof(uint8)) { + if (dtls_uint8_to_int(data) == TLS_CLIENT_CERTIFICATE_TYPE_ECDSA_SIGN + && auth_alg == 0) + auth_alg = dtls_uint8_to_int(data); + data += sizeof(uint8); + } + + if (auth_alg != TLS_CLIENT_CERTIFICATE_TYPE_ECDSA_SIGN) { + dtls_alert("the request authentication algorithm is not supproted\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + i = dtls_uint16_to_int(data); + data += sizeof(uint16); + if (i + 1 > data_length) { + dtls_alert("the signature and hash algorithm list is too long\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + + hash_alg = 0; + sig_alg = 0; + + /* Signal error if we do not have an even number of remaining + * bytes. */ + if ((i & 1) != 0) { + dtls_alert("illegal certificate request\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + for (; i >= sizeof(uint16); i -= sizeof(uint16)) { + int current_hash_alg; + int current_sig_alg; + + current_hash_alg = dtls_uint8_to_int(data); + data += sizeof(uint8); + current_sig_alg = dtls_uint8_to_int(data); + data += sizeof(uint8); + + if (current_hash_alg == TLS_EXT_SIG_HASH_ALGO_SHA256 && hash_alg == 0 && + current_sig_alg == TLS_EXT_SIG_HASH_ALGO_ECDSA && sig_alg == 0) { + hash_alg = current_hash_alg; + sig_alg = current_sig_alg; + } + } + + if (hash_alg != TLS_EXT_SIG_HASH_ALGO_SHA256 || + sig_alg != TLS_EXT_SIG_HASH_ALGO_ECDSA) { + dtls_alert("no supported hash and signature algorithm\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + /* common names are ignored */ + + peer->handshake_params->do_client_auth = 1; + return 0; +} +#endif /* DTLS_ECC */ + +static int +check_server_hellodone(dtls_context_t *ctx, + dtls_peer_t *peer, + uint8 *data, size_t data_length) +{ + int res; +#ifdef DTLS_ECC + const dtls_ecdsa_key_t *ecdsa_key; +#endif /* DTLS_ECC */ + + dtls_handshake_parameters_t *handshake = peer->handshake_params; + + /* calculate master key, send CCS */ + + update_hs_hash(peer, data, data_length); + +#ifdef DTLS_ECC + if (handshake->do_client_auth) { + + res = CALL(ctx, get_ecdsa_key, &peer->session, &ecdsa_key); + if (res < 0) { + dtls_crit("no ecdsa certificate to send in certificate\n"); + return res; + } + + res = dtls_send_certificate_ecdsa(ctx, peer, ecdsa_key); + + if (res < 0) { + dtls_debug("dtls_server_hello: cannot prepare Certificate record\n"); + return res; + } + } +#endif /* DTLS_ECC */ + + /* send ClientKeyExchange */ + res = dtls_send_client_key_exchange(ctx, peer); + + if (res < 0) { + dtls_debug("cannot send KeyExchange message\n"); + return res; + } + +#ifdef DTLS_ECC + if (handshake->do_client_auth) { + + res = dtls_send_certificate_verify_ecdh(ctx, peer, ecdsa_key); + + if (res < 0) { + dtls_debug("dtls_server_hello: cannot prepare Certificate record\n"); + return res; + } + } +#endif /* DTLS_ECC */ + + res = calculate_key_block(ctx, handshake, peer, + &peer->session, peer->role); + if (res < 0) { + return res; + } + + res = dtls_send_ccs(ctx, peer); + if (res < 0) { + dtls_debug("cannot send CCS message\n"); + return res; + } + + /* and switch cipher suite */ + dtls_security_params_switch(peer); + + /* Client Finished */ + return dtls_send_finished(ctx, peer, PRF_LABEL(client), PRF_LABEL_SIZE(client)); +} + +static int +decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length, + uint8 **cleartext) +{ + dtls_record_header_t *header = DTLS_RECORD_HEADER(packet); + dtls_security_parameters_t *security = dtls_security_params_read_epoch(peer, dtls_get_epoch(header)); + int clen; + + *cleartext = (uint8 *)packet + sizeof(dtls_record_header_t); + clen = length - sizeof(dtls_record_header_t); + + if (!security) { + dtls_alert("No security context for epoch: %i\n", dtls_get_epoch(header)); + return -1; + } + + if (security->cipher == TLS_NULL_WITH_NULL_NULL) { + /* no cipher suite selected */ + return clen; + } else { /* TLS_PSK_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */ + /** + * length of additional_data for the AEAD cipher which consists of + * seq_num(2+6) + type(1) + version(2) + length(2) + */ +#define A_DATA_LEN 13 + unsigned char nonce[DTLS_CCM_BLOCKSIZE]; + unsigned char A_DATA[A_DATA_LEN]; + /* For backwards-compatibility, dtls_encrypt_params is called with + * M= and L=3. */ + const dtls_ccm_params_t params = { nonce, 8, 3 }; + + if (clen < 16) /* need at least IV and MAC */ + return -1; + + memset(nonce, 0, DTLS_CCM_BLOCKSIZE); + memcpy(nonce, dtls_kb_remote_iv(security, peer->role), + dtls_kb_iv_size(security, peer->role)); + + /* read epoch and seq_num from message */ + memcpy(nonce + dtls_kb_iv_size(security, peer->role), *cleartext, 8); + *cleartext += 8; + clen -= 8; /* length without nonce_explicit */ + + dtls_debug_dump("nonce", nonce, DTLS_CCM_BLOCKSIZE); + dtls_debug_dump("key", dtls_kb_remote_write_key(security, peer->role), + dtls_kb_key_size(security, peer->role)); + dtls_debug_dump("ciphertext", *cleartext, clen); + + /* re-use N to create additional data according to RFC 5246, Section 6.2.3.3: + * + * additional_data = seq_num + TLSCompressed.type + + * TLSCompressed.version + TLSCompressed.length; + */ + memcpy(A_DATA, &DTLS_RECORD_HEADER(packet)->epoch, 8); /* epoch and seq_num */ + memcpy(A_DATA + 8, &DTLS_RECORD_HEADER(packet)->content_type, 3); /* type and version */ + + dtls_int_to_uint16(A_DATA + 11, clen - 8); /* length without MAC */ + + clen = dtls_decrypt_params(¶ms, *cleartext, clen, *cleartext, + dtls_kb_remote_write_key(security, peer->role), + dtls_kb_key_size(security, peer->role), + A_DATA, A_DATA_LEN); + if (clen < 0) + dtls_warn("decryption failed\n"); + else { + dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen); + dtls_security_params_free_other(peer); + dtls_debug_dump("cleartext", *cleartext, clen); + } + } + return clen; +} + +static int +dtls_send_hello_request(dtls_context_t *ctx, dtls_peer_t *peer) +{ + return dtls_send_handshake_msg_hash(ctx, peer, &peer->session, + DTLS_HT_HELLO_REQUEST, + NULL, 0, 0); +} + +int +dtls_renegotiate(dtls_context_t *ctx, const session_t *dst) +{ + dtls_peer_t *peer = NULL; + int err; + + peer = dtls_get_peer(ctx, dst); + + if (!peer) { + return -1; + } + if (peer->state != DTLS_STATE_CONNECTED) + return -1; + + peer->handshake_params = dtls_handshake_new(); + if (!peer->handshake_params) + return -1; + + peer->handshake_params->hs_state.mseq_r = 0; + peer->handshake_params->hs_state.mseq_s = 0; + peer->optional_handshake_message = DTLS_HT_NO_OPTIONAL_MESSAGE; + + if (peer->role == DTLS_CLIENT) { + /* send ClientHello with empty Cookie */ + err = dtls_send_client_hello(ctx, peer, NULL, 0); + if (err < 0) + dtls_warn("cannot send ClientHello\n"); + else + peer->state = DTLS_STATE_CLIENTHELLO; + return err; + } else if (peer->role == DTLS_SERVER) { + return dtls_send_hello_request(ctx, peer); + } + + return -1; +} + +/** + * Process verified ClientHellos. + * + * For a verified ClientHello a peer is available/created. This function + * returns the number of bytes that were sent, or \c -1 if an error occurred. + * + * \param ctx The DTLS context to use. + * \param peer The remote peer to exchange the handshake messages. + * \param data The data of the ClientHello containing the proposed crypto parameter. + * \param data_length The actual length of \p data. + * \return Less than zero on error, the number of bytes written otherwise. + */ +static int +handle_verified_client_hello(dtls_context_t *ctx, dtls_peer_t *peer, + uint8 *data, size_t data_length) { + + clear_hs_hash(peer); + + /* First negotiation step: check for PSK + * + * Note that we already have checked that msg is a Handshake + * message containing a ClientHello. dtls_get_cipher() therefore + * does not check again. + */ + int err = dtls_update_parameters(ctx, peer, data, data_length); + if (err < 0) { + dtls_warn("error updating security parameters\n"); + return err; + } + + /* update finish MAC */ + update_hs_hash(peer, data, data_length); + + err = dtls_send_server_hello_msgs(ctx, peer); + if (err < 0) { + return err; + } + if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher) && + is_ecdsa_client_auth_supported(ctx)) + peer->state = DTLS_STATE_WAIT_CLIENTCERTIFICATE; + else + peer->state = DTLS_STATE_WAIT_CLIENTKEYEXCHANGE; + + return err; +} + +static int +handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, uint8 *data, size_t data_length) { + + int err = 0; + const dtls_peer_type role = peer->role; + const dtls_state_t state = peer->state; + + /* This will clear the retransmission buffer if we get an expected + * handshake message. We have to make sure that no handshake message + * should get expected when we still should retransmit something, when + * we do everything accordingly to the DTLS 1.2 standard this should + * not be a problem. */ + dtls_stop_retransmission(ctx, peer); + + /* The following switch construct handles the given message with + * respect to the current internal state for this peer. In case of + * error, it is left with return 0. */ + + dtls_debug("handle handshake packet of type: %s (%i)\n", + dtls_handshake_type_to_name(data[0]), data[0]); + switch (data[0]) { + + /************************************************************************ + * Client states + ************************************************************************/ + case DTLS_HT_HELLO_VERIFY_REQUEST: + + if (state != DTLS_STATE_CLIENTHELLO) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + + err = check_server_hello_verify_request(ctx, peer, data, data_length); + if (err < 0) { + dtls_warn("error in check_server_hello_verify_request err: %i\n", err); + return err; + } + + break; + case DTLS_HT_SERVER_HELLO: + + if (state != DTLS_STATE_CLIENTHELLO) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + + err = check_server_hello(ctx, peer, data, data_length); + if (err < 0) { + dtls_warn("error in check_server_hello err: %i\n", err); + return err; + } + if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)) + peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE; + else { + peer->optional_handshake_message = DTLS_HT_SERVER_KEY_EXCHANGE; + peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; + } + /* update_hs_hash(peer, data, data_length); */ + + break; + +#ifdef DTLS_ECC + case DTLS_HT_CERTIFICATE: + + if ((role == DTLS_CLIENT && state != DTLS_STATE_WAIT_SERVERCERTIFICATE) || + (role == DTLS_SERVER && state != DTLS_STATE_WAIT_CLIENTCERTIFICATE)) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + err = check_server_certificate(ctx, peer, data, data_length); + if (err < 0) { + dtls_warn("error in check_server_certificate err: %i\n", err); + return err; + } + if (role == DTLS_CLIENT) { + peer->state = DTLS_STATE_WAIT_SERVERKEYEXCHANGE; + } else if (role == DTLS_SERVER){ + peer->state = DTLS_STATE_WAIT_CLIENTKEYEXCHANGE; + } + /* update_hs_hash(peer, data, data_length); */ + + break; +#endif /* DTLS_ECC */ + + case DTLS_HT_SERVER_KEY_EXCHANGE: + +#ifdef DTLS_ECC + if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)) { + if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + peer->optional_handshake_message = DTLS_HT_CERTIFICATE_REQUEST; + err = check_server_key_exchange_ecdsa(ctx, peer, data, data_length); + } +#endif /* DTLS_ECC */ +#ifdef DTLS_PSK + if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) { + if (state != DTLS_STATE_WAIT_SERVERHELLODONE || peer->optional_handshake_message != DTLS_HT_SERVER_KEY_EXCHANGE) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + peer->optional_handshake_message = DTLS_HT_NO_OPTIONAL_MESSAGE; + err = check_server_key_exchange_psk(ctx, peer, data, data_length); + } +#endif /* DTLS_PSK */ + + if (err < 0) { + dtls_warn("error in check_server_key_exchange err: %i\n", err); + return err; + } + peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; + /* update_hs_hash(peer, data, data_length); */ + + break; + + case DTLS_HT_SERVER_HELLO_DONE: + + if (state != DTLS_STATE_WAIT_SERVERHELLODONE) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + + err = check_server_hellodone(ctx, peer, data, data_length); + if (err < 0) { + dtls_warn("error in check_server_hellodone err: %i\n", err); + return err; + } + peer->state = DTLS_STATE_WAIT_CHANGECIPHERSPEC; + /* update_hs_hash(peer, data, data_length); */ + + break; + +#ifdef DTLS_ECC + case DTLS_HT_CERTIFICATE_REQUEST: + + if (state != DTLS_STATE_WAIT_SERVERHELLODONE || + peer->optional_handshake_message != DTLS_HT_CERTIFICATE_REQUEST || + !is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + peer->optional_handshake_message = DTLS_HT_NO_OPTIONAL_MESSAGE; + err = check_certificate_request(ctx, peer, data, data_length); + if (err < 0) { + dtls_warn("error in check_certificate_request err: %i\n", err); + return err; + } + + break; +#endif /* DTLS_ECC */ + + case DTLS_HT_FINISHED: + /* expect a Finished message from server */ + + if (state != DTLS_STATE_WAIT_FINISHED) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + + err = check_finished(ctx, peer, data, data_length); + if (err < 0) { + dtls_warn("error in check_finished err: %i\n", err); + return err; + } + if (role == DTLS_SERVER) { + /* send ServerFinished */ + update_hs_hash(peer, data, data_length); + + /* send change cipher spec message and switch to new configuration */ + err = dtls_send_ccs(ctx, peer); + if (err < 0) { + dtls_warn("cannot send CCS message\n"); + return err; + } + + dtls_security_params_switch(peer); + + err = dtls_send_finished(ctx, peer, PRF_LABEL(server), PRF_LABEL_SIZE(server)); + if (err < 0) { + dtls_warn("sending server Finished failed\n"); + return err; + } + } + dtls_handshake_free(peer->handshake_params); + peer->handshake_params = NULL; + dtls_debug("Handshake complete\n"); + check_stack(); + peer->state = DTLS_STATE_CONNECTED; + + /* return here to not increase the message receive counter */ + return err; + + /************************************************************************ + * Server states + ************************************************************************/ + + case DTLS_HT_CLIENT_KEY_EXCHANGE: + /* handle ClientHello, update msg and msglen and goto next if not finished */ + + if (state != DTLS_STATE_WAIT_CLIENTKEYEXCHANGE) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + + err = check_client_keyexchange(ctx, peer->handshake_params, data, data_length); + if (err < 0) { + dtls_warn("error in check_client_keyexchange err: %i\n", err); + return err; + } + update_hs_hash(peer, data, data_length); + + /* Keep hash information for extended master secret */ + memcpy(&peer->handshake_params->hs_state.ext_hash, + &peer->handshake_params->hs_state.hs_hash, + sizeof(peer->handshake_params->hs_state.ext_hash)); + + if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher) && + is_ecdsa_client_auth_supported(ctx)) + peer->state = DTLS_STATE_WAIT_CERTIFICATEVERIFY; + else + peer->state = DTLS_STATE_WAIT_CHANGECIPHERSPEC; + break; + +#ifdef DTLS_ECC + case DTLS_HT_CERTIFICATE_VERIFY: + + if (state != DTLS_STATE_WAIT_CERTIFICATEVERIFY) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + + err = check_client_certificate_verify(ctx, peer, data, data_length); + if (err < 0) { + dtls_warn("error in check_client_certificate_verify err: %i\n", err); + return err; + } + + update_hs_hash(peer, data, data_length); + peer->state = DTLS_STATE_WAIT_CHANGECIPHERSPEC; + break; +#endif /* DTLS_ECC */ + + case DTLS_HT_CLIENT_HELLO: + + if (state != DTLS_STATE_CONNECTED) { + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + + /* At this point, we have a good relationship with this peer. This + * state is left for re-negotiation of key material. */ + /* As per RFC 6347 - section 4.2.8 if this is an attempt to + * rehandshake, we can delete the existing key material + * as the client has demonstrated reachibility by completing + * the cookie exchange */ + if (!peer->handshake_params) { + dtls_handshake_header_t *hs_header = DTLS_HANDSHAKE_HEADER(data); + + peer->handshake_params = dtls_handshake_new(); + if (!peer->handshake_params) + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + + peer->handshake_params->hs_state.mseq_r = dtls_uint16_to_int(hs_header->message_seq); + peer->handshake_params->hs_state.mseq_s = 1; + peer->handshake_params->hs_state.read_epoch = dtls_security_params(peer)->epoch; + } + err = handle_verified_client_hello(ctx, peer, data, data_length); + + /* after sending the ServerHelloDone, we expect the + * ClientKeyExchange (possibly containing the PSK id), + * followed by a ChangeCipherSpec and an encrypted Finished. + */ + + break; + + case DTLS_HT_HELLO_REQUEST: + + if (state != DTLS_STATE_CONNECTED) { + /* we should just ignore such packets when in handshake */ + return 0; + } + + if (!peer->handshake_params) { + peer->handshake_params = dtls_handshake_new(); + if (!peer->handshake_params) + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + + peer->handshake_params->hs_state.mseq_r = 0; + peer->handshake_params->hs_state.mseq_s = 0; + } + + /* send ClientHello with empty Cookie */ + err = dtls_send_client_hello(ctx, peer, NULL, 0); + if (err < 0) { + dtls_warn("cannot send ClientHello\n"); + return err; + } + peer->state = DTLS_STATE_CLIENTHELLO; + peer->optional_handshake_message = DTLS_HT_NO_OPTIONAL_MESSAGE; + break; + + default: + dtls_crit("unhandled message %d\n", data[0]); + return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE); + } + + if (peer->handshake_params && err >= 0) { + peer->handshake_params->hs_state.mseq_r++; + } + + return err; +} + +/** + * Process verified ClientHellos of epoch 0. + * + * This function returns the number of bytes that were sent, or less than zero if an error occurred. + * + * \param ctx The DTLS context to use. + * \param ephemeral_peer The ephemeral remote peer. + * \param data The data received. + * \param data_length The actual length of \p buf. + * \return Less than zero on error, the number of bytes written otherwise. + */ +static int +handle_0_verified_client_hello(dtls_context_t *ctx, dtls_ephemeral_peer_t *ephemeral_peer, + uint8 *data, size_t data_length) +{ + int err; + + dtls_peer_t *peer = dtls_get_peer(ctx, ephemeral_peer->session); + if (peer) { + dtls_debug("removing the peer, new handshake\n"); + dtls_destroy_peer(ctx, peer, 0); + peer = NULL; + } + dtls_debug("creating new peer\n"); + + /* msg contains a ClientHello with a valid cookie, so we can + * safely create the server state machine and continue with + * the handshake. */ + peer = dtls_new_peer(ephemeral_peer->session); + if (!peer) { + dtls_alert("cannot create peer\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + peer->role = DTLS_SERVER; + + dtls_security_parameters_t *security = dtls_security_params(peer); + security->rseq = ephemeral_peer->rseq; + security->cseq.cseq = ephemeral_peer->rseq; + /* bitfield. B0 last seq seen. B1 seq-1 seen, B2 seq-2 seen etc. */ + /* => set all, older "stateless records" will be duplicates. */ + security->cseq.bitfield = (uint64_t) -1L; + + if (dtls_add_peer(ctx, peer) < 0) { + dtls_alert("cannot add peer\n"); + dtls_free_peer(peer); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + peer->handshake_params = dtls_handshake_new(); + if (!peer->handshake_params) { + dtls_alert("cannot create handshake parameter\n"); + DEL_PEER(ctx->peers, peer); + dtls_free_peer(peer); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + peer->handshake_params->hs_state.read_epoch = dtls_security_params(peer)->epoch; + peer->handshake_params->hs_state.mseq_r = ephemeral_peer->mseq; + peer->handshake_params->hs_state.mseq_s = ephemeral_peer->mseq; + + err = handle_verified_client_hello(ctx, peer, data, data_length); + if (err < 0) { + dtls_destroy_peer(ctx, peer, DTLS_DESTROY_CLOSE); + return err; + } + + peer->handshake_params->hs_state.mseq_r++; + + return err; +} + +/** + * Process initial ClientHello of epoch 0. + * + * In order to protect against "denial of service" attacks, RFC6347 + * contains in https://datatracker.ietf.org/doc/html/rfc6347#section-4.2.1 + * the advice to process initial a ClientHello in a stateless fashion. + * If a ClientHello doesn't provide a matching cookie, a HelloVerifyRequest + * is sent back based on the record and handshake message sequence numbers + * contained in the \p ephemeral_peer. If a matching cookie is provided, + * the server starts the handshake, also based on the record and handshake + * message sequence numbers contained in the \p ephemeral_peer. This function + * returns the number of bytes that were sent, or \c -1 if an error occurred. + * + * \param ctx The DTLS context to use. + * \param ephemeral_peer The ephemeral remote peer. + * \param data The data to send. + * \param data_length The actual length of \p buf. + * \return Less than zero on error, the number of bytes written otherwise. + */ +static int +handle_0_client_hello(dtls_context_t *ctx, dtls_ephemeral_peer_t *ephemeral_peer, + uint8 *data, size_t data_length) +{ + dtls_handshake_header_t *hs_header; + size_t packet_length; + size_t fragment_length; + size_t fragment_offset; + int err; + + hs_header = DTLS_HANDSHAKE_HEADER(data); + + dtls_debug("received initial client hello\n"); + + packet_length = dtls_uint24_to_int(hs_header->length); + fragment_length = dtls_uint24_to_int(hs_header->fragment_length); + fragment_offset = dtls_uint24_to_int(hs_header->fragment_offset); + if (packet_length != fragment_length || fragment_offset != 0) { + dtls_warn("No fragment support (yet)\n"); + return 0; + } + if (fragment_length + DTLS_HS_LENGTH != data_length) { + dtls_warn("Fragment size does not match packet size\n"); + return 0; + } + ephemeral_peer->mseq = dtls_uint16_to_int(hs_header->message_seq); + err = dtls_0_verify_peer(ctx, ephemeral_peer, data, data_length); + if (err < 0) { + dtls_warn("error in dtls_verify_peer err: %i\n", err); + return err; + } + + if (err > 0) { + dtls_debug("server hello verify was sent\n"); + return err; + } + + err = handle_0_verified_client_hello(ctx, ephemeral_peer, data, data_length); + if (err < 0) { + dtls_0_send_alert_from_err(ctx, ephemeral_peer, err); + } + return err; +} + +static int +handle_handshake(dtls_context_t *ctx, dtls_peer_t *peer, uint8 *data, size_t data_length) +{ + dtls_handshake_header_t *hs_header; + int res; + size_t packet_length; + size_t fragment_length; + size_t fragment_offset; + + assert(peer); + + if (data_length < DTLS_HS_LENGTH) { + dtls_warn("handshake message too short\n"); + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + } + hs_header = DTLS_HANDSHAKE_HEADER(data); + + dtls_debug("received handshake packet of type: %s (%i)\n", + dtls_handshake_type_to_name(hs_header->msg_type), + hs_header->msg_type); + + packet_length = dtls_uint24_to_int(hs_header->length); + fragment_length = dtls_uint24_to_int(hs_header->fragment_length); + fragment_offset = dtls_uint24_to_int(hs_header->fragment_offset); + if (packet_length != fragment_length || fragment_offset != 0) { + dtls_warn("No fragment support (yet)\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + if (fragment_length + DTLS_HS_LENGTH != data_length) { + dtls_warn("Fragment size does not match packet size\n"); + return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE); + } + + if (!peer->handshake_params) { + + /* This is a ClientHello or Hello Request send when doing TLS renegotiation */ + if (hs_header->msg_type == DTLS_HT_HELLO_REQUEST) { + return handle_handshake_msg(ctx, peer, data, data_length); + } else { + dtls_warn("ignore unexpected handshake message\n"); + return 0; + } + } + uint16_t mseq = dtls_uint16_to_int(hs_header->message_seq); + if (mseq < peer->handshake_params->hs_state.mseq_r) { + dtls_warn("The message sequence number is too small, expected %i, got: %i\n", + peer->handshake_params->hs_state.mseq_r, mseq); + return 0; + } else if (mseq > peer->handshake_params->hs_state.mseq_r) { + /* A packet in between is missing, buffer this packet. */ + netq_t *n; + + dtls_info("The message sequence number is too larger, expected %i, got: %i\n", + peer->handshake_params->hs_state.mseq_r, mseq); + + /* TODO: only add packet that are not too new. */ + if (data_length > DTLS_MAX_BUF) { + dtls_warn("the packet is too big to buffer for reoder\n"); + return 0; + } + + netq_t *node = netq_head(&peer->handshake_params->reorder_queue); + while (node) { + dtls_handshake_header_t *node_header = DTLS_HANDSHAKE_HEADER(node->data); + if (dtls_uint16_to_int(node_header->message_seq) == mseq) { + dtls_warn("a packet with this sequence number is already stored\n"); + return 0; + } + node = netq_next(node); + } + + n = netq_node_new(data_length); + if (!n) { + dtls_warn("no space in reorder buffer\n"); + return 0; + } + + n->peer = peer; + n->length = data_length; + memcpy(n->data, data, data_length); + + if (!netq_insert_node(&peer->handshake_params->reorder_queue, n)) { + dtls_warn("cannot add packet to reorder buffer\n"); + netq_node_free(n); + } + dtls_info("Added packet %u for reordering\n", mseq); + return 0; + } else if (mseq == peer->handshake_params->hs_state.mseq_r) { + /* Found the expected packet, use this and all the buffered packet */ + int next = 1; + + res = handle_handshake_msg(ctx, peer, data, data_length); + if (res < 0) + return res; + + /* We do not know in which order the packet are in the list just search the list for every packet. */ + while (next && peer->handshake_params) { + next = 0; + netq_t *node = netq_head(&peer->handshake_params->reorder_queue); + while (node) { + dtls_handshake_header_t *node_header = DTLS_HANDSHAKE_HEADER(node->data); + + if (dtls_uint16_to_int(node_header->message_seq) == peer->handshake_params->hs_state.mseq_r) { + netq_remove(&peer->handshake_params->reorder_queue, node); + next = 1; + res = handle_handshake_msg(ctx, peer, node->data, node->length); + + /* free message data */ + netq_node_free(node); + + if (res < 0) { + return res; + } + + break; + } else { + node = netq_next(node); + } + } + } + return res; + } + assert(0); + return 0; +} + +static int +handle_ccs(dtls_context_t *ctx, dtls_peer_t *peer, + uint8 *record_header, uint8 *data, size_t data_length) +{ + int err; + (void)record_header; + + assert(peer); + + /* A CCS message is handled after a KeyExchange message was + * received from the client. When security parameters have been + * updated successfully and a ChangeCipherSpec message was sent + * by ourself, the security context is switched and the record + * sequence number is reset. */ + + if (peer->state != DTLS_STATE_WAIT_CHANGECIPHERSPEC) { + dtls_warn("unexpected ChangeCipherSpec during handshake\n"); + return 0; + } + + if (data_length != 1 || data[0] != 1) + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + + /* Just change the cipher when we are on the same epoch */ + if (peer->role == DTLS_SERVER) { + err = calculate_key_block(ctx, peer->handshake_params, peer, + &peer->session, peer->role); + if (err < 0) { + return err; + } + } + + peer->handshake_params->hs_state.read_epoch++; + assert(peer->handshake_params->hs_state.read_epoch > 0); + peer->state = DTLS_STATE_WAIT_FINISHED; + + return 0; +} + +/** + * Handles incoming Alert messages. This function returns \c 1 if the + * connection should be closed and the peer is to be invalidated. + * \c 0 if the Alert is valid, but not closing the connection. + * Less than \c 0 if the Alert could not be decoded. + */ +static int +handle_alert(dtls_context_t *ctx, dtls_peer_t *peer, + uint8 *record_header, uint8 *data, size_t data_length) { + int free_peer = 0; /* indicates whether to free peer */ + int close_notify = 0; + (void)record_header; + + assert(peer); + + if (data_length < 2) + return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR); + + dtls_info("** Alert: level %d, description %d\n", data[0], data[1]); + + /* The peer object is invalidated for FATAL alerts and close + * notifies. This is done in two steps.: First, remove the object + * from our list of peers. After that, the event handler callback is + * invoked with the still existing peer object. Finally, the storage + * used by peer is released. + */ + close_notify = data[1] == DTLS_ALERT_CLOSE_NOTIFY; + if (data[0] == DTLS_ALERT_LEVEL_FATAL || close_notify) { + if (close_notify) + dtls_info("invalidate peer (Close Notify)\n"); + else + dtls_alert("%d invalidate peer\n", data[1]); + + DEL_PEER(ctx->peers, peer); + +#ifdef WITH_CONTIKI +#ifndef NDEBUG + PRINTF("removed peer ["); + PRINT6ADDR(&peer->session.addr); + PRINTF("]:%d\n", uip_ntohs(peer->session.port)); +#endif +#endif /* WITH_CONTIKI */ + + free_peer = 1; + + } + + (void)CALL(ctx, event, &peer->session, + (dtls_alert_level_t)data[0], (unsigned short)data[1]); + if (close_notify) { + /* If state is DTLS_STATE_CLOSING, we have already sent a + * close_notify so, do not send that again. */ + if (peer->state != DTLS_STATE_CLOSING) { + peer->state = DTLS_STATE_CLOSING; + dtls_send_alert(ctx, peer, DTLS_ALERT_LEVEL_WARNING, + DTLS_ALERT_CLOSE_NOTIFY); + } else + peer->state = DTLS_STATE_CLOSED; + } + + if (free_peer) { + dtls_destroy_peer(ctx, peer, DTLS_DESTROY_CLOSE); + } + + return free_peer; +} + +static int dtls_alert_send_from_err(dtls_context_t *ctx, dtls_peer_t *peer, int err) +{ + assert(peer); + + if (dtls_is_alert(err)) { + dtls_alert_level_t level = ((-err) & 0xff00) >> 8; + dtls_alert_t desc = (-err) & 0xff; + peer->state = DTLS_STATE_CLOSING; + return dtls_send_alert(ctx, peer, level, desc); + } else if (err == -1) { + peer->state = DTLS_STATE_CLOSING; + return dtls_send_alert(ctx, peer, DTLS_ALERT_LEVEL_FATAL, DTLS_ALERT_INTERNAL_ERROR); + } + return -1; +} + +/** + * Handles incoming data as DTLS message from given peer. + */ +int +dtls_handle_message(dtls_context_t *ctx, + session_t *session, + uint8 *msg, int msglen) { + dtls_peer_t *peer = NULL; + unsigned int rlen; /* record length */ + uint8 *data; /* (decrypted) payload */ + int data_length; /* length of decrypted payload + (without MAC and padding) */ + int err; + + /* check for ClientHellos of epoch 0, maybe a peer's start over */ + if ((rlen = is_record(msg,msglen))) { + dtls_record_header_t *header = DTLS_RECORD_HEADER(msg); + uint16_t epoch = dtls_get_epoch(header); + uint8_t content_type = dtls_get_content_type(header); + const char* content_type_name = dtls_message_type_to_name(content_type); + if (content_type_name) { + dtls_info("received message (%d bytes), starting with '%s', epoch %u\n", msglen, content_type_name, epoch); + } else { + dtls_info("received message (%d bytes), starting with unknown ct '%u', epoch %u\n", msglen, content_type, epoch); + } + if (DTLS_CT_HANDSHAKE == content_type && 0 == epoch) { + dtls_info("handshake message epoch 0\n"); + data = msg + DTLS_RH_LENGTH; + data_length = rlen - DTLS_RH_LENGTH; + if ((size_t) data_length < DTLS_HS_LENGTH) { + dtls_warn("ignore too short handshake message\n"); + return 0; + } + dtls_handshake_header_t *hs_header = DTLS_HANDSHAKE_HEADER(data); + if (hs_header->msg_type == DTLS_HT_CLIENT_HELLO) { + /* + * Stateless processing of ClientHello in epoch 0. + * + * In order to protect against "denial of service" attacks, RFC6347 + * contains in https://datatracker.ietf.org/doc/html/rfc6347#section-4.2.1 + * the advice to process initial a ClientHello in a stateless fashion. + * Therefore no peer is used, but a ephemeral peer with the required + * record and handshake sequence numbers along with the ip-endoint. + * If the ClientHello contains no matching cookie, the client will be + * challenged using a HelloVerifyRequest. If a matching cookie is provided, + * a peer is created and the handshake is continued using the state of the + * peer. + */ + dtls_info("client_hello epoch 0\n"); + dtls_ephemeral_peer_t ephemeral_peer = {session, dtls_uint48_to_int(header->sequence_number), 0}; + err = handle_0_client_hello(ctx, &ephemeral_peer, data, data_length); + if (err < 0) { + dtls_warn("error while handling handshake packet\n"); + } + return 0; + } + } + } else { + /** no payload */ + return 0; + } + + /* check if we have DTLS state for addr/port/ifindex */ + peer = dtls_get_peer(ctx, session); + + if (!peer) { + dtls_debug("dtls_handle_message: PEER NOT FOUND\n"); + dtls_dsrv_log_addr(DTLS_LOG_DEBUG, "peer addr", session); + /** no peer, no ClientHello => drop it */ + return 0; + } else { + dtls_debug("dtls_handle_message: FOUND PEER\n"); + } + + while ((rlen = is_record(msg,msglen))) { + dtls_record_header_t *header = DTLS_RECORD_HEADER(msg); + uint16_t epoch = dtls_get_epoch(header); + uint8_t content_type = dtls_get_content_type(header); + const char* content_type_name = dtls_message_type_to_name(content_type); + uint64_t pkt_seq_nr = dtls_uint48_to_int(header->sequence_number); + + if (content_type_name) { + dtls_info("got '%s' epoch %u sequence %" PRIu64 " (%d bytes)\n", + content_type_name, epoch, pkt_seq_nr, rlen); + } + else { + dtls_info("got 'unknown %u' epoch %u sequence %" PRIu64 " (%d bytes)\n", + content_type, epoch, pkt_seq_nr, rlen); + } + + dtls_security_parameters_t *security = dtls_security_params_read_epoch(peer, epoch); + if (!security) { + if (content_type_name) { + dtls_warn("No security context for epoch: %i (%s)\n", epoch, content_type_name); + } else { + dtls_warn("No security context for epoch: %i (%u)\n", epoch, content_type); + } + data_length = -1; + } else { + dtls_debug("bitfield is %" PRIx64 " sequence base %" PRIx64 " rseqn %" PRIx64 "\n", + security->cseq.bitfield, security->cseq.cseq, pkt_seq_nr); + if (security->cseq.bitfield == 0) { /* first message of epoch */ + data_length = decrypt_verify(peer, msg, rlen, &data); + if(data_length > 0) { + security->cseq.cseq = pkt_seq_nr; + security->cseq.bitfield = 1; + dtls_debug("init bitfield is %" PRIx64 " sequence base %" PRIx64 "\n", + security->cseq.bitfield, security->cseq.cseq); + } + } else { + int64_t seqn_diff = (int64_t)(pkt_seq_nr - security->cseq.cseq); + if(seqn_diff == 0) { + /* already seen */ + dtls_debug("Drop: duplicate packet arrived (cseq=%" PRIu64 " bitfield's start)\n", pkt_seq_nr); + return 0; + } else if (seqn_diff < 0) { /* older pkt_seq_nr < security->cseq.cseq */ + if (seqn_diff < -63) { /* too old */ + dtls_debug("Drop: packet from before the bitfield arrived\n"); + return 0; + } + uint64_t seqn_bit = ((uint64_t)1 << -seqn_diff); + if (security->cseq.bitfield & seqn_bit) { /* seen it */ + dtls_debug("Drop: duplicate packet arrived (bitfield)\n"); + return 0; + } + dtls_debug("Packet arrived out of order\n"); + data_length = decrypt_verify(peer, msg, rlen, &data); + if(data_length > 0) { + security->cseq.bitfield |= seqn_bit; + dtls_debug("update bitfield is %" PRIx64 " keep sequence base %" PRIx64 "\n", + security->cseq.bitfield, security->cseq.cseq); + } + } else { /* newer pkt_seq_nr > security->cseq.cseq */ + data_length = decrypt_verify(peer, msg, rlen, &data); + if(data_length > 0) { + security->cseq.cseq = pkt_seq_nr; + /* bitfield. B0 last seq seen. B1 seq-1 seen, B2 seq-2 seen etc. */ + if (seqn_diff > 63) { + /* reset bitfield if new packet number is beyond its boundaries */ + security->cseq.bitfield = 1; + } else { + /* shift bitfield */ + security->cseq.bitfield <<= seqn_diff; + security->cseq.bitfield |= 1; + } + dtls_debug("update bitfield is %" PRIx64 " new sequence base %" PRIx64 "\n", + security->cseq.bitfield, security->cseq.cseq); + } + } + } + } + if (data_length < 0) { + dtls_info("decrypt_verify() failed, drop message.\n"); + return 0; + } + + dtls_debug_hexdump("receive header", msg, sizeof(dtls_record_header_t)); + dtls_debug_hexdump("receive unencrypted", data, data_length); + + /* Handle received record according to the first byte of the + * message, i.e. the subprotocol. We currently do not support + * combining multiple fragments of one type into a single + * record. */ + + switch (content_type) { + + case DTLS_CT_CHANGE_CIPHER_SPEC: + err = handle_ccs(ctx, peer, msg, data, data_length); + if (err < 0) { + dtls_warn("error while handling ChangeCipherSpec message\n"); + dtls_stop_retransmission(ctx, peer); + dtls_alert_send_from_err(ctx, peer, err); + + /* invalidate peer */ + dtls_destroy_peer(ctx, peer, DTLS_DESTROY_CLOSE); + peer = NULL; + + return err; + } + break; + + case DTLS_CT_ALERT: + if (peer->state == DTLS_STATE_WAIT_FINISHED) { + dtls_info("** drop alert before Finish.\n"); + return 0; + } + err = handle_alert(ctx, peer, msg, data, data_length); + if (err < 0) { + /* Alert could not be decoded, ignore it */ + dtls_info("** drop alert, decode error.\n"); + return err; + } + if (err == 1) { + if (data[1] == DTLS_ALERT_CLOSE_NOTIFY) + dtls_info("received close_notify alert, peer has been invalidated\n"); + else + dtls_warn("received fatal alert, peer has been invalidated\n"); + /* handle alert has invalidated peer */ + peer = NULL; + err = -1; + } else { + dtls_stop_retransmission(ctx, peer); + } + break; + + case DTLS_CT_HANDSHAKE: + + err = handle_handshake(ctx, peer, data, data_length); + if (err < 0) { + dtls_warn("error while handling handshake packet\n"); + dtls_alert_send_from_err(ctx, peer, err); + + if (peer && DTLS_ALERT_LEVEL_FATAL == ((-err) & 0xff00) >> 8) { + /* invalidate peer */ + peer->state = DTLS_STATE_CLOSED; + dtls_stop_retransmission(ctx, peer); + dtls_destroy_peer(ctx, peer, DTLS_DESTROY_CLOSE); + peer = NULL; + } + return err; + } + if (peer && peer->state == DTLS_STATE_CONNECTED) { + /* stop retransmissions */ + dtls_stop_retransmission(ctx, peer); + CALL(ctx, event, &peer->session, 0, DTLS_EVENT_CONNECTED); + } + break; + + case DTLS_CT_APPLICATION_DATA: + if (epoch == 0 || peer->state == DTLS_STATE_WAIT_FINISHED) { + dtls_info("** drop application data before Finish.\n"); + return 0; + } + dtls_info("** application data:\n"); + dtls_stop_retransmission(ctx, peer); + CALL(ctx, read, &peer->session, data, data_length); + break; + default: + dtls_info("dropped unknown message of type %d\n",msg[0]); + } + + /* advance msg by length of ciphertext */ + msg += rlen; + msglen -= rlen; + } + + return 0; +} + +dtls_context_t * +dtls_new_context(void *app_data) { + dtls_context_t *c; + dtls_tick_t now; + + dtls_ticks(&now); + dtls_prng_init(now); + + c = malloc_context(); + if (!c) + goto error; + + memset(c, 0, sizeof(dtls_context_t)); + c->app = app_data; + +#ifdef WITH_CONTIKI + process_start(&dtls_retransmit_process, (char *)c); + PROCESS_CONTEXT_BEGIN(&dtls_retransmit_process); + /* the retransmit timer must be initialized to some large value */ + etimer_set(&c->retransmit_timer, 0xFFFF); + PROCESS_CONTEXT_END(&coap_retransmit_process); +#endif /* WITH_CONTIKI */ + + if (dtls_prng(c->cookie_secret, DTLS_COOKIE_SECRET_LENGTH)) + c->cookie_secret_age = now; + else + goto error; + + return c; + + error: + dtls_alert("cannot create DTLS context\n"); + if (c) + dtls_free_context(c); + return NULL; +} + +void dtls_reset_peer(dtls_context_t *ctx, dtls_peer_t *peer) +{ + dtls_destroy_peer(ctx, peer, DTLS_DESTROY_CLOSE); +} + +void +dtls_free_context(dtls_context_t *ctx) { + dtls_peer_t *p, *tmp; + + if (!ctx) { + return; + } + + if (ctx->peers) { +#ifdef DTLS_PEERS_NOHASH + LL_FOREACH_SAFE(ctx->peers, p, tmp) { +#else /* DTLS_PEERS_NOHASH */ + HASH_ITER(hh, ctx->peers, p, tmp) { +#endif /* DTLS_PEERS_NOHASH */ + dtls_destroy_peer(ctx, p, DTLS_DESTROY_CLOSE); + } + } + + free_context(ctx); +} + +int +dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer) { + int res; + + assert(peer); + if (!peer) + return -1; + + /* check if the same peer is already in our list */ + if (peer == dtls_get_peer(ctx, &peer->session)) { + dtls_debug("found peer, try to re-connect\n"); + res = dtls_renegotiate(ctx, &peer->session); + return res < 0 ? -1 : 0; + } + + /* set local peer role to client, remote is server */ + peer->role = DTLS_CLIENT; + + if (dtls_add_peer(ctx, peer) < 0) { + dtls_alert("cannot add peer\n"); + return -1; + } + + /* send ClientHello with empty Cookie */ + peer->handshake_params = dtls_handshake_new(); + if (!peer->handshake_params) + return -1; + + peer->handshake_params->hs_state.mseq_r = 0; + peer->handshake_params->hs_state.mseq_s = 0; + res = dtls_send_client_hello(ctx, peer, NULL, 0); + if (res < 0) + dtls_warn("cannot send ClientHello\n"); + else + peer->state = DTLS_STATE_CLIENTHELLO; + + return res; +} + +int +dtls_connect(dtls_context_t *ctx, const session_t *dst) { + dtls_peer_t *peer; + int res; + + peer = dtls_get_peer(ctx, dst); + + if (!peer) + peer = dtls_new_peer(dst); + + if (!peer) { + dtls_crit("cannot create new peer\n"); + return -1; + } + + res = dtls_connect_peer(ctx, peer); + + /* Invoke event callback to indicate connection attempt or + * re-negotiation. */ + if (res > 0) { + CALL(ctx, event, &peer->session, 0, DTLS_EVENT_CONNECT); + } else if (res == 0) { + CALL(ctx, event, &peer->session, 0, DTLS_EVENT_RENEGOTIATE); + } + + return res; +} + +static void +dtls_retransmit(dtls_context_t *context, netq_t *node) { + if (!context || !node) + return; + + /* re-initialize timeout when maximum number of retransmissions are not reached yet */ + if (node->retransmit_cnt < DTLS_DEFAULT_MAX_RETRANSMIT) { +#ifndef DTLS_CONSTRAINED_STACK + unsigned char sendbuf[DTLS_MAX_BUF]; +#endif /* ! DTLS_CONSTRAINED_STACK */ + size_t len = sizeof(sendbuf); + int err; + unsigned char *data = node->data; + size_t length = node->length; + dtls_tick_t now; + dtls_security_parameters_t *security = dtls_security_params_epoch(node->peer, node->epoch); + + if (node->job == TIMEOUT) { + if (node->type == DTLS_CT_ALERT) { + dtls_debug("** alert times out\n"); + handle_alert(context, node->peer, NULL, data, length); + } + netq_node_free(node); + return; + } + +#ifdef DTLS_CONSTRAINED_STACK + dtls_mutex_lock(&static_mutex); +#endif /* DTLS_CONSTRAINED_STACK */ + + dtls_ticks(&now); + node->retransmit_cnt++; + node->t = now + (node->timeout << node->retransmit_cnt); + netq_insert_node(&context->sendqueue, node); + + if (node->type == DTLS_CT_HANDSHAKE) { + dtls_handshake_header_t *hs_header = DTLS_HANDSHAKE_HEADER(data); + dtls_debug("** retransmit handshake packet of type: %s (%i)\n", + dtls_handshake_type_to_name(hs_header->msg_type), + hs_header->msg_type); + } else { + dtls_debug("** retransmit packet\n"); + } + + err = dtls_prepare_record(node->peer, security, node->type, &data, &length, + 1, sendbuf, &len); + if (err < 0) { + dtls_warn("can not retransmit packet, err: %i\n", err); + goto return_unlock; + } + dtls_debug_hexdump("retransmit header", sendbuf, sizeof(dtls_record_header_t)); + dtls_debug_hexdump("retransmit unencrypted", node->data, node->length); + + (void)CALL(context, write, &node->peer->session, sendbuf, len); +return_unlock: +#ifdef DTLS_CONSTRAINED_STACK + dtls_mutex_unlock(&static_mutex); +#endif /* DTLS_CONSTRAINED_STACK */ + + return; + } + + /* no more retransmissions, remove node from system */ + + dtls_debug("** removed transaction\n"); + + /* And finally delete the node */ + netq_node_free(node); +} + +static void +dtls_stop_retransmission(dtls_context_t *context, dtls_peer_t *peer) { + netq_t *node; + node = netq_head(&context->sendqueue); + + while (node) { + if (dtls_session_equals(&node->peer->session, &peer->session)) { + netq_t *tmp = node; + node = netq_next(node); + netq_remove(&context->sendqueue, tmp); + netq_node_free(tmp); + } else + node = netq_next(node); + } +} + +void +dtls_check_retransmit(dtls_context_t *context, clock_time_t *next) { + dtls_tick_t now; + netq_t *node = netq_head(&context->sendqueue); + + dtls_ticks(&now); + /* comparison considering 32bit overflow */ + while (node && DTLS_IS_BEFORE_TIME(node->t, now)) { + netq_pop_first(&context->sendqueue); + dtls_retransmit(context, node); + node = netq_head(&context->sendqueue); + } + + if (next) { + *next = node ? node->t : 0; + } +} + +#ifdef WITH_CONTIKI +/*---------------------------------------------------------------------------*/ +/* message retransmission */ +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(dtls_retransmit_process, ev, data) +{ + clock_time_t now; + netq_t *node; + + PROCESS_BEGIN(); + + dtls_debug("Started DTLS retransmit process\r\n"); + + while(1) { + PROCESS_YIELD(); + if (ev == PROCESS_EVENT_TIMER) { + if (etimer_expired(&the_dtls_context.retransmit_timer)) { + + node = netq_head(&the_dtls_context.sendqueue); + + now = clock_time(); + if (node && node->t <= now) { + netq_pop_first(&the_dtls_context.sendqueue); + dtls_retransmit(&the_dtls_context, node); + node = netq_head(&the_dtls_context.sendqueue); + } + + /* need to set timer to some value even if no nextpdu is available */ + if (node) { + etimer_set(&the_dtls_context.retransmit_timer, + node->t <= now ? 1 : node->t - now); + } else { + etimer_set(&the_dtls_context.retransmit_timer, 0xFFFF); + } + } + } + } + + PROCESS_END(); +} +#endif /* WITH_CONTIKI */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls.h new file mode 100644 index 000000000..a7c6c6410 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls.h @@ -0,0 +1,755 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * Achim Kraus - session recovery + * + *******************************************************************************/ + +/** + * @file dtls.h + * @brief High level DTLS API and visible structures. + */ + +#ifndef _DTLS_DTLS_H_ +#define _DTLS_DTLS_H_ + +#include + +#include "tinydtls.h" + +#include "state.h" +#include "peer.h" + +#include "uthash.h" + +#include "alert.h" +#include "crypto.h" +#include "hmac.h" + +#include "global.h" +#include "dtls_time.h" + +#ifndef DTLSv12 +#define DTLS_VERSION 0xfeff /* DTLS v1.1 */ +#else +#define DTLS_VERSION 0xfefd /* DTLS v1.2 */ +#endif + +typedef enum dtls_credentials_type_t { + DTLS_PSK_HINT, DTLS_PSK_IDENTITY, DTLS_PSK_KEY +} dtls_credentials_type_t; + +typedef struct dtls_ecdsa_key_t { + dtls_ecdh_curve curve; + const unsigned char *priv_key; /** < private key as bytes > */ + const unsigned char *pub_key_x; /** < x part of the public key for the given private key > */ + const unsigned char *pub_key_y; /** < y part of the public key for the given private key > */ +} dtls_ecdsa_key_t; + +/** Length of the secret that is used for generating Hello Verify cookies. */ +#define DTLS_COOKIE_SECRET_LENGTH 12 + +struct dtls_context_t; + +/** + * This structure contains callback functions used by tinydtls to + * communicate with the application. At least the write function must + * be provided. It is called by the DTLS state machine to send packets + * over the network. The read function is invoked to deliver decrypted + * and verfified application data. The third callback is an event + * handler function that is called when alert messages are encountered + * or events generated by the library have occured. + */ +typedef struct { + /** + * Called from dtls_handle_message() to send DTLS packets over the + * network. The callback function must use the network interface + * denoted by session->ifindex to send the data. + * + * @param ctx The current DTLS context. + * @param session The session object, including the address of the + * remote peer where the data shall be sent. + * @param buf The data to send. + * @param len The actual length of @p buf. + * @return The callback function must return the number of bytes + * that were sent, or a value less than zero to indicate an + * error. + */ + int (*write)(struct dtls_context_t *ctx, + session_t *session, uint8 *buf, size_t len); + + /** + * Called from dtls_handle_message() deliver application data that was + * received on the given session. The data is delivered only after + * decryption and verification have succeeded. + * + * @param ctx The current DTLS context. + * @param session The session object, including the address of the + * data's origin. + * @param buf The received data packet. + * @param len The actual length of @p buf. + * @return ignored + */ + int (*read)(struct dtls_context_t *ctx, + session_t *session, uint8 *buf, size_t len); + + /** + * The event handler is called when a message from the alert + * protocol is received or the state of the DTLS session changes. + * + * @param ctx The current dtls context. + * @param session The session object that was affected. + * @param level The alert level or @c 0 when an event ocurred that + * is not an alert. + * @param code Values less than @c 256 indicate alerts, while + * @c 256 or greater indicate internal DTLS session changes. + * @return ignored + */ + int (*event)(struct dtls_context_t *ctx, session_t *session, + dtls_alert_level_t level, unsigned short code); + +#ifdef DTLS_PSK + /** + * Called during handshake to get information related to the + * psk key exchange. The type of information requested is + * indicated by @p type which will be one of DTLS_PSK_HINT, + * DTLS_PSK_IDENTITY, or DTLS_PSK_KEY. The called function + * must store the requested item in the buffer @p result of + * size @p result_length. On success, the function must return + * the actual number of bytes written to @p result, of a + * value less than zero on error. The parameter @p desc may + * contain additional request information (e.g. the psk_identity + * for which a key is requested when @p type == @c DTLS_PSK_KEY. + * + * @param ctx The current dtls context. + * @param session The session where the key will be used. + * @param type The type of the requested information. + * @param desc Additional request information + * @param desc_len The actual length of desc. + * @param result Must be filled with the requested information. + * @param result_length Maximum size of @p result. + * @return The number of bytes written to @p result or a value + * less than zero on error. + */ + int (*get_psk_info)(struct dtls_context_t *ctx, + const session_t *session, + dtls_credentials_type_t type, + const unsigned char *desc, size_t desc_len, + unsigned char *result, size_t result_length); + +#endif /* DTLS_PSK */ + +#ifdef DTLS_ECC + /** + * Called during handshake to get the server's or client's ecdsa + * key used to authenticate this server or client in this + * session. If found, the key must be stored in @p result and + * the return value must be @c 0. If not found, @p result is + * undefined and the return value must be less than zero. + * + * If ECDSA should not be supported, set this pointer to NULL. + * + * Implement this if you want to provide your own certificate to + * the other peer. This is mandatory for a server providing ECDSA + * support and optional for a client. A client doing DTLS client + * authentication has to implementing this callback. + * + * @param ctx The current dtls context. + * @param session The session where the key will be used. + * @param result Must be set to the key object to used for the given + * session. + * @return @c 0 if result is set, or less than zero on error. + */ + int (*get_ecdsa_key)(struct dtls_context_t *ctx, + const session_t *session, + const dtls_ecdsa_key_t **result); + + /** + * Called during handshake to check the peer's pubic key in this + * session. If the public key matches the session and should be + * considerated valid the return value must be @c 0. If not valid, + * the return value must be less than zero. + * + * If ECDSA should not be supported, set this pointer to NULL. + * + * Implement this if you want to verify the other peers public key. + * This is mandatory for a DTLS client doing based ECDSA + * authentication. A server implementing this will request the + * client to do DTLS client authentication. + * + * @param ctx The current dtls context. + * @param session The session where the key will be used. + * @param other_pub_x x component of the public key. + * @param other_pub_y y component of the public key. + * @return @c 0 if public key matches, or less than zero on error. + * error codes: + * return dtls_alert_fatal_create(DTLS_ALERT_BAD_CERTIFICATE); + * return dtls_alert_fatal_create(DTLS_ALERT_UNSUPPORTED_CERTIFICATE); + * return dtls_alert_fatal_create(DTLS_ALERT_CERTIFICATE_REVOKED); + * return dtls_alert_fatal_create(DTLS_ALERT_CERTIFICATE_EXPIRED); + * return dtls_alert_fatal_create(DTLS_ALERT_CERTIFICATE_UNKNOWN); + * return dtls_alert_fatal_create(DTLS_ALERT_UNKNOWN_CA); + */ + int (*verify_ecdsa_key)(struct dtls_context_t *ctx, + const session_t *session, + const unsigned char *other_pub_x, + const unsigned char *other_pub_y, + size_t key_size); +#endif /* DTLS_ECC */ +} dtls_handler_t; + +struct netq_t; + +/** Holds global information of the DTLS engine. */ +typedef struct dtls_context_t { + unsigned char cookie_secret[DTLS_COOKIE_SECRET_LENGTH]; + clock_time_t cookie_secret_age; /**< the time the secret has been generated */ + + dtls_peer_t *peers; /**< peer hash map */ +#ifdef WITH_CONTIKI + struct etimer retransmit_timer; /**< fires when the next packet must be sent */ +#endif /* WITH_CONTIKI */ + + struct netq_t *sendqueue; /**< the packets to send */ + + void *app; /**< application-specific data */ + + dtls_handler_t *h; /**< callback handlers */ +} dtls_context_t; + +/** + * This function initializes the tinyDTLS memory management and must + * be called first. + */ +void dtls_init(void); + +/** + * Creates a new context object. The storage allocated for the new + * object must be released with dtls_free_context(). */ +dtls_context_t *dtls_new_context(void *app_data); + +/** Releases any storage that has been allocated for \p ctx. */ +void dtls_free_context(dtls_context_t *ctx); + +#define dtls_set_app_data(CTX,DATA) ((CTX)->app = (DATA)) +#define dtls_get_app_data(CTX) ((CTX)->app) + +/** Sets the callback handler object for @p ctx to @p h. */ +static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) { + ctx->h = h; +} + +/** + * Establishes a DTLS channel with the specified remote peer @p dst. + * This function returns @c 0 if that channel already exists, a value + * greater than zero when a new ClientHello message was sent, and + * a value less than zero on error. + * + * @param ctx The DTLS context to use. + * @param dst The remote party to connect to. + * @return A value less than zero on error, greater or equal otherwise. + */ +int dtls_connect(dtls_context_t *ctx, const session_t *dst); + +/** + * Establishes a DTLS channel with the specified remote peer. + * This function returns @c 0 if that channel already exists and a renegotiate + * was initiated, a value greater than zero when a new ClientHello message was + * sent, and a value less than zero on error. + * + * @param ctx The DTLS context to use. + * @param peer The peer object that describes the session. + * @return A value less than zero on error, greater or equal otherwise. + */ +int dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer); + +/** + * Closes the DTLS connection associated with @p remote. This function + * returns zero on success, and a value less than zero on error. + */ +int dtls_close(dtls_context_t *ctx, const session_t *remote); + +/** + * Renegotiates a DTLS channel based on the specified session. + * This function returns a value greater than zero when a new ClientHello + * message was sent, and a value less than zero on error. + * + * @param ctx The DTLS context to use. + * @param dst The session object that describes the existing session. + * @return A value less than zero on error, greater otherwise. + */ +int dtls_renegotiate(dtls_context_t *ctx, const session_t *dst); + +/** + * Writes the application data given in @p buf to the peer specified + * by @p session. + * + * @param ctx The DTLS context to use. + * @param session The remote transport address and local interface. + * @param buf The data to write. + * @param len The actual length of @p data. + * + * @return The number of bytes written, @c -1 on error or @c 0 + * if the peer already exists but is not connected yet. + */ +int dtls_write(struct dtls_context_t *ctx, session_t *session, + uint8 *buf, size_t len); + +/** + * Checks sendqueue of given DTLS context object for any outstanding + * packets to be transmitted. + * + * @param context The DTLS context object to use. + * @param next If not NULL, @p next is filled with the timestamp + * of the next scheduled retransmission, or @c 0 when no packets are + * waiting. + */ +void dtls_check_retransmit(dtls_context_t *context, clock_time_t *next); + +#define DTLS_COOKIE_LENGTH 16 + +#define DTLS_CT_CHANGE_CIPHER_SPEC 20 +#define DTLS_CT_ALERT 21 +#define DTLS_CT_HANDSHAKE 22 +#define DTLS_CT_APPLICATION_DATA 23 + +/** Generic header structure of the DTLS record layer. */ +typedef struct __attribute__((__packed__)) { + uint8 content_type; /**< content type of the included message */ + uint16 version; /**< Protocol version */ + uint16 epoch; /**< counter for cipher state changes */ + uint48 sequence_number; /**< sequence number */ + uint16 length; /**< length of the following fragment */ + /* fragment */ +} dtls_record_header_t; + +/* Handshake types */ + +#define DTLS_HT_HELLO_REQUEST 0 +#define DTLS_HT_CLIENT_HELLO 1 +#define DTLS_HT_SERVER_HELLO 2 +#define DTLS_HT_HELLO_VERIFY_REQUEST 3 +#define DTLS_HT_CERTIFICATE 11 +#define DTLS_HT_SERVER_KEY_EXCHANGE 12 +#define DTLS_HT_CERTIFICATE_REQUEST 13 +#define DTLS_HT_SERVER_HELLO_DONE 14 +#define DTLS_HT_CERTIFICATE_VERIFY 15 +#define DTLS_HT_CLIENT_KEY_EXCHANGE 16 +#define DTLS_HT_FINISHED 20 + +/** + * Pseudo handshake message type, if no optional handshake message is expected. + */ +#define DTLS_HT_NO_OPTIONAL_MESSAGE -1 + +/** Header structure for the DTLS handshake protocol. */ +typedef struct __attribute__((__packed__)) { + uint8 msg_type; /**< Type of handshake message (one of DTLS_HT_) */ + uint24 length; /**< length of this message */ + uint16 message_seq; /**< Message sequence number */ + uint24 fragment_offset; /**< Fragment offset. */ + uint24 fragment_length; /**< Fragment length. */ + /* body */ +} dtls_handshake_header_t; + +/** Structure of the Client Hello message. */ +typedef struct __attribute__((__packed__)) { + uint16 version; /**< Client version */ + uint32 gmt_random; /**< GMT time of the random byte creation */ + unsigned char random[28]; /**< Client random bytes */ + /* session id (up to 32 bytes) */ + /* cookie (up to 32 bytes) */ + /* cipher suite (2 to 2^16 -1 bytes) */ + /* compression method */ +} dtls_client_hello_t; + +/** Structure of the Hello Verify Request. */ +typedef struct __attribute__((__packed__)) { + uint16 version; /**< Server version */ + uint8 cookie_length; /**< Length of the included cookie */ + uint8 cookie[]; /**< up to 32 bytes making up the cookie */ +} dtls_hello_verify_t; + +#if 0 +/** + * Checks a received DTLS record for consistency and eventually decrypt, + * verify, decompress and reassemble the contained fragment for + * delivery to high-lever clients. + * + * \param state The DTLS record state for the current session. + * \param + */ +int dtls_record_read(dtls_state_t *state, uint8 *msg, int msglen); +#endif + +/** + * Handles incoming data as DTLS message from given peer. + * + * @param ctx The dtls context to use. + * @param session The current session + * @param msg The received data + * @param msglen The actual length of @p msg. + * @return A value less than zero on error, zero on success. + */ +int dtls_handle_message(dtls_context_t *ctx, session_t *session, + uint8 *msg, int msglen); + +/** + * Check if @p session is associated with a peer object in @p context. + * This function returns a pointer to the peer if found, NULL otherwise. + * + * @param context The DTLS context to search. + * @param session The remote address and local interface + * @return A pointer to the peer associated with @p session or NULL if + * none exists. + */ +dtls_peer_t *dtls_get_peer(const dtls_context_t *context, + const session_t *session); + +/** + * Resets all connections with @p peer. + * + * @param context The active DTLS context. + * @param peer The peer to reset. + */ +void dtls_reset_peer(dtls_context_t *context, dtls_peer_t *peer); + +#endif /* _DTLS_DTLS_H_ */ + +/** + * @mainpage + * + * @author Olaf Bergmann, TZI Uni Bremen + * + * This library provides a very simple datagram server with DTLS + * support. It is designed to support session multiplexing in + * single-threaded applications and thus targets specifically on + * embedded systems. + * + * @section license License + * + * This software is under the MIT License. + * + * @subsection uthash UTHash + * + * This library uses uthash to manage + * its peers (not used for Contiki). @b uthash uses the BSD revised license, see + * http://uthash.sourceforge.net/license.html. + * + * @subsection sha256 Aaron D. Gifford's SHA256 Implementation + * + * tinyDTLS provides HMAC-SHA256 with BSD-licensed code from Aaron D. Gifford, + * see www.aarongifford.com. + * + * @subsection aes Rijndael Implementation From OpenBSD + * + * The AES implementation is taken from rijndael.{c,h} contained in the crypto + * sub-system of the OpenBSD operating system. It is copyright by Vincent Rijmen, * + * Antoon Bosselaers and Paulo Barreto. See rijndael.c + * for License info. + * + * @section download Getting the Files + * + * You can get the sources either from the downloads section or + * through git from the project develop page. + * + * @section config Configuration + * + * Use @c configure to set up everything for a successful build. For Contiki, use the + * option @c --with-contiki. + * + * @section build Building + * + * After configuration, just type + * @code +make + * @endcode + * optionally followed by + * @code +make install + * @endcode + * The Contiki version is integrated with the Contiki build system, hence you do not + * need to invoke @c make explicitely. Just add @c tinydtls to the variable @c APPS + * in your @c Makefile. + * + * @addtogroup dtls_usage DTLS Usage + * + * @section dtls_server_example DTLS Server Example + * + * This section shows how to use the DTLS library functions to setup a + * simple secure UDP echo server. The application is responsible for the + * entire network communication and thus will look like a usual UDP + * server with socket creation and binding and a typical select-loop as + * shown below. The minimum configuration required for DTLS is the + * creation of the dtls_context_t using dtls_new_context(), and a callback + * for sending data. Received packets are read by the application and + * passed to dtls_handle_message() as shown in @ref dtls_read_cb. + * For any useful communication to happen, read and write call backs + * and a key management function should be registered as well. + * + * @code + dtls_context_t *the_context = NULL; + int fd, result; + + static dtls_handler_t cb = { + .write = send_to_peer, + .read = read_from_peer, + .event = NULL, + .get_psk_key = get_psk_key + }; + + fd = socket(...); + if (fd < 0 || bind(fd, ...) < 0) + exit(-1); + + the_context = dtls_new_context(&fd); + dtls_set_handler(the_context, &cb); + + while (1) { + ...initialize fd_set rfds and timeout ... + result = select(fd+1, &rfds, NULL, 0, NULL); + + if (FD_ISSET(fd, &rfds)) + dtls_handle_read(the_context); + } + + dtls_free_context(the_context); + * @endcode + * + * @subsection dtls_read_cb The Read Callback + * + * The DTLS library expects received raw data to be passed to + * dtls_handle_message(). The application is responsible for + * filling a session_t structure with the address data of the + * remote peer as illustrated by the following example: + * + * @code +int dtls_handle_read(struct dtls_context_t *ctx) { + int *fd; + session_t session; + static uint8 buf[DTLS_MAX_BUF]; + int len; + + fd = dtls_get_app_data(ctx); + + assert(fd); + + session.size = sizeof(session.addr); + len = recvfrom(*fd, buf, sizeof(buf), 0, &session.addr.sa, &session.size); + + return len < 0 ? len : dtls_handle_message(ctx, &session, buf, len); +} + * @endcode + * + * Once a new DTLS session was established and DTLS ApplicationData has been + * received, the DTLS server invokes the read callback with the MAC-verified + * cleartext data as its argument. A read callback for a simple echo server + * could look like this: + * @code +int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { + return dtls_write(ctx, session, data, len); +} + * @endcode + * + * @subsection dtls_send_cb The Send Callback + * + * The callback function send_to_peer() is called whenever data must be + * sent over the network. Here, the sendto() system call is used to + * transmit data within the given session. The socket descriptor required + * by sendto() has been registered as application data when the DTLS context + * was created with dtls_new_context(). + * Note that it is on the application to buffer the data when it cannot be + * sent at the time this callback is invoked. The following example thus + * is incomplete as it would have to deal with EAGAIN somehow. + * @code +int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { + int fd = *(int *)dtls_get_app_data(ctx); + return sendto(fd, data, len, MSG_DONTWAIT, &session->addr.sa, session->size); +} + * @endcode + * + * @subsection dtls_get_psk_info The Key Storage + * + * When a new DTLS session is created, the library must ask the application + * for keying material. To do so, it invokes the registered call-back function + * get_psk_info() with the current context and session information as parameter. + * When the call-back function is invoked with the parameter @p type set to + * @c DTLS_PSK_IDENTITY, the result parameter @p result must be filled with + * the psk_identity_hint in case of a server, or the actual psk_identity in + * case of a client. When @p type is @c DTLS_PSK_KEY, the result parameter + * must be filled with a key for the given identity @p id. The function must + * return the number of bytes written to @p result which must not exceed + * @p result_length. + * In case of an error, the function must return a negative value that + * corresponds to a valid error code defined in alert.h. + * + * @code +int get_psk_info(struct dtls_context_t *ctx UNUSED_PARAM, + const session_t *session UNUSED_PARAM, + dtls_credentials_type_t type, + const unsigned char *id, size_t id_len, + unsigned char *result, size_t result_length) { + + switch (type) { + case DTLS_PSK_IDENTITY: + if (result_length < psk_id_length) { + dtls_warn("cannot set psk_identity -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + memcpy(result, psk_id, psk_id_length); + return psk_id_length; + case DTLS_PSK_KEY: + if (id_len != psk_id_length || memcmp(psk_id, id, id_len) != 0) { + dtls_warn("PSK for unknown id requested, exiting\n"); + return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); + } else if (result_length < psk_key_length) { + dtls_warn("cannot set psk -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + memcpy(result, psk_key, psk_key_length); + return psk_key_length; + default: + dtls_warn("unsupported request type: %d\n", type); + } + + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); +} + * @endcode + * + * @subsection dtls_events The Event Notifier + * + * Applications that want to be notified whenever the status of a DTLS session + * has changed can register an event handling function with the field @c event + * in the dtls_handler_t structure (see \ref dtls_server_example). The call-back + * function is called for alert messages and internal state changes. For alert + * messages, the argument @p level will be set to a value greater than zero, and + * @p code will indicate the notification code. For internal events, @p level + * is @c 0, and @p code a value greater than @c 255. + * + * Internal events are DTLS_EVENT_CONNECTED, @c DTLS_EVENT_CONNECT, and + * @c DTLS_EVENT_RENEGOTIATE. + * + * @code +int handle_event(struct dtls_context_t *ctx, session_t *session, + dtls_alert_level_t level, unsigned short code) { + ... do something with event ... + return 0; +} + * @endcode + * + * @section dtls_client_example DTLS Client Example + * + * A DTLS client is constructed like a server but needs to actively setup + * a new session by calling dtls_connect() at some point. As this function + * usually returns before the new DTLS channel is established, the application + * must register an event handler and wait for @c DTLS_EVENT_CONNECT before + * it can send data over the DTLS channel. + * + */ + +/** + * @addtogroup contiki Contiki + * + * To use tinyDTLS as Contiki application, place the source code in the directory + * @c apps/tinydtls in the Contiki source tree and invoke configure with the option + * @c --with-contiki. This will define WITH_CONTIKI in tinydtls.h and include + * @c Makefile.contiki in the main Makefile. To cross-compile for another platform + * you will need to set your host and build system accordingly. For example, + * when configuring for ARM, you would invoke + * @code +./configure --with-contiki --build=x86_64-linux-gnu --host=arm-none-eabi + * @endcode + * on an x86_64 linux host. + * + * Then, create a Contiki project with @c APPS += tinydtls in its Makefile. A sample + * server could look like this (with read_from_peer() and get_psk_key() as shown above). + * + * @code +#include "contiki.h" + +#include "tinydtls.h" +#include "dtls.h" + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) + +int send_to_peer(struct dtls_context_t *, session_t *, uint8 *, size_t); + +static struct uip_udp_conn *server_conn; +static dtls_context_t *dtls_context; + +static dtls_handler_t cb = { + .write = send_to_peer, + .read = read_from_peer, + .event = NULL, + .get_psk_key = get_psk_key +}; + +PROCESS(server_process, "DTLS server process"); +AUTOSTART_PROCESSES(&server_process); + +PROCESS_THREAD(server_process, ev, data) +{ + PROCESS_BEGIN(); + + dtls_init(); + + server_conn = udp_new(NULL, 0, NULL); + udp_bind(server_conn, UIP_HTONS(5684)); + + dtls_context = dtls_new_context(server_conn); + if (!dtls_context) { + dtls_emerg("cannot create context\n"); + PROCESS_EXIT(); + } + + dtls_set_handler(dtls_context, &cb); + + while(1) { + PROCESS_WAIT_EVENT(); + if(ev == tcpip_event && uip_newdata()) { + session_t session; + + uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr); + session.port = UIP_UDP_BUF->srcport; + session.size = sizeof(session.addr) + sizeof(session.port); + + dtls_handle_message(ctx, &session, uip_appdata, uip_datalen()); + } + } + + PROCESS_END(); +} + +int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { + struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx); + + uip_ipaddr_copy(&conn->ripaddr, &session->addr); + conn->rport = session->port; + + uip_udp_packet_send(conn, data, len); + + memset(&conn->ripaddr, 0, sizeof(server_conn->ripaddr)); + memset(&conn->rport, 0, sizeof(conn->rport)); + + return len; +} + * @endcode + */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_config.h.cmake.in b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_config.h.cmake.in new file mode 100644 index 000000000..3b72d12df --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_config.h.cmake.in @@ -0,0 +1,162 @@ +/******************************************************************************* + * + * Copyright (c) 2022 Contributors to the Eclipse Foundation + * + * See the LICENSE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 1.0 + * which is available at https://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License v. 1.0 + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * SPDX-License-Identifier: EPL-1.0 + * + * Contributors: + * Jimmy Björklund - initial version + * Achim Kraus - add getrandom and libcunit + * + * dtls_config.h: Generated by cmake from dtls_config.h.cmake.in + * + ******************************************************************************/ + +/* Define if building universal (internal helper macro) */ +#cmakedefine AC_APPLE_UNIVERSAL_BUILD + +/* Define to 1 if building with ECC support. */ +#cmakedefine DTLS_ECC 1 + +/* Define to 1 if building with PSK support */ +#cmakedefine DTLS_PSK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ASSERT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `fls' function. */ +#cmakedefine HAVE_FLS 1 + +/* Define to 1 if you have the `getrandom' function. */ +#cmakedefine HAVE_GETRANDOM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define if the system has libcunit */ +#cmakedefine HAVE_LIBCUNIT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#cmakedefine HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the `select' function. */ +#cmakedefine HAVE_SELECT 1 + +/* Define to 1 if struct sockaddr_in6 has a member sin6_len. */ +#cmakedefine HAVE_SOCKADDR_IN6_SIN6_LEN 1 + +/* Define to 1 if you have the `socket' function. */ +#cmakedefine HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strdup' function. */ +#cmakedefine HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#cmakedefine HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the `strnlen' function. */ +#cmakedefine HAVE_STRNLEN 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vprintf' function. */ +#cmakedefine HAVE_VPRINTF 1 + +/* Define to 1 if you have the `inet_ntop' function. */ +#cmakedefine HAVE_INET_NTOP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NET_SOCKET_H 1 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "${PACKAGE_NAME}" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "${PACKAGE_NAME}" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "${PACKAGE_VERSION}" + +/* Define to 1 if you have the ANSI C header files. */ +#cmakedefine STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#cmakedefine WORDS_BIGENDIAN 1 + +/* TODO + Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. +#ifndef __cplusplus +#undef inline +#endif + + Define to `unsigned int' if does not define. +#undef size_t */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_debug.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_debug.c new file mode 100644 index 000000000..e0e56e228 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_debug.c @@ -0,0 +1,460 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#include "tinydtls.h" + +#if defined(HAVE_ASSERT_H) && !defined(assert) +#include +#endif + +#include +#include + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef WITH_ZEPHYR +#ifdef HAVE_NET_SOCKET_H +#include +#endif /* HAVE_NET_SOCKET_H */ +typedef int in_port_t; +#endif /* WITH_ZEPHYR */ + +#include "global.h" +#include "dtls_debug.h" + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifdef WITH_ZEPHYR +LOG_MODULE_REGISTER(TINYDTLS, CONFIG_TINYDTLS_LOG_LEVEL); +#endif /* WITH_ZEPHYR */ + +static int maxlog = DTLS_LOG_WARN; /* default maximum log level */ + +const char *dtls_package_name(void) { + return PACKAGE_NAME; +} + +const char *dtls_package_version(void) { + return PACKAGE_VERSION; +} + +log_t +dtls_get_log_level(void) { + return maxlog; +} + +void +dtls_set_log_level(log_t level) { + maxlog = level; +} + +/* this array has the same order as the type log_t */ +static const char *loglevels[] = { + "EMRG", "ALRT", "CRIT", "WARN", "NOTE", "INFO", "DEBG" +}; + +#ifdef HAVE_TIME_H + +static inline size_t +print_timestamp(char *s, size_t len, time_t t) { + struct tm *tmp; + tmp = localtime(&t); + return strftime(s, len, "%b %d %H:%M:%S", tmp); +} + +#else /* alternative implementation: just print the timestamp */ + +static inline size_t +print_timestamp(char *s, size_t len, clock_time_t t) { +#ifdef HAVE_SNPRINTF + return snprintf(s, len, "%u.%03u", + (unsigned int)(t / CLOCK_SECOND), + (unsigned int)(t % CLOCK_SECOND)); +#else /* HAVE_SNPRINTF */ + /* @todo do manual conversion of timestamp */ + return 0; +#endif /* HAVE_SNPRINTF */ +} + +#endif /* HAVE_TIME_H */ + +#ifndef NDEBUG + +/** + * A length-safe strlen() fake. + * + * @param s The string to count characters != 0. + * @param maxlen The maximum length of @p s. + * + * @return The length of @p s. + */ +static inline size_t +dtls_strnlen(const char *s, size_t maxlen) { + size_t n = 0; + while(*s++ && n < maxlen) + ++n; + return n; +} + +/** + * Write service-address as text to buffer. + * + * The text is \000 terminated. + * + * \param addr The session including the sockaddr. + * \param buf The buffer to write the service address into. + * \param len The actual length of \p buf. + * \return Less than zero on error, the number of bytes written otherwise. + */ +static size_t +dsrv_print_addr(const session_t *addr, char *buf, size_t len) { +#ifdef HAVE_INET_NTOP + const void *addrptr = NULL; + in_port_t port; + char *p = buf; + size_t append; + int err; + + /* max. '[' ipv6 ']:' port '\0' */ + assert(len >= 1 + INET6_ADDRSTRLEN + 2 + 5 + 1); + + switch (addr->addr.sa.sa_family) { + case AF_INET: + addrptr = &addr->addr.sin.sin_addr; + port = ntohs(addr->addr.sin.sin_port); + break; + case AF_INET6: + *p++ = '['; + --len; + addrptr = &addr->addr.sin6.sin6_addr; + port = ntohs(addr->addr.sin6.sin6_port); + break; + default: + /* include terminating \000 */ + append = strlen("(unknown address type)"); + memcpy(p, "(unknown address type)", append + 1); + return append; + } + + if (inet_ntop(addr->addr.sa.sa_family, addrptr, p, len) == 0) { + perror("dsrv_print_addr"); + return 0; + } + + /* append inet_ntop to p */ + append = dtls_strnlen(p, len); + p += append; + len -= append; + + if (addr->addr.sa.sa_family == AF_INET6) { + *p++ = ']'; + --len; + } + + /* append port and \000 termination */ + err = snprintf(p, len, ":%d", port); + if (err < 0) { + return 0; + } + p += err; + len -= err; + + return p - buf; +#else /* HAVE_INET_NTOP */ + +#ifdef WITH_CONTIKI + char *p = buf; +#if NETSTACK_CONF_WITH_IPV6 + uint8_t i; + const char hex[] = "0123456789ABCDEF"; + + if (len < 41) + return 0; + + *p++ = '['; + + for (i=0; i < 16; i += 2) { + if (i) { + *p++ = ':'; + } + *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4]; + *p++ = hex[(addr->addr.u8[i] & 0x0f)]; + *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4]; + *p++ = hex[(addr->addr.u8[i+1] & 0x0f)]; + } + *p++ = ']'; +#else /* NETSTACK_CONF_IPV6 */ + if (len < 21) + return 0; + + p += sprintf(p, "%u.%u.%u.%u", + addr->addr.u8[0], addr->addr.u8[1], + addr->addr.u8[2], addr->addr.u8[3]); +#endif /* NETSTACK_CONF_IPV6 */ + if (buf + len - p < 6) + return 0; + + p += sprintf(p, ":%d", uip_htons(addr->port)); + + return p - buf; + +#endif /* WITH_CONTIKI */ + +#ifdef RIOT_VERSION + /* FIXME: Switch to RIOT own DEBUG lines */ + (void) addr; + (void) buf; + (void) len; +#endif /* RIOT_VERSION */ + +#ifdef WITH_POSIX + /* TODO: output addresses manually */ +#warning "inet_ntop() not available, network addresses will not be included in debug output" +#endif /* WITH_POSIX */ + + return 0; +#endif /* HAVE_ARPA_INET_H */ +} + +#endif /* NDEBUG */ + +#ifndef WITH_CONTIKI +void +dsrv_log(log_t level, const char *format, ...) { + static char timebuf[32]; + va_list ap; + FILE *log_fd; + + if (maxlog < (int) level) + return; + + log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout; + + if (print_timestamp(timebuf,sizeof(timebuf), time(NULL))) + fprintf(log_fd, "%s ", timebuf); + + if (level <= DTLS_LOG_DEBUG) + fprintf(log_fd, "%s ", loglevels[level]); + + va_start(ap, format); + vfprintf(log_fd, format, ap); + va_end(ap); + fflush(log_fd); +} +#elif defined (HAVE_VPRINTF) /* WITH_CONTIKI */ +void +dsrv_log(log_t level, char *format, ...) { + static char timebuf[32]; + va_list ap; + + if (maxlog < level) + return; + + if (print_timestamp(timebuf,sizeof(timebuf), clock_time())) + PRINTF("%s ", timebuf); + + if (level <= DTLS_LOG_DEBUG) + PRINTF("%s ", loglevels[level]); + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} +#endif /* WITH_CONTIKI */ + +#ifndef NDEBUG +/** dumps packets in usual hexdump format */ +void hexdump(const unsigned char *packet, int length) { + int n = 0; + + while (length--) { + if (n % 16 == 0) + printf("%08X ",n); + + printf("%02X ", *packet++); + + n++; + if (n % 8 == 0) { + if (n % 16 == 0) + printf("\n"); + else + printf(" "); + } + } +} + +/** dump as narrow string of hex digits */ +void dump(unsigned char *buf, size_t len) { + while (len--) + printf("%02x", *buf++); +} + +void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr) +{ + char addrbuf[73]; + int len; + + len = dsrv_print_addr(addr, addrbuf, sizeof(addrbuf)); + if (!len) + return; +#ifdef WITH_ZEPHYR + switch(level) { + case DTLS_LOG_EMERG: + case DTLS_LOG_ALERT: + case DTLS_LOG_CRIT: + Z_LOG(LOG_LEVEL_ERR, "%s: %s\n", name, addrbuf); + break; + case DTLS_LOG_WARN: + Z_LOG(LOG_LEVEL_WRN, "%s: %s\n", name, addrbuf); + break; + case DTLS_LOG_NOTICE: + case DTLS_LOG_INFO: + Z_LOG(LOG_LEVEL_INF, "%s: %s\n", name, addrbuf); + break; + case DTLS_LOG_DEBUG: + Z_LOG(LOG_LEVEL_DBG, "%s: %s\n", name, addrbuf); + break; + } +#else /* WITH_ZEPHYR */ + dsrv_log(level, "%s: %s\n", name, addrbuf); +#endif /* WITH_ZEPHYR */ +} + +#ifndef WITH_CONTIKI +void +dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) { + static char timebuf[32]; + FILE *log_fd; + int n = 0; + + if (maxlog < (int) level) + return; + + log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout; + + if (print_timestamp(timebuf, sizeof(timebuf), time(NULL))) + fprintf(log_fd, "%s ", timebuf); + + if (level <= DTLS_LOG_DEBUG) + fprintf(log_fd, "%s ", loglevels[level]); + + if (extend) { + fprintf(log_fd, "%s: (%zu bytes):\n", name, length); + + while (length--) { + if (n % 16 == 0) + fprintf(log_fd, "%08X ", n); + + fprintf(log_fd, "%02X ", *buf++); + + n++; + if (n % 8 == 0) { + if (n % 16 == 0) + fprintf(log_fd, "\n"); + else + fprintf(log_fd, " "); + } + } + } else { + fprintf(log_fd, "%s: (%zu bytes): ", name, length); + while (length--) + fprintf(log_fd, "%02X", *buf++); + } + fprintf(log_fd, "\n"); + + fflush(log_fd); +} +#else /* WITH_CONTIKI */ +void +dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) { + static char timebuf[32]; + int n = 0; + + if (maxlog < level) + return; + + if (print_timestamp(timebuf,sizeof(timebuf), clock_time())) + PRINTF("%s ", timebuf); + + if (level >= 0 && level <= DTLS_LOG_DEBUG) + PRINTF("%s ", loglevels[level]); + + if (extend) { + PRINTF("%s: (%zu bytes):\n", name, length); + + while (length--) { + if (n % 16 == 0) + PRINTF("%08X ", n); + + PRINTF("%02X ", *buf++); + + n++; + if (n % 8 == 0) { + if (n % 16 == 0) + PRINTF("\n"); + else + PRINTF(" "); + } + } + } else { + PRINTF("%s: (%zu bytes): ", name, length); + while (length--) + PRINTF("%02X", *buf++); + } + PRINTF("\n"); +} +#endif /* WITH_CONTIKI */ + +#else /* NDEBUG */ + +void +hexdump(const unsigned char *packet, int length) { + (void)packet; + (void)length; +} + +void +dump(unsigned char *buf, size_t len) { + (void)buf; + (void)len; +} + +void +dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) { + (void)level; + (void)name; + (void)buf; + (void)length; + (void)extend; +} + +void +dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr) { + (void)level; + (void)name; + (void)addr; +} + +#endif /* NDEBUG */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_debug.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_debug.h new file mode 100644 index 000000000..bb90128ae --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_debug.h @@ -0,0 +1,123 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#ifndef _DTLS_DEBUG_H_ +#define _DTLS_DEBUG_H_ + +#include + +#include "tinydtls.h" +#include "global.h" +#include "session.h" + +#ifdef WITH_ZEPHYR +#include +#endif /* WITH_ZEPHYR */ + +#ifdef WITH_CONTIKI +# ifndef DEBUG +# define DEBUG DEBUG_PRINT +# endif /* DEBUG */ +#include "net/ip/uip-debug.h" + +#ifdef CONTIKI_TARGET_MBXXX +extern char __Stack_Init, _estack; + +static inline void check_stack(void) { + const char *p = &__Stack_Init; + while (p < &_estack && *p == 0x38) { + p++; + } + + PRINTF("Stack: %d bytes used (%d free)\n", &_estack - p, p - &__Stack_Init); +} +#else /* CONTIKI_TARGET_MBXXX */ +static inline void check_stack(void) { +} +#endif /* CONTIKI_TARGET_MBXXX */ +#else /* WITH_CONTKI */ +#define PRINTF(...) + +static inline void check_stack(void) { +} +#endif + +/** Pre-defined log levels akin to what is used in \b syslog. */ +typedef enum { DTLS_LOG_EMERG=0, DTLS_LOG_ALERT, DTLS_LOG_CRIT, DTLS_LOG_WARN, + DTLS_LOG_NOTICE, DTLS_LOG_INFO, DTLS_LOG_DEBUG +} log_t; + +/** Returns a zero-terminated string with the name of this library. */ +const char *dtls_package_name(void); + +/** Returns a zero-terminated string with the library version. */ +const char *dtls_package_version(void); + +/** Returns the current log level. */ +log_t dtls_get_log_level(void); + +/** Sets the log level to the specified value. */ +void dtls_set_log_level(log_t level); + +/** + * Writes the given text to \c stdout. The text is output only when \p + * level is below or equal to the log level that set by + * set_log_level(). */ +#ifdef HAVE_VPRINTF +#if (defined(__GNUC__)) +void dsrv_log(log_t level, const char *format, ...) __attribute__ ((format(printf, 2, 3))); +#else /* !__GNUC__ */ +void dsrv_log(log_t level, const char *format, ...); +#endif /* !__GNUC__ */ +#else +#define dsrv_log(level, format, ...) PRINTF(format, ##__VA_ARGS__) +#endif + +/** dumps packets in usual hexdump format */ +void hexdump(const unsigned char *packet, int length); + +/** dump as narrow string of hex digits */ +void dump(unsigned char *buf, size_t len); + +void dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend); + +void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr); + +/* A set of convenience macros for common log levels. */ +#ifdef WITH_ZEPHYR +#define dtls_emerg(...) LOG_ERR(__VA_ARGS__) +#define dtls_alert(...) LOG_ERR(__VA_ARGS__) +#define dtls_crit(...) LOG_ERR(__VA_ARGS__) +#define dtls_warn(...) LOG_WRN(__VA_ARGS__) +#define dtls_notice(...) LOG_INF(__VA_ARGS__) +#define dtls_info(...) LOG_INF(__VA_ARGS__) +#define dtls_debug(...) LOG_DBG(__VA_ARGS__) +#define dtls_debug_hexdump(name, buf, length) { LOG_DBG("%s (%zu bytes):", name, length); LOG_HEXDUMP_DBG(buf, length, name); } +#define dtls_debug_dump(name, buf, length) { LOG_DBG("%s (%zu bytes):", name, length); LOG_HEXDUMP_DBG(buf, length, name); } +#else /* WITH_ZEPHYR */ +#define dtls_emerg(...) dsrv_log(DTLS_LOG_EMERG, __VA_ARGS__) +#define dtls_alert(...) dsrv_log(DTLS_LOG_ALERT, __VA_ARGS__) +#define dtls_crit(...) dsrv_log(DTLS_LOG_CRIT, __VA_ARGS__) +#define dtls_warn(...) dsrv_log(DTLS_LOG_WARN, __VA_ARGS__) +#define dtls_notice(...) dsrv_log(DTLS_LOG_NOTICE, __VA_ARGS__) +#define dtls_info(...) dsrv_log(DTLS_LOG_INFO, __VA_ARGS__) +#define dtls_debug(...) dsrv_log(DTLS_LOG_DEBUG, __VA_ARGS__) +#define dtls_debug_hexdump(name, buf, length) dtls_dsrv_hexdump_log(DTLS_LOG_DEBUG, name, buf, length, 1) +#define dtls_debug_dump(name, buf, length) dtls_dsrv_hexdump_log(DTLS_LOG_DEBUG, name, buf, length, 0) +#endif /* WITH_ZEPHYR */ + +#endif /* _DTLS_DEBUG_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_mutex.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_mutex.h new file mode 100644 index 000000000..7f919f872 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_mutex.h @@ -0,0 +1,68 @@ +/******************************************************************************* + * + * Copyright (c) 2019 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Jon Shallow - Initall add in of generic mutex support + * + *******************************************************************************/ + +/** + * @file dtls_mutex.h + * @brief DTLS mutex mechanism wrapper + */ + +#ifndef _DTLS_MUTEX_H_ +#define _DTLS_MUTEX_H_ + +#if defined(RIOT_VERSION) + +#include + +typedef mutex_t dtls_mutex_t; +#define DTLS_MUTEX_INITIALIZER MUTEX_INIT +#define dtls_mutex_lock(a) mutex_lock(a) +#define dtls_mutex_trylock(a) mutex_trylock(a) +#define dtls_mutex_unlock(a) mutex_unlock(a) + +#elif defined(WITH_CONTIKI) + +/* CONTIKI does not support mutex */ + +typedef int dtls_mutex_t; +#define DTLS_MUTEX_INITIALIZER 0 +#define dtls_mutex_lock(a) *(a) = 1 +#define dtls_mutex_trylock(a) *(a) = 1 +#define dtls_mutex_unlock(a) *(a) = 0 + +#elif defined(WITH_ZEPHYR) + +/* zephyr supports mutex, but this port doesn't use it */ + +typedef int dtls_mutex_t; +#define DTLS_MUTEX_INITIALIZER 0 +#define dtls_mutex_lock(a) *(a) = 1 +#define dtls_mutex_trylock(a) *(a) = 1 +#define dtls_mutex_unlock(a) *(a) = 0 + + +#else /* ! RIOT_VERSION && ! WITH_CONTIKI && ! WITH_ZEPHYR */ + +#include + +typedef pthread_mutex_t dtls_mutex_t; +#define DTLS_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define dtls_mutex_lock(a) pthread_mutex_lock(a) +#define dtls_mutex_trylock(a) pthread_mutex_trylock(a) +#define dtls_mutex_unlock(a) pthread_mutex_unlock(a) + +#endif /* ! RIOT_VERSION && ! WITH_CONTIKI */ + +#endif /* _DTLS_MUTEX_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_prng.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_prng.c new file mode 100644 index 000000000..cef07d249 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_prng.c @@ -0,0 +1,39 @@ +/******************************************************************************* + * + * Copyright (c) 2011-2019 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * Jon Shallow - platform dependent prng support + * + *******************************************************************************/ + +#include "tinydtls.h" + +#if defined (WITH_CONTIKI) +#include "platform-specific/dtls_prng_contiki.c" + +#elif defined (ESPIDF_VERSION) +#include "platform-specific/dtls_prng_espidf.c" + +#elif defined (RIOT_VERSION) +#include "platform-specific/dtls_prng_riot.c" + +#elif defined (WITH_ZEPHYR) +#include "platform-specific/dtls_prng_zephyr.c" + +#elif defined (WITH_POSIX) +#include "platform-specific/dtls_prng_posix.c" + +#else +#error platform specific prng not defined + +#endif diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_prng.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_prng.h new file mode 100644 index 000000000..6bb0774d2 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_prng.h @@ -0,0 +1,56 @@ +/******************************************************************************* + * + * Copyright (c) 2011-2019 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * Jon Shallow - platform dependent prng support + * + *******************************************************************************/ + +/** + * @file prng.h + * @brief Pseudo Random Numbers + */ + +#ifndef _DTLS_PRNG_H_ +#define _DTLS_PRNG_H_ + +#include "tinydtls.h" +#include + +/** + * @defgroup prng Pseudo Random Numbers + * @{ + */ + +/** + * Fills \p buf with \p len random bytes. This is the default + * implementation for prng(). You might want to change prng() to use + * a better PRNG on your specific platform. + * + * @buf The buffer to fill + * @len the length of the buffer to fill + * + * @return 1 buffer filled + */ +int dtls_prng(unsigned char *buf, size_t len); + +/** + * Seeds the random number generator used by the function dtls_prng() + * + * @seed The seed to prime the random number generator + */ +void dtls_prng_init(unsigned seed); + +/** @} */ + +#endif /* _DTLS_PRNG_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_time.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_time.c new file mode 100644 index 000000000..5b3126301 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_time.c @@ -0,0 +1,98 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * + *******************************************************************************/ + +/** + * @file dtls_time.c + * @brief Clock Handling + */ + +#include "tinydtls.h" +#include "dtls_time.h" + +#ifdef WITH_CONTIKI +clock_time_t dtls_clock_offset; + +void +dtls_clock_init(void) { + clock_init(); + dtls_clock_offset = clock_time(); +} + +void +dtls_ticks(dtls_tick_t *t) { + *t = clock_time(); +} + +#endif /* WITH_CONTIKI */ + +#ifdef RIOT_VERSION +dtls_tick_t dtls_clock_offset; + +void +dtls_clock_init(void) { + dtls_clock_offset = ztimer_now(ZTIMER_MSEC); +} + +void +dtls_ticks(dtls_tick_t *t) { + *t = ztimer_now(ZTIMER_MSEC) - dtls_clock_offset; +} + +#endif /* RIOT_VERSION */ + +#ifdef WITH_ZEPHYR + +void +dtls_clock_init(void) { +} + +void +dtls_ticks(dtls_tick_t *t) { + *t = k_uptime_get(); +} + +#elif defined(WITH_POSIX) + +time_t dtls_clock_offset; + +void +dtls_clock_init(void) { +#ifdef HAVE_TIME_H + dtls_clock_offset = time(NULL); +#else +# ifdef __GNUC__ + /* Issue a warning when using gcc. Other prepropressors do + * not seem to have a similar feature. */ +# warning "cannot initialize clock" +# endif + dtls_clock_offset = 0; +#endif +} + +void dtls_ticks(dtls_tick_t *t) { +#ifdef HAVE_SYS_TIME_H + struct timeval tv; + gettimeofday(&tv, NULL); + *t = (tv.tv_sec - dtls_clock_offset) * DTLS_TICKS_PER_SECOND + + (tv.tv_usec * DTLS_TICKS_PER_SECOND / 1000000); +#else +#error "clock not implemented" +#endif +} + +#endif /* WITH_POSIX */ + + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_time.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_time.h new file mode 100644 index 000000000..adddcd1d4 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/dtls_time.h @@ -0,0 +1,96 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * + *******************************************************************************/ + +/** + * @file dtls_time.h + * @brief Clock Handling + */ + +#ifndef _DTLS_DTLS_TIME_H_ +#define _DTLS_DTLS_TIME_H_ + +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ + +#include "tinydtls.h" + +/** + * @defgroup clock Clock Handling + * Default implementation of internal clock. You should redefine this if + * you do not have time() and gettimeofday(). + * @{ + */ + +#ifdef WITH_CONTIKI +#include "clock.h" + +#elif defined(RIOT_VERSION) + +#include "ztimer.h" +#include "timex.h" + +/* this macro is already present on FreeBSD + which causes a redefine error otherwise */ +#ifndef CLOCK_SECOND +#define CLOCK_SECOND (MS_PER_SEC) +#endif + +typedef uint32_t clock_time_t; + +#elif defined(WITH_ZEPHYR) + +#include + +#ifndef CLOCK_SECOND +# define CLOCK_SECOND 1000 +#endif + +typedef int64_t clock_time_t; + +#else /* WITH_CONTIKI || RIOT_VERSION */ + +#ifdef HAVE_TIME_H +#include +#endif /* HAVE_TIME_H */ + +#ifndef CLOCK_SECOND +# define CLOCK_SECOND 1000 +#endif + +typedef uint32_t clock_time_t; + +#endif /* WITH_CONTIKI || RIOT_VERSION */ + +typedef clock_time_t dtls_tick_t; + +#ifndef DTLS_TICKS_PER_SECOND +#define DTLS_TICKS_PER_SECOND CLOCK_SECOND +#endif /* DTLS_TICKS_PER_SECOND */ + +void dtls_clock_init(void); +void dtls_ticks(dtls_tick_t *t); + +/* see https://godbolt.org/z/YchexKaeT */ +#define DTLS_OFFSET_TIME (((clock_time_t)~0) >> 1) +/** Checks if A is before (or equal) B. Considers 32 bit time overflow */ +#define DTLS_IS_BEFORE_TIME(A, B) ((clock_time_t)(DTLS_OFFSET_TIME + (B)-(A)) >= DTLS_OFFSET_TIME) + +/** @} */ + +#endif /* _DTLS_DTLS_TIME_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.contiki b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.contiki new file mode 100644 index 000000000..7787d2d46 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.contiki @@ -0,0 +1,7 @@ +CONTIKI=../../.. + +APPS += ecc + +CFLAGS += -DTEST_INCLUDE + +include $(CONTIKI)/Makefile.include diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.ecc b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.ecc new file mode 100644 index 000000000..382e48fda --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.ecc @@ -0,0 +1,3 @@ +# This is a -*- Makefile -*- + +ecc_src = ecc.c test_helper.c diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.riot b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.riot new file mode 100644 index 000000000..6758178ec --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/Makefile.riot @@ -0,0 +1,5 @@ +MODULE := tinydtls_ecc + +SRC := ecc.c + +include $(RIOTBASE)/Makefile.base diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/ecc.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/ecc.c new file mode 100644 index 000000000..d67233d94 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/ecc.c @@ -0,0 +1,727 @@ +/* + * Copyright (c) 2009 Chris K Cockrum + * + * Copyright (c) 2013 Jens Trillmann + * Copyright (c) 2013 Marc Müller-Weinhardt + * Copyright (c) 2013 Lars Schmertmann + * Copyright (c) 2013 Hauke Mehrtens + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * This implementation is based in part on the paper Implementation of an + * Elliptic Curve Cryptosystem on an 8-bit Microcontroller [0] by + * Chris K Cockrum . + * + * [0]: http://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf + * + * This is a efficient ECC implementation on the secp256r1 curve for 32 Bit CPU + * architectures. It provides basic operations on the secp256r1 curve and support + * for ECDH and ECDSA. + */ + +//big number functions +#include "ecc.h" +#include + +static uint32_t add( const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length){ + uint64_t d = 0; //carry + int v = 0; + for(v = 0;v>32; //save carry + } + + return (uint32_t)d; +} + +static uint32_t sub( const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length){ + uint64_t d = 0; + int v; + for(v = 0;v < length; v++){ + d = (uint64_t) x[v] - (uint64_t) y[v] - d; + result[v] = d & 0xFFFFFFFF; + d = d>>32; + d &= 0x1; + } + return (uint32_t)d; +} + +static void rshiftby(const uint32_t *in, uint8_t in_size, uint32_t *out, uint8_t out_size, uint8_t shift) { + int i; + + for (i = 0; i < (in_size - shift) && i < out_size; i++) + out[i] = in[i + shift]; + for (/* reuse i */; i < out_size; i++) + out[i] = 0; +} + +//finite field functions +//FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF +static const uint32_t ecc_prime_m[8] = {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0xffffffff}; + + +/* This is added after an static byte addition if the answer has a carry in MSB*/ +static const uint32_t ecc_prime_r[8] = {0x00000001, 0x00000000, 0x00000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffffe, 0x00000000}; + +// ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 +static const uint32_t ecc_order_m[9] = {0xFC632551, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000}; + +static const uint32_t ecc_order_r[8] = {0x039CDAAF, 0x0C46353D, 0x58E8617B, 0x43190552, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000}; + +static const uint32_t ecc_order_mu[9] = {0xEEDF9BFE, 0x012FFD85, 0xDF1A6C21, 0x43190552, + 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x00000000, + 0x00000001}; + +static const uint8_t ecc_order_k = 8; + +const uint32_t ecc_g_point_x[8] = { 0xD898C296, 0xF4A13945, 0x2DEB33A0, 0x77037D81, + 0x63A440F2, 0xF8BCE6E5, 0xE12C4247, 0x6B17D1F2}; +const uint32_t ecc_g_point_y[8] = { 0x37BF51F5, 0xCBB64068, 0x6B315ECE, 0x2BCE3357, + 0x7C0F9E16, 0x8EE7EB4A, 0xFE1A7F9B, 0x4FE342E2}; + + +static void setZero(uint32_t *A, const int length){ + memset(A, 0x0, length * sizeof(uint32_t)); +} + +/* + * copy one array to another + */ +static void copy(const uint32_t *from, uint32_t *to, uint8_t length){ + memcpy(to, from, length * sizeof(uint32_t)); +} + +static int isSame(const uint32_t *A, const uint32_t *B, uint8_t length){ + return !memcmp(A, B, length * sizeof(uint32_t)); +} + +//is A greater than B? +static int isGreater(const uint32_t *A, const uint32_t *B, uint8_t length){ + int i; + for (i = length-1; i >= 0; --i) + { + if(A[i] > B[i]) + return 1; + if(A[i] < B[i]) + return -1; + } + return 0; +} + + +static int fieldAdd(const uint32_t *x, const uint32_t *y, const uint32_t *reducer, uint32_t *result){ + if(add(x, y, result, arrayLength)){ //add prime if carry is still set! + uint32_t tempas[8]; + setZero(tempas, 8); + add(result, reducer, tempas, arrayLength); + copy(tempas, result, arrayLength); + } + return 0; +} + +static int fieldSub(const uint32_t *x, const uint32_t *y, const uint32_t *modulus, uint32_t *result){ + if(sub(x, y, result, arrayLength)){ //add modulus if carry is set + uint32_t tempas[8]; + setZero(tempas, 8); + add(result, modulus, tempas, arrayLength); + copy(tempas, result, arrayLength); + } + return 0; +} + +//finite Field multiplication +//32bit * 32bit = 64bit +static int fieldMult(const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length){ + uint32_t temp[length * 2]; + setZero(temp, length * 2); + setZero(result, length * 2); + uint8_t k, n; + uint64_t l; + for (k = 0; k < length; k++){ + for (n = 0; n < length; n++){ + l = (uint64_t)x[n]*(uint64_t)y[k]; + temp[n+k] = l&0xFFFFFFFF; + temp[n+k+1] = l>>32; + add(&temp[n+k], &result[n+k], &result[n+k], (length * 2) - (n + k)); + + setZero(temp, length * 2); + } + } + return 0; +} + +//TODO: maximum: +//fffffffe00000002fffffffe0000000100000001fffffffe00000001fffffffe00000001fffffffefffffffffffffffffffffffe000000000000000000000001_16 +static void fieldModP(uint32_t *A, const uint32_t *B) +{ + uint32_t tempm[8]; + uint32_t tempm2[8]; + uint8_t n; + setZero(tempm, 8); + setZero(tempm2, 8); + /* A = T */ + copy(B,A,arrayLength); + + /* Form S1 */ + for(n=0;n<3;n++) tempm[n]=0; + for(n=3;n<8;n++) tempm[n]=B[n+8]; + + /* tempm2=T+S1 */ + fieldAdd(A,tempm,ecc_prime_r,tempm2); + /* A=T+S1+S1 */ + fieldAdd(tempm2,tempm,ecc_prime_r,A); + /* Form S2 */ + for(n=0;n<3;n++) tempm[n]=0; + for(n=3;n<7;n++) tempm[n]=B[n+9]; + for(n=7;n<8;n++) tempm[n]=0; + /* tempm2=T+S1+S1+S2 */ + fieldAdd(A,tempm,ecc_prime_r,tempm2); + /* A=T+S1+S1+S2+S2 */ + fieldAdd(tempm2,tempm,ecc_prime_r,A); + /* Form S3 */ + for(n=0;n<3;n++) tempm[n]=B[n+8]; + for(n=3;n<6;n++) tempm[n]=0; + for(n=6;n<8;n++) tempm[n]=B[n+8]; + /* tempm2=T+S1+S1+S2+S2+S3 */ + fieldAdd(A,tempm,ecc_prime_r,tempm2); + /* Form S4 */ + for(n=0;n<3;n++) tempm[n]=B[n+9]; + for(n=3;n<6;n++) tempm[n]=B[n+10]; + for(n=6;n<7;n++) tempm[n]=B[n+7]; + for(n=7;n<8;n++) tempm[n]=B[n+1]; + /* A=T+S1+S1+S2+S2+S3+S4 */ + fieldAdd(tempm2,tempm,ecc_prime_r,A); + /* Form D1 */ + for(n=0;n<3;n++) tempm[n]=B[n+11]; + for(n=3;n<6;n++) tempm[n]=0; + for(n=6;n<7;n++) tempm[n]=B[n+2]; + for(n=7;n<8;n++) tempm[n]=B[n+3]; + /* tempm2=T+S1+S1+S2+S2+S3+S4-D1 */ + fieldSub(A,tempm,ecc_prime_m,tempm2); + /* Form D2 */ + for(n=0;n<4;n++) tempm[n]=B[n+12]; + for(n=4;n<6;n++) tempm[n]=0; + for(n=6;n<7;n++) tempm[n]=B[n+3]; + for(n=7;n<8;n++) tempm[n]=B[n+4]; + /* A=T+S1+S1+S2+S2+S3+S4-D1-D2 */ + fieldSub(tempm2,tempm,ecc_prime_m,A); + /* Form D3 */ + for(n=0;n<3;n++) tempm[n]=B[n+13]; + for(n=3;n<6;n++) tempm[n]=B[n+5]; + for(n=6;n<7;n++) tempm[n]=0; + for(n=7;n<8;n++) tempm[n]=B[n+5]; + /* tempm2=T+S1+S1+S2+S2+S3+S4-D1-D2-D3 */ + fieldSub(A,tempm,ecc_prime_m,tempm2); + /* Form D4 */ + for(n=0;n<2;n++) tempm[n]=B[n+14]; + for(n=2;n<3;n++) tempm[n]=0; + for(n=3;n<6;n++) tempm[n]=B[n+6]; + for(n=6;n<7;n++) tempm[n]=0; + for(n=7;n<8;n++) tempm[n]=B[n+6]; + /* A=T+S1+S1+S2+S2+S3+S4-D1-D2-D3-D4 */ + fieldSub(tempm2,tempm,ecc_prime_m,A); + if(isGreater(A, ecc_prime_m, arrayLength) >= 0){ + fieldSub(A, ecc_prime_m, ecc_prime_m, tempm); + copy(tempm, A, arrayLength); + } +} + +/** + * calculate the result = A mod n. + * n is the order of the eliptic curve. + * A and result could point to the same value + * + * A: input value (max size * 4 bytes) + * result: result of modulo calculation (max 36 bytes) + * size: size of A + * + * This uses the Barrett modular reduction as described in the Handbook + * of Applied Cryptography 14.42 Algorithm Barrett modular reduction, + * see http://cacr.uwaterloo.ca/hac/about/chap14.pdf and + * http://everything2.com/title/Barrett+Reduction + * + * b = 32 (bite size of the processor architecture) + * mu (ecc_order_mu) was precomputed in a java program + */ +static void fieldModO(const uint32_t *A, uint32_t *result, uint8_t length) { + // This is used for value q1 and q3 + uint32_t q1_q3[9]; + // This is used for q2 and a temp var + uint32_t q2_tmp[18]; + + // return if the given value is smaller than the modulus + if (length == arrayLength && isGreater(A, ecc_order_m, arrayLength) <= 0) { + if (A != result) + copy(A, result, length); + return; + } + + rshiftby(A, length, q1_q3, 9, ecc_order_k - 1); + + fieldMult(ecc_order_mu, q1_q3, q2_tmp, 9); + + rshiftby(q2_tmp, 18, q1_q3, 8, ecc_order_k + 1); + + // r1 = first 9 blocks of A + + fieldMult(q1_q3, ecc_order_m, q2_tmp, 8); + + // r2 = first 9 blocks of q2_tmp + + sub(A, q2_tmp, result, 9); + + while (isGreater(result, ecc_order_m, 9) >= 0) + sub(result, ecc_order_m, result, 9); +} + +/** + * Checks if all @p count elements in the given array @p val have the + * value 0. In this case, this function returns 1, otherwise the + * return value is 0. + * + * @param val The start of the number array to check. + * @param count The number of elements in @p val. + * + * @return 1 if all elements in @val are zero, 0 otherwise. + */ +static int is_zero(const uint32_t* val, size_t count) { + size_t result = 0; + size_t idx; + + for (idx = 0; idx < count; idx++) { + result += val[idx] == 0; + } + return result == count; +} + +/** + * Checks if the given array @p A represents the little endian number + * 1. The array @p A must have exactly eight elements. + * + * @param val The start of the number array to check. + * + * @return 1 if A[0] has the value 1 and all remaining elements have + * the value 0, 0 otherwise. + */ +static int isOne(const uint32_t* A){ + return (is_zero(&A[1], 7) + (A[0] == 1)) == 2; +} + +static int isZero(const uint32_t* A){ + return is_zero(A, 8); +} + +static void rshift(uint32_t* A){ + int n, i; + uint32_t nOld = 0; + for (i = 8; i--;) + { + n = A[i]&0x1; + A[i] = A[i]>>1 | nOld<<31; + nOld = n; + } +} + +static int fieldAddAndDivide(const uint32_t *x, const uint32_t *modulus, const uint32_t *reducer, uint32_t* result){ + uint32_t n = add(x, modulus, result, arrayLength); + rshift(result); + if(n){ //add prime if carry is still set! + result[7] |= 0x80000000;//add the carry + if (isGreater(result, modulus, arrayLength) == 1) + { + uint32_t tempas[8]; + setZero(tempas, 8); + add(result, reducer, tempas, 8); + copy(tempas, result, arrayLength); + } + + } + return 0; +} + +/* + * Inverse A and output to B + */ +static void fieldInv(const uint32_t *A, const uint32_t *modulus, const uint32_t *reducer, uint32_t *B){ + uint32_t u[8],v[8],x1[8],x2[8]; + uint32_t tempm[8]; + uint32_t tempm2[8]; + setZero(tempm, 8); + setZero(tempm2, 8); + setZero(u, 8); + setZero(v, 8); + + uint8_t t; + copy(A,u,arrayLength); + copy(modulus,v,arrayLength); + setZero(x1, 8); + setZero(x2, 8); + x1[0]=1; + /* While u !=1 and v !=1 */ + while ((isOne(u) || isOne(v))==0) { + while(!(u[0]&1)) { /* While u is even */ + rshift(u); /* divide by 2 */ + if (!(x1[0]&1)) /*ifx1iseven*/ + rshift(x1); /* Divide by 2 */ + else { + fieldAddAndDivide(x1,modulus,reducer,tempm); /* tempm=x1+p */ + copy(tempm,x1,arrayLength); /* x1=tempm */ + //rshift(x1); /* Divide by 2 */ + } + } + while(!(v[0]&1)) { /* While v is even */ + rshift(v); /* divide by 2 */ + if (!(x2[0]&1)) /*ifx1iseven*/ + rshift(x2); /* Divide by 2 */ + else + { + fieldAddAndDivide(x2,modulus,reducer,tempm); /* tempm=x1+p */ + copy(tempm,x2,arrayLength); /* x1=tempm */ + //rshift(x2); /* Divide by 2 */ + } + + } + t=sub(u,v,tempm,arrayLength); /* tempm=u-v */ + if (t==0) { /* If u > 0 */ + copy(tempm,u,arrayLength); /* u=u-v */ + fieldSub(x1,x2,modulus,tempm); /* tempm=x1-x2 */ + copy(tempm,x1,arrayLength); /* x1=x1-x2 */ + } else { + sub(v,u,tempm,arrayLength); /* tempm=v-u */ + copy(tempm,v,arrayLength); /* v=v-u */ + fieldSub(x2,x1,modulus,tempm); /* tempm=x2-x1 */ + copy(tempm,x2,arrayLength); /* x2=x2-x1 */ + } + } + if (isOne(u)) { + copy(x1,B,arrayLength); + } else { + copy(x2,B,arrayLength); + } +} + +static void ec_double(const uint32_t *px, const uint32_t *py, uint32_t *Dx, uint32_t *Dy){ + uint32_t tempA[8]; + uint32_t tempB[8]; + uint32_t tempC[8]; + uint32_t tempD[16]; + + if(isZero(px) && isZero(py)){ + copy(px, Dx,arrayLength); + copy(py, Dy,arrayLength); + return; + } + + fieldMult(px, px, tempD, arrayLength); + fieldModP(tempA, tempD); + setZero(tempB, 8); + tempB[0] = 0x00000001; + fieldSub(tempA, tempB, ecc_prime_m, tempC); //tempC = (qx^2-1) + tempB[0] = 0x00000003; + fieldMult(tempC, tempB, tempD, arrayLength); + fieldModP(tempA, tempD);//tempA = 3*(qx^2-1) + fieldAdd(py, py, ecc_prime_r, tempB); //tempB = 2*qy + fieldInv(tempB, ecc_prime_m, ecc_prime_r, tempC); //tempC = 1/(2*qy) + fieldMult(tempA, tempC, tempD, arrayLength); //tempB = lambda = (3*(qx^2-1))/(2*qy) + fieldModP(tempB, tempD); + + fieldMult(tempB, tempB, tempD, arrayLength); //tempC = lambda^2 + fieldModP(tempC, tempD); + fieldSub(tempC, px, ecc_prime_m, tempA); //lambda^2 - Px + fieldSub(tempA, px, ecc_prime_m, Dx); //lambda^2 - Px - Qx + + fieldSub(px, Dx, ecc_prime_m, tempA); //tempA = qx-dx + fieldMult(tempB, tempA, tempD, arrayLength); //tempC = lambda * (qx-dx) + fieldModP(tempC, tempD); + fieldSub(tempC, py, ecc_prime_m, Dy); //Dy = lambda * (qx-dx) - px +} + +static void ec_add(const uint32_t *px, const uint32_t *py, const uint32_t *qx, const uint32_t *qy, uint32_t *Sx, uint32_t *Sy){ + uint32_t tempA[8]; + uint32_t tempB[8]; + uint32_t tempC[8]; + uint32_t tempD[16]; + + if(isZero(px) && isZero(py)){ + copy(qx, Sx,arrayLength); + copy(qy, Sy,arrayLength); + return; + } else if(isZero(qx) && isZero(qy)) { + copy(px, Sx,arrayLength); + copy(py, Sy,arrayLength); + return; + } + + if(isSame(px, qx, arrayLength)){ + if(!isSame(py, qy, arrayLength)){ + setZero(Sx, 8); + setZero(Sy, 8); + return; + } else { + ec_double(px, py, Sx, Sy); + return; + } + } + + fieldSub(py, qy, ecc_prime_m, tempA); + fieldSub(px, qx, ecc_prime_m, tempB); + fieldInv(tempB, ecc_prime_m, ecc_prime_r, tempB); + fieldMult(tempA, tempB, tempD, arrayLength); + fieldModP(tempC, tempD); //tempC = lambda + + fieldMult(tempC, tempC, tempD, arrayLength); //tempA = lambda^2 + fieldModP(tempA, tempD); + fieldSub(tempA, px, ecc_prime_m, tempB); //lambda^2 - Px + fieldSub(tempB, qx, ecc_prime_m, Sx); //lambda^2 - Px - Qx + + fieldSub(qx, Sx, ecc_prime_m, tempB); + fieldMult(tempC, tempB, tempD, arrayLength); + fieldModP(tempC, tempD); + fieldSub(tempC, qy, ecc_prime_m, Sy); +} + +void ecc_ec_mult(const uint32_t *px, const uint32_t *py, const uint32_t *secret, uint32_t *resultx, uint32_t *resulty){ + uint32_t Qx[8]; + uint32_t Qy[8]; + setZero(Qx, 8); + setZero(Qy, 8); + + uint32_t tempx[8]; + uint32_t tempy[8]; + + int i; + for (i = 256;i--;){ + ec_double(Qx, Qy, tempx, tempy); + copy(tempx, Qx,arrayLength); + copy(tempy, Qy,arrayLength); + if (((secret[i / 32]) & ((uint32_t)1 << (i % 32)))) { + ec_add(Qx, Qy, px, py, tempx, tempy); //eccAdd + copy(tempx, Qx,arrayLength); + copy(tempy, Qy,arrayLength); + } + } + copy(Qx, resultx,arrayLength); + copy(Qy, resulty,arrayLength); +} + +/** + * Calculate the ecdsa signature. + * + * For a description of this algorithm see + * https://en.wikipedia.org/wiki/Elliptic_Curve_DSA#Signature_generation_algorithm + * + * input: + * d: private key on the curve secp256r1 (32 bytes) + * e: hash to sign (32 bytes) + * k: random data, this must be changed for every signature (32 bytes) + * + * output: + * r: r value of the signature (36 bytes) + * s: s value of the signature (36 bytes) + * + * return: + * 0: everything is ok + * -1: can not create signature, try again with different k. + */ +int ecc_ecdsa_sign(const uint32_t *d, const uint32_t *e, const uint32_t *k, uint32_t *r, uint32_t *s) +{ + uint32_t tmp1[16]; + uint32_t tmp2[9]; + uint32_t tmp3[9]; + + if (isZero(k)) + return -1; + + // 4. Calculate the curve point (x_1, y_1) = k * G. + ecc_ec_mult(ecc_g_point_x, ecc_g_point_y, k, r, tmp1); + + // 5. Calculate r = x_1 \pmod{n}. + fieldModO(r, r, 8); + + // 5. If r = 0, go back to step 3. + if (isZero(r)) + return -1; + + // 6. Calculate s = k^{-1}(z + r d_A) \pmod{n}. + // 6. r * d + fieldMult(r, d, tmp1, arrayLength); + fieldModO(tmp1, tmp2, 16); + + // 6. z + (r d) + tmp1[8] = add(e, tmp2, tmp1, 8); + fieldModO(tmp1, tmp3, 9); + + // 6. k^{-1} + fieldInv(k, ecc_order_m, ecc_order_r, tmp2); + + // 6. (k^{-1}) (z + (r d)) + fieldMult(tmp2, tmp3, tmp1, arrayLength); + fieldModO(tmp1, s, 16); + + // 6. If s = 0, go back to step 3. + if (isZero(s)) + return -1; + + return 0; +} + +/** + * Verifies a ecdsa signature. + * + * For a description of this algorithm see + * https://en.wikipedia.org/wiki/Elliptic_Curve_DSA#Signature_verification_algorithm + * + * input: + * x: x coordinate of the public key (32 bytes) + * y: y coordinate of the public key (32 bytes) + * e: hash to verify the signature of (32 bytes) + * r: r value of the signature (32 bytes) + * s: s value of the signature (32 bytes) + * + * return: + * 0: signature is ok + * -1: signature check failed the signature is invalid + */ +int ecc_ecdsa_validate(const uint32_t *x, const uint32_t *y, const uint32_t *e, const uint32_t *r, const uint32_t *s) +{ + uint32_t w[8]; + uint32_t tmp[16]; + uint32_t u1[9]; + uint32_t u2[9]; + uint32_t tmp1_x[8]; + uint32_t tmp1_y[8]; + uint32_t tmp2_x[8]; + uint32_t tmp2_y[8]; + uint32_t tmp3_x[8]; + uint32_t tmp3_y[8]; + + if (isZero(r) || isZero(s)) + return -1; + + // 3. Calculate w = s^{-1} \pmod{n} + fieldInv(s, ecc_order_m, ecc_order_r, w); + + // 4. Calculate u_1 = zw \pmod{n} + fieldMult(e, w, tmp, arrayLength); + fieldModO(tmp, u1, 16); + + // 4. Calculate u_2 = rw \pmod{n} + fieldMult(r, w, tmp, arrayLength); + fieldModO(tmp, u2, 16); + + // 5. Calculate the curve point (x_1, y_1) = u_1 * G + u_2 * Q_A. + // tmp1 = u_1 * G + ecc_ec_mult(ecc_g_point_x, ecc_g_point_y, u1, tmp1_x, tmp1_y); + + // tmp2 = u_2 * Q_A + ecc_ec_mult(x, y, u2, tmp2_x, tmp2_y); + + // tmp3 = tmp1 + tmp2 + ec_add(tmp1_x, tmp1_y, tmp2_x, tmp2_y, tmp3_x, tmp3_y); + // TODO: this u_1 * G + u_2 * Q_A could be optimiced with Straus's algorithm. + + return isSame(tmp3_x, r, arrayLength) ? 0 : -1; +} + +int ecc_is_valid_key(const uint32_t * priv_key) +{ + return isGreater(ecc_order_m, priv_key, arrayLength) == 1; +} + +/* + * This exports the low level functions so the tests can use them. + * In real use the compiler is now bale to optimice the code better. + */ +#ifdef TEST_INCLUDE +uint32_t ecc_add( const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length) +{ + return add(x, y, result, length); +} +uint32_t ecc_sub( const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length) +{ + return sub(x, y, result, length); +} +int ecc_fieldAdd(const uint32_t *x, const uint32_t *y, const uint32_t *reducer, uint32_t *result) +{ + return fieldAdd(x, y, reducer, result); +} +int ecc_fieldSub(const uint32_t *x, const uint32_t *y, const uint32_t *modulus, uint32_t *result) +{ + return fieldSub(x, y, modulus, result); +} +int ecc_fieldMult(const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length) +{ + return fieldMult(x, y, result, length); +} +void ecc_fieldModP(uint32_t *A, const uint32_t *B) +{ + fieldModP(A, B); +} +void ecc_fieldModO(const uint32_t *A, uint32_t *result, uint8_t length) +{ + fieldModO(A, result, length); +} +void ecc_fieldInv(const uint32_t *A, const uint32_t *modulus, const uint32_t *reducer, uint32_t *B) +{ + fieldInv(A, modulus, reducer, B); +} +void ecc_copy(const uint32_t *from, uint32_t *to, uint8_t length) +{ + copy(from, to, length); +} +int ecc_isSame(const uint32_t *A, const uint32_t *B, uint8_t length) +{ + return isSame(A, B, length); +} +void ecc_setZero(uint32_t *A, const int length) +{ + setZero(A, length); +} +int ecc_isOne(const uint32_t* A) +{ + return isOne(A); +} +void ecc_rshift(uint32_t* A) +{ + rshift(A); +} +int ecc_isGreater(const uint32_t *A, const uint32_t *B, uint8_t length) +{ + return isGreater(A, B , length); +} + +void ecc_ec_add(const uint32_t *px, const uint32_t *py, const uint32_t *qx, const uint32_t *qy, uint32_t *Sx, uint32_t *Sy) +{ + ec_add(px, py, qx, qy, Sx, Sy); +} +void ecc_ec_double(const uint32_t *px, const uint32_t *py, uint32_t *Dx, uint32_t *Dy) +{ + ec_double(px, py, Dx, Dy); +} + +#endif /* TEST_INCLUDE */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/ecc.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/ecc.h new file mode 100644 index 000000000..3c0d9b1dc --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/ecc.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009 Chris K Cockrum + * + * Copyright (c) 2013 Jens Trillmann + * Copyright (c) 2013 Marc Müller-Weinhardt + * Copyright (c) 2013 Lars Schmertmann + * Copyright (c) 2013 Hauke Mehrtens + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * This implementation is based in part on the paper Implementation of an + * Elliptic Curve Cryptosystem on an 8-bit Microcontroller [0] by + * Chris K Cockrum . + * + * [0]: http://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf + * + * This is a efficient ECC implementation on the secp256r1 curve for 32 Bit CPU + * architectures. It provides basic operations on the secp256r1 curve and support + * for ECDH and ECDSA. + */ +#include + +#define keyLengthInBytes 32 +#define arrayLength 8 + +extern const uint32_t ecc_g_point_x[8]; +extern const uint32_t ecc_g_point_y[8]; + +//ec Functions +void ecc_ec_mult(const uint32_t *px, const uint32_t *py, const uint32_t *secret, uint32_t *resultx, uint32_t *resulty); + +static inline void ecc_ecdh(const uint32_t *px, const uint32_t *py, const uint32_t *secret, uint32_t *resultx, uint32_t *resulty) { + ecc_ec_mult(px, py, secret, resultx, resulty); +} +int ecc_ecdsa_validate(const uint32_t *x, const uint32_t *y, const uint32_t *e, const uint32_t *r, const uint32_t *s); +int ecc_ecdsa_sign(const uint32_t *d, const uint32_t *e, const uint32_t *k, uint32_t *r, uint32_t *s); + +int ecc_is_valid_key(const uint32_t * priv_key); +static inline void ecc_gen_pub_key(const uint32_t *priv_key, uint32_t *pub_x, uint32_t *pub_y) +{ + ecc_ec_mult(ecc_g_point_x, ecc_g_point_y, priv_key, pub_x, pub_y); +} + +#ifdef TEST_INCLUDE +//ec Functions +void ecc_ec_add(const uint32_t *px, const uint32_t *py, const uint32_t *qx, const uint32_t *qy, uint32_t *Sx, uint32_t *Sy); +void ecc_ec_double(const uint32_t *px, const uint32_t *py, uint32_t *Dx, uint32_t *Dy); + +//simple Functions for addition and substraction of big numbers +uint32_t ecc_add( const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length); +uint32_t ecc_sub( const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length); + +//field functions for big numbers +int ecc_fieldAdd(const uint32_t *x, const uint32_t *y, const uint32_t *reducer, uint32_t *result); +int ecc_fieldSub(const uint32_t *x, const uint32_t *y, const uint32_t *modulus, uint32_t *result); +int ecc_fieldMult(const uint32_t *x, const uint32_t *y, uint32_t *result, uint8_t length); +void ecc_fieldModP(uint32_t *A, const uint32_t *B); +void ecc_fieldModO(const uint32_t *A, uint32_t *result, uint8_t length); +void ecc_fieldInv(const uint32_t *A, const uint32_t *modulus, const uint32_t *reducer, uint32_t *B); + +//simple functions to work with the big numbers +void ecc_copy(const uint32_t *from, uint32_t *to, uint8_t length); +int ecc_isSame(const uint32_t *A, const uint32_t *B, uint8_t length); +void ecc_setZero(uint32_t *A, const int length); +int ecc_isOne(const uint32_t* A); +void ecc_rshift(uint32_t* A); +int ecc_isGreater(const uint32_t *A, const uint32_t *B, uint8_t length); + +#endif /* TEST_INCLUDE */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/test_helper.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/test_helper.c new file mode 100644 index 000000000..bda44ba9e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/test_helper.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2009 Chris K Cockrum + * + * Copyright (c) 2013 Jens Trillmann + * Copyright (c) 2013 Marc Müller-Weinhardt + * Copyright (c) 2013 Lars Schmertmann + * Copyright (c) 2013 Hauke Mehrtens + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * This implementation is based in part on the paper Implementation of an + * Elliptic Curve Cryptosystem on an 8-bit Microcontroller [0] by + * Chris K Cockrum . + * + * [0]: http://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf + * + * This is a efficient ECC implementation on the secp256r1 curve for 32 Bit CPU + * architectures. It provides basic operations on the secp256r1 curve and support + * for ECDH and ECDSA. + */ +#include "test_helper.h" +#include "ecc.h" +#include +#include +#include + +void ecc_printNumber(const uint32_t *x, int numberLength){ //here the values are turned to MSB! + int n; + + for(n = numberLength - 1; n >= 0; n--){ + printf("%08x", x[n]); + } + printf("\n"); +} + +void ecc_setRandom(uint32_t *secret){ + int i; + + for (i = 0; i < arrayLength; ++i) + { + secret[i] = rand(); + } +} +const uint32_t ecc_prime_m[8] = {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0xffffffff}; + + +/* This is added after an static byte addition if the answer has a carry in MSB*/ +const uint32_t ecc_prime_r[8] = {0x00000001, 0x00000000, 0x00000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfffffffe, 0x00000000}; + +#ifdef CONTIKI +void +test_assert(const char *file, int lineno) +{ + printf("Assertion failed: file %s, line %d.\n", file, lineno); + /* + * loop for a while; + * call _reset_vector__(); + */ +} +#endif diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/test_helper.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/test_helper.h new file mode 100644 index 000000000..38a194e45 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/test_helper.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009 Chris K Cockrum + * + * Copyright (c) 2013 Jens Trillmann + * Copyright (c) 2013 Marc Müller-Weinhardt + * Copyright (c) 2013 Lars Schmertmann + * Copyright (c) 2013 Hauke Mehrtens + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * This implementation is based in part on the paper Implementation of an + * Elliptic Curve Cryptosystem on an 8-bit Microcontroller [0] by + * Chris K Cockrum . + * + * [0]: http://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf + * + * This is a efficient ECC implementation on the secp256r1 curve for 32 Bit CPU + * architectures. It provides basic operations on the secp256r1 curve and support + * for ECDH and ECDSA. + */ +#include + +extern const uint32_t ecc_prime_m[8]; +extern const uint32_t ecc_prime_r[8]; + +//debug function to print long numbers +void ecc_printNumber(const uint32_t *x, int numberLength); +void ecc_setRandom(uint32_t *secret); + +#ifdef CONTIKI +#undef assert +#define assert(e) ((e) ? (void)0 : test_assert(__FILE__, __LINE__)) +void test_assert(const char *, int); +#endif diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/testecc.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/testecc.c new file mode 100644 index 000000000..28d2134e0 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/testecc.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2009 Chris K Cockrum + * + * Copyright (c) 2013 Jens Trillmann + * Copyright (c) 2013 Marc Müller-Weinhardt + * Copyright (c) 2013 Lars Schmertmann + * Copyright (c) 2013 Hauke Mehrtens + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * This implementation is based in part on the paper Implementation of an + * Elliptic Curve Cryptosystem on an 8-bit Microcontroller [0] by + * Chris K Cockrum . + * + * [0]: http://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf + * + * This is a efficient ECC implementation on the secp256r1 curve for 32 Bit CPU + * architectures. It provides basic operations on the secp256r1 curve and support + * for ECDH and ECDSA. + */ + +#include +#include +#include +#include + +#include "ecc.h" +#include "test_helper.h" + +#ifdef CONTIKI +#include "contiki.h" +#else +#include +#endif /* CONTIKI */ + +//These are testvalues taken from the NIST P-256 definition +//6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296 +uint32_t BasePointx[8] = { 0xd898c296, 0xf4a13945, 0x2deb33a0, 0x77037d81, + 0x63a440f2, 0xf8bce6e5, 0xe12c4247, 0x6b17d1f2}; + +//4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5 +uint32_t BasePointy[8] = { 0x37bf51f5, 0xcbb64068, 0x6b315ece, 0x2bce3357, + 0x7c0f9e16, 0x8ee7eb4a, 0xfe1a7f9b, 0x4fe342e2}; + +//de2444be bc8d36e6 82edd27e 0f271508 617519b3 221a8fa0 b77cab39 89da97c9 +uint32_t Sx[8] = { 0x89da97c9, 0xb77cab39, 0x221a8fa0, 0x617519b3, + 0x0f271508, 0x82edd27e, 0xbc8d36e6, 0xde2444be}; + +//c093ae7f f36e5380 fc01a5aa d1e66659 702de80f 53cec576 b6350b24 3042a256 +uint32_t Sy[8] = { 0x3042a256, 0xb6350b24, 0x53cec576, 0x702de80f, + 0xd1e66659, 0xfc01a5aa, 0xf36e5380, 0xc093ae7f}; + +//55a8b00f 8da1d44e 62f6b3b2 5316212e 39540dc8 61c89575 bb8cf92e 35e0986b +uint32_t Tx[8] = { 0x35e0986b, 0xbb8cf92e, 0x61c89575, 0x39540dc8, + 0x5316212e, 0x62f6b3b2, 0x8da1d44e, 0x55a8b00f}; + +//5421c320 9c2d6c70 4835d82a c4c3dd90 f61a8a52 598b9e7a b656e9d8 c8b24316 +uint32_t Ty[8] = { 0xc8b24316, 0xb656e9d8, 0x598b9e7a, 0xf61a8a52, + 0xc4c3dd90, 0x4835d82a, 0x9c2d6c70, 0x5421c320}; + +//c51e4753 afdec1e6 b6c6a5b9 92f43f8d d0c7a893 3072708b 6522468b 2ffb06fd +uint32_t secret[8] = { 0x2ffb06fd, 0x6522468b, 0x3072708b, 0xd0c7a893, + 0x92f43f8d, 0xb6c6a5b9, 0xafdec1e6, 0xc51e4753}; + +//72b13dd4 354b6b81 745195e9 8cc5ba69 70349191 ac476bd4 553cf35a 545a067e +uint32_t resultAddx[8] = { 0x545a067e, 0x553cf35a, 0xac476bd4, 0x70349191, + 0x8cc5ba69, 0x745195e9, 0x354b6b81, 0x72b13dd4}; + +//8d585cbb 2e1327d7 5241a8a1 22d7620d c33b1331 5aa5c9d4 6d013011 744ac264 +uint32_t resultAddy[8] = { 0x744ac264, 0x6d013011, 0x5aa5c9d4, 0xc33b1331, + 0x22d7620d, 0x5241a8a1, 0x2e1327d7, 0x8d585cbb}; + +//7669e690 1606ee3b a1a8eef1 e0024c33 df6c22f3 b17481b8 2a860ffc db6127b0 +uint32_t resultDoublex[8] = { 0xdb6127b0, 0x2a860ffc, 0xb17481b8, 0xdf6c22f3, + 0xe0024c33, 0xa1a8eef1, 0x1606ee3b, 0x7669e690}; + +//fa878162 187a54f6 c39f6ee0 072f33de 389ef3ee cd03023d e10ca2c1 db61d0c7 +uint32_t resultDoubley[8] = { 0xdb61d0c7, 0xe10ca2c1, 0xcd03023d, 0x389ef3ee, + 0x072f33de, 0xc39f6ee0, 0x187a54f6, 0xfa878162}; + +//51d08d5f 2d427888 2946d88d 83c97d11 e62becc3 cfc18bed acc89ba3 4eeca03f +uint32_t resultMultx[8] = { 0x4eeca03f, 0xacc89ba3, 0xcfc18bed, 0xe62becc3, + 0x83c97d11, 0x2946d88d, 0x2d427888, 0x51d08d5f}; + +//75ee68eb 8bf626aa 5b673ab5 1f6e744e 06f8fcf8 a6c0cf30 35beca95 6a7b41d5 +uint32_t resultMulty[8] = { 0x6a7b41d5, 0x35beca95, 0xa6c0cf30, 0x06f8fcf8, + 0x1f6e744e, 0x5b673ab5, 0x8bf626aa, 0x75ee68eb}; + +static const uint32_t ecdsaTestMessage[] = { 0x65637572, 0x20612073, 0x68206F66, 0x20686173, 0x69732061, 0x68697320, 0x6F2C2054, 0x48616C6C}; + +static const uint32_t ecdsaTestSecret[] = {0x94A949FA, 0x401455A1, 0xAD7294CA, 0x896A33BB, 0x7A80E714, 0x4321435B, 0x51247A14, 0x41C1CB6B}; + +static const uint32_t ecdsaTestRand1[] = { 0x1D1E1F20, 0x191A1B1C, 0x15161718, 0x11121314, 0x0D0E0F10, 0x090A0B0C, 0x05060708, 0x01020304}; +static const uint32_t ecdsaTestresultR1[] = { 0xC3B4035F, 0x515AD0A6, 0xBF375DCA, 0x0CC1E997, 0x7F54FDCD, 0x04D3FECA, 0xB9E396B9, 0x515C3D6E}; +static const uint32_t ecdsaTestresultS1[] = { 0x5366B1AB, 0x0F1DBF46, 0xB0C8D3C4, 0xDB755B6F, 0xB9BF9243, 0xE644A8BE, 0x55159A59, 0x6F9E52A6}; + +static const uint32_t ecdsaTestRand2[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x01FFFFFF}; +static const uint32_t ecdsaTestresultR2[] = { 0x14146C91, 0xE878724D, 0xCD4FF928, 0xCC24BC04, 0xAC403390, 0x650C0060, 0x4A30B3F1, 0x9C69B726}; +static const uint32_t ecdsaTestresultS2[] = { 0x433AAB6F, 0x808250B1, 0xE46F90F4, 0xB342E972, 0x18B2F7E4, 0x2DB981A2, 0x6A288FA4, 0x41CF59DB}; + +static void +addTest(void){ + uint32_t tempx[8]; + uint32_t tempy[8]; + + ecc_ec_add(Tx, Ty, Sx, Sy, tempx, tempy); + assert(ecc_isSame(tempx, resultAddx, arrayLength)); + assert(ecc_isSame(tempy, resultAddy, arrayLength)); +} + +static void +doubleTest(void){ + uint32_t tempx[8]; + uint32_t tempy[8]; + + ecc_ec_double(Sx, Sy, tempx, tempy); + assert(ecc_isSame(tempx, resultDoublex, arrayLength)); + assert(ecc_isSame(tempy, resultDoubley, arrayLength)); +} + +static void +multTest(void){ + uint32_t tempx[8]; + uint32_t tempy[8]; + + ecc_ec_mult(Sx, Sy, secret, tempx, tempy); + assert(ecc_isSame(tempx, resultMultx, arrayLength)); + assert(ecc_isSame(tempy, resultMulty, arrayLength)); +} + +static void +eccdhTest(void){ + uint32_t tempx[8]; + uint32_t tempy[8]; + uint32_t tempAx2[8]; + uint32_t tempAy2[8]; + uint32_t tempBx1[8]; + uint32_t tempBy1[8]; + uint32_t tempBx2[8]; + uint32_t tempBy2[8]; + uint32_t secretA[8]; + uint32_t secretB[8]; + ecc_setRandom(secretA); + ecc_printNumber(secretA, 8); + ecc_setRandom(secretB); + ecc_printNumber(secretB, 8); + ecc_ec_mult(BasePointx, BasePointy, secretA, tempx, tempy); + ecc_ec_mult(BasePointx, BasePointy, secretB, tempBx1, tempBy1); + //public key exchange + ecc_ec_mult(tempBx1, tempBy1, secretA, tempAx2, tempAy2); + ecc_ec_mult(tempx, tempy, secretB, tempBx2, tempBy2); + assert(ecc_isSame(tempAx2, tempBx2, arrayLength)); + assert(ecc_isSame(tempAy2, tempBy2, arrayLength)); + +} + +static void +ecdsaTest(void) { + int ret __attribute__((unused)); + uint32_t tempx[9]; + uint32_t tempy[9]; + uint32_t pub_x[8]; + uint32_t pub_y[8]; + + ecc_ec_mult(BasePointx, BasePointy, ecdsaTestSecret, pub_x, pub_y); + + ret = ecc_ecdsa_sign(ecdsaTestSecret, ecdsaTestMessage, ecdsaTestRand1, tempx, tempy); + assert(ecc_isSame(tempx, ecdsaTestresultR1, arrayLength)); + assert(ecc_isSame(tempy, ecdsaTestresultS1, arrayLength)); + assert(ret == 0); + + ret = ecc_ecdsa_validate(pub_x, pub_y, ecdsaTestMessage, tempx, tempy); + assert(!ret); + + + ret = ecc_ecdsa_sign(ecdsaTestSecret, ecdsaTestMessage, ecdsaTestRand2, tempx, tempy); + assert(ecc_isSame(tempx, ecdsaTestresultR2, arrayLength)); + assert(ecc_isSame(tempy, ecdsaTestresultS2, arrayLength)); + assert(ret == 0); + + ret = ecc_ecdsa_validate(pub_x, pub_y, ecdsaTestMessage, tempx, tempy); + assert(!ret); +} + +#ifdef CONTIKI +PROCESS(ecc_test, "ECC test"); +AUTOSTART_PROCESSES(&ecc_test); +PROCESS_THREAD(ecc_test, ev, d) +{ + PROCESS_BEGIN(); + + srand(1234); + addTest(); + doubleTest(); + multTest(); + eccdhTest(); + ecdsaTest(); + printf("%s\n", "All Tests successful."); + + PROCESS_END(); +} +#else /* CONTIKI */ +int main(int argc, char const *argv[]) +{ + (void)argc; + (void)argv; + + srand(time(NULL)); + addTest(); + doubleTest(); + multTest(); + eccdhTest(); + ecdsaTest(); + printf("%s\n", "All Tests successful."); + return 0; +} +#endif /* CONTIKI */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/testfield.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/testfield.c new file mode 100644 index 000000000..bd7b48fd3 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/ecc/testfield.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2009 Chris K Cockrum + * + * Copyright (c) 2013 Jens Trillmann + * Copyright (c) 2013 Marc Müller-Weinhardt + * Copyright (c) 2013 Lars Schmertmann + * Copyright (c) 2013 Hauke Mehrtens + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * This implementation is based in part on the paper Implementation of an + * Elliptic Curve Cryptosystem on an 8-bit Microcontroller [0] by + * Chris K Cockrum . + * + * [0]: http://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf + * + * This is a efficient ECC implementation on the secp256r1 curve for 32 Bit CPU + * architectures. It provides basic operations on the secp256r1 curve and support + * for ECDH and ECDSA. + */ +#include +#include +#include +#include "ecc.h" +#include "test_helper.h" + +#ifdef CONTIKI +#include "contiki.h" +#endif /* CONTIKI */ + +//arbitrary test values and results +uint32_t null[8] = { 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t null64[16] = { 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t one[8] = { 0x00000001,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t one64[16] = { 0x00000001,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t two[8] = { 0x00000002,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t two64[16] = { 0x00000002,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t three[8] = { 0x00000003,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t four[8] = {0x00000004,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t four64[16] = { 0x00000004,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t six[8] = { 0x00000006,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t eight[8] = { 0x00000008,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}; +uint32_t full[8] = { 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; +//00000000fffffffeffffffffffffffffffffffff000000000000000000000001_16 +uint32_t resultFullAdd[8] = { 0x00000001,0x00000000,0x00000000,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFE,0x00000000}; +uint32_t primeMinusOne[8]= { 0xfffffffe,0xffffffff,0xffffffff,0x00000000, + 0x00000000,0x00000000,0x00000001,0xffffffff}; +uint32_t resultDoubleMod[8] = { 0xfffffffd,0xffffffff,0xffffffff,0x00000000, + 0x00000000,0x00000000,0x00000001,0xffffffff}; +//fffffffe00000002fffffffe0000000100000001fffffffe00000001fffffffc00000003fffffffcfffffffffffffffffffffffc000000000000000000000004_16 +uint32_t resultQuadMod[16] = { 0x00000004,0x00000000,0x00000000,0xFFFFFFFC, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFC,0x00000003, + 0xFFFFFFFC,0x00000001,0xFFFFFFFE,0x00000001, + 0x00000001,0xFFFFFFFE,0x00000002,0xFFFFFFFE}; +//00000002fffffffffffffffffffffffefffffffdffffffff0000000000000002_16 +uint32_t resultFullMod[8] = { 0x00000002,0x00000000,0xFFFFFFFF,0xFFFFFFFD, + 0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFF,0x00000002}; + +static const uint32_t orderMinusOne[8] = {0xFC632550, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF}; +static const uint32_t orderResultDoubleMod[8] = {0xFC63254F, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF}; + +uint32_t temp[8]; +uint32_t temp2[16]; + +static void +nullEverything(void){ + memset(temp, 0, sizeof(temp)); + memset(temp2, 0, sizeof(temp)); +} + +static void +fieldAddTest(void){ + assert(ecc_isSame(one, one, arrayLength)); + ecc_fieldAdd(one, null, ecc_prime_r, temp); + assert(ecc_isSame(temp, one, arrayLength)); + nullEverything(); + ecc_fieldAdd(one, one, ecc_prime_r, temp); + assert(ecc_isSame(temp, two, arrayLength)); + nullEverything(); + ecc_add(full, one, temp, 32); + assert(ecc_isSame(null, temp, arrayLength)); + nullEverything(); + ecc_fieldAdd(full, one, ecc_prime_r, temp); + assert(ecc_isSame(temp, resultFullAdd, arrayLength)); +} + +static void +fieldSubTest(void){ + assert(ecc_isSame(one, one, arrayLength)); + ecc_fieldSub(one, null, ecc_prime_m, temp); + assert(ecc_isSame(one, temp, arrayLength)); + nullEverything(); + ecc_fieldSub(one, one, ecc_prime_m, temp); + assert(ecc_isSame(null, temp, arrayLength)); + nullEverything(); + ecc_fieldSub(null, one, ecc_prime_m, temp); + assert(ecc_isSame(primeMinusOne, temp, arrayLength)); +} + +static void +fieldMultTest(void){ + ecc_fieldMult(one, null, temp2, arrayLength); + assert(ecc_isSame(temp2, null64, arrayLength * 2)); + nullEverything(); + ecc_fieldMult(one, two, temp2, arrayLength); + assert(ecc_isSame(temp2, two64, arrayLength * 2)); + nullEverything(); + ecc_fieldMult(two, two, temp2, arrayLength); + assert(ecc_isSame(temp2, four64, arrayLength * 2)); + nullEverything(); + ecc_fieldMult(primeMinusOne, primeMinusOne, temp2, arrayLength); + assert(ecc_isSame(temp2, resultQuadMod, arrayLength * 2)); + nullEverything(); + ecc_fieldInv(two, ecc_prime_m, ecc_prime_r, temp); + ecc_fieldMult(temp, two, temp2, arrayLength); + ecc_fieldModP(temp, temp2); + assert(ecc_isSame(temp, one, arrayLength)); +} + +static void +fieldModPTest(void){ + ecc_fieldMult(primeMinusOne, primeMinusOne, temp2, arrayLength); + ecc_fieldModP(temp, temp2); + assert(ecc_isSame(temp, one, arrayLength)); + nullEverything(); + ecc_fieldModP(temp, one64); + assert(ecc_isSame(temp, one, arrayLength)); + nullEverything(); + ecc_fieldMult(two, primeMinusOne, temp2, arrayLength); + ecc_fieldModP(temp, temp2); + assert(ecc_isSame(temp, resultDoubleMod, arrayLength)); + nullEverything(); + /*fieldMult(full, full, temp2, arrayLength); //not working, maybe because of the number bigger than p^2? + fieldModP(temp, temp2); + assert(ecc_isSame(temp, resultFullMod, arrayLength));*/ +} + +static void +fieldModOTest(void){ + ecc_fieldMult(orderMinusOne, orderMinusOne, temp2, arrayLength); + ecc_fieldModO(temp2, temp, arrayLength * 2); + assert(ecc_isSame(temp, one, arrayLength)); + nullEverything(); + ecc_fieldModO(one64, temp, arrayLength * 2); + assert(ecc_isSame(temp, one, arrayLength)); + nullEverything(); + ecc_fieldMult(two, orderMinusOne, temp2, arrayLength); + ecc_fieldModO(temp2, temp, arrayLength * 2); + assert(ecc_isSame(temp, orderResultDoubleMod, arrayLength)); + nullEverything(); +} + + +// static void +// rShiftTest(void){ +// printNumber(full, 32); +// rshift(full); +// printNumber(full, 32); +// printNumber(two, 32); +// rshift(two); +// printNumber(two, 32); +// printNumber(four, 32); +// rshift(four); +// printNumber(four, 32); +// } + +// static void +// isOneTest(void){ +// printf("%d\n", isone(one)); +// printf("%d\n", isone(two)); +// printf("%d\n", isone(four)); +// printf("%d\n", isone(full)); +// printf("%d\n", isone(null)); +// } + +static void +fieldInvTest(void){ + nullEverything(); + ecc_fieldInv(two, ecc_prime_m, ecc_prime_r, temp); + ecc_fieldMult(temp, two, temp2, arrayLength); + ecc_fieldModP(temp, temp2); + assert(ecc_isSame(one, temp, arrayLength)); + nullEverything(); + ecc_fieldInv(eight, ecc_prime_m, ecc_prime_r, temp); + ecc_fieldMult(temp, eight, temp2, arrayLength); + ecc_fieldModP(temp, temp2); + assert(ecc_isSame(one, temp, arrayLength)); + nullEverything(); + ecc_fieldInv(three, ecc_prime_m, ecc_prime_r, temp); + ecc_fieldMult(temp, three, temp2, arrayLength); + ecc_fieldModP(temp, temp2); + assert(ecc_isSame(one, temp, arrayLength)); + nullEverything(); + ecc_fieldInv(six, ecc_prime_m, ecc_prime_r, temp); + ecc_fieldMult(temp, six, temp2, arrayLength); + ecc_fieldModP(temp, temp2); + assert(ecc_isSame(one, temp, arrayLength)); + nullEverything(); + ecc_fieldInv(primeMinusOne, ecc_prime_m, ecc_prime_r, temp); + ecc_fieldMult(temp, primeMinusOne, temp2, arrayLength); + ecc_fieldModP(temp, temp2); + assert(ecc_isSame(one, temp, arrayLength)); +} + +// static void +// randomStuff(void){ + +// } + +#ifdef CONTIKI +PROCESS(ecc_field_test, "ECC field test"); +AUTOSTART_PROCESSES(&ecc_field_test); +PROCESS_THREAD(ecc_field_test, ev, d) +{ + PROCESS_BEGIN(); + + nullEverything(); + //randomStuff(); + nullEverything(); + fieldAddTest(); + nullEverything(); + fieldSubTest(); + nullEverything(); + fieldMultTest(); + nullEverything(); + fieldModPTest(); + nullEverything(); + fieldModOTest(); + nullEverything(); + fieldInvTest(); + nullEverything(); + //rShiftTest(); + //isOneTest(); + printf("%s\n", "All Tests succesfull!"); + + PROCESS_END(); +} +#else /* CONTIKI */ +int main(int argc, char const *argv[]) +{ + (void)argc; + (void)argv; + + nullEverything(); + //randomStuff(); + nullEverything(); + fieldAddTest(); + nullEverything(); + fieldSubTest(); + nullEverything(); + fieldMultTest(); + nullEverything(); + fieldModPTest(); + nullEverything(); + fieldModOTest(); + nullEverything(); + fieldInvTest(); + nullEverything(); + //rShiftTest(); + //isOneTest(); + printf("%s\n", "All Tests succesfull!"); + return 0; +} +#endif /* CONTIKI */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/global.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/global.h new file mode 100644 index 000000000..87153df39 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/global.h @@ -0,0 +1,143 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#ifndef _DTLS_GLOBAL_H_ +#define _DTLS_GLOBAL_H_ + +#include +#include + +#include "tinydtls.h" + +#ifndef DTLSv12 +/* The current version of tinyDTLS supports DTLSv1.2 only. */ +#define DTLSv12 1 +#endif + +#ifndef WITH_SHA256 +/* The current version of tinyDTLS supports DTLSv1.2 with SHA256 PRF + only. */ +#define WITH_SHA256 1 +#endif + +/* Define our own types as at least uint32_t does not work on my amd64. */ + +typedef unsigned char uint8; +typedef unsigned char uint16[2]; +typedef unsigned char uint24[3]; +typedef unsigned char uint32[4]; +typedef unsigned char uint48[6]; + +#ifndef DTLS_MAX_BUF +/** Maximum size of DTLS message. + When Peers are sending bigger messages this causes problems. Californium + with ECDSA needs at least 220 */ +#if (defined(WITH_CONTIKI) || defined(RIOT_VERSION)) +#ifdef DTLS_ECC +#define DTLS_MAX_BUF 200 +#else /* DTLS_ECC */ +#define DTLS_MAX_BUF 120 +#endif /* DTLS_ECC */ +#else /* WITH_CONTIKI */ +#define DTLS_MAX_BUF 1400 +#endif /* WITH_CONTIKI || RIOT_VERSION */ +#endif + +#ifndef DTLS_DEFAULT_MAX_RETRANSMIT +/** Number of message retransmissions. */ +#define DTLS_DEFAULT_MAX_RETRANSMIT 7 +#endif + +/** Known cipher suites.*/ +typedef enum { + TLS_NULL_WITH_NULL_NULL = 0x0000, /**< NULL cipher */ + TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8, /**< see RFC 6655 */ + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE /**< see RFC 7251 */ +} dtls_cipher_t; + +/** Known compression suites.*/ +typedef enum { + TLS_COMPRESSION_NULL = 0x0000 /* NULL compression */ +} dtls_compression_t; + +#define TLS_EXT_ELLIPTIC_CURVES 10 /* see RFC 4492 */ +#define TLS_EXT_EC_POINT_FORMATS 11 /* see RFC 4492 */ +#define TLS_EXT_SIG_HASH_ALGO 13 /* see RFC 5246 */ +#define TLS_EXT_CLIENT_CERTIFICATE_TYPE 19 /* see RFC 7250 */ +#define TLS_EXT_SERVER_CERTIFICATE_TYPE 20 /* see RFC 7250 */ +#define TLS_EXT_ENCRYPT_THEN_MAC 22 /* see RFC 7366 */ +#define TLS_EXT_EXTENDED_MASTER_SECRET 23 /* see RFC 7627 */ + +#define TLS_CERT_TYPE_RAW_PUBLIC_KEY 2 /* see RFC 7250 */ + +#define TLS_EXT_ELLIPTIC_CURVES_SECP256R1 23 /* see RFC 4492 */ + +#define TLS_EXT_EC_POINT_FORMATS_UNCOMPRESSED 0 /* see RFC 4492 */ + +#define TLS_EC_CURVE_TYPE_NAMED_CURVE 3 /* see RFC 4492 */ + +#define TLS_CLIENT_CERTIFICATE_TYPE_ECDSA_SIGN 64 /* see RFC 4492 */ + +#define TLS_EXT_SIG_HASH_ALGO_SHA256 4 /* see RFC 5246 */ +#define TLS_EXT_SIG_HASH_ALGO_ECDSA 3 /* see RFC 5246 */ + +/** + * XORs \p n bytes byte-by-byte starting at \p y to the memory area + * starting at \p x. */ +static inline void +memxor(unsigned char *x, const unsigned char *y, size_t n) { + while(n--) { + *x ^= *y; + x++; y++; + } +} + +/** + * Compares \p len bytes from @p a with @p b in constant time. This + * functions always traverses the entire length to prevent timing + * attacks. + * + * \param a Byte sequence to compare + * \param b Byte sequence to compare + * \param len Number of bytes to compare. + * \return \c 1 if \p a and \p b are equal, \c 0 otherwise. + */ +static inline int +equals(unsigned char *a, unsigned char *b, size_t len) { + int result = 1; + while (len--) { + result &= (*a++ == *b++); + } + return result; +} + +#ifdef HAVE_FLS +#define dtls_fls(i) fls(i) +#else +static inline int +dtls_fls(unsigned int i) { + int n; + for (n = 0; i; n++) + i >>= 1; + return n; +} +#endif /* HAVE_FLS */ + +#undef uthash_fatal +#define uthash_fatal(msg) return(-1) /* fatal error in uthash */ + +#endif /* _DTLS_GLOBAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/hmac.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/hmac.c new file mode 100644 index 000000000..93db779c9 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/hmac.c @@ -0,0 +1,107 @@ +/******************************************************************************* + * + * Copyright (c) 2011-2020 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#include +#include +#include + +#include "tinydtls.h" +#if defined(HAVE_ASSERT_H) && !defined(assert) +#include +#endif /* HAVE_ASSERT_H && !assert */ + +#include "dtls_debug.h" +#include "hmac.h" + +void +dtls_hmac_update(dtls_hmac_context_t *ctx, + const unsigned char *input, size_t ilen) { + assert(ctx); + dtls_hash_update(&ctx->data, input, ilen); +} + +void +dtls_hmac_init(dtls_hmac_context_t *ctx, const unsigned char *key, size_t klen) { + int i; + + assert(ctx); + + memset(ctx, 0, sizeof(dtls_hmac_context_t)); + + if (klen > DTLS_HMAC_BLOCKSIZE) { + dtls_hash_init(&ctx->data); + dtls_hash_update(&ctx->data, key, klen); + dtls_hash_finalize(ctx->pad, &ctx->data); + } else + memcpy(ctx->pad, key, klen); + + /* create ipad: */ + for (i=0; i < DTLS_HMAC_BLOCKSIZE; ++i) + ctx->pad[i] ^= 0x36; + + dtls_hash_init(&ctx->data); + dtls_hmac_update(ctx, ctx->pad, DTLS_HMAC_BLOCKSIZE); + + /* create opad by xor-ing pad[i] with 0x36 ^ 0x5C: */ + for (i=0; i < DTLS_HMAC_BLOCKSIZE; ++i) + ctx->pad[i] ^= 0x6A; +} + +int +dtls_hmac_finalize(dtls_hmac_context_t *ctx, unsigned char *result) { + unsigned char buf[DTLS_HMAC_DIGEST_SIZE]; + size_t len; + + assert(ctx); + assert(result); + + len = dtls_hash_finalize(buf, &ctx->data); + + dtls_hash_init(&ctx->data); + dtls_hash_update(&ctx->data, ctx->pad, DTLS_HMAC_BLOCKSIZE); + dtls_hash_update(&ctx->data, buf, len); + + len = dtls_hash_finalize(result, &ctx->data); + + return len; +} + +#ifdef HMAC_TEST +#include + +int main(int argc, char **argv) { + static unsigned char buf[DTLS_HMAC_DIGEST_SIZE]; + size_t len, i; + dtls_hmac_context_t ctx; + + if (argc < 3) { + fprintf(stderr, "usage: %s key text", argv[0]); + return -1; + } + + dtls_hmac_init(&ctx, argv[1], strlen(argv[1])); + dtls_hmac_update(ctx, argv[2], strlen(argv[2])); + + len = dtls_hmac_finalize(ctx, buf); + + for(i = 0; i < len; i++) + printf("%02x", buf[i]); + printf("\n"); + + return 0; +} +#endif diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/hmac.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/hmac.h new file mode 100644 index 000000000..67ceaa7a7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/hmac.h @@ -0,0 +1,151 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#ifndef _DTLS_HMAC_H_ +#define _DTLS_HMAC_H_ + +#include + +#include "tinydtls.h" +#include "global.h" + +#ifdef WITH_SHA256 +#ifdef RIOT_VERSION +#include "hashes/sha256.h" + +typedef sha256_context_t dtls_hash_ctx; +typedef sha256_context_t dtls_sha256_ctx; +#define DTLS_HASH_CTX_SIZE sizeof(sha256_context_t) +#define DTLS_SHA256_DIGEST_LENGTH (SHA256_DIGEST_LENGTH) + +#define dtls_sha256_init(Ctx) sha256_init((Ctx)) +#define dtls_sha256_update(Ctx,Input,Len) sha256_update((Ctx), (Input), (Len)) +#define dtls_sha256_final(Buf,Ctx) sha256_final((Ctx), (Buf)) + +#elif defined ESP_PLATFORM && defined CONFIG_LIBSODIUM_USE_MBEDTLS_SHA +#include "sodium/crypto_hash_sha256.h" + +typedef crypto_hash_sha256_state dtls_hash_ctx; +typedef crypto_hash_sha256_state dtls_sha256_ctx; +#define DTLS_HASH_CTX_SIZE sizeof(crypto_hash_sha256_state) +#define DTLS_SHA256_DIGEST_LENGTH (crypto_hash_sha256_BYTES) + +#define dtls_sha256_init(Ctx) crypto_hash_sha256_init((Ctx)) +#define dtls_sha256_update(Ctx,Input,Len) crypto_hash_sha256_update((Ctx), (Input), (Len)) +#define dtls_sha256_final(Buf,Ctx) crypto_hash_sha256_final((Ctx), (Buf)) + +#else /* ! RIOT_VERSION && ! ESP_PLATFORM */ + +/** Aaron D. Gifford's implementation of SHA256 + * see http://www.aarongifford.com/ */ +#include "sha2/sha2.h" + +typedef dtls_sha256_ctx dtls_hash_ctx; +#define DTLS_HASH_CTX_SIZE sizeof(dtls_sha256_ctx) + +#endif /* ! RIOT_VERSION && ! ESP_PLATFORM */ + + +typedef dtls_hash_ctx *dtls_hash_t; + + +static inline void +dtls_hash_init(dtls_hash_t ctx) { + dtls_sha256_init((dtls_sha256_ctx *)ctx); +} + +static inline void +dtls_hash_update(dtls_hash_t ctx, const unsigned char *input, size_t len) { + dtls_sha256_update((dtls_sha256_ctx *)ctx, input, len); +} + +static inline size_t +dtls_hash_finalize(unsigned char *buf, dtls_hash_t ctx) { + dtls_sha256_final(buf, (dtls_sha256_ctx *)ctx); + return DTLS_SHA256_DIGEST_LENGTH; +} +#endif /* WITH_SHA256 */ + +/** + * \defgroup HMAC Keyed-Hash Message Authentication Code (HMAC) + * NIST Standard FIPS 198 describes the Keyed-Hash Message Authentication + * Code (HMAC) which is used as hash function for the DTLS PRF. + * @{ + */ + +#define DTLS_HMAC_BLOCKSIZE 64 /**< size of hmac blocks */ +#define DTLS_HMAC_DIGEST_SIZE 32 /**< digest size (for SHA-256) */ +#define DTLS_HMAC_MAX 64 /**< max number of bytes in digest */ + +/** + * List of known hash functions for use in dtls_hmac_init(). The + * identifiers are the same as the HashAlgorithm defined in + * Section 7.4.1.4.1 of RFC 5246. + */ +typedef enum { + HASH_NONE=0, HASH_MD5=1, HASH_SHA1=2, HASH_SHA224=3, + HASH_SHA256=4, HASH_SHA384=5, HASH_SHA512=6 +} dtls_hashfunc_t; + +/** + * Context for HMAC generation. This object is initialized with + * dtls_hmac_init() and must be passed to dtls_hmac_update() and + * dtls_hmac_finalize(). Once, finalized, the component \c H is + * invalid and must be initialized again with dtls_hmac_init() before + * the structure can be used again. + */ +typedef struct { + unsigned char pad[DTLS_HMAC_BLOCKSIZE]; /**< ipad and opad storage */ + dtls_hash_ctx data; /**< context for hash function */ +} dtls_hmac_context_t; + +/** + * Initializes an existing HMAC context. + * + * @param ctx The HMAC context to initialize. + * @param key The secret key. + * @param klen The length of @p key. + */ +void dtls_hmac_init(dtls_hmac_context_t *ctx, const unsigned char *key, size_t klen); + +/** + * Updates the HMAC context with data from \p input. + * + * \param ctx The HMAC context. + * \param input The input data. + * \param ilen Size of \p input. + */ +void dtls_hmac_update(dtls_hmac_context_t *ctx, + const unsigned char *input, size_t ilen); + +/** + * Completes the HMAC generation and writes the result to the given + * output parameter \c result. The buffer must be large enough to hold + * the message digest created by the actual hash function. If in + * doubt, use \c DTLS_HMAC_MAX. The function returns the number of + * bytes written to \c result. + * + * \param ctx The HMAC context. + * \param result Output parameter where the MAC is written to. + * \return Length of the MAC written to \p result. + */ +int dtls_hmac_finalize(dtls_hmac_context_t *ctx, unsigned char *result); + +/**@}*/ + +#endif /* _DTLS_HMAC_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/netq.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/netq.c new file mode 100644 index 000000000..a6d17a154 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/netq.c @@ -0,0 +1,176 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#include "dtls_debug.h" +#include "netq.h" +#include "utlist.h" + +#ifdef HAVE_ASSERT_H +#include +#else +#ifndef assert +#warning "assertions are disabled" +# define assert(x) +#endif +#endif + +#ifdef WITH_ZEPHYR +LOG_MODULE_DECLARE(TINYDTLS, CONFIG_TINYDTLS_LOG_LEVEL); +#endif /* WITH_ZEPHYR */ + +#if !(defined (WITH_CONTIKI)) && !(defined (RIOT_VERSION)) +#include + +static inline netq_t * +netq_malloc_node(size_t size) { + return (netq_t *)malloc(sizeof(netq_t) + size); +} + +static inline void +netq_free_node(netq_t *node) { + free(node); +} + +#elif defined (WITH_CONTIKI) /* WITH_CONTIKI */ +#include "memb.h" + +MEMB(netq_storage, netq_t, NETQ_MAXCNT); + +static inline netq_t * +netq_malloc_node(size_t size) { + return (netq_t *)memb_alloc(&netq_storage); +} + +static inline void +netq_free_node(netq_t *node) { + memb_free(&netq_storage, node); +} + +void +netq_init() { + memb_init(&netq_storage); +} + +#elif defined (RIOT_VERSION) +# include + +netq_t netq_storage_data[NETQ_MAXCNT]; +memarray_t netq_storage; + +static inline netq_t * +netq_malloc_node(size_t size) { + (void) size; + return (netq_t *)memarray_alloc(&netq_storage); +} + +static inline void +netq_free_node(netq_t *node) { + memarray_free(&netq_storage, node); +} + +void +netq_init(void) { + memarray_init(&netq_storage, netq_storage_data, sizeof(netq_t), NETQ_MAXCNT); +} + +#endif /* WITH_CONTIKI */ + +int +netq_insert_node(netq_t **queue, netq_t *node) { + netq_t *p; + + assert(queue); + assert(node); + + p = *queue; + /* comparison considering 32bit overflow */ + while(p && DTLS_IS_BEFORE_TIME(p->t, node->t)) { + assert(p != node); + if (p == node) + return 0; + p = p->next; + } + + if (p) + LL_PREPEND_ELEM(*queue, p, node); + else + LL_APPEND(*queue, node); + + return 1; +} + +netq_t * +netq_head(netq_t **queue) { + return queue ? *queue : NULL; +} + +netq_t * +netq_next(netq_t *p) { + if (!p) + return NULL; + + return p->next; +} + +void +netq_remove(netq_t **queue, netq_t *p) { + if (!queue || !p) + return; + + LL_DELETE(*queue, p); +} + +netq_t *netq_pop_first(netq_t **queue) { + netq_t *p = netq_head(queue); + + if (p) + LL_DELETE(*queue, p); + + return p; +} + +netq_t * +netq_node_new(size_t size) { + netq_t *node; + node = netq_malloc_node(size); + + if (node) { + memset(node, 0, sizeof(netq_t)); + } else { + dtls_warn("netq_node_new: malloc\n"); + } + + return node; +} + +void +netq_node_free(netq_t *node) { + if (node) + netq_free_node(node); +} + +void +netq_delete_all(netq_t **queue) { + netq_t *p, *tmp; + if (queue) { + LL_FOREACH_SAFE(*queue,p,tmp) { + netq_free_node(p); + } + + *queue = NULL; + } +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/netq.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/netq.h new file mode 100644 index 000000000..61876ccf6 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/netq.h @@ -0,0 +1,122 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#ifndef _DTLS_NETQ_H_ +#define _DTLS_NETQ_H_ + +#include "tinydtls.h" +#include "global.h" +#include "dtls.h" +#include "dtls_time.h" + +/** + * \defgroup netq Network Packet Queue + * The netq utility functions implement an ordered queue of data packets + * to send over the network and can also be used to queue received packets + * from the network. + * @{ + */ + +#ifndef NETQ_MAXCNT +#ifdef DTLS_ECC +#define NETQ_MAXCNT 5 /**< maximum number of elements in netq structure */ +#elif defined(DTLS_PSK) +#define NETQ_MAXCNT 3 /**< maximum number of elements in netq structure */ +#endif +#endif + +/** + * Job to be executed for the timer entry in the netq. + */ +typedef enum netq_job_type_t { + RESEND, /**< resend related message on timeout */ + TIMEOUT /**< timeout of the related alert */ +} netq_job_type_t; + +/** + * Datagrams in the netq_t structure have a fixed maximum size of + * DTLS_MAX_BUF to simplify memory management on constrained nodes. */ +typedef unsigned char netq_packet_t[DTLS_MAX_BUF]; + +typedef struct netq_t { + struct netq_t *next; + + clock_time_t t; /**< when to send PDU for the next time */ + unsigned int timeout; /**< randomized timeout value */ + + netq_job_type_t job; /**< job to be executed on timeout */ + + dtls_peer_t *peer; /**< remote address */ + uint16_t epoch; + uint8_t type; + unsigned char retransmit_cnt; /**< retransmission counter, will be removed when zero */ + + size_t length; /**< actual length of data */ +#if !(defined (WITH_CONTIKI)) && !(defined (RIOT_VERSION)) + unsigned char data[]; /**< the datagram to send */ +#else + netq_packet_t data; /**< the datagram to send */ +#endif +} netq_t; + +#if !(defined (WITH_CONTIKI)) && !(defined (RIOT_VERSION)) +static inline void netq_init(void) +{ } +#else +void netq_init(void); +#endif + +/** + * Adds a node to the given queue, ordered by their time-stamp t. + * This function returns @c 0 on error, or non-zero if @p node has + * been added successfully. + * + * @param queue A pointer to the queue head where @p node will be added. + * @param node The new item to add. + * @return @c 0 on error, or non-zero if the new item was added. + */ +int netq_insert_node(netq_t **queue, netq_t *node); + +/** Destroys specified node and releases any memory that was allocated + * for the associated datagram. */ +void netq_node_free(netq_t *node); + +/** Removes all items from given queue and frees the allocated storage */ +void netq_delete_all(netq_t **queue); + +/** Creates a new node suitable for adding to a netq_t queue. */ +netq_t *netq_node_new(size_t size); + +/** + * Returns a pointer to the first item in given queue or NULL if + * empty. + */ +netq_t *netq_head(netq_t **queue); + +netq_t *netq_next(netq_t *p); +void netq_remove(netq_t **queue, netq_t *p); + +/** + * Removes the first item in given queue and returns a pointer to the + * removed element. If queue is empty when netq_pop_first() is called, + * this function returns NULL. + */ +netq_t *netq_pop_first(netq_t **queue); + +/**@}*/ + +#endif /* _DTLS_NETQ_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/numeric.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/numeric.h new file mode 100644 index 000000000..e8d1f561a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/numeric.h @@ -0,0 +1,134 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#ifndef _DTLS_NUMERIC_H_ +#define _DTLS_NUMERIC_H_ + +#include + +#ifndef min +#define min(A,B) ((A) <= (B) ? (A) : (B)) +#endif + +#ifndef max +#define max(A,B) ((A) < (B) ? (B) : (A)) +#endif + +/* this one is for consistency... */ +static inline int dtls_int_to_uint8(unsigned char *field, uint8_t value) +{ + field[0] = value & 0xff; + return 1; +} + +static inline int dtls_int_to_uint16(unsigned char *field, uint16_t value) +{ + field[0] = (value >> 8) & 0xff; + field[1] = value & 0xff; + return 2; +} + +static inline int dtls_int_to_uint24(unsigned char *field, uint32_t value) +{ + field[0] = (value >> 16) & 0xff; + field[1] = (value >> 8) & 0xff; + field[2] = value & 0xff; + return 3; +} + +static inline int dtls_int_to_uint32(unsigned char *field, uint32_t value) +{ + field[0] = (value >> 24) & 0xff; + field[1] = (value >> 16) & 0xff; + field[2] = (value >> 8) & 0xff; + field[3] = value & 0xff; + return 4; +} + +static inline int dtls_int_to_uint48(unsigned char *field, uint64_t value) +{ + field[0] = (value >> 40) & 0xff; + field[1] = (value >> 32) & 0xff; + field[2] = (value >> 24) & 0xff; + field[3] = (value >> 16) & 0xff; + field[4] = (value >> 8) & 0xff; + field[5] = value & 0xff; + return 6; +} + +static inline int dtls_int_to_uint64(unsigned char *field, uint64_t value) +{ + field[0] = (value >> 56) & 0xff; + field[1] = (value >> 48) & 0xff; + field[2] = (value >> 40) & 0xff; + field[3] = (value >> 32) & 0xff; + field[4] = (value >> 24) & 0xff; + field[5] = (value >> 16) & 0xff; + field[6] = (value >> 8) & 0xff; + field[7] = value & 0xff; + return 8; +} + +static inline uint8_t dtls_uint8_to_int(const unsigned char *field) +{ + return (uint8_t)field[0]; +} + +static inline uint16_t dtls_uint16_to_int(const unsigned char *field) +{ + return ((uint16_t)field[0] << 8) + | (uint16_t)field[1]; +} + +static inline uint32_t dtls_uint24_to_int(const unsigned char *field) +{ + return ((uint32_t)field[0] << 16) + | ((uint32_t)field[1] << 8) + | (uint32_t)field[2]; +} + +static inline uint32_t dtls_uint32_to_int(const unsigned char *field) +{ + return ((uint32_t)field[0] << 24) + | ((uint32_t)field[1] << 16) + | ((uint32_t)field[2] << 8) + | (uint32_t)field[3]; +} + +static inline uint64_t dtls_uint48_to_int(const unsigned char *field) +{ + return ((uint64_t)field[0] << 40) + | ((uint64_t)field[1] << 32) + | ((uint64_t)field[2] << 24) + | ((uint64_t)field[3] << 16) + | ((uint64_t)field[4] << 8) + | (uint64_t)field[5]; +} + +static inline uint64_t dtls_uint64_to_int(const unsigned char *field) +{ + return ((uint64_t)field[0] << 56) + | ((uint64_t)field[1] << 48) + | ((uint64_t)field[2] << 40) + | ((uint64_t)field[3] << 32) + | ((uint64_t)field[4] << 24) + | ((uint64_t)field[5] << 16) + | ((uint64_t)field[6] << 8) + | (uint64_t)field[7]; +} + +#endif /* _DTLS_NUMERIC_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/peer.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/peer.c new file mode 100644 index 000000000..bf06fae33 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/peer.c @@ -0,0 +1,107 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +#include "global.h" +#include "peer.h" +#include "dtls_debug.h" + +#if !(defined (WITH_CONTIKI)) && !(defined (RIOT_VERSION)) +void peer_init(void) +{ +} + +static inline dtls_peer_t * +dtls_malloc_peer(void) { + return (dtls_peer_t *)malloc(sizeof(dtls_peer_t)); +} + +void +dtls_free_peer(dtls_peer_t *peer) { + dtls_handshake_free(peer->handshake_params); + dtls_security_free(peer->security_params[0]); + dtls_security_free(peer->security_params[1]); + free(peer); +} +#elif defined (WITH_CONTIKI) /* WITH_CONTIKI */ + +#include "memb.h" +MEMB(peer_storage, dtls_peer_t, DTLS_PEER_MAX); + +void +peer_init(void) { + memb_init(&peer_storage); +} + +static inline dtls_peer_t * +dtls_malloc_peer(void) { + return memb_alloc(&peer_storage); +} + +void +dtls_free_peer(dtls_peer_t *peer) { + dtls_handshake_free(peer->handshake_params); + dtls_security_free(peer->security_params[0]); + dtls_security_free(peer->security_params[1]); + memb_free(&peer_storage, peer); +} + +#elif defined (RIOT_VERSION) +# include + +dtls_peer_t peer_storage_data[DTLS_PEER_MAX]; +memarray_t peer_storage; + +void +peer_init(void) { + memarray_init(&peer_storage, peer_storage_data, sizeof(dtls_peer_t), DTLS_PEER_MAX); +} + +static inline dtls_peer_t * +dtls_malloc_peer(void) { + return memarray_alloc(&peer_storage); +} + +void +dtls_free_peer(dtls_peer_t *peer) { + dtls_handshake_free(peer->handshake_params); + dtls_security_free(peer->security_params[0]); + dtls_security_free(peer->security_params[1]); + memarray_free(&peer_storage, peer); +} + +#endif /* WITH_CONTIKI */ + +dtls_peer_t * +dtls_new_peer(const session_t *session) { + dtls_peer_t *peer; + + peer = dtls_malloc_peer(); + if (peer) { + memset(peer, 0, sizeof(dtls_peer_t)); + memcpy(&peer->session, session, sizeof(session_t)); + peer->security_params[0] = dtls_security_new(); + + if (!peer->security_params[0]) { + dtls_free_peer(peer); + return NULL; + } + + dtls_dsrv_log_addr(DTLS_LOG_DEBUG, "dtls_new_peer", session); + } + + return peer; +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/peer.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/peer.h new file mode 100644 index 000000000..bd327fa7f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/peer.h @@ -0,0 +1,168 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +/** + * @file peer.h + * @brief information about peers in a DTLS session + */ + +#ifndef _DTLS_PEER_H_ +#define _DTLS_PEER_H_ + +#include + +#include "tinydtls.h" +#include "global.h" +#include "session.h" + +#include "state.h" +#include "crypto.h" + +#ifndef DTLS_PEERS_NOHASH +#include "uthash.h" +#endif /* DTLS_PEERS_NOHASH */ + +typedef enum { DTLS_CLIENT=0, DTLS_SERVER } dtls_peer_type; + +/** + * Holds security parameters, local state and the transport address + * for each peer. */ +typedef struct dtls_peer_t { +#ifdef DTLS_PEERS_NOHASH + struct dtls_peer_t *next; +#else /* DTLS_PEERS_NOHASH */ + UT_hash_handle hh; +#endif /* DTLS_PEERS_NOHASH */ + + session_t session; /**< peer address and local interface */ + + dtls_peer_type role; /**< denotes if this host is DTLS_CLIENT or DTLS_SERVER */ + dtls_state_t state; /**< DTLS engine state */ + int16_t optional_handshake_message; /**< optional next handshake message, DTLS_HT_NO_OPTIONAL_MESSAGE, if no optional message is expected. */ + + dtls_security_parameters_t *security_params[2]; + dtls_handshake_parameters_t *handshake_params; +} dtls_peer_t; + +/** + * Holds ClientHello's sequence numbers for the stateless address verification. */ +typedef struct dtls_ephemeral_peer_t { + session_t *session; /**< peer address and local interface */ + uint64_t rseq; /**< ClientHello record sequence number */ + uint16_t mseq; /**< ClientHello handshake message sequence number */ +} dtls_ephemeral_peer_t; + +static inline dtls_security_parameters_t *dtls_security_params_epoch(dtls_peer_t *peer, uint16_t epoch) +{ + if (peer->security_params[0] && peer->security_params[0]->epoch == epoch) { + return peer->security_params[0]; + } else if (peer->security_params[1] && peer->security_params[1]->epoch == epoch) { + return peer->security_params[1]; + } else { + return NULL; + } +} + +/** + * Get security parameter for read epoch. + * + * @param peer The remote party where the packet is received from. + * @param epoch The read epoch the packet is received in. + * @return The security parameter for the remote party and read epoch. @c NULL if not available. + */ +static inline dtls_security_parameters_t *dtls_security_params_read_epoch(dtls_peer_t *peer, uint16_t epoch) +{ + if (peer->handshake_params) { + if (peer->handshake_params->hs_state.read_epoch == epoch) { + return dtls_security_params_epoch(peer, epoch); + } + } else if (peer->security_params[0] && peer->security_params[0]->epoch == epoch) { + return peer->security_params[0]; + } + return NULL; +} + +static inline dtls_security_parameters_t *dtls_security_params(dtls_peer_t *peer) +{ + return peer->security_params[0]; +} + +static inline dtls_security_parameters_t *dtls_security_params_next(dtls_peer_t *peer) +{ + if (peer->security_params[1]) + dtls_security_free(peer->security_params[1]); + + peer->security_params[1] = dtls_security_new(); + if (!peer->security_params[1]) { + return NULL; + } + peer->security_params[1]->epoch = peer->security_params[0]->epoch + 1; + return peer->security_params[1]; +} + +static inline void dtls_security_params_free_other(dtls_peer_t *peer) +{ + dtls_security_parameters_t * security0 = peer->security_params[0]; + dtls_security_parameters_t * security1 = peer->security_params[1]; + + if (!security0 || !security1 || security0->epoch < security1->epoch) + return; + + dtls_security_free(security1); + peer->security_params[1] = NULL; +} + +static inline void dtls_security_params_switch(dtls_peer_t *peer) +{ + dtls_security_parameters_t * security = peer->security_params[1]; + + peer->security_params[1] = peer->security_params[0]; + peer->security_params[0] = security; +} + +void peer_init(void); + +/** + * Creates a new peer for given @p session. The current configuration + * is initialized with the cipher suite TLS_NULL_WITH_NULL_NULL (i.e. + * no security at all). This function returns a pointer to the new + * peer or NULL on error. The caller is responsible for releasing the + * storage allocated for this peer using dtls_free_peer(). + * + * @param session The remote peer's address and local interface index. + * @return A pointer to a newly created and initialized peer object + * or NULL on error. + */ +dtls_peer_t *dtls_new_peer(const session_t *session); + +/** Releases the storage allocated to @p peer. */ +void dtls_free_peer(dtls_peer_t *peer); + +/** Returns the current state of @p peer. */ +static inline dtls_state_t dtls_peer_state(const dtls_peer_t *peer) { + return peer->state; +} + +/** + * Checks if given @p peer is connected. This function returns + * @c 1 if connected, or @c 0 otherwise. + */ +static inline int dtls_peer_is_connected(const dtls_peer_t *peer) { + return peer->state == DTLS_STATE_CONNECTED; +} + +#endif /* _DTLS_PEER_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_contiki.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_contiki.c new file mode 100644 index 000000000..4730f77b6 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_contiki.c @@ -0,0 +1,60 @@ +/******************************************************************************* + * + * Copyright (c) 2011-2019 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * Achim Kraus - session recovery + * Sachin Agrawal - rehandshake support + * Jon Shallow - platform dependent prng support + * + *******************************************************************************/ + +#include "tinydtls.h" +#include "dtls_prng.h" +#include +#include "random.h" + +int +dtls_prng(unsigned char *buf, size_t len) +{ +#ifdef HAVE_PRNG + return contiki_prng_impl(buf, len); +#else /* ! HAVE_PRNG */ + /** + * Fills \p buf with \p len random bytes. This is the default + * implementation for prng(). You might want to change prng() to use + * a better PRNG on your specific platform. + */ + unsigned short v = random_rand(); + while (len > sizeof(v)) { + memcpy(buf, &v, sizeof(v)); + len -= sizeof(v); + buf += sizeof(v); + v = random_rand(); + } + + memcpy(buf, &v, len); + return len; +} +#endif /* ! HAVE_PRNG */ + +void +dtls_prng_init(unsigned seed) +{ + /* random_init() messes with the radio interface of the CC2538 and + * therefore must not be called after the radio has been + * initialized. */ +#ifndef CONTIKI_TARGET_CC2538DK + random_init(seed); +#endif +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_espidf.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_espidf.c new file mode 100644 index 000000000..084bcecbb --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_espidf.c @@ -0,0 +1,42 @@ +/******************************************************************************* + * + * Copyright (c) 2011-2019 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * Achim Kraus - session recovery + * Sachin Agrawal - rehandshake support + * Jon Shallow - platform dependent prng support + * + *******************************************************************************/ + +#include "tinydtls.h" +#include "dtls_prng.h" +#include + +#include + +/** + * Fills \p buf with \p len random bytes. This is the default + * implementation for prng(). You might want to change prng() to use + * a better PRNG on your specific platform. + */ +int +dtls_prng(unsigned char *buf, size_t len) { + esp_fill_random(buf, len); + return len; +} + +void +dtls_prng_init(unsigned seed) { + return; +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_posix.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_posix.c new file mode 100644 index 000000000..0051fc73c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_posix.c @@ -0,0 +1,73 @@ +/******************************************************************************* + * + * Copyright (c) 2011-2020 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * Achim Kraus - session recovery + * Sachin Agrawal - rehandshake support + * Jon Shallow - platform dependent prng support + * + *******************************************************************************/ + +#include "tinydtls.h" +#include "dtls_prng.h" +#include "dtls_debug.h" + +#ifdef HAVE_GETRANDOM +#include +#endif /* HAVE_GETRANDOM */ +#include +#include + +/** + * Fills @p buf with @p len random bytes. This is the default + * implementation for prng(). You might want to change prng() to use + * a better PRNG on your specific platform. + */ +int +dtls_prng(unsigned char *buf, size_t len) { +#ifdef HAVE_GETRANDOM + return getrandom(buf, len, 0); +#else /* !HAVE_GETRANDOM */ + size_t klen = len; + while (len--) + *buf++ = rand() & 0xFF; + return klen; +#endif /* !HAVE_GETRANDOM */ +} + +void +dtls_prng_init(unsigned seed) { +#ifdef HAVE_GETRANDOM + /* No seed to seed the random source if getrandom() is used, + * see dtls_prng(). */ + (void)seed; +#else /* !HAVE_GETRANDOM */ + FILE *urandom = fopen("/dev/urandom", "r"); + unsigned char buf[sizeof(unsigned long)]; + (void)seed; + + if (!urandom) { + dtls_emerg("cannot initialize PRNG\n"); + return; + } + + if (fread(buf, 1, sizeof(buf), urandom) != sizeof(buf)) { + dtls_emerg("cannot initialize PRNG\n"); + return; + } + + fclose(urandom); + srand((unsigned long)*buf); +#endif /* !HAVE_GETRANDOM */ +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_riot.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_riot.c new file mode 100644 index 000000000..3a03b7ff3 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_riot.c @@ -0,0 +1,35 @@ +/******************************************************************************* + * + * Copyright (c) 2011-2019 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * Achim Kraus - session recovery + * Sachin Agrawal - rehandshake support + * Jon Shallow - platform dependent prng support + * + *******************************************************************************/ + +#include "tinydtls.h" +#include "dtls_prng.h" +#include "random.h" + +int +dtls_prng(unsigned char *buf, size_t len) { + random_bytes(buf, len); + return len; +} + +void +dtls_prng_init(unsigned seed) { + (void) seed; +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_zephyr.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_zephyr.c new file mode 100644 index 000000000..e2f9a703a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/dtls_prng_zephyr.c @@ -0,0 +1,35 @@ +/******************************************************************************* + * + * Copyright (c) 2022 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.html. + * + * SPDX-License-Identifier: EPL-1.0 + * + * Contributors: + * Achim Kraus - initial port for zephyr + * + *******************************************************************************/ + +#include "tinydtls.h" +#include "dtls_prng.h" +#include "random/rand32.h" + +int +dtls_prng(unsigned char *buf, size_t len) { + sys_csrand_get(buf, len); + return len; +} + +void +dtls_prng_init(unsigned seed) { + (void) seed; +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/platform.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/platform.h new file mode 100644 index 000000000..42b8bc994 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/platform.h @@ -0,0 +1,90 @@ +/************************************************************************/ +/* Contiki-specific parameters */ +/************************************************************************/ + +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ 1 + +#ifdef CONTIKI +#define WITH_CONTIKI 1 + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include "contiki-conf.h" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "tinydtls" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.8.6" + +/* support for TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */ +#ifndef DTLS_CONF_ECC +#define DTLS_CONF_ECC 1 +#endif +#if DTLS_CONF_ECC +#define DTLS_ECC +#endif + +/* support for TLS_PSK_WITH_AES_128_CCM_8 */ +#ifndef DTLS_CONF_PSK +#define DTLS_CONF_PSK 1 +#endif +#if DTLS_CONF_PSK +#define DTLS_PSK +#endif + +/* Disable all debug output and assertions */ +#ifndef DTLS_CONF_NDEBUG +#if DTLS_CONF_NDEBUG +#define NDEBUG +#endif +#endif + +/* Contiki has assert.h */ +#define HAVE_ASSERT_H 1 + +/* global constants for constrained devices running Contiki */ +#ifndef DTLS_PEER_MAX +/** The maximum number DTLS peers (i.e. sessions). */ +# define DTLS_PEER_MAX 1 +#endif + +#ifndef DTLS_HANDSHAKE_MAX +/** The maximum number of concurrent DTLS handshakes. */ +# define DTLS_HANDSHAKE_MAX 1 +#endif + +#ifndef DTLS_SECURITY_MAX +/** The maximum number of concurrently used cipher keys */ +# define DTLS_SECURITY_MAX (DTLS_PEER_MAX + DTLS_HANDSHAKE_MAX) +#endif + +#ifndef DTLS_HASH_MAX +/** The maximum number of hash functions that can be used in parallel. */ +# define DTLS_HASH_MAX (3 * DTLS_PEER_MAX) +#endif + +/** do not use uthash hash tables */ +#define DTLS_PEERS_NOHASH 1 + +/* BYTE_ORDER definition for sha2 */ +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN UIP_LITTLE_ENDIAN +#endif +#ifndef BIG_ENDIAN +#define BIG_ENDIAN UIP_BIG_ENDIAN +#endif +#ifndef BYTE_ORDER +#define BYTE_ORDER UIP_BYTE_ORDER +#endif + +#ifndef SHA2_USE_INTTYPES_H +#define SHA2_USE_INTTYPES_H 1 +#endif + +#endif /* CONTIKI */ + +#endif /* _PLATFORM_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/riot_boards.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/riot_boards.h new file mode 100644 index 000000000..f18e5ae7a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/platform-specific/riot_boards.h @@ -0,0 +1,152 @@ +/************************************************************************/ +/* RIOT-specific parameters */ +/************************************************************************/ + + +#ifndef _RIOT_BOARDS_H_ +#define _RIOT_BOARDS_H_ + +/* + * SETTING FOR TINYDTLS OVER RIOT + * In standard installation of TinyDTLS they are at dtls_config.h + * Only those used by the main library (not test/ or test* files) are here. + * + * WARNING: Dynamic memory is not working very well over RIOT. + */ + + +/* RIOT supports header file. */ +#define HAVE_ASSERT_H 1 + +/* RIOT supports header file. */ +#define HAVE_INTTYPES_H 1 + +/* RIOT does NOT implement the member sin6_len */ +#undef HAVE_SOCKADDR_IN6_SIN6_LEN + +/* RIOT supports the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* RIOT supports the header file. */ +#define HAVE_TIME_H 1 + +/* RIOT supports Sockets */ +/* TODO NOTE: This should be enable by WITH_RIOT_SOCKETS */ + +/* RIOT has partial support for the `vprintf' function. */ +/* DANGER Removing bring issues with dtls_debug.h and dtls_debug.c */ +#define HAVE_VPRINTF 1 + + +/* + * INFORMATION ABOUT TINYDTLS + * NOTE: This is used mostly by dtls_debug + */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "tinydtls" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "tinydtls 0.8.6.X" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "tinydtls" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.8.6.X" + +/* + * PERFORMANCE AND RESOURCES AVALIABLE TO THE MOTES FOR DTLS SESSIONS + * + * They are used with peer.c, crypto.c and hmac.c + * + * NOTE: Those numbers are not strictly the minimum. You can adjust at will. + * Example: iotlab-m3 were tested with two Peers sessions. + * + * WARNING: Dynamic memory is not working very well over RIOT. + Therefore, adapting static memory could improve the performance + for RIOT nodes. + */ + +#ifndef DTLS_CONTEXT_MAX +/** The maximum number of DTLS context at the same time. */ +# define DTLS_CONTEXT_MAX 2 +#endif + +#ifndef DTLS_PEER_MAX +/** The maximum number DTLS peers (i.e. sessions). */ +# define DTLS_PEER_MAX 1 +#endif + +#ifndef DTLS_HANDSHAKE_MAX +/** The maximum number of concurrent DTLS handshakes. */ +# define DTLS_HANDSHAKE_MAX 1 +#endif + +#ifndef DTLS_SECURITY_MAX +/** The maximum number of concurrently used cipher keys */ +# define DTLS_SECURITY_MAX (DTLS_PEER_MAX + DTLS_HANDSHAKE_MAX) +#endif + +/* TODO: Adapt this to RIOT (currently is only for Contiki) */ +#ifndef DTLS_HASH_MAX +/** The maximum number of hash functions that can be used in parallel. */ +# define DTLS_HASH_MAX (3 * DTLS_PEER_MAX) +#endif + +/** do not use uthash's hash tables (the tables uses malloc/free) */ +#define DTLS_PEERS_NOHASH 1 + +/* The 802.15.4 ACK can provoke very fast re-transmissions with a value + * higher than one. This is a temporary bad behavior for the RIOT MAC + */ +#ifndef DTLS_DEFAULT_MAX_RETRANSMIT +# define DTLS_DEFAULT_MAX_RETRANSMIT 1 +#endif + + +/* + * INFORMATION SHA2/ LIBRARY VARIABLES + * + * TODO: Clarify the way RIOT identifies BYTE_ORDER + */ + +/* + * RIOT supports the header file. + * NOTE: uintXX_t definitions with the ANSI C headers instead of custom typedef + */ +#define SHA2_USE_INTTYPES_H 1 + +/* RIOT "supports" memset()/memcpy() BUT not bzero()/mcopy(). */ +#define SHA2_USE_MEMSET_MEMCPY 1 + + +/* + * NOTE Gcc is who define if we are big endian or little endian. + * Because RIOT has __BYTE_ORDER__ and BYTE_ORDER it is not clear which one + * should take preference here. Or, if the #define inside of sha2/sha2.h + * should be removed at all. + */ +#ifndef BIG_ENDIAN +#if !defined(__BIG_ENDIAN__) +# define BIG_ENDIAN 4321 +# else +# define BIG_ENDIAN __BIG_ENDIAN__ +# endif +#endif + +#ifndef LITTLE_ENDIAN +#if !defined(__LITTLE_ENDIAN__) +# define LITTLE_ENDIAN 1234 +# else +# define LITTLE_ENDIAN __LITTLE_ENDIAN__ +# endif +#endif + +#endif /* _RIOT_BOARDS_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/session.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/session.c new file mode 100644 index 000000000..bdd845a9d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/session.c @@ -0,0 +1,152 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * + *******************************************************************************/ + +#include "session.h" + +#ifdef HAVE_ASSERT_H +#include +#else +#ifndef assert +#warning "assertions are disabled" +# define assert(x) +#endif +#endif + +#if defined(WITH_CONTIKI) +#define _dtls_address_equals_impl(A,B) \ + ((A)->size == (B)->size \ + && (A)->port == (B)->port \ + && uip_ipaddr_cmp(&((A)->addr),&((B)->addr)) \ + && (A)->ifindex == (B)->ifindex) +#elif defined(WITH_RIOT_SOCK) +#include "net/af.h" +#ifdef SOCK_HAS_IPV4 +#define _dtls_ipv4_address_equals_impl(A,B) \ + ((A)->size == (B)->size \ + && (A)->addr.port == (B)->addr.port \ + && (A)->ifindex == (B)->ifindex) \ + && (A)->addr.family == (B)->addr.family \ + && ipv4_addr_equal(&((A)->addr.ipv4),&((B)->addr.ipv4)) +#endif +#ifdef SOCK_HAS_IPV6 +#define _dtls_ipv6_address_equals_impl(A,B) \ + ((A)->size == (B)->size \ + && (A)->addr.port == (B)->addr.port \ + && (A)->ifindex == (B)->ifindex) \ + && (A)->addr.family == (B)->addr.family \ + && ipv6_addr_equal(&((A)->addr.ipv6),&((B)->addr.ipv6)) +#endif +#else /* WITH_CONTIKI */ + +static inline int +_dtls_address_equals_impl(const session_t *a, + const session_t *b) { + if (a->ifindex != b->ifindex || + a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family) + return 0; + + /* need to compare only relevant parts of sockaddr_in6 */ + switch (a->addr.sa.sa_family) { + case AF_INET: + return + a->addr.sin.sin_port == b->addr.sin.sin_port && + memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr, + sizeof(struct in_addr)) == 0; + case AF_INET6: + return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port && + memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr, + sizeof(struct in6_addr)) == 0; + default: /* fall through and signal error */ + ; + } + return 0; +} +#endif /* WITH_CONTIKI */ + +void +dtls_session_init(session_t *sess) { + assert(sess); + memset(sess, 0, sizeof(session_t)); + sess->size = sizeof(sess->addr); +} + +/* These functions are primarly needed for the tinydtls ruby gem. + * + * They are not implemented on Contiki and RIOT because these operating + * system don't supply malloc(3). This could be fixed by fixed by using + * memory pools on these operating system as in `peer.c`. However, the + * downside of this approach is that the memory pools reserve memory + * even if the `dtls_new_session` isn't used and usually memory for the + * `session_t` type is already resevered in the `peer_t` struct. + * Therefore it would introduces quite some overhead on these + * constrained platforms. + * + * In the long run we probably want to create two seperate memory pools + * for sessions and peers and store a pointer to a session in the peer + * struct. + */ +#if !(defined (WITH_CONTIKI)) && !(defined (RIOT_VERSION)) +session_t* +dtls_new_session(struct sockaddr *addr, socklen_t addrlen) { + session_t *sess; + + sess = malloc(sizeof(session_t)); + if (!sess) + return NULL; + dtls_session_init(sess); + + sess->size = addrlen; + memcpy(&sess->addr.sa, addr, sess->size); + + return sess; +} + +void +dtls_free_session(session_t *sess) { + free(sess); +} + +struct sockaddr* +dtls_session_addr(session_t *sess, socklen_t *addrlen) { + if (!sess) + return NULL; + + *addrlen = sess->size; + return &sess->addr.sa; +} +#endif /* !(defined (WITH_CONTIKI)) && !(defined (RIOT_VERSION)) */ + +int +dtls_session_equals(const session_t *a, const session_t *b) { + assert(a); assert(b); +#ifdef RIOT_VERSION + switch (a->addr.family) { +#ifdef SOCK_HAS_IPV4 + case AF_INET: + return _dtls_ipv4_address_equals_impl(a, b); +#endif +#ifdef SOCK_HAS_IPV6 + case AF_INET6: + return _dtls_ipv6_address_equals_impl(a, b); +#endif + default: + assert(0); + return false; + } +#else + return _dtls_address_equals_impl(a, b); +#endif /* RIOT_VERSION */ +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/session.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/session.h new file mode 100644 index 000000000..8304c8b78 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/session.h @@ -0,0 +1,129 @@ +/******************************************************************************* + * + * Copyright (c) 2011-2019 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * + *******************************************************************************/ + +#ifndef _DTLS_SESSION_H_ +#define _DTLS_SESSION_H_ + +#include + +#include "tinydtls.h" +#include "global.h" + +#ifdef WITH_CONTIKI +#include "ip/uip.h" +typedef struct { + unsigned char size; /**< size of session_t::addr */ + uip_ipaddr_t addr; /**< session IP address */ + unsigned short port; /**< transport layer port */ + int ifindex; /**< network interface index */ +} session_t; + /* TODO: Add support for RIOT over sockets */ +#elif defined(WITH_RIOT_SOCK) +#include "net/ipv4/addr.h" +#include "net/ipv6/addr.h" +typedef struct { + unsigned char size; /**< size of session_t::addr */ + struct { + unsigned short family; /**< IP address family */ + unsigned short port; /**< transport layer port */ + union { +#ifdef SOCK_HAS_IPV4 + ipv4_addr_t ipv4; /**< IPv4 address */ +#endif +#ifdef SOCK_HAS_IPV6 + ipv6_addr_t ipv6; /**< IPv6 address */ +#endif + }; + } addr; /**< session IP address and port */ + int ifindex; /**< network interface index */ +} session_t; +#else /* ! WITH_CONTIKI && ! WITH_RIOT_SOCK */ + +#ifdef WITH_ZEPHYR +#include +#ifdef HAVE_NET_SOCKET_H +#include +#endif /* HAVE_NET_SOCKET_H */ + +#elif defined(WITH_LWIP) +#include "lwip/sockets.h" +#undef write +#undef read +typedef unsigned char uint8_t; + +#else /* ! WITH_ZEPHYR && ! WITH_LWIP */ +#include +#include +#include +#endif /* ! WITH_ZEPHYR && ! WITH_LWIP */ + +typedef struct { + socklen_t size; /**< size of addr */ + union { + struct sockaddr sa; + struct sockaddr_storage st; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + } addr; + int ifindex; +} session_t; +#endif /* ! WITH_CONTIKI && ! WITH_RIOT_SOCK */ + +/** + * Resets the given session_t object @p sess to its default + * values. In particular, the member rlen must be initialized to the + * available size for storing addresses. + * + * @param sess The session_t object to initialize. + */ +void dtls_session_init(session_t *sess); + +#if !(defined (WITH_CONTIKI)) && !(defined (RIOT_VERSION)) +/** + * Creates a new ::session_t for the given address. + * + * @param addr Address which should be stored in the ::session_t. + * @param addrlen Length of the @p addr. + * @return The new session or @c NULL on error. + */ +session_t* dtls_new_session(struct sockaddr *addr, socklen_t addrlen); + +/** + * Frees memory allocated for a session using ::dtls_new_session. + * + * @param sess Pointer to a session for which allocated memory should be + * freed. + */ +void dtls_free_session(session_t *sess); + +/** + * Extracts the address of the given ::session_t. + * + * @param sess Session to extract address for. + * @param addrlen Pointer to memory location where the address + * length should be stored. + * @return The address or @c NULL if @p sess was @c NULL. + */ +struct sockaddr* dtls_session_addr(session_t *sess, socklen_t *addrlen); +#endif /* !(defined (WITH_CONTIKI)) && !(defined (RIOT_VERSION)) */ + +/** + * Compares the given session objects. This function returns @c 0 + * when @p a and @p b differ, @c 1 otherwise. + */ +int dtls_session_equals(const session_t *a, const session_t *b); + +#endif /* _DTLS_SESSION_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/README b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/README new file mode 100644 index 000000000..95e57f39d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/README @@ -0,0 +1,272 @@ +VERSION: + +This is version 1.0 RELEASE + +While this is my "release" version, due to lack of additional +official test vectors against which to verify this implementation's +correctness, beware that there may be implementation bugs. Also, +it has not yet been tested on very many other architectures, +big-endian machines in particular. + + +LICENSE: + +This implementation is released freely under an open-source BSD +license which appears at the top of each source code file. + + +WHAT IT IS: + +The files sha2.h and sha2.c implement the SHA-256, SHA-384, and SHA-512 +hash algorithms as described in the PDF document found at the following +web address: + + http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf + +The interface is similar to the interface to SHA-1 found in the OpenSSL +library. + +The file sha2prog.c is a simple program that accepts input from either +STDIN or reads one or more files specified on the command line, and then +generates the specified hash (either SHA-256, SHA-384, SHA-512, or any +combination thereof, including all three at once). + + +LIMITATIONS: + +This implementation has several limitations: + + * Input data is only accepted in octet-length increments. No sub-byte + data is handled. The NIST document describes how to handle sub-byte + input data, but for ease of implementation this version will only + accept message data in multiples of bytes. + * This implementation utilizes 64-bit integer data types. If your + system and compiler does not have a 64-bit integer data type, this + implementation will not work. + * Because of the use of 64-bit operations, many 32-bit architectures + that do have 64-bit data types but do operations most efficiently + on 32-bit words, this implementation may be slower than an + implementation designed to use only 32-bit words (emulating the + 64-bit operations). + * On platforms with 128-bit integer data types, the SHA-384 and SHA-512 + bit counters used by this implementation might be better off using + the 128-bit type instead of simulating it with two 64-bit integers. + * This implementation was written in C in hopes of portability and for + the fun of it during my spare time. It is probably not the most + efficient or fastest C implementation. I welcome suggestions, + however, that suggest ways to speed things up without breaking + portability. I also welcome suggestions to improve portability. + * As mentioned above, this code has NOT been thoroughly tested. + This is perhaps the most severe limitation. + + +BEFORE YOU COMPILE (OPTIONS): + +Each of the options described below may either be defined in the sha2.h +header file (or in the sha2.c file in some cases), or on the command +line at compile time if your compiler supports such things. For +example: + + #define SHA2_USE_INTTYPES_H + #define SHA2_UNROLL_TRANSFORM + +Or: + + cc -c -DSHA2_UNROLL_TRANSFORM sha2.c + cc -c -DBYTE_ORDER=4321 -DBIG_ENDIAN=4321 sha2.c + +Here are the available options. Read on below for a description of +each one: + + SHA2_USE_INTTYPES_H + SHA2_USE_MEMSET_MEMCPY/SHA2_USE_BZERO_BCOPY + SHA2_UNROLL_TRANSFORM + BYTE_ORDER (LITTLE_ENDIAN/BIG_ENDIAN) + +* SHA2_USE_INTTYPES_H option: +By default, this code uses u_intXX_t data types for 8 bit, 32 bit, and +64 bit unsigned integer type definitions. Most BSD systems define these, +as does Linux. However, some (like Compaq's Tru64 Unix) may instead +use uintXX_t data types as defined by recent ANSI C standards and as +included in the inttypes.h header file. Those wanting to use inttypes.h +need to define this either in sha.h or at compile time. + +On those systems where NEITHER definitions are available, you will need +to edit both sha2.h and sha2.c and define things by hand in the appropriate +sections. + +* BYTE_ORDER definitions: +This code assumes that BYTE_ORDER will be defined by the system during +compile to either equal LITTLE_ENDIAN or BIG_ENDIAN. If your system +does not define these, you may need to define them by hand in the sha.c +file according to the byte ordering conventions of your system. + +* SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY +The code in sha2.c can use either memset()/memcpy() for memory block +operations, or bzero()/mcopy(). If you define neither of these, the +code will default to memset()/memcpy(). You can define either at the +command line or in sha2.h or in sha2.c. + +* SHA2_UNROLL_TRANSFORM +By defining this either on the command line or in sha2.h or sha2.c, +the code will use macros to partially "unroll" the SHA transform +function. This usually generates bigger executables. It CAN (but +not necessarily WILL) generate faster code when you tell your compiler +to optimize things. For example, on the FreeBSD and Linux x86 systems +I tested things on (using gcc), when I optimized with just -O2 and +unrolled the transform, the hash transform was faster by 15-30%. On +these same systems, if I did NO optimization, the unrolled transform +was SLOWER, much slower (I'm guessing because the code was breaking +the cache, but I'm not sure). Your mileage may vary. + + +PORTABILITY: + +The code in sha2.c and sha2.h is intended to be portable. It may +require that you do a few #definitions in the .h file. I've successfully +compiled and tested the sha2.c and sha2.h code on Apple's OS X (on +a PPC), FreeBSD 4.1.1 on Intel, Linux on Intel, FreeBSD on the Alpha, +and even under Windows98SE using Metrowerks C. The utility/example +programs (sha2prog.c, sha2test.c, and sha2speed.c) will very likely +have more trouble in portability since they do I/O. + +To get sha2.c/sha2.h working under Windows, I had to define +SHA2_USE_INTTYPES_H, BYTE_ORDER, LITTLE_ENDIAN, and had to comment +out the include of in sha2.h. With a bit more work +I got the test program to run and verified that all the test +cases passed. + + +SUGGESTIONS/BUG FIXES: + +If you make changes to get it working on other architectures, if you fix +any bugs, or if you make changes that improve this implementation's +efficiency that would be relatively portable and you're willing to release +your changes under the same license, please send them to me for possible +inclusion in future versions. + +If you know where I can find some additional test vectors, please let me +know. + + +CHANGE HISTORY: + +0.8 to 0.9 - Fixed spelling errors, changed to u_intXX_t type usage, + removed names from prototypes, added prototypes to sha2.c, + and a few things I can't recall. + +0.9 to 0.9.5 - Add a new define in sha2.c that permits one to compile + it to either use memcpy()/memset() or bcopy()/bzero() + for memory block copying and zeroing. Added support + for unrolled SHA-256/384/512 transform loops. Just + compile with SHA2_UNROLL_TRANSFORM to enable. It takes + longer to compile, but I hope it is a bit faster. I + need to do some test to see whether or not it is. Oh, + in sha2.c, you either need to define SHA2_USE_BZERO_BCOPY + or SHA2_USE_MEMSET_MEMCPY to choose which way you want + to compile. *Whew* It's amazing how quickly something + simple starts to grow more complex even in the span of + just a few hours. I didn't really intend to do this much. +0.9.5 to 0.9.6 - Added a test program (sha2test) which tests against several + known test vectors. WARNING: Some of the test output + hashes are NOT from NIST's documentation and are the + output of this implementation and so may be incorrect. +0.9.6 to 0.9.7 - Fixed a bug that could cause invalid output in certain + cases and added an assumed scenario where zero-length + data is hashed. Also changed the rotation macros to use + a temporary variable as this reduces the number of operations. + When data is fed in blocks of the right length, copying of + data is reduced in this version. Added SHAYXZ_Data() + functions for ease of hashing a set of data. Added another + file sha2speed.c for doing speed testing. Added another test + vector with a larger data size (16KB). Fixed u_intXX_t and + uintXX_t handling by adding a define for SHA2_USE_INTTYPES_H + as well as made a few other minor changes to get rid of + warnings when compiling on Compaq's Tru64 Unix. +0.9.7 to 0.9.8 - The bug fix in 0.9.7 was incomplete and in some cases made + things worse. I believe that 0.9.8 fixes the bug completely + so that output is correct. I cannot verify this, however, + because of the lack of test vectors against which to do such + verification. All versions correctly matched the very few + NIST-provided vectors, but unfortunately the bug only + appeared in longer message data sets. +0.9.8 to 0.9.9 - Fixed some really bad typos and mistakes on my part that + only affected big-endian systems. I didn't have direct + access for testing before this version. Thanks to + Lucas Marshall for giving me access to his OS X system. +0.9.9 to 1.0.0b1 Added a few more test samples and made a few changes to + make things easier compiling on several other platforms. + Also I experimented with alternate macro definitions + in the SHA2_UNROLL_TRANSFORM version (see sha2.slower.c) + and eliminated the T1 temporary variable (the compiler + would of course still use internal temporary storage + during expression evaluation, but I'd hoped the compiler + would be more efficient), but unfortunately under FreeBSD + 4.1.1-STABLE on an x86 platform, the change slowed things + down. +1.0.0b1 to 1.0 RELEASE Fixed an off-by-one implementation bug that affected + SHA-256 when hashed data length L = 55 + 64 * X where X is + either zero or a positive integer, and another (basically + the same bug) bug in SHA-384 and SHA-512 that showed up when + hashed data lengths L = 111 + 128 * X. Thanks to Rogier + van de Pol for sending me test data that revealed the bug. + The fix was very simple (just two tiny changes). Also, + I finally put the files into RCS so future changes will be + easier to manage. The sha2prog.c file was rewritten to + be more useful to me, and I got rid of the old C testing + program and now use a perl script with a subdirectory full + of test data. It's a more flexible test system. + + +LATEST VERSION: + +The latest version and documentation (if any ;) should always be available +on the web at: + + http://www.aarongifford.com/computers/sha.html + + +CONTACT ME: + +I can be reached via email at: + + Aaron Gifford + +Please don't send support questions. I don't have the time to answer and +they'll probably be ignored. Bug fixes, or patches that add something useful +will be gratefully accepted, however. + +If you use this implementation, I would enjoy getting a brief email message +letting me know who you are and what use to which it is being put. There +is no requirement to do so. I just think it would be fun. + + +EXAMPLES: + +Here's an example of compiling and using the sha2 program (in this example +I build it using the unrolled transform version with -O2 optimizations), +and then running the perl testing script: + + cc -O2 -DSHA2_UNROLL_TRANSFORM -Wall -o sha2 sha2prog.c sha2.c + % ./sha2test.pl + + [most of the perl script output deleted for brevity] + + ===== RESULTS (18 VECTOR DATA FILES HASHED) ===== + + HASH TYPE NO. OF TESTS PASSED FAILED + --------- ------------ ------ ------ + SHA-256 18 18 0 + SHA-384 18 18 0 + SHA-512 18 18 0 + ---------------------------------------------- + TOTAL: 54 54 0 + + NO ERRORS! ALL TESTS WERE SUCCESSFUL! + + ALL TEST VECTORS PASSED! + +That's all folks! Have fun! + +Aaron out. + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2.c new file mode 100644 index 000000000..633c3a910 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2.c @@ -0,0 +1,1106 @@ +/* + * FILE: sha2.c + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * 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. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 OR CONTRIBUTOR(S) 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. + * + * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ + */ + +#include "tinydtls.h" +#include /* memcpy()/memset() or bcopy()/bzero() */ +#ifdef HAVE_ASSERT_H +#include /* assert() */ +#else +#ifndef assert +#warning "assertions are disabled" +# define assert(x) +#endif +#endif +#include "sha2.h" + +/* + * ASSERT NOTE: + * Some sanity checking code is included using assert(). On my FreeBSD + * system, this additional code can be removed by compiling with NDEBUG + * defined. Check your own systems manpage on assert() to see how to + * compile WITHOUT the sanity checking code on your system. + * + * UNROLLED TRANSFORM LOOP NOTE: + * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform + * loop version for the hash transform rounds (defined using macros + * later in this file). Either define on the command line, for example: + * + * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c + * + * or define below: + * + * #define SHA2_UNROLL_TRANSFORM + * + */ + + +/*** SHA-256/384/512 Machine Architecture Definitions *****************/ +/* + * BYTE_ORDER NOTE: + * + * Please make sure that your system defines BYTE_ORDER. If your + * architecture is little-endian, make sure it also defines + * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are + * equivilent. + * + * If your system does not define the above, then you can do so by + * hand like this: + * + * #define LITTLE_ENDIAN 1234 + * #define BIG_ENDIAN 4321 + * + * And for little-endian machines, add: + * + * #define BYTE_ORDER LITTLE_ENDIAN + * + * Or for big-endian machines: + * + * #define BYTE_ORDER BIG_ENDIAN + * + * The FreeBSD machine this was written on defines BYTE_ORDER + * appropriately by including (which in turn includes + * where the appropriate definitions are actually + * made). + */ + +/* bergmann: define LITTLE_ENDIAN and BIG_ENDIAN to ease autoconf: */ +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#ifndef BYTE_ORDER +# if defined(WORDS_BIGENDIAN) || (defined(AC_APPLE_UNIVERSAL_BUILD) && defined(__BIG_ENDIAN__)) +# define BYTE_ORDER BIG_ENDIAN +# else /* WORDS_BIGENDIAN */ +# define BYTE_ORDER LITTLE_ENDIAN +# endif +#endif + +#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) +#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN +#endif + +/* + * Macros for copying blocks of memory and for zeroing out ranges + * of memory. Using these macros makes it easy to switch from + * using memset()/memcpy() and using bzero()/bcopy(). + * + * Please define either SHA2_USE_MEMSET_MEMCPY or define + * SHA2_USE_BZERO_BCOPY depending on which function set you + * choose to use: + */ +#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) +/* Default to memset()/memcpy() if no option is specified */ +#define SHA2_USE_MEMSET_MEMCPY 1 +#endif +#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) +/* Abort with an error if BOTH options are defined */ +#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! +#endif + +#ifdef SHA2_USE_MEMSET_MEMCPY +#define MEMSET_BZERO(p,l) memset((p), 0, (l)) +#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) +#endif +#ifdef SHA2_USE_BZERO_BCOPY +#define MEMSET_BZERO(p,l) bzero((p), (l)) +#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) +#endif + +/* + * Define the followingsha2_* types to types of the correct length on + * the native archtecture. Most BSD systems and Linux define u_intXX_t + * types. Machines with very recent ANSI C headers, can use the + * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H + * during compile or in the sha.h header file. + * + * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t + * will need to define these three typedefs below (and the appropriate + * ones in sha.h too) by hand according to their system architecture. + * + * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t + * types and pointing out recent ANSI C support for uintXX_t in inttypes.h. + */ +#ifdef SHA2_USE_INTTYPES_H + +typedef uint8_t sha2_byte; /* Exactly 1 byte */ +typedef uint32_t sha2_word32; /* Exactly 4 bytes */ +typedef uint64_t sha2_word64; /* Exactly 8 bytes */ + +#else /* SHA2_USE_INTTYPES_H */ + +typedef u_int8_t sha2_byte; /* Exactly 1 byte */ +typedef u_int32_t sha2_word32; /* Exactly 4 bytes */ +typedef u_int64_t sha2_word64; /* Exactly 8 bytes */ + +#endif /* SHA2_USE_INTTYPES_H */ + + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +/* NOTE: Most of these are in sha2.h */ +#define DTLS_SHA256_SHORT_BLOCK_LENGTH (DTLS_SHA256_BLOCK_LENGTH - 8) +#define DTLS_SHA384_SHORT_BLOCK_LENGTH (DTLS_SHA384_BLOCK_LENGTH - 16) +#define DTLS_SHA512_SHORT_BLOCK_LENGTH (DTLS_SHA512_BLOCK_LENGTH - 16) + +/*** ENDIAN / WORD ALIGNING Handling Functions ***/ + +static inline sha2_word32 get32be(const sha2_byte* data) +{ +#if BYTE_ORDER == LITTLE_ENDIAN + sha2_word32 tmp = ((sha2_word32)data[0] << 24) | + ((sha2_word32)data[1] << 16) | + ((sha2_word32)data[2] << 8) | + (sha2_word32)data[3]; + return tmp; +#else /* BYTE_ORDER != LITTLE_ENDIAN */ + sha2_word32 tmp; + MEMCPY_BCOPY(&tmp, data, sizeof(tmp)); + return tmp; +#endif /* BYTE_ORDER != LITTLE_ENDIAN */ +} + +static inline void put32be(sha2_byte* data, sha2_word32 val) +{ +#if BYTE_ORDER == LITTLE_ENDIAN + data[3] = val; val >>= 8; + data[2] = val; val >>= 8; + data[1] = val; val >>= 8; + data[0] = val; +#else /* BYTE_ORDER != LITTLE_ENDIAN */ + MEMCPY_BCOPY(data, &val, sizeof(val)); +#endif /* BYTE_ORDER != LITTLE_ENDIAN */ +} + +static inline sha2_word64 get64be(const sha2_byte* data) +{ +#if BYTE_ORDER == LITTLE_ENDIAN + sha2_word64 tmp = ((sha2_word64)data[0] << 56) | + ((sha2_word64)data[1] << 48) | + ((sha2_word64)data[2] << 40) | + ((sha2_word64)data[3] << 32) | + ((sha2_word64)data[4] << 24) | + ((sha2_word64)data[5] << 16) | + ((sha2_word64)data[6] << 8) | + (sha2_word64)data[7]; + return tmp; +#else /* BYTE_ORDER != LITTLE_ENDIAN */ + sha2_word64 tmp; + MEMCPY_BCOPY(&tmp, data, sizeof(tmp)); + return tmp; +#endif /* BYTE_ORDER != LITTLE_ENDIAN */ +} + +static inline void put64be(sha2_byte* data, sha2_word64 val) +{ +#if BYTE_ORDER == LITTLE_ENDIAN + data[7] = val; val >>= 8; + data[6] = val; val >>= 8; + data[5] = val; val >>= 8; + data[4] = val; val >>= 8; + data[3] = val; val >>= 8; + data[2] = val; val >>= 8; + data[1] = val; val >>= 8; + data[0] = val; +#else /* BYTE_ORDER != LITTLE_ENDIAN */ + MEMCPY_BCOPY(data, &val, sizeof(val)); +#endif /* BYTE_ORDER != LITTLE_ENDIAN */ +} + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) { \ + (w)[0] += (sha2_word64)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} + + +/*** THE SIX LOGICAL FUNCTIONS ****************************************/ +/* + * Bit shifting and rotation (used by the six SHA-XYZ logical functions: + * + * NOTE: The naming of R and S appears backwards here (R is a SHIFT and + * S is a ROTATION) because the SHA-256/384/512 description document + * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this + * same "backwards" definition. + */ +/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +#define R(b,x) ((x) >> (b)) +/* 32-bit Rotate-right (used in SHA-256): */ +#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) +/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ +#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) + +/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) +#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) +#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) +#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) + +/* Four of six logical functions used in SHA-384 and SHA-512: */ +#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) +#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) +#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) +#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) + +/*** INTERNAL FUNCTION PROTOTYPES *************************************/ +/* NOTE: These should not be accessed directly from outside this + * library -- they are intended for private internal visibility/use + * only. + */ +void dtls_sha512_last(dtls_sha512_ctx*); +void dtls_sha256_transform(dtls_sha256_ctx*, const sha2_byte*); +void dtls_sha512_transform(dtls_sha512_ctx*, const sha2_byte*); + +#ifdef WITH_SHA256 +/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ +/* Hash constant words K for SHA-256: */ +static const sha2_word32 K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Initial hash value H for SHA-256: */ +static const sha2_word32 sha256_initial_hash_value[8] = { + 0x6a09e667UL, + 0xbb67ae85UL, + 0x3c6ef372UL, + 0xa54ff53aUL, + 0x510e527fUL, + 0x9b05688cUL, + 0x1f83d9abUL, + 0x5be0cd19UL +}; +#endif + +#if defined(WITH_SHA384) || defined(WITH_SHA512) +/* Hash constant words K for SHA-384 and SHA-512: */ +static const sha2_word64 K512[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; +#endif + +#ifdef WITH_SHA384 +/* Initial hash value H for SHA-384 */ +static const sha2_word64 sha384_initial_hash_value[8] = { + 0xcbbb9d5dc1059ed8ULL, + 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, + 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, + 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, + 0x47b5481dbefa4fa4ULL +}; +#endif + +#ifdef WITH_SHA512 +/* Initial hash value H for SHA-512 */ +static const sha2_word64 sha512_initial_hash_value[8] = { + 0x6a09e667f3bcc908ULL, + 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, + 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, + 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, + 0x5be0cd19137e2179ULL +}; +#endif + +/* + * Constant used by SHA256/384/512_End() functions for converting the + * digest to a readable hexadecimal character string: + */ +static const char *sha2_hex_digits = "0123456789abcdef"; + + +/*** SHA-256: *********************************************************/ +#ifdef WITH_SHA256 +void dtls_sha256_init(dtls_sha256_ctx* context) { + if (context == (dtls_sha256_ctx*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha256_initial_hash_value, DTLS_SHA256_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, DTLS_SHA256_BLOCK_LENGTH); + context->bitcount = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-256 round macros: */ + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + W256[j] = get32be(data); \ + data += 4; \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + W256[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +#define ROUND256(a,b,c,d,e,f,g,h) \ + s0 = W256[(j+1)&0x0f]; \ + s0 = sigma0_256(s0); \ + s1 = W256[(j+14)&0x0f]; \ + s1 = sigma1_256(s1); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +void dtls_sha256_transform(dtls_sha256_ctx* context, const sha2_byte* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + ROUND256_0_TO_15(a,b,c,d,e,f,g,h); + ROUND256_0_TO_15(h,a,b,c,d,e,f,g); + ROUND256_0_TO_15(g,h,a,b,c,d,e,f); + ROUND256_0_TO_15(f,g,h,a,b,c,d,e); + ROUND256_0_TO_15(e,f,g,h,a,b,c,d); + ROUND256_0_TO_15(d,e,f,g,h,a,b,c); + ROUND256_0_TO_15(c,d,e,f,g,h,a,b); + ROUND256_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds to 64: */ + do { + ROUND256(a,b,c,d,e,f,g,h); + ROUND256(h,a,b,c,d,e,f,g); + ROUND256(g,h,a,b,c,d,e,f); + ROUND256(f,g,h,a,b,c,d,e); + ROUND256(e,f,g,h,a,b,c,d); + ROUND256(d,e,f,g,h,a,b,c); + ROUND256(c,d,e,f,g,h,a,b); + ROUND256(b,c,d,e,f,g,h,a); + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void dtls_sha256_transform(dtls_sha256_ctx* context, const sha2_byte* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, T2, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + /* Copy data while converting to host byte order */ + W256[j] = get32be(data); + data += 4; + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void dtls_sha256_update(dtls_sha256_ctx* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (dtls_sha256_ctx*)0 && data != (sha2_byte*)0); + + usedspace = (context->bitcount >> 3) % DTLS_SHA256_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = DTLS_SHA256_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; + dtls_sha256_transform(context, context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + context->bitcount += len << 3; + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= DTLS_SHA256_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + dtls_sha256_transform(context, data); + context->bitcount += DTLS_SHA256_BLOCK_LENGTH << 3; + len -= DTLS_SHA256_BLOCK_LENGTH; + data += DTLS_SHA256_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + context->bitcount += len << 3; + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void dtls_sha256_final(uint8_t digest[DTLS_SHA256_DIGEST_LENGTH], dtls_sha256_ctx* context) { + sha2_byte *d = digest; + unsigned int usedspace; + + /* Sanity check: */ + assert(context != (dtls_sha256_ctx*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + usedspace = (context->bitcount >> 3) % DTLS_SHA256_BLOCK_LENGTH; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + context->bitcount = get64be((const sha2_byte *)&context->bitcount); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= DTLS_SHA256_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], DTLS_SHA256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < DTLS_SHA256_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], DTLS_SHA256_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + dtls_sha256_transform(context, context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, DTLS_SHA256_SHORT_BLOCK_LENGTH); + } + } else { + /* Set-up for the last transform: */ + MEMSET_BZERO(context->buffer, DTLS_SHA256_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Set the bit count: */ + /* *(sha2_word64*)(context->buffer+DTLS_SHA256_SHORT_BLOCK_LENGTH) = context->bitcount; */ + MEMCPY_BCOPY(context->buffer+DTLS_SHA256_SHORT_BLOCK_LENGTH, + (void *)&context->bitcount, sizeof(context->bitcount)); + /* Final transform: */ + dtls_sha256_transform(context, context->buffer); + + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + put32be(d, context->state[j]); + d+= 4; + } + } + } + + /* Clean up state data: */ + MEMSET_BZERO(context, sizeof(*context)); + usedspace = 0; +} + +char *dtls_sha256_end(dtls_sha256_ctx* context, char buffer[DTLS_SHA256_DIGEST_STRING_LENGTH]) { + sha2_byte digest[DTLS_SHA256_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (dtls_sha256_ctx*)0); + + if (buffer != (char*)0) { + dtls_sha256_final(digest, context); + + for (i = 0; i < DTLS_SHA256_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(*context)); + } + MEMSET_BZERO(digest, DTLS_SHA256_DIGEST_LENGTH); + return buffer; +} + +char* dtls_sha256_data(const sha2_byte* data, size_t len, char digest[DTLS_SHA256_DIGEST_STRING_LENGTH]) { + dtls_sha256_ctx context; + + dtls_sha256_init(&context); + dtls_sha256_update(&context, data, len); + return dtls_sha256_end(&context, digest); +} +#endif + +/*** SHA-512: *********************************************************/ +#ifdef WITH_SHA512 +void dtls_sha512_init(dtls_sha512_ctx* context) { + if (context == (dtls_sha512_ctx*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha512_initial_hash_value, DTLS_SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, DTLS_SHA512_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-512 round macros: */ + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + W512[j] = get64be(data); \ + data += 8; \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + W512[j]; \ + (d) += T1, \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ + j++ + +#define ROUND512(a,b,c,d,e,f,g,h) \ + s0 = W512[(j+1)&0x0f]; \ + s0 = sigma0_512(s0); \ + s1 = W512[(j+14)&0x0f]; \ + s1 = sigma1_512(s1); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +void dtls_sha512_transform(dtls_sha512_ctx* context, const sha2_byte* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + ROUND512_0_TO_15(a,b,c,d,e,f,g,h); + ROUND512_0_TO_15(h,a,b,c,d,e,f,g); + ROUND512_0_TO_15(g,h,a,b,c,d,e,f); + ROUND512_0_TO_15(f,g,h,a,b,c,d,e); + ROUND512_0_TO_15(e,f,g,h,a,b,c,d); + ROUND512_0_TO_15(d,e,f,g,h,a,b,c); + ROUND512_0_TO_15(c,d,e,f,g,h,a,b); + ROUND512_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds up to 79: */ + do { + ROUND512(a,b,c,d,e,f,g,h); + ROUND512(h,a,b,c,d,e,f,g); + ROUND512(g,h,a,b,c,d,e,f); + ROUND512(f,g,h,a,b,c,d,e); + ROUND512(e,f,g,h,a,b,c,d); + ROUND512(d,e,f,g,h,a,b,c); + ROUND512(c,d,e,f,g,h,a,b); + ROUND512(b,c,d,e,f,g,h,a); + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void dtls_sha512_transform(dtls_sha512_ctx* context, const sha2_byte* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + /* Convert TO host byte order */ + W512[j] = get64be(data); + data += 8; + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void dtls_sha512_update(dtls_sha512_ctx* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (dtls_sha512_ctx*)0 && data != (sha2_byte*)0); + + usedspace = (context->bitcount[0] >> 3) % DTLS_SHA512_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = DTLS_SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + ADDINC128(context->bitcount, freespace << 3); + len -= freespace; + data += freespace; + dtls_sha512_transform(context, context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + ADDINC128(context->bitcount, len << 3); + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= DTLS_SHA512_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + dtls_sha512_transform(context, data); + ADDINC128(context->bitcount, DTLS_SHA512_BLOCK_LENGTH << 3); + len -= DTLS_SHA512_BLOCK_LENGTH; + data += DTLS_SHA512_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + ADDINC128(context->bitcount, len << 3); + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void dtls_sha512_last(dtls_sha512_ctx* context) { + unsigned int usedspace; + + usedspace = (context->bitcount[0] >> 3) % DTLS_SHA512_BLOCK_LENGTH; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + context->bitcount[0] = get64be((sha2_byte *)&context->bitcount[0]); + context->bitcount[1] = get64be((sha2_byte *)&context->bitcount[1]); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= DTLS_SHA512_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], DTLS_SHA512_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < DTLS_SHA512_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], DTLS_SHA512_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + dtls_sha512_transform(context, context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, DTLS_SHA512_BLOCK_LENGTH - 2); + } + } else { + /* Prepare for final transform: */ + MEMSET_BZERO(context->buffer, DTLS_SHA512_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits): */ + *(sha2_word64*)&context->buffer[DTLS_SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; + *(sha2_word64*)&context->buffer[DTLS_SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; + + /* Final transform: */ + dtls_sha512_transform(context, context->buffer); +} + +void dtls_sha512_final(uint8_t digest[DTLS_SHA512_DIGEST_LENGTH], dtls_sha512_ctx* context) { + sha2_byte *d = digest; + + /* Sanity check: */ + assert(context != (dtls_sha512_ctx*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + dtls_sha512_last(context); + + /* Save the hash data for output: */ + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + put64be(d, context->state[j]); + d += 8; + } + } + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(*context)); +} + +char *dtls_sha512_end(dtls_sha512_ctx* context, char buffer[DTLS_SHA512_DIGEST_STRING_LENGTH]) { + sha2_byte digest[DTLS_SHA512_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (dtls_sha512_ctx*)0); + + if (buffer != (char*)0) { + dtls_sha512_final(digest, context); + + for (i = 0; i < DTLS_SHA512_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(*context)); + } + MEMSET_BZERO(digest, DTLS_SHA512_DIGEST_LENGTH); + return buffer; +} + +char* dtls_sha512_data(const sha2_byte* data, size_t len, char digest[DTLS_SHA512_DIGEST_STRING_LENGTH]) { + dtls_sha512_ctx context; + + dtls_sha512_init(&context); + dtls_sha512_update(&context, data, len); + return dtls_sha512_end(&context, digest); +} +#endif + +/*** SHA-384: *********************************************************/ +#ifdef WITH_SHA384 +void dtls_sha384_init(dtls_sha384_ctx* context) { + if (context == (dtls_sha384_ctx*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha384_initial_hash_value, DTLS_SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, DTLS_SHA384_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +void dtls_sha384_update(dtls_sha384_ctx* context, const sha2_byte* data, size_t len) { + dtls_sha512_update((dtls_sha512_ctx*)context, data, len); +} + +void dtls_sha384_final(uint8_t digest[DTLS_SHA384_DIGEST_LENGTH], dtls_sha384_ctx* context) { + sha2_byte *d = digest; + + /* Sanity check: */ + assert(context != (dtls_sha384_ctx*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + dtls_sha512_last((dtls_sha512_ctx*)context); + + /* Save the hash data for output: */ +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 6; j++) { + put64be(d, context->state[j]); + d += 8; + } + } +#else + MEMCPY_BCOPY(d, context->state, DTLS_SHA384_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(*context)); +} + +char *dtls_sha384_end(dtls_sha384_ctx* context, char buffer[DTLS_SHA384_DIGEST_STRING_LENGTH]) { + sha2_byte digest[DTLS_SHA384_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (dtls_sha384_ctx*)0); + + if (buffer != (char*)0) { + dtls_sha384_final(digest, context); + + for (i = 0; i < DTLS_SHA384_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(*context)); + } + MEMSET_BZERO(digest, DTLS_SHA384_DIGEST_LENGTH); + return buffer; +} + +char* dtls_sha384_data(const sha2_byte* data, size_t len, char digest[DTLS_SHA384_DIGEST_STRING_LENGTH]) { + dtls_sha384_ctx context; + + dtls_sha384_init(&context); + dtls_sha384_update(&context, data, len); + return dtls_sha384_end(&context, digest); +} +#endif diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2.h new file mode 100644 index 000000000..f0c132c0a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2.h @@ -0,0 +1,216 @@ +/* + * FILE: sha2.h + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * 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. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 OR CONTRIBUTOR(S) 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. + * + * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ + */ + +#ifndef __SHA2_H__ +#define __SHA2_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Import u_intXX_t size_t type definitions from system headers. You + * may need to change this, or define these things yourself in this + * file. + */ +#include +#include "tinydtls.h" + +#ifdef SHA2_USE_INTTYPES_H + +#include + +#endif /* SHA2_USE_INTTYPES_H */ + + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define DTLS_SHA256_BLOCK_LENGTH 64 +#define DTLS_SHA256_DIGEST_LENGTH 32 +#define DTLS_SHA256_DIGEST_STRING_LENGTH (DTLS_SHA256_DIGEST_LENGTH * 2 + 1) +#define DTLS_SHA384_BLOCK_LENGTH 128 +#define DTLS_SHA384_DIGEST_LENGTH 48 +#define DTLS_SHA384_DIGEST_STRING_LENGTH (DTLS_SHA384_DIGEST_LENGTH * 2 + 1) +#define DTLS_SHA512_BLOCK_LENGTH 128 +#define DTLS_SHA512_DIGEST_LENGTH 64 +#define DTLS_SHA512_DIGEST_STRING_LENGTH (DTLS_SHA512_DIGEST_LENGTH * 2 + 1) + + +/*** SHA-256/384/512 Context Structures *******************************/ +/* NOTE: If your architecture does not define either u_intXX_t types or + * uintXX_t (from inttypes.h), you may need to define things by hand + * for your system: + */ +#if 0 +typedef unsigned char u_int8_t; /* 1-byte (8-bits) */ +typedef unsigned int u_int32_t; /* 4-bytes (32-bits) */ +typedef unsigned long long u_int64_t; /* 8-bytes (64-bits) */ +#endif +/* + * Most BSD systems already define u_intXX_t types, as does Linux. + * Some systems, however, like Compaq's Tru64 Unix instead can use + * uintXX_t types defined by very recent ANSI C standards and included + * in the file: + * + * #include + * + * If you choose to use then please define: + * + * #define SHA2_USE_INTTYPES_H + * + * Or on the command line during compile: + * + * cc -DSHA2_USE_INTTYPES_H ... + */ +#ifdef SHA2_USE_INTTYPES_H + +typedef struct _dtls_sha256_ctx { + uint32_t state[8]; + uint64_t bitcount; + uint8_t buffer[DTLS_SHA256_BLOCK_LENGTH]; +} dtls_sha256_ctx; +typedef struct _dtls_sha512_ctx { + uint64_t state[8]; + uint64_t bitcount[2]; + uint8_t buffer[DTLS_SHA512_BLOCK_LENGTH]; +} dtls_sha512_ctx; + +#else /* SHA2_USE_INTTYPES_H */ + +typedef struct _dtls_sha256_ctx { + u_int32_t state[8]; + u_int64_t bitcount; + u_int8_t buffer[DTLS_SHA256_BLOCK_LENGTH]; +} dtls_sha256_ctx; +typedef struct _dtls_sha512_ctx { + u_int64_t state[8]; + u_int64_t bitcount[2]; + u_int8_t buffer[DTLS_SHA512_BLOCK_LENGTH]; +} dtls_sha512_ctx; + +#endif /* SHA2_USE_INTTYPES_H */ + +typedef dtls_sha512_ctx dtls_sha384_ctx; + + +/*** SHA-256/384/512 Function Prototypes ******************************/ +#ifndef NOPROTO +#ifdef SHA2_USE_INTTYPES_H + +#ifdef WITH_SHA256 +void dtls_sha256_init(dtls_sha256_ctx *); +void dtls_sha256_update(dtls_sha256_ctx*, const uint8_t*, size_t); +void dtls_sha256_final(uint8_t[DTLS_SHA256_DIGEST_LENGTH], dtls_sha256_ctx*); +char* dtls_sha256_end(dtls_sha256_ctx*, char[DTLS_SHA256_DIGEST_STRING_LENGTH]); +char* dtls_sha256_data(const uint8_t*, size_t, char[DTLS_SHA256_DIGEST_STRING_LENGTH]); +#endif + +#ifdef WITH_SHA384 +void dtls_sha384_init(dtls_sha384_ctx*); +void dtls_sha384_update(dtls_sha384_ctx*, const uint8_t*, size_t); +void dtls_sha384_final(uint8_t[DTLS_SHA384_DIGEST_LENGTH], dtls_sha384_ctx*); +char* dtls_sha384_end(dtls_sha384_ctx*, char[DTLS_SHA384_DIGEST_STRING_LENGTH]); +char* dtls_sha384_data(const uint8_t*, size_t, char[DTLS_SHA384_DIGEST_STRING_LENGTH]); +#endif + +#ifdef WITH_SHA512 +void dtls_sha512_init(dtls_sha512_ctx*); +void dtls_sha512_update(dtls_sha512_ctx*, const uint8_t*, size_t); +void dtls_sha512_final(uint8_t[DTLS_SHA512_DIGEST_LENGTH], dtls_sha512_ctx*); +char* dtls_sha512_end(dtls_sha512_ctx*, char[DTLS_SHA512_DIGEST_STRING_LENGTH]); +char* dtls_sha512_data(const uint8_t*, size_t, char[DTLS_SHA512_DIGEST_STRING_LENGTH]); +#endif + +#else /* SHA2_USE_INTTYPES_H */ + +#ifdef WITH_SHA256 +void dtls_sha256_init(dtls_sha256_ctx *); +void dtls_sha256_update(dtls_sha256_ctx*, const u_int8_t*, size_t); +void dtls_sha256_final(u_int8_t[DTLS_SHA256_DIGEST_LENGTH], dtls_sha256_ctx*); +char* dtls_sha256_end(dtls_sha256_ctx*, char[DTLS_SHA256_DIGEST_STRING_LENGTH]); +char* dtls_sha256_data(const u_int8_t*, size_t, char[DTLS_SHA256_DIGEST_STRING_LENGTH]); +#endif + +#ifdef WITH_SHA384 +void dtls_sha384_init(dtls_sha384_ctx*); +void dtls_sha384_update(dtls_sha384_ctx*, const u_int8_t*, size_t); +void dtls_sha384_final(u_int8_t[DTLS_SHA384_DIGEST_LENGTH], dtls_sha384_ctx*); +char* dtls_sha384_end(dtls_sha384_ctx*, char[DTLS_SHA384_DIGEST_STRING_LENGTH]); +char* dtls_sha384_data(const u_int8_t*, size_t, char[DTLS_SHA384_DIGEST_STRING_LENGTH]); +#endif + +#ifdef WITH_SHA512 +void dtls_sha512_init(dtls_sha512_ctx*); +void dtls_sha512_update(dtls_sha512_ctx*, const u_int8_t*, size_t); +void dtls_sha512_final(u_int8_t[DTLS_SHA512_DIGEST_LENGTH], dtls_sha512_ctx*); +char* dtls_sha512_end(dtls_sha512_ctx*, char[DTLS_SHA512_DIGEST_STRING_LENGTH]); +char* dtls_sha512_data(const u_int8_t*, size_t, char[DTLS_SHA512_DIGEST_STRING_LENGTH]); +#endif + +#endif /* SHA2_USE_INTTYPES_H */ + +#else /* NOPROTO */ + +#ifdef WITH_SHA256 +void dtls_sha256_init(); +void dtls_sha256_update(); +void dtls_sha256_final(); +char* dtls_sha256_end(); +char* dtls_sha256_data(); +#endif + +#ifdef WITH_SHA384 +void dtls_sha384_init(); +void dtls_sha384_update(); +void dtls_sha384_final(); +char* dtls_sha384_end(); +char* dtls_sha384_data(); +#endif + +#ifdef WITH_SHA512 +void dtls_sha512_init(); +void dtls_sha512_update(); +void dtls_sha512_final(); +char* dtls_sha512_end(); +char* dtls_sha512_data(); +#endif + +#endif /* NOPROTO */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SHA2_H__ */ + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2prog.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2prog.c new file mode 100644 index 000000000..df8725cb4 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2prog.c @@ -0,0 +1,134 @@ +/* + * FILE: sha2prog.c + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * 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. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 OR CONTRIBUTOR(S) 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. + * + * $Id: sha2prog.c,v 1.1 2001/11/08 00:02:11 adg Exp adg $ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sha2.h" + +void usage(char *prog, char *msg) { + fprintf(stderr, "%s\nUsage:\t%s [options] []\nOptions:\n\t-256\tGenerate SHA-256 hash\n\t-384\tGenerate SHA-284 hash\n\t-512\tGenerate SHA-512 hash\n\t-ALL\tGenerate all three hashes\n\t-q\tQuiet mode - only output hexadecimal hashes, one per line\n\n", msg, prog); + exit(-1); +} + +#define BUFLEN 16384 + +int main(int argc, char **argv) { + int kl, l, fd, ac; + int quiet = 0, hash = 0; + char *av, *file = (char*)0; + FILE *IN = (FILE*)0; + dtls_sha256_ctx ctx256; + dtls_sha384_ctx ctx384; + dtls_sha512_ctx ctx512; + unsigned char buf[BUFLEN]; + + dtls_sha256_init(&ctx256); + dtls_sha384_init(&ctx384); + dtls_sha512_init(&ctx512); + + /* Read data from STDIN by default */ + fd = fileno(stdin); + + ac = 1; + while (ac < argc) { + if (*argv[ac] == '-') { + av = argv[ac] + 1; + if (!strcmp(av, "q")) { + quiet = 1; + } else if (!strcmp(av, "256")) { + hash |= 1; + } else if (!strcmp(av, "384")) { + hash |= 2; + } else if (!strcmp(av, "512")) { + hash |= 4; + } else if (!strcmp(av, "ALL")) { + hash = 7; + } else { + usage(argv[0], "Invalid option."); + } + ac++; + } else { + file = argv[ac++]; + if (ac != argc) { + usage(argv[0], "Too many arguments."); + } + if ((IN = fopen(file, "r")) == NULL) { + perror(argv[0]); + exit(-1); + } + fd = fileno(IN); + } + } + if (hash == 0) + hash = 7; /* Default to ALL */ + + kl = 0; + while ((l = read(fd,buf,BUFLEN)) > 0) { + kl += l; + dtls_sha256_update(&ctx256, (unsigned char*)buf, l); + dtls_sha384_update(&ctx384, (unsigned char*)buf, l); + dtls_sha512_update(&ctx512, (unsigned char*)buf, l); + } + if (file) { + fclose(IN); + } + + if (hash & 1) { + dtls_sha256_end(&ctx256, buf); + if (!quiet) + printf("SHA-256 (%s) = ", file); + printf("%s\n", buf); + } + if (hash & 2) { + dtls_sha384_end(&ctx384, buf); + if (!quiet) + printf("SHA-384 (%s) = ", file); + printf("%s\n", buf); + } + if (hash & 4) { + dtls_sha512_end(&ctx512, buf); + if (!quiet) + printf("SHA-512 (%s) = ", file); + printf("%s\n", buf); + } + + return 1; +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2speed.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2speed.c new file mode 100644 index 000000000..9cf44a56d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2speed.c @@ -0,0 +1,176 @@ +/* + * FILE: sha2speed.c + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * 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. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 OR CONTRIBUTOR(S) 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. + * + * $Id: sha2speed.c,v 1.1 2001/11/08 00:02:23 adg Exp adg $ + */ + +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ + +#include "sha2.h" + +#define BUFSIZE 16384 + +void usage(char *prog) { + fprintf(stderr, "Usage:\t%s [] [] []\n", prog); + exit(-1); +} + +void printspeed(char *caption, unsigned long bytes, double time) { + if (bytes / 1073741824UL > 0) { + printf("%s %.4f sec (%.3f GBps)\n", caption, time, (double)bytes/1073741824UL/time); + } else if (bytes / 1048576 > 0) { + printf("%s %.4f (%.3f MBps)\n", caption, time, (double)bytes/1048576/time); + } else if (bytes / 1024 > 0) { + printf("%s %.4f (%.3f KBps)\n", caption, time, (double)bytes/1024/time); + } else { + printf("%s %.4f (%f Bps)\n", caption, time, (double)bytes/time); + } +} + + +int main(int argc, char **argv) { + dtls_sha256_ctx c256; + dtls_sha384_ctx c384; + dtls_sha512_ctx c512; + char buf[BUFSIZE]; + char md[DTLS_SHA512_DIGEST_STRING_LENGTH]; + int bytes, blocks, rep, i, j; + struct timeval start, end; + double t, ave256, ave384, ave512; + double best256, best384, best512; + + if (argc > 4) { + usage(argv[0]); + } + + /* Default to 1024 16K blocks (16 MB) */ + bytes = 1024 * 1024 * 16; + if (argc > 1) { + blocks = atoi(argv[1]); + } + blocks = bytes / BUFSIZE; + + /* Default to 10 repetitions */ + rep = 10; + if (argc > 2) { + rep = atoi(argv[2]); + } + + /* Set up the input data */ + if (argc > 3) { + memset(buf, atoi(argv[2]), BUFSIZE); + } else { + memset(buf, 0xb7, BUFSIZE); + } + + ave256 = ave384 = ave512 = 0; + best256 = best384 = best512 = 100000; + for (i = 0; i < rep; i++) { + dtls_sha256_init(&c256); + dtls_sha384_init(&c384); + dtls_sha512_init(&c512); + + gettimeofday(&start, (struct timezone*)0); + for (j = 0; j < blocks; j++) { + dtls_sha256_update(&c256, (unsigned char*)buf, BUFSIZE); + } + if (bytes % BUFSIZE) { + dtls_sha256_update(&c256, (unsigned char*)buf, bytes % BUFSIZE); + } + dtls_sha256_end(&c256, md); + gettimeofday(&end, (struct timezone*)0); + t = ((end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec)) / 1000000.0; + ave256 += t; + if (t < best256) { + best256 = t; + } + printf("SHA-256[%d] (%.4f/%.4f/%.4f seconds) = 0x%s\n", i+1, t, ave256/(i+1), best256, md); + + gettimeofday(&start, (struct timezone*)0); + for (j = 0; j < blocks; j++) { + dtls_sha384_update(&c384, (unsigned char*)buf, BUFSIZE); + } + if (bytes % BUFSIZE) { + dtls_sha384_update(&c384, (unsigned char*)buf, bytes % BUFSIZE); + } + dtls_sha384_end(&c384, md); + gettimeofday(&end, (struct timezone*)0); + t = ((end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec)) / 1000000.0; + ave384 += t; + if (t < best384) { + best384 = t; + } + printf("SHA-384[%d] (%.4f/%.4f/%.4f seconds) = 0x%s\n", i+1, t, ave384/(i+1), best384, md); + + gettimeofday(&start, (struct timezone*)0); + for (j = 0; j < blocks; j++) { + dtls_sha512_update(&c512, (unsigned char*)buf, BUFSIZE); + } + if (bytes % BUFSIZE) { + dtls_sha512_update(&c512, (unsigned char*)buf, bytes % BUFSIZE); + } + dtls_sha512_end(&c512, md); + gettimeofday(&end, (struct timezone*)0); + t = ((end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec)) / 1000000.0; + ave512 += t; + if (t < best512) { + best512 = t; + } + printf("SHA-512[%d] (%.4f/%.4f/%.4f seconds) = 0x%s\n", i+1, t, ave512/(i+1), best512, md); + } + ave256 /= rep; + ave384 /= rep; + ave512 /= rep; + printf("\nTEST RESULTS SUMMARY:\nTEST REPETITIONS: %d\n", rep); + if (bytes / 1073741824UL > 0) { + printf("TEST SET SIZE: %.3f GB\n", (double)bytes/1073741824UL); + } else if (bytes / 1048576 > 0) { + printf("TEST SET SIZE: %.3f MB\n", (double)bytes/1048576); + } else if (bytes /1024 > 0) { + printf("TEST SET SIZE: %.3f KB\n", (double)bytes/1024); + } else { + printf("TEST SET SIZE: %d B\n", bytes); + } + printspeed("SHA-256 average:", bytes, ave256); + printspeed("SHA-256 best: ", bytes, best256); + printspeed("SHA-384 average:", bytes, ave384); + printspeed("SHA-384 best: ", bytes, best384); + printspeed("SHA-512 average:", bytes, ave512); + printspeed("SHA-512 best: ", bytes, best512); + + return 1; +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2test.pl b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2test.pl new file mode 100644 index 000000000..dc884d8c1 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/sha2test.pl @@ -0,0 +1,358 @@ +#!/usr/bin/perl +# +# FILE: sha2test.pl +# AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ +# +# Copyright (c) 2001, Aaron D. Gifford +# All rights reserved. +# +# 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. Neither the name of the copyright holder nor the names of contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 OR CONTRIBUTOR(S) 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. +# +# $Id: sha2test.pl,v 1.1 2001/11/08 00:02:37 adg Exp adg $ +# + +sub usage { + my ($err) = shift(@_); + + print <] [ [ ...]] + +Options: + -256 Use SHA-256 hashes during testing + -384 Use SHA-384 hashes during testing + -512 Use SHA-512 hashes during testing + -ALL Use all three hashes during testing + -c256 Specify a command to execute to generate a + SHA-256 hash. Be sure to include a '%' + character which will be replaced by the + test vector data filename containing the + data to be hashed. This command implies + the -256 option. + -c384 Specify a command to execute to generate a + SHA-384 hash. See above. Implies -384. + -c512 Specify a command to execute to generate a + SHA-512 hash. See above. Implies -512. + -cALL Specify a command to execute that will + generate all three hashes at once and output + the data in hexadecimal. See above for + information about the . + This option implies the -ALL option, and + also overrides any other command options if + present. + +By default, this program expects to execute the command ./sha2 within the +current working directory to generate all hashes. If no test vector +information files are specified, this program expects to read a series of +files ending in ".info" within a subdirectory of the current working +directory called "testvectors". + +EOM + exit(-1); +} + +$c256 = $c384 = $c512 = $cALL = ""; +$hashes = 0; +@FILES = (); + +# Read all command-line options and files: +while ($opt = shift(@ARGV)) { + if ($opt =~ s/^\-//) { + if ($opt eq "256") { + $hashes |= 1; + } elsif ($opt eq "384") { + $hashes |= 2; + } elsif ($opt eq "512") { + $hashes |= 4; + } elsif ($opt =~ /^ALL$/i) { + $hashes = 7; + } elsif ($opt =~ /^c256$/i) { + $hashes |= 1; + $opt = $c256 = shift(@ARGV); + $opt =~ s/\s+.*$//; + if (!$c256 || $c256 !~ /\%/ || !-x $opt) { + usage("Missing or invalid command specification for option -c256: $opt\n"); + } + } elsif ($opt =~ /^c384$/i) { + $hashes |= 2; + $opt = $c384 = shift(@ARGV); + $opt =~ s/\s+.*$//; + if (!$c384 || $c384 !~ /\%/ || !-x $opt) { + usage("Missing or invalid command specification for option -c384: $opt\n"); + } + } elsif ($opt =~ /^c512$/i) { + $hashes |= 4; + $opt = $c512 = shift(@ARGV); + $opt =~ s/\s+.*$//; + if (!$c512 || $c512 !~ /\%/ || !-x $opt) { + usage("Missing or invalid command specification for option -c512: $opt\n"); + } + } elsif ($opt =~ /^cALL$/i) { + $hashes = 7; + $opt = $cALL = shift(@ARGV); + $opt =~ s/\s+.*$//; + if (!$cALL || $cALL !~ /\%/ || !-x $opt) { + usage("Missing or invalid command specification for option -cALL: $opt\n"); + } + } else { + usage("Unknown/invalid option '$opt'\n"); + } + } else { + usage("Invalid, nonexistent, or unreadable file '$opt': $!\n") if (!-f $opt); + push(@FILES, $opt); + } +} + +# Set up defaults: +if (!$cALL && !$c256 && !$c384 && !$c512) { + $cALL = "./sha2 -ALL %"; + usage("Required ./sha2 binary executable not found.\n") if (!-x "./sha2"); +} +$hashes = 7 if (!$hashes); + +# Do some sanity checks: +usage("No command was supplied to generate SHA-256 hashes.\n") if ($hashes & 1 == 1 && !$cALL && !$c256); +usage("No command was supplied to generate SHA-384 hashes.\n") if ($hashes & 2 == 2 && !$cALL && !$c384); +usage("No command was supplied to generate SHA-512 hashes.\n") if ($hashes & 4 == 4 && !$cALL && !$c512); + +# Default .info files: +if (scalar(@FILES) < 1) { + opendir(DIR, "testvectors") || usage("Unable to scan directory 'testvectors' for vector information files: $!\n"); + @FILES = grep(/\.info$/, readdir(DIR)); + closedir(DIR); + @FILES = map { s/^/testvectors\//; $_; } @FILES; + @FILES = sort(@FILES); +} + +# Now read in each test vector information file: +foreach $file (@FILES) { + $dir = $file; + if ($file !~ /\//) { + $dir = "./"; + } else { + $dir =~ s/\/[^\/]+$//; + $dir .= "/"; + } + open(FILE, "<" . $file) || + usage("Unable to open test vector information file '$file' for reading: $!\n"); + $vec = { desc => "", file => "", sha256 => "", sha384 => "", sha512 => "" }; + $data = $field = ""; + $line = 0; + while() { + $line++; + s/\s*[\r\n]+$//; + next if ($field && $field ne "DESCRIPTION" && !$_); + if (/^(DESCRIPTION|FILE|SHA256|SHA384|SHA512):$/) { + if ($field eq "DESCRIPTION") { + $vec->{desc} = $data; + } elsif ($field eq "FILE") { + $data = $dir . $data if ($data !~ /^\//); + $vec->{file} = $data; + } elsif ($field eq "SHA256") { + $vec->{sha256} = $data; + } elsif ($field eq "SHA384") { + $vec->{sha384} = $data; + } elsif ($field eq "SHA512") { + $vec->{sha512} = $data; + } + $data = ""; + $field = $1; + } elsif ($field eq "DESCRIPTION") { + s/^ //; + $data .= $_ . "\n"; + } elsif ($field =~ /^SHA\d\d\d$/) { + s/^\s+//; + if (!/^([a-f0-9]{32}|[a-f0-9]{64})$/) { + usage("Invalid SHA-256/384/512 test vector information " . + "file format at line $line of file '$file'\n"); + } + $data .= $_; + } elsif ($field eq "FILE") { + s/^ //; + $data .= $_; + } else { + usage("Invalid SHA-256/384/512 test vector information file " . + "format at line $line of file '$file'\n"); + } + } + if ($field eq "DESCRIPTION") { + $data = $dir . $data if ($data !~ /^\//); + $vec->{desc} = $data; + } elsif ($field eq "FILE") { + $vec->{file} = $data; + } elsif ($field eq "SHA256") { + $vec->{sha256} = $data; + } elsif ($field eq "SHA384") { + $vec->{sha384} = $data; + } elsif ($field eq "SHA512") { + $vec->{sha512} = $data; + } else { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. Missing required fields in file '$file'\n"); + } + + # Sanity check all entries: + if (!$vec->{desc}) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. Missing required DESCRIPTION field in file '$file'\n"); + } + if (!$vec->{file}) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. Missing required FILE field in file '$file'\n"); + } + if (! -f $vec->{file}) { + usage("The test vector data file (field FILE) name " . + "'$vec->{file}' is not a readable file. Check the FILE filed in " . + "file '$file'.\n"); + } + if (!($vec->{sha256} || $vec->{sha384} || $vec->{sha512})) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. There must be at least one SHA256, SHA384, or SHA512 " . + "field specified in file '$file'.\n"); + } + if ($vec->{sha256} !~ /^(|[a-f0-9]{64})$/) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. The SHA256 field is invalid in file '$file'.\n"); + } + if ($vec->{sha384} !~ /^(|[a-f0-9]{96})$/) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. The SHA384 field is invalid in file '$file'.\n"); + } + if ($vec->{sha512} !~ /^(|[a-f0-9]{128})$/) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. The SHA512 field is invalid in file '$file'.\n"); + } + close(FILE); + if ($hashes & (($vec->{sha256} ? 1 : 0) | ($vec->{sha384} ? 2 : 0) | ($vec->{sha512} ? 4 : 0))) { + push(@VECTORS, $vec); + } +} + +usage("There were no test vectors for the specified hash(es) in any of the test vector information files you specified.\n") if (scalar(@VECTORS) < 1); + +$num = $errors = $error256 = $error384 = $error512 = $tests = $test256 = $test384 = $test512 = 0; +foreach $vec (@VECTORS) { + $num++; + print "TEST VECTOR #$num:\n"; + print "\t" . join("\n\t", split(/\n/, $vec->{desc})) . "\n"; + print "VECTOR DATA FILE:\n\t$vec->{file}\n"; + $sha256 = $sha384 = $sha512 = ""; + if ($cALL) { + $prog = $cALL; + $prog =~ s/\%/'$vec->{file}'/g; + @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`)); + ($sha256) = grep(/(^[a-fA-F0-9]{64}$|^[a-fA-F0-9]{64}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{64}$|[^a-fA-F0-9][a-fA-F0-9]{64}[^a-fA-F0-9])/, @SHA); + ($sha384) = grep(/(^[a-fA-F0-9]{96}$|^[a-fA-F0-9]{96}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{96}$|[^a-fA-F0-9][a-fA-F0-9]{96}[^a-fA-F0-9])/, @SHA); + ($sha512) = grep(/(^[a-fA-F0-9]{128}$|^[a-fA-F0-9]{128}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{128}$|[^a-fA-F0-9][a-fA-F0-9]{128}[^a-fA-F0-9])/, @SHA); + } else { + if ($c256) { + $prog = $c256; + $prog =~ s/\%/'$vec->{file}'/g; + @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`)); + ($sha256) = grep(/(^[a-fA-F0-9]{64}$|^[a-fA-F0-9]{64}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{64}$|[^a-fA-F0-9][a-fA-F0-9]{64}[^a-fA-F0-9])/, @SHA); + } + if ($c384) { + $prog = $c384; + $prog =~ s/\%/'$vec->{file}'/g; + @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`)); + ($sha384) = grep(/(^[a-fA-F0-9]{96}$|^[a-fA-F0-9]{96}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{96}$|[^a-fA-F0-9][a-fA-F0-9]{96}[^a-fA-F0-9])/, @SHA); + } + if ($c512) { + $prog = $c512; + $prog =~ s/\%/'$vec->{file}'/g; + @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`)); + ($sha512) = grep(/(^[a-fA-F0-9]{128}$|^[a-fA-F0-9]{128}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{128}$|[^a-fA-F0-9][a-fA-F0-9]{128}[^a-fA-F0-9])/, @SHA); + } + } + usage("Unable to generate any hashes for file '$vec->{file}'!\n") if (!$sha256 && !$sha384 && $sha512); + $sha256 =~ tr/A-F/a-f/; + $sha384 =~ tr/A-F/a-f/; + $sha512 =~ tr/A-F/a-f/; + $sha256 =~ s/^.*([a-f0-9]{64}).*$/$1/; + $sha384 =~ s/^.*([a-f0-9]{96}).*$/$1/; + $sha512 =~ s/^.*([a-f0-9]{128}).*$/$1/; + + if ($sha256 && $hashes & 1 == 1) { + if ($vec->{sha256} eq $sha256) { + print "SHA256 MATCHES:\n\t$sha256\n" + } else { + print "SHA256 DOES NOT MATCH:\n\tEXPECTED:\n\t\t$vec->{sha256}\n" . + "\tGOT:\n\t\t$sha256\n\n"; + $error256++; + } + $test256++; + } + if ($sha384 && $hashes & 2 == 2) { + if ($vec->{sha384} eq $sha384) { + print "SHA384 MATCHES:\n\t" . substr($sha384, 0, 64) . "\n\t" . + substr($sha384, -32) . "\n"; + } else { + print "SHA384 DOES NOT MATCH:\n\tEXPECTED:\n\t\t" . + substr($vec->{sha384}, 0, 64) . "\n\t\t" . + substr($vec->{sha384}, -32) . "\n\tGOT:\n\t\t" . + substr($sha384, 0, 64) . "\n\t\t" . substr($sha384, -32) . "\n\n"; + $error384++; + } + $test384++; + } + if ($sha512 && $hashes & 4 == 4) { + if ($vec->{sha512} eq $sha512) { + print "SHA512 MATCHES:\n\t" . substr($sha512, 0, 64) . "\n\t" . + substr($sha512, -64) . "\n"; + } else { + print "SHA512 DOES NOT MATCH:\n\tEXPECTED:\n\t\t" . + substr($vec->{sha512}, 0, 64) . "\n\t\t" . + substr($vec->{sha512}, -32) . "\n\tGOT:\n\t\t" . + substr($sha512, 0, 64) . "\n\t\t" . substr($sha512, -64) . "\n\n"; + $error512++; + } + $test512++; + } +} + +$errors = $error256 + $error384 + $error512; +$tests = $test256 + $test384 + $test512; +print "\n\n===== RESULTS ($num VECTOR DATA FILES HASHED) =====\n\n"; +print "HASH TYPE\tNO. OF TESTS\tPASSED\tFAILED\n"; +print "---------\t------------\t------\t------\n"; +if ($test256) { + $pass = $test256 - $error256; + print "SHA-256\t\t".substr(" $test256", -12)."\t".substr(" $pass", -6)."\t".substr(" $error256", -6)."\n"; +} +if ($test384) { + $pass = $test384 - $error384; + print "SHA-384\t\t".substr(" $test384", -12)."\t".substr(" $pass", -6)."\t".substr(" $error384", -6)."\n"; +} +if ($test512) { + $pass = $test512 - $error512; + print "SHA-512\t\t".substr(" $test512", -12)."\t".substr(" $pass", -6)."\t".substr(" $error512", -6)."\n"; +} +print "----------------------------------------------\n"; +$pass = $tests - $errors; +print "TOTAL: ".substr(" $tests", -12)."\t".substr(" $pass", -6)."\t".substr(" $errors", -6)."\n\n"; +print "NO ERRORS! ALL TESTS WERE SUCCESSFUL!\n\n" if (!$errors); + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector001.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector001.dat new file mode 100644 index 000000000..f2ba8f84a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector001.dat @@ -0,0 +1 @@ +abc \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector001.info b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector001.info new file mode 100644 index 000000000..57b444edc --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector001.info @@ -0,0 +1,21 @@ +DESCRIPTION: + This test vector is taken from the PDF document that describes + the SHA-256/384/512 algorithms. That document contains sample + output for all three versions (SHA-256, SHA-384, and SHA-512). + + (Total length of test vector data: 3) + +FILE: + vector001.dat + +SHA256: + ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad + +SHA384: + cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed + 8086072ba1e7cc2358baeca134c825a7 + +SHA512: + ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a + 2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector002.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector002.dat new file mode 100644 index 000000000..199f24ed0 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector002.dat @@ -0,0 +1 @@ +abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector002.info b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector002.info new file mode 100644 index 000000000..0fc1ed3ce --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector002.info @@ -0,0 +1,21 @@ +DESCRIPTION: + The PDF document only provided sample output for SHA-256 using + this test data. I have provided SHA-384 and SHA-512 sample + output from my own implementation which may not be correct. + + (Total length of test vector data: 56) + +FILE: + vector002.dat + +SHA256: + 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1 + +SHA384: + 3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6 + b0455a8520bc4e6f5fe95b1fe3c8452b + +SHA512: + 204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c335 + 96fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445 + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector003.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector003.dat new file mode 100644 index 000000000..4674ea42f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector003.dat @@ -0,0 +1 @@ +abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector003.info b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector003.info new file mode 100644 index 000000000..17a2ad859 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector003.info @@ -0,0 +1,22 @@ +DESCRIPTION: + For this test data (from the PDF document), no example output + was provided for SHA-256 (SHA-384 and SHA-512 samples were + provided), so the sample for SHA-256 comes from the output of + my own implementation and so may not be correct. + + (Total length of test vector data: 112) + +FILE: + vector003.dat + +SHA256: + cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1 + +SHA384: + 09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712 + fcc7c71a557e2db966c3e9fa91746039 + +SHA512: + 8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018 + 501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909 + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector004.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector004.dat new file mode 100644 index 000000000..3d71ebac2 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector004.dat @@ -0,0 +1 @@ +Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battlefield of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate--we can not consecrate--we can not hallow--this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us--that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion--that we here highly resolve that these dead shall not have died in vain--that this nation, under God, shall have a new birth of freedom--and that government of the people, by the people, for the people, shall not perish from the earth. -- President Abraham Lincoln, November 19, 1863 \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector004.info b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector004.info new file mode 100644 index 000000000..eed148cf9 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector004.info @@ -0,0 +1,22 @@ +DESCRIPTION: + The output samples for this test vector come exclusively from my + own implementation and so may be completely incorrect. Use with + a very large grain of salt. The input sample comes from...well + most anyone in the U.S. will know and many outside the U.S. too. + + (Total length of test vector data: 1515) + +FILE: + vector004.dat + +SHA256: + 4d25fccf8752ce470a58cd21d90939b7eb25f3fa418dd2da4c38288ea561e600 + +SHA384: + 69cc75b95280bdd9e154e743903e37b1205aa382e92e051b1f48a6db9d0203f8 + a17c1762d46887037275606932d3381e + +SHA512: + 23450737795d2f6a13aa61adcca0df5eef6df8d8db2b42cd2ca8f783734217a7 + 3e9cabc3c9b8a8602f8aeaeb34562b6b1286846060f9809b90286b3555751f09 + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector005.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector005.dat new file mode 100644 index 000000000..e69de29bb diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector005.info b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector005.info new file mode 100644 index 000000000..37602d30a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector005.info @@ -0,0 +1,23 @@ +DESCRIPTION: + The output samples for this test vector come exclusively from my + own implementation and so may be completely incorrect. Use with + a very large grain of salt. The input sample is EMPTY (no bits). + Mr. David A. Ireland's SHA-256 implementation agrees with my own + implementation on the output of this test vector (SHA-256 only). + + (Total length of test vector data: 0) + +FILE: + vector005.dat + +SHA256: + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + +SHA384: + 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da + 274edebfe76f65fbd51ad2f14898b95b + +SHA512: + cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce + 47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector006.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector006.dat new file mode 100644 index 000000000..7caf16133 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector006.dat @@ -0,0 +1 @@ +This is exactly 64 bytes long, not counting the terminating byte \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector006.info b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector006.info new file mode 100644 index 000000000..2a0d78aca --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector006.info @@ -0,0 +1,22 @@ +DESCRIPTION: + The output samples for thi test vector come exclusively from my + own implementation and so may be completely incorrect. Use with + a very large grain of salt. The input sample exactly the same + length as the SHA-256 block length. + + (Total length of test vector data: 64) + +FILE: + vector006.dat + +SHA256: + ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8 + +SHA384: + e28e35e25a1874908bf0958bb088b69f3d742a753c86993e9f4b1c4c21988f95 + 8bd1fe0315b195aca7b061213ac2a9bd + +SHA512: + 70aefeaa0e7ac4f8fe17532d7185a289bee3b428d950c14fa8b713ca09814a38 + 7d245870e007a80ad97c369d193e41701aa07f3221d15f0e65a1ff970cedf030 + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector007.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector007.dat new file mode 100644 index 000000000..1caf01b39 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector007.dat @@ -0,0 +1 @@ +For this sample, this 63-byte string will be used as input data \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector007.info b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector007.info new file mode 100644 index 000000000..fad860d61 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector007.info @@ -0,0 +1,22 @@ +DESCRIPTION: + The output samples for thi test vector come exclusively from my + own implementation and so may be completely incorrect. Use with + a very large grain of salt. The input sample one byte shorter + than the SHA-256 block length. + + (Total length of test vector data: 63) + +FILE: + vector007.dat + +SHA256: + f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342 + +SHA384: + 37b49ef3d08de53e9bd018b0630067bd43d09c427d06b05812f48531bce7d2a6 + 98ee2d1ed1ffed46fd4c3b9f38a8a557 + +SHA512: + b3de4afbc516d2478fe9b518d063bda6c8dd65fc38402dd81d1eb7364e72fb6e + 6663cf6d2771c8f5a6da09601712fb3d2a36c6ffea3e28b0818b05b0a8660766 + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector008.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector008.dat new file mode 100644 index 000000000..baae22678 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector008.dat @@ -0,0 +1 @@ +And this textual data, astonishing as it may appear, is exactly 128 bytes in length, as are both SHA-384 and SHA-512 block sizes \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector008.info b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector008.info new file mode 100644 index 000000000..22cfd811a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector008.info @@ -0,0 +1,22 @@ +DESCRIPTION: + The output samples for thi test vector come exclusively from my + own implementation and so may be completely incorrect. Use with + a very large grain of salt. The input sample exactly the same + length as the SHA-384 and SHA-512 block lengths. + + (Total length of test vector data: 128) + +FILE: + vector008.dat + +SHA256: + 0ab803344830f92089494fb635ad00d76164ad6e57012b237722df0d7ad26896 + +SHA384: + e3e3602f4d90c935321d788f722071a8809f4f09366f2825cd85da97ccd2955e + b6b8245974402aa64789ed45293e94ba + +SHA512: + 97fb4ec472f3cb698b9c3c12a12768483e5b62bcdad934280750b4fa4701e5e0 + 550a80bb0828342c19631ba55a55e1cee5de2fda91fc5d40e7bee1d4e6d415b3 + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector009.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector009.dat new file mode 100644 index 000000000..9c64af44e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector009.dat @@ -0,0 +1 @@ +By hashing data that is one byte less than a multiple of a hash block length (like this 127-byte string), bugs may be revealed. \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector009.info b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector009.info new file mode 100644 index 000000000..d5fe51584 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector009.info @@ -0,0 +1,22 @@ +DESCRIPTION: + The output samples for thi test vector come exclusively from my + own implementation and so may be completely incorrect. Use with + a very large grain of salt. The input sample is one byte shorter + in length than the SHA-384 and SHA-512 block lengths. + + (Total length of test vector data: 127) + +FILE: + vector009.dat + +SHA256: + e4326d0459653d7d3514674d713e74dc3df11ed4d30b4013fd327fdb9e394c26 + +SHA384: + 1ca650f38480fa9dfb5729636bec4a935ebc1cd4c0055ee50cad2aa627e06687 + 1044fd8e6fdb80edf10b85df15ba7aab + +SHA512: + d399507bbf5f2d0da51db1ff1fc51c1c9ff1de0937e00d01693b240e84fcc340 + 0601429f45c297acc6e8fcf1e4e4abe9ff21a54a0d3d88888f298971bd206cd5 + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector010.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector010.dat new file mode 100644 index 0000000000000000000000000000000000000000..f1681bce65cb44b71f4e7d038c0996d18e87e52d GIT binary patch literal 320 zcmV-G0l)qi?_wT_&uOCGc%%j%23hC|&&IOS1gR8BGE?I*zIf8%28ujfJXqz+MOpEb zQTh4+iDHl^gCSGgb3=fr^+xlNDBJ=46-NNfK8tNXdh*|`j7}SQfE#RGQFH7(W%C5N zy;G@9j?B>L;`;+6>zqQQ91wq>SY)RJf=zXl<07DF;=*e-G-&~(V zAA9HoSr!4veH7BtVZC>+&ERmF`FoNw!qV2Z5imje_UHbps@~W?T*emj)?L1O2Xy*D zuL?nSnJ?7(T`id8xt;aAXzAbWJGY-wt6$ZqA_YRJdP?>13Zfs?Ir}l;plRmXLF6X7 zCROD{c_>#$&J4ngIdK@G=r<_T6rfg=8-3YqJ646+>`;?Xm%ix(8ay1ufMq8CGFoYQ S#pjxPhO@Ky;+z{B`1-N&OsFUT literal 0 HcmV?d00001 diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector010.info b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector010.info new file mode 100644 index 000000000..df7717d8d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector010.info @@ -0,0 +1,22 @@ +DESCRIPTION: + The output samples for thi test vector come exclusively from my + own implementation and so may be completely incorrect. Use with + a very large grain of salt. The input sample is exactly 5 times + size of the SHA-256 block length. + + (Total length of test vector data: 320) + +FILE: + vector010.dat + +SHA256: + a7f001d996dd25af402d03b5f61aef950565949c1a6ad5004efa730328d2dbf3 + +SHA384: + b8261ddcd7df7b3969a516b72550de6fbf0e394a4a7bb2bbc60ec603c2ceff64 + 3c5bf62bc6dcbfa5beb54b62d750b969 + +SHA512: + caf970d3638e21053173a638c4b94d6d1ff87bc47b58f8ee928fbe9e245c23ab + f81019e45bf017ecc8610e5e0b95e3b025ccd611a772ca4fb3dfba26f0859725 + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector011.dat b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/sha2/testvectors/vector011.dat new file mode 100644 index 0000000000000000000000000000000000000000..d1609a9b5e72c7125f55e39cb9e2ef20e2ad36e6 GIT binary patch literal 447 zcmV;w0YLsue@9|VqFjU1a#k~Et^q|DOu3BCP(^fUZilk#G%64?%ADnBvx%#MsV0TH zSmOX62J(PkVWRv;MDRi7bHtUCmb;`|W9gOTG-gPXw=;D1lR;yUOxX;NVM%frG1*@O zSY`pHPrRnwsLBN6nz}KK>x$XqQ22CT+auD@z%Thros6t*BM1tHXpMtSv&2Q8zwToz}g{NDaU4#c!bFt zbkoFg0GC666&Y`d8V&*Zhr$_p&eW}mD#FqoWNC2LpuDr#fO7e-^_1wPC6($2CTzIF zJtv@`@gT00307*(0-iCG?jAx1MwTfjc1{2!QQ0u@!k$|2YJTWUL@r1>M%=5ila)r! zsrScSX2*tA50JWhdq51{`LJTfDRoiqN7Yzsj@Hes0$a@eVhhp{C0kwM(8oUPu9t~w zewqF6qq#;B$!t6CGlgh!7|U`dNNXv!{4Mk5-Jnyq`3>r;k7#A;RCp2RzOpYZ=5QMjf=h|Da0YdiOdIVnUhuyZZ1&O^yNLfgM|ncQKk{eZFcs(2MR zd~b`bR8>n>GN*O<$z1KvL;$n*gO$|c^_&lH1>17KL5h?RS+-yBJB~4i3%%gQi+}74 zAFhWxGAijtYCrTj5&X~T>Trh{D((kUy(8aa-Gi_;Q#YQ*_2{OT z-;F?I3tVg^%t3>Rm<=?WFHwA=S73Ks+`t!?Ddd(HFehG+&;n`ctN5kV9otqwmZecI zk{5YIDvIR61)zY%FV2Q*(Q&ZKJOs@6BqC$O!W!FAXt)|{pcpvLk8L_z#s1f{i^2*T_Rk>>I;)!5hSn#v6HVofe? zob>llHbs(kr?j@nZYr-vt@E(3I$3k;=g3tPsnX9?IpNvLvC^y3mF(o;{zu)h-5POg zXstLpgdjVdwpgwLoef_X2%V}E8{DM!@~L5P=Wt*gahfG~*0%sanDrom@|7lm+QT{- zEVJRbi5AAH?$FS7N99g2wbbDoVsjiaPG}n^-Rgv@=%i{yt(V0ef0+z96`&aF^$<`6 z>vNe|v$QsI9`E^#-TW%B7U;=iVgtN-TN_0kIm>zpW4JW)YsQD9rAcCi>_4IzRDy&Mk`CxWHE)j{l4Z10 z{a{sG8owBz)x$GZUy_RLPacsGK*KJYI@=;RZ-pj9f>jdb;U0YFm^TP$B4SC1`PH;( zl|n%e9B6?_lWLH}U*@S-pD-DFz+|MjnReWGv4dF5eAbS3dOL#&$Fd0YlvOOo>TtWT z3&W0%V5NQH{cjP@Wuo0Z-eG_v-XL7Ih>oqS;ee2Y+|6HGo-dQhlrVuAyHUaxLCX|I z`0b4vR_=v(1$-TYrWif@q{FFb2yO zlBq{wZc4J?Z^n`36Sw)EoV$x(IQ3W8sVChu{x3WZQljLyPPrTU5{fC&iwS-jvwSTh z;`#`_+rTspndl8Xt(Ib-pvH7TIXCZ5(N)=Tniy^&?Y~HEGmR*+CO=t7(cX&GE#IUS zeib%Q`{kCw&=RR*>HeNOwn<0Edyd+{rJ#6*Fv`@eS?^;;*dd%<#@vwxKj|*9)|ZjH z;rLDDPg7lUG1MN8_7{Bb$a`D!ATJh#&3SuvP9YC*mbBsMiB5n|2(kMPRKRs#HLU%Hnsy zFQL#U!tfz*@sHt66x`QE@0LA?+5=UF?oD!vfDf%LKb$VBQ>0Z#e3Ba?lbTHM7xw4; zDlSy~64X;fkPP55c6v()-(yk;uyxze&asDxgEQ7Z_Kr)r=OM(|^5kKUE>%JA!L8v% zUqnxcgDtcGMbmM_iu*8X`se7#zT}ZQMr@4YhyJgdspm>~^bJzVhDJGi^4~$U2sm7| zIEcza!A#|9b$6HwILT8MSm8|7lUb6?{8>$bcfA7UfO-T3R~nqT=`p*zlgBC#3T3 zsftd!i0+LW0$RQZ>hW|fYX{hcybCc0kBPN6zcoFW*d&4eX|!3b>p*F*F$>M7&d8%y z)Q!&fRO#IC?*u{})?Zl+*OEMnZB74U08S7S1eAXrg@qD})ih?ZiB)9(K)m=rA4Aw|vd`{wnr{gheapJF9get;n+&ze!lqON>Tj_izA^%u5p_vx>MF zhWz%-pGXc%%glgQC2|h54i+HLl!hdpZ?Qi}iJN$J(LqZ`JiSOgVfK{QXCE`tay=IT z6HFwI@d#+4CD&oos2|z|Dr!UC!cZ8CFYj5GA2BCb^l)!7(#xWy<;sxblOioNH=;OQNk zz}Mb4v4*_mmteR#&nNWTrDTw4ZHu+w?KvGPfFZB4xuFtOcj5Oc$LzccyeB^cO%^uv z1Xv$r41K+wWHGI5?Mh)cQIyV@YhAH|a@JNn>v~E+GZYCsdT~MX>(cS=z?qR;mVt54 zWPXyZ+C}_;H68nrS-9Apq8@~bt8{64g6%>je4viqpVWdNQk1cy;xpZk6wzU$I|`Gp zzX(tSB7z}>Zul6Fh|f*_{10Fw44$S#R(GFiA+wW#`Wyd~>N*?fs+HdCTf2n3WE@SZ zCdy)%vfJ_m#C+GQ((gzDY`{uLD(gulm4*x%$+G9g`^7kG?vBw0mcz`rUI>x!u3VjD zB9wnhaj{Rn5`)5V9_!Ps+WlsSq|^@J!Cbm*W8Iw+>2Cz02ppz^obVx@8tTartvfPQ z`lcWtZ-}Nb_j=aADHvn?Z3su8(AWpQ$L7p`m2R8{DE;a{I-%i82G@Qn8qnp72S-*1 zVtJc@%ue32om!2wI%pzRl4t{kmNkPtt4sujC=F9nneAn~#6wJ- z%)yeUcKGK3P%ApZGtJ=-BhWBpDqQ%6jx`Jl60iR}sRz1#tnP~9t)2P4R3rIsTGM0Ys7$a>R*?j!GOc&}od*}9g6=%2D?^^O zu@tOahY|>dyXxMlMDQ?U7+fi{Mc=${?l#oN)DEYLp3}MI143=$gg>_audQRC<7X@B1%A_LVoDi%;kAA!?~2|)x7 z;nl|u8zOj(tn_V4!kP2dH}4Zm>MA=)M0rZzTv+S%nO3s+Ola8{(5QGUNG!GQkH(co zxVic2&~qU|gDrXNy&FKlC77j#zQ(ju!uNr>)wBo>vA0~O9M%oY4w(k@pq{tI*_S)9 zB1__fhOc9t6f&(~(GQF7e(d`++ao=;{Xaqc;j)xP1iWfKf>+Mgbth$kLlT#)>}|>F z(veFJMHV8tRzaay%Oot7efteR#4_IqF~P47<5`ZK6x4O12WHtRawTb51YRl~>Qmjh z`h&1}t0rJtIxgR3`2SYB|6~2vJBi|vec$P?omg+mGy9M<2doK%sJq`gh3Y08b))`P4DNsq1jMw1v$L|~I zb@~&BWrHUVGtb!cvAbXX(>_qXY>uY`&QUlRRfW(|NI&=x;_ykre6Jz|z4C+eBDsb& zR5U2}9`2EzsSG>W)O^f|%{4plte3Q=z55T{3gayg*RkR<5`!EYSx)JD23*^dNZ-{rR zjY=oof6{c>j|#NnK)x#V^*b&Yzu4A zBkl+w09flPC1exgM9>G2Wht7i)G+-ryrC19s3dn+r^+8krIC%m>DqJlw=Xxghb52G zkv$%I*k9?46)|%j;gJsnd4}1rOb?wFBgjz=?+eFf=IX1M3NOPm=WHSjw|Z3lQh2n1 z>lt#8p}Ko9iizmq{LcZ5y(TbBgDC?UsUr1}QUc8v=6X6Y*3cvaw6MQy{IBY>ug}0+KIag_T?}v8E13vqKf@XYaWnVrb+o*ij@uSvig_Z z$8f}#i3}Xh>O4B{uu-Q6@02P zir+^`jt2a(jr3X2D>Ifs{C1Eh5r$3fb^C~~9lk5JcC;f!*uxRq-@Ku-p{cpUzLXA? z!CO1n1t*TJ@B0CB(JU22cQ2HHB6(QZt_oAS#`_44)!(rgt1hjiTtxN0bO}{03vWmh zcVtEI(f>qlRJa7$f-M31kJ^Weynv){vuOFMyWMOyBM)vyTX=c5>A_+&Zpvw7@B;}y z)C|!rw0!?jw4I^tc%(N{el3~qcLpSF5lh8opUfTp#EYmhMXM`SDnBQ&ms05P(KW?F z4f}51xX4mViI~%I?qkxK-6={0vDGG9P*~eZ)f;e=@hhStM^hyG$g9?|yQEgAaf=^Y z1FyG~^=YM*dDA6;aq0sK5GU9@!5!syEb-*<`NkSG8#-&D{hEd`wEq^QGeb zs~=SFatM_FMnN0Ylf2m!RpJyH&Cu+*?+TJqM#W%5>S}e0G%@AoY3o*eYw zYV&+|*Qt&IUWYDG-t}f$f~vt`x6v9^AeKe& z6@d}a!at|iGN{ykGa07Z!Vow;XNX9eFwAaCjE5C0J?np?^nDxmsRwE2VmGm5l=HOq z6vIAsUutOMu%Njj1Q~#t?#t-{qJxqAlazs?o6LB2c~%~%xVcQ$>#+!ne#!nXxG(+; zT@$}%EF4wJ;3j`TUZ_AVWYBljL(V6jG?1RE9#3&|%2VE=wqdGCtDge@GFkA#;|ew& zM9`Ww`XWo+NLI#QL%UI-WE<)@W{|0K2F7ya=Lz?L3%Iks994d<+TezsbP_`-XW|0_lf$@jY7rLi)_o*Dx|I_-PU^COq-0@K*gCtY+bX=#C`LIf(;-~t2 z?ncif;Q^HSqTM_TIf+}VgodPT^XoIeKJ)AU z=KmaLkill5SnV^cerwnEAUyQ4-1iP25{H`qSP+TftUAtJYTp_~?YPl~qmV~VS@c1@jT{oPCBHuurXc)^>z0cqJ#-$wM%uJ}3R&bLf(v=^ZqAXts6Qx+62rYXPY+T~}gcNQE1NDa#4R2UK3&ao6b- z^xuX|-}UI!Sj3cP%`kuM))~*kZR{%BLuWH{{E0|HL7J>4OxmPtl1||@Q`v z7dPFes}^cT-Y#j0`R>_wF{lrhgG~j{%(8*>uTgF^me9LJdvTClI^&xA{>*@3+x4GX z1!>F6C*M<~A-bz8Icd4Ucb(oXqWXJ>wz{b<-o7ps39R2P zuX}d0yTe64iSChpXz%CTxs@j}7C}nsMQerp+X}Dr4S&2}<`bT_cJUYu)xEI&(Ris8 zs|P@LNCtMA-$HRv)1O2#MWJle;HcxSW$LdHMY~*JfkO2UINL{Y49SwgO06 zX?mK46YE_|)WNc|g)H>U3LAc4+rLVjwY}YckPjPc?R1#UOLyU)Y)gSxs>*&UPRuxu5ZjfzlzM>=>zzeFNO1yiaX z*O@Cufbudq40bT3$k>kgot#%m8jx8;Q!%7wZU8m!FrOaOgu>&_!n|5JpfgzYu zhp0RZA7PW{e}$SkKygZ1>&VP6(hAWsXvUFc3>nexaS0Bz$Flkgfde1Iy}MRz#2D3U zF0yQX9>rzlNc;5yew-na3|ZlaSDNMin1W*MB#z`L#*WE;uGjOls%Af*f9UmlpDjX9^nTT&Slij>~d_B$XPAW*zqNDsq56i%mlO{E0%ZYk-R;$2NpGP!#kGUJDv&)=;Gn5u`l1?H`~ag z7H~X4#kLdC)8bZ5C~~go8#SA?6~|v%V|)t!I5M%8t9pAXdR_yghwEm)!iR`^PElA5#i!B52QM%y-Tb# zCeAnZ2o&G1=6-KMhe%IGH+K%hAfJ^U)#LC8jIgp>78n1Tp4fREN*u%~5a+e@8dA<+ zB?)r~`BvUK7hp}2l_4RG@Fr2r7ir=`hec>&lphayF4G9*;Hjf*V)WdMm|I7cD{YsCkygeG)q5-w3u zPd6VApm4dR6jN;iOL3ln&mva4tlnSqpLa{aQOhvI*}4Z$IRCg)=k?khih91EAaSsk@bBmc zHBU&L6lw#h(SR@)H;5+ueZ5(^;SO&*c;9amewb~AE8EZU6RVW7EX3_x3d>QO<-l`q zKsQU7K&Rp5aAI&g0tT`&7FD$S1X|m>WK9o|Z}D`nFHME8dWA$WG;p! zQcUx*$il_m(8RqcX$Z#^Gc5?2B9PTKSa=nj)4q&hC>$d@)~~^O_|9pE;tA?;CYSFq zy(Z%KK2!Nkb#26CcG%9R4JnB3`dhur6~QH$tJA*I1}6Uf^)N^iX!W-LW%CyPgaG7-)YkcGZ*X+}p0x0k6T*^i996gzwpjZd0vW1HuZV zI+UIC_ld({T6Q-5QlkbG8YL*26}moBo{zdh!&j@!nuoQsq@RX1C>*2q7#O5ae0oqI zR9sH-Kr{HAv^_E7F3tfV87q=TVRlq!ZV5f5`U(|?Y>?XjKv+_c=IkGr|qNl%xR z`IJ^zzD|ua=v#Y77ISx{B&rE=yDb^NA&w~JSGzl!PV0sSntu?sBxsoqC?={#G8lQ= zM=gjf!bQcc527dXx4b|DM;O9f9eggx`Lgl}S|ud37@$Spdch;7qpG8E(M0jL7M;Yu z4nl^IUB=TL7`vJ-e#+N}zbLN^Pa?%?jS75ss7?tGePHJYjcp`)h9=oUlaUF~Jkb7? zIy98M9FX`@dd;Bh&LYMZJP>z&JOf0T7k(=NT9j)HM2J8;BepGnw#(3vKYMltAhuq>0 z_UR^7_ga)hJPGvEip6zA^q{-`pCa5-o*_E-RQNJhzp0-%eNhuZUc8Ch_RyG+`;0FH z19$;~`+xLntpcpQ<+YO~e*Q#%4-d?oSBPep!x20vw2YQ#JV$Q(26s)N*>#Na7k1&N zRY4(NTP3ia2UaRUjw6jsEZK7} zZ2eh^*og7cCjVO8GsI;>A7e&0Sm?`afY@&-DIDJfES@3r9tlb)gXeQ>HkWYcOJ4z{ z!v1YU0o+|5UKK7D`Zi3TjmNIB8{IK{jS1YV&jVRjgWG8EYYF0|P3k8Xr=2{svC(BP z+5UKXtR~;+a`5rIQ$8m20F3Dd4(Sa%qt^8sM5-Qil-71vW8uqTo0RmN8?vTn*(6PH z?|TqjQjU4%+e^mE8cd9wP$o(!OZJb3P{n4F>GFCc_4MG@hz&OP#|~4u#Y9bhS7I#r z+x!}L^y7$eC@}AKPZ#C2-V!zhy2bBwk+@p%np02&Z;_FqD5ta?mQ+o+WAU|n<7E<| zG$)VEX8C75UO7~&I2GoIYsOk?L;1_$U}8JdpSa~ppT{j0zW-He`Xe!xdd+j*;y| zHi79YE=$4q*&pf1L~ros*w|@%sYFFU#uiFoZ%wJ1o#UzF!mC+7=d8Nc;O=j4BfvWL zg;w!26^7M}{ECTa+x4g78f_-O%3&0uiYOKtSGKkmWEsK00Dy*m5W4IvZ+~aFx~g{H zPJp?ozcubuMYEGaB(6|BRzDA+dkc%YlH2y zk;LQyMB-o~;YQ1mZ17*wCgvEB%Ldkr>O@DcuJ&U$uDmJ{nMjaHME<_%l|LRyZ}&EN zLVDy_F|fKN!^eOPO6YX+(d(lCSRR|r`ujT-ouEagSdNv*B6lpM--jT?fF25vD*8@Lt?;}tDc1z8_2O@mR0en0 z$SvmWn1Gk=sTS-FzlR7PN}f?nnd)0pOg#qwgSw{y%`*Z**E_)vz0eL+yf0h=w6^5m zKNxW-g8qTk_;)djNJhYBTHhiM0`m`zve`PsP=KA|f>oV3o4&ySo?x%x_<5<_2g_;$|MVQQV{`7aIDrp1I`ttpaP9KV`f1!dl%EYk^*#f#q9 zjI$;r9a2ZtK67?2_QgBw+X7Rfe<1Ved#-=ysrK@$JJ2&y+Qq0(@&N!Ftxq4DjV~Vq z>*L7ff=gn4z}K*x5$-%;EijoZfux><3zmuk5ItPC)!Rl0xg78vn;RH_4=0W;!r9H^ z#4U>YvSbtj!S9Jj%$ua<<)FU2+1TaR*04;gdU1 zJBI(V;*PMOWNSdV@^@RGH;y$0HxEuq*^(wXecwyccA6C`(4Sa5 zP*4WTg;GgMBCl)gU|O5N6d!xQu?Yb$ov^frvOB4S*qN`G|I#6T;ey{SRU1lZ?CAQk zQ}}TH;f3F{FxEw`KGBL0bzU(scO%am;q`F;`q(VC^!6xlSuAOu{NhxX&2dD4OjpFk z6M#wlhn7vye#$UYMrtY=Bdy?%#_vIG^5m?qJGkEl_IUEm+i}bHjjnGBnI$P0*&8(S zQZfPVbBwX!#8%t&;M5jU+Z;5$P7VA2ubAX#4=i4dviI9YCh( zu=)jw(;ojSooZOIg5X1)Mys?4d3Khl;_B!8^}lQWQj?gV9Zr{#8jsZJ^jS$)PR*{C zqb{pSER!#@!Hm6`4ArJ@d@^r;&@#qgj{z}C3{2_`iblegn=@~SWmz|T*PBxt=_&zX z;UX&V{HLvJbd7XLghJU&&G@4#xnD&nD}#=3qyO>8S}|x%aFnu^3Wm@zQI9;Gbreyy zjOTzATJgNqvIXq$Tn@@Lcl*UIKmF^|zdrrz)4x9b>(jqJ{p-`eKK<*{zdrrz)4x9b z>(jqJ{p-`eKK<*{zdrrz)4x9b>(jqJ{p-`eKK<)+|M353|8U@$y3$4x<1W)E3ueuy zBP&+G+bj!7J=Atbcs1n%hu481INPE*5OL}V$34MBHG>TE@P{dQry=j3P7YteOgUd5 z4MJ9Qgs`O)TD8|ghAeS&A}ONRqhQGnkhPazfiysY-Q#k_j=Q+Y<4c%mb2MH{w9gcb zPQ2Uc4f6>@lk2YRj+pn-i{-KRj6R;NVS?ptgr9CH(=8AKzwY6` zyDJ2}NPel%=6MBjx1%2!CIp76r1aEyBIJAG(p{mAiKR=?B=n*RZl`=EOPfD(pvE0V zyYar=)j7bZmti#^2Y~V{b(A;bJhTaiP)Pal4;MDd2=%AlFK33v$-C##JlX!SZ8ept z>7Ow<=PN7rLSey5R%j`P(63CIYcp)84Qg3?pYA1zjaI{Tg6?d@P%RIqmN+eE=y?HC zt#10e*i<%nLt6pSvcyL;v$XjG;R&jELf79aQQ>|6Pk6d0&GDcROrhcaW+^in-7Foy zHpe%3pBJO?`5^I0nXGYUoe_8GvsvgFf*UhnNKhYs7*_YVZJMcPyPB|7Mj^c9Gc(QS zjkW*}(ll=yg^rq?<&jlWEdRRanrl7bjrqmEER(0XNvO#j-8na6$k703E zuQ`tkNgKQt9$X66&9pq#(|iUGP^u7u-nC8HUw3Q|u>2eP7uOIqGaC#6&q&sz#N4tJ zhQpU+c;r3UT&m~|rUM7P+8FZ=GXM_*Nadyt!B` zvr`#@`g?hfA<7RKddEmF!f`?(-Or&oYu;{z(iL!qX^IGA27>V@OaVd1$%*!i`#7)J z2v8ApFM#*~mT89o^pIow5>+E#S7at2?i{S?Ra?SdtklxmRm95AnP{ES{P@k?9gn}O{?%2Yph;9V1nD42;);O8U#7}IbRV9!QT z8=^S2BPICmc{pWSmU-pA5pE9hRxEysajscb6+JG66oOwuDbGRK(M9wWqsm{btUhf|+4muts~ zV8MkkXNuwJBSJ>hh{3BjOkWY(80^*`TGUUZ1K^Hiq7;=0pLX-YxH*?W`$Bm~p^78A zcKO-S%_w!z2?RE)8Oyb}L8yEB;u1XFRkbDeKS;5*L5qhEv;E<`0vBi-;vUo_#!nxq zVq1o|5v;FK^KE!&HO1ml6p^{y* zuFQeM!!b{@ewxVzXyO#DgnGs}6jo(l}h zn4m!5U5v@CHfF1=gl*HOp#Km}d z^_8Q$3u@O~L<3ZqFNjP2FG?Rr9OMrv`&FR78yGneuHDVLN2C{vsB0wH^l;WAyY*_= z*?Ixg(4my>M8n8?`_&S7Qx78KioUCJ;s61G z61$RAJ&BWe4ENqWg-3=g0?6$Uh1o4nMwhYFZX1J2 zMiz-gxLwQK7mhi`4oh4wJeR_G|Me!h!b+Lb)Mj4dc# zOXG9^PGBR|&yk{4htnqByiSce4H=i`uGFSG0neCBvJ6ZBZE)5+0eF&$Ot@$W2lYb~ z58C{`uA=#`agzKapGYJOxcW%BbJ|0{ldH&@pbW3D=BsX%O=m^F`a$BEiU*}b0q*^D z$v`w*>;3nP38p;oQmTfZ63bo;4MC-tNK4yFI@rDg81rBR@mG-h{>|%9cX9BFJx`WO zkUZnrh`uAjm*U2+)+V&aenrB360XgPAifk`4Xdc0=!cpK~*lxHA-m1G>>uH%6yTsG30`9ufzHlIA!~$ zVKgyZAC7?D0@sKr{Yy zm=RdO9#bHZNhf7=WZWqR!Jbxpmx!E$dF|l3A>J>!@Q8X3+nb>!!v>isW z;VHl@fBb?ZgvYMp!g9^uEP|?yOK`>dCt#zLCCvl|_r)`I!L^%4eMu=my!IdHc*=Fe zIy=5%n_>6BFZ;(P!TOwnusF#rg7R)Y>5V30Sez!4*W~qcM(i|o==+ePHrSaPA&+FMh+Q2Na9@RxNb(zo>qdV zsG`>d5Jsn(b`Zfw&IA4C^pPTcfxK}`QqG*%;==w8gmEwm$5=|}K}Jq(F1!|@(C*6oYvSyx%OYOj-C zPDA`oQEQFw6yR_PGJ9h7ZGbOCZMrSS5{7?$HWJ%}R@c*~LSdIzK?h-UgTrg_Lz*?Q zRbzK(>i6X!3Bjabn0N@=*`G5Tr<9K?So$2Bl~PUXwZv4Pyg9$d`eY`P-7apn&Y{tE zHesQTT)ryt5O>|iJTYeYYbL&Biskue6KEdd3Gi4zQTfiTxA>pPaD9)guJxrE8)Sc` zNqG)k;VnPw9+xX`k@+1-^1TsbI-w8gm$d`38G~73{Aj=3mjB4Kmh&Vh?Llzh|AIp~ zBU2-~2qtYIsmFw+FhqjJLrZ(vKA!~fqS*U z8n*2GDEZwTO7}MJH3^)VOKYZ7zgdk}kB%}C3Fy%zpS~c+xc%h=^&9dkC6B~#`fJ6y z#ZwVg;Y4QYEjJF#^)HmJEqSpbm7`6&G7&5-eDUZ(MEaK{KK&4EH6J)CPR!YRMT(x= zE$fzG{KJlUw067sa8e(yPcR#VPgAd+ABY)c6SqM@qu8OJn=lzrrqoIoCuzoand1EE zHmiqLG@!djSpA6m)he5DTC~9di3=F8b>Aot!6f+i(0@$@APG!)2Gw=k01-`F#t&Ri z8*~7WR4AYoO_>cH8CxPcWN));MJY%{I+maSrTtLAa#2yndGXxGi|OQ~Lf!sJ)-sa0QT+lnB$E&D(6bUlOobF)~i`` zXeL)H(d1NJ)*Ij75YR==OQROKXst39SC*|*TEzF>+k?$~?>6jkC z_J@67RbU3DMlikcH+c46Ugp$`vvoH`WM|(_0R9j5g^X9)?OlO0jy@#Cw;LoC0{Nh| zZrA$LKH4Ea*f2F+yp1=h>$u%{_W?ex9b>~FTw~SCJJ6nbs=&E}@bBQPd>B?|(KF!4 zH6M3UgFABIo=B_O8A?>d3Jpj5{U@h+K>pzoF~Zts;!(O~j4VYfb@2s`J6TdjXPQA| z!s*@u=fD#gg6)81KRU|GXAk$?0sL$|R=O(ndfr#|^D={@_fx|6W z$(<$a95R-K6Un1v@Y)aB9Z5x>(K(p?YtCluk&{JRFltCmo!-%~sC5*WP$P40Y`6_R z@}@jpbfQWIHjiOv`l_^-iH1lq`&`LPfIPbG^~fyeZ)im13yYbN+@1|CxBG5E6zFNiR!+|ye zhX?Z6z5HVQrCt({`>G4-QDKd9F~O+t9B$X&?+xO16x2}C(X!5V5#a|6j1uLJSdn3<~_#a})(lJ2e6G!l$TIYSwYtVJE%M24VdsU71d0mKceCj(-9DFk` z#3Roh3QX;F9AhWwa5^08kE!Aa25NePRkqV|G6tdcDsUAwy#uS-X41mf4Bx_>iKV5G z4<8g|)#uj-?s)zf=@d<;7x;mG%S2VzBNue7ycs>rI8iYUIS3XfffPS$D2)<8hLgTg z*c2)JE1jw6w&%6)Ip_Uy@DrJFDB0anX77>hgHS(PWN28B1p#@y=`O1x6{wU3ye)X- z2URs~M8;dl7n&q{0(=VyeuTtlvv7&X86D5nOGmjjne*oH8R z_PSIL*CXU3YMyomjW*{)Qjrh|Us=Mbt%Guf3ZoDKU1bn8i1k?Vl+O7g1>t2_a&}?T z&?9_(r|tr=krT4-c*7(Bxqb6ZOYLw`&eo|xObQbnE{~ekew>F8usQ!I{Uj;3p&bS7 z3Uxl&OXwPy^Dea^zEAc&?0rq0w@t;ha_?*t4RHV$=0ETc5XZC5U>;+YwSMFcYA<##N z^b7Jydb!~79h0`$EC}P2{!KvZQ8z-^N7qymoQO7>cv+rTUd|9Z$V5JY8B98=&{Lbb|3h;|8^~F> zP>)l|=<*>)z%qh~cEAdc4MaKKm(-Y-7!2Mt)Hm!U$3X9}G7$IkLwS6;I)_O|%!4Ll zSibvl%h{!%5t7B&)3t~N#(((<`E|oI{S17`kfJTKaBMSI3DnL=qAlo|=d+TaOP=g> zmY(GTyJTTK`K_608qL8Yp^t1ty;a?$32#MI4l>E5(5|P969~x-wqkbBFF5qk$6*zO zw(}{!V{Q|1pxhR5i@yDz#>cFEDI-l;TR|!!qd%ruGtU^7J}U>`2p&+B+)gv272hB~ z0&bXHu)=^-0w%0A_QcFJ@Y59e@@0A~9e!D~{Y~sq|OQ1-Iim15Sm$uzUC##w(fs!%$j_B45qZ>64 z{r~expFGhj<%$G+K;pz`jbD=w^2G^&t>BGO{K8@R!c{_Ikra$~o{{t4bhtN101-a`UB5)SX~@~# z308mR+YWEycS%1|;A1!@R>8Yh()(90x}54GWyAq)8h};xkHpso4HsGNdXW{;QqU+Q z%Yamc96qUm0;}*HD@78!3hKfb0UHK~$o!^?5xKx8{_(l7!g4%IbO4)jRCh zSMyW^526J77%8(2qVOPE*R&OBIqfF{*rC_0+{A@6xY{_!d_BUHW_6+oX2N4VcX_9< zX3w)eaf|FtP;r3>OS;d<_mNy)2mWYo!OW~UMN{ajBb@1!C)MJ2M`VAK9#2~q;kR|^ zw%u2Esspg^SDBl7HG~gcTJqJRR#i21q>+q;Nda#E-^F){$tZas!4#YJnW|LtoGF#_ ze#>YgT=l4>_7)+neC9OA(uxoZWLFd%KX8#Wo4 z$S}Bqqr5;ktnW~R7x|Jj+*DSTz*{Tue3_}3&%!a7^6DCur(4cbN*>l?7-^REz3hs8 zNVaaoP#0Vu*^al&dD3DbE--a@PfOcpwQ*c>Ugz+qo?dJ2b;u4+SH>IBnSS!fu4h60 zvm9k;j>6mRs>_r~DF8U1$w%%X4GQw7h~;lKO|Uco&6;UkT|`O<58hEZ--+0$(8kH$ z(7c9NqVO-BsXQvz10M1P=Fm5N(D3W<= z;)0Opsy4p13tzhRqFA*G0MX$9pDr%YomQj8=o~Q0p24z7_i_IN(7O3^60d#|fnO6K zjzaM(n3eH?vLQ@R6iTrN-G+0>QXo^=qOjxxUPwxUkuZNO|NEl0|Jd(CDdkuY=36MS~JM z@3ds7b1+CN;3Bpto0>Z<;HYJ=kq;(7lJWA_bp;Y-x_1pNr&d{rco4A^tL#FHm8U!> zwqs~WRazj*U^6cosy#?jlcC!Sv5g>IdSd7h2_-kbh@S`D`Y5PcTiA656}?!gUo^E5 z!PRa%H&;tQeS`l6A_wCgFN=4IW9^Z7tLY*N9@iY-t&1Dv;$|dY=_F+gD@Z9@)S>1$ zj(4#+Vber^t6*MO>v=rR;9)Mxg_G8?+yD%*q4Mc3X_{%uZmmig4ykeaBCf~-5ckcM zi=;T28KPpIRZRU(TSq0~9eN-!w<5AEBB^#K?>z|hN+Td- z#e)JH(En*GM~)0+2`!euP)Y4_@?)9ep`q97#rRK)ds3!LQV@2To`e3Vu$5>4-d1wa zxeT*gt&2x7`0LwZYX?MAZEBX=U|DyJs17bj{EqSQnMtu9VxDIwjNZ=cz<1 zeL*1RrWP+@en{5x7N-<$zo|-YJthWsOWJ2Mgsffx?SJT#l^69BV9W(}a~b6`!Z4u# zR;YNQgW%N%j57&&v+)f`2m)Ma&tcy~d&G7=^cX)%z_;u~m%&RU^;DgxMyv5otxmUn zu$I6pTQ+J>PN|s>VTM!qN1q%$^t$FcW!H%lCP0wZ*H8g6hirk>6&vJsp*U~p*Ni61 zMhyk5g>7u4N{iL3A zhk1*l#f_Dmwo|+77lsCE5-W}FGFEFG_z_k0wex8_ZS~(Wf^^R~$crT45h_a~R@f1U zE`6jXj`|!#?S+9_dSQ+H)?GE8=vjaHgvuS-qAz05tOxfy0TY1lm;y=@W7iKkG)34P zpH~(mAvFHPWMP#NXpBv2pv_r1&!bE;dt7X=p+(F=oa1D^7-E8a!x)V$q}rB6sPBGw zlgg_OCK$fQU5g0%Z*91T&^rW_QZC5=ON4t*Og*xf1QmAyWGkvO~>tZXro-k1H z!V&2(X(mRo;?#_24t5k_9*GfB2E6w1A0e&1QT?tI50^xFzKSZLU$+TvE*{TKr{SQj zotB@xxJ-EoN+=##z+%&X?fxK5wJE#gNQyDc8rs=!5^VBXh^sRATM%En93E^%Jhz`^NQ zQ6!t<26c0>Hn~ogm?k4ZDMyI(4b;RuMI#gj ztMa*Vf1nLAJ<^2AVospi5W&O&s@_YUI3A}Su=z_{>jlkgrQ4q4ts|}vaZc%h5Uzu} zjn7%d?EvGQ`7in9G{;feqwl>?5^G?Cx=IDg_=tstSl>%U-!9|XUfsWvq!4UJ04kUg zmH3uWLz@~rB%r~3e+|N4JEl3BgZL~c37K#S!w4K%0kWw@PQ!t6WJ2%bP_jacSbHVh zbW#L<>vV{(eWVC~Rv zfy%~&QdoDdH@UIVto#l+n2$*z@vy*^IsLet9ZGAS6fq-biJKO|RLGJ6#GyJ}Fob?0 zG(NX&JZ}nFxpw%@ryDgewoLI06od@fB}X<@%e8m^^e=5No_LB_?t&+lon6LMskmRh zJ#3d^v(C7FgD`$~U+k#H zVV57vV>z_d9MNmBbpNPB7i&fKq3w22U_w4chgZMo?%uRg7-=UoJCo(Fl8*DL`Z%DQ zCKv67S}e@rgN({@YktLp=8fSuD5EXKVi|6Rf*bg!(=+j+2G1$xqO`Iz+Kg{%Yx zO4k{7p4Ob6G+xB14sdwt=_pC>q8wnGv{ijN0f9eESy{sPFJG2pzFG~;%Z0bKtpKD@ z9R=*tT4@Yi>P)CarD{FZ%F{TAE=E=P%M7o04O7S~S+xDL9tjT#Rkuz1B8t%MUI}%L zPs@iI*fx^oidzul5Dk_t7p6CDUW90X4>)aZLF4<7uY#(FxIJt`nSCayi@n#PV-63& zlXya+u&@#GlMI4GjxEYZYd4Anw6U!~ZiM2|lk$@$YSqabh1v}n=a5`=y(hgXUq~$! z`P)=yU^hAQD$N;`qT{eAzP&=FO`aMH#@I9^AYwThJ&l5$#k`U4iK>Jwjx7%}`Ur(Ls`XLpFRch2n0mg?n($X`xQdPY*vE5agfD}mJW9G?S z2jAsgNxGy9Y@3SJt$hretYH#>JSv4de;rb|!ez zX~wPI9~Mms$y{I|GZensc_<-3?z;c`o(SL-E?MW7AeDAMtHeolAgY&Czg90fe^7aC z3V3L#fJncup{GZ|JiP(vflFSZ_VxF*OeXKkcW5|);h-yG>FN=SkyuR57EZR8niV>b z3o%AlST!Qgo?B6X{Cwi&X7h0POufcp41M~hk~B7*W_|R&vKNg}a^BHyTeDQbr^LGR zf`C?z{ZKTJgljG8=_09{IX3L96}}sBac?piGwltwZDT}hvw8bCVbCc*rx{W^pJF~Ocb8>!bAviY5Vorc_CxjyjpaVW6h*>g(2hITqNe7H(Yll_fSJ%OgTEmTAiO3_Y|sI z;ZD$IZ?r?q*eYufhT=4SGk4#Auo*=Qx8x$P`OOO28{0vPkA+ugufljXrLDBsB$HRw zt)1ayf&&wK(H>Ro`j>c#9MAI0l4}7s7`6~SNoW%G1@v2o_-+Epjaasa?=BGx{R7yK zZraC(kl4i9K-bVl%Ph^ro6wCYDMPOqalj>S#Qpy>*T=eNpMF8#RuU#5KJ(?;#B&1e zx3UH)b1RrPD41#hUnFP#qp9BcyaXHi_yN_ubl0jZiLq7u-0n05hMooG!)@ee7sFuF z$9vAeeWQKxdMF(P*>eH5VKuww)WOY|FS7qebzd1h+vojQi+f52qi70!+YB>3LhmIP zu=B6qrLHC#4nJ4wCsabR(2cls^~3Se&?OHN6f`QuC)uUUh|A`d3qF7|lEdX=QJ&XF zV#ydX?k7b9TyM#PNN!NkIyYxUb?A5qtX^yW{6a-u3|*1?h1UM!M#p83Hnm`I?Z~!b zu`X&}jMZF;7@_DS|9T*VP#$KM=FBA>f`*N6PD9cEaywoB5xIydTX9ZW>u%mWjYZRR z68Vvoe;x$QV%E*n5-ZaqFFzsC#Fz?^14x@!#`LEG_D2E}&kA;T;0 zUdE_sKb-&mWD3wFrZ#3_p>%)ZPjEI>HmpHcaBWA=Gw(NZj5l%cK|vPiczjA3@X7o@ zIy07V;Md4dMGqf&{#WdZj$M1upOU#34+Aj(%q~C&Vb*s+u0WFWP_k@J30T>fwpD0W z=OS+QC7<^4&Nulm4RLb3vIMXKwj5Ewbt+jbf5L)i;E@b67_P}RA7pb55dMFV zd=-qARc<~4&BXo3b22qk!$F4J@K6yCwS^wVgPvCZv*MNrQPc|`nF;0$I~-vDUFO?P zH|<{Rb9}M(8wd8z>W$YtVd7i+>p}=8UT7w~PXY^u@M&^n<|JAHEK$%G-ltPQimp3$ z@kE_Zti%iZ#}l`9V@V>|#i+^bGNQ?VB7$tpaEHMKC8h;lGQwIW6@vZ%1!js<#WD z#QYnvmpAuCI$l43k7l`XCPXM-avhT5WdS}9xk|5nM#?YV0wyFqg=D=H%XfwGysl9$ z%;OO;2FA35M|7IFQIX|)NYEJLx39-nQ@|*SzvcuMz>BHJQC&-z(&bSj zb~m5C2)LoYXK5F@DL+N%CQ1J1)Tgc{1o^+#-Vpj!NSYH+Qne7e9w&51XSpzq0xopd z)g%4d9K5mn%&brqMr37~8Ff=PoyUI!fv=K--3MB;D_4$46hA}Y?3DI0_*=^n(H}`~ z=E!qrcn0fL4n_$&o|uBN*v6B@T8Z{j<-%mQ;jJdfcA7Bmp&Uf8VovG-=4`aSGDm`q z(RtvvJVb6D@|EXlFBe$QGn{~y>uQ(L*G!NKloOX_jdvZ%yo~6sA{Y)5d?$b3=)&@bL$1 zak9^0eobEOd{b!j5y%256*;fz04}+7azY_uG$_uc+MNbj>Sab|xUO5uc3t$0m!o!< z(Ju=`axA8%Rdh@*5>tr%xX)y9eZM>O9WQ~j()UZGCs*j1gpWYk1C0q5;F1%WVRs7O zHbvA^bX5pPO;qc2tJDoJV@?WZ+Z27grjS(#2w&(vq`Z1fE1`5l=7e1SkAJ<>W*ZJMuK=7aYJWy6V;nRKCp-DwlnhOO8GE*Kt4KB_-wY` z@UG=mac}Ai*p&py<};cP-M-NLSB zW|-S)KdEF>Ek0IY{;mZr^0hy~^Av~FfXW43jI_k^O`lwiNWkEA|2EeB<=ZRQkZPHP ze<4}_>t9`W6CrA0z{c(ght7Y71XYCUF|WbF8e2x0e4m+T|MuS!7)f*45Mkn%Fku}v zx1t~DQQ@j=Jn;p%ke?usmj9xzNEV1#cxvyc%njazul;NR-WP2f2y@e!67(sk^UPN} z;@^~8N`wR#k>Z;{;0Qv$Ah6mgBd)?WqU_(5xHr+77G?Hf>iT(m+!ejN9sqkjuvTZ( z1S$%q7U?_AAPs3Za$lKUS`*keD3leVj>bm`IGBq;^O z=vXbPHMW6vmzJ=^Fng@i92Re{%^F%l11usZRVVE}e;etw(rYVe0^2PzR@w%0@O2}; zkA47?sw27pN~b@{!YF@~l&k)hhb+k52G3FVM0B;(^R{Q6*&?1K$=>da2W}yo86YyC zO!|IP%Fs#=MF8VCw@cQMZFRLaQ>4RM6Xo_T1t`r?BTS|39q;^N@Zg%LD{(oP=I_rs zlarOEc#G40w4u+}?sdfrWx{P$q6q!Xc{gTYCN`S7$uD6+yEVUW){jTU1P#$?&p*F$ zN4-D6^rj&j+`QGM>^JDAY^N7PH(v-mY}utd7-g+sBJCj;lS49a{|FZAKmL=frmOGX z3ildz(Z90lBwtHMOl@A^u#r%(nrEEaW-x{f+jZ*YZ3SFE#11LxZFMlZ;*Xn?A?!oD zQ{a`l5F5wqkh0PKw=O+=JZEL9+?Hj&CIC@K?3DsQc9{Bxv%+#jbVNcca)76<=M7oI zqrQU5zSI$`X%y?@ngY)4A^apF{8NFWW^?QZ|J-Q9Fvn zJJBv*1*Spr*dr9H+ybY3MVD%Ia<9h3=1cxJhl%{cS}P)8(PLAphG$h{Y5m`>l}RKA z`RdHzHp>^jR1|=(KcWv21!B95$`S7~56|MH7zV5o@p +#include +#include + +#include "dtls_debug.h" +#include "numeric.h" +#include "crypto.h" + +#include "cbc_aes128-testdata.c" + +void +dump(unsigned char *buf, size_t len) { + size_t i = 0; + while (i < len) { + printf("%02x ", buf[i++]); + if (i % 4 == 0) + printf(" "); + if (i % 16 == 0) + printf("\n\t"); + } + printf("\n"); +} + +int main(int argc, char **argv) { + int len, n; + + for (n = 0; n < sizeof(data)/sizeof(struct test_vector); ++n) { + dtls_cipher_context_t *cipher; + + cipher = dtls_new_cipher(&ciphers[AES128], + data[n].key, + sizeof(data[n].key)); + + if (!cipher) { + fprintf(stderr, "cannot set key\n"); + exit(-1); + } + + dtls_init_cipher(cipher, data[n].nonce, sizeof(data[n].nonce)); + + if (data[n].M == 0) + len = dtls_encrypt(cipher, data[n].msg, data[n].lm); + else + len = dtls_decrypt(cipher, data[n].msg, data[n].lm); + + printf("Packet Vector #%d ", n+1); + if (len != data[n].r_lm + || memcmp(data[n].msg, data[n].result, len)) + printf("FAILED, "); + else + printf("OK, "); + + printf("result is (total length = %d):\n\t", (int)len); + dump(data[n].msg, len); + + free(cipher); + } + + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/cbc_aes128-testdata.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/cbc_aes128-testdata.c new file mode 100644 index 000000000..ba6f96416 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/cbc_aes128-testdata.c @@ -0,0 +1,66 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * + *******************************************************************************/ + +/** + * @file cbc_aes128-testdata.c + * @brief test vectors from Appendix F.2.{1,2} of NIST SP 800-38A, ed. 2001 + */ + +struct test_vector { + size_t M; /* mode: 0 == encrypt, 1 == decrypt */ + size_t lm; /* overall message length */ + size_t la; /* not used */ + unsigned char key[AES_BLKLEN]; + unsigned char nonce[AES_BLKLEN]; + unsigned char msg[2000]; + size_t r_lm; /* overall result length */ + unsigned char result[2000]; /* result */ +}; + +struct test_vector data[] = { + /* F.2.1 (encrypt) */ + { 0, 4 * AES_BLKLEN, 0, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, /* AES key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* Nonce */ + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, /* msg */ + 4 * AES_BLKLEN, /* length of result */ + { 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 + } /* result */ + }, + + /* F.2.2 (decrypt) */ + { 1, 4 * AES_BLKLEN, 0, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, /* AES key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* Nonce */ + { 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 + }, /* msg */ + 4 * AES_BLKLEN, /* length of result */ + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + } /* result */ + } +}; diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/ccm-test.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/ccm-test.c new file mode 100644 index 000000000..7e2e7f87d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/ccm-test.c @@ -0,0 +1,90 @@ +#include +#include +#include +#ifdef HAVE_STRINGS_H +#include +#endif + +#ifdef WITH_CONTIKI +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" +#endif /* WITH_CONTIKI */ + +//#include "dtls_debug.h" +#include "tinydtls.h" +#include "numeric.h" +#include "ccm.h" + +#include "ccm-testdata.c" + +static void +dump(unsigned char *buf, size_t len) { + size_t i = 0; + while (i < len) { + printf("%02x ", buf[i++]); + if (i % 4 == 0) + printf(" "); + if (i % 16 == 0) + printf("\n\t"); + } + printf("\n"); +} + +#ifdef WITH_CONTIKI +PROCESS(ccm_test_process, "CCM test process"); +AUTOSTART_PROCESSES(&ccm_test_process); +PROCESS_THREAD(ccm_test_process, ev, d) +{ +#else /* WITH_CONTIKI */ +int main(int argc, char **argv) { + (void)argc; + (void)argv; +#endif /* WITH_CONTIKI */ + long int len; + size_t n; + + rijndael_ctx ctx; + +#ifdef WITH_CONTIKI + PROCESS_BEGIN(); +#endif /* WITH_CONTIKI */ + + for (n = 0; n < sizeof(data)/sizeof(struct test_vector); ++n) { + + if (rijndael_set_key_enc_only(&ctx, data[n].key, 8*sizeof(data[n].key)) < 0) { + fprintf(stderr, "cannot set key\n"); + return -1; + } + + len = dtls_ccm_encrypt_message(&ctx, data[n].M, data[n].L, data[n].nonce, + data[n].msg + data[n].la, + data[n].lm - data[n].la, + data[n].msg, data[n].la); + + len += + data[n].la; + printf("Packet Vector #%lu ", n+1); + if ((size_t)len != data[n].r_lm || memcmp(data[n].msg, data[n].result, len)) + printf("FAILED, "); + else + printf("OK, "); + + printf("result is (total length = %lu):\n\t", len); + dump(data[n].msg, len); + + len = dtls_ccm_decrypt_message(&ctx, data[n].M, data[n].L, data[n].nonce, + data[n].msg + data[n].la, len - data[n].la, + data[n].msg, data[n].la); + + if (len < 0) + printf("Packet Vector #%lu: cannot decrypt message\n", n+1); + else + printf("\t*** MAC verified (total length = %lu) ***\n", len + data[n].la); + } + +#ifdef WITH_CONTIKI + PROCESS_END(); +#else /* WITH_CONTIKI */ + return 0; +#endif /* WITH_CONTIKI */ +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/ccm-testdata.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/ccm-testdata.c new file mode 100644 index 000000000..1ff289d26 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/ccm-testdata.c @@ -0,0 +1,449 @@ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * + *******************************************************************************/ + +/** + * @file ccm-testdata.c + * @brief test vectors from RFC 3610 + */ + +struct test_vector { + size_t M, L; + size_t lm; /* overall message length */ + size_t la; /* number of bytes additional data */ + unsigned char key[DTLS_CCM_BLOCKSIZE]; + unsigned char nonce[DTLS_CCM_BLOCKSIZE]; + unsigned char msg[200]; + size_t r_lm; /* overall result length */ + unsigned char result[200]; /* result */ +}; + +struct test_vector data[] = { + /* #1 */ + { 8, 2, 31, 8, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E}, /* msg */ + 39, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2, 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80, 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84, 0x17, 0xE8, 0xD1, 0x2C, 0xFD, 0xF9, 0x26, 0xE0} /* result */ + }, + + /* #2 */ + { 8, 2, 32, 8, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}, /* msg */ + 40, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x72, 0xC9, 0x1A, 0x36, 0xE1, 0x35, 0xF8, 0xCF, 0x29, 0x1C, 0xA8, 0x94, 0x08, 0x5C, 0x87, 0xE3, 0xCC, 0x15, 0xC4, 0x39, 0xC9, 0xE4, 0x3A, 0x3B, 0xA0, 0x91, 0xD5, 0x6E, 0x10, 0x40, 0x09, 0x16} /* result */ + }, + + /* #3 */ + { 8, 2, 33, 8, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x02, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20}, /* msg */ + 41, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x51, 0xB1, 0xE5, 0xF4, 0x4A, 0x19, 0x7D, 0x1D, 0xA4, 0x6B, 0x0F, 0x8E, 0x2D, 0x28, 0x2A, 0xE8, 0x71, 0xE8, 0x38, 0xBB, 0x64, 0xDA, 0x85, 0x96, 0x57, 0x4A, 0xDA, 0xA7, 0x6F, 0xBD, 0x9F, 0xB0, 0xC5} /* result */ + }, + + /* #4 */ + { 8, 2, 31, 12, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x06, 0x05, 0x04, 0x03, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E}, /* msg */ + 39, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xA2, 0x8C, 0x68, 0x65, 0x93, 0x9A, 0x9A, 0x79, 0xFA, 0xAA, 0x5C, 0x4C, 0x2A, 0x9D, 0x4A, 0x91, 0xCD, 0xAC, 0x8C, 0x96, 0xC8, 0x61, 0xB9, 0xC9, 0xE6, 0x1E, 0xF1} /* result */ + }, + + /* #5 */ + { 8, 2, 32, 12, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}, /* msg */ + 40, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xDC, 0xF1, 0xFB, 0x7B, 0x5D, 0x9E, 0x23, 0xFB, 0x9D, 0x4E, 0x13, 0x12, 0x53, 0x65, 0x8A, 0xD8, 0x6E, 0xBD, 0xCA, 0x3E, 0x51, 0xE8, 0x3F, 0x07, 0x7D, 0x9C, 0x2D, 0x93} /* result */ + }, + + /* #6 */ + { 8, 2, 33, 12, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x08, 0x07, 0x06, 0x05, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20}, /* msg */ + 41, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x6F, 0xC1, 0xB0, 0x11, 0xF0, 0x06, 0x56, 0x8B, 0x51, 0x71, 0xA4, 0x2D, 0x95, 0x3D, 0x46, 0x9B, 0x25, 0x70, 0xA4, 0xBD, 0x87, 0x40, 0x5A, 0x04, 0x43, 0xAC, 0x91, 0xCB, 0x94} /* result */ + }, + + /* #7 */ + { 10, 2, 31, 8, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x09, 0x08, 0x07, 0x06, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E}, /* msg */ + 41, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x35, 0xD1, 0xB2, 0xC9, 0x5F, 0x41, 0xD5, 0xD1, 0xD4, 0xFE, 0xC1, 0x85, 0xD1, 0x66, 0xB8, 0x09, 0x4E, 0x99, 0x9D, 0xFE, 0xD9, 0x6C, 0x04, 0x8C, 0x56, 0x60, 0x2C, 0x97, 0xAC, 0xBB, 0x74, 0x90} /* result */ + }, + + /* #8 */ + { 10, 2, 32, 8, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x07, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}, /* msg */ + 42, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x7B, 0x75, 0x39, 0x9A, 0xC0, 0x83, 0x1D, 0xD2, 0xF0, 0xBB, 0xD7, 0x58, 0x79, 0xA2, 0xFD, 0x8F, 0x6C, 0xAE, 0x6B, 0x6C, 0xD9, 0xB7, 0xDB, 0x24, 0xC1, 0x7B, 0x44, 0x33, 0xF4, 0x34, 0x96, 0x3F, 0x34, 0xB4} /* result */ + }, + + /* #9 */ + { 10, 2, 33, 8, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x0B, 0x0A, 0x09, 0x08, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20}, /* msg */ + 43, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x82, 0x53, 0x1A, 0x60, 0xCC, 0x24, 0x94, 0x5A, 0x4B, 0x82, 0x79, 0x18, 0x1A, 0xB5, 0xC8, 0x4D, 0xF2, 0x1C, 0xE7, 0xF9, 0xB7, 0x3F, 0x42, 0xE1, 0x97, 0xEA, 0x9C, 0x07, 0xE5, 0x6B, 0x5E, 0xB1, 0x7E, 0x5F, 0x4E} /* result */ + }, + + /* #10 */ + { 10, 2, 31, 12, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x0C, 0x0B, 0x0A, 0x09, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E}, /* msg */ + 41, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15, 0x2B, 0x07, 0x40, 0x98, 0x33, 0x0A, 0xBB, 0x14, 0x1B, 0x94, 0x7B, 0x56, 0x6A, 0xA9, 0x40, 0x6B, 0x4D, 0x99, 0x99, 0x88, 0xDD} /* result */ + }, + + /* #11 */ + { 10, 2, 32, 12, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x0D, 0x0C, 0x0B, 0x0A, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}, /* msg */ + 42, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x67, 0x6B, 0xB2, 0x03, 0x80, 0xB0, 0xE3, 0x01, 0xE8, 0xAB, 0x79, 0x59, 0x0A, 0x39, 0x6D, 0xA7, 0x8B, 0x83, 0x49, 0x34, 0xF5, 0x3A, 0xA2, 0xE9, 0x10, 0x7A, 0x8B, 0x6C, 0x02, 0x2C} /* result */ + }, + + /* #12 */ + { 10, 2, 33, 12, + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, /* AES key */ + { 0x00, 0x00, 0x00, 0x0E, 0x0D, 0x0C, 0x0B, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20}, /* msg */ + 43, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xC0, 0xFF, 0xA0, 0xD6, 0xF0, 0x5B, 0xDB, 0x67, 0xF2, 0x4D, 0x43, 0xA4, 0x33, 0x8D, 0x2A, 0xA4, 0xBE, 0xD7, 0xB2, 0x0E, 0x43, 0xCD, 0x1A, 0xA3, 0x16, 0x62, 0xE7, 0xAD, 0x65, 0xD6, 0xDB} /* result */ + }, + + /* #13 */ + { 8, 2, 31, 8, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0x41, 0x2B, 0x4E, 0xA9, 0xCD, 0xBE, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0x0B, 0xE1, 0xA8, 0x8B, 0xAC, 0xE0, 0x18, 0xB1, 0x08, 0xE8, 0xCF, 0x97, 0xD8, 0x20, 0xEA, 0x25, 0x84, 0x60, 0xE9, 0x6A, 0xD9, 0xCF, 0x52, 0x89, 0x05, 0x4D, 0x89, 0x5C, 0xEA, 0xC4, 0x7C}, /* msg */ + 39, /* length of result */ + { 0x0B, 0xE1, 0xA8, 0x8B, 0xAC, 0xE0, 0x18, 0xB1, 0x4C, 0xB9, 0x7F, 0x86, 0xA2, 0xA4, 0x68, 0x9A, 0x87, 0x79, 0x47, 0xAB, 0x80, 0x91, 0xEF, 0x53, 0x86, 0xA6, 0xFF, 0xBD, 0xD0, 0x80, 0xF8, 0xE7, 0x8C, 0xF7, 0xCB, 0x0C, 0xDD, 0xD7, 0xB3} /* result */ + }, + + /* #14 */ + { 8, 2, 32, 8, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0x33, 0x56, 0x8E, 0xF7, 0xB2, 0x63, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0x63, 0x01, 0x8F, 0x76, 0xDC, 0x8A, 0x1B, 0xCB, 0x90, 0x20, 0xEA, 0x6F, 0x91, 0xBD, 0xD8, 0x5A, 0xFA, 0x00, 0x39, 0xBA, 0x4B, 0xAF, 0xF9, 0xBF, 0xB7, 0x9C, 0x70, 0x28, 0x94, 0x9C, 0xD0, 0xEC}, /* msg */ + 40, /* length of result */ + { 0x63, 0x01, 0x8F, 0x76, 0xDC, 0x8A, 0x1B, 0xCB, 0x4C, 0xCB, 0x1E, 0x7C, 0xA9, 0x81, 0xBE, 0xFA, 0xA0, 0x72, 0x6C, 0x55, 0xD3, 0x78, 0x06, 0x12, 0x98, 0xC8, 0x5C, 0x92, 0x81, 0x4A, 0xBC, 0x33, 0xC5, 0x2E, 0xE8, 0x1D, 0x7D, 0x77, 0xC0, 0x8A} /* result */ + }, + + /* #15 */ + { 8, 2, 33, 8, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0x10, 0x3F, 0xE4, 0x13, 0x36, 0x71, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0xAA, 0x6C, 0xFA, 0x36, 0xCA, 0xE8, 0x6B, 0x40, 0xB9, 0x16, 0xE0, 0xEA, 0xCC, 0x1C, 0x00, 0xD7, 0xDC, 0xEC, 0x68, 0xEC, 0x0B, 0x3B, 0xBB, 0x1A, 0x02, 0xDE, 0x8A, 0x2D, 0x1A, 0xA3, 0x46, 0x13, 0x2E}, /* msg */ + 41, /* length of result */ + { 0xAA, 0x6C, 0xFA, 0x36, 0xCA, 0xE8, 0x6B, 0x40, 0xB1, 0xD2, 0x3A, 0x22, 0x20, 0xDD, 0xC0, 0xAC, 0x90, 0x0D, 0x9A, 0xA0, 0x3C, 0x61, 0xFC, 0xF4, 0xA5, 0x59, 0xA4, 0x41, 0x77, 0x67, 0x08, 0x97, 0x08, 0xA7, 0x76, 0x79, 0x6E, 0xDB, 0x72, 0x35, 0x06} /* result */ + }, + + /* #16 */ + { 8, 2, 31, 12, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0x76, 0x4C, 0x63, 0xB8, 0x05, 0x8E, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0xD0, 0xD0, 0x73, 0x5C, 0x53, 0x1E, 0x1B, 0xEC, 0xF0, 0x49, 0xC2, 0x44, 0x12, 0xDA, 0xAC, 0x56, 0x30, 0xEF, 0xA5, 0x39, 0x6F, 0x77, 0x0C, 0xE1, 0xA6, 0x6B, 0x21, 0xF7, 0xB2, 0x10, 0x1C}, /* msg */ + 39, /* length of result */ + { 0xD0, 0xD0, 0x73, 0x5C, 0x53, 0x1E, 0x1B, 0xEC, 0xF0, 0x49, 0xC2, 0x44, 0x14, 0xD2, 0x53, 0xC3, 0x96, 0x7B, 0x70, 0x60, 0x9B, 0x7C, 0xBB, 0x7C, 0x49, 0x91, 0x60, 0x28, 0x32, 0x45, 0x26, 0x9A, 0x6F, 0x49, 0x97, 0x5B, 0xCA, 0xDE, 0xAF} /* result */ + }, + + /* #17 */ + { 8, 2, 32, 12, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0xF8, 0xB6, 0x78, 0x09, 0x4E, 0x3B, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0x77, 0xB6, 0x0F, 0x01, 0x1C, 0x03, 0xE1, 0x52, 0x58, 0x99, 0xBC, 0xAE, 0xE8, 0x8B, 0x6A, 0x46, 0xC7, 0x8D, 0x63, 0xE5, 0x2E, 0xB8, 0xC5, 0x46, 0xEF, 0xB5, 0xDE, 0x6F, 0x75, 0xE9, 0xCC, 0x0D}, /* msg */ + 40, /* length of result */ + { 0x77, 0xB6, 0x0F, 0x01, 0x1C, 0x03, 0xE1, 0x52, 0x58, 0x99, 0xBC, 0xAE, 0x55, 0x45, 0xFF, 0x1A, 0x08, 0x5E, 0xE2, 0xEF, 0xBF, 0x52, 0xB2, 0xE0, 0x4B, 0xEE, 0x1E, 0x23, 0x36, 0xC7, 0x3E, 0x3F, 0x76, 0x2C, 0x0C, 0x77, 0x44, 0xFE, 0x7E, 0x3C} /* result */ + }, + + /* #18 */ + { 8, 2, 33, 12, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0xD5, 0x60, 0x91, 0x2D, 0x3F, 0x70, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0xCD, 0x90, 0x44, 0xD2, 0xB7, 0x1F, 0xDB, 0x81, 0x20, 0xEA, 0x60, 0xC0, 0x64, 0x35, 0xAC, 0xBA, 0xFB, 0x11, 0xA8, 0x2E, 0x2F, 0x07, 0x1D, 0x7C, 0xA4, 0xA5, 0xEB, 0xD9, 0x3A, 0x80, 0x3B, 0xA8, 0x7F}, /* msg */ + 41, /* length of result */ + { 0xCD, 0x90, 0x44, 0xD2, 0xB7, 0x1F, 0xDB, 0x81, 0x20, 0xEA, 0x60, 0xC0, 0x00, 0x97, 0x69, 0xEC, 0xAB, 0xDF, 0x48, 0x62, 0x55, 0x94, 0xC5, 0x92, 0x51, 0xE6, 0x03, 0x57, 0x22, 0x67, 0x5E, 0x04, 0xC8, 0x47, 0x09, 0x9E, 0x5A, 0xE0, 0x70, 0x45, 0x51} /* result */ + }, + + /* #19 */ + { 10, 2, 31, 8, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0x42, 0xFF, 0xF8, 0xF1, 0x95, 0x1C, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0xD8, 0x5B, 0xC7, 0xE6, 0x9F, 0x94, 0x4F, 0xB8, 0x8A, 0x19, 0xB9, 0x50, 0xBC, 0xF7, 0x1A, 0x01, 0x8E, 0x5E, 0x67, 0x01, 0xC9, 0x17, 0x87, 0x65, 0x98, 0x09, 0xD6, 0x7D, 0xBE, 0xDD, 0x18}, /* msg */ + 41, /* length of result */ + { 0xD8, 0x5B, 0xC7, 0xE6, 0x9F, 0x94, 0x4F, 0xB8, 0xBC, 0x21, 0x8D, 0xAA, 0x94, 0x74, 0x27, 0xB6, 0xDB, 0x38, 0x6A, 0x99, 0xAC, 0x1A, 0xEF, 0x23, 0xAD, 0xE0, 0xB5, 0x29, 0x39, 0xCB, 0x6A, 0x63, 0x7C, 0xF9, 0xBE, 0xC2, 0x40, 0x88, 0x97, 0xC6, 0xBA} /* result */ + }, + + /* #20 */ + { 10, 2, 32, 8, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0x92, 0x0F, 0x40, 0xE5, 0x6C, 0xDC, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0x74, 0xA0, 0xEB, 0xC9, 0x06, 0x9F, 0x5B, 0x37, 0x17, 0x61, 0x43, 0x3C, 0x37, 0xC5, 0xA3, 0x5F, 0xC1, 0xF3, 0x9F, 0x40, 0x63, 0x02, 0xEB, 0x90, 0x7C, 0x61, 0x63, 0xBE, 0x38, 0xC9, 0x84, 0x37}, /* msg */ + 42, /* length of result */ + { 0x74, 0xA0, 0xEB, 0xC9, 0x06, 0x9F, 0x5B, 0x37, 0x58, 0x10, 0xE6, 0xFD, 0x25, 0x87, 0x40, 0x22, 0xE8, 0x03, 0x61, 0xA4, 0x78, 0xE3, 0xE9, 0xCF, 0x48, 0x4A, 0xB0, 0x4F, 0x44, 0x7E, 0xFF, 0xF6, 0xF0, 0xA4, 0x77, 0xCC, 0x2F, 0xC9, 0xBF, 0x54, 0x89, 0x44} /* result */ + }, + + /* #21 */ + { 10, 2, 33, 8, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0x27, 0xCA, 0x0C, 0x71, 0x20, 0xBC, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0x44, 0xA3, 0xAA, 0x3A, 0xAE, 0x64, 0x75, 0xCA, 0xA4, 0x34, 0xA8, 0xE5, 0x85, 0x00, 0xC6, 0xE4, 0x15, 0x30, 0x53, 0x88, 0x62, 0xD6, 0x86, 0xEA, 0x9E, 0x81, 0x30, 0x1B, 0x5A, 0xE4, 0x22, 0x6B, 0xFA}, /* msg */ + 43, /* length of result */ + { 0x44, 0xA3, 0xAA, 0x3A, 0xAE, 0x64, 0x75, 0xCA, 0xF2, 0xBE, 0xED, 0x7B, 0xC5, 0x09, 0x8E, 0x83, 0xFE, 0xB5, 0xB3, 0x16, 0x08, 0xF8, 0xE2, 0x9C, 0x38, 0x81, 0x9A, 0x89, 0xC8, 0xE7, 0x76, 0xF1, 0x54, 0x4D, 0x41, 0x51, 0xA4, 0xED, 0x3A, 0x8B, 0x87, 0xB9, 0xCE} /* result */ + }, + + /* #22 */ + { 10, 2, 31, 12, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0x5B, 0x8C, 0xCB, 0xCD, 0x9A, 0xF8, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25, 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70, 0xB9, 0x6B, 0x49, 0xE2, 0x1D, 0x62, 0x17, 0x41, 0x63, 0x28, 0x75, 0xDB, 0x7F, 0x6C, 0x92, 0x43, 0xD2, 0xD7, 0xC2}, /* msg */ + 41, /* length of result */ + { 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25, 0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70, 0x31, 0xD7, 0x50, 0xA0, 0x9D, 0xA3, 0xED, 0x7F, 0xDD, 0xD4, 0x9A, 0x20, 0x32, 0xAA, 0xBF, 0x17, 0xEC, 0x8E, 0xBF, 0x7D, 0x22, 0xC8, 0x08, 0x8C, 0x66, 0x6B, 0xE5, 0xC1, 0x97} /* result */ + }, + + /* #23 */ + { 10, 2, 32, 12, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0x3E, 0xBE, 0x94, 0x04, 0x4B, 0x9A, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0x47, 0xA6, 0x5A, 0xC7, 0x8B, 0x3D, 0x59, 0x42, 0x27, 0xE8, 0x5E, 0x71, 0xE2, 0xFC, 0xFB, 0xB8, 0x80, 0x44, 0x2C, 0x73, 0x1B, 0xF9, 0x51, 0x67, 0xC8, 0xFF, 0xD7, 0x89, 0x5E, 0x33, 0x70, 0x76}, /* msg */ + 42, /* length of result */ + { 0x47, 0xA6, 0x5A, 0xC7, 0x8B, 0x3D, 0x59, 0x42, 0x27, 0xE8, 0x5E, 0x71, 0xE8, 0x82, 0xF1, 0xDB, 0xD3, 0x8C, 0xE3, 0xED, 0xA7, 0xC2, 0x3F, 0x04, 0xDD, 0x65, 0x07, 0x1E, 0xB4, 0x13, 0x42, 0xAC, 0xDF, 0x7E, 0x00, 0xDC, 0xCE, 0xC7, 0xAE, 0x52, 0x98, 0x7D} /* result */ + }, + + /* #24 */ + { 10, 2, 33, 12, + { 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3, 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B}, /* AES key */ + { 0x00, 0x8D, 0x49, 0x3B, 0x30, 0xAE, 0x8B, 0x3C, 0x96, 0x96, 0x76, 0x6C, 0xFA}, /* Nonce */ + { 0x6E, 0x37, 0xA6, 0xEF, 0x54, 0x6D, 0x95, 0x5D, 0x34, 0xAB, 0x60, 0x59, 0xAB, 0xF2, 0x1C, 0x0B, 0x02, 0xFE, 0xB8, 0x8F, 0x85, 0x6D, 0xF4, 0xA3, 0x73, 0x81, 0xBC, 0xE3, 0xCC, 0x12, 0x85, 0x17, 0xD4}, /* msg */ + 43, /* length of result */ + { 0x6E, 0x37, 0xA6, 0xEF, 0x54, 0x6D, 0x95, 0x5D, 0x34, 0xAB, 0x60, 0x59, 0xF3, 0x29, 0x05, 0xB8, 0x8A, 0x64, 0x1B, 0x04, 0xB9, 0xC9, 0xFF, 0xB5, 0x8C, 0xC3, 0x90, 0x90, 0x0F, 0x3D, 0xA1, 0x2A, 0xB1, 0x6D, 0xCE, 0x9E, 0x82, 0xEF, 0xA1, 0x6D, 0xA6, 0x20, 0x59} /* result */ + }, + + /* #25 */ + /* Cipher: AES-128 M=16 L=2 K_LEN=1 N_LEN=13 K=0x00 N=0x00000000000000000000000000 */ + { 16, 2, 0, 0, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* AES key */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Nonce */ + { 0 }, /* msg */ + 16, /* length of result */ + { 0x8b, 0x60, 0xab, 0xcd, 0x60, 0x43, 0x81, 0x0b, + 0xa3, 0x78, 0xa0, 0x1d, 0x4a, 0x29, 0x83, 0x0b + } /* result */ + }, + + /* #26 */ + /* Cipher: AES-128 M=16 L=2 K_LEN=1 N_LEN=13 K=0x00 N=0x00000000000000000000000000 */ + { 16, 2, 37, 0, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* AES key */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, /* Nonce */ + { 0x45, 0x69, 0x6e, 0x20, 0x6b, 0x6c, 0x65, 0x69, + 0x6e, 0x65, 0x72, 0x20, 0x54, 0x65, 0x78, 0x74, + 0x0a, 0x7a, 0x75, 0x6d, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x65, 0x6e, 0x20, 0x76, 0x6f, 0x6e, 0x20, + 0x43, 0x43, 0x4d, 0x2e, 0x0a + }, /* msg */ + 53, /* length of result */ + { 0x90, 0x11, 0x9c, 0x2d, 0x6b, 0xf9, 0xe9, 0x05, + 0x3e, 0x0b, 0x44, 0x56, 0xca, 0xc8, 0xb6, 0x1a, + 0x00, 0x57, 0xa9, 0x8b, 0x6b, 0x69, 0x09, 0x7e, + 0x8e, 0x50, 0x50, 0x63, 0x50, 0x58, 0x0f, 0x78, + 0x75, 0x69, 0x6e, 0x9f, 0x3d, 0x63, 0x93, 0xe7, + 0x7a, 0x84, 0xe9, 0x9f, 0x11, 0x93, 0x95, 0xa0, + 0x9a, 0xef, 0x0d, 0xa0, 0xed + } /* result */ + }, + + /* #27 */ + /* Cipher: AES-128 M=8 L=5 K_LEN=16 N_LEN=10 K=0x001234567890abcdefdcaffeed3921ee N=0x00112233445566778899 */ + { 8, 5, 0, 0, + { 0x00, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, + 0xef, 0xdc, 0xaf, 0xfe, 0xed, 0x39, 0x21, 0xee }, /* AES key */ + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99 }, /* Nonce */ + { 0 }, /* msg */ + 8, /* length of result */ + { 0xb1, 0x33, 0x51, 0xc8, 0xb3, 0xd5, 0x10, 0xa7 } /* result */ + }, + + /* #28 */ + /* Cipher: AES-128 M=8 L=5 K_LEN=16 N_LEN=10 K=0x001234567890abcdefdcaffeed3921ee N=0x00112233445566778899 */ + { 8, 5, 37, 0, + { 0x00, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, + 0xef, 0xdc, 0xaf, 0xfe, 0xed, 0x39, 0x21, 0xee }, /* AES key */ + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99 }, /* Nonce */ + { 0x45, 0x69, 0x6e, 0x20, 0x6b, 0x6c, 0x65, 0x69, + 0x6e, 0x65, 0x72, 0x20, 0x54, 0x65, 0x78, 0x74, + 0x0a, 0x7a, 0x75, 0x6d, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x65, 0x6e, 0x20, 0x76, 0x6f, 0x6e, 0x20, + 0x43, 0x43, 0x4d, 0x2e, 0x0a + }, /* msg */ + 45, /* length of result */ + { 0x44, 0x7a, 0x82, 0x70, 0x1d, 0xd0, 0x35, 0x7b, + 0x68, 0xf7, 0x35, 0x4d, 0xbf, 0xd9, 0x16, 0x15, + 0x97, 0x41, 0x3d, 0x1e, 0x89, 0xc1, 0x25, 0xe7, + 0xd6, 0xa7, 0xde, 0x90, 0x1e, 0xf1, 0x69, 0x69, + 0x9f, 0xce, 0x40, 0xdc, 0xf0, 0xd1, 0x74, 0x53, + 0x2c, 0xa3, 0xb0, 0xcf, 0xb9 + } /* result */ + }, + + /* #29 */ + /* Cipher: AES-128 M=14 L=3 K_LEN=16 N_LEN=12 K=0x001234567890abcdefdcaffeed3921ee N=0x001122334455667788990000 */ + { 14, 3, 0, 0, + { 0x00, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, + 0xef, 0xdc, 0xaf, 0xfe, 0xed, 0x39, 0x21, 0xee }, /* AES key */ + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0x00, 0x00 }, /* Nonce */ + { 0 }, /* msg */ + 14, /* length of result */ + { 0xa4, 0x06, 0xa4, 0x23, 0x93, 0x3d, 0xa0, 0xca, + 0xb5, 0x90, 0xdb, 0x69, 0x69, 0x33 } /* result */ + }, + + /* #30 */ + /* Cipher: AES-128 M=14 L=3 K_LEN=16 N_LEN=12 K=0x001234567890abcdefdcaffeed3921ee N=0x001122334455667788990000 */ + { 14, 3, 37, 0, + { 0x00, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, + 0xef, 0xdc, 0xaf, 0xfe, 0xed, 0x39, 0x21, 0xee }, /* AES key */ + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0x00, 0x00 }, /* Nonce */ + { 0x45, 0x69, 0x6e, 0x20, 0x6b, 0x6c, 0x65, 0x69, + 0x6e, 0x65, 0x72, 0x20, 0x54, 0x65, 0x78, 0x74, + 0x0a, 0x7a, 0x75, 0x6d, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x65, 0x6e, 0x20, 0x76, 0x6f, 0x6e, 0x20, + 0x43, 0x43, 0x4d, 0x2e, 0x0a + }, /* msg */ + 51, + { 0x60, 0xaf, 0x87, 0x67, 0x4d, 0x9d, 0x54, 0x17, + 0x16, 0xc0, 0x29, 0x10, 0x7e, 0x3e, 0x34, 0x93, + 0x78, 0xe8, 0xd3, 0xc8, 0xc1, 0x03, 0x4f, 0xd6, + 0xf5, 0x3b, 0xaf, 0xd3, 0xf0, 0xd7, 0x0b, 0xdd, + 0x63, 0x93, 0xed, 0xf2, 0xb2, 0x72, 0xdc, 0xae, + 0x7c, 0xa0, 0x01, 0xdb, 0x56, 0x2a, 0x06, 0xb6, + 0xe9, 0xcf, 0x3c } /* result */ + }, + + /* #31 */ + /* Cipher: AES-128 M=8 L=5 K_LEN=6 N_LEN=10 K=0x11223344aabb N=0x00112233445566778899 */ + { 8, 5, 0, 0, + { 0x11, 0x22, 0x33, 0x44, 0xaa, 0xbb }, /* AES key */ + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99 }, /* Nonce */ + { 0 }, /* msg */ + 8, + { 0x28, 0x15, 0xfe, 0x81, 0xdd, 0xc3, 0x79, 0x04 } /* result */ + }, + + /* #32 */ + /* Cipher: AES-128 M=8 L=5 K_LEN=6 N_LEN=10 K=0x11223344aabb N=0x00112233445566778899 */ + + { 8, 5, 37, 0, + { 0x11, 0x22, 0x33, 0x44, 0xaa, 0xbb }, /* AES key */ + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99 }, /* Nonce */ + { 0x45, 0x69, 0x6e, 0x20, 0x6b, 0x6c, 0x65, 0x69, + 0x6e, 0x65, 0x72, 0x20, 0x54, 0x65, 0x78, 0x74, + 0x0a, 0x7a, 0x75, 0x6d, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x65, 0x6e, 0x20, 0x76, 0x6f, 0x6e, 0x20, + 0x43, 0x43, 0x4d, 0x2e, 0x0a + }, /* msg */ + 45, + { 0xdb, 0x31, 0x55, 0x9d, 0xab, 0x70, 0xdc, 0x62, + 0xd7, 0x76, 0x41, 0xb2, 0x14, 0x9e, 0x9c, 0x26, + 0x70, 0x61, 0xea, 0x36, 0xf8, 0x0e, 0xdf, 0x19, + 0xa6, 0xc7, 0x46, 0x3d, 0x5a, 0xc3, 0x0a, 0x73, + 0x14, 0x96, 0xa4, 0x84, 0x7f, 0x37, 0x55, 0x42, + 0xce, 0x7e, 0xf9, 0x3b, 0xe5 } /* result */ + }, + + /* #33 */ + /* Cipher: AES-128 M=8 L=3 K_LEN=16 N_LEN=12 K=0xc0c1c2c3c4c5c6c7c8c9cacbcccdcecf N=0xabcdef030201a0a1a200a4a5 */ + { 8, 3, 22, 8, + { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf + }, /* AES key */ + { 0xab, 0xcd, 0xef, 0x03, 0x02, 0x01, 0xa0, 0xa1, + 0xa2, 0x00, 0xa4, 0xa5 }, /* Nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x61, 0x62, 0x63, 0x44, 0x45, 0x46, 0x78, 0x79, + 0x7a, 0x31, 0x32, 0x33, 0x34, 0x35 }, /* msg */ + 30, /* length of result */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0xad, 0xf3, 0xfc, 0x3a, 0xd8, 0xf2, 0x4f, 0xfe, + 0x2b, 0xc2, 0x77, 0x21, 0x85, 0x1a, 0xa6, 0x13, + 0x87, 0xe6, 0x31, 0xc4, 0xed, 0xd7 + } /* result */ + }, + + /* #34 */ + /* Cipher: AES-128 M=8 L=3 K_LEN=16 N_LEN=12 K=0xc0c1c2c3c4c5c6c7c8c9cacbcccdcecf N=0xabcdef030201a0a1a200a4a5 */ + { 8, 3, 14, 0, + { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf + }, /* AES key */ + { 0xab, 0xcd, 0xef, 0x03, 0x02, 0x01, 0xa0, 0xa1, + 0xa2, 0x00, 0xa4, 0xa5 + }, /* Nonce */ + { 0x61, 0x62, 0x63, 0x44, 0x45, 0x46, 0x78, 0x79, + 0x7a, 0x31, 0x32, 0x33, 0x34, 0x35 + }, /* msg */ + 22, /* length of result */ + { 0xad, 0xf3, 0xfc, 0x3a, 0xd8, 0xf2, 0x4f, 0xfe, + 0x2b, 0xc2, 0x77, 0x21, 0x85, 0x1a, 0xdb, 0x21, + 0x61, 0xde, 0x8f, 0x24, 0x1e, 0x91 + } /* result */ + }, + + /* #35 */ + /* Cipher: AES-128 M=16 L=3 K_LEN=16 N_LEN=12 K=0xc0c1c2c3c4c5c6c7c8c9cacbcccdcecf N=0xabcdef030201a0a1a200a4a5 */ + { 16, 3, 19, 3, + { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf + }, /* AES key */ + { 0xab, 0xcd, 0xef, 0x03, 0x02, 0x01, 0xa0, 0xa1, + 0xa2, 0x00, 0xa4, 0xa5 }, /* Nonce */ + { 0xaa, 0xbb, 0xcc, 0x31, 0x36, 0x20, 0x42, 0x79, + 0x74, 0x65, 0x73, 0x20, 0x4d, 0x41, 0x43, 0x20, + 0x74, 0x61, 0x67 + }, /* msg */ + 35, /* length of result */ + { 0xaa, 0xbb, 0xcc, 0xfd, 0xa7, 0xbf, 0x3c, 0xe4, + 0xc0, 0x52, 0xf4, 0x71, 0xbe, 0x04, 0x51, 0x91, + 0x5b, 0x21, 0x84, 0x77, 0x05, 0xa0, 0xb7, 0x02, + 0xce, 0xd1, 0xac, 0xd3, 0x27, 0x60, 0xb1, 0x4a, + 0x15, 0xc7, 0xe6 + } /* result */ + } + +}; diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dsrv-test.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dsrv-test.c new file mode 100644 index 000000000..4ef460515 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dsrv-test.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ + +#include "dsrv.h" + +void +handle_read(struct dsrv_context_t *ctx) { + int len; + static char buf[200]; + struct sockaddr_storage src; + socklen_t srclen = sizeof(src); + int fd = dsrv_get_fd(ctx, DSRV_READ); + + len = recvfrom(fd, buf, sizeof(buf), 0, + (struct sockaddr *)&src, &srclen); + + if (len < 0) { + perror("recvfrom"); + } else { + printf("read %d bytes: '%*s'\n", len, len, buf); + if (dsrv_sendto(ctx, (struct sockaddr *)&src, srclen, 0, buf, len) + == NULL) { + fprintf(stderr, "cannot add packet to sendqueue\n"); + } + } +} + +int +handle_write(struct dsrv_context_t *ctx) { + struct packet_t *p; + int fd = dsrv_get_fd(ctx, DSRV_WRITE); + int len; + + p = ctx->rq ? nq_peek(ctx->wq) : NULL; + + if (!p) + return -1; + + len = sendto(fd, p->buf, p->len, 0, p->raddr, p->rlen); + + if (len < 0) + perror("sendto"); + else + nq_pop(ctx->wq); + + return len; +} + +int main(int argc, char **argv) { + +#if 1 + struct sockaddr_in6 listen_addr = { AF_INET6, htons(20220), 0, IN6ADDR_ANY_INIT, 0 }; +#else + struct sockaddr_in listen_addr = { AF_INET, htons(20220), { htonl(0x7f000001) } }; +#endif + fd_set rfds, wfds; + struct timeval timeout; + struct dsrv_context_t *ctx; + int result; + + ctx = dsrv_new_context((struct sockaddr *)&listen_addr, sizeof(listen_addr), + 200,200); + + if (!ctx) { + fprintf(stderr, "E: cannot create server context\n"); + return -1; + } + + while (1) { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + dsrv_prepare(ctx, &rfds, DSRV_READ); + dsrv_prepare(ctx, &wfds, DSRV_WRITE); + +#if 0 + timeout.tv_sec = 0; + timeout.tv_usec = dsrv_get_timeout(ctx); +#else + timeout.tv_sec = 5; + timeout.tv_usec = 0; +#endif + + result = select( FD_SETSIZE, &rfds, &wfds, 0, &timeout); + + if (result < 0) { /* error */ + if (errno != EINTR) + perror("select"); + } else if (result == 0) { /* timeout */ + printf("."); + } else { /* ok */ + if (dsrv_check(ctx, &wfds, DSRV_WRITE)) + handle_write(ctx); + else if (dsrv_check(ctx, &rfds, DSRV_READ)) + handle_read(ctx); + } + } + + dsrv_close(ctx); + dsrv_free_context(ctx); + + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dtls-client.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dtls-client.c new file mode 100644 index 000000000..6058f99f4 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dtls-client.c @@ -0,0 +1,554 @@ +#include "tinydtls.h" + +/* This is needed for apple */ +#define __APPLE_USE_RFC_3542 + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ + +#include +#include +#include + +#include "global.h" +#include "dtls_debug.h" +#include "dtls.h" + +#define DEFAULT_PORT 20220 + +#define PSK_DEFAULT_IDENTITY "Client_identity" +#define PSK_DEFAULT_KEY "secretPSK" +#define PSK_OPTIONS "i:k:" + +#ifdef __GNUC__ +#define UNUSED_PARAM __attribute__((unused)) +#else +#define UNUSED_PARAM +#endif /* __GNUC__ */ + +typedef struct { + size_t length; /* length of string */ + unsigned char *s; /* string data */ +} dtls_str; + +static dtls_str output_file = { 0, NULL }; /* output file name */ + +static dtls_context_t *dtls_context = NULL; +static dtls_context_t *orig_dtls_context = NULL; + + +#ifdef DTLS_ECC +static const unsigned char ecdsa_priv_key[] = { + 0x41, 0xC1, 0xCB, 0x6B, 0x51, 0x24, 0x7A, 0x14, + 0x43, 0x21, 0x43, 0x5B, 0x7A, 0x80, 0xE7, 0x14, + 0x89, 0x6A, 0x33, 0xBB, 0xAD, 0x72, 0x94, 0xCA, + 0x40, 0x14, 0x55, 0xA1, 0x94, 0xA9, 0x49, 0xFA}; + +static const unsigned char ecdsa_pub_key_x[] = { + 0x36, 0xDF, 0xE2, 0xC6, 0xF9, 0xF2, 0xED, 0x29, + 0xDA, 0x0A, 0x9A, 0x8F, 0x62, 0x68, 0x4E, 0x91, + 0x63, 0x75, 0xBA, 0x10, 0x30, 0x0C, 0x28, 0xC5, + 0xE4, 0x7C, 0xFB, 0xF2, 0x5F, 0xA5, 0x8F, 0x52}; + +static const unsigned char ecdsa_pub_key_y[] = { + 0x71, 0xA0, 0xD4, 0xFC, 0xDE, 0x1A, 0xB8, 0x78, + 0x5A, 0x3C, 0x78, 0x69, 0x35, 0xA7, 0xCF, 0xAB, + 0xE9, 0x3F, 0x98, 0x72, 0x09, 0xDA, 0xED, 0x0B, + 0x4F, 0xAB, 0xC3, 0x6F, 0xC7, 0x72, 0xF8, 0x29}; +#endif /* DTLS_ECC */ + +#ifdef DTLS_PSK +static ssize_t +read_from_file(char *arg, unsigned char *buf, size_t max_buf_len) { + FILE *f; + ssize_t result = 0; + + f = fopen(arg, "r"); + if (f == NULL) + return -1; + + while (!feof(f)) { + size_t bytes_read; + bytes_read = fread(buf, 1, max_buf_len, f); + if (ferror(f)) { + result = -1; + break; + } + + buf += bytes_read; + result += bytes_read; + max_buf_len -= bytes_read; + } + + fclose(f); + return result; +} + +/* The PSK information for DTLS */ +#define PSK_ID_MAXLEN 256 +#define PSK_MAXLEN 256 +static unsigned char psk_id[PSK_ID_MAXLEN]; +static size_t psk_id_length = 0; +static unsigned char psk_key[PSK_MAXLEN]; +static size_t psk_key_length = 0; + +/* This function is the "key store" for tinyDTLS. It is called to + * retrieve a key for the given identity within this particular + * session. */ +static int +get_psk_info(struct dtls_context_t *ctx UNUSED_PARAM, + const session_t *session UNUSED_PARAM, + dtls_credentials_type_t type, + const unsigned char *id, size_t id_len, + unsigned char *result, size_t result_length) { + + switch (type) { + case DTLS_PSK_IDENTITY: + if (id_len) { + dtls_debug("got psk_identity_hint: '%.*s'\n", (int)id_len, id); + } + + if (result_length < psk_id_length) { + dtls_warn("cannot set psk_identity -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + memcpy(result, psk_id, psk_id_length); + return psk_id_length; + case DTLS_PSK_KEY: + if (id_len != psk_id_length || memcmp(psk_id, id, id_len) != 0) { + dtls_warn("PSK for unknown id requested, exiting\n"); + return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); + } else if (result_length < psk_key_length) { + dtls_warn("cannot set psk -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + memcpy(result, psk_key, psk_key_length); + return psk_key_length; + case DTLS_PSK_HINT: + default: + dtls_warn("unsupported request type: %d\n", type); + } + + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); +} +#endif /* DTLS_PSK */ + +#ifdef DTLS_ECC +static int +get_ecdsa_key(struct dtls_context_t *ctx, + const session_t *session, + const dtls_ecdsa_key_t **result) { + static const dtls_ecdsa_key_t ecdsa_key = { + .curve = DTLS_ECDH_CURVE_SECP256R1, + .priv_key = ecdsa_priv_key, + .pub_key_x = ecdsa_pub_key_x, + .pub_key_y = ecdsa_pub_key_y + }; + (void)ctx; + (void)session; + + *result = &ecdsa_key; + return 0; +} + +static int +verify_ecdsa_key(struct dtls_context_t *ctx, + const session_t *session, + const unsigned char *other_pub_x, + const unsigned char *other_pub_y, + size_t key_size) { + (void)ctx; + (void)session; + (void)other_pub_x; + (void)other_pub_y; + (void)key_size; + return 0; +} +#endif /* DTLS_ECC */ + +static void +try_send(struct dtls_context_t *ctx, session_t *dst, size_t len, char *buf) { + int res; + res = dtls_write(ctx, dst, (uint8 *)buf, len); + if (res >= 0) { + memmove(buf, buf + res, len - res); + len -= res; + } +} + +static void +handle_stdin(size_t *len, char *buf) { + if (fgets(buf + *len, sizeof(buf) - *len, stdin)) + *len += strlen(buf + *len); +} + +static int +read_from_peer(struct dtls_context_t *ctx, + session_t *session, uint8 *data, size_t len) { + size_t i; + (void)ctx; + (void)session; + + for (i = 0; i < len; i++) + printf("%c", data[i]); + return 0; +} + +static int +send_to_peer(struct dtls_context_t *ctx, + session_t *session, uint8 *data, size_t len) { + + int fd = *(int *)dtls_get_app_data(ctx); + return sendto(fd, data, len, MSG_DONTWAIT, + &session->addr.sa, session->size); +} + +static int +dtls_handle_read(struct dtls_context_t *ctx) { + int fd; + session_t session; +#define MAX_READ_BUF 2000 + static uint8 buf[MAX_READ_BUF]; + int len; + + fd = *(int *)dtls_get_app_data(ctx); + + if (!fd) + return -1; + + memset(&session, 0, sizeof(session_t)); + session.size = sizeof(session.addr); + len = recvfrom(fd, buf, MAX_READ_BUF, 0, + &session.addr.sa, &session.size); + + if (len < 0) { + perror("recvfrom"); + return -1; + } else { + dtls_dsrv_log_addr(DTLS_LOG_DEBUG, "peer", &session); + dtls_debug_dump("bytes from peer", buf, len); + } + + return dtls_handle_message(ctx, &session, buf, len); +} + +static void dtls_handle_signal(int sig) +{ + dtls_free_context(dtls_context); + dtls_free_context(orig_dtls_context); + signal(sig, SIG_DFL); + kill(getpid(), sig); +} + +/* stolen from libcoap: */ +static int +resolve_address(const char *server, struct sockaddr *dst) { + + struct addrinfo *res, *ainfo; + struct addrinfo hints; + static char addrstr[256]; + int error, result; + + memset(addrstr, 0, sizeof(addrstr)); + if (server && strlen(server) > 0) + memcpy(addrstr, server, strlen(server)); + else + memcpy(addrstr, "localhost", 9); + + memset ((char *)&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_UNSPEC; + + error = getaddrinfo(addrstr, NULL, &hints, &res); + + if (error != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); + return error; + } + + result = -1; + for (ainfo = res; (result == -1) && (ainfo != NULL); ainfo = ainfo->ai_next) { + + switch (ainfo->ai_family) { + case AF_INET6: + case AF_INET: + + memcpy(dst, ainfo->ai_addr, ainfo->ai_addrlen); + result = ainfo->ai_addrlen; + break; + default: + ; + } + } + + freeaddrinfo(res); + return result; +} + +/*---------------------------------------------------------------------------*/ +static void +usage( const char *program, const char *version) { + const char *p; + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf(stderr, "%s v%s -- DTLS client implementation\n" + "(c) 2011-2014 Olaf Bergmann \n\n" +#ifdef DTLS_PSK + "usage: %s [-i file] [-k file] [-o file] [-p port] [-v num] addr [port]\n" +#else /* DTLS_PSK */ + "usage: %s [-o file] [-p port] [-v num] addr [port]\n" +#endif /* DTLS_PSK */ +#ifdef DTLS_PSK + "\t-i file\t\tread PSK identity from file\n" + "\t-k file\t\tread pre-shared key from file\n" +#endif /* DTLS_PSK */ + "\t-o file\t\toutput received data to this file (use '-' for STDOUT)\n" + "\t-p port\t\tlisten on specified port (default is %d)\n" + "\t-v num\t\tverbosity level (default: 3)\n", + program, version, program, DEFAULT_PORT); +} + +static dtls_handler_t cb = { + .write = send_to_peer, + .read = read_from_peer, + .event = NULL, +#ifdef DTLS_PSK + .get_psk_info = get_psk_info, +#endif /* DTLS_PSK */ +#ifdef DTLS_ECC + .get_ecdsa_key = get_ecdsa_key, + .verify_ecdsa_key = verify_ecdsa_key +#endif /* DTLS_ECC */ +}; + +#define DTLS_CLIENT_CMD_CLOSE "client:close" +#define DTLS_CLIENT_CMD_RENEGOTIATE "client:renegotiate" + +/* As per RFC 6347 section 4.2.8, DTLS Server should support requests + * from clients who have silently abandoned the existing association + * and initiated a new handshake request by sending a ClientHello. + * Below command tests this feature. + */ +#define DTLS_CLIENT_CMD_REHANDSHAKE "client:rehandshake" + +int +main(int argc, char **argv) { + fd_set rfds, wfds; + struct timeval timeout; + unsigned short port = DEFAULT_PORT; + char port_str[NI_MAXSERV] = "0"; + log_t log_level = DTLS_LOG_WARN; + int fd; + ssize_t result; + int on = 1; + int opt, res; + session_t dst; + char buf[200]; + size_t len = 0; + + + dtls_init(); + snprintf(port_str, sizeof(port_str), "%d", port); + +#ifdef DTLS_PSK + psk_id_length = strlen(PSK_DEFAULT_IDENTITY); + psk_key_length = strlen(PSK_DEFAULT_KEY); + memcpy(psk_id, PSK_DEFAULT_IDENTITY, psk_id_length); + memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length); +#endif /* DTLS_PSK */ + + while ((opt = getopt(argc, argv, "p:o:v:" PSK_OPTIONS)) != -1) { + switch (opt) { +#ifdef DTLS_PSK + case 'i' : + result = read_from_file(optarg, psk_id, PSK_ID_MAXLEN); + if (result < 0) { + dtls_warn("cannot read PSK identity\n"); + } else { + psk_id_length = result; + } + break; + case 'k' : + result = read_from_file(optarg, psk_key, PSK_MAXLEN); + if (result < 0) { + dtls_warn("cannot read PSK\n"); + } else { + psk_key_length = result; + } + break; +#endif /* DTLS_PSK */ + case 'p' : + strncpy(port_str, optarg, NI_MAXSERV-1); + port_str[NI_MAXSERV - 1] = '\0'; + break; + case 'o' : + output_file.length = strlen(optarg); + output_file.s = (unsigned char *)malloc(output_file.length + 1); + + if (!output_file.s) { + dtls_crit("cannot set output file: insufficient memory\n"); + exit(-1); + } else { + /* copy filename including trailing zero */ + memcpy(output_file.s, optarg, output_file.length + 1); + } + break; + case 'v' : + log_level = strtol(optarg, NULL, 10); + break; + default: + usage(argv[0], dtls_package_version()); + exit(1); + } + } + + dtls_set_log_level(log_level); + + if (argc <= optind) { + usage(argv[0], dtls_package_version()); + exit(1); + } + + memset(&dst, 0, sizeof(session_t)); + /* resolve destination address where server should be sent */ + res = resolve_address(argv[optind++], &dst.addr.sa); + if (res < 0) { + dtls_emerg("failed to resolve address\n"); + exit(-1); + } + dst.size = res; + + /* use port number from command line when specified or the listen + port, otherwise */ + dst.addr.sin.sin_port = htons(atoi(optind < argc ? argv[optind++] : port_str)); + + + /* init socket and set it to non-blocking */ + fd = socket(dst.addr.sa.sa_family, SOCK_DGRAM, 0); + + if (fd < 0) { + dtls_alert("socket: %s\n", strerror(errno)); + return 0; + } + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) { + dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno)); + } +#if 0 + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { + dtls_alert("fcntl: %s\n", strerror(errno)); + goto error; + } +#endif + on = 1; + if (dst.addr.sa.sa_family == AF_INET6) { +#ifdef IPV6_RECVPKTINFO + if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on) ) < 0) { +#else /* IPV6_RECVPKTINFO */ + if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on) ) < 0) { +#endif /* IPV6_RECVPKTINFO */ + dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno)); + } + } + else { + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on) ) < 0) { + dtls_alert("setsockopt IP_PKTINFO: %s\n", strerror(errno)); + } + } + + if (signal(SIGINT, dtls_handle_signal) == SIG_ERR) { + dtls_alert("An error occurred while setting a signal handler.\n"); + return EXIT_FAILURE; + } + + dtls_context = dtls_new_context(&fd); + if (!dtls_context) { + dtls_emerg("cannot create context\n"); + exit(-1); + } + + dtls_set_handler(dtls_context, &cb); + + dtls_connect(dtls_context, &dst); + + while (1) { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + FD_SET(fileno(stdin), &rfds); + FD_SET(fd, &rfds); + /* FD_SET(fd, &wfds); */ + + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + result = select(fd+1, &rfds, &wfds, 0, &timeout); + + if (result < 0) { /* error */ + if (errno != EINTR) + perror("select"); + } else if (result == 0) { /* timeout */ + } else { /* ok */ + if (FD_ISSET(fd, &wfds)) + /* FIXME */; + else if (FD_ISSET(fd, &rfds)) + dtls_handle_read(dtls_context); + else if (FD_ISSET(fileno(stdin), &rfds)) + handle_stdin(&len, buf); + } + + if (len) { + if (len >= strlen(DTLS_CLIENT_CMD_CLOSE) && + !memcmp(buf, DTLS_CLIENT_CMD_CLOSE, strlen(DTLS_CLIENT_CMD_CLOSE))) { + printf("client: closing connection\n"); + dtls_close(dtls_context, &dst); + len = 0; + } else if (len >= strlen(DTLS_CLIENT_CMD_RENEGOTIATE) && + !memcmp(buf, DTLS_CLIENT_CMD_RENEGOTIATE, strlen(DTLS_CLIENT_CMD_RENEGOTIATE))) { + printf("client: renegotiate connection\n"); + dtls_renegotiate(dtls_context, &dst); + len = 0; + } else if (len >= strlen(DTLS_CLIENT_CMD_REHANDSHAKE) && + !memcmp(buf, DTLS_CLIENT_CMD_REHANDSHAKE, strlen(DTLS_CLIENT_CMD_REHANDSHAKE))) { + printf("client: rehandshake connection\n"); + if (orig_dtls_context == NULL) { + /* Cache the current context. We cannot free the current context as it will notify + * the Server to close the connection (which we do not want). + */ + orig_dtls_context = dtls_context; + /* Now, Create a new context and attempt to initiate a handshake. */ + dtls_context = dtls_new_context(&fd); + if (!dtls_context) { + dtls_emerg("cannot create context\n"); + exit(-1); + } + dtls_set_handler(dtls_context, &cb); + dtls_connect(dtls_context, &dst); + } + len = 0; + } else { + try_send(dtls_context, &dst, len, buf); + } + } + } + + dtls_free_context(dtls_context); + dtls_free_context(orig_dtls_context); + exit(0); +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dtls-server.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dtls-server.c new file mode 100644 index 000000000..e76876b75 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/dtls-server.c @@ -0,0 +1,402 @@ + +/* This is needed for apple */ +#define __APPLE_USE_RFC_3542 + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ +#include +#include + +#include "tinydtls.h" +#include "dtls.h" +#include "dtls_debug.h" + +#define DEFAULT_PORT 20220 + +static dtls_context_t *the_context = NULL; + +#ifdef DTLS_ECC +static const unsigned char ecdsa_priv_key[] = { + 0xD9, 0xE2, 0x70, 0x7A, 0x72, 0xDA, 0x6A, 0x05, + 0x04, 0x99, 0x5C, 0x86, 0xED, 0xDB, 0xE3, 0xEF, + 0xC7, 0xF1, 0xCD, 0x74, 0x83, 0x8F, 0x75, 0x70, + 0xC8, 0x07, 0x2D, 0x0A, 0x76, 0x26, 0x1B, 0xD4}; + +static const unsigned char ecdsa_pub_key_x[] = { + 0xD0, 0x55, 0xEE, 0x14, 0x08, 0x4D, 0x6E, 0x06, + 0x15, 0x59, 0x9D, 0xB5, 0x83, 0x91, 0x3E, 0x4A, + 0x3E, 0x45, 0x26, 0xA2, 0x70, 0x4D, 0x61, 0xF2, + 0x7A, 0x4C, 0xCF, 0xBA, 0x97, 0x58, 0xEF, 0x9A}; + +static const unsigned char ecdsa_pub_key_y[] = { + 0xB4, 0x18, 0xB6, 0x4A, 0xFE, 0x80, 0x30, 0xDA, + 0x1D, 0xDC, 0xF4, 0xF4, 0x2E, 0x2F, 0x26, 0x31, + 0xD0, 0x43, 0xB1, 0xFB, 0x03, 0xE2, 0x2F, 0x4D, + 0x17, 0xDE, 0x43, 0xF9, 0xF9, 0xAD, 0xEE, 0x70}; +#endif /* DTLS_ECC */ + +#ifdef DTLS_PSK +/* This function is the "key store" for tinyDTLS. It is called to + * retrieve a key for the given identity within this particular + * session. */ +static int +get_psk_info(struct dtls_context_t *ctx, const session_t *session, + dtls_credentials_type_t type, + const unsigned char *id, size_t id_len, + unsigned char *result, size_t result_length) { + + struct keymap_t { + unsigned char *id; + size_t id_length; + unsigned char *key; + size_t key_length; + } psk[3] = { + { (unsigned char *)"Client_identity", 15, + (unsigned char *)"secretPSK", 9 }, + { (unsigned char *)"default identity", 16, + (unsigned char *)"\x11\x22\x33", 3 }, + { (unsigned char *)"\0", 2, + (unsigned char *)"", 1 } + }; + (void)ctx; + (void)session; + + if (type != DTLS_PSK_KEY) { + return 0; + } + + if (id) { + size_t i; + for (i = 0; i < sizeof(psk)/sizeof(struct keymap_t); i++) { + if (id_len == psk[i].id_length && memcmp(id, psk[i].id, id_len) == 0) { + if (result_length < psk[i].key_length) { + dtls_warn("buffer too small for PSK"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + + memcpy(result, psk[i].key, psk[i].key_length); + return psk[i].key_length; + } + } + } + + return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR); +} + +#endif /* DTLS_PSK */ + +#ifdef DTLS_ECC +static int +get_ecdsa_key(struct dtls_context_t *ctx, + const session_t *session, + const dtls_ecdsa_key_t **result) { + static const dtls_ecdsa_key_t ecdsa_key = { + .curve = DTLS_ECDH_CURVE_SECP256R1, + .priv_key = ecdsa_priv_key, + .pub_key_x = ecdsa_pub_key_x, + .pub_key_y = ecdsa_pub_key_y + }; + (void)ctx; + (void)session; + + *result = &ecdsa_key; + return 0; +} + +static int +verify_ecdsa_key(struct dtls_context_t *ctx, + const session_t *session, + const unsigned char *other_pub_x, + const unsigned char *other_pub_y, + size_t key_size) { + (void)ctx; + (void)session; + (void)other_pub_x; + (void)other_pub_y; + (void)key_size; + return 0; +} +#endif /* DTLS_ECC */ + +#define DTLS_SERVER_CMD_CLOSE "server:close" +#define DTLS_SERVER_CMD_RENEGOTIATE "server:renegotiate" + +static int +read_from_peer(struct dtls_context_t *ctx, + session_t *session, uint8 *data, size_t len) { + if (write(STDOUT_FILENO, data, len) == -1) + dtls_debug("write failed: %s\n", strerror(errno)); + if (len >= strlen(DTLS_SERVER_CMD_CLOSE) && + !memcmp(data, DTLS_SERVER_CMD_CLOSE, strlen(DTLS_SERVER_CMD_CLOSE))) { + printf("server: closing connection\n"); + dtls_close(ctx, session); + return len; + } else if (len >= strlen(DTLS_SERVER_CMD_RENEGOTIATE) && + !memcmp(data, DTLS_SERVER_CMD_RENEGOTIATE, strlen(DTLS_SERVER_CMD_RENEGOTIATE))) { + printf("server: renegotiate connection\n"); + dtls_renegotiate(ctx, session); + return len; + } + + return dtls_write(ctx, session, data, len); +} + +static int +send_to_peer(struct dtls_context_t *ctx, + session_t *session, uint8 *data, size_t len) { + + int fd = *(int *)dtls_get_app_data(ctx); + return sendto(fd, data, len, MSG_DONTWAIT, + &session->addr.sa, session->size); +} + +static int +dtls_handle_read(struct dtls_context_t *ctx) { + int *fd; + session_t session; + static uint8 buf[DTLS_MAX_BUF]; + int len; + + fd = dtls_get_app_data(ctx); + + assert(fd); + + memset(&session, 0, sizeof(session_t)); + session.size = sizeof(session.addr); + len = recvfrom(*fd, buf, sizeof(buf), MSG_TRUNC, + &session.addr.sa, &session.size); + + if (len < 0) { + perror("recvfrom"); + return -1; + } else { + dtls_debug("got %d bytes from port %d\n", len, + ntohs(session.addr.sin6.sin6_port)); + if (sizeof(buf) < (size_t)len) { + dtls_warn("packet was truncated (%ld bytes lost)\n", len - sizeof(buf)); + } + } + + return dtls_handle_message(ctx, &session, buf, len); +} + +static void dtls_handle_signal(int sig) +{ + dtls_free_context(the_context); + signal(sig, SIG_DFL); + kill(getpid(), sig); +} + +static int +resolve_address(const char *server, struct sockaddr *dst) { + + struct addrinfo *res, *ainfo; + struct addrinfo hints; + static char addrstr[256]; + int error, len=-1; + + memset(addrstr, 0, sizeof(addrstr)); + if (server && strlen(server) > 0) + memcpy(addrstr, server, strlen(server)); + else + memcpy(addrstr, "localhost", 9); + + memset ((char *)&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_UNSPEC; + + error = getaddrinfo(addrstr, NULL, &hints, &res); + + if (error != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); + return error; + } + + for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) { + switch (ainfo->ai_family) { + case AF_INET6: + case AF_INET: + len = (int)ainfo->ai_addrlen; + memcpy(dst, ainfo->ai_addr, len); + goto finish; + default: + ; + } + } + +finish: + freeaddrinfo(res); + return len; +} + +static void +usage(const char *program, const char *version) { + const char *p; + + p = strrchr( program, '/' ); + if ( p ) + program = ++p; + + fprintf(stderr, "%s v%s -- DTLS server implementation\n" + "(c) 2011-2014 Olaf Bergmann \n\n" + "usage: %s [-A address] [-p port] [-v num]\n" + "\t-A address\t\tlisten on specified address (default is ::)\n" + "\t-p port\t\tlisten on specified port (default is %d)\n" + "\t-v num\t\tverbosity level (default: 3)\n", + program, version, program, DEFAULT_PORT); +} + +static dtls_handler_t cb = { + .write = send_to_peer, + .read = read_from_peer, + .event = NULL, +#ifdef DTLS_PSK + .get_psk_info = get_psk_info, +#endif /* DTLS_PSK */ +#ifdef DTLS_ECC + .get_ecdsa_key = get_ecdsa_key, + .verify_ecdsa_key = verify_ecdsa_key +#endif /* DTLS_ECC */ +}; + +int +main(int argc, char **argv) { + log_t log_level = DTLS_LOG_WARN; + fd_set rfds, wfds; + struct timeval timeout; + int fd, opt, result; + int on = 1; + int off = 0; + struct sockaddr_in6 listen_addr; + struct sigaction sa; + uint16_t port = htons(DEFAULT_PORT); + + memset(&listen_addr, 0, sizeof(struct sockaddr_in6)); + + /* fill extra field for 4.4BSD-based systems (see RFC 3493, section 3.4) */ +#if defined(SIN6_LEN) || defined(HAVE_SOCKADDR_IN6_SIN6_LEN) + listen_addr.sin6_len = sizeof(struct sockaddr_in6); +#endif + + listen_addr.sin6_family = AF_INET6; + listen_addr.sin6_addr = in6addr_any; + + while ((opt = getopt(argc, argv, "A:p:v:")) != -1) { + switch (opt) { + case 'A' : + if (resolve_address(optarg, (struct sockaddr *)&listen_addr) < 0) { + fprintf(stderr, "cannot resolve address\n"); + exit(-1); + } + break; + case 'p' : + port = htons(atoi(optarg)); + break; + case 'v' : + log_level = strtol(optarg, NULL, 10); + break; + default: + usage(argv[0], dtls_package_version()); + exit(1); + } + } + listen_addr.sin6_port = port; + + dtls_set_log_level(log_level); + + /* init socket and set it to non-blocking */ + fd = socket(listen_addr.sin6_family, SOCK_DGRAM, 0); + + if (fd < 0) { + dtls_alert("socket: %s\n", strerror(errno)); + return 0; + } + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) { + dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno)); + } +#if 0 + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { + dtls_alert("fcntl: %s\n", strerror(errno)); + goto error; + } +#endif + on = 1; + if (listen_addr.sin6_family == AF_INET6) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) < 0) { + dtls_alert("setsockopt IPV6_V6ONLY: %s\n", strerror(errno)); + } +#ifdef IPV6_RECVPKTINFO + if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on) ) < 0) { +#else /* IPV6_RECVPKTINFO */ + if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on) ) < 0) { +#endif /* IPV6_RECVPKTINFO */ + dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno)); + } + } + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) < 0) { + dtls_alert("setsockopt IP_PKTINFO: %s\n", strerror(errno)); + } + + if (bind(fd, (struct sockaddr *)&listen_addr, + listen_addr.sin6_family == AF_INET ? sizeof(struct sockaddr_in) : + sizeof(listen_addr)) < 0) { + dtls_alert("bind: %s\n", strerror(errno)); + goto error; + } + + dtls_init(); + + memset (&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = dtls_handle_signal; + sa.sa_flags = 0; + sigaction (SIGINT, &sa, NULL); + sigaction (SIGTERM, &sa, NULL); + /* So we do not exit on a SIGPIPE */ + sa.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &sa, NULL); + + the_context = dtls_new_context(&fd); + + dtls_set_handler(the_context, &cb); + + while (1) { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + FD_SET(fd, &rfds); + /* FD_SET(fd, &wfds); */ + + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + result = select( fd+1, &rfds, &wfds, 0, &timeout); + + if (result < 0) { /* error */ + if (errno != EINTR) + perror("select"); + } else if (result == 0) { /* timeout */ + } else { /* ok */ + if (FD_ISSET(fd, &wfds)) + ; + else if (FD_ISSET(fd, &rfds)) { + dtls_handle_read(the_context); + } + } + } + + error: + dtls_free_context(the_context); + exit(0); +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/netq-test.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/netq-test.c new file mode 100644 index 000000000..901a3424a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/netq-test.c @@ -0,0 +1,123 @@ +#include +#include + +#include "utlist.h" +#include "netq.h" + +void +dump_queue(struct netq_t *queue) { + struct netq_t *p; + int i = 0; + + if (!queue) { + printf("(null)\n"); + } else { + LL_FOREACH(queue, p) { + printf("node #%d, timeout: %d\n", i++, p->t); + } + } +} + +int main(int argc, char **argv) { + struct netq_t *nq = NULL, *node; + int i; + + clock_time_t timestamps[] = { 300, 100, 200, 400, 500 }; + + for (i = 0; i < sizeof(timestamps)/sizeof(clock_time_t); i++) { + node = netq_node_new(0); + + if (!node) { + fprintf(stderr, "E: cannot create node #%d\n", i); + exit(EXIT_FAILURE); + } + + node->t = timestamps[i]; + + if (!netq_insert_node(&nq, node)) { + fprintf(stderr, "E: cannot add node to nodelist #%d\n", i); + exit(EXIT_FAILURE); + } + } + + printf("------------------------------------------------------------------------\n"); + printf("initial queue:\n"); + dump_queue(nq); + + printf("------------------------------------------------------------------------\n"); + printf("pop first element:\n"); + node = netq_pop_first(&nq); + + assert(node); + printf("first node's timeout is %d\n", node->t); + dump_queue(nq); + + netq_node_free(node); + + printf("------------------------------------------------------------------------\n"); + printf("queue head:\n"); + node = netq_head(&nq); + + printf("head's timeout is %d\n", node->t); + dump_queue(nq); + + printf("------------------------------------------------------------------------\n"); + printf("next timeout:\n"); + + node = netq_next(node); + + printf("next node's timeout is %d\n", node->t); + + printf("------------------------------------------------------------------------\n"); + printf("remove next:\n"); + + netq_remove(&nq, node); + dump_queue(nq); + + netq_node_free(node); + + printf("------------------------------------------------------------------------\n"); + printf("insert new item (timeout 50):\n"); + node = netq_node_new(0); + + assert(node); + node->t = 50; + + netq_insert_node(&nq, node); + dump_queue(nq); + + printf("------------------------------------------------------------------------\n"); + printf("insert new item (timeout 350):\n"); + node = netq_node_new(0); + + assert(node); + node->t = 350; + + netq_insert_node(&nq, node); + dump_queue(nq); + + printf("------------------------------------------------------------------------\n"); + printf("insert new item (timeout 1000):\n"); + node = netq_node_new(0); + + assert(node); + node->t = 1000; + + netq_insert_node(&nq, node); + dump_queue(nq); + + printf("------------------------------------------------------------------------\n"); + printf("remove all:\n"); + + netq_delete_all(&nq); + dump_queue(nq); + + printf("------------------------------------------------------------------------\n"); + printf("pop first element of empty queue:\n"); + node = netq_pop_first(&nq); + + assert(node == NULL); + dump_queue(nq); + + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/pcap.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/pcap.c new file mode 100644 index 000000000..90f7f180b --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/pcap.c @@ -0,0 +1,478 @@ +#include +#include +#include +#include + +#include "tinydtls.h" +#include "dtls_debug.h" +#include "dtls.h" + +#define TRANSPORT_HEADER_SIZE (14+20+8) /* Ethernet + IP + UDP */ + +/* the pre_master_secret is generated from the PSK at startup */ +unsigned char pre_master_secret[60]; +size_t pre_master_len = 0; + +unsigned char master_secret[DTLS_MASTER_SECRET_LENGTH]; +size_t master_secret_len = 0; + +dtls_security_parameters_t security_params[2]; +int config = 0; +unsigned int epoch[2] = { 0, 0 }; + +#if DTLS_VERSION == 0xfeff +dtls_hash_t hs_hash[2]; +#elif DTLS_VERSION == 0xfefd +dtls_hash_t hs_hash[1]; +#endif + +static inline void +update_hash(uint8 *record, size_t rlength, + uint8 *data, size_t data_length) { + int i; + + if (!hs_hash[0]) + return; + + for (i = 0; i < sizeof(hs_hash) / sizeof(dtls_hash_t *); ++i) { + dtls_hash_update(hs_hash[i], data, data_length); + } +} + +static inline void +finalize_hash(uint8 *buf) { +#if DTLS_VERSION == 0xfeff + unsigned char statebuf[sizeof(md5_state_t) + sizeof(SHA_CTX)]; +#elif DTLS_VERSION == 0xfefd + unsigned char statebuf[sizeof(dtls_sha256_ctx)]; +#endif + + if (!hs_hash[0]) + return; + + /* temporarily store hash status for roll-back after finalize */ +#if DTLS_VERSION == 0xfeff + memcpy(statebuf, hs_hash[0], sizeof(md5_state_t)); + memcpy(statebuf + sizeof(md5_state_t), + hs_hash[1], + sizeof(SHA_CTX)); +#elif DTLS_VERSION == 0xfefd + memcpy(statebuf, hs_hash[0], sizeof(statebuf)); +#endif + + dtls_hash_finalize(buf, hs_hash[0]); +#if DTLS_VERSION == 0xfeff + dtls_hash_finalize(buf + 16, hs_hash[1]); +#endif + + /* restore hash status */ +#if DTLS_VERSION == 0xfeff + memcpy(hs_hash[0], statebuf, sizeof(md5_state_t)); + memcpy(hs_hash[1], + statebuf + sizeof(md5_state_t), + sizeof(SHA_CTX)); +#elif DTLS_VERSION == 0xfefd + memcpy(hs_hash[0], statebuf, sizeof(statebuf)); +#endif +} + +static inline void +clear_hash() { + int i; + + for (i = 0; i < sizeof(hs_hash) / sizeof(dtls_hash_t *); ++i) + free(hs_hash[i]); + memset(hs_hash, 0, sizeof(hs_hash)); +} + +#undef CURRENT_CONFIG +#undef OTHER_CONFIG +#undef SWITCH_CONFIG +#define CURRENT_CONFIG (&security_params[config]) +#define OTHER_CONFIG (&security_params[!(config & 0x01)]) +#define SWITCH_CONFIG (config = !(config & 0x01)) + +int +pcap_verify(dtls_security_parameters_t *sec, + int is_client, + const unsigned char *record, size_t record_length, + const unsigned char *cleartext, size_t cleartext_length) { + + unsigned char mac[DTLS_HMAC_MAX]; + dtls_hmac_context_t hmac_ctx; + int ok; + + if (cleartext_length < dtls_kb_digest_size(sec)) + return 0; + + dtls_hmac_init(&hmac_ctx, + is_client + ? dtls_kb_client_mac_secret(sec) + : dtls_kb_server_mac_secret(sec), + dtls_kb_mac_secret_size(sec)); + + cleartext_length -= dtls_kb_digest_size(sec); + + /* calculate MAC even if padding is wrong */ + dtls_mac(&hmac_ctx, + record, /* the pre-filled record header */ + cleartext, cleartext_length, + mac); + + ok = memcmp(mac, cleartext + cleartext_length, + dtls_kb_digest_size(sec)) == 0; +#ifndef NDEBUG + printf("MAC (%s): ", ok ? "valid" : "invalid"); + dump(mac, dtls_kb_digest_size(sec)); + printf("\n"); +#endif + return ok; +} + +int +decrypt_verify(int is_client, const uint8 *packet, size_t length, + uint8 **cleartext, size_t *clen) { + int res, ok = 0; + dtls_cipher_context_t *cipher; + + static unsigned char buf[1000]; + + switch (CURRENT_CONFIG->cipher) { + case AES128: /* TLS_PSK_WITH_AES128_CBC_SHA */ + *cleartext = buf; + *clen = length - sizeof(dtls_record_header_t); + + if (is_client) + cipher = CURRENT_CONFIG->read_cipher; + else + cipher = CURRENT_CONFIG->write_cipher; + + res = dtls_decrypt(cipher, + (uint8 *)packet + sizeof(dtls_record_header_t), *clen, + buf, NULL, 0); + + if (res < 0) { + warn("decryption failed!\n"); + } else { + ok = pcap_verify(CURRENT_CONFIG, is_client, (uint8 *)packet, length, + *cleartext, res); + + if (ok) + *clen = res - dtls_kb_digest_size(CURRENT_CONFIG); + } + break; + default: /* no cipher suite selected */ + *cleartext = (uint8 *)packet + sizeof(dtls_record_header_t); + *clen = length - sizeof(dtls_record_header_t); + + ok = 1; + } + + if (ok) + printf("verify OK\n"); + else + printf("verification failed!\n"); + return ok; +} + +#define SKIP_ETH_HEADER(M,L) \ + if ((L) < 14) \ + return; \ + else { \ + (M) += 14; \ + (L) -= 14; \ + } + +#define SKIP_IP_HEADER(M,L) \ + if (((M)[0] & 0xF0) == 0x40) { /* IPv4 */ \ + (M) += (M[0] & 0x0F) * 4; \ + (L) -= (M[0] & 0x0F) * 4; \ + } else \ + if (((M)[0] & 0xF0) == 0x60) { /* IPv6 */ \ + (M) += 40; \ + (L) -= 40; \ + } + +#define SKIP_UDP_HEADER(M,L) { \ + (M) += 8; \ + (L) -= 8; \ + } + +void +handle_packet(const u_char *packet, int length) { + static int n = 0; + static unsigned char initial_hello[] = { + 0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + uint8 *data; + size_t data_length, rlen; + int i, res; +#if DTLS_VERSION == 0xfeff +#ifndef SHA1_DIGEST_LENGTH +#define SHA1_DIGEST_LENGTH 20 +#endif + uint8 hash_buf[16 + SHA1_DIGEST_LENGTH]; +#elif DTLS_VERSION == 0xfefd + uint8 hash_buf[DTLS_SHA256_DIGEST_LENGTH]; +#endif +#define verify_data_length 12 + int is_client; + n++; + + SKIP_ETH_HEADER(packet, length); + SKIP_IP_HEADER(packet, length); + + /* determine from port if this is a client */ + is_client = dtls_uint16_to_int(packet) != 20220; + + SKIP_UDP_HEADER(packet, length); + + while (length) { + rlen = dtls_uint16_to_int(packet + 11) + sizeof(dtls_record_header_t); + + if (!rlen) { + fprintf(stderr, "invalid length!\n"); + return; + } + + /* skip packet if it is from a different epoch */ + if (dtls_uint16_to_int(packet + 3) != epoch[is_client]) + goto next; + + res = decrypt_verify(is_client, packet, rlen, + &data, &data_length); + + if (res <= 0) + goto next; + + printf("packet %d (from %s):\n", n, is_client ? "client" : "server"); + hexdump(packet, sizeof(dtls_record_header_t)); + printf("\n"); + hexdump(data, data_length); + printf("\n"); + + if (packet[0] == 22 && data[0] == 1) { /* ClientHello */ + if (memcmp(packet, initial_hello, sizeof(initial_hello)) == 0) + goto next; + + memcpy(dtls_kb_client_iv(OTHER_CONFIG), data + 14, 32); + + clear_hash(); +#if DTLS_VERSION == 0xfeff + hs_hash[0] = dtls_new_hash(HASH_MD5); + hs_hash[1] = dtls_new_hash(HASH_SHA1); + + hs_hash[0]->init(hs_hash[0]->data); + hs_hash[1]->init(hs_hash[1]->data); +#elif DTLS_VERSION == 0xfefd + dtls_hash_init(hs_hash[0]); +#endif + } + + if (packet[0] == 22 && data[0] == 2) { /* ServerHello */ + memcpy(dtls_kb_server_iv(OTHER_CONFIG), data + 14, 32); + /* FIXME: search in ciphers */ + OTHER_CONFIG->cipher = TLS_PSK_WITH_AES_128_CCM_8; + } + + if (packet[0] == 20 && data[0] == 1) { /* ChangeCipherSpec */ + printf("client random: "); + dump(dtls_kb_client_iv(OTHER_CONFIG), 32); + printf("\nserver random: "); + dump(dtls_kb_server_iv(OTHER_CONFIG), 32); + printf("\n"); + master_secret_len = + dtls_prf(pre_master_secret, pre_master_len, + (unsigned char *)"master secret", 13, + dtls_kb_client_iv(OTHER_CONFIG), 32, + dtls_kb_server_iv(OTHER_CONFIG), 32, + master_secret, DTLS_MASTER_SECRET_LENGTH); + + printf("master_secret:\n "); + for(i = 0; i < master_secret_len; i++) + printf("%02x", master_secret[i]); + printf("\n"); + + /* create key_block from master_secret + * key_block = PRF(master_secret, + "key expansion" + server_random + client_random) */ + dtls_prf(master_secret, master_secret_len, + (unsigned char *)"key expansion", 13, + dtls_kb_server_iv(OTHER_CONFIG), 32, + dtls_kb_client_iv(OTHER_CONFIG), 32, + OTHER_CONFIG->key_block, + dtls_kb_size(OTHER_CONFIG)); + + OTHER_CONFIG->read_cipher = + dtls_cipher_new(OTHER_CONFIG->cipher, + dtls_kb_client_write_key(OTHER_CONFIG), + dtls_kb_key_size(OTHER_CONFIG)); + + if (!OTHER_CONFIG->read_cipher) { + warn("cannot create read cipher\n"); + } else { + dtls_cipher_set_iv(OTHER_CONFIG->read_cipher, + dtls_kb_client_iv(OTHER_CONFIG), + dtls_kb_iv_size(OTHER_CONFIG)); + } + + OTHER_CONFIG->write_cipher = + dtls_cipher_new(OTHER_CONFIG->cipher, + dtls_kb_server_write_key(OTHER_CONFIG), + dtls_kb_key_size(OTHER_CONFIG)); + + if (!OTHER_CONFIG->write_cipher) { + warn("cannot create write cipher\n"); + } else { + dtls_cipher_set_iv(OTHER_CONFIG->write_cipher, + dtls_kb_server_iv(OTHER_CONFIG), + dtls_kb_iv_size(OTHER_CONFIG)); + } + + /* if (is_client) */ + SWITCH_CONFIG; + epoch[is_client]++; + + printf("key_block:\n"); + printf(" client_MAC_secret:\t"); + dump(dtls_kb_client_mac_secret(CURRENT_CONFIG), + dtls_kb_mac_secret_size(CURRENT_CONFIG)); + printf("\n"); + + printf(" server_MAC_secret:\t"); + dump(dtls_kb_server_mac_secret(CURRENT_CONFIG), + dtls_kb_mac_secret_size(CURRENT_CONFIG)); + printf("\n"); + + printf(" client_write_key:\t"); + dump(dtls_kb_client_write_key(CURRENT_CONFIG), + dtls_kb_key_size(CURRENT_CONFIG)); + printf("\n"); + + printf(" server_write_key:\t"); + dump(dtls_kb_server_write_key(CURRENT_CONFIG), + dtls_kb_key_size(CURRENT_CONFIG)); + printf("\n"); + + printf(" client_IV:\t\t"); + dump(dtls_kb_client_iv(CURRENT_CONFIG), + dtls_kb_iv_size(CURRENT_CONFIG)); + printf("\n"); + + printf(" server_IV:\t\t"); + dump(dtls_kb_server_iv(CURRENT_CONFIG), + dtls_kb_iv_size(CURRENT_CONFIG)); + printf("\n"); + + } + + if (packet[0] == 22) { + if (data[0] == 20) { /* Finished */ + finalize_hash(hash_buf); + /* clear_hash(); */ + + update_hash((unsigned char *)packet, sizeof(dtls_record_header_t), + data, data_length); + + dtls_prf(master_secret, master_secret_len, + is_client + ? (unsigned char *)"client finished" + : (unsigned char *)"server finished" + , 15, + hash_buf, sizeof(hash_buf), + NULL, 0, + data + sizeof(dtls_handshake_header_t), + verify_data_length); + printf("verify_data:\n"); + dump(data, data_length); + printf("\n"); + } else { + update_hash((unsigned char *)packet, sizeof(dtls_record_header_t), + data, data_length); + } + } + + if (packet[0] == 23) { /* Application Data */ + printf("Application Data:\n"); + dump(data, data_length); + printf("\n"); + } + + next: + length -= rlen; + packet += rlen; + } +} + +void init() { + memset(security_params, 0, sizeof(security_params)); + CURRENT_CONFIG->cipher = -1; + + memset(hs_hash, 0, sizeof(hs_hash)); + + /* set pre_master_secret to default if no PSK was given */ + if (!pre_master_len) { + /* unsigned char psk[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; */ + pre_master_len = + dtls_pre_master_secret((unsigned char *)"secretPSK", 9, + pre_master_secret); + } +} + +int main(int argc, char **argv) { + pcap_t *pcap; + char errbuf[PCAP_ERRBUF_SIZE]; + struct pcap_pkthdr *pkthdr; + const u_char *packet; + int res = 0; + int c, option_index = 0; + + static struct option opts[] = { + { "psk", 1, 0, 'p' }, + { 0, 0, 0, 0 } + }; + + /* handle command line options */ + while (1) { + c = getopt_long(argc, argv, "p:", opts, &option_index); + if (c == -1) + break; + + switch (c) { + case 'p': + pre_master_len = dtls_pre_master_secret((unsigned char *)optarg, + strlen(optarg), pre_master_secret); + break; + } + } + + if (argc <= optind) { + fprintf(stderr, "usage: %s [-p|--psk PSK] pcapfile\n", argv[0]); + return -1; + } + + init(); + + pcap = pcap_open_offline(argv[optind], errbuf); + if (!pcap) { + fprintf(stderr, "pcap_open_offline: %s\n", errbuf); + return -2; + } + + for (;;) { + res = pcap_next_ex(pcap, &pkthdr, &packet); + + switch(res) { + case -2: goto done; + case -1: pcap_perror(pcap, "read packet"); break; + case 1: handle_packet(packet, pkthdr->caplen); break; + default: + ; + } + } + done: + + pcap_close(pcap); + + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ccm.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ccm.c new file mode 100644 index 000000000..f54df8f91 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ccm.c @@ -0,0 +1,215 @@ +/******************************************************************************* + * + * Copyright (c) 2020 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + */ + +#include + +#include "dtls_config.h" +#include "test_ccm.h" + +#include "tinydtls.h" +#include "ccm.h" +#include "crypto.h" +#include "../ccm-testdata.c" + +#include + +static uint8_t buf[1024]; + +static void +t_test_encrypt_message(void) { + long int len; + size_t n; + rijndael_ctx ctx; + + for (n = 0; n < sizeof(data)/sizeof(struct test_vector); ++n) { + + CU_ASSERT(rijndael_set_key_enc_only(&ctx, data[n].key, 8*sizeof(data[n].key)) == 0); + + assert(data[n].r_lm - data[n].la <= sizeof(buf)); + memcpy(buf, data[n].msg + data[n].la, data[n].lm - data[n].la); + len = dtls_ccm_encrypt_message(&ctx, data[n].M, data[n].L, data[n].nonce, + buf, + data[n].lm - data[n].la, + data[n].msg, data[n].la); + + CU_ASSERT((size_t)len == data[n].r_lm - data[n].la); + CU_ASSERT(memcmp(buf, data[n].result + data[n].la, len) == 0); + } +} + +static void +t_test_decrypt_message(void) { + size_t n; + int len; + rijndael_ctx ctx; + + for (n = 0; n < sizeof(data)/sizeof(struct test_vector); ++n) { + + CU_ASSERT(rijndael_set_key_enc_only(&ctx, data[n].key, 8*sizeof(data[n].key)) == 0); + + assert(data[n].r_lm - data[n].la <= sizeof(buf)); + memcpy(buf, data[n].result + data[n].la, data[n].r_lm - data[n].la); + + len = dtls_ccm_decrypt_message(&ctx, data[n].M, data[n].L, data[n].nonce, + buf, data[n].r_lm - data[n].la, + data[n].result, data[n].la); + + CU_ASSERT((size_t)len == data[n].lm - data[n].la); + CU_ASSERT(memcmp(buf, data[n].msg + data[n].la, len) == 0); + } +} + +static void +t_test_dtls_encrypt_params(void) { + size_t n; + int len; + + for (n = 0; n < sizeof(data)/sizeof(struct test_vector); ++n) { + dtls_ccm_params_t params = + { .nonce = data[n].nonce, + .tag_length = data[n].M, + .l = data[n].L + }; + + len = dtls_encrypt_params(¶ms, + data[n].msg + data[n].la, + data[n].lm - data[n].la, + buf, + data[n].key, + sizeof(data[n].key), + data[n].msg, + data[n].la); + + CU_ASSERT((size_t)len == data[n].r_lm - data[n].la); + CU_ASSERT(memcmp(data[n].result + data[n].la, buf, len) == 0); + } +} + +static void +t_test_dtls_decrypt_params(void) { + size_t n; + int len; + + for (n = 0; n < sizeof(data)/sizeof(struct test_vector); ++n) { + dtls_ccm_params_t params = + { .nonce = data[n].nonce, + .tag_length = data[n].M, + .l = data[n].L + }; + + assert(data[n].r_lm - data[n].la - data[n].M <= sizeof(buf)); + + len = dtls_decrypt_params(¶ms, + data[n].result + data[n].la, + data[n].r_lm - data[n].la, + buf, + data[n].key, + sizeof(data[n].key), + data[n].result, + data[n].la); + + CU_ASSERT((size_t)len == data[n].lm - data[n].la); + CU_ASSERT(memcmp(data[n].msg + data[n].la, buf, len) == 0); + } +} + +static void +t_test_dtls_encrypt(void) { + size_t n; + int len; + + for (n = 0; n < sizeof(data)/sizeof(struct test_vector); ++n) { + /* The backwards-compatible dtls_encrypt() and dtls_decrypt() + * only handle cipher suites with M=8 and L=3. */ + if ((data[n].M == 8) && ((15 - data[n].L) == DTLS_CCM_NONCE_SIZE)) { + len = dtls_encrypt(data[n].msg + data[n].la, + data[n].lm - data[n].la, + buf, + data[n].nonce, + data[n].key, + sizeof(data[n].key), + data[n].msg, + data[n].la); + CU_ASSERT((size_t)len == data[n].r_lm - data[n].la); + CU_ASSERT(memcmp(data[n].result + data[n].la, buf, len) == 0); + } + } +} + +static void +t_test_dtls_decrypt(void) { + size_t n; + int len; + + for (n = 0; n < sizeof(data)/sizeof(struct test_vector); ++n) { + /* The backwards-compatible dtls_encrypt() and dtls_decrypt() + * only handle cipher suites with M=8 and L=3. */ + if ((data[n].M == 8) && ((15 - data[n].L) == DTLS_CCM_NONCE_SIZE)) { + assert(data[n].r_lm - data[n].la - data[n].M <= sizeof(buf)); + + len = dtls_decrypt(data[n].result + data[n].la, data[n].r_lm - data[n].la, + buf, + data[n].nonce, + data[n].key, + sizeof(data[n].key), + data[n].msg, data[n].la); + CU_ASSERT((size_t)len == data[n].r_lm - data[n].la - data[n].M); + CU_ASSERT(memcmp(data[n].msg + data[n].la, buf, len) == 0); + } + } +} + +CU_pSuite +t_init_ccm_tests(void) { + CU_pSuite suite; + + suite = CU_add_suite("CCM", NULL, NULL); + if (!suite) { /* signal error */ + fprintf(stderr, "W: cannot add CCM test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + + if (!CU_ADD_TEST(suite,t_test_encrypt_message)) { + fprintf(stderr, "W: cannot add t_dtls_encrypt_message (%s)\n", + CU_get_error_msg()); + } + + if (!CU_ADD_TEST(suite,t_test_decrypt_message)) { + fprintf(stderr, "W: cannot add t_dtls_decrypt_message (%s)\n", + CU_get_error_msg()); + } + + if (!CU_ADD_TEST(suite,t_test_dtls_encrypt_params)) { + fprintf(stderr, "W: cannot add t_dtls_encrypt_params (%s)\n", + CU_get_error_msg()); + } + + if (!CU_ADD_TEST(suite,t_test_dtls_decrypt_params)) { + fprintf(stderr, "W: cannot add t_dtls_decrypt_params (%s)\n", + CU_get_error_msg()); + } + + if (!CU_ADD_TEST(suite,t_test_dtls_encrypt)) { + fprintf(stderr, "W: cannot add t_dtls_encrypt (%s)\n", + CU_get_error_msg()); + } + + if (!CU_ADD_TEST(suite,t_test_dtls_decrypt)) { + fprintf(stderr, "W: cannot add t_dtls_decrypt (%s)\n", + CU_get_error_msg()); + } + + return suite; +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ccm.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ccm.h new file mode 100644 index 000000000..5a8d933d6 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ccm.h @@ -0,0 +1,15 @@ +/******************************************************************************* + * + * Copyright (c) 2020 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + */ + +#include + +CU_pSuite t_init_ccm_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ecc.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ecc.c new file mode 100644 index 000000000..a2dc99fe3 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ecc.c @@ -0,0 +1,242 @@ +/******************************************************************************* + * + * Copyright (c) 2020 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + */ + +#include + +#include "dtls_config.h" +#include "dtls_prng.h" +#include "test_ecc.h" +#include "ecc/ecc.h" + +#include "tinydtls.h" +#include "crypto.h" + +#include + +//These are testvalues taken from the NIST P-256 definition +//6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296 +uint32_t BasePointx[8] = { 0xd898c296, 0xf4a13945, 0x2deb33a0, 0x77037d81, + 0x63a440f2, 0xf8bce6e5, 0xe12c4247, 0x6b17d1f2}; + +//4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5 +uint32_t BasePointy[8] = { 0x37bf51f5, 0xcbb64068, 0x6b315ece, 0x2bce3357, + 0x7c0f9e16, 0x8ee7eb4a, 0xfe1a7f9b, 0x4fe342e2}; + +//de2444be bc8d36e6 82edd27e 0f271508 617519b3 221a8fa0 b77cab39 89da97c9 +uint32_t Sx[8] = { 0x89da97c9, 0xb77cab39, 0x221a8fa0, 0x617519b3, + 0x0f271508, 0x82edd27e, 0xbc8d36e6, 0xde2444be}; + +//c093ae7f f36e5380 fc01a5aa d1e66659 702de80f 53cec576 b6350b24 3042a256 +uint32_t Sy[8] = { 0x3042a256, 0xb6350b24, 0x53cec576, 0x702de80f, + 0xd1e66659, 0xfc01a5aa, 0xf36e5380, 0xc093ae7f}; + +//55a8b00f 8da1d44e 62f6b3b2 5316212e 39540dc8 61c89575 bb8cf92e 35e0986b +uint32_t Tx[8] = { 0x35e0986b, 0xbb8cf92e, 0x61c89575, 0x39540dc8, + 0x5316212e, 0x62f6b3b2, 0x8da1d44e, 0x55a8b00f}; + +//5421c320 9c2d6c70 4835d82a c4c3dd90 f61a8a52 598b9e7a b656e9d8 c8b24316 +uint32_t Ty[8] = { 0xc8b24316, 0xb656e9d8, 0x598b9e7a, 0xf61a8a52, + 0xc4c3dd90, 0x4835d82a, 0x9c2d6c70, 0x5421c320}; + +//c51e4753 afdec1e6 b6c6a5b9 92f43f8d d0c7a893 3072708b 6522468b 2ffb06fd +uint32_t secret[8] = { 0x2ffb06fd, 0x6522468b, 0x3072708b, 0xd0c7a893, + 0x92f43f8d, 0xb6c6a5b9, 0xafdec1e6, 0xc51e4753}; + +//72b13dd4 354b6b81 745195e9 8cc5ba69 70349191 ac476bd4 553cf35a 545a067e +uint32_t resultAddx[8] = { 0x545a067e, 0x553cf35a, 0xac476bd4, 0x70349191, + 0x8cc5ba69, 0x745195e9, 0x354b6b81, 0x72b13dd4}; + +//8d585cbb 2e1327d7 5241a8a1 22d7620d c33b1331 5aa5c9d4 6d013011 744ac264 +uint32_t resultAddy[8] = { 0x744ac264, 0x6d013011, 0x5aa5c9d4, 0xc33b1331, + 0x22d7620d, 0x5241a8a1, 0x2e1327d7, 0x8d585cbb}; + +//7669e690 1606ee3b a1a8eef1 e0024c33 df6c22f3 b17481b8 2a860ffc db6127b0 +uint32_t resultDoublex[8] = { 0xdb6127b0, 0x2a860ffc, 0xb17481b8, 0xdf6c22f3, + 0xe0024c33, 0xa1a8eef1, 0x1606ee3b, 0x7669e690}; + +//fa878162 187a54f6 c39f6ee0 072f33de 389ef3ee cd03023d e10ca2c1 db61d0c7 +uint32_t resultDoubley[8] = { 0xdb61d0c7, 0xe10ca2c1, 0xcd03023d, 0x389ef3ee, + 0x072f33de, 0xc39f6ee0, 0x187a54f6, 0xfa878162}; + +//51d08d5f 2d427888 2946d88d 83c97d11 e62becc3 cfc18bed acc89ba3 4eeca03f +uint32_t resultMultx[8] = { 0x4eeca03f, 0xacc89ba3, 0xcfc18bed, 0xe62becc3, + 0x83c97d11, 0x2946d88d, 0x2d427888, 0x51d08d5f}; + +//75ee68eb 8bf626aa 5b673ab5 1f6e744e 06f8fcf8 a6c0cf30 35beca95 6a7b41d5 +uint32_t resultMulty[8] = { 0x6a7b41d5, 0x35beca95, 0xa6c0cf30, 0x06f8fcf8, + 0x1f6e744e, 0x5b673ab5, 0x8bf626aa, 0x75ee68eb}; + +static const uint32_t ecdsaTestMessage[] = { 0x65637572, 0x20612073, 0x68206F66, 0x20686173, 0x69732061, 0x68697320, 0x6F2C2054, 0x48616C6C}; + +static const uint32_t ecdsaTestSecret[] = {0x94A949FA, 0x401455A1, 0xAD7294CA, 0x896A33BB, 0x7A80E714, 0x4321435B, 0x51247A14, 0x41C1CB6B}; + +static const uint32_t ecdsaTestRand1[] = { 0x1D1E1F20, 0x191A1B1C, 0x15161718, 0x11121314, 0x0D0E0F10, 0x090A0B0C, 0x05060708, 0x01020304}; +static const uint32_t ecdsaTestresultR1[] = { 0xC3B4035F, 0x515AD0A6, 0xBF375DCA, 0x0CC1E997, 0x7F54FDCD, 0x04D3FECA, 0xB9E396B9, 0x515C3D6E}; +static const uint32_t ecdsaTestresultS1[] = { 0x5366B1AB, 0x0F1DBF46, 0xB0C8D3C4, 0xDB755B6F, 0xB9BF9243, 0xE644A8BE, 0x55159A59, 0x6F9E52A6}; + +static const uint32_t ecdsaTestRand2[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x01FFFFFF}; +static const uint32_t ecdsaTestresultR2[] = { 0x14146C91, 0xE878724D, 0xCD4FF928, 0xCC24BC04, 0xAC403390, 0x650C0060, 0x4A30B3F1, 0x9C69B726}; +static const uint32_t ecdsaTestresultS2[] = { 0x433AAB6F, 0x808250B1, 0xE46F90F4, 0xB342E972, 0x18B2F7E4, 0x2DB981A2, 0x6A288FA4, 0x41CF59DB}; + +static void +t_test_ecc_add(void) { + uint32_t tempx[8]; + uint32_t tempy[8]; + + ecc_ec_add(Tx, Ty, Sx, Sy, tempx, tempy); + CU_ASSERT(ecc_isSame(tempx, resultAddx, arrayLength)); + CU_ASSERT(ecc_isSame(tempy, resultAddy, arrayLength)); +} + +static void +t_test_ecc_double(void) { + uint32_t tempx[8]; + uint32_t tempy[8]; + + ecc_ec_double(Sx, Sy, tempx, tempy); + CU_ASSERT(ecc_isSame(tempx, resultDoublex, arrayLength)); + CU_ASSERT(ecc_isSame(tempy, resultDoubley, arrayLength)); +} + +static void +t_test_ecc_mult(void) { + uint32_t tempx[8]; + uint32_t tempy[8]; + + ecc_ec_mult(Sx, Sy, secret, tempx, tempy); + CU_ASSERT(ecc_isSame(tempx, resultMultx, arrayLength)); + CU_ASSERT(ecc_isSame(tempy, resultMulty, arrayLength)); +} + +static void +t_test_ecc_dh(void) { + uint32_t tempx[8]; + uint32_t tempy[8]; + uint32_t tempAx2[8]; + uint32_t tempAy2[8]; + uint32_t tempBx1[8]; + uint32_t tempBy1[8]; + uint32_t tempBx2[8]; + uint32_t tempBy2[8]; + uint32_t secretA[8]; + uint32_t secretB[8]; + int ret; + + ret = dtls_prng((void *)secretA, sizeof(secretA)); + CU_ASSERT(ret > 1); + + ret = dtls_prng((void *)secretB, sizeof(secretB)); + CU_ASSERT(ret > 1); + + ecc_ec_mult(BasePointx, BasePointy, secretA, tempx, tempy); + ecc_ec_mult(BasePointx, BasePointy, secretB, tempBx1, tempBy1); + //public key exchange + ecc_ec_mult(tempBx1, tempBy1, secretA, tempAx2, tempAy2); + ecc_ec_mult(tempx, tempy, secretB, tempBx2, tempBy2); + CU_ASSERT(ecc_isSame(tempAx2, tempBx2, arrayLength)); + CU_ASSERT(ecc_isSame(tempAy2, tempBy2, arrayLength)); +} + +static void +t_test_ecc_ecdsa(void) { + int ret; + uint32_t tempx[9]; + uint32_t tempy[9]; + uint32_t pub_x[8]; + uint32_t pub_y[8]; + + ecc_ec_mult(BasePointx, BasePointy, ecdsaTestSecret, pub_x, pub_y); + + ret = ecc_ecdsa_sign(ecdsaTestSecret, ecdsaTestMessage, ecdsaTestRand1, tempx, tempy); + assert(ecc_isSame(tempx, ecdsaTestresultR1, arrayLength)); + assert(ecc_isSame(tempy, ecdsaTestresultS1, arrayLength)); + assert(ret == 0); + + ret = ecc_ecdsa_validate(pub_x, pub_y, ecdsaTestMessage, tempx, tempy); + assert(ret == 0); + + ret = ecc_ecdsa_sign(ecdsaTestSecret, ecdsaTestMessage, ecdsaTestRand2, tempx, tempy); + assert(ecc_isSame(tempx, ecdsaTestresultR2, arrayLength)); + assert(ecc_isSame(tempy, ecdsaTestresultS2, arrayLength)); + assert(ret == 0); + + ret = ecc_ecdsa_validate(pub_x, pub_y, ecdsaTestMessage, tempx, tempy); + assert(ret == 0); +} + +static void +t_test_ecc_ecdsa0(void) { + int ret; + uint32_t tempx[9] = {0x433aab6f, 0x36dfe2c6, 0xf9f2ed29, 0xda0a9a8f, 0x62684e91, 0x6375ba10, 0x300c28c5, 0xe47cfbf2, 0x5fa58f52}; + uint32_t tempy[9]; + uint32_t pub_x[8]; + uint32_t pub_y[8]; + + ecc_ec_mult(BasePointx, BasePointy, ecdsaTestSecret, pub_x, pub_y); + + ret = ecc_ecdsa_sign(ecdsaTestSecret, ecdsaTestMessage, ecdsaTestRand1, tempx, tempy); + + memset(tempy, 0, sizeof(tempy)); + ret = ecc_ecdsa_validate(pub_x, pub_y, ecdsaTestMessage, tempx, tempy); + CU_ASSERT(ret == -1); +} + +CU_pSuite +t_init_ecc_tests(void) { + CU_pSuite suite; + + suite = CU_add_suite("ECC", NULL, NULL); + if (!suite) { /* signal error */ + fprintf(stderr, "W: cannot add ECC test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + + /* On POSIX system, getrandom() is used where available, ignoring + * the seed. For other platforms, the random sequence will be the + * same for each run. */ + dtls_prng_init(0); + + if (!CU_ADD_TEST(suite,t_test_ecc_add)) { + fprintf(stderr, "W: cannot add test for ECC add (%s)\n", + CU_get_error_msg()); + } + + if (!CU_ADD_TEST(suite,t_test_ecc_double)) { + fprintf(stderr, "W: cannot add test for ECC double (%s)\n", + CU_get_error_msg()); + } + + if (!CU_ADD_TEST(suite,t_test_ecc_mult)) { + fprintf(stderr, "W: cannot add test for ECC mult (%s)\n", + CU_get_error_msg()); + } + + if (!CU_ADD_TEST(suite,t_test_ecc_dh)) { + fprintf(stderr, "W: cannot add test for ECC DH (%s)\n", + CU_get_error_msg()); + } + + if (!CU_ADD_TEST(suite,t_test_ecc_ecdsa)) { + fprintf(stderr, "W: cannot add test for ECC ECDSA (%s)\n", + CU_get_error_msg()); + } + + if (!CU_ADD_TEST(suite,t_test_ecc_ecdsa0)) { + fprintf(stderr, "W: cannot add test for ECC ECDSA with invalid argument (%s)\n", + CU_get_error_msg()); + } + + return suite; +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ecc.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ecc.h new file mode 100644 index 000000000..ef6ab5232 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_ecc.h @@ -0,0 +1,15 @@ +/******************************************************************************* + * + * Copyright (c) 2020 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + */ + +#include + +CU_pSuite t_init_ecc_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_prf.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_prf.c new file mode 100644 index 000000000..1fb53f125 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_prf.c @@ -0,0 +1,287 @@ +/******************************************************************************* + * + * Copyright (c) 2022 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + */ + +#include + +#include "dtls_config.h" +#include "dtls_prng.h" +#include "test_prf.h" + +#include "tinydtls.h" +#include "crypto.h" + +#include + +/* Check against SHA256 test vector from + * https://mailarchive.ietf.org/arch/msg/tls/fzVCzk-z3FShgGJ6DOXqM1ydxms/ + */ +static void +t_test_prf0(void) { + const uint8_t key[] = { + 0x9b, 0xbe, 0x43, 0x6b, 0xa9, 0x40, 0xf0, 0x17, + 0xb1, 0x76, 0x52, 0x84, 0x9a, 0x71, 0xdb, 0x35 + }; + const uint8_t label[] = { + 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c + }; + const uint8_t random1[] = { + 0xa0, 0xba, 0x9f, 0x93, 0x6c, 0xda, 0x31, 0x18, + 0x27, 0xa6, 0xf7, 0x96, 0xff, 0xd5, 0x19, 0x8c + }; + /* expected result */ + const uint8_t result[] = { + 0xe3, 0xf2, 0x29, 0xba, 0x72, 0x7b, 0xe1, 0x7b, + 0x8d, 0x12, 0x26, 0x20, 0x55, 0x7c, 0xd4, 0x53, + 0xc2, 0xaa, 0xb2, 0x1d, 0x07, 0xc3, 0xd4, 0x95, + 0x32, 0x9b, 0x52, 0xd4, 0xe6, 0x1e, 0xdb, 0x5a, + 0x6b, 0x30, 0x17, 0x91, 0xe9, 0x0d, 0x35, 0xc9, + 0xc9, 0xa4, 0x6b, 0x4e, 0x14, 0xba, 0xf9, 0xaf, + 0x0f, 0xa0, 0x22, 0xf7, 0x07, 0x7d, 0xef, 0x17, + 0xab, 0xfd, 0x37, 0x97, 0xc0, 0x56, 0x4b, 0xab, + 0x4f, 0xbc, 0x91, 0x66, 0x6e, 0x9d, 0xef, 0x9b, + 0x97, 0xfc, 0xe3, 0x4f, 0x79, 0x67, 0x89, 0xba, + 0xa4, 0x80, 0x82, 0xd1, 0x22, 0xee, 0x42, 0xc5, + 0xa7, 0x2e, 0x5a, 0x51, 0x10, 0xff, 0xf7, 0x01, + 0x87, 0x34, 0x7b, 0x66 + }; + uint8_t outbuf[sizeof(result)]; + size_t bytes_written; + + bytes_written = dtls_p_hash(HASH_SHA256, + key, sizeof(key), + label, sizeof(label), + random1, sizeof(random1), + NULL, 0, /* random2 */ + outbuf, sizeof(outbuf)); + + CU_ASSERT_EQUAL(bytes_written, sizeof(outbuf)); + CU_ASSERT(memcmp(outbuf, result, bytes_written) == 0); + + const size_t random2_len = sizeof(random1)/2; + const uint8_t *random2 = random1 + sizeof(random1) - random2_len; + + bytes_written = dtls_p_hash(HASH_SHA256, + key, sizeof(key), + label, sizeof(label), + random1, sizeof(random1) - random2_len, + random2, random2_len, + outbuf, sizeof(outbuf)); + + CU_ASSERT_EQUAL(bytes_written, sizeof(outbuf)); + CU_ASSERT(memcmp(outbuf, result, bytes_written) == 0); + +} + +static void +t_test_prf1(void) { + const uint8_t key[] = { 0x73, 0x65, 0x63, 0x72, 0x65, 0x74 }; + const uint8_t label[] = { + 0x21, 0x3f, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x31, 0x32, 0x33 + }; + const uint8_t random[] = { + 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d + }; + /* expected result */ + const uint8_t result[] = { + 0xd0, 0x2d, 0xf7, 0x99, 0x9a, 0xe4, 0xed, 0x36, 0xb1, + 0xba, 0x07, 0x81, 0x9e, 0x5d, 0xa8, 0xb0, 0xbe, 0x13, + 0x19, 0xe7, 0x90, 0x46, 0xe5, 0xea, 0x05, 0xa3, 0xec, + 0xff, 0xfc, 0xd9, 0x59, 0xa4, 0x1a, 0x31, 0x48, 0xda, + 0xe3, 0x84, 0x1f, 0x81, 0x69, 0xd8, 0x01, 0xd9, 0x44, + 0x1c, 0xd9, 0xed, 0x83, 0xf7, 0x8a, 0x4f, 0xa3, 0x5c, + 0x4a, 0x76, 0x4d, 0x48, 0x90, 0x32 + }; + uint8_t outbuf[sizeof(result)]; + size_t bytes_written; + + bytes_written = dtls_p_hash(HASH_SHA256, + key, sizeof(key), + label, sizeof(label), + random, sizeof(random), + NULL, 0, /* random2 */ + outbuf, sizeof(outbuf)); + + CU_ASSERT_EQUAL(bytes_written, sizeof(outbuf)); + CU_ASSERT(memcmp(outbuf, result, bytes_written) == 0); +} + +static void +t_test_prf2(void) { + const uint8_t key[] = { 0x00 }; + const uint8_t random[] = { + 0x75, 0xfc, 0x29, 0x97, 0x64, 0x38, 0x2e, 0x1b, 0x91, + 0xe0, 0x28, 0x7d, 0x6a, 0xac, 0x66, 0x98, 0x25, 0x3f, + 0x08, 0xf4, 0x06, 0x66, 0x32, 0x18, 0x9f, 0x37, 0xb9, + 0xef, 0xd1, 0x01, 0xac, 0xe2, 0x0a, 0x3b, 0xda, 0x57, + 0x9c, 0x77, 0xc7, 0xa2, 0x86, 0x4d, 0x62, 0xaa, 0xf3, + 0xf1, 0xfc, 0xd0, 0x15, 0x62, 0xc4, 0x93, 0x6e, 0x0b, + 0x09, 0x03, 0xab, 0xc2, 0x8f, 0x0a, 0xbb, 0x5f, 0xbb, + 0x89, 0x45, 0xc3, 0x50, 0xb5, 0x6e, 0x65, 0xd5, 0x80, + 0x5d, 0xb8, 0x5e, 0xb2, 0x30, 0x34, 0xee, 0x17 + }; + /* expected result */ + const uint8_t result[] = { + 0x4c, 0xd2, 0xef, 0xad, 0x3e, 0x92, 0x28, 0xee, 0xb1, + 0xb2, 0x46, 0xbb, 0x3a, 0x80, 0xf0, 0x19, 0xde, 0x4e, + 0xfd, 0xbc, 0x8b, 0x2a, 0x36, 0xf4, 0xb1, 0x97, 0x5f, + 0xc9, 0x94, 0xb0, 0xc9, 0x68, 0x4f, 0xfa, 0x4f, 0x09, + 0x36, 0x9a, 0x89, 0x8f, 0xa4, 0xc1, 0xd5, 0x5c, 0x48, + 0x8a, 0xd2, 0xf9, 0x95, 0x23, 0xf4, 0x2a, 0x98, 0x54, + 0xa2, 0xb4, 0x68, 0xab, 0x52, 0xb7, 0x69, 0x11, 0x2e, + 0xfb, 0x81, 0x07, 0xf8, 0xb0, 0x78, 0x6f, 0x53, 0x18, + 0x60, 0x0c, 0xc0, 0xa3, 0x0d, 0x22, 0x8a, 0xa0, 0x90, + 0x8c, 0x40, 0x3f, 0x4f, 0xab, 0x95, 0x3d, 0xa5, 0x31, + 0x21, 0x8a, 0xc3, 0x4b, 0xa9, 0x8b, 0xba, 0x12, 0xd0 + }; + uint8_t outbuf[sizeof(result)]; + size_t bytes_written; + + bytes_written = dtls_p_hash(HASH_SHA256, + key, sizeof(key), + NULL, 0, + random, sizeof(random), + NULL, 0, /* random2 */ + outbuf, sizeof(outbuf)); + + CU_ASSERT_EQUAL(bytes_written, sizeof(outbuf)); + CU_ASSERT(memcmp(outbuf, result, bytes_written) == 0); +} + +static void +t_test_prf3(void) { + const uint8_t key[] = { 0x00, 0x01, 0x02, 0x03 }; + const uint8_t label[] = { 0x6c, 0x61, 0x62, 0x65, 0x6c }; + const uint8_t random1[] = { + 0x75, 0xfc, 0x29, 0x97, 0x64, 0x38, 0x2e, 0x1b, + 0x91, 0xe0, 0x28, 0x7d, 0x6a, 0xac, 0x66, 0x98, + 0x25, 0x3f, 0x08, 0xf4, 0x06, 0x66, 0x32, 0x18, + 0x9f, 0x37, 0xb9, 0xef, 0xd1, 0x01, 0xac, 0xe2, + }; + const uint8_t random2[] = { + 0x0a, 0x3b, 0xda, 0x57, 0x9c, 0x77, 0xc7, 0xa2, + 0x86, 0x4d, 0x62, 0xaa, 0xf3, 0xf1, 0xfc, 0xd0, + 0x15, 0x62, 0xc4, 0x93, 0x6e, 0x0b, 0x09, 0x03, + 0xab, 0xc2, 0x8f, 0x0a, 0xbb, 0x5f, 0xbb, 0x89, + 0x45, 0xc3, 0x50, 0xb5, 0x6e, 0x65, 0xd5, 0x80, + 0x5d, 0xb8, 0x5e, 0xb2, 0x30, 0x34, 0xee, 0x17 + }; + /* expected result */ + const uint8_t result[] = { 0xf1, 0xb0, 0x85 }; + uint8_t outbuf[sizeof(result)]; + size_t bytes_written; + + bytes_written = dtls_p_hash(HASH_SHA256, + key, sizeof(key), + label, sizeof(label), + random1, sizeof(random1), + random2, sizeof(random2), + outbuf, sizeof(outbuf)); + + CU_ASSERT_EQUAL(bytes_written, sizeof(outbuf)); + CU_ASSERT(memcmp(outbuf, result, bytes_written) == 0); +} + +static void +t_test_prf4(void) { + const uint8_t label[] = { 0x6c, 0x61, 0x62, 0x65, 0x6c }; + const uint8_t random1[] = { + 0x75, 0xfc, 0x29, 0x97, 0x64, 0x38, 0x2e, 0x1b, + 0x91, 0xe0, 0x28, 0x7d, 0x6a, 0xac, 0x66, 0x98, + 0x25, 0x3f, 0x08, 0xf4, 0x06, 0x66, 0x32, 0x18, + 0x9f, 0x37, 0xb9, 0xef, 0xd1, 0x01, 0xac, 0xe2, + }; + const uint8_t random2[] = { + 0x0a, 0x3b, 0xda, 0x57, 0x9c, 0x77, 0xc7, 0xa2, + 0x86, 0x4d, 0x62, 0xaa, 0xf3, 0xf1, 0xfc, 0xd0, + 0x15, 0x62, 0xc4, 0x93, 0x6e, 0x0b, 0x09, 0x03, + 0xab, 0xc2, 0x8f, 0x0a, 0xbb, 0x5f, 0xbb, 0x89, + 0x45, 0xc3, 0x50, 0xb5, 0x6e, 0x65, 0xd5, 0x80, + 0x5d, 0xb8, 0x5e, 0xb2, 0x30, 0x34, 0xee, 0x17 + }; + /* expected result */ + const uint8_t result[] = { + 0xdc, 0xe1, 0x0a, 0x7d, 0xa0, 0xa8, 0x7c, 0x8c, 0xc6, + 0x1e, 0x33, 0xf6, 0xa9, 0x61, 0x96, 0x7a, 0x1c, 0x22, + 0xb6, 0xbc, 0x62, 0xe4, 0xb0, 0x19, 0x5b, 0x98, 0x2e, + 0xb5, 0xd8, 0x2a, 0xa2, 0x2e, 0x9c, 0xce, 0x79 + }; + uint8_t outbuf[sizeof(result)]; + size_t bytes_written; + + bytes_written = dtls_p_hash(HASH_SHA256, + NULL, 0, + label, sizeof(label), + random1, sizeof(random1), + random2, sizeof(random2), + outbuf, sizeof(outbuf)); + + CU_ASSERT_EQUAL(bytes_written, sizeof(outbuf)); + CU_ASSERT(memcmp(outbuf, result, bytes_written) == 0); +} + +static void +t_test_prf5(void) { + /* expected result */ + const uint8_t result[] = { + 0xa6, 0xf9, 0x91, 0xab, 0x2b, 0x5f, 0x9e, 0xe8, + 0x06, 0x3c, 0x11, 0x5a, 0xb7, 0xb4, 0x00, 0x9b, + 0x0f, 0x3b, 0xcb, 0x8f, 0x10, 0x90, 0xe1, 0xaf, + 0xc4, 0xa3, 0xff, 0x20, 0x2e, 0x82, 0xed, 0x00 + }; + uint8_t outbuf[sizeof(result)]; + size_t bytes_written; + + bytes_written = dtls_p_hash(HASH_SHA256, + NULL, 0, /* secret */ + NULL, 0, /* label */ + NULL, 0, /* random1 */ + NULL, 0, /* random2 */ + outbuf, sizeof(outbuf)); + + CU_ASSERT_EQUAL(bytes_written, sizeof(outbuf)); + CU_ASSERT(memcmp(outbuf, result, bytes_written) == 0); +} + +CU_pSuite +t_init_prf_tests(void) { + CU_pSuite suite; + + suite = CU_add_suite("PRF", NULL, NULL); + if (!suite) { /* signal error */ + fprintf(stderr, "W: cannot add PRF test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + + /* On POSIX system, getrandom() is used where available, ignoring + * the seed. For other platforms, the random sequence will be the + * same for each run. */ + dtls_prng_init(0); + +#define PRF_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add test for PRF (%s)\n", \ + CU_get_error_msg()); \ + } + + PRF_TEST(suite, t_test_prf0); + PRF_TEST(suite, t_test_prf1); + PRF_TEST(suite, t_test_prf2); + PRF_TEST(suite, t_test_prf3); + PRF_TEST(suite, t_test_prf4); + PRF_TEST(suite, t_test_prf5); + + return suite; +} + diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_prf.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_prf.h new file mode 100644 index 000000000..bc726abaf --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/test_prf.h @@ -0,0 +1,15 @@ +/******************************************************************************* + * + * Copyright (c) 2022 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + */ + +#include + +CU_pSuite t_init_prf_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/testdriver.c b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/testdriver.c new file mode 100644 index 000000000..17be75331 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tests/unit-tests/testdriver.c @@ -0,0 +1,30 @@ +#include + +#include +#include + +#include "test_ccm.h" +#include "test_ecc.h" +#include "test_prf.h" +#include "tinydtls.h" + +int main(void) { + CU_ErrorCode result; + CU_BasicRunMode run_mode = CU_BRM_VERBOSE; + + if (CU_initialize_registry() != CUE_SUCCESS) { + fprintf(stderr, "E: test framework initialization failed\n"); + return -2; + } + + t_init_ccm_tests(); + t_init_ecc_tests(); + t_init_prf_tests(); + + CU_basic_set_mode(run_mode); + result = CU_basic_run_tests(); + + CU_cleanup_registry(); + + return result; +} diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tinydtls.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tinydtls.h new file mode 100644 index 000000000..cf2594105 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tinydtls.h @@ -0,0 +1,51 @@ +/* tinydtls.h. Generated from tinydtls.h.in by configure. */ +/******************************************************************************* + * + * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v. 1.0 which accompanies this distribution. + * + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Olaf Bergmann - initial API and implementation + * Hauke Mehrtens - memory optimization, ECC integration + * + *******************************************************************************/ + +/** + * @file tinydtls.h + * @brief public tinydtls API + */ + +#ifndef _DTLS_TINYDTLS_H_ +#define _DTLS_TINYDTLS_H_ + +#ifdef RIOT_VERSION +#include "platform-specific/riot_boards.h" +#endif /* RIOT_VERSION */ + +#ifdef CONTIKI +#include "platform-specific/platform.h" +#endif /* CONTIKI */ + +#ifndef CONTIKI +#ifndef RIOT_VERSION +#ifndef WITH_POSIX +/* TODO: To remove in a future */ +#define WITH_POSIX 1 +#endif /* WITH_POSIX */ +#include "dtls_config.h" +#endif /* RIOT_VERSION */ +#endif /* CONTIKI */ + +#ifndef DTLS_ECC +#ifndef DTLS_PSK +#error "TinyDTLS requires at least one Cipher suite!" +#endif /* DTLS_PSK */ +#endif /* DTLS_ECC */ + +#endif /* _DTLS_TINYDTLS_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tinydtls.pc.in b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tinydtls.pc.in new file mode 100644 index 000000000..85e2b2372 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/tinydtls.pc.in @@ -0,0 +1,26 @@ +# pkg-config file for tinydtls +# +# +# Copyright (c) 2011-2021 Olaf Bergmann (TZI) and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# and Eclipse Distribution License v. 1.0 which accompanies this distribution. +# +# The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html +# and the Eclipse Distribution License is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# Contributors: +# Hugo Damer - support for pkg-config in tinydtls + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ +libdir=@libdir@ + +Name: @PACKAGE_NAME@ +Description: A C library for Datagram Transport Layer Security (DTLS) supporting both client and server functionality. +URL: @PACKAGE_URL@ +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -ltinydtls +Cflags: -I${includedir}/tinydtls diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/uthash.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/uthash.h new file mode 100644 index 000000000..d0830b6f3 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/uthash.h @@ -0,0 +1,1210 @@ +/* +Copyright (c) 2003-2017, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +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. + +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. +*/ + +#ifndef UTHASH_H +#define UTHASH_H + +#define UTHASH_VERSION 2.0.2 + +#include /* memcmp, memset, strlen */ +#include /* ptrdiff_t */ +#include /* exit */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if !defined(DECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#endif +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE(x) +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while (0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while (0) +#endif + +/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */ +#if defined(_WIN32) +#if defined(_MSC_VER) && _MSC_VER >= 1600 +#include +#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__) +#include +#else +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif +#elif defined(__GNUC__) && !defined(__VXWORKS__) +#include +#else +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif + +#ifndef uthash_malloc +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#endif +#ifndef uthash_free +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ +#endif +#ifndef uthash_bzero +#define uthash_bzero(a,n) memset(a,'\0',n) +#endif +#ifndef uthash_memcmp +#define uthash_memcmp(a,b,n) memcmp(a,b,n) +#endif +#ifndef uthash_strlen +#define uthash_strlen(s) strlen(s) +#endif + +#ifndef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#endif +#ifndef uthash_expand_fyi +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ +#endif + +#ifndef HASH_NONFATAL_OOM +#define HASH_NONFATAL_OOM 0 +#endif + +#if HASH_NONFATAL_OOM +/* malloc failures can be recovered from */ + +#ifndef uthash_nonfatal_oom +#define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0) +#define IF_HASH_NONFATAL_OOM(x) x + +#else +/* malloc failures result in lost memory, hash tables are unusable */ + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory") +#define IF_HASH_NONFATAL_OOM(x) + +#endif + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhp */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) +/* calculate the hash handle from element address elp */ +#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho))) + +#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ +do { \ + struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ + unsigned _hd_bkt; \ + HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + (head)->hh.tbl->buckets[_hd_bkt].count++; \ + _hd_hh_item->hh_next = NULL; \ + _hd_hh_item->hh_prev = NULL; \ +} while (0) + +#define HASH_VALUE(keyptr,keylen,hashv) \ +do { \ + HASH_FCN(keyptr, keylen, hashv); \ +} while (0) + +#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ + } \ + } \ +} while (0) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl,oomed) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!(tbl)->bloom_bv) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ + } \ +} while (0) + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0) + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) + +#else +#define HASH_BLOOM_MAKE(tbl,oomed) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) (1) +#define HASH_BLOOM_BYTELEN 0U +#endif + +#define HASH_MAKE_TABLE(hh,head,oomed) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \ + if (!(head)->hh.tbl) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ + if (!(head)->hh.tbl->buckets) { \ + HASH_RECORD_OOM(oomed); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } else { \ + uthash_bzero((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + uthash_free((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } \ + ) \ + } \ + } \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ +} while (0) + +#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ +} while (0) + +#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ +} while (0) + +#define HASH_APPEND_LIST(hh, head, add) \ +do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ +} while (0) + +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + do { \ + if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ + break; \ + } \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) + +#ifdef NO_DECLTYPE +#undef HASH_AKBI_INNER_LOOP +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + char *_hs_saved_head = (char*)(head); \ + do { \ + DECLTYPE_ASSIGN(head, _hs_iter); \ + if (cmpfcn(head, add) > 0) { \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + break; \ + } \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) +#endif + +#if HASH_NONFATAL_OOM + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + if (!(oomed)) { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + if (oomed) { \ + HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ + HASH_DELETE_HH(hh, head, &(add)->hh); \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } else { \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + } \ + } else { \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } \ +} while (0) + +#else + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ +} while (0) + +#endif + + +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + void *_hs_iter = (head); \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ +} while (0) + +#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ +do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) + +#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) + +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ +} while (0) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) + +#define HASH_TO_BKT(hashv,num_bkts,bkt) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1U)); \ +} while (0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ + HASH_DELETE_HH(hh, head, &(delptr)->hh) + +#define HASH_DELETE_HH(hh,head,delptrhh) \ +do { \ + struct UT_hash_handle *_hd_hh_del = (delptrhh); \ + if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } else { \ + unsigned _hd_bkt; \ + if (_hd_hh_del == (head)->hh.tbl->tail) { \ + (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ + } \ + if (_hd_hh_del->prev != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ + } else { \ + DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ + } \ + HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ +} while (0) + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ + HASH_FIND(hh,head,findstr,(unsigned)uthash_strlen(findstr),out) +#define HASH_ADD_STR(head,strfield,add) \ + HASH_ADD(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add) +#define HASH_REPLACE_STR(head,strfield,add,replaced) \ + HASH_REPLACE(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add,replaced) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_REPLACE_INT(head,intfield,add,replaced) \ + HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ + HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head,where) \ +do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ + unsigned _bkt_i; \ + unsigned _count = 0; \ + char *_prev; \ + for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ + (where), (void*)_thh->hh_prev, (void*)_prev); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \ + (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev != (char*)_thh->prev) { \ + HASH_OOPS("%s: invalid prev %p, actual %p\n", \ + (where), (void*)_thh->prev, (void*)_prev); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head,where) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ +#ifdef HASH_FUNCTION +#define HASH_FCN HASH_FUNCTION +#else +#define HASH_FCN HASH_JEN +#endif + +/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ +#define HASH_BER(key,keylen,hashv) \ +do { \ + unsigned _hb_keylen = (unsigned)keylen; \ + const unsigned char *_hb_key = (const unsigned char*)(key); \ + (hashv) = 0; \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ +} while (0) + + +/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at + * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ +#define HASH_SAX(key,keylen,hashv) \ +do { \ + unsigned _sx_i; \ + const unsigned char *_hs_key = (const unsigned char*)(key); \ + hashv = 0; \ + for (_sx_i=0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ +} while (0) +/* FNV-1a variation */ +#define HASH_FNV(key,keylen,hashv) \ +do { \ + unsigned _fn_i; \ + const unsigned char *_hf_key = (const unsigned char*)(key); \ + (hashv) = 2166136261U; \ + for (_fn_i=0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ +} while (0) + +#define HASH_OAT(key,keylen,hashv) \ +do { \ + unsigned _ho_i; \ + const unsigned char *_ho_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ +} while (0) + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,hashv) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + unsigned const char *_hj_key=(unsigned const char*)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned)(keylen); \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ + case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ + case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \ + default: /* make gcc -Wswitch-default happy */ \ + ; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ +} while (0) + +/* The Paul Hsieh hash function */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif +#define HASH_SFH(key,keylen,hashv) \ +do { \ + unsigned const char *_sfh_key=(unsigned const char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ + \ + unsigned _sfh_rem = _sfh_len & 3U; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabeu; \ + \ + /* Main loop */ \ + for (;_sfh_len > 0U; _sfh_len--) { \ + hashv += get16bits (_sfh_key); \ + _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2U*sizeof (uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ +} while (0) + +#ifdef HASH_USING_NO_STRICT_ALIASING +/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. + * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. + * MurmurHash uses the faster approach only on CPU's where we know it's safe. + * + * Note the preprocessor built-in defines can be emitted using: + * + * gcc -m64 -dM -E - < /dev/null (on gcc) + * cc -## a.c (where a.c is a simple test file) (Sun Studio) + */ +#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) +#define MUR_GETBLOCK(p,i) p[i] +#else /* non intel */ +#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL) +#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL) +#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL) +#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL) +#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) +#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) +#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) +#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) +#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) +#else /* assume little endian non-intel */ +#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) +#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) +#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) +#endif +#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ + (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ + (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ + MUR_ONE_THREE(p)))) +#endif +#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) +#define MUR_FMIX(_h) \ +do { \ + _h ^= _h >> 16; \ + _h *= 0x85ebca6bu; \ + _h ^= _h >> 13; \ + _h *= 0xc2b2ae35u; \ + _h ^= _h >> 16; \ +} while (0) + +#define HASH_MUR(key,keylen,hashv) \ +do { \ + const uint8_t *_mur_data = (const uint8_t*)(key); \ + const int _mur_nblocks = (int)(keylen) / 4; \ + uint32_t _mur_h1 = 0xf88D5353u; \ + uint32_t _mur_c1 = 0xcc9e2d51u; \ + uint32_t _mur_c2 = 0x1b873593u; \ + uint32_t _mur_k1 = 0; \ + const uint8_t *_mur_tail; \ + const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \ + int _mur_i; \ + for (_mur_i = -_mur_nblocks; _mur_i != 0; _mur_i++) { \ + _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ + _mur_k1 *= _mur_c1; \ + _mur_k1 = MUR_ROTL32(_mur_k1,15); \ + _mur_k1 *= _mur_c2; \ + \ + _mur_h1 ^= _mur_k1; \ + _mur_h1 = MUR_ROTL32(_mur_h1,13); \ + _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \ + } \ + _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \ + _mur_k1=0; \ + switch ((keylen) & 3U) { \ + case 0: break; \ + case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \ + case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \ + case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \ + _mur_k1 *= _mur_c1; \ + _mur_k1 = MUR_ROTL32(_mur_k1,15); \ + _mur_k1 *= _mur_c2; \ + _mur_h1 ^= _mur_k1; \ + } \ + _mur_h1 ^= (uint32_t)(keylen); \ + MUR_FMIX(_mur_h1); \ + hashv = _mur_h1; \ +} while (0) +#endif /* HASH_USING_NO_STRICT_ALIASING */ + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ +do { \ + if ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ + if (uthash_memcmp((out)->hh.key, keyptr, keylen_in) == 0) { \ + break; \ + } \ + } \ + if ((out)->hh.hh_next != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ + } else { \ + (out) = NULL; \ + } \ + } \ +} while (0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \ +do { \ + UT_hash_bucket *_ha_head = &(head); \ + _ha_head->count++; \ + (addhh)->hh_next = _ha_head->hh_head; \ + (addhh)->hh_prev = NULL; \ + if (_ha_head->hh_head != NULL) { \ + _ha_head->hh_head->hh_prev = (addhh); \ + } \ + _ha_head->hh_head = (addhh); \ + if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \ + && !(addhh)->tbl->noexpand) { \ + HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + HASH_DEL_IN_BKT(head,addhh); \ + } \ + ) \ + } \ +} while (0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(head,delhh) \ +do { \ + UT_hash_bucket *_hd_head = &(head); \ + _hd_head->count--; \ + if (_hd_head->hh_head == (delhh)) { \ + _hd_head->hh_head = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_prev) { \ + (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_next) { \ + (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ + } \ +} while (0) + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + if (!_he_new_buckets) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero(_he_new_buckets, \ + 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->ideal_chain_maxlen = \ + ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \ + ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ + (tbl)->nonideal_items = 0; \ + for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \ + _he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[_he_bkt]); \ + if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ + (tbl)->nonideal_items++; \ + _he_newbkt->expand_mult = _he_newbkt->count / (tbl)->ideal_chain_maxlen; \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { \ + _he_newbkt->hh_head->hh_prev = _he_thh; \ + } \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->num_buckets *= 2U; \ + (tbl)->log2_num_buckets++; \ + (tbl)->buckets = _he_new_buckets; \ + (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \ + ((tbl)->ineff_expands+1U) : 0U; \ + if ((tbl)->ineff_expands > 1U) { \ + (tbl)->noexpand = 1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ + } \ +} while (0) + + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ + _hs_psize++; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + if (_hs_q == NULL) { \ + break; \ + } \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else if ((cmpfcn( \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)) \ + )) <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail != NULL ) { \ + _hs_tail->next = ((_hs_e != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail != NULL) { \ + _hs_tail->next = NULL; \ + } \ + if (_hs_nmerges <= 1U) { \ + _hs_looping = 0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh, head, "HASH_SRT"); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt = NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if ((src) != NULL) { \ + for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \ + _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh != NULL) { \ + _last_elt_hh->next = _elt; \ + } \ + if ((dst) == NULL) { \ + DECLTYPE_ASSIGN(dst, _elt); \ + HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + uthash_nonfatal_oom(_elt); \ + (dst) = NULL; \ + continue; \ + } \ + ) \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \ + (dst)->hh_dst.tbl->num_items++; \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ + HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ + _dst_hh->tbl = NULL; \ + uthash_nonfatal_oom(_elt); \ + continue; \ + } \ + ) \ + HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if ((head) != NULL) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } \ +} while (0) + +#define HASH_OVERHEAD(hh,head) \ + (((head) != NULL) ? ( \ + (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ + sizeof(UT_hash_table) + \ + (HASH_BLOOM_BYTELEN))) : 0U) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) + +typedef struct UT_hash_bucket { + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1u +#define HASH_BLOOM_SIGNATURE 0xb12220f2u + +typedef struct UT_hash_table { + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + uint8_t bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle { + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/utlist.h b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/utlist.h new file mode 100644 index 000000000..2f4c08406 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/utlist.h @@ -0,0 +1,1073 @@ +/* +Copyright (c) 2007-2017, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +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. + +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. +*/ + +#ifndef UTLIST_H +#define UTLIST_H + +#define UTLIST_VERSION 2.0.2 + +#include + +/* + * This file contains macros to manipulate singly and doubly-linked lists. + * + * 1. LL_ macros: singly-linked lists. + * 2. DL_ macros: doubly-linked lists. + * 3. CDL_ macros: circular doubly-linked lists. + * + * To use singly-linked lists, your structure must have a "next" pointer. + * To use doubly-linked lists, your structure must "prev" and "next" pointers. + * Either way, the pointer to the head of the list must be initialized to NULL. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *prev, *next; + * } + * + * struct item *list = NULL: + * + * int main() { + * struct item *item; + * ... allocate and populate item ... + * DL_APPEND(list, item); + * } + * -------------------------------------------------- + * + * For doubly-linked lists, the append and delete macros are O(1) + * For singly-linked lists, append and delete are O(n) but prepend is O(1) + * The sort macro is O(n log(n)) for all types of single/double/circular lists. + */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if !defined(LDECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define LDECLTYPE(x) decltype(x) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#endif +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#else /* GNU, Sun and other compilers */ +#define LDECLTYPE(x) __typeof(x) +#endif +#endif + +/* for VS2008 we use some workarounds to get around the lack of decltype, + * namely, we always reassign our tmp variable to the list head if we need + * to dereference its prev/next pointers, and save/restore the real head.*/ +#ifdef NO_DECLTYPE +#define IF_NO_DECLTYPE(x) x +#define LDECLTYPE(x) char* +#define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } +#define UTLIST_NEXT(elt,list,next) ((char*)((list)->next)) +#define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } +/* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */ +#define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } +#define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } +#define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } +#else +#define IF_NO_DECLTYPE(x) +#define UTLIST_SV(elt,list) +#define UTLIST_NEXT(elt,list,next) ((elt)->next) +#define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to) +/* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */ +#define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) +#define UTLIST_RS(list) +#define UTLIST_CASTASGN(a,b) (a)=(b) +#endif + +/****************************************************************************** + * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * + * Unwieldy variable names used here to avoid shadowing passed-in variables. * + *****************************************************************************/ +#define LL_SORT(list, cmp) \ + LL_SORT2(list, cmp, next) + +#define LL_SORT2(list, cmp, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ + } \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + + +#define DL_SORT(list, cmp) \ + DL_SORT2(list, cmp, prev, next) + +#define DL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if ((_ls_qsize == 0) || (!_ls_q)) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev, _ls_tail); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +#define CDL_SORT(list, cmp) \ + CDL_SORT2(list, cmp, prev, next) + +#define CDL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + UTLIST_CASTASGN(_ls_oldhead,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); \ + if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \ + _ls_q = NULL; \ + } else { \ + _ls_q = UTLIST_NEXT(_ls_q,list,next); \ + } \ + UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev,_ls_tail); \ + UTLIST_CASTASGN(_tmp,list); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +/****************************************************************************** + * singly linked list macros (non-circular) * + *****************************************************************************/ +#define LL_PREPEND(head,add) \ + LL_PREPEND2(head,add,next) + +#define LL_PREPEND2(head,add,next) \ +do { \ + (add)->next = (head); \ + (head) = (add); \ +} while (0) + +#define LL_CONCAT(head1,head2) \ + LL_CONCAT2(head1,head2,next) + +#define LL_CONCAT2(head1,head2,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head1) { \ + _tmp = (head1); \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(head2); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#define LL_APPEND(head,add) \ + LL_APPEND2(head,add,next) + +#define LL_APPEND2(head,add,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + (add)->next=NULL; \ + if (head) { \ + _tmp = (head); \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(add); \ + } else { \ + (head)=(add); \ + } \ +} while (0) + +#define LL_INSERT_INORDER(head,add,cmp) \ + LL_INSERT_INORDER2(head,add,cmp,next) + +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + LL_LOWER_BOUND(head, _tmp, add, cmp); \ + LL_APPEND_ELEM(head, _tmp, add); \ + } else { \ + (head) = (add); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define LL_LOWER_BOUND(head,elt,like,cmp) \ + LL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define LL_LOWER_BOUND2(head,elt,like,cmp,next) \ + do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if (cmp((elt)->next, like) >= 0) { \ + break; \ + } \ + } \ + } \ + } while (0) + +#define LL_DELETE(head,del) \ + LL_DELETE2(head,del,next) + +#define LL_DELETE2(head,del,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (del))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (del)->next; \ + } \ + } \ +} while (0) + +#define LL_COUNT(head,el,counter) \ + LL_COUNT2(head,el,counter,next) \ + +#define LL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + LL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define LL_FOREACH(head,el) \ + LL_FOREACH2(head,el,next) + +#define LL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +#define LL_FOREACH_SAFE(head,el,tmp) \ + LL_FOREACH_SAFE2(head,el,tmp,next) + +#define LL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +#define LL_SEARCH_SCALAR(head,out,field,val) \ + LL_SEARCH_SCALAR2(head,out,field,val,next) + +#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define LL_SEARCH(head,out,elt,cmp) \ + LL_SEARCH2(head,out,elt,cmp,next) + +#define LL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ +} while (0) + +#define LL_REPLACE_ELEM(head, el, add) \ + LL_REPLACE_ELEM2(head, el, add, next) + +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_PREPEND_ELEM(head, el, add) \ + LL_PREPEND_ELEM2(head, el, add, next) + +#define LL_APPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (el)->next = (add); \ + } else { \ + LL_PREPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_APPEND_ELEM(head, el, add) \ + LL_APPEND_ELEM2(head, el, add, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef LL_CONCAT2 +#define LL_CONCAT2(head1,head2,next) \ +do { \ + char *_tmp; \ + if (head1) { \ + _tmp = (char*)(head1); \ + while ((head1)->next) { (head1) = (head1)->next; } \ + (head1)->next = (head2); \ + UTLIST_RS(head1); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#undef LL_APPEND2 +#define LL_APPEND2(head,add,next) \ +do { \ + if (head) { \ + (add)->next = head; /* use add->next as a temp variable */ \ + while ((add)->next->next) { (add)->next = (add)->next->next; } \ + (add)->next->next=(add); \ + } else { \ + (head)=(add); \ + } \ + (add)->next=NULL; \ +} while (0) + +#undef LL_INSERT_INORDER2 +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, add)) >= 0) { \ + (add)->next = (head); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) + +#undef LL_DELETE2 +#define LL_DELETE2(head,del,next) \ +do { \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && ((head)->next != (del))) { \ + (head) = (head)->next; \ + } \ + if ((head)->next) { \ + (head)->next = ((del)->next); \ + } \ + UTLIST_RS(head); \ + } \ +} while (0) + +#undef LL_REPLACE_ELEM2 +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = head; \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el)->next; \ +} while (0) + +#undef LL_PREPEND_ELEM2 +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = (head); \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el); \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#endif /* NO_DECLTYPE */ + +/****************************************************************************** + * doubly linked list macros (non-circular) * + *****************************************************************************/ +#define DL_PREPEND(head,add) \ + DL_PREPEND2(head,add,prev,next) + +#define DL_PREPEND2(head,add,prev,next) \ +do { \ + (add)->next = (head); \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev = (add); \ + } else { \ + (add)->prev = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define DL_APPEND(head,add) \ + DL_APPEND2(head,add,prev,next) + +#define DL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev->next = (add); \ + (head)->prev = (add); \ + (add)->next = NULL; \ + } else { \ + (head)=(add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_INSERT_INORDER(head,add,cmp) \ + DL_INSERT_INORDER2(head,add,cmp,next) + +#define DL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + DL_LOWER_BOUND(head, _tmp, add, cmp); \ + DL_APPEND_ELEM(head, _tmp, add); \ + } else { \ + (head) = (add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_LOWER_BOUND(head,elt,like,cmp) \ + DL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define DL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) + +#define DL_CONCAT(head1,head2) \ + DL_CONCAT2(head1,head2,prev,next) + +#define DL_CONCAT2(head1,head2,prev,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head2) { \ + if (head1) { \ + UTLIST_CASTASGN(_tmp, (head2)->prev); \ + (head2)->prev = (head1)->prev; \ + (head1)->prev->next = (head2); \ + UTLIST_CASTASGN((head1)->prev, _tmp); \ + } else { \ + (head1)=(head2); \ + } \ + } \ +} while (0) + +#define DL_DELETE(head,del) \ + DL_DELETE2(head,del,prev,next) + +#define DL_DELETE2(head,del,prev,next) \ +do { \ + assert((head) != NULL); \ + assert((del)->prev != NULL); \ + if ((del)->prev == (del)) { \ + (head)=NULL; \ + } else if ((del)==(head)) { \ + (del)->next->prev = (del)->prev; \ + (head) = (del)->next; \ + } else { \ + (del)->prev->next = (del)->next; \ + if ((del)->next) { \ + (del)->next->prev = (del)->prev; \ + } else { \ + (head)->prev = (del)->prev; \ + } \ + } \ +} while (0) + +#define DL_COUNT(head,el,counter) \ + DL_COUNT2(head,el,counter,next) \ + +#define DL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + DL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define DL_FOREACH(head,el) \ + DL_FOREACH2(head,el,next) + +#define DL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +/* this version is safe for deleting the elements during iteration */ +#define DL_FOREACH_SAFE(head,el,tmp) \ + DL_FOREACH_SAFE2(head,el,tmp,next) + +#define DL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +/* these are identical to their singly-linked list counterparts */ +#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR +#define DL_SEARCH LL_SEARCH +#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 +#define DL_SEARCH2 LL_SEARCH2 + +#define DL_REPLACE_ELEM2(head, el, add, prev, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + (add)->next = (el)->next; \ + if ((el)->next == NULL) { \ + (add)->prev = (add); \ + } else { \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + } \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->prev->next = (add); \ + if ((el)->next == NULL) { \ + (head)->prev = (add); \ + } else { \ + (add)->next->prev = (add); \ + } \ + } \ +} while (0) + +#define DL_REPLACE_ELEM(head, el, add) \ + DL_REPLACE_ELEM2(head, el, add, prev, next) + +#define DL_PREPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->prev->next = (add); \ + } \ + } else { \ + DL_APPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_PREPEND_ELEM(head, el, add) \ + DL_PREPEND_ELEM2(head, el, add, prev, next) + +#define DL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } else { \ + DL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_APPEND_ELEM(head, el, add) \ + DL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef DL_INSERT_INORDER2 +#define DL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = NULL; \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ + +/****************************************************************************** + * circular doubly linked list macros * + *****************************************************************************/ +#define CDL_APPEND(head,add) \ + CDL_APPEND2(head,add,prev,next) + +#define CDL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } \ +} while (0) + +#define CDL_PREPEND(head,add) \ + CDL_PREPEND2(head,add,prev,next) + +#define CDL_PREPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define CDL_INSERT_INORDER(head,add,cmp) \ + CDL_INSERT_INORDER2(head,add,cmp,next) + +#define CDL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + CDL_LOWER_BOUND(head, _tmp, add, cmp); \ + CDL_APPEND_ELEM(head, _tmp, add); \ + } else { \ + (head) = (add); \ + (head)->next = (head); \ + (head)->prev = (head); \ + } \ +} while (0) + +#define CDL_LOWER_BOUND(head,elt,like,cmp) \ + CDL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) + +#define CDL_DELETE(head,del) \ + CDL_DELETE2(head,del,prev,next) + +#define CDL_DELETE2(head,del,prev,next) \ +do { \ + if (((head)==(del)) && ((head)->next == (head))) { \ + (head) = NULL; \ + } else { \ + (del)->next->prev = (del)->prev; \ + (del)->prev->next = (del)->next; \ + if ((del) == (head)) (head)=(del)->next; \ + } \ +} while (0) + +#define CDL_COUNT(head,el,counter) \ + CDL_COUNT2(head,el,counter,next) \ + +#define CDL_COUNT2(head, el, counter,next) \ +do { \ + (counter) = 0; \ + CDL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define CDL_FOREACH(head,el) \ + CDL_FOREACH2(head,el,next) + +#define CDL_FOREACH2(head,el,next) \ + for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next)) + +#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ + CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) + +#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ + for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \ + (el) && ((tmp2) = (el)->next, 1); \ + (el) = ((el) == (tmp1) ? NULL : (tmp2))) + +#define CDL_SEARCH_SCALAR(head,out,field,val) \ + CDL_SEARCH_SCALAR2(head,out,field,val,next) + +#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define CDL_SEARCH(head,out,elt,cmp) \ + CDL_SEARCH2(head,out,elt,cmp,next) + +#define CDL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((el)->next == (el)) { \ + (add)->next = (add); \ + (add)->prev = (add); \ + (head) = (add); \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } \ +} while (0) + +#define CDL_REPLACE_ELEM(head, el, add) \ + CDL_REPLACE_ELEM2(head, el, add, prev, next) + +#define CDL_PREPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } else { \ + CDL_APPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_PREPEND_ELEM(head, el, add) \ + CDL_PREPEND_ELEM2(head, el, add, prev, next) + +#define CDL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + (add)->next->prev = (add); \ + } else { \ + CDL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_APPEND_ELEM(head, el, add) \ + CDL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef CDL_INSERT_INORDER2 +#define CDL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (add)->prev->next = (add); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (add)->next->prev = (add); \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ + +#endif /* UTLIST_H */ diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/zephyr/CMakeLists.txt b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/zephyr/CMakeLists.txt new file mode 100644 index 000000000..be7707943 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/zephyr/CMakeLists.txt @@ -0,0 +1,43 @@ +############################################################################### +# +# Copyright (c) 2022 Contributors to the Eclipse Foundation +# +# See the LICENSE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 1.0 +# which is available at http://www.eclipse.org/legal/epl-v10.html +# and the Eclipse Distribution License v. 1.0 +# available at http://www.eclipse.org/org/documents/edl-v10.php +# +# SPDX-License-Identifier: EPL-1.0 +# +# Contributors: +# Achim Kraus - initial build file for supmodule +# +############################################################################### + +cmake_minimum_required(VERSION 3.20.0) + +if(CONFIG_LIBTINYDTLS) + enable_language(C) + # TEST_BIG_ENDIAN doesn't work for zephyr/ncs 1.9.1 + if(${ARCH} STREQUAL "arm") + set(CMAKE_C_BYTE_ORDER LITTLE_ENDIAN) + endif() + if(CONFIG_LIBTINYDTLS_PSK) + set(DTLS_PSK On) + else() + set(DTLS_PSK Off) + endif() + if(CONFIG_LIBTINYDTLS_ECDHE_ECDSA) + set(DTLS_ECC On) + else() + set(DTLS_ECC Off) + endif() + add_subdirectory(.. build) + target_compile_definitions(tinydtls PUBLIC WITH_ZEPHYR) + target_link_libraries(tinydtls PUBLIC zephyr_interface) + set_property(GLOBAL APPEND PROPERTY ZEPHYR_INTERFACE_LIBS tinydtls) +endif() diff --git a/examples/espidf-coap-server/components/libcoap/ext/tinydtls/zephyr/Kconfig b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/zephyr/Kconfig new file mode 100644 index 000000000..47e68d471 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/ext/tinydtls/zephyr/Kconfig @@ -0,0 +1,47 @@ +############################################################################### +# +# Copyright (c) 2022 Contributors to the Eclipse Foundation +# +# See the LICENSE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 1.0 +# which is available at http://www.eclipse.org/legal/epl-v10.html +# and the Eclipse Distribution License v. 1.0 +# available at http://www.eclipse.org/org/documents/edl-v10.php +# +# SPDX-License-Identifier: EPL-1.0 +# +# Contributors: +# Achim Kraus - initial confiuration +# +############################################################################### + +menu "tinyDTLS Settings" + +config LIBTINYDTLS + bool "Enable libtinydtls" + help + This option enables the libtinydtls as a Zephyr module. + +if LIBTINYDTLS + config LIBTINYDTLS_PSK + bool "Enable PSK" + default y + help + This option enables the PSK cipher suites. + config LIBTINYDTLS_ECDHE_ECDSA + bool "Enable ECDHE_ECDSA" + default n + help + This option enables the ECDHE_ECDSA cipher suites. + +endif # LIBTINYDTLS +endmenu + +if LIBTINYDTLS +module = TINYDTLS +module-str = tinyDTLS +source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" +endif # LIBTINYDTLS diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/block.h b/examples/espidf-coap-server/components/libcoap/include/coap3/block.h new file mode 100644 index 000000000..2ede789e0 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/block.h @@ -0,0 +1,431 @@ +/* + * block.h -- block transfer + * + * Copyright (C) 2010-2012,2014-2015 Olaf Bergmann + * Copyright (C) 2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file block.h + * @brief CoAP Block information + */ + +#ifndef COAP_BLOCK_H_ +#define COAP_BLOCK_H_ + +#include "encode.h" +#include "coap_option.h" +#include "pdu.h" + +/** + * @ingroup application_api + * @defgroup block Block Transfer + * API for handling PDUs using CoAP Block options (RFC7959) + * @{ + */ + +#ifndef COAP_MAX_BLOCK_SZX +/** + * The largest value for the SZX component in a Block option. + */ +#define COAP_MAX_BLOCK_SZX 6 +#endif /* COAP_MAX_BLOCK_SZX */ + +/** + * Structure of Block options. + */ +typedef struct { + unsigned int num; /**< block number */ + unsigned int m:1; /**< 1 if more blocks follow, 0 otherwise */ + unsigned int szx:3; /**< block size */ +} coap_block_t; + +/** + * Structure of Block options with BERT support. + */ +typedef struct { + unsigned int num; /**< block number */ + unsigned int m:1; /**< 1 if more blocks follow, 0 otherwise */ + unsigned int szx:3; /**< block size (0-6) */ + unsigned int aszx:3; /**< block size (0-7 including BERT */ + unsigned int defined:1; /**< Set if block found */ + unsigned int bert:1; /**< Operating as BERT */ + uint32_t chunk_size; /**< > 1024 if BERT */ +} coap_block_b_t; + +#define COAP_BLOCK_USE_LIBCOAP 0x01 /* Use libcoap to do block requests */ +#define COAP_BLOCK_SINGLE_BODY 0x02 /* Deliver the data as a single body */ + +/** + * Returns the value of the least significant byte of a Block option @p opt. + * For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST + * returns @c NULL. + */ +#define COAP_OPT_BLOCK_LAST(opt) \ + (coap_opt_length(opt) ? (coap_opt_value(opt) + (coap_opt_length(opt)-1)) : 0) + +/** Returns the value of the More-bit of a Block option @p opt. */ +#define COAP_OPT_BLOCK_MORE(opt) \ + (coap_opt_length(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x08) : 0) + +/** Returns the value of the SZX-field of a Block option @p opt. */ +#define COAP_OPT_BLOCK_SZX(opt) \ + (coap_opt_length(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x07) : 0) + +/** + * Returns the value of field @c num in the given block option @p block_opt. + */ +unsigned int coap_opt_block_num(const coap_opt_t *block_opt); + +/** + * Checks if more than @p num blocks are required to deliver @p data_len + * bytes of data for a block size of 1 << (@p szx + 4). + */ +COAP_STATIC_INLINE int +coap_more_blocks(size_t data_len, unsigned int num, uint16_t szx) { + return ((num+1) << (szx + 4)) < data_len; +} + +#if 0 +/** Sets the More-bit in @p block_opt */ +COAP_STATIC_INLINE void +coap_opt_block_set_m(coap_opt_t *block_opt, int m) { + if (m) + *(coap_opt_value(block_opt) + (coap_opt_length(block_opt) - 1)) |= 0x08; + else + *(coap_opt_value(block_opt) + (coap_opt_length(block_opt) - 1)) &= ~0x08; +} +#endif + +/** + * Initializes @p block from @p pdu. @p number must be either COAP_OPTION_BLOCK1 + * or COAP_OPTION_BLOCK2. When option @p number was found in @p pdu, @p block is + * initialized with values from this option and the function returns the value + * @c 1. Otherwise, @c 0 is returned. + * + * @param pdu The pdu to search for option @p number. + * @param number The option number to search for (must be COAP_OPTION_BLOCK1 or + * COAP_OPTION_BLOCK2). + * @param block The block structure to initialize. + * + * @return @c 1 on success, @c 0 otherwise. + */ +int coap_get_block(const coap_pdu_t *pdu, coap_option_num_t number, + coap_block_t *block); + + +/** + * Initializes @p block from @p pdu. @p number must be either COAP_OPTION_BLOCK1 + * or COAP_OPTION_BLOCK2. When option @p number was found in @p pdu, @p block is + * initialized with values from this option and the function returns the value + * @c 1. Otherwise, @c 0 is returned. BERT information is abstracted as + * appropriate. + * + * @param session THe session that the pdu is associated with, + * @param pdu The pdu to search for option @p number. + * @param number The option number to search for (must be COAP_OPTION_BLOCK1 or + * COAP_OPTION_BLOCK2). + * @param block The block structure to initialize. + * + * @return @c 1 on success, @c 0 otherwise. + */ +int coap_get_block_b(const coap_session_t *session, const coap_pdu_t *pdu, + coap_option_num_t number, coap_block_b_t *block); + +/** + * Writes a block option of type @p number to message @p pdu. If the requested + * block size is too large to fit in @p pdu, it is reduced accordingly. An + * exception is made for the final block when less space is required. The actual + * length of the resource is specified in @p data_length. + * + * This function may change *block to reflect the values written to @p pdu. As + * the function takes into consideration the remaining space @p pdu, no more + * options should be added after coap_write_block_opt() has returned. + * + * @param block The block structure to use. On return, this object is + * updated according to the values that have been written to + * @p pdu. + * @param number COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2. + * @param pdu The message where the block option should be written. + * @param data_length The length of the actual data that will be added the @p + * pdu by calling coap_add_block(). + * + * @return @c 1 on success, or a negative value on error. + */ +int coap_write_block_opt(coap_block_t *block, + coap_option_num_t number, + coap_pdu_t *pdu, + size_t data_length); +/** + * Writes a block option of type @p number to message @p pdu. If the requested + * block size is too large to fit in @p pdu, it is reduced accordingly. An + * exception is made for the final block when less space is required. The actual + * length of the resource is specified in @p data_length. + * + * This function may change *block to reflect the values written to @p pdu. As + * the function takes into consideration the remaining space @p pdu, no more + * options should be added after coap_write_block_opt() has returned. + * + * @param session The CoAP session. + * @param block The block structure to use. On return, this object is + * updated according to the values that have been written to + * @p pdu. + * @param number COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2. + * @param pdu The message where the block option should be written. + * @param data_length The length of the actual data that will be added the @p + * pdu by calling coap_add_block(). + * + * @return @c 1 on success, or a negative value on error. + */ +int coap_write_block_b_opt(coap_session_t *session, + coap_block_b_t *block, + coap_option_num_t number, + coap_pdu_t *pdu, + size_t data_length); + + +/** + * Adds the @p block_num block of size 1 << (@p block_szx + 4) from source @p + * data to @p pdu. + * + * @param pdu The message to add the block. + * @param len The length of @p data. + * @param data The source data to fill the block with. + * @param block_num The actual block number. + * @param block_szx Encoded size of block @p block_number. + * + * @return @c 1 on success, @c 0 otherwise. + */ +int coap_add_block(coap_pdu_t *pdu, + size_t len, + const uint8_t *data, + unsigned int block_num, + unsigned char block_szx); + +/** + * Adds the appropriate payload data of the body to the @p pdu. + * + * @param pdu The message to add the block. + * @param len The length of @p data. + * @param data The source data to fill the block with. + * @param block The block information (including potentially BERT) + * + * @return @c 1 on success, @c 0 otherwise. + */ +int coap_add_block_b_data(coap_pdu_t *pdu, size_t len, const uint8_t *data, + coap_block_b_t *block); + +/** + * Re-assemble payloads into a body + * + * @param body_data The pointer to the data for the body holding the + * representation so far or NULL if the first time. + * @param length The length of @p data. + * @param data The payload data to update the body with. + * @param offset The offset of the @p data into the body. + * @param total The estimated total size of the body. + * + * @return The current representation of the body or @c NULL if error. + * If NULL, @p body_data will have been de-allocated. + */ +coap_binary_t * +coap_block_build_body(coap_binary_t *body_data, size_t length, + const uint8_t *data, size_t offset, size_t total); + +/** + * Adds the appropriate part of @p data to the @p response pdu. If blocks are + * required, then the appropriate block will be added to the PDU and sent. + * Adds a ETag option that is the hash of the entire data if the data is to be + * split into blocks + * Used by a request handler. + * + * Note: The application will get called for every packet of a large body to + * process. Consider using coap_add_data_response_large() instead. + * + * @param request The requesting pdu. + * @param response The response pdu. + * @param media_type The format of the data. + * @param maxage The maxmimum life of the data. If @c -1, then there + * is no maxage. + * @param length The total length of the data. + * @param data The entire data block to transmit. + * + */ +void +coap_add_data_blocked_response(const coap_pdu_t *request, + coap_pdu_t *response, + uint16_t media_type, + int maxage, + size_t length, + const uint8_t* data); + +/** + * Callback handler for de-allocating the data based on @p app_ptr provided to + * coap_add_data_large_*() functions following transmission of the supplied + * data. + * + * @param session The session that this data is associated with + * @param app_ptr The application provided pointer provided to the + * coap_add_data_large_* functions. + */ +typedef void (*coap_release_large_data_t)(coap_session_t *session, + void *app_ptr); + +/** + * Associates given data with the @p pdu that is passed as second parameter. + * + * This function will fail if data has aready been added to the @p pdu. + * + * If all the data can be transmitted in a single PDU, this is functionally + * the same as coap_add_data() except @p release_func (if not NULL) will get + * invoked after data transmission. + * + * Used for a client request. + * + * If the data spans multiple PDUs, then the data will get transmitted using + * Block1 option with the addition of the Size1 and Request-Tag options. + * The underlying library will handle the transmission of the individual blocks. + * Once the body of data has been transmitted (or a failure occurred), then + * @p release_func (if not NULL) will get called so the application can + * de-allocate the @p data based on @p app_data. It is the responsibility of + * the application not to change the contents of @p data until the data + * transfer has completed. + * + * There is no need for the application to include the Block1 option in the + * @p pdu. + * + * coap_add_data_large_request() (or the alternative coap_add_data_large_*() + * functions) must be called only once per PDU and must be the last PDU update + * before the PDU is transmitted. The (potentially) initial data will get + * transmitted when coap_send() is invoked. + * + * Note: COAP_BLOCK_USE_LIBCOAP must be set by coap_context_set_block_mode() + * for libcoap to work correctly when using this function. + * + * @param session The session to associate the data with. + * @param pdu The PDU to associate the data with. + * @param length The length of data to transmit. + * @param data The data to transmit. + * @param release_func The function to call to de-allocate @p data or @c NULL + * if the function is not required. + * @param app_ptr A Pointer that the application can provide for when + * release_func() is called. + * + * @return @c 1 if addition is successful, else @c 0. + */ +int coap_add_data_large_request(coap_session_t *session, + coap_pdu_t *pdu, + size_t length, + const uint8_t *data, + coap_release_large_data_t release_func, + void *app_ptr); + +/** + * Associates given data with the @p response pdu that is passed as fourth + * parameter. + * + * This function will fail if data has aready been added to the @p pdu. + * + * If all the data can be transmitted in a single PDU, this is functionally + * the same as coap_add_data() except @p release_func (if not NULL) will get + * invoked after data transmission. The Content-Format, Max-Age and ETag + * options may be added in as appropriate. + * + * Used by a server request handler to create the response. + * + * If the data spans multiple PDUs, then the data will get transmitted using + * Block2 (response) option with the addition of the Size2 and ETag + * options. The underlying library will handle the transmission of the + * individual blocks. Once the body of data has been transmitted (or a + * failure occurred), then @p release_func (if not NULL) will get called so the + * application can de-allocate the @p data based on @p app_data. It is the + * responsibility of the application not to change the contents of @p data + * until the data transfer has completed. + * + * There is no need for the application to include the Block2 option in the + * @p pdu. + * + * coap_add_data_large_response() (or the alternative coap_add_data_large_*() + * functions) must be called only once per PDU and must be the last PDU update + * before returning from the request handler function. + * + * Note: COAP_BLOCK_USE_LIBCOAP must be set by coap_context_set_block_mode() + * for libcoap to work correctly when using this function. + * + * @param resource The resource the data is associated with. + * @param session The coap session. + * @param request The requesting pdu. + * @param response The response pdu. + * @param query The query taken from the (original) requesting pdu. + * @param media_type The content format of the data. + * @param maxage The maxmimum life of the data. If @c -1, then there + * is no maxage. + * @param etag ETag to use if not 0. + * @param length The total length of the data. + * @param data The entire data block to transmit. + * @param release_func The function to call to de-allocate @p data or NULL if + * the function is not required. + * @param app_ptr A Pointer that the application can provide for when + * release_func() is called. + * + * @return @c 1 if addition is successful, else @c 0. + */ +int +coap_add_data_large_response(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + coap_pdu_t *response, + const coap_string_t *query, + uint16_t media_type, + int maxage, + uint64_t etag, + size_t length, + const uint8_t *data, + coap_release_large_data_t release_func, + void *app_ptr); + +/** + * Set the context level CoAP block handling bits for handling RFC7959. + * These bits flow down to a session when a session is created and if the peer + * does not support something, an appropriate bit may get disabled in the + * session block_mode. + * The session block_mode then flows down into coap_crcv_t or coap_srcv_t where + * again an appropriate bit may get disabled. + * + * Note: This function must be called before the session is set up. + * + * Note: COAP_BLOCK_USE_LIBCOAP must be set if libcoap is to do all the + * block tracking and requesting, otherwise the application will have to do + * all of this work (the default if coap_context_set_block_mode() is not + * called). + * + * @param context The coap_context_t object. + * @param block_mode Zero or more COAP_BLOCK_ or'd options + */ +void coap_context_set_block_mode(coap_context_t *context, + uint8_t block_mode); + +/** + * Cancel an observe that is being tracked by the client large receive logic. + * (coap_context_set_block_mode() has to be called) + * This will trigger the sending of an observe cancel pdu to the server. + * + * @param session The session that is being used for the observe. + * @param token The original token used to initiate the observation. + * @param message_type The COAP_MESSAGE_ type (NON or CON) to send the observe + * cancel pdu as. + * + * @return @c 1 if observe cancel transmission initiation is successful, + * else @c 0. + */ +int coap_cancel_observe(coap_session_t *session, coap_binary_t *token, + coap_pdu_type_t message_type); + +/**@}*/ + +#endif /* COAP_BLOCK_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.in b/examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.in new file mode 100644 index 000000000..5d2d4731a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.in @@ -0,0 +1,65 @@ +/* + * coap.h -- main header file for CoAP stack of libcoap + * + * Copyright (C) 2010-2012,2015-2022 Olaf Bergmann + * 2015 Carsten Schoenert + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef COAP_H_ +#define COAP_H_ + +/* Define the address where bug reports for libcoap should be sent. */ +#define LIBCOAP_PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define the full name of libcoap. */ +#define LIBCOAP_PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define the full name and version of libcoap. */ +#define LIBCOAP_PACKAGE_STRING "@PACKAGE_STRING@" + +/* Define the home page for libcoap. */ +#define LIBCOAP_PACKAGE_URL "@PACKAGE_URL@" + +/* Define the version of libcoap this file belongs to. */ +#define LIBCOAP_PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* Define the numeric version identifier for libcoap */ +#define LIBCOAP_VERSION (@LIBCOAP_VERSION@U) + +#ifdef __cplusplus +extern "C" { +#endif + +#include "coap@LIBCOAP_API_VERSION@/libcoap.h" + +#include "coap@LIBCOAP_API_VERSION@/coap_forward_decls.h" +#include "coap@LIBCOAP_API_VERSION@/block.h" +#include "coap@LIBCOAP_API_VERSION@/coap_address.h" +#include "coap@LIBCOAP_API_VERSION@/coap_async.h" +#include "coap@LIBCOAP_API_VERSION@/coap_cache.h" +#include "coap@LIBCOAP_API_VERSION@/coap_debug.h" +#include "coap@LIBCOAP_API_VERSION@/coap_dtls.h" +#include "coap@LIBCOAP_API_VERSION@/coap_event.h" +#include "coap@LIBCOAP_API_VERSION@/coap_io.h" +#include "coap@LIBCOAP_API_VERSION@/coap_prng.h" +#include "coap@LIBCOAP_API_VERSION@/coap_option.h" +#include "coap@LIBCOAP_API_VERSION@/coap_subscribe.h" +#include "coap@LIBCOAP_API_VERSION@/coap_time.h" +#include "coap@LIBCOAP_API_VERSION@/encode.h" +#include "coap@LIBCOAP_API_VERSION@/mem.h" +#include "coap@LIBCOAP_API_VERSION@/net.h" +#include "coap@LIBCOAP_API_VERSION@/pdu.h" +#include "coap@LIBCOAP_API_VERSION@/resource.h" +#include "coap@LIBCOAP_API_VERSION@/str.h" +#include "coap@LIBCOAP_API_VERSION@/uri.h" + +#ifdef __cplusplus +} +#endif + +#endif /* COAP_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.windows b/examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.windows new file mode 100644 index 000000000..ce6fb9464 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.windows @@ -0,0 +1,65 @@ +/* + * coap.h -- main header file for CoAP stack of libcoap + * + * Copyright (C) 2010-2012,2015-2022 Olaf Bergmann + * 2015 Carsten Schoenert + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef COAP_H_ +#define COAP_H_ + +/* Define the address where bug reports for libcoap should be sent. */ +#define LIBCOAP_PACKAGE_BUGREPORT "libcoap-developers@lists.sourceforge.net" + +/* Define the full name of libcoap. */ +#define LIBCOAP_PACKAGE_NAME "libcoap" + +/* Define the full name and version of libcoap. */ +#define LIBCOAP_PACKAGE_STRING "libcoap 4.3.1" + +/* Define the home page for libcoap. */ +#define LIBCOAP_PACKAGE_URL "https://libcoap.net/" + +/* Define the version of libcoap this file belongs to. */ +#define LIBCOAP_PACKAGE_VERSION "4.3.1" + +/* Define the numeric version identifier for libcoap */ +#define LIBCOAP_VERSION (4003001U) + +#ifdef __cplusplus +extern "C" { +#endif + +#include "coap3/libcoap.h" + +#include "coap3/coap_forward_decls.h" +#include "coap3/block.h" +#include "coap3/coap_address.h" +#include "coap3/coap_async.h" +#include "coap3/coap_cache.h" +#include "coap3/coap_debug.h" +#include "coap3/coap_dtls.h" +#include "coap3/coap_event.h" +#include "coap3/coap_io.h" +#include "coap3/coap_option.h" +#include "coap3/coap_prng.h" +#include "coap3/coap_subscribe.h" +#include "coap3/coap_time.h" +#include "coap3/encode.h" +#include "coap3/mem.h" +#include "coap3/net.h" +#include "coap3/pdu.h" +#include "coap3/resource.h" +#include "coap3/str.h" +#include "coap3/uri.h" + +#ifdef __cplusplus +} +#endif + +#endif /* COAP_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.windows.in b/examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.windows.in new file mode 100644 index 000000000..5f72941c5 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap.h.windows.in @@ -0,0 +1,65 @@ +/* + * coap.h -- main header file for CoAP stack of libcoap + * + * Copyright (C) 2010-2012,2015-2022 Olaf Bergmann + * 2015 Carsten Schoenert + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef COAP_H_ +#define COAP_H_ + +/* Define the address where bug reports for libcoap should be sent. */ +#define LIBCOAP_PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define the full name of libcoap. */ +#define LIBCOAP_PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define the full name and version of libcoap. */ +#define LIBCOAP_PACKAGE_STRING "@PACKAGE_STRING@" + +/* Define the home page for libcoap. */ +#define LIBCOAP_PACKAGE_URL "@PACKAGE_URL@" + +/* Define the version of libcoap this file belongs to. */ +#define LIBCOAP_PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* Define the numeric version identifier for libcoap */ +#define LIBCOAP_VERSION (@LIBCOAP_VERSION@U) + +#ifdef __cplusplus +extern "C" { +#endif + +#include "coap@LIBCOAP_API_VERSION@/libcoap.h" + +#include "coap@LIBCOAP_API_VERSION@/coap_forward_decls.h" +#include "coap@LIBCOAP_API_VERSION@/block.h" +#include "coap@LIBCOAP_API_VERSION@/coap_address.h" +#include "coap@LIBCOAP_API_VERSION@/coap_async.h" +#include "coap@LIBCOAP_API_VERSION@/coap_cache.h" +#include "coap@LIBCOAP_API_VERSION@/coap_debug.h" +#include "coap@LIBCOAP_API_VERSION@/coap_dtls.h" +#include "coap@LIBCOAP_API_VERSION@/coap_event.h" +#include "coap@LIBCOAP_API_VERSION@/coap_io.h" +#include "coap@LIBCOAP_API_VERSION@/coap_option.h" +#include "coap@LIBCOAP_API_VERSION@/coap_prng.h" +#include "coap@LIBCOAP_API_VERSION@/coap_subscribe.h" +#include "coap@LIBCOAP_API_VERSION@/coap_time.h" +#include "coap@LIBCOAP_API_VERSION@/encode.h" +#include "coap@LIBCOAP_API_VERSION@/mem.h" +#include "coap@LIBCOAP_API_VERSION@/net.h" +#include "coap@LIBCOAP_API_VERSION@/pdu.h" +#include "coap@LIBCOAP_API_VERSION@/resource.h" +#include "coap@LIBCOAP_API_VERSION@/str.h" +#include "coap@LIBCOAP_API_VERSION@/uri.h" + +#ifdef __cplusplus +} +#endif + +#endif /* COAP_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_address.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_address.h new file mode 100644 index 000000000..2c9e4c2b7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_address.h @@ -0,0 +1,213 @@ +/* + * coap_address.h -- representation of network addresses + * + * Copyright (C) 2010-2011,2015-2016,2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_address.h + * @brief Representation of network addresses + */ + +#ifndef COAP_ADDRESS_H_ +#define COAP_ADDRESS_H_ + +#include +#include +#include +#include +#include "libcoap.h" + +#if defined(WITH_LWIP) + +#include + +typedef struct coap_address_t { + uint16_t port; + ip_addr_t addr; +} coap_address_t; + +/** + * Returns the port from @p addr in host byte order. + */ +COAP_STATIC_INLINE uint16_t +coap_address_get_port(const coap_address_t *addr) { + return ntohs(addr->port); +} + +/** + * Sets the port field of @p addr to @p port (in host byte order). + */ +COAP_STATIC_INLINE void +coap_address_set_port(coap_address_t *addr, uint16_t port) { + addr->port = htons(port); +} + +#define _coap_address_equals_impl(A, B) \ + ((A)->port == (B)->port \ + && (!!ip_addr_cmp(&(A)->addr,&(B)->addr))) + +#define _coap_address_isany_impl(A) ip_addr_isany(&(A)->addr) + +#define _coap_is_mcast_impl(Address) ip_addr_ismulticast(&(Address)->addr) + +#elif defined(WITH_CONTIKI) + +#include "uip.h" + +typedef struct coap_address_t { + uip_ipaddr_t addr; + uint16_t port; +} coap_address_t; + +/** + * Returns the port from @p addr in host byte order. + */ +COAP_STATIC_INLINE uint16_t +coap_address_get_port(const coap_address_t *addr) { + return uip_ntohs(addr->port); +} + +/** + * Sets the port field of @p addr to @p port (in host byte order). + */ +COAP_STATIC_INLINE void +coap_address_set_port(coap_address_t *addr, uint16_t port) { + addr->port = uip_htons(port); +} + +#define _coap_address_equals_impl(A,B) \ + ((A)->port == (B)->port \ + && uip_ipaddr_cmp(&((A)->addr),&((B)->addr))) + +/** @todo implementation of _coap_address_isany_impl() for Contiki */ +#define _coap_address_isany_impl(A) 0 + +#define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr)) + +#else /* WITH_LWIP || WITH_CONTIKI */ + + /** multi-purpose address abstraction */ +typedef struct coap_address_t { + socklen_t size; /**< size of addr */ + union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + } addr; +} coap_address_t; + +/** + * Returns the port from @p addr in host byte order. + */ +uint16_t coap_address_get_port(const coap_address_t *addr); + +/** + * Set the port field of @p addr to @p port (in host byte order). + */ +void coap_address_set_port(coap_address_t *addr, uint16_t port); + +/** + * Compares given address objects @p a and @p b. This function returns @c 1 if + * addresses are equal, @c 0 otherwise. The parameters @p a and @p b must not be + * @c NULL; + */ +int coap_address_equals(const coap_address_t *a, const coap_address_t *b); + +COAP_STATIC_INLINE int +_coap_address_isany_impl(const coap_address_t *a) { + /* need to compare only relevant parts of sockaddr_in6 */ + switch (a->addr.sa.sa_family) { + case AF_INET: + return a->addr.sin.sin_addr.s_addr == INADDR_ANY; + case AF_INET6: + return memcmp(&in6addr_any, + &a->addr.sin6.sin6_addr, + sizeof(in6addr_any)) == 0; + default: + ; + } + + return 0; +} +#endif /* WITH_LWIP || WITH_CONTIKI */ + +/** + * Resets the given coap_address_t object @p addr to its default values. In + * particular, the member size must be initialized to the available size for + * storing addresses. + * + * @param addr The coap_address_t object to initialize. + */ +void coap_address_init(coap_address_t *addr); + +/* Convenience function to copy IPv6 addresses without garbage. */ + +COAP_STATIC_INLINE void +coap_address_copy( coap_address_t *dst, const coap_address_t *src ) { +#if defined(WITH_LWIP) || defined(WITH_CONTIKI) + memcpy( dst, src, sizeof( coap_address_t ) ); +#else + memset( dst, 0, sizeof( coap_address_t ) ); + dst->size = src->size; + if ( src->addr.sa.sa_family == AF_INET6 ) { + dst->addr.sin6.sin6_family = src->addr.sin6.sin6_family; + dst->addr.sin6.sin6_addr = src->addr.sin6.sin6_addr; + dst->addr.sin6.sin6_port = src->addr.sin6.sin6_port; + dst->addr.sin6.sin6_scope_id = src->addr.sin6.sin6_scope_id; + } else if ( src->addr.sa.sa_family == AF_INET ) { + dst->addr.sin = src->addr.sin; + } else { + memcpy( &dst->addr, &src->addr, src->size ); + } +#endif +} + +#if defined(WITH_LWIP) || defined(WITH_CONTIKI) +/** + * Compares given address objects @p a and @p b. This function returns @c 1 if + * addresses are equal, @c 0 otherwise. The parameters @p a and @p b must not be + * @c NULL; + */ +COAP_STATIC_INLINE int +coap_address_equals(const coap_address_t *a, const coap_address_t *b) { + assert(a); assert(b); + return _coap_address_equals_impl(a, b); +} +#endif + +/** + * Checks if given address object @p a denotes the wildcard address. This + * function returns @c 1 if this is the case, @c 0 otherwise. The parameters @p + * a must not be @c NULL; + */ +COAP_STATIC_INLINE int +coap_address_isany(const coap_address_t *a) { + assert(a); + return _coap_address_isany_impl(a); +} + +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) + +/** + * Checks if given address @p a denotes a multicast address. This function + * returns @c 1 if @p a is multicast, @c 0 otherwise. + */ +int coap_is_mcast(const coap_address_t *a); +#else /* !WITH_LWIP && !WITH_CONTIKI */ +/** + * Checks if given address @p a denotes a multicast address. This function + * returns @c 1 if @p a is multicast, @c 0 otherwise. + */ +COAP_STATIC_INLINE int +coap_is_mcast(const coap_address_t *a) { + return a && _coap_is_mcast_impl(a); +} +#endif /* !WITH_LWIP && !WITH_CONTIKI */ + +#endif /* COAP_ADDRESS_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_asn1_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_asn1_internal.h new file mode 100644 index 000000000..cfd29c696 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_asn1_internal.h @@ -0,0 +1,90 @@ +/* + * coap_asn1_internal.h -- ASN.1 functions for libcoap + * + * Copyright (C) 2020 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_asn1_internal.h + * @brief CoAP ASN.1 internal information + */ + +#ifndef COAP_ASN1_INTERNAL_H_ +#define COAP_ASN1_INTERNAL_H_ + +#include "coap_internal.h" + +/** + * @ingroup internal_api + * @defgroup asn1 ASN.1 Support + * Internal API for CoAP ASN.1 handling + * @{ + */ + +typedef enum { + COAP_ASN1_NONE = 0, + COAP_ASN1_INTEGER = 2, + COAP_ASN1_BITSTRING = 3, + COAP_ASN1_OCTETSTRING = 4, + COAP_ASN1_IDENTIFIER = 6, +} coap_asn1_tag_t; + +/** + * Callback to validate the asn1 tag and data. + * + * Internal function. + * + * @param data The start of the tag and data + * @param size The size of the tag and data + * + * @return @c 1 if pass, else @c 0 if fail + */ +typedef int (*asn1_validate)(const uint8_t *data, size_t size); + +/** + * Get the asn1 length from the current @p ptr. + * + * Internal function. + * + * @param ptr The current asn.1 object length pointer + * + * @return The length of the asn.1 object. @p ptr is updated to be after the length. + */ +size_t asn1_len(const uint8_t **ptr); + +/** + * Get the asn1 tag from the current @p ptr. + * + * Internal function. + * + * @param ptr The current asn.1 object tag pointer + * @param constructed 1 if current tag is constructed + * @param class The current class of the tag + * + * @return The tag value.@p ptr is updated to be after the tag. + */ +coap_asn1_tag_t asn1_tag_c(const uint8_t **ptr, int *constructed, int *class); + +/** + * Get the asn1 tag and data from the current @p ptr. + * + * Internal function. + * + * @param ltag The tag to look for + * @param ptr The current asn.1 object pointer + * @param tlen The remaining size oof the asn.1 data + * @param validate Call validate to verify tag data or @c NULL + * + * @return The asn.1 tag and data or @c NULL if not found + */ +coap_binary_t *get_asn1_tag(coap_asn1_tag_t ltag, const uint8_t *ptr, + size_t tlen, asn1_validate validate); + +/** @} */ + +#endif /* COAP_ASN1_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_async.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_async.h new file mode 100644 index 000000000..62e4f6367 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_async.h @@ -0,0 +1,128 @@ +/* + * coap_async.h -- state management for asynchronous messages + * + * Copyright (C) 2010-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_async.h + * @brief State management for asynchronous messages + */ + +#ifndef COAP_ASYNC_H_ +#define COAP_ASYNC_H_ + +#include "net.h" + +/** + * @ingroup application_api + * @defgroup coap_async Asynchronous Messaging + * @{ + * API for delayed "separate" messages. + * A coap_context_t object holds a list of coap_async_t objects that can + * be used to generate a separate response in the case a result of a request + * cannot be delivered immediately. + */ + +/** + * Returns @c 1 if libcoap was built with separate messages enabled, + * @c 0 otherwise. + */ +int coap_async_is_supported(void); + +/** + * Allocates a new coap_async_t object and fills its fields according to + * the given @p request. This function returns a pointer to the registered + * coap_async_t object or @c NULL on error. Note that this function will + * return @c NULL in case that an object with the same identifier is already + * registered. + * + * When the delay expires, a copy of the @p request will get sent to the + * appropriate request handler. + * + * @param session The session that is used for asynchronous transmissions. + * @param request The request that is handled asynchronously. + * @param delay The amount of time to delay before sending response, 0 means + * wait forever. + * + * @return A pointer to the registered coap_async_t object or @c + * NULL in case of an error. + */ +coap_async_t * +coap_register_async(coap_session_t *session, + const coap_pdu_t *request, + coap_tick_t delay); + +/** + * Update the delay timeout, so changing when the registered @p async triggers. + * + * When the new delay expires, a copy of the original request will get sent to + * the appropriate request handler. + * + * @param async The object to update. + * @param delay The amount of time to delay before sending response, 0 means + * wait forever. + */ +void +coap_async_set_delay(coap_async_t *async, coap_tick_t delay); + +/** + * Trigger the registered @p async. + * + * A copy of the original request will get sent to the appropriate request + * handler. + * + * @param async The async object to trigger. + */ +void +coap_async_trigger(coap_async_t *async); + +/** + * Releases the memory that was allocated by coap_register_async() for the + * object @p async. + * + * @param session The session to use. + * @param async The object to delete. + */ +void +coap_free_async(coap_session_t *session, coap_async_t *async); + +/** + * Retrieves the object identified by @p token from the list of asynchronous + * transactions that are registered with @p context. This function returns a + * pointer to that object or @c NULL if not found. + * + * @param session The session that is used for asynchronous transmissions. + * @param token The PDU's token of the object to retrieve. + * + * @return A pointer to the object identified by @p token or @c NULL if + * not found. + */ +coap_async_t *coap_find_async(coap_session_t *session, coap_bin_const_t token); + +/** + * Set the application data pointer held in @p async. This overwrites any + * existing data pointer. + * + * @param async The async state object. + * @param app_data The pointer to the data. + */ +void coap_async_set_app_data(coap_async_t *async, void *app_data); + +/** + * Gets the application data pointer held in @p async. + * + * @param async The async state object. + * + * @return The applicaton data pointer. + */ +void *coap_async_get_app_data(const coap_async_t *async); + +/** @} */ + +#endif /* COAP_ASYNC_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_async_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_async_internal.h new file mode 100644 index 000000000..e8d343c10 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_async_internal.h @@ -0,0 +1,69 @@ +/* + * coap_async_internal.h -- state management for asynchronous messages + * + * Copyright (C) 2010-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_async_internal.h + * @brief CoAP async internal information + */ + +#ifndef COAP_ASYNC_INTERNAL_H_ +#define COAP_ASYNC_INTERNAL_H_ + +#include "coap_internal.h" +#include "net.h" + +/* Note that if COAP_SERVER_SUPPORT is not set, then WITHOUT_ASYNC undefined */ +#ifndef WITHOUT_ASYNC + +/** + * @ingroup internal_api + * @defgroup coap_async_internal Asynchronous Messaging + * @{ + * Internal API for CoAP Asynchronous processing. + * A coap_context_t object holds a list of coap_async_t objects that can be + * used to generate a separate response in the case a result of a request cannot + * be delivered immediately. + */ +struct coap_async_t { + struct coap_async_t *next; /**< internally used for linking */ + coap_tick_t delay; /**< When to delay to before triggering the response + 0 indicates never trigger */ + coap_session_t *session; /**< transaction session */ + coap_pdu_t *pdu; /**< copy of request pdu */ + void* appdata; /** User definable data pointer */ +}; + +/** + * Checks if there are any pending Async requests - if so, send them off. + * Otherewise return the time remaining for the next Async to be triggered + * or 0 if nothing to do. + * + * @param context The current context. + * @param now The current time in ticks. + * + * @return The tick time before the next Async needs to go, else 0 if + * nothing to do. + */ +coap_tick_t coap_check_async(coap_context_t *context, coap_tick_t now); + +/** + * Removes and frees off all of the async entries for the given context. + * + * @param context The context to remove all async entries from. + */ +void +coap_delete_all_async(coap_context_t *context); + +/** @} */ + +#endif /* WITHOUT_ASYNC */ + +#endif /* COAP_ASYNC_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_block_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_block_internal.h new file mode 100644 index 000000000..fe5c7d3a7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_block_internal.h @@ -0,0 +1,231 @@ +/* + * coap_block_internal.h -- Structures, Enums & Functions that are not + * exposed to application programming + * + * Copyright (C) 2010-2022 Olaf Bergmann + * Copyright (C) 2021-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_block_internal.h + * @brief CoAP block internal information + */ + +#ifndef COAP_BLOCK_INTERNAL_H_ +#define COAP_BLOCK_INTERNAL_H_ + +#include "coap_internal.h" +#include "coap_pdu_internal.h" +#include "resource.h" + +/** + * @ingroup internal_api + * @defgroup block_internal Block Transfer + * Internal API for Block Transfer (RC7959) + * @{ + */ + +typedef enum { + COAP_RECURSE_OK, + COAP_RECURSE_NO +} coap_recurse_t; + +struct coap_lg_range { + uint32_t begin; + uint32_t end; +}; + +#define COAP_RBLOCK_CNT 4 +/** + * Structure to keep track of received blocks + */ +typedef struct coap_rblock_t { + uint32_t used; + uint32_t retry; + struct coap_lg_range range[COAP_RBLOCK_CNT]; + coap_tick_t last_seen; +} coap_rblock_t; + +/** + * Structure to keep track of block1 specific information + * (Requests) + */ +typedef struct coap_l_block1_t { + coap_binary_t *app_token; /**< original PDU token */ + uint64_t state_token; /**< state token */ + size_t bert_size; /**< size of last BERT block */ + uint32_t count; /**< the number of packets sent for payload */ +} coap_l_block1_t; + +/** + * Structure to keep track of block2 specific information + * (Responses) + */ +typedef struct coap_l_block2_t { + coap_resource_t *resource; /**< associated resource */ + coap_string_t *query; /**< Associated query for the resource */ + uint64_t etag; /**< ETag value */ + coap_time_t maxage_expire; /**< When this entry expires */ + coap_pdu_code_t request_method; /**< Method used to request this data */ +} coap_l_block2_t; + +/** + * Structure to hold large body (many blocks) transmission information + */ +struct coap_lg_xmit_t { + struct coap_lg_xmit_t *next; + uint8_t blk_size; /**< large block transmission size */ + uint16_t option; /**< large block transmisson CoAP option */ + int last_block; /**< last acknowledged block number */ + const uint8_t *data; /**< large data ptr */ + size_t length; /**< large data length */ + size_t offset; /**< large data next offset to transmit */ + union { + coap_l_block1_t b1; + coap_l_block2_t b2; + } b; + coap_pdu_t pdu; /**< skeletal PDU */ + coap_tick_t last_payload; /**< Last time MAX_PAYLOAD was sent or 0 */ + coap_tick_t last_sent; /**< Last time any data sent */ + coap_tick_t last_all_sent; /**< Last time all data sent or 0 */ + coap_tick_t last_obs; /**< Last time used (Observe tracking) or 0 */ + coap_release_large_data_t release_func; /**< large data de-alloc function */ + void *app_ptr; /**< applicaton provided ptr for de-alloc function */ +}; + +#if COAP_CLIENT_SUPPORT +/** + * Structure to hold large body (many blocks) client receive information + */ +struct coap_lg_crcv_t { + struct coap_lg_crcv_t *next; + uint8_t observe[3]; /**< Observe data (if observe_set) (only 24 bits) */ + uint8_t observe_length;/**< Length of observe data */ + uint8_t observe_set; /**< Set if this is an observe receive PDU */ + uint8_t szx; /**< size of individual blocks */ + uint8_t etag_set; /**< Set if ETag is in receive PDU */ + uint8_t etag_length; /**< ETag length */ + uint8_t etag[8]; /**< ETag for block checking */ + uint16_t content_format; /**< Content format for the set of blocks */ + uint8_t last_type; /**< Last request type (CON/NON) */ + uint8_t initial; /**< If set, has not been used yet */ + uint16_t block_option; /**< Block option in use */ + uint16_t retry_counter; /**< Retry counter (part of state token) */ + size_t total_len; /**< Length as indicated by SIZE2 option */ + coap_binary_t *body_data; /**< Used for re-assembling entire body */ + coap_binary_t *app_token; /**< app requesting PDU token */ + coap_binary_t *obs_token; /**< Initial Observe response PDU token */ + uint64_t state_token; /**< state token */ + coap_pdu_t pdu; /**< skeletal PDU */ + coap_rblock_t rec_blocks; /** < list of received blocks */ + coap_tick_t last_used; /**< Last time all data sent or 0 */ +}; +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +/** + * Structure to hold large body (many blocks) server receive information + */ +struct coap_lg_srcv_t { + struct coap_lg_srcv_t *next; + uint8_t observe[3]; /**< Observe data (if set) (only 24 bits) */ + uint8_t observe_length;/**< Length of observe data */ + uint8_t observe_set; /**< Set if this is an observe receive PDU */ + uint8_t rtag_set; /**< Set if RTag is in receive PDU */ + uint8_t rtag_length; /**< RTag length */ + uint8_t rtag[8]; /**< RTag for block checking */ + uint16_t content_format; /**< Content format for the set of blocks */ + uint8_t last_type; /**< Last request type (CON/NON) */ + uint8_t szx; /**< size of individual blocks */ + size_t total_len; /**< Length as indicated by SIZE1 option */ + coap_binary_t *body_data; /**< Used for re-assembling entire body */ + size_t amount_so_far; /**< Amount of data seen so far */ + coap_resource_t *resource; /**< associated resource */ + coap_str_const_t *uri_path; /** set to uri_path if unknown resource */ + coap_rblock_t rec_blocks; /** < list of received blocks */ + uint8_t last_token[8]; /**< last used token */ + size_t last_token_length; /**< length of token */ + coap_mid_t last_mid; /**< Last received mid for this set of packets */ + coap_tick_t last_used; /**< Last time data sent or 0 */ + uint16_t block_option; /**< Block option in use */ +}; +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +coap_lg_crcv_t * coap_block_new_lg_crcv(coap_session_t *session, + coap_pdu_t *pdu); + +void coap_block_delete_lg_crcv(coap_session_t *session, + coap_lg_crcv_t *lg_crcv); + +int coap_block_check_lg_crcv_timeouts(coap_session_t *session, + coap_tick_t now, + coap_tick_t *tim_rem); +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +void coap_block_delete_lg_srcv(coap_session_t *session, + coap_lg_srcv_t *lg_srcv); + +int coap_block_check_lg_srcv_timeouts(coap_session_t *session, + coap_tick_t now, + coap_tick_t *tim_rem); + +int coap_handle_request_send_block(coap_session_t *session, + coap_pdu_t *pdu, + coap_pdu_t *response, + coap_resource_t *resource, + coap_string_t *query); + +int coap_handle_request_put_block(coap_context_t *context, + coap_session_t *session, + coap_pdu_t *pdu, + coap_pdu_t *response, + coap_resource_t *resource, + coap_string_t *uri_path, + coap_opt_t *observe, + coap_string_t *query, + coap_method_handler_t h, + int *added_block); +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +int coap_handle_response_send_block(coap_session_t *session, coap_pdu_t *sent, + coap_pdu_t *rcvd); + +int coap_handle_response_get_block(coap_context_t *context, + coap_session_t *session, + coap_pdu_t *sent, + coap_pdu_t *rcvd, + coap_recurse_t recursive); +#endif /* COAP_CLIENT_SUPPORT */ + +void coap_block_delete_lg_xmit(coap_session_t *session, + coap_lg_xmit_t *lg_xmit); + +int coap_block_check_lg_xmit_timeouts(coap_session_t *session, + coap_tick_t now, + coap_tick_t *tim_rem); + +/** + * The function checks that the code in a newly formed lg_xmit created by + * coap_add_data_large_response() is updated. + * + * @param session The session + * @param response The response PDU to to check + * @param resource The requested resource + * @param query The requested query + * @param request_method The requested method + */ +void coap_check_code_lg_xmit(coap_session_t *session, coap_pdu_t *response, + coap_resource_t *resource, coap_string_t *query, + coap_pdu_code_t request_method); + +/** @} */ + +#endif /* COAP_BLOCK_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_cache.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_cache.h new file mode 100644 index 000000000..1e1cd6740 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_cache.h @@ -0,0 +1,234 @@ +/* coap_cache.h -- Caching of CoAP requests +* +* Copyright (C) 2020-2022 Olaf Bergmann +* + * SPDX-License-Identifier: BSD-2-Clause + * +* This file is part of the CoAP library libcoap. Please see +* README for terms of use. +*/ + +/** + * @file coap_cache.h + * @brief Provides a simple cache request storage for CoAP requests + */ + +#ifndef COAP_CACHE_H_ +#define COAP_CACHE_H_ + +#include "coap_forward_decls.h" + +/** + * @ingroup application_api + * @defgroup cache Cache Support + * API for Cache-Key and Cache-Entry. + * See https://datatracker.ietf.org/doc/html/rfc7252#section-5.4.2 + * @{ + */ + +/** + * Callback to free off the app data when the cache-entry is + * being deleted / freed off. + * + * @param data The app data to be freed off. + */ +typedef void (*coap_cache_app_data_free_callback_t)(void *data); + +typedef enum coap_cache_session_based_t { + COAP_CACHE_NOT_SESSION_BASED, + COAP_CACHE_IS_SESSION_BASED +} coap_cache_session_based_t; + +typedef enum coap_cache_record_pdu_t { + COAP_CACHE_NOT_RECORD_PDU, + COAP_CACHE_RECORD_PDU +} coap_cache_record_pdu_t; + +/** + * Calculates a cache-key for the given CoAP PDU. See + * https://tools.ietf.org/html/rfc7252#section-5.4.2 + * for an explanation of CoAP cache keys. + * + * Specific CoAP options can be removed from the cache-key. Examples of + * this are the Block1 and Block2 options - which make no real sense including + * them in a client or server environment, but should be included in a proxy + * caching environment where things are cached on a per block basis. + * This is done globally by calling the coap_cache_ignore_options() + * function. + * + * NOTE: The returned cache-key needs to be freed off by the caller by + * calling coap_cache_delete_key(). + * + * @param session The session to add into cache-key if @p session_based + * is set. + * @param pdu The CoAP PDU for which a cache-key is to be + * calculated. + * @param session_based COAP_CACHE_IS_SESSION_BASED if session based + * cache-key, else COAP_CACHE_NOT_SESSION_BASED. + * + * @return The returned cache-key or @c NULL if failure. + */ +coap_cache_key_t *coap_cache_derive_key(const coap_session_t *session, + const coap_pdu_t *pdu, + coap_cache_session_based_t session_based); + +/** + * Calculates a cache-key for the given CoAP PDU. See + * https://tools.ietf.org/html/rfc7252#section-5.4.2 + * for an explanation of CoAP cache keys. + * + * Specific CoAP options can be removed from the cache-key. Examples of + * this are the Block1 and Block2 options - which make no real sense including + * them in a client or server environment, but should be included in a proxy + * caching environment where things are cached on a per block basis. + * This is done individually by specifying @p cache_ignore_count and + * @p cache_ignore_options . + * + * NOTE: The returned cache-key needs to be freed off by the caller by + * calling coap_cache_delete_key(). + * + * @param session The session to add into cache-key if @p session_based + * is set. + * @param pdu The CoAP PDU for which a cache-key is to be + * calculated. + * @param session_based COAP_CACHE_IS_SESSION_BASED if session based + * cache-key, else COAP_CACHE_NOT_SESSION_BASED. + * @param ignore_options The array of options to ignore. + * @param ignore_count The number of options to ignore. + * + * @return The returned cache-key or @c NULL if failure. + */ +coap_cache_key_t *coap_cache_derive_key_w_ignore(const coap_session_t *session, + const coap_pdu_t *pdu, + coap_cache_session_based_t session_based, + const uint16_t *ignore_options, + size_t ignore_count); + +/** + * Delete the cache-key. + * + * @param cache_key The cache-key to delete. + */ +void coap_delete_cache_key(coap_cache_key_t *cache_key); + +/** + * Define the CoAP options that are not to be included when calculating + * the cache-key. Options that are defined as Non-Cache and the Observe + * option are always ignored. + * + * @param context The context to save the ignored options information in. + * @param options The array of options to ignore. + * @param count The number of options to ignore. Use 0 to reset the + * options matching. + * + * @return @return @c 1 if successful, else @c 0. + */ +int coap_cache_ignore_options(coap_context_t *context, + const uint16_t *options, size_t count); + +/** + * Create a new cache-entry hash keyed by cache-key derived from the PDU. + * + * If @p session_based is set, then this cache-entry will get deleted when + * the session is freed off. + * If @p record_pdu is set, then the copied PDU will get freed off when + * this cache-entry is deleted. + * + * The cache-entry is maintained on a context hash list. + * + * @param session The session to use to derive the context from. + * @param pdu The pdu to use to generate the cache-key. + * @param record_pdu COAP_CACHE_RECORD_PDU if to take a copy of the PDU for + * later use, else COAP_CACHE_NOT_RECORD_PDU. + * @param session_based COAP_CACHE_IS_SESSION_BASED if to associate this + * cache-entry with the the session (which is embedded + * in the cache-entry), else COAP_CACHE_NOT_SESSION_BASED. + * @param idle_time Idle time in seconds before cache-entry is expired. + * If set to 0, it does not expire (but will get + * deleted if the session is deleted and it is session_based). + * + * @return The returned cache-key or @c NULL if failure. + */ +coap_cache_entry_t *coap_new_cache_entry(coap_session_t *session, + const coap_pdu_t *pdu, + coap_cache_record_pdu_t record_pdu, + coap_cache_session_based_t session_based, + unsigned int idle_time); + +/** + * Remove a cache-entry from the hash list and free off all the appropriate + * contents apart from app_data. + * + * @param context The context to use. + * @param cache_entry The cache-entry to remove. + */ +void coap_delete_cache_entry(coap_context_t *context, + coap_cache_entry_t *cache_entry); + +/** + * Searches for a cache-entry identified by @p cache_key. This + * function returns the corresponding cache-entry or @c NULL + * if not found. + * + * @param context The context to use. + * @param cache_key The cache-key to get the hashed coap-entry. + * + * @return The cache-entry for @p cache_key or @c NULL if not found. + */ +coap_cache_entry_t *coap_cache_get_by_key(coap_context_t *context, + const coap_cache_key_t *cache_key); + +/** + * Searches for a cache-entry corresponding to @p pdu. This + * function returns the corresponding cache-entry or @c NULL if not + * found. + * + * @param session The session to use. + * @param pdu The CoAP request to search for. + * @param session_based COAP_CACHE_IS_SESSION_BASED if session based + * cache-key to be used, else COAP_CACHE_NOT_SESSION_BASED. + * + * @return The cache-entry for @p request or @c NULL if not found. + */ +coap_cache_entry_t *coap_cache_get_by_pdu(coap_session_t *session, + const coap_pdu_t *pdu, + coap_cache_session_based_t session_based); + +/** + * Returns the PDU information stored in the @p coap_cache entry. + * + * @param cache_entry The CoAP cache entry. + * + * @return The PDU information stored in the cache_entry or NULL + * if the PDU was not initially copied. + */ +const coap_pdu_t *coap_cache_get_pdu(const coap_cache_entry_t *cache_entry); + +/** + * Stores @p data with the given cache entry. This function + * overwrites any value that has previously been stored with @p + * cache_entry. + * + * @param cache_entry The CoAP cache entry. + * @param data The data pointer to store with wih the cache entry. Note that + * this data must be valid during the lifetime of @p cache_entry. + * @param callback The callback to call to free off this data when the + * cache-entry is deleted, or @c NULL if not required. + */ +void coap_cache_set_app_data(coap_cache_entry_t *cache_entry, void *data, + coap_cache_app_data_free_callback_t callback); + +/** + * Returns any application-specific data that has been stored with @p + * cache_entry using the function coap_cache_set_app_data(). This function will + * return @c NULL if no data has been stored. + * + * @param cache_entry The CoAP cache entry. + * + * @return The data pointer previously stored or @c NULL if no data stored. + */ +void *coap_cache_get_app_data(const coap_cache_entry_t *cache_entry); + +/** @} */ + +#endif /* COAP_CACHE_H */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_cache_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_cache_internal.h new file mode 100644 index 000000000..764caf82a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_cache_internal.h @@ -0,0 +1,115 @@ +/* + * coap_cache_internal.h -- Cache functions for libcoap + * + * Copyright (C) 2019--2020 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_cache_internal.h + * @brief CoAP cache internal information + */ + +#ifndef COAP_CACHE_INTERNAL_H_ +#define COAP_CACHE_INTERNAL_H_ + +#include "coap_internal.h" +#include "coap_io.h" + +#if COAP_SERVER_SUPPORT +/** + * @ingroup internal_api + * @defgroup cache_internal Cache Support + * Internal API for Cache-Key and Cache-Entry support + * @{ + */ + +/* Holds a digest in binary typically sha256 except for notls */ +typedef struct coap_digest_t { + uint8_t key[32]; +} coap_digest_t; + +struct coap_cache_key_t { + uint8_t key[32]; +}; + +struct coap_cache_entry_t { + UT_hash_handle hh; + coap_cache_key_t *cache_key; + coap_session_t *session; + coap_pdu_t *pdu; + void* app_data; + coap_tick_t expire_ticks; + unsigned int idle_timeout; + coap_cache_app_data_free_callback_t callback; +}; + +/** + * Expire coap_cache_entry_t entries + * + * Internal function. + * + * @param context The context holding the coap-entries to exire + */ +void coap_expire_cache_entries(coap_context_t *context); + +typedef void coap_digest_ctx_t; + +/** + * Initialize a coap_digest + * + * Internal function. + * + * @return The digest context or @c NULL if failure. + */ +coap_digest_ctx_t *coap_digest_setup(void); + +/** + * Free off coap_digest_ctx_t. Always done by + * coap_digest_final() + * + * Internal function. + * + * @param digest_ctx The coap_digest context. + */ +void coap_digest_free(coap_digest_ctx_t *digest_ctx); + +/** + * Update the coap_digest information with the next chunk of data + * + * Internal function. + * + * @param digest_ctx The coap_digest context. + * @param data Pointer to data. + * @param data_len Number of bytes. + * + * @return @c 1 success, @c 0 failure. + */ +int coap_digest_update(coap_digest_ctx_t *digest_ctx, + const uint8_t *data, + size_t data_len + ); + +/** + * Finalize the coap_digest information into the provided + * @p digest_buffer. + * + * Internal function. + * + * @param digest_ctx The coap_digest context. + * @param digest_buffer Pointer to digest buffer to update + * + * @return @c 1 success, @c 0 failure. + */ +int coap_digest_final(coap_digest_ctx_t *digest_ctx, + coap_digest_t *digest_buffer); + +/** @} */ + +#endif /* COAP_SERVER_SUPPORT */ + +#endif /* COAP_CACHE_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_debug.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_debug.h new file mode 100644 index 000000000..4901722de --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_debug.h @@ -0,0 +1,260 @@ +/* + * coap_debug.h -- debug utilities + * + * Copyright (C) 2010-2011,2014-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_debug.h + * @brief CoAP Logging support + */ + +#ifndef COAP_DEBUG_H_ +#define COAP_DEBUG_H_ + +/** + * @ingroup application_api + * @defgroup logging Logging Support + * API for logging support + * @{ + */ + +#ifndef COAP_DEBUG_FD +/** + * Used for output for @c LOG_DEBUG to @c LOG_ERR. + */ +#define COAP_DEBUG_FD stdout +#endif + +#ifndef COAP_ERR_FD +/** + * Used for output for @c LOG_CRIT to @c LOG_EMERG. + */ +#define COAP_ERR_FD stderr +#endif + +/** + * Logging type. One of LOG_* from @b syslog. + */ +typedef int coap_log_t; + +#ifdef HAVE_SYSLOG_H +#include +#else +#if defined(RIOT_VERSION) +/* RIOT defines a subset of the syslog levels in log.h with different + * numeric values. The remaining levels are defined here. Note that + * output granularity differs from what would be expected when + * adhering to the syslog levels. + */ +#include +#endif /* RIOT_VERSION */ +#endif /* HAVE_SYSLOG_H */ + +#ifndef LOG_EMERG +# define LOG_EMERG 0 +#endif +#ifndef LOG_ALERT +# define LOG_ALERT 1 +#endif +#ifndef LOG_CRIT +# define LOG_CRIT 2 +#endif +#ifndef LOG_ERR +# define LOG_ERR 3 +#endif +#ifndef LOG_WARNING +# define LOG_WARNING 4 +#endif +#ifndef LOG_NOTICE +# define LOG_NOTICE 5 +#endif +#ifndef LOG_INFO +# define LOG_INFO 6 +#endif +#ifndef LOG_DEBUG +# define LOG_DEBUG 7 +#endif +/* + LOG_DEBUG+2 gives ciphers in GnuTLS + Use COAP_LOG_CIPHERS to output Cipher Info in OpenSSL etc. + */ +#define COAP_LOG_CIPHERS (LOG_DEBUG+2) + +/** + * Get the current logging level. + * + * @return One of the LOG_* values. + */ +coap_log_t coap_get_log_level(void); + +/** + * Sets the log level to the specified value. + * + * @param level One of the LOG_* values. + */ +void coap_set_log_level(coap_log_t level); + +/** + * Logging callback handler definition. + * + * @param level One of the LOG_* values. + * @param message Zero-terminated string message to log. + */ +typedef void (*coap_log_handler_t) (coap_log_t level, const char *message); + +/** + * Add a custom log callback handler. + * + * @param handler The logging handler to use or @p NULL to use default handler. + */ +void coap_set_log_handler(coap_log_handler_t handler); + +/** + * Get the library package name. + * + * @return Zero-terminated string with the name of this library. + */ +const char *coap_package_name(void); + +/** + * Get the library package version. + * + * @return Zero-terminated string with the library version. + */ +const char *coap_package_version(void); + +/** + * Get the library package build. + * + * @return Zero-terminated string with the library build. + */ +const char *coap_package_build(void); + +/** + * Writes the given text to @c COAP_ERR_FD (for @p level <= @c LOG_CRIT) or @c + * COAP_DEBUG_FD (for @p level >= @c LOG_ERR). The text is output only when + * @p level is below or equal to the log level that set by coap_set_log_level(). + * + * Internal function. + * + * @param level One of the LOG_* values. + & @param format The format string to use. + */ +#if (defined(__GNUC__)) +void coap_log_impl(coap_log_t level, + const char *format, ...) __attribute__ ((format(printf, 2, 3))); +#else +void coap_log_impl(coap_log_t level, const char *format, ...); +#endif + +#ifndef coap_log +/** + * Logging function. + * Writes the given text to @c COAP_ERR_FD (for @p level <= @c LOG_CRIT) or @c + * COAP_DEBUG_FD (for @p level >= @c LOG_ERR). The text is output only when + * @p level is below or equal to the log level that set by coap_set_log_level(). + * + * @param level One of the LOG_* values. + */ +#define coap_log(level, ...) do { \ + if ((int)((level))<=(int)coap_get_log_level()) \ + coap_log_impl((level), __VA_ARGS__); \ +} while(0) +#endif + +#include "pdu.h" + +/** + * Defines the output mode for the coap_show_pdu() function. + * + * @param use_fprintf @p 1 if the output is to use fprintf() (the default) + * @p 0 if the output is to use coap_log(). + */ +void coap_set_show_pdu_output(int use_fprintf); + +/** + * Display the contents of the specified @p pdu. + * Note: The output method of coap_show_pdu() is dependent on the setting of + * coap_set_show_pdu_output(). + * + * @param level The required minimum logging level. + * @param pdu The PDU to decode. + */ +void coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu); + +/** + * Display the current (D)TLS library linked with and built for version. + * + * @param level The required minimum logging level. + */ +void coap_show_tls_version(coap_log_t level); + +/** + * Build a string containing the current (D)TLS library linked with and + * built for version. + * + * @param buffer The buffer to put the string into. + * @param bufsize The size of the buffer to put the string into. + * + * @return A pointer to the provided buffer. + */ +char *coap_string_tls_version(char *buffer, size_t bufsize); + +/** + * Build a string containing the current (D)TLS library support + * + * @param buffer The buffer to put the string into. + * @param bufsize The size of the buffer to put the string into. + * + * @return A pointer to the provided buffer. + */ +char *coap_string_tls_support(char *buffer, size_t bufsize); + +/** + * Print the address into the defined buffer. + * + * Internal Function. + * + * @param address The address to print. + * @param buffer The buffer to print into. + * @param size The size of the buffer to print into. + * + * @return The amount written into the buffer. + */ +size_t coap_print_addr(const coap_address_t *address, + unsigned char *buffer, size_t size); + +/** @} */ + +/** + * Set the packet loss level for testing. This can be in one of two forms. + * + * Percentage : 0% to 100%. Use the specified probability. + * 0% is send all packets, 100% is drop all packets. + * + * List: A comma separated list of numbers or number ranges that are the + * packets to drop. + * + * @param loss_level The defined loss level (percentage or list). + * + * @return @c 1 If loss level set, @c 0 if there is an error. + */ +int coap_debug_set_packet_loss(const char *loss_level); + +/** + * Check to see whether a packet should be sent or not. + * + * Internal function + * + * @return @c 1 if packet is to be sent, @c 0 if packet is to be dropped. + */ +int coap_debug_send_packet(void); + + +#endif /* COAP_DEBUG_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_dtls.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_dtls.h new file mode 100644 index 000000000..95ca1ec05 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_dtls.h @@ -0,0 +1,491 @@ +/* + * coap_dtls.h -- (Datagram) Transport Layer Support for libcoap + * + * Copyright (C) 2016 Olaf Bergmann + * Copyright (C) 2017 Jean-Claude Michelou + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_dtls.h + * @brief CoAP DTLS support + */ + +#ifndef COAP_DTLS_H_ +#define COAP_DTLS_H_ + +#include "coap_time.h" +#include "str.h" + +/** + * @ingroup application_api + * @defgroup dtls DTLS Support + * API for interfacing with DTLS libraries. + * @{ + */ + +typedef struct coap_dtls_pki_t coap_dtls_pki_t; + +#ifndef COAP_DTLS_HINT_LENGTH +#define COAP_DTLS_HINT_LENGTH 128 +#endif +#ifndef COAP_DTLS_MAX_PSK_IDENTITY +#define COAP_DTLS_MAX_PSK_IDENTITY 64 +#endif +#ifndef COAP_DTLS_MAX_PSK +#define COAP_DTLS_MAX_PSK 64 +#endif + +typedef enum coap_dtls_role_t { + COAP_DTLS_ROLE_CLIENT, /**< Internal function invoked for client */ + COAP_DTLS_ROLE_SERVER /**< Internal function invoked for server */ +} coap_dtls_role_t; + +#define COAP_DTLS_RPK_CERT_CN "RPK" + +/** + * Check whether DTLS is available. + * + * @return @c 1 if support for DTLS is enabled, or @c 0 otherwise. + */ +int coap_dtls_is_supported(void); + +/** + * Check whether TLS is available. + * + * @return @c 1 if support for TLS is enabled, or @c 0 otherwise. + */ +int coap_tls_is_supported(void); + +typedef enum coap_tls_library_t { + COAP_TLS_LIBRARY_NOTLS = 0, /**< No DTLS library */ + COAP_TLS_LIBRARY_TINYDTLS, /**< Using TinyDTLS library */ + COAP_TLS_LIBRARY_OPENSSL, /**< Using OpenSSL library */ + COAP_TLS_LIBRARY_GNUTLS, /**< Using GnuTLS library */ + COAP_TLS_LIBRARY_MBEDTLS, /**< Using Mbed TLS library */ +} coap_tls_library_t; + +/** + * The structure used for returning the underlying (D)TLS library + * information. + */ +typedef struct coap_tls_version_t { + uint64_t version; /**< (D)TLS runtime Library Version */ + coap_tls_library_t type; /**< Library type. One of COAP_TLS_LIBRARY_* */ + uint64_t built_version; /**< (D)TLS Built against Library Version */ +} coap_tls_version_t; + +/** + * Determine the type and version of the underlying (D)TLS library. + * + * @return The version and type of library libcoap was compiled against. + */ +coap_tls_version_t *coap_get_tls_library_version(void); + +/** + * Additional Security setup handler that can be set up by + * coap_context_set_pki(). + * Invoked when libcoap has done the validation checks at the TLS level, + * but the application needs to do some additional checks/changes/updates. + * + * @param tls_session The security session definition - e.g. SSL * for OpenSSL. + * NULL if server callback. + * This will be dependent on the underlying TLS library - + * see coap_get_tls_library_version() + * @param setup_data A structure containing setup data originally passed into + * coap_context_set_pki() or coap_new_client_session_pki(). + * + * @return @c 1 if successful, else @c 0. + */ +typedef int (*coap_dtls_security_setup_t)(void* tls_session, + coap_dtls_pki_t *setup_data); + +/** + * CN Validation callback that can be set up by coap_context_set_pki(). + * Invoked when libcoap has done the validation checks at the TLS level, + * but the application needs to check that the CN is allowed. + * CN is the SubjectAltName in the cert, if not present, then the leftmost + * Common Name (CN) component of the subject name. + * NOTE: If using RPK, then the Public Key does not contain a CN, but the + * content of COAP_DTLS_RPK_CERT_CN is presented for the @p cn parameter. + * + * @param cn The determined CN from the certificate + * @param asn1_public_cert The ASN.1 DER encoded X.509 certificate + * @param asn1_length The ASN.1 length + * @param coap_session The CoAP session associated with the certificate update + * @param depth Depth in cert chain. If 0, then client cert, else a CA + * @param validated TLS layer can find no issues if 1 + * @param arg The same as was passed into coap_context_set_pki() + * in setup_data->cn_call_back_arg + * + * @return @c 1 if accepted, else @c 0 if to be rejected. + */ +typedef int (*coap_dtls_cn_callback_t)(const char *cn, + const uint8_t *asn1_public_cert, + size_t asn1_length, + coap_session_t *coap_session, + unsigned int depth, + int validated, + void *arg); + +/** + * The enum used for determining the provided PKI ASN.1 (DER) Private Key + * formats. + */ +typedef enum coap_asn1_privatekey_type_t { + COAP_ASN1_PKEY_NONE, /**< NONE */ + COAP_ASN1_PKEY_RSA, /**< RSA type */ + COAP_ASN1_PKEY_RSA2, /**< RSA2 type */ + COAP_ASN1_PKEY_DSA, /**< DSA type */ + COAP_ASN1_PKEY_DSA1, /**< DSA1 type */ + COAP_ASN1_PKEY_DSA2, /**< DSA2 type */ + COAP_ASN1_PKEY_DSA3, /**< DSA3 type */ + COAP_ASN1_PKEY_DSA4, /**< DSA4 type */ + COAP_ASN1_PKEY_DH, /**< DH type */ + COAP_ASN1_PKEY_DHX, /**< DHX type */ + COAP_ASN1_PKEY_EC, /**< EC type */ + COAP_ASN1_PKEY_HMAC, /**< HMAC type */ + COAP_ASN1_PKEY_CMAC, /**< CMAC type */ + COAP_ASN1_PKEY_TLS1_PRF, /**< TLS1_PRF type */ + COAP_ASN1_PKEY_HKDF /**< HKDF type */ +} coap_asn1_privatekey_type_t; + +/** + * The enum used for determining the PKI key formats. + */ +typedef enum coap_pki_key_t { + COAP_PKI_KEY_PEM = 0, /**< The PKI key type is PEM file */ + COAP_PKI_KEY_ASN1, /**< The PKI key type is ASN.1 (DER) buffer */ + COAP_PKI_KEY_PEM_BUF, /**< The PKI key type is PEM buffer */ + COAP_PKI_KEY_PKCS11, /**< The PKI key type is PKCS11 (DER) */ +} coap_pki_key_t; + +/** + * The structure that holds the PKI PEM definitions. + */ +typedef struct coap_pki_key_pem_t { + const char *ca_file; /**< File location of Common CA in PEM format */ + const char *public_cert; /**< File location of Public Cert */ + const char *private_key; /**< File location of Private Key in PEM format */ +} coap_pki_key_pem_t; + +/** + * The structure that holds the PKI PEM buffer definitions. + * The certificates and private key data must be in PEM format. + * + * Note: The Certs and Key should be NULL terminated strings for + * performance reasons (to save a potential buffer copy) and the length include + * this NULL terminator. It is not a requirement to have the NULL terminator + * though and the length must then reflect the actual data size. + */ +typedef struct coap_pki_key_pem_buf_t { + const uint8_t *ca_cert; /**< PEM buffer Common CA Cert */ + const uint8_t *public_cert; /**< PEM buffer Public Cert, or Public Key if RPK */ + const uint8_t *private_key; /**< PEM buffer Private Key + If RPK and 'EC PRIVATE KEY' this can be used + for both the public_cert and private_key */ + size_t ca_cert_len; /**< PEM buffer CA Cert length */ + size_t public_cert_len; /**< PEM buffer Public Cert length */ + size_t private_key_len; /**< PEM buffer Private Key length */ +} coap_pki_key_pem_buf_t; + +/** + * The structure that holds the PKI ASN.1 (DER) definitions. + */ +typedef struct coap_pki_key_asn1_t { + const uint8_t *ca_cert; /**< ASN1 (DER) Common CA Cert */ + const uint8_t *public_cert; /**< ASN1 (DER) Public Cert, or Public Key if RPK */ + const uint8_t *private_key; /**< ASN1 (DER) Private Key */ + size_t ca_cert_len; /**< ASN1 CA Cert length */ + size_t public_cert_len; /**< ASN1 Public Cert length */ + size_t private_key_len; /**< ASN1 Private Key length */ + coap_asn1_privatekey_type_t private_key_type; /**< Private Key Type */ +} coap_pki_key_asn1_t; + +/** + * The structure that holds the PKI PKCS11 definitions. + */ +typedef struct coap_pki_key_pkcs11_t { + const char *ca; /**< pkcs11: URI for Common CA Certificate */ + const char *public_cert; /**< pkcs11: URI for Public Cert */ + const char *private_key; /**< pkcs11: URI for Private Key */ + const char *user_pin; /**< User pin to access PKCS11. If NULL, then + pin-value= parameter must be set in + pkcs11: URI as a query. */ +} coap_pki_key_pkcs11_t; + +/** + * The structure that holds the PKI key information. + */ +typedef struct coap_dtls_key_t { + coap_pki_key_t key_type; /**< key format type */ + union { + coap_pki_key_pem_t pem; /**< for PEM file keys */ + coap_pki_key_pem_buf_t pem_buf; /**< for PEM memory keys */ + coap_pki_key_asn1_t asn1; /**< for ASN.1 (DER) memory keys */ + coap_pki_key_pkcs11_t pkcs11; /**< for PKCS11 keys */ + } key; +} coap_dtls_key_t; + +/** + * Server Name Indication (SNI) Validation callback that can be set up by + * coap_context_set_pki(). + * Invoked if the SNI is not previously seen and prior to sending a certificate + * set back to the client so that the appropriate certificate set can be used + * based on the requesting SNI. + * + * @param sni The requested SNI + * @param arg The same as was passed into coap_context_set_pki() + * in setup_data->sni_call_back_arg + * + * @return New set of certificates to use, or @c NULL if SNI is to be rejected. + */ +typedef coap_dtls_key_t *(*coap_dtls_pki_sni_callback_t)(const char *sni, + void* arg); + + +#define COAP_DTLS_PKI_SETUP_VERSION 1 /**< Latest PKI setup version */ + +/** + * The structure used for defining the PKI setup data to be used. + */ +struct coap_dtls_pki_t { + uint8_t version; /** Set to COAP_DTLS_PKI_SETUP_VERSION + to support this version of the struct */ + + /* Options to enable different TLS functionality in libcoap */ + uint8_t verify_peer_cert; /**< 1 if peer cert is to be verified */ + uint8_t check_common_ca; /**< 1 if peer cert is to be signed by + * the same CA as the local cert */ + uint8_t allow_self_signed; /**< 1 if self-signed certs are allowed. + * Ignored if check_common_ca set */ + uint8_t allow_expired_certs; /**< 1 if expired certs are allowed */ + uint8_t cert_chain_validation; /**< 1 if to check cert_chain_verify_depth */ + uint8_t cert_chain_verify_depth; /**< recommended depth is 3 */ + uint8_t check_cert_revocation; /**< 1 if revocation checks wanted */ + uint8_t allow_no_crl; /**< 1 ignore if CRL not there */ + uint8_t allow_expired_crl; /**< 1 if expired crl is allowed */ + uint8_t allow_bad_md_hash; /**< 1 if unsupported MD hashes are allowed */ + uint8_t allow_short_rsa_length; /**< 1 if small RSA keysizes are allowed */ + uint8_t is_rpk_not_cert; /**< 1 is RPK instead of Public Certificate. + * If set, PKI key format type cannot be + * COAP_PKI_KEY_PEM */ + uint8_t reserved[3]; /**< Reserved - must be set to 0 for + future compatibility */ + /* Size of 3 chosen to align to next + * parameter, so if newly defined option + * it can use one of the reserverd slot so + * no need to change + * COAP_DTLS_PKI_SETUP_VERSION and just + * decrement the reserved[] count. + */ + + /** CN check callback function. + * If not NULL, is called when the TLS connection has passed the configured + * TLS options above for the application to verify if the CN is valid. + */ + coap_dtls_cn_callback_t validate_cn_call_back; + void *cn_call_back_arg; /**< Passed in to the CN callback function */ + + /** SNI check callback function. + * If not @p NULL, called if the SNI is not previously seen and prior to + * sending a certificate set back to the client so that the appropriate + * certificate set can be used based on the requesting SNI. + */ + coap_dtls_pki_sni_callback_t validate_sni_call_back; + void *sni_call_back_arg; /**< Passed in to the sni callback function */ + + /** Additional Security callback handler that is invoked when libcoap has + * done the standard, defined validation checks at the TLS level, + * If not @p NULL, called from within the TLS Client Hello connection + * setup. + */ + coap_dtls_security_setup_t additional_tls_setup_call_back; + + char* client_sni; /**< If not NULL, SNI to use in client TLS setup. + Owned by the client app and must remain valid + during the call to coap_new_client_session_pki() */ + + coap_dtls_key_t pki_key; /**< PKI key definition */ +}; + +/** + * The structure that holds the Client PSK information. + */ +typedef struct coap_dtls_cpsk_info_t { + coap_bin_const_t identity; + coap_bin_const_t key; +} coap_dtls_cpsk_info_t; + +/** + * Identity Hint Validation callback that can be set up by + * coap_new_client_session_psk2(). + * Invoked when libcoap has done the validation checks at the TLS level, + * but the application needs to check that the Identity Hint is allowed, + * and thus needs to use the appropriate PSK information for the Identity + * Hint for the (D)TLS session. + * Note: Identity Hint is not supported in (D)TLS1.3. + * + * @param hint The server provided Identity Hint + * @param coap_session The CoAP session associated with the Identity Hint + * @param arg The same as was passed into coap_new_client_session_psk2() + * in setup_data->ih_call_back_arg + * + * @return New coap_dtls_cpsk_info_t object or @c NULL on error. + */ +typedef const coap_dtls_cpsk_info_t *(*coap_dtls_ih_callback_t)( + coap_str_const_t *hint, + coap_session_t *coap_session, + void *arg); + +#define COAP_DTLS_CPSK_SETUP_VERSION 1 /**< Latest CPSK setup version */ + +/** + * The structure used for defining the Client PSK setup data to be used. + */ +typedef struct coap_dtls_cpsk_t { + uint8_t version; /** Set to COAP_DTLS_CPSK_SETUP_VERSION + to support this version of the struct */ + + /* Options to enable different TLS functionality in libcoap */ + uint8_t reserved[7]; /**< Reserved - must be set to 0 for + future compatibility */ + /* Size of 7 chosen to align to next + * parameter, so if newly defined option + * it can use one of the reserverd slot so + * no need to change + * COAP_DTLS_CPSK_SETUP_VERSION and just + * decrement the reserved[] count. + */ + + /** Identity Hint check callback function. + * If not NULL, is called when the Identity Hint (TLS1.2 or earlier) is + * provided by the server. + * The appropriate Identity and Pre-shared Key to use can then be returned. + */ + coap_dtls_ih_callback_t validate_ih_call_back; + void *ih_call_back_arg; /**< Passed in to the Identity Hint callback + function */ + + char* client_sni; /**< If not NULL, SNI to use in client TLS setup. + Owned by the client app and must remain valid + during the call to coap_new_client_session_psk2() + Note: Not supported by TinyDTLS. */ + + coap_dtls_cpsk_info_t psk_info; /**< Client PSK definition */ +} coap_dtls_cpsk_t; + +/** + * The structure that holds the Server Pre-Shared Key and Identity + * Hint information. + */ +typedef struct coap_dtls_spsk_info_t { + coap_bin_const_t hint; + coap_bin_const_t key; +} coap_dtls_spsk_info_t; + + +/** + * Identity Validation callback that can be set up by + * coap_context_set_psk2(). + * Invoked when libcoap has done the validation checks at the TLS level, + * but the application needs to check that the Identity is allowed, + * and needs to use the appropriate Pre-Shared Key for the (D)TLS session. + * + * @param identity The client provided Identity + * @param coap_session The CoAP session associated with the Identity Hint + * @param arg The value as passed into coap_context_set_psk2() + * in setup_data->id_call_back_arg + * + * @return New coap_bin_const_t object containing the Pre-Shared Key or + @c NULL on error. + * Note: This information will be duplicated into an internal + * structure. + */ +typedef const coap_bin_const_t *(*coap_dtls_id_callback_t)( + coap_bin_const_t *identity, + coap_session_t *coap_session, + void *arg); +/** + * PSK SNI callback that can be set up by coap_context_set_psk2(). + * Invoked when libcoap has done the validation checks at the TLS level + * and the application needs to:- + * a) check that the SNI is allowed + * b) provide the appropriate PSK information for the (D)TLS session. + * + * @param sni The client provided SNI + * @param coap_session The CoAP session associated with the SNI + * @param arg The same as was passed into coap_context_set_psk2() + * in setup_data->sni_call_back_arg + * + * @return New coap_dtls_spsk_info_t object or @c NULL on error. + */ +typedef const coap_dtls_spsk_info_t *(*coap_dtls_psk_sni_callback_t)( + const char *sni, + coap_session_t *coap_session, + void *arg); + +#define COAP_DTLS_SPSK_SETUP_VERSION 1 /**< Latest SPSK setup version */ + +/** + * The structure used for defining the Server PSK setup data to be used. + */ +typedef struct coap_dtls_spsk_t { + uint8_t version; /** Set to COAP_DTLS_SPSK_SETUP_VERSION + to support this version of the struct */ + + /* Options to enable different TLS functionality in libcoap */ + uint8_t reserved[7]; /**< Reserved - must be set to 0 for + future compatibility */ + /* Size of 7 chosen to align to next + * parameter, so if newly defined option + * it can use one of the reserverd slot so + * no need to change + * COAP_DTLS_SPSK_SETUP_VERSION and just + * decrement the reserved[] count. + */ + + /** Identity check callback function. + * If not @p NULL, is called when the Identity is provided by the client. + * The appropriate Pre-Shared Key to use can then be returned. + */ + coap_dtls_id_callback_t validate_id_call_back; + void *id_call_back_arg; /**< Passed in to the Identity callback function */ + + /** SNI check callback function. + * If not @p NULL, called if the SNI is not previously seen and prior to + * sending PSK information back to the client so that the appropriate + * PSK information can be used based on the requesting SNI. + */ + coap_dtls_psk_sni_callback_t validate_sni_call_back; + void *sni_call_back_arg; /**< Passed in to the SNI callback function */ + + coap_dtls_spsk_info_t psk_info; /**< Server PSK definition */ +} coap_dtls_spsk_t; + + +/** @} */ + +/** + * @ingroup logging + * Sets the (D)TLS logging level to the specified @p level. + * Note: coap_log_level() will influence output if at a specified level. + * + * @param level The logging level to use - LOG_* + */ +void coap_dtls_set_log_level(int level); + +/** + * @ingroup logging + * Get the current (D)TLS logging. + * + * @return The current log level (one of LOG_*). + */ +int coap_dtls_get_log_level(void); + + +#endif /* COAP_DTLS_H */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_dtls_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_dtls_internal.h new file mode 100644 index 000000000..c9eac7172 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_dtls_internal.h @@ -0,0 +1,408 @@ +/* + * coap_dtls_internal.h -- (Datagram) Transport Layer Support for libcoap + * + * Copyright (C) 2016 Olaf Bergmann + * Copyright (C) 2017 Jean-Claude Michelou + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_dtls_internal.h + * @brief Internal CoAP DTLS support + */ + +#ifndef COAP_DTLS_INTERNAL_H_ +#define COAP_DTLS_INTERNAL_H_ + +#include "coap_internal.h" + +/** + * @ingroup internal_api + * @defgroup dtls_internal DTLS Support + * Internal API for DTLS Support + * @{ + */ + +/* https://tools.ietf.org/html/rfc6347#section-4.2.4.1 */ +#ifndef COAP_DTLS_RETRANSMIT_MS +#define COAP_DTLS_RETRANSMIT_MS 1000 +#endif +#ifndef COAP_DTLS_RETRANSMIT_TOTAL_MS +#define COAP_DTLS_RETRANSMIT_TOTAL_MS 60000 +#endif + +#define COAP_DTLS_RETRANSMIT_COAP_TICKS (COAP_DTLS_RETRANSMIT_MS * COAP_TICKS_PER_SECOND / 1000) + +/** + * Creates a new DTLS context for the given @p coap_context. This function + * returns a pointer to a new DTLS context object or @c NULL on error. + * + * @param coap_context The CoAP context where the DTLS object shall be used. + * + * @return A DTLS context object or @c NULL on error. + */ +void * +coap_dtls_new_context(coap_context_t *coap_context); + +#if COAP_SERVER_SUPPORT +/** + * Set the DTLS context's default server PSK information. + * This does the PSK specifics following coap_dtls_new_context(). + * + * @param coap_context The CoAP context. + * @param setup_data A structure containing setup data originally passed into + * coap_context_set_psk2(). + * + * @return @c 1 if successful, else @c 0. + */ + +int +coap_dtls_context_set_spsk(coap_context_t *coap_context, + coap_dtls_spsk_t *setup_data); +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +/** + * Set the DTLS context's default client PSK information. + * This does the PSK specifics following coap_dtls_new_context(). + * + * @param coap_context The CoAP context. + * @param setup_data A structure containing setup data originally passed into + * coap_new_client_session_psk2(). + * + * @return @c 1 if successful, else @c 0. + */ + +int +coap_dtls_context_set_cpsk(coap_context_t *coap_context, + coap_dtls_cpsk_t *setup_data); +#endif /* COAP_CLIENT_SUPPORT */ + +/** + * Set the DTLS context's default server PKI information. + * This does the PKI specifics following coap_dtls_new_context(). + * If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the + * TLS library's context (from which sessions are derived). + * If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the + * TLS library's session. + * + * @param coap_context The CoAP context. + * @param setup_data Setup information defining how PKI is to be setup. + * Required parameter. If @p NULL, PKI will not be + * set up. + * @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER + * + * @return @c 1 if successful, else @c 0. + */ + +int +coap_dtls_context_set_pki(coap_context_t *coap_context, + const coap_dtls_pki_t *setup_data, + const coap_dtls_role_t role); + +/** + * Set the dtls context's default Root CA information for a client or server. + * + * @param coap_context The current coap_context_t object. + * @param ca_file If not @p NULL, is the full path name of a PEM encoded + * file containing all the Root CAs to be used. + * @param ca_dir If not @p NULL, points to a directory containing PEM + * encoded files containing all the Root CAs to be used. + * + * @return @c 1 if successful, else @c 0. + */ + +int +coap_dtls_context_set_pki_root_cas(coap_context_t *coap_context, + const char *ca_file, + const char *ca_dir); + +/** + * Check whether one of the coap_dtls_context_set_{psk|pki}() functions have + * been called. + * + * @param coap_context The current coap_context_t object. + * + * @return @c 1 if coap_dtls_context_set_{psk|pki}() called, else @c 0. + */ + +int coap_dtls_context_check_keys_enabled(coap_context_t *coap_context); + +/** + * Releases the storage allocated for @p dtls_context. + * + * @param dtls_context The DTLS context as returned by coap_dtls_new_context(). + */ +void coap_dtls_free_context(void *dtls_context); + +#if COAP_CLIENT_SUPPORT +/** + * Create a new client-side session. This should send a HELLO to the server. + * + * @param coap_session The CoAP session. + * + * @return Opaque handle to underlying TLS library object containing security + * parameters for the session. +*/ +void *coap_dtls_new_client_session(coap_session_t *coap_session); +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +/** + * Create a new DTLS server-side session. + * Called after coap_dtls_hello() has returned @c 1, signalling that a validated + * HELLO was received from a client. + * This should send a HELLO to the server. + * + * @param coap_session The CoAP session. + * + * @return Opaque handle to underlying TLS library object containing security + * parameters for the DTLS session. + */ +void *coap_dtls_new_server_session(coap_session_t *coap_session); +#endif /* COAP_SERVER_SUPPORT */ + +/** + * Terminates the DTLS session (may send an ALERT if necessary) then frees the + * underlying TLS library object containing security parameters for the session. + * + * @param coap_session The CoAP session. + */ +void coap_dtls_free_session(coap_session_t *coap_session); + +/** + * Notify of a change in the CoAP session's MTU, for example after + * a PMTU update. + * + * @param coap_session The CoAP session. + */ +void coap_dtls_session_update_mtu(coap_session_t *coap_session); + +/** + * Send data to a DTLS peer. + * + * @param coap_session The CoAP session. + * @param data pointer to data. + * @param data_len Number of bytes to send. + * + * @return @c 0 if this would be blocking, @c -1 if there is an error or the + * number of cleartext bytes sent. + */ +int coap_dtls_send(coap_session_t *coap_session, + const uint8_t *data, + size_t data_len); + +/** + * Check if timeout is handled per CoAP session or per CoAP context. + * + * @return @c 1 of timeout and retransmit is per context, @c 0 if it is + * per session. + */ +int coap_dtls_is_context_timeout(void); + +/** + * Do all pending retransmits and get next timeout + * + * @param dtls_context The DTLS context. + * + * @return @c 0 if no event is pending or date of the next retransmit. + */ +coap_tick_t coap_dtls_get_context_timeout(void *dtls_context); + +/** + * Get next timeout for this session. + * + * @param coap_session The CoAP session. + * @param now The current time in ticks. + * + * @return @c 0 If no event is pending or ticks time of the next retransmit. + */ +coap_tick_t coap_dtls_get_timeout(coap_session_t *coap_session, + coap_tick_t now); + +/** + * Handle a DTLS timeout expiration. + * + * @param coap_session The CoAP session. + * + * @return @c 1 timed out or @c 0 still timing out + */ +int coap_dtls_handle_timeout(coap_session_t *coap_session); + +/** + * Handling incoming data from a DTLS peer. + * + * @param coap_session The CoAP session. + * @param data Encrypted datagram. + * @param data_len Encrypted datagram size. + * + * @return Result of coap_handle_dgram on the decrypted CoAP PDU + * or @c -1 for error. + */ +int coap_dtls_receive(coap_session_t *coap_session, + const uint8_t *data, + size_t data_len); + +#if COAP_SERVER_SUPPORT +/** + * Handling client HELLO messages from a new candiate peer. + * Note that session->tls is empty. + * + * @param coap_session The CoAP session. + * @param data Encrypted datagram. + * @param data_len Encrypted datagram size. + * + * @return @c 0 if a cookie verification message has been sent, @c 1 if the + * HELLO contains a valid cookie and a server session should be created, + * @c -1 if the message is invalid. + */ +int coap_dtls_hello(coap_session_t *coap_session, + const uint8_t *data, + size_t data_len); +#endif /* COAP_SERVER_SUPPORT */ + +/** + * Get DTLS overhead over cleartext PDUs. + * + * @param coap_session The CoAP session. + * + * @return Maximum number of bytes added by DTLS layer. + */ +unsigned int coap_dtls_get_overhead(coap_session_t *coap_session); + +#if COAP_CLIENT_SUPPORT +/** + * Create a new TLS client-side session. + * + * @param coap_session The CoAP session. + * @param connected Updated with whether the connection is connected yet or not. + * @c 0 is not connected, @c 1 is connected. + * + * @return Opaque handle to underlying TLS library object containing security + * parameters for the session. +*/ +void *coap_tls_new_client_session(coap_session_t *coap_session, int *connected); +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +/** + * Create a TLS new server-side session. + * + * @param coap_session The CoAP session. + * @param connected Updated with whether the connection is connected yet or not. + * @c 0 is not connected, @c 1 is connected. + * + * @return Opaque handle to underlying TLS library object containing security + * parameters for the session. + */ +void *coap_tls_new_server_session(coap_session_t *coap_session, int *connected); +#endif /* COAP_SERVER_SUPPORT */ + +/** + * Terminates the TLS session (may send an ALERT if necessary) then frees the + * underlying TLS library object containing security parameters for the session. + * + * @param coap_session The CoAP session. + */ +void coap_tls_free_session( coap_session_t *coap_session ); + +/** + * Send data to a TLS peer, with implicit flush. + * + * @param coap_session The CoAP session. + * @param data Pointer to data. + * @param data_len Number of bytes to send. + * + * @return @c 0 if this should be retried, @c -1 if there is an error + * or the number of cleartext bytes sent. + */ +ssize_t coap_tls_write(coap_session_t *coap_session, + const uint8_t *data, + size_t data_len + ); + +/** + * Read some data from a TLS peer. + * + * @param coap_session The CoAP session. + * @param data Pointer to data. + * @param data_len Maximum number of bytes to read. + * + * @return @c 0 if this should be retried, @c -1 if there is an error + * or the number of cleartext bytes read. + */ +ssize_t coap_tls_read(coap_session_t *coap_session, + uint8_t *data, + size_t data_len + ); + +/** + * Get the current client's PSK key. + * + * @param coap_session The CoAP session. + * + * @return @c NULL if no key, else a pointer the current key. + */ +const coap_bin_const_t *coap_get_session_client_psk_key( + const coap_session_t *coap_session); + +/** + * Get the current client's PSK identity. + * + * @param coap_session The CoAP session. + * + * @return @c NULL if no identity, else a pointer the current identity. + */ +const coap_bin_const_t *coap_get_session_client_psk_identity( + const coap_session_t *coap_session); + +/** + * Get the current server's PSK key. + * + * @param coap_session The CoAP session. + * + * @return @c NULL if no key, else a pointer the current key. + */ +const coap_bin_const_t *coap_get_session_server_psk_key( + const coap_session_t *coap_session); + +/** + * Get the current server's PSK identity hint. + * + * @param coap_session The CoAP session. + * + * @return @c NULL if no hint, else a pointer the current hint. + */ +const coap_bin_const_t *coap_get_session_server_psk_hint( + const coap_session_t *coap_session); + +/** + * Initialize the underlying (D)TLS Library layer. + * + */ +void coap_dtls_startup(void); + +/** + * Close down the underlying (D)TLS Library layer. + * + */ +void coap_dtls_shutdown(void); + +/** + * Get the actual (D)TLS object for the session. + * + * @param session The session. + * @param tls_lib Updated with the library type. + * + * @return The TLS information. + */ +void *coap_dtls_get_tls(const coap_session_t *session, + coap_tls_library_t *tls_lib); + +/** @} */ + +#endif /* COAP_DTLS_INTERNAL_H */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_event.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_event.h new file mode 100644 index 000000000..2b5cb014b --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_event.h @@ -0,0 +1,146 @@ +/* + * coap_event.h -- libcoap Event API + * + * Copyright (C) 2016 Olaf Bergmann + * Copyright (C) 2021-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_event.h + * @brief Event handling + */ + +#ifndef COAP_EVENT_H_ +#define COAP_EVENT_H_ + +#include "libcoap.h" + +/** + * @ingroup application_api + * @defgroup events Event Handling + * API for event delivery from lower-layer library functions. + * @{ + */ + +/** + * Scalar type to represent different events, e.g. DTLS events or + * retransmission timeouts. + */ +typedef enum { +/* + * (D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS + */ + /** Triggerred when (D)TLS session closed */ + COAP_EVENT_DTLS_CLOSED = 0x0000, + /** Triggered when (D)TLS session connected */ + COAP_EVENT_DTLS_CONNECTED = 0x01DE, + /** Triggered when (D)TLS session renegotiated */ + COAP_EVENT_DTLS_RENEGOTIATE = 0x01DF, + /** Triggered when (D)TLS error occurs */ + COAP_EVENT_DTLS_ERROR = 0x0200, + +/* + * TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS + */ + /** Triggered when TCP layer connects */ + COAP_EVENT_TCP_CONNECTED = 0x1001, + /** Triggered when TCP layer is closed */ + COAP_EVENT_TCP_CLOSED = 0x1002, + /** Triggered when TCP layer fails for some reason */ + COAP_EVENT_TCP_FAILED = 0x1003, + +/* + * CSM exchange events for reliable protocols only + */ + /** Triggered when TCP layer completes exchange of CSM information */ + COAP_EVENT_SESSION_CONNECTED = 0x2001, + /** Triggered when TCP layer closes following exchange of CSM information */ + COAP_EVENT_SESSION_CLOSED = 0x2002, + /** Triggered when TCP layer fails following exchange of CSM information */ + COAP_EVENT_SESSION_FAILED = 0x2003, + +/* + * (Q-)Block errors + */ + /** Triggered when not all of a large body has been received */ + COAP_EVENT_PARTIAL_BLOCK = 0x3001, + /** Triggered when not all of a large body has been transmitted */ + COAP_EVENT_XMIT_BLOCK_FAIL = 0x3002, + +/* + * Server session events + */ +/** + * Called in the CoAP IO loop if a new *server-side* session is created due + * to an incoming connection. + * + * Note that the session might not be a fully established connection yet, + * it might also refer to, e.g., a DTLS session in a handshake stage. + */ + COAP_EVENT_SERVER_SESSION_NEW = 0x4001, + +/** + * Called in the CoAP IO loop if a server session is deleted (e.g., due to + * inactivity or because the maximum number of idle sessions was exceeded). + * + * The session will still contain valid data when the event handler is + * called. + */ + COAP_EVENT_SERVER_SESSION_DEL = 0x4002 + +} coap_event_t; + +/** + * Type for event handler functions that can be registered with a CoAP + * context using the unction coap_set_event_handler(). When called by + * the library, the first argument will be the current coap_session_t object + * which is associated with the original CoAP context. The second parameter + * is the event type. + */ +typedef int (*coap_event_handler_t)(coap_session_t *session, + const coap_event_t event); + +/** + * Registers the function @p hnd as callback for events from the given + * CoAP context @p context. Any event handler that has previously been + * registered with @p context will be overwritten by this operation. + * + * @param context The CoAP context to register the event handler with. + * @param hnd The event handler to be registered. @c NULL if to be + * de-registered. + */ +void coap_register_event_handler(coap_context_t *context, + coap_event_handler_t hnd); + +/** @} */ + +/** + * Registers the function @p hnd as callback for events from the given + * CoAP context @p context. Any event handler that has previously been + * registered with @p context will be overwritten by this operation. + * + * @deprecated Use coap_register_event_handler() instead. + * + * @param context The CoAP context to register the event handler with. + * @param hnd The event handler to be registered. + */ +COAP_DEPRECATED +void coap_set_event_handler(coap_context_t *context, + coap_event_handler_t hnd); + +/** + * Clears the event handler registered with @p context. + * + * @deprecated Use coap_register_event_handler() instead with NULL for hnd. + * + * @param context The CoAP context whose event handler is to be removed. + */ +COAP_DEPRECATED +void coap_clear_event_handler(coap_context_t *context); + +#endif /* COAP_EVENT_H */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_forward_decls.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_forward_decls.h new file mode 100644 index 000000000..c361a6872 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_forward_decls.h @@ -0,0 +1,107 @@ +/* + * coap_forward_decls.h -- Forward declarations of structures that are + * opaque to application programming that use libcoap. + * + * Copyright (C) 2019-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_forward_decls.h + * @brief CoAP forward definitions + */ + +#ifndef COAP_FORWARD_DECLS_H_ +#define COAP_FORWARD_DECLS_H_ + +/* + * Define the forward declations for the structures (even non-opaque) + * so that applications (using coap.h) as well as libcoap builds + * can reference them (and makes .h file dependencies a lot simpler). + */ +struct coap_address_t; +struct coap_bin_const_t; +struct coap_dtls_pki_t; +struct coap_str_const_t; +struct coap_string_t; + +/* + * typedef all the opaque structures that are defined in coap_*_internal.h + */ + +/* ************* coap_async_internal.h ***************** */ + +/** + * Async Entry information. + */ +typedef struct coap_async_t coap_async_t; + +/* ************* coap_block_internal.h ***************** */ + +/* + * Block handling information. + */ +typedef struct coap_lg_xmit_t coap_lg_xmit_t; +typedef struct coap_lg_crcv_t coap_lg_crcv_t; +typedef struct coap_lg_srcv_t coap_lg_srcv_t; + +/* ************* coap_cache_internal.h ***************** */ + +/* + * Cache Entry information. + */ +typedef struct coap_cache_entry_t coap_cache_entry_t; +typedef struct coap_cache_key_t coap_cache_key_t; + +/* ************* coap_io_internal.h ***************** */ + +/** + * coap_socket_t and coap_packet_t information. + */ +typedef struct coap_packet_t coap_packet_t; +typedef struct coap_socket_t coap_socket_t; + +/* ************* coap_net_internal.h ***************** */ + +/* + * Net information. + */ +typedef struct coap_context_t coap_context_t; +typedef struct coap_queue_t coap_queue_t; + +/* ************* coap_pdu_internal.h ***************** */ + +/** + * PDU information. + */ +typedef struct coap_pdu_t coap_pdu_t; + +/* ************* coap_resource_internal.h ***************** */ + +/* + * Resource information. + */ +typedef struct coap_attr_t coap_attr_t; +typedef struct coap_resource_t coap_resource_t; + +/* ************* coap_session_internal.h ***************** */ + +/* + * Session information. + */ +typedef struct coap_addr_hash_t coap_addr_hash_t; +typedef struct coap_endpoint_t coap_endpoint_t; +typedef struct coap_session_t coap_session_t; + +/* ************* coap_subscribe_internal.h ***************** */ + +/* + * Observe subscriber information. + */ +typedef struct coap_subscription_t coap_subscription_t; + +#endif /* COAP_FORWARD_DECLS_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_hashkey.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_hashkey.h new file mode 100644 index 000000000..40341e082 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_hashkey.h @@ -0,0 +1,61 @@ +/* + * coap_hashkey.h -- definition of hash key type and helper functions + * + * Copyright (C) 2010-2011 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_hashkey.h + * @brief Definition of hash key type and helper functions + */ + +#ifndef COAP_HASHKEY_H_ +#define COAP_HASHKEY_H_ + +#include "libcoap.h" +#include "uthash.h" +#include "str.h" + +typedef unsigned char coap_key_t[4]; + +#ifndef coap_hash +/** + * Calculates a fast hash over the given string @p s of length @p len and stores + * the result into @p h. Depending on the exact implementation, this function + * cannot be used as one-way function to check message integrity or simlar. + * + * @param s The string used for hash calculation. + * @param len The length of @p s. + * @param h The result buffer to store the calculated hash key. + */ +void coap_hash_impl(const unsigned char *s, size_t len, coap_key_t h); + +#define coap_hash(String,Length,Result) \ + coap_hash_impl((String),(Length),(Result)) + +/* This is used to control the pre-set hash-keys for resources. */ +#define COAP_DEFAULT_HASH +#else +#undef COAP_DEFAULT_HASH +#endif /* coap_hash */ + +/** + * Calls coap_hash() with given @c coap_string_t object as parameter. + * + * @param Str Must contain a pointer to a coap string object. + * @param H A coap_key_t object to store the result. + * + * @hideinitializer + */ +#define coap_str_hash(Str,H) { \ + assert(Str); \ + memset((H), 0, sizeof(coap_key_t)); \ + coap_hash((Str)->s, (Str)->length, (H)); \ + } + +#endif /* COAP_HASHKEY_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_internal.h new file mode 100644 index 000000000..953801f33 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_internal.h @@ -0,0 +1,80 @@ +/* + * coap_internal.h -- Structures, Enums & Functions that are not exposed to + * application programming + * + * Copyright (C) 2019-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/* + * All libcoap library files should include this file which then pulls in all + * of the other appropriate header files. + * + * Note: This file should never be included in application code (with the + * possible exception of internal test suites). + */ + +/** + * @file coap_internal.h + * @brief Pulls together all the internal only header files + */ + +#ifndef COAP_INTERNAL_H_ +#define COAP_INTERNAL_H_ + +#include "coap_config.h" + +/* + * Correctly set up assert() based on NDEBUG for libcoap + */ +#if defined(HAVE_ASSERT_H) && !defined(assert) +# include +#endif + +/* By default without either configured, these need to be set */ +#ifndef COAP_SERVER_SUPPORT +#ifndef COAP_CLIENT_SUPPORT +#define COAP_SERVER_SUPPORT 1 +#define COAP_CLIENT_SUPPORT 1 +#endif /* COAP_CLIENT_SUPPORT */ +#endif /* COAP_SERVER_SUPPORT */ + +#if ! COAP_SERVER_SUPPORT +#ifndef WITHOUT_ASYNC +/* ASYNC is only there for Server code */ +#define WITHOUT_ASYNC +#endif /* WITHOUT_ASYNC */ +#endif /* COAP_SERVER_SUPPORT */ + +#include "coap3/coap.h" + +/* + * Include all the header files that are for internal use only. + */ + +/* Not defined in coap.h - internal usage .h files */ +#include "utlist.h" +#include "uthash.h" +#include "coap_hashkey.h" +#include "coap_mutex.h" + +/* Specifically defined internal .h files */ +#include "coap_asn1_internal.h" +#include "coap_async_internal.h" +#include "coap_block_internal.h" +#include "coap_cache_internal.h" +#include "coap_dtls_internal.h" +#include "coap_io_internal.h" +#include "coap_net_internal.h" +#include "coap_pdu_internal.h" +#include "coap_session_internal.h" +#include "coap_resource_internal.h" +#include "coap_session_internal.h" +#include "coap_subscribe_internal.h" +#include "coap_tcp_internal.h" + +#endif /* COAP_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_io.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_io.h new file mode 100644 index 000000000..ef2e72d81 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_io.h @@ -0,0 +1,77 @@ +/* + * coap_io.h -- Default network I/O functions for libcoap + * + * Copyright (C) 2012-2013,2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_io.h + * @brief Default network I/O functions + */ + +#ifndef COAP_IO_H_ +#define COAP_IO_H_ + +#include + +#include "coap_address.h" + +#ifdef RIOT_VERSION +#include "net/gnrc.h" +#endif /* RIOT_VERSION */ + +#ifndef COAP_RXBUFFER_SIZE +#define COAP_RXBUFFER_SIZE 1472 +#endif /* COAP_RXBUFFER_SIZE */ + +/* + * It may may make sense to define this larger on busy systems + * (lots of sessions, large number of which are active), by using + * -DCOAP_MAX_EPOLL_EVENTS=nn at compile time. + */ +#ifndef COAP_MAX_EPOLL_EVENTS +#define COAP_MAX_EPOLL_EVENTS 10 +#endif /* COAP_MAX_EPOLL_EVENTS */ + +#ifdef _WIN32 +typedef SOCKET coap_fd_t; +#define coap_closesocket closesocket +#define COAP_SOCKET_ERROR SOCKET_ERROR +#define COAP_INVALID_SOCKET INVALID_SOCKET +#else +typedef int coap_fd_t; +#define coap_closesocket close +#define COAP_SOCKET_ERROR (-1) +#define COAP_INVALID_SOCKET (-1) +#endif + +typedef uint16_t coap_socket_flags_t; + +typedef struct coap_addr_tuple_t { + coap_address_t remote; /**< remote address and port */ + coap_address_t local; /**< local address and port */ +} coap_addr_tuple_t; + +const char *coap_socket_strerror( void ); + +/** + * Check whether TCP is available. + * + * @return @c 1 if support for TCP is enabled, or @c 0 otherwise. + */ +int coap_tcp_is_supported(void); + +typedef enum { + COAP_NACK_TOO_MANY_RETRIES, + COAP_NACK_NOT_DELIVERABLE, + COAP_NACK_RST, + COAP_NACK_TLS_FAILED, + COAP_NACK_ICMP_ISSUE +} coap_nack_reason_t; + +#endif /* COAP_IO_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_io_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_io_internal.h new file mode 100644 index 000000000..75382bfb4 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_io_internal.h @@ -0,0 +1,186 @@ +/* + * coap_io.h -- Default network I/O functions for libcoap + * + * Copyright (C) 2012-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_io_internal.h + * @brief Internal network I/O functions + */ + +#ifndef COAP_IO_INTERNAL_H_ +#define COAP_IO_INTERNAL_H_ + +#include "coap_internal.h" +#include + +#include "coap_address.h" + +#ifdef RIOT_VERSION +#include "net/gnrc.h" +#endif /* RIOT_VERSION */ + +struct coap_socket_t { +#if defined(WITH_LWIP) + struct udp_pcb *pcb; +#elif defined(WITH_CONTIKI) + void *conn; +#else + coap_fd_t fd; +#endif /* WITH_LWIP */ +#if defined(RIOT_VERSION) + gnrc_pktsnip_t *pkt; /* pointer to received packet for processing */ +#endif /* RIOT_VERSION */ + coap_socket_flags_t flags; + coap_session_t *session; /* Used by the epoll logic for an active session. */ + coap_endpoint_t *endpoint; /* Used by the epoll logic for a listening + endpoint. */ +}; + +/** + * coap_socket_flags_t values + */ +#define COAP_SOCKET_EMPTY 0x0000 /**< the socket is not used */ +#define COAP_SOCKET_NOT_EMPTY 0x0001 /**< the socket is not empty */ +#define COAP_SOCKET_BOUND 0x0002 /**< the socket is bound */ +#define COAP_SOCKET_CONNECTED 0x0004 /**< the socket is connected */ +#define COAP_SOCKET_WANT_READ 0x0010 /**< non blocking socket is waiting for reading */ +#define COAP_SOCKET_WANT_WRITE 0x0020 /**< non blocking socket is waiting for writing */ +#define COAP_SOCKET_WANT_ACCEPT 0x0040 /**< non blocking server socket is waiting for accept */ +#define COAP_SOCKET_WANT_CONNECT 0x0080 /**< non blocking client socket is waiting for connect */ +#define COAP_SOCKET_CAN_READ 0x0100 /**< non blocking socket can now read without blocking */ +#define COAP_SOCKET_CAN_WRITE 0x0200 /**< non blocking socket can now write without blocking */ +#define COAP_SOCKET_CAN_ACCEPT 0x0400 /**< non blocking server socket can now accept without blocking */ +#define COAP_SOCKET_CAN_CONNECT 0x0800 /**< non blocking client socket can now connect without blocking */ +#define COAP_SOCKET_MULTICAST 0x1000 /**< socket is used for multicast communication */ + +#if COAP_SERVER_SUPPORT +coap_endpoint_t *coap_malloc_endpoint( void ); +void coap_mfree_endpoint( coap_endpoint_t *ep ); +#endif /* COAP_SERVER_SUPPORT */ + +const char *coap_socket_format_errno(int error); + +#if COAP_CLIENT_SUPPORT +int +coap_socket_connect_udp(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr); +#endif /* COAP_CLIENT_SUPPORT */ + +int +coap_socket_bind_udp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr ); + +void coap_socket_close(coap_socket_t *sock); + +ssize_t +coap_socket_send( coap_socket_t *sock, coap_session_t *session, + const uint8_t *data, size_t data_len ); + +ssize_t +coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len); + +ssize_t +coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len); + +void +coap_epoll_ctl_mod(coap_socket_t *sock, uint32_t events, const char *func); + +/** + * Update the epoll timer fd as to when it is to trigger. + * + * @param context The context to update the epoll timer on. + * @param delay The time to delay before the epoll timer fires. + */ +void coap_update_epoll_timer(coap_context_t *context, coap_tick_t delay); + +#ifdef WITH_LWIP +ssize_t +coap_socket_send_pdu( coap_socket_t *sock, coap_session_t *session, + coap_pdu_t *pdu ); +#endif + +/** + * Function interface for data transmission. This function returns the number of + * bytes that have been transmitted, or a value less than zero on error. + * + * @param sock Socket to send data with + * @param session Addressing information for unconnected sockets, or NULL + * @param data The data to send. + * @param datalen The actual length of @p data. + * + * @return The number of bytes written on success, or a value + * less than zero on error. + */ +ssize_t coap_network_send( coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen ); + +/** + * Function interface for reading data. This function returns the number of + * bytes that have been read, or a value less than zero on error. In case of an + * error, @p *packet is set to NULL. + * + * @param sock Socket to read data from + * @param packet Received packet metadata and payload. src and dst should be preset. + * + * @return The number of bytes received on success, or a value less than + * zero on error. + */ +ssize_t coap_network_read( coap_socket_t *sock, coap_packet_t *packet ); + +#ifndef coap_mcast_interface +# define coap_mcast_interface(Local) 0 +#endif + +/** + * Given a packet, set msg and msg_len to an address and length of the packet's + * data in memory. + * */ +void coap_packet_get_memmapped(coap_packet_t *packet, + unsigned char **address, + size_t *length); + +#ifdef WITH_LWIP +/** + * Get the pbuf of a packet. The caller takes over responsibility for freeing + * the pbuf. + */ +struct pbuf *coap_packet_extract_pbuf(coap_packet_t *packet); +#endif + +#if defined(WITH_LWIP) +/* + * This is only included in coap_io.h instead of .c in order to be available for + * sizeof in lwippools.h. + * Simple carry-over of the incoming pbuf that is later turned into a node. + * + * Source address data is currently side-banded via ip_current_dest_addr & co + * as the packets have limited lifetime anyway. + */ +struct coap_packet_t { + struct pbuf *pbuf; + const coap_endpoint_t *local_interface; + coap_addr_tuple_t addr_info; /**< local and remote addresses */ + int ifindex; /**< the interface index */ +// uint16_t srcport; +}; +#else +struct coap_packet_t { + coap_addr_tuple_t addr_info; /**< local and remote addresses */ + int ifindex; /**< the interface index */ + size_t length; /**< length of payload */ + unsigned char payload[COAP_RXBUFFER_SIZE]; /**< payload */ +}; +#endif + +#endif /* COAP_IO_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_mutex.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_mutex.h new file mode 100644 index 000000000..95aae49f6 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_mutex.h @@ -0,0 +1,82 @@ +/* + * coap_mutex.h -- mutex utilities + * + * Copyright (C) 2019-2022 Jon Shallow + * 2019 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_mutex.h + * @brief CoAP mutex mechanism wrapper + */ + +#ifndef COAP_MUTEX_H_ +#define COAP_MUTEX_H_ + +/* + * Mutexes are currently only used if there is a constrained stack, + * and large static variables (instead of the large variable being on + * the stack) need to be protected. + */ +#if COAP_CONSTRAINED_STACK + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK) +#include + +typedef pthread_mutex_t coap_mutex_t; +#define COAP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define coap_mutex_lock(a) pthread_mutex_lock(a) +#define coap_mutex_trylock(a) pthread_mutex_trylock(a) +#define coap_mutex_unlock(a) pthread_mutex_unlock(a) + +#elif defined(RIOT_VERSION) +/* use RIOT's mutex API */ +#include + +typedef mutex_t coap_mutex_t; +#define COAP_MUTEX_INITIALIZER MUTEX_INIT +#define coap_mutex_lock(a) mutex_lock(a) +#define coap_mutex_trylock(a) mutex_trylock(a) +#define coap_mutex_unlock(a) mutex_unlock(a) + +#elif defined(WITH_LWIP) +/* Use LwIP's mutex API */ + +#if NO_SYS +/* Single threaded, no-op'd in lwip/sys.h */ +typedef int coap_mutex_t; +#define COAP_MUTEX_INITIALIZER 0 +#define coap_mutex_lock(a) *(a) = 1 +#define coap_mutex_trylock(a) *(a) = 1 +#define coap_mutex_unlock(a) *(a) = 0 +#else /* !NO SYS */ +#error Need support for LwIP mutex +#endif /* !NO SYS */ + +#elif defined(WITH_CONTIKI) +/* Contiki does not have a mutex API, used as single thread */ +typedef int coap_mutex_t; +#define COAP_MUTEX_INITIALIZER 0 +#define coap_mutex_lock(a) *(a) = 1 +#define coap_mutex_trylock(a) *(a) = 1 +#define coap_mutex_unlock(a) *(a) = 0 + +#else /* !WITH_CONTIKI && !WITH_LWIP && !RIOT_VERSION && !HAVE_PTHREAD_H && !HAVE_PTHREAD_MUTEX_LOCK */ +/* define stub mutex functions */ +#warning "stub mutex functions" +typedef int coap_mutex_t; +#define COAP_MUTEX_INITIALIZER 0 +#define coap_mutex_lock(a) *(a) = 1 +#define coap_mutex_trylock(a) *(a) = 1 +#define coap_mutex_unlock(a) *(a) = 0 + +#endif /* !WITH_CONTIKI && !WITH_LWIP && !RIOT_VERSION && !HAVE_PTHREAD_H && !HAVE_PTHREAD_MUTEX_LOCK */ + +#endif /* COAP_CONSTRAINED_STACK */ + +#endif /* COAP_MUTEX_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_net_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_net_internal.h new file mode 100644 index 000000000..08e16eb93 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_net_internal.h @@ -0,0 +1,386 @@ +/* + * coap_net_internal.h -- CoAP context internal information + * exposed to application programming + * + * Copyright (C) 2010-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_net_internal.h + * @brief CoAP context internal information + */ + +#ifndef COAP_NET_INTERNAL_H_ +#define COAP_NET_INTERNAL_H_ + +#include "coap_internal.h" + +/** + * @ingroup internal_api + * @defgroup context_internal Context Handling + * Internal API for Context Handling + * @{ + */ + +/** + * Queue entry + */ +struct coap_queue_t { + struct coap_queue_t *next; + coap_tick_t t; /**< when to send PDU for the next time */ + unsigned char retransmit_cnt; /**< retransmission counter, will be removed + * when zero */ + uint8_t is_mcast; /**< Set if this is a queued mcast response */ + unsigned int timeout; /**< the randomized timeout value */ + coap_session_t *session; /**< the CoAP session */ + coap_mid_t id; /**< CoAP message id */ + coap_pdu_t *pdu; /**< the CoAP PDU to send */ +}; + +/** + * The CoAP stack's global state is stored in a coap_context_t object. + */ +struct coap_context_t { + coap_opt_filter_t known_options; +#if COAP_SERVER_SUPPORT + coap_resource_t *resources; /**< hash table or list of known + resources */ + coap_resource_t *unknown_resource; /**< can be used for handling + unknown resources */ + coap_resource_t *proxy_uri_resource; /**< can be used for handling + proxy URI resources */ + coap_resource_release_userdata_handler_t release_userdata; + /**< function to release user_data + when resource is deleted */ +#endif /* COAP_SERVER_SUPPORT */ + +#ifndef WITHOUT_ASYNC + /** + * list of asynchronous message ids */ + coap_async_t *async_state; +#endif /* WITHOUT_ASYNC */ + + /** + * The time stamp in the first element of the sendqeue is relative + * to sendqueue_basetime. */ + coap_tick_t sendqueue_basetime; + coap_queue_t *sendqueue; +#if COAP_SERVER_SUPPORT + coap_endpoint_t *endpoint; /**< the endpoints used for listening */ +#endif /* COAP_SERVER_SUPPORT */ +#if COAP_CLIENT_SUPPORT + coap_session_t *sessions; /**< client sessions */ +#endif /* COAP_CLIENT_SUPPORT */ + +#ifdef WITH_CONTIKI + struct uip_udp_conn *conn; /**< uIP connection object */ + struct etimer retransmit_timer; /**< fires when the next packet must be + sent */ + struct etimer notify_timer; /**< used to check resources periodically */ +#endif /* WITH_CONTIKI */ + +#ifdef WITH_LWIP + uint8_t timer_configured; /**< Set to 1 when a retransmission is + * scheduled using lwIP timers for this + * context, otherwise 0. */ +#endif /* WITH_LWIP */ + +#if COAP_CLIENT_SUPPORT + coap_response_handler_t response_handler; +#endif /* COAP_CLIENT_SUPPORT */ + coap_nack_handler_t nack_handler; + coap_ping_handler_t ping_handler; + coap_pong_handler_t pong_handler; + + /** + * Callback function that is used to signal events to the + * application. This field is set by coap_set_event_handler(). + */ + coap_event_handler_t handle_event; + + ssize_t (*network_send)(coap_socket_t *sock, const coap_session_t *session, + const uint8_t *data, size_t datalen); + + ssize_t (*network_read)(coap_socket_t *sock, coap_packet_t *packet); + + void *dtls_context; + +#if COAP_SERVER_SUPPORT + coap_dtls_spsk_t spsk_setup_data; /**< Contains the initial PSK server setup + data */ +#endif /* COAP_SERVER_SUPPORT */ + + unsigned int session_timeout; /**< Number of seconds of inactivity after + which an unused session will be closed. + 0 means use default. */ + unsigned int max_idle_sessions; /**< Maximum number of simultaneous unused + sessions per endpoint. 0 means no + maximum. */ + unsigned int max_handshake_sessions; /**< Maximum number of simultaneous + negotating sessions per endpoint. 0 + means use default. */ + unsigned int ping_timeout; /**< Minimum inactivity time before + sending a ping message. 0 means + disabled. */ + unsigned int csm_timeout; /**< Timeout for waiting for a CSM from + the remote side. 0 means disabled. */ + uint32_t csm_max_message_size; /**< Value for CSM Max-Message-Size */ + uint64_t etag; /**< Next ETag to use */ + +#if COAP_SERVER_SUPPORT + coap_cache_entry_t *cache; /**< CoAP cache-entry cache */ + uint16_t *cache_ignore_options; /**< CoAP options to ignore when creating a + cache-key */ + size_t cache_ignore_count; /**< The number of CoAP options to ignore + when creating a cache-key */ +#endif /* COAP_SERVER_SUPPORT */ + void *app; /**< application-specific data */ +#ifdef COAP_EPOLL_SUPPORT + int epfd; /**< External FD for epoll */ + int eptimerfd; /**< Internal FD for timeout */ + coap_tick_t next_timeout; /**< When the next timeout is to occur */ +#endif /* COAP_EPOLL_SUPPORT */ +#if COAP_SERVER_SUPPORT + uint8_t observe_pending; /**< Observe response pending */ + uint8_t mcast_per_resource; /**< Mcast controlled on a per resource + basis */ +#endif /* COAP_SERVER_SUPPORT */ + uint8_t block_mode; /**< Zero or more COAP_BLOCK_ or'd options */ +}; + +/** + * Adds @p node to given @p queue, ordered by variable t in @p node. + * + * @param queue Queue to add to. + * @param node Node entry to add to Queue. + * + * @return @c 1 added to queue, @c 0 failure. + */ +int coap_insert_node(coap_queue_t **queue, coap_queue_t *node); + +/** + * Destroys specified @p node. + * + * @param node Node entry to remove. + * + * @return @c 1 node deleted from queue, @c 0 failure. + */ +int coap_delete_node(coap_queue_t *node); + +/** + * Removes all items from given @p queue and frees the allocated storage. + * + * Internal function. + * + * @param queue The queue to delete. + */ +void coap_delete_all(coap_queue_t *queue); + +/** + * Creates a new node suitable for adding to the CoAP sendqueue. + * + * @return New node entry, or @c NULL if failure. + */ +coap_queue_t *coap_new_node(void); + +/** + * Set sendqueue_basetime in the given context object @p ctx to @p now. This + * function returns the number of elements in the queue head that have timed + * out. + */ +unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now); + +/** + * Returns the next pdu to send without removing from sendqeue. + */ +coap_queue_t *coap_peek_next( coap_context_t *context ); + +/** + * Returns the next pdu to send and removes it from the sendqeue. + */ +coap_queue_t *coap_pop_next( coap_context_t *context ); + +/** + * Handles retransmissions of confirmable messages + * + * @param context The CoAP context. + * @param node The node to retransmit. + * + * @return The message id of the sent message or @c + * COAP_INVALID_MID on error. + */ +coap_mid_t coap_retransmit(coap_context_t *context, coap_queue_t *node); + +/** + * Parses and interprets a CoAP datagram with context @p ctx. This function + * returns @c 0 if the datagram was handled, or a value less than zero on + * error. + * + * @param ctx The current CoAP context. + * @param session The current CoAP session. + * @param data The received packet'd data. + * @param data_len The received packet'd data length. + * + * @return @c 0 if message was handled successfully, or less than zero on + * error. + */ +int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *data, size_t data_len); + +/** + * This function removes the element with given @p id from the list given list. + * If @p id was found, @p node is updated to point to the removed element. Note + * that the storage allocated by @p node is @b not released. The caller must do + * this manually using coap_delete_node(). This function returns @c 1 if the + * element with id @p id was found, @c 0 otherwise. For a return value of @c 0, + * the contents of @p node is undefined. + * + * @param queue The queue to search for @p id. + * @param session The session to look for. + * @param id The message id to look for. + * @param node If found, @p node is updated to point to the removed node. You + * must release the storage pointed to by @p node manually. + * + * @return @c 1 if @p id was found, @c 0 otherwise. + */ +int coap_remove_from_queue(coap_queue_t **queue, + coap_session_t *session, + coap_mid_t id, + coap_queue_t **node); + +coap_mid_t +coap_wait_ack( coap_context_t *context, coap_session_t *session, + coap_queue_t *node); + +/** + * Cancels all outstanding messages for session @p session that have the specified + * token. + * + * @param context The context in use. + * @param session Session of the messages to remove. + * @param token Message token. + * @param token_length Actual length of @p token. + */ +void coap_cancel_all_messages(coap_context_t *context, + coap_session_t *session, + const uint8_t *token, + size_t token_length); + +/** +* Cancels all outstanding messages for session @p session. +* +* @param context The context in use. +* @param session Session of the messages to remove. +* @param reason The reasion for the session cancellation +*/ +void +coap_cancel_session_messages(coap_context_t *context, + coap_session_t *session, + coap_nack_reason_t reason); + +/** + * Dispatches the PDUs from the receive queue in given context. + */ +void coap_dispatch(coap_context_t *context, coap_session_t *session, + coap_pdu_t *pdu); + +/** + * Verifies that @p pdu contains no unknown critical options. Options must be + * registered at @p ctx, using the function coap_register_option(). A basic set + * of options is registered automatically by coap_new_context(). This function + * returns @c 1 if @p pdu is ok, @c 0 otherwise. The given filter object @p + * unknown will be updated with the unknown options. As only @c COAP_MAX_OPT + * options can be signalled this way, remaining options must be examined + * manually. + * + * @code + coap_opt_filter_t f = COAP_OPT_NONE; + coap_opt_iterator_t opt_iter; + + if (coap_option_check_critical(session, pdu, f) == 0) { + coap_option_iterator_init(pdu, &opt_iter, f); + + while (coap_option_next(&opt_iter)) { + if (opt_iter.type & 0x01) { + ... handle unknown critical option in opt_iter ... + } + } + } + @endcode + * + * @param session The current session. + * @param pdu The PDU to check. + * @param unknown The output filter that will be updated to indicate the + * unknown critical options found in @p pdu. + * + * @return @c 1 if everything was ok, @c 0 otherwise. + */ +int coap_option_check_critical(coap_session_t *session, + coap_pdu_t *pdu, + coap_opt_filter_t *unknown); + +/** + * Creates a new response for given @p request with the contents of @c + * .well-known/core. The result is NULL on error or a newly allocated PDU that + * must be either sent with coap_sent() or released by coap_delete_pdu(). + * + * @param context The current coap context to use. + * @param session The CoAP session. + * @param request The request for @c .well-known/core . + * + * @return A new 2.05 response for @c .well-known/core or NULL on error. + */ +coap_pdu_t *coap_wellknown_response(coap_context_t *context, + coap_session_t *session, + coap_pdu_t *request); + +/** + * Calculates the initial timeout based on the session CoAP transmission + * parameters 'ack_timeout', 'ack_random_factor', and COAP_TICKS_PER_SECOND. + * The calculation requires 'ack_timeout' and 'ack_random_factor' to be in + * Qx.FRAC_BITS fixed point notation, whereas the passed parameter @p r + * is interpreted as the fractional part of a Q0.MAX_BITS random value. + * + * @param session session timeout is associated with + * @param r random value as fractional part of a Q0.MAX_BITS fixed point + * value + * @return COAP_TICKS_PER_SECOND * 'ack_timeout' * + * (1 + ('ack_random_factor' - 1) * r) + */ +unsigned int coap_calc_timeout(coap_session_t *session, unsigned char r); + +/** + * Sends a CoAP message to given peer. The memory that is + * allocated for the pdu will be released by coap_send_internal(). + * The caller must not use the pdu after calling coap_send_internal(). + * + * If the response body is split into multiple payloads using blocks, libcoap + * will handle asking for the subsequent blocks and any necessary recovery + * needed. + * + * @param session The CoAP session. + * @param pdu The CoAP PDU to send. + * + * @return The message id of the sent message or @c + * COAP_INVALID_MID on error. + */ +coap_mid_t coap_send_internal(coap_session_t *session, coap_pdu_t *pdu); + +/** + * Delay the sending of the first client request until some other negotiation + * has completed. + * + * @param session The CoAP session. + * + * @return @c 1 if everything was ok, @c 0 otherwise. + */ +int coap_client_delay_first(coap_session_t *session); + +/** @} */ + +#endif /* COAP_NET_INTERNAL_H_ */ + diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_option.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_option.h new file mode 100644 index 000000000..1cc846f96 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_option.h @@ -0,0 +1,440 @@ +/* + * coap_option.h -- helpers for handling options in CoAP PDUs + * + * Copyright (C) 2010-2013,2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_option.h + * @brief Helpers for handling options in CoAP PDUs + */ + +#ifndef COAP_OPTION_H_ +#define COAP_OPTION_H_ + +typedef uint16_t coap_option_num_t; + +/** + * Use byte-oriented access methods here because sliding a complex struct + * coap_opt_t over the data buffer may cause bus error on certain platforms. + */ +typedef uint8_t coap_opt_t; +#define PCHAR(p) ((coap_opt_t *)(p)) + +/** + * Representation of CoAP options. + */ +typedef struct { + uint16_t delta; + size_t length; + const uint8_t *value; +} coap_option_t; + +/** + * Parses the option pointed to by @p opt into @p result. This function returns + * the number of bytes that have been parsed, or @c 0 on error. An error is + * signaled when illegal delta or length values are encountered or when option + * parsing would result in reading past the option (i.e. beyond opt + length). + * + * @param opt The beginning of the option to parse. + * @param length The maximum length of @p opt. + * @param result A pointer to the coap_option_t structure that is filled with + * actual values iff coap_opt_parse() > 0. + * @return The number of bytes parsed or @c 0 on error. + */ +size_t coap_opt_parse(const coap_opt_t *opt, + size_t length, + coap_option_t *result); + +/** + * Returns the size of the given option, taking into account a possible option + * jump. + * + * @param opt An option jump or the beginning of the option. + * @return The number of bytes between @p opt and the end of the option + * starting at @p opt. In case of an error, this function returns + * @c 0 as options need at least one byte storage space. + */ +size_t coap_opt_size(const coap_opt_t *opt); + +/** + * @ingroup application_api + * @defgroup opt_filter Option Filters + * API for access option filters + * @{ + */ + +/** + * The number of option types below 256 that can be stored in an + * option filter. COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be + * at most 16. Each coap_option_filter_t object reserves + * ((COAP_OPT_FILTER_SHORT + 1) / 2) * 2 bytes for short options. + */ +#define COAP_OPT_FILTER_SHORT 6 + +/** + * The number of option types above 255 that can be stored in an + * option filter. COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be + * at most 16. Each coap_option_filter_t object reserves + * COAP_OPT_FILTER_LONG * 2 bytes for short options. + */ +#define COAP_OPT_FILTER_LONG 2 + +/* Ensure that COAP_OPT_FILTER_SHORT and COAP_OPT_FILTER_LONG are set + * correctly. */ +#if (COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG > 16) +#error COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG must be less or equal 16 +#endif /* (COAP_OPT_FILTER_SHORT + COAP_OPT_FILTER_LONG > 16) */ + +/* + * mask contains a bit vector that indicates which fields in the long_opts[] + * and subsequent short_opts[] are used. The first COAP_OPT_FILTER_LONG bits + * correspond to the long option types that are stored in long_opts[] + * elements. The next COAP_OPT_FILTER_SHORT bits correspond to the short + * option types that are stored in short_opts[]. + */ +typedef struct coap_opt_filter_t { + uint16_t mask; + uint16_t long_opts[COAP_OPT_FILTER_LONG]; + uint8_t short_opts[COAP_OPT_FILTER_SHORT]; +} coap_opt_filter_t; + +/** Pre-defined filter that includes all options. */ +#define COAP_OPT_ALL NULL + +/** + * Clears filter @p filter. + * + * @param filter The filter to clear. + */ +void +coap_option_filter_clear(coap_opt_filter_t *filter); + +/** + * Sets the corresponding entry for @p number in @p filter. This + * function returns @c 1 if bit was set or @c 0 on error (i.e. when + * the given number does not fit in the filter). + * + * @param filter The filter object to change. + * @param number The option number for which the bit should be set. + * + * @return @c 1 if bit was set, @c 0 otherwise. + */ +int coap_option_filter_set(coap_opt_filter_t *filter, coap_option_num_t number); + +/** + * Clears the corresponding entry for @p number in @p filter. This + * function returns @c 1 if bit was set or @c 0 on error (i.e. when + * the given number does not fit in the filter). + * + * @param filter The filter object to change. + * @param number The option number that should be cleared from the filter. + * + * @return @c 1 if bit was set, @c 0 otherwise. + */ +int coap_option_filter_unset(coap_opt_filter_t *filter, + coap_option_num_t number); + +/** + * Checks if @p number is contained in @p filter. This function returns + * @c 1 if found, @c 0 if not, or @c -1 on error (i.e. when the given + * number does not fit in the filter). + * + * @param filter The filter object to search. + * @param number The option number to search for. + * + * @return @c 1 if @p number was found, @c 0 otherwise, or @c -1 on error. + */ +int coap_option_filter_get(coap_opt_filter_t *filter, coap_option_num_t number); + +/** + * Iterator to run through PDU options. This object must be + * initialized with coap_option_iterator_init(). Call + * coap_option_next() to walk through the list of options until + * coap_option_next() returns @c NULL. + * + * @code + * coap_opt_t *option; + * coap_opt_iterator_t opt_iter; + * coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + * + * while ((option = coap_option_next(&opt_iter))) { + * ... do something with option ... + * } + * @endcode + */ +typedef struct { + size_t length; /**< remaining length of PDU */ + coap_option_num_t number; /**< decoded option number */ + unsigned int bad:1; /**< iterator object is ok if not set */ + unsigned int filtered:1; /**< denotes whether or not filter is used */ + coap_opt_t *next_option; /**< pointer to the unparsed next option */ + coap_opt_filter_t filter; /**< option filter */ +} coap_opt_iterator_t; + +/** + * Initializes the given option iterator @p oi to point to the beginning of the + * @p pdu's option list. This function returns @p oi on success, @c NULL + * otherwise (i.e. when no options exist). Note that a length check on the + * option list must be performed before coap_option_iterator_init() is called. + * + * @param pdu The PDU the options of which should be walked through. + * @param oi An iterator object that will be initilized. + * @param filter An optional option number filter. + * With @p number != @c COAP_OPT_ALL, coap_option_next() + * will return only options matching this bitmask. + * Fence-post options @c 14, @c 28, @c 42, ... are always + * skipped. + * + * @return The iterator object @p oi on success, @c NULL otherwise. + */ +coap_opt_iterator_t *coap_option_iterator_init(const coap_pdu_t *pdu, + coap_opt_iterator_t *oi, + const coap_opt_filter_t *filter); + +/** + * Updates the iterator @p oi to point to the next option. This function returns + * a pointer to that option or @c NULL if no more options exist. The contents of + * @p oi will be updated. In particular, @c oi->n specifies the current option's + * ordinal number (counted from @c 1), @c oi->number is the option's number + * value, and @c oi->option points to the beginning of the current option + * itself. When * advanced past the last option, @c oi->option will be @c NULL. + * + * Note that options are skipped whose corresponding bits in the filter + * specified with coap_option_iterator_init() are @c 0. Options with numbers + * that do not fit in this filter hence will always be returned. + * + * @param oi The option iterator to update. + * + * @return The next option or @c NULL if no more options exist. + */ +coap_opt_t *coap_option_next(coap_opt_iterator_t *oi); + +/** + * Retrieves the first option of number @p number from @p pdu. @p oi must + * point to a coap_opt_iterator_t object that will be initialized by this + * function to filter only options with number @p number. This function returns + * the first option with this number, or @c NULL if not found. + * + * @param pdu The PDU to parse for options. + * @param number The option number to search for. + * @param oi An iterator object to use. + * + * @return A pointer to the first option of number @p number, or @c NULL if + * not found. + */ +coap_opt_t *coap_check_option(const coap_pdu_t *pdu, + coap_option_num_t number, + coap_opt_iterator_t *oi); + +/** + * Encodes the given delta and length values into @p opt. This function returns + * the number of bytes that were required to encode @p delta and @p length or @c + * 0 on error. Note that the result indicates by how many bytes @p opt must be + * advanced to encode the option value. + * + * @param opt The option buffer space where @p delta and @p length are + * written. + * @param maxlen The maximum length of @p opt. + * @param delta The actual delta value to encode. + * @param length The actual length value to encode. + * + * @return The number of bytes used or @c 0 on error. + */ +size_t coap_opt_setheader(coap_opt_t *opt, + size_t maxlen, + uint16_t delta, + size_t length); + +/** + * Compute storage bytes needed for an option with given @p delta and + * @p length + * + * @param delta The option delta. + * @param length The option length. + * + * @return The number of bytes required to encode this option. + */ +size_t coap_opt_encode_size(uint16_t delta, size_t length); + +/** + * Encodes option with given @p delta into @p opt. This function returns the + * number of bytes written to @p opt or @c 0 on error. This happens especially + * when @p opt does not provide sufficient space to store the option value, + * delta, and option jumps when required. + * + * @param opt The option buffer space where @p val is written. + * @param n Maximum length of @p opt. + * @param delta The option delta. + * @param val The option value to copy into @p opt. + * @param length The actual length of @p val. + * + * @return The number of bytes that have been written to @p opt or @c 0 on + * error. The return value will always be less than @p n. + */ +size_t coap_opt_encode(coap_opt_t *opt, + size_t n, + uint16_t delta, + const uint8_t *val, + size_t length); + +/** + * Returns the length of the given option. @p opt must point to an option jump + * or the beginning of the option. This function returns @c 0 when @p opt is not + * an option or the actual length of @p opt (which can be @c 0 as well). + * + * @note {The rationale for using @c 0 in case of an error is that in most + * contexts, the result of this function is used to skip the next + * coap_opt_length() bytes.} + * + * @param opt The option whose length should be returned. + * + * @return The option's length or @c 0 when undefined. + */ +uint32_t coap_opt_length(const coap_opt_t *opt); + +/** + * Returns a pointer to the value of the given option. @p opt must point to an + * option jump or the beginning of the option. This function returns @c NULL if + * @p opt is not a valid option. + * + * @param opt The option whose value should be returned. + * + * @return A pointer to the option value or @c NULL on error. + */ +const uint8_t *coap_opt_value(const coap_opt_t *opt); + +/** + * Representation of chained list of CoAP options to install. + * + * @code + * coap_optlist_t *optlist_chain = NULL; + * coap_pdu_t *pdu = coap_new_pdu(session); + * + * ... other set up code ... + * coap_insert_optlist(&optlist_chain, coap_new_optlist(COAP_OPTION_OBSERVE, + * COAP_OBSERVE_ESTABLISH, NULL)); + * + * coap_add_optlist_pdu(pdu, &optlist_chain); + * ... other code ... + * coap_delete_optlist(optlist_chain); + * @endcode + */ +typedef struct coap_optlist_t { + struct coap_optlist_t *next; /**< next entry in the optlist chain */ + uint16_t number; /**< the option number (no delta coding) */ + size_t length; /**< the option value length */ + uint8_t *data; /**< the option data */ +} coap_optlist_t; + +/** + * Create a new optlist entry. + * + * Note: Where possible, the option data needs to be stripped of leading zeros + * (big endian) to reduce the amount of data needed in the PDU, as well as in + * some cases the maximum data size of an opton can be exceeded if not stripped + * and hence be illegal. This is done by using coap_encode_var_safe() or + * coap_encode_var_safe8(). + * + * @param number The option number (COAP_OPTION_*) + * @param length The option length + * @param data The option value data + * + * @return A pointer to the new optlist entry, or @c NULL if error + */ +coap_optlist_t *coap_new_optlist(uint16_t number, + size_t length, + const uint8_t *data); + +/** + * The current optlist of @p optlist_chain is first sorted (as per RFC7272 + * ordering requirements) and then added to the @p pdu. + * + * @param pdu The pdu to add the options to from the chain list + * @param optlist_chain The chained list of optlist to add to the pdu + * + * @return @c 1 if succesful or @c 0 if failure; + */ +int coap_add_optlist_pdu(coap_pdu_t *pdu, coap_optlist_t** optlist_chain); + +/** + * Adds @p optlist to the given @p optlist_chain. The optlist_chain variable + * be set to NULL before the initial call to coap_insert_optlist(). + * The optlist_chain will need to be deleted using coap_delete_optlist() + * when no longer required. + * + * @param optlist_chain The chain to add optlist to + * @param optlist The optlist to add to the queue + * + * @return @c 1 if successful, @c 0 otherwise. + */ +int coap_insert_optlist(coap_optlist_t **optlist_chain, + coap_optlist_t *optlist); + +/** + * Removes all entries from the @p optlist_chain, freeing off their + * memory usage. + * + * @param optlist_chain The optlist chain to remove all the entries from + */ +void coap_delete_optlist(coap_optlist_t *optlist_chain); + +/** @} */ + +/** + * Sets the corresponding bit for @p type in @p filter. This function returns @c + * 1 if bit was set or @c -1 on error (i.e. when the given type does not fit in + * the filter). + * + * @deprecated Use coap_option_filter_set() instead. + * + * @param filter The filter object to change. + * @param type The type for which the bit should be set. + * + * @return @c 1 if bit was set, @c -1 otherwise. + */ +COAP_STATIC_INLINE COAP_DEPRECATED int +coap_option_setb(coap_opt_filter_t *filter, uint16_t type) { + return coap_option_filter_set(filter, type) ? 1 : -1; +} + +/** + * Clears the corresponding bit for @p type in @p filter. This function returns + * @c 1 if bit was cleared or @c -1 on error (i.e. when the given type does not + * fit in the filter). + * + * @deprecated Use coap_option_filter_unset() instead. + * + * @param filter The filter object to change. + * @param type The type for which the bit should be cleared. + * + * @return @c 1 if bit was set, @c -1 otherwise. + */ +COAP_STATIC_INLINE COAP_DEPRECATED int +coap_option_clrb(coap_opt_filter_t *filter, uint16_t type) { + return coap_option_filter_unset(filter, type) ? 1 : -1; +} + +/** + * Gets the corresponding bit for @p type in @p filter. This function returns @c + * 1 if the bit is set @c 0 if not, or @c -1 on error (i.e. when the given type + * does not fit in the filter). + * + * @deprecated Use coap_option_filter_get() instead. + * + * @param filter The filter object to read bit from. + * @param type The type for which the bit should be read. + * + * @return @c 1 if bit was set, @c 0 if not, @c -1 on error. + */ +COAP_STATIC_INLINE COAP_DEPRECATED int +coap_option_getb(coap_opt_filter_t *filter, uint16_t type) { + return coap_option_filter_get(filter, type); +} + +#endif /* COAP_OPTION_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_pdu_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_pdu_internal.h new file mode 100644 index 000000000..67d20ce6e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_pdu_internal.h @@ -0,0 +1,318 @@ +/* + * coap_pdu_internal.h -- CoAP PDU structure + * + * Copyright (C) 2010-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_pdu_internal.h + * @brief CoAP PDU internal information + */ + +#ifndef COAP_COAP_PDU_INTERNAL_H_ +#define COAP_COAP_PDU_INTERNAL_H_ + +#include "coap_internal.h" + +#ifdef WITH_LWIP +#include +#endif + +#include + +/** + * @ingroup internal_api + * @defgroup pdu_internal PDU + * Internal API for PDUs + * @{ + */ + +#define COAP_DEFAULT_VERSION 1 /* version of CoAP supported */ + +/* TCP Message format constants, do not modify */ +#define COAP_MESSAGE_SIZE_OFFSET_TCP8 13 +#define COAP_MESSAGE_SIZE_OFFSET_TCP16 269 /* 13 + 256 */ +#define COAP_MESSAGE_SIZE_OFFSET_TCP32 65805 /* 269 + 65536 */ + +/* Derived message size limits */ +#define COAP_MAX_MESSAGE_SIZE_TCP0 (COAP_MESSAGE_SIZE_OFFSET_TCP8-1) /* 12 */ +#define COAP_MAX_MESSAGE_SIZE_TCP8 (COAP_MESSAGE_SIZE_OFFSET_TCP16-1) /* 268 */ +#define COAP_MAX_MESSAGE_SIZE_TCP16 (COAP_MESSAGE_SIZE_OFFSET_TCP32-1) /* 65804 */ +#define COAP_MAX_MESSAGE_SIZE_TCP32 (COAP_MESSAGE_SIZE_OFFSET_TCP32+0xFFFFFFFF) + +#ifndef COAP_DEBUG_BUF_SIZE +#if defined(WITH_CONTIKI) || defined(WITH_LWIP) +#define COAP_DEBUG_BUF_SIZE 128 +#else /* defined(WITH_CONTIKI) || defined(WITH_LWIP) */ +/* 1024 derived from RFC7252 4.6. Message Size max payload */ +#define COAP_DEBUG_BUF_SIZE (8 + 1024 * 2) +#endif /* defined(WITH_CONTIKI) || defined(WITH_LWIP) */ +#endif /* COAP_DEBUG_BUF_SIZE */ + +#ifndef COAP_DEFAULT_MAX_PDU_RX_SIZE +#if defined(WITH_CONTIKI) || defined(WITH_LWIP) +#define COAP_DEFAULT_MAX_PDU_RX_SIZE (COAP_MAX_MESSAGE_SIZE_TCP16+4UL) +#else +/* 8 MiB max-message-size plus some space for options */ +#define COAP_DEFAULT_MAX_PDU_RX_SIZE (8UL*1024*1024+256) +#endif +#endif /* COAP_DEFAULT_MAX_PDU_RX_SIZE */ + +/** + * Indicates that a response is suppressed. This will occur for error + * responses if the request was received via IP multicast. + */ +#define COAP_DROPPED_RESPONSE -2 + +#define COAP_PDU_DELAYED -3 + +#define COAP_PAYLOAD_START 0xFF /* payload marker */ + +#define COAP_PDU_IS_EMPTY(pdu) ((pdu)->code == 0) +#define COAP_PDU_IS_REQUEST(pdu) (!COAP_PDU_IS_EMPTY(pdu) && (pdu)->code < 32) +#define COAP_PDU_IS_RESPONSE(pdu) ((pdu)->code >= 64 && (pdu)->code < 224) +#define COAP_PDU_IS_SIGNALING(pdu) ((pdu)->code >= 224) + +#define COAP_PDU_MAX_UDP_HEADER_SIZE 4 +#define COAP_PDU_MAX_TCP_HEADER_SIZE 6 + +/** + * structure for CoAP PDUs + * + * Separate COAP_PDU_BUF is allocated with offsets held in coap_pdu_t. + + * token, if any, follows the fixed size header, then optional options until + * payload marker (0xff) (if paylooad), then the optional payload. + * + * Memory layout is: + * <---header--->|<---token---><---options--->0xff<---payload---> + * + * header is addressed with a negative offset to token, its maximum size is + * max_hdr_size. + * + * allocated buffer always starts max_hdr_size before token. + * + * options starts at token + token_length. + * payload starts at data, its length is used_size - (data - token). + * + * alloc_size, used_size and max_size are the offsets from token. + */ + +struct coap_pdu_t { + coap_pdu_type_t type; /**< message type */ + coap_pdu_code_t code; /**< request method (value 1--31) or response code + (value 64-255) */ + coap_mid_t mid; /**< message id, if any, in regular host byte + order */ + uint8_t max_hdr_size; /**< space reserved for protocol-specific header */ + uint8_t hdr_size; /**< actual size used for protocol-specific + header (0 until header is encoded) */ + uint8_t token_length; /**< length of Token */ + uint8_t crit_opt; /**< Set if unknown critical option for proxy */ + uint16_t max_opt; /**< highest option number in PDU */ + size_t alloc_size; /**< allocated storage for token, options and + payload */ + size_t used_size; /**< used bytes of storage for token, options and + payload */ + size_t max_size; /**< maximum size for token, options and payload, + or zero for variable size pdu */ + uint8_t *token; /**< first byte of token, if any, or options */ + uint8_t *data; /**< first byte of payload, if any */ +#ifdef WITH_LWIP + struct pbuf *pbuf; /**< lwIP PBUF. The package data will always reside + * inside the pbuf's payload, but this pointer + * has to be kept because no exact offset can be + * given. This field must not be accessed from + * outside, because the pbuf's reference count + * is checked to be 1 when the pbuf is assigned + * to the pdu, and the pbuf stays exclusive to + * this pdu. */ +#endif + const uint8_t *body_data; /**< Holds ptr to re-assembled data or NULL */ + size_t body_length; /**< Holds body data length */ + size_t body_offset; /**< Holds body data offset */ + size_t body_total; /**< Holds body data total size */ + coap_lg_xmit_t *lg_xmit; /**< Holds ptr to lg_xmit if sending a set of + blocks */ +}; + +/** + * Dynamically grows the size of @p pdu to @p new_size. The new size + * must not exceed the PDU's configure maximum size. On success, this + * function returns 1, otherwise 0. + * + * @param pdu The PDU to resize. + * @param new_size The new size in bytes. + * @return 1 if the operation succeeded, 0 otherwise. + */ +int coap_pdu_resize(coap_pdu_t *pdu, size_t new_size); + +/** + * Dynamically grows the size of @p pdu to @p new_size if needed. The new size + * must not exceed the PDU's configured maximum size. On success, this + * function returns 1, otherwise 0. + * + * @param pdu The PDU to resize. + * @param new_size The new size in bytes. + * @return 1 if the operation succeeded, 0 otherwise. + */ +int coap_pdu_check_resize(coap_pdu_t *pdu, size_t new_size); + +/** +* Interprets @p data to determine the number of bytes in the header. +* This function returns @c 0 on error or a number greater than zero on success. +* +* @param proto Session's protocol +* @param data The first byte of raw data to parse as CoAP PDU. +* +* @return A value greater than zero on success or @c 0 on error. +*/ +size_t coap_pdu_parse_header_size(coap_proto_t proto, + const uint8_t *data); + +/** + * Parses @p data to extract the message size. + * @p length must be at least coap_pdu_parse_header_size(proto, data). + * This function returns @c 0 on error or a number greater than zero on success. + * + * @param proto Session's protocol + * @param data The raw data to parse as CoAP PDU. + * @param length The actual size of @p data. + * + * @return A value greater than zero on success or @c 0 on error. + */ +size_t coap_pdu_parse_size(coap_proto_t proto, + const uint8_t *data, + size_t length); + +/** + * Decode the protocol specific header for the specified PDU. + * @param pdu A newly received PDU. + * @param proto The target wire protocol. + * @return 1 for success or 0 on error. + */ + +int coap_pdu_parse_header(coap_pdu_t *pdu, coap_proto_t proto); + +/** + * Verify consistency in the given CoAP PDU structure and locate the data. + * This function returns @c 0 on error or a number greater than zero on + * success. + * This function only parses the token and options, up to the payload start + * marker. + * + * @param pdu The PDU structure to check. + * + * @return 1 on success or @c 0 on error. + */ +int coap_pdu_parse_opt(coap_pdu_t *pdu); + +/** + * Clears any contents from @p pdu and resets @c used_size, + * and @c data pointers. @c max_size is set to @p size, any + * other field is set to @c 0. Note that @p pdu must be a valid + * pointer to a coap_pdu_t object created e.g. by coap_pdu_init(). + * + * @param pdu The PDU to clear. + * @param size The maximum size of the PDU. + */ +void coap_pdu_clear(coap_pdu_t *pdu, size_t size); + +/** + * Adds option of given @p number to @p pdu that is passed as first + * parameter. + * + * The internal version of coap_add_option() may cause an @p option to be + * inserted, even if there is any data in the @p pdu. + * + * Note: Where possible, the option @p data needs to be stripped of leading + * zeros (big endian) to reduce the amount of data needed in the PDU, as well + * as in some cases the maximum data size of an option can be exceeded if not + * stripped and hence be illegal. This is done by using coap_encode_var_safe() + * or coap_encode_var_safe8(). + * + * @param pdu The PDU where the option is to be added. + * @param number The number of the new option. + * @param len The length of the new option. + * @param data The data of the new option. + * + * @return The overall length of the option or @c 0 on failure. + */ +size_t coap_add_option_internal(coap_pdu_t *pdu, + coap_option_num_t number, + size_t len, + const uint8_t *data); +/** + * Removes (first) option of given number from the @p pdu. + * + * @param pdu The PDU to remove the option from. + * @param number The number of the CoAP option to remove (first only removed). + * + * @return @c 1 if success else @c 0 if error. + */ +int coap_remove_option(coap_pdu_t *pdu, coap_option_num_t number); + +/** + * Inserts option of given number in the @p pdu with the appropriate data. + * The option will be inserted in the appropriate place in the options in + * the pdu. + * + * @param pdu The PDU where the option is to be inserted. + * @param number The number of the new option. + * @param len The length of the new option. + * @param data The data of the new option. + * + * @return The overall length of the option or @c 0 on failure. + */ +size_t coap_insert_option(coap_pdu_t *pdu, coap_option_num_t number, + size_t len, const uint8_t *data); + +/** + * Updates existing first option of given number in the @p pdu with the new + * data. + * + * @param pdu The PDU where the option is to be updated. + * @param number The number of the option to update (first only updated). + * @param len The length of the updated option. + * @param data The data of the updated option. + * + * @return The overall length of the updated option or @c 0 on failure. + */ +size_t coap_update_option(coap_pdu_t *pdu, + coap_option_num_t number, + size_t len, + const uint8_t *data); + +/** + * Compose the protocol specific header for the specified PDU. + * + * @param pdu A newly composed PDU. + * @param proto The target wire protocol. + * + * @return Number of header bytes prepended before pdu->token or 0 on error. + */ + +size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto); + + /** + * Updates token in @p pdu with length @p len and @p data. + * This function returns @c 0 on error or a value greater than zero on success. + * + * @param pdu The PDU where the token is to be updated. + * @param len The length of the new token. + * @param data The token to add. + * + * @return A value greater than zero on success, or @c 0 on error. + */ +int coap_update_token(coap_pdu_t *pdu, + size_t len, + const uint8_t *data); + +/** @} */ + +#endif /* COAP_COAP_PDU_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_prng.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_prng.h new file mode 100644 index 000000000..ae9b51f81 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_prng.h @@ -0,0 +1,114 @@ +/* + * coap_prng.h -- Pseudo Random Numbers + * + * Copyright (C) 2010-2020 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_prng.h + * @brief Pseudo Random Numbers + */ + +#ifndef COAP_PRNG_H_ +#define COAP_PRNG_H_ + +/** + * @ingroup application_api + * @defgroup coap_prng Pseudo Random Numbers + * API for generating pseudo random numbers + * @{ + */ + +#if defined(WITH_CONTIKI) +#include + +/** + * Fills \p buf with \p len random bytes. This is the default implementation for + * coap_prng(). You might want to change contiki_prng_impl() to use a better + * PRNG on your specific platform. + */ +COAP_STATIC_INLINE int +contiki_prng_impl(unsigned char *buf, size_t len) { + uint16_t v = random_rand(); + while (len > sizeof(v)) { + memcpy(buf, &v, sizeof(v)); + len -= sizeof(v); + buf += sizeof(v); + v = random_rand(); + } + + memcpy(buf, &v, len); + return 1; +} + +#define coap_prng(Buf,Length) contiki_prng_impl((Buf), (Length)) +#define coap_prng_init(Value) random_init((uint16_t)(Value)) + +#elif defined(WITH_LWIP) && defined(LWIP_RAND) + +COAP_STATIC_INLINE int +lwip_prng_impl(unsigned char *buf, size_t len) { + u32_t v = LWIP_RAND(); + while (len > sizeof(v)) { + memcpy(buf, &v, sizeof(v)); + len -= sizeof(v); + buf += sizeof(v); + v = LWIP_RAND(); + } + + memcpy(buf, &v, len); + return 1; +} + +#define coap_prng(Buf,Length) lwip_prng_impl((Buf), (Length)) +#define coap_prng_init(Value) (void)Value + +#else + +/** + * Data type for random number generator function. The function must + * fill @p len bytes of random data into the buffer starting at @p + * out. On success, the function should return 1, zero otherwise. + */ +typedef int (*coap_rand_func_t)(void *out, size_t len); + +/** + * Replaces the current random number generation function with the + * default function @p rng. + * + * @param rng The random number generation function to use. + */ +void coap_set_prng(coap_rand_func_t rng); + +/** + * Seeds the default random number generation function with the given + * @p seed. The default random number generation function will use + * getrandom() if available, ignoring the seed. + * + * @param seed The seed for the pseudo random number generator. + */ +void coap_prng_init(unsigned int seed); + +/** + * Fills @p buf with @p len random bytes using the default pseudo + * random number generator. The default PRNG can be changed with + * coap_set_prng(). This function returns 1 when @p len random bytes + * have been written to @p buf, zero otherwise. + * + * @param buf The buffer to fill with random bytes. + * @param len The number of random bytes to write into @p buf. + * + * @return 1 on success, 0 otherwise. + */ +int coap_prng(void *buf, size_t len); + +#endif /* POSIX */ + +/** @} */ + +#endif /* COAP_PRNG_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_resource_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_resource_internal.h new file mode 100644 index 000000000..ed6f0c69a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_resource_internal.h @@ -0,0 +1,145 @@ +/* + * coap_resource_internal.h -- generic resource handling + * + * Copyright (C) 2010,2011,2014-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_resource_internal.h + * @brief Generic resource internal handling + */ + +#ifndef COAP_RESOURCE_INTERNAL_H_ +#define COAP_RESOURCE_INTERNAL_H_ + +#include "coap_internal.h" +#include "uthash.h" + +#if COAP_SERVER_SUPPORT +/** + * @ingroup internal_api + * @defgroup coap_resource_internal Resources + * Internal API for handling resources + * @{ + */ + +/** +* Abstraction of attribute associated with a resource. +*/ +struct coap_attr_t { + struct coap_attr_t *next; /**< Pointer to next in chain or NULL */ + coap_str_const_t *name; /**< Name of the attribute */ + coap_str_const_t *value; /**< Value of the attribute (can be NULL) */ + int flags; +}; + +/** +* Abstraction of resource that can be attached to coap_context_t. +* The key is uri_path. +*/ +struct coap_resource_t { + unsigned int dirty:1; /**< set to 1 if resource has changed */ + unsigned int partiallydirty:1; /**< set to 1 if some subscribers have not yet + * been notified of the last change */ + unsigned int observable:1; /**< can be observed */ + unsigned int cacheable:1; /**< can be cached */ + unsigned int is_unknown:1; /**< resource created for unknown handler */ + unsigned int is_proxy_uri:1; /**< resource created for proxy URI handler */ + + /** + * Used to store handlers for the seven coap methods @c GET, @c POST, @c PUT, + * @c DELETE, @c FETCH, @c PATCH and @c IPATCH. + * coap_dispatch() will pass incoming requests to handle_request() and then + * to the handler that corresponds to its request method or generate a 4.05 + * response if no handler is available. + */ + coap_method_handler_t handler[7]; + + UT_hash_handle hh; + + coap_attr_t *link_attr; /**< attributes to be included with the link format */ + coap_subscription_t *subscribers; /**< list of observers for this resource */ + + /** + * Request URI Path for this resource. This field will point into static + * or allocated memory which must remain there for the duration of the + * resource. + */ + coap_str_const_t *uri_path; /**< the key used for hash lookup for this + resource */ + int flags; /**< zero or more COAP_RESOURCE_FLAGS_* or'd together */ + + /** + * The next value for the Observe option. This field must be increased each + * time the resource changes. Only the lower 24 bits are sent. + */ + unsigned int observe; + + /** + * Pointer back to the context that 'owns' this resource. + */ + coap_context_t *context; + + /** + * Count of valid names this host is known by (proxy support) + */ + size_t proxy_name_count; + + /** + * Array valid names this host is known by (proxy support) + */ + coap_str_const_t ** proxy_name_list; + + /** + * This pointer is under user control. It can be used to store context for + * the coap handler. + */ + void *user_data; + +}; + +/** + * Deletes all resources from given @p context and frees their storage. + * + * @param context The CoAP context with the resources to be deleted. + */ +void coap_delete_all_resources(coap_context_t *context); + +#define RESOURCES_ADD(r, obj) \ + HASH_ADD(hh, (r), uri_path->s[0], (obj)->uri_path->length, (obj)) + +#define RESOURCES_DELETE(r, obj) \ + HASH_DELETE(hh, (r), (obj)) + +#define RESOURCES_ITER(r,tmp) \ + coap_resource_t *tmp, *rtmp; \ + HASH_ITER(hh, (r), tmp, rtmp) + +#define RESOURCES_FIND(r, k, res) { \ + HASH_FIND(hh, (r), (k)->s, (k)->length, (res)); \ + } + +/** + * Deletes an attribute. + * Note: This is for internal use only, as it is not deleted from its chain. + * + * @param attr Pointer to a previously created attribute. + * + */ +void coap_delete_attr(coap_attr_t *attr); + +coap_print_status_t coap_print_wellknown(coap_context_t *, + unsigned char *, + size_t *, size_t, + const coap_string_t *); + +/** @} */ + +#endif /* COAP_SERVER_SUPPORT */ + +#endif /* COAP_RESOURCE_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_riot.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_riot.h new file mode 100644 index 000000000..5a6910076 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_riot.h @@ -0,0 +1,39 @@ +/* coap_riot.h -- RIOT-specific definitions for libcoap + * + * Copyright (C) 2019 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_riot.h + * @brief RIOT-specific definitions for libcoap + */ + +#ifndef COAP_RIOT_H_ +#define COAP_RIOT_H_ + +#ifndef LIBCOAP_MSG_QUEUE_SIZE +/** + * Size of the queue for passing messages between the network + * interface and the coap stack. */ +#define LIBCOAP_MSG_QUEUE_SIZE (32U) +#endif /* LIBCOAP_MSG_QUEUE_SIZE */ + +#ifndef LIBCOAP_MAX_SOCKETS +/** + * Maximum number of sockets that are simultaneously considered for + * reading or writing. */ +#define LIBCOAP_MAX_SOCKETS (16U) +#endif /* LIBCOAP_MAX_SOCKETS */ + +/** + * This function must be called in the RIOT CoAP thread for + * RIOT-specific initialization. + */ +void coap_riot_startup(void); + +#endif /* COAP_RIOT_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_session.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_session.h new file mode 100644 index 000000000..6c3846011 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_session.h @@ -0,0 +1,624 @@ +/* coap_session.h -- Session management for libcoap +* +* Copyright (C) 2017 Jean-Claue Michelou +* + * SPDX-License-Identifier: BSD-2-Clause + * +* This file is part of the CoAP library libcoap. Please see +* README for terms of use. +*/ + +/** + * @file coap_session.h + * @brief Defines the application visible session information + */ + +#ifndef COAP_SESSION_H_ +#define COAP_SESSION_H_ + +/** + * @ingroup application_api + * @defgroup session Sessions + * API for CoAP Session access + * @{ + */ + +/** +* Abstraction of a fixed point number that can be used where necessary instead +* of a float. 1,000 fractional bits equals one integer +*/ +typedef struct coap_fixed_point_t { + uint16_t integer_part; /**< Integer part of fixed point variable */ + uint16_t fractional_part; /**< Fractional part of fixed point variable + 1/1000 (3 points) precision */ +} coap_fixed_point_t; + +#define COAP_PROTO_NOT_RELIABLE(p) ((p)==COAP_PROTO_UDP || (p)==COAP_PROTO_DTLS) +#define COAP_PROTO_RELIABLE(p) ((p)==COAP_PROTO_TCP || (p)==COAP_PROTO_TLS) + +/** + * coap_session_type_t values + */ +typedef enum coap_session_type_t { + COAP_SESSION_TYPE_NONE = 0, /**< Not defined */ + COAP_SESSION_TYPE_CLIENT, /**< client-side */ + COAP_SESSION_TYPE_SERVER, /**< server-side */ + COAP_SESSION_TYPE_HELLO, /**< server-side ephemeral session for + responding to a client hello */ +} coap_session_type_t; + +/** + * coap_session_state_t values + */ +typedef enum coap_session_state_t { + COAP_SESSION_STATE_NONE = 0, + COAP_SESSION_STATE_CONNECTING, + COAP_SESSION_STATE_HANDSHAKE, + COAP_SESSION_STATE_CSM, + COAP_SESSION_STATE_ESTABLISHED, +} coap_session_state_t; + +/** + * Increment reference counter on a session. + * + * @param session The CoAP session. + * @return same as session + */ +coap_session_t *coap_session_reference(coap_session_t *session); + +/** + * Decrement reference counter on a session. + * Note that the session may be deleted as a result and should not be used + * after this call. + * + * @param session The CoAP session. + */ +void coap_session_release(coap_session_t *session); + +/** + * Notify session that it has failed. This cleans up any outstanding / queued + * transmissions, observations etc.. + * + * @param session The CoAP session. + * @param reason The reason why the session was disconnected. + */ +void coap_session_disconnected(coap_session_t *session, + coap_nack_reason_t reason); + +/** + * Stores @p data with the given session. This function overwrites any value + * that has previously been stored with @p session. + * + * @param session The CoAP session. + * @param data The pointer to the data to store. + */ +void coap_session_set_app_data(coap_session_t *session, void *data); + +/** + * Returns any application-specific data that has been stored with @p + * session using the function coap_session_set_app_data(). This function will + * return @c NULL if no data has been stored. + * + * @param session The CoAP session. + * + * @return Pointer to the stored data or @c NULL. + */ +void *coap_session_get_app_data(const coap_session_t *session); + +/** + * Get the remote IP address from the session. + * + * @param session The CoAP session. + * + * @return The session's remote address or @c NULL on failure. + */ +const coap_address_t *coap_session_get_addr_remote( + const coap_session_t *session); + +/** + * Get the local IP address from the session. + * + * @param session The CoAP session. + * + * @return The session's local address or @c NULL on failure. + */ +const coap_address_t *coap_session_get_addr_local( + const coap_session_t *session); + +/** + * Get the session protocol type + * + * @param session The CoAP session. + * + * @return The session's protocol type + */ +coap_proto_t coap_session_get_proto(const coap_session_t *session); + +/** + * Get the session type + * + * @param session The CoAP session. + * + * @return The session's type + */ +coap_session_type_t coap_session_get_type(const coap_session_t *session); + +/** + * Get the session state + * + * @param session The CoAP session. + * + * @return The session's state + */ +coap_session_state_t coap_session_get_state(const coap_session_t *session); + +/** + * Get the session if index + * + * @param session The CoAP session. + * + * @return The session's if index, or @c -1 on error. + */ +int coap_session_get_ifindex(const coap_session_t *session); + +/** + * Get the session TLS security ptr (TLS type dependent) + * + * OpenSSL: SSL* + * GnuTLS: gnutls_session_t (implicit *) + * Mbed TLS: mbedtls_ssl_context* + * TinyDTLS: struct dtls_context* + * + * @param session The CoAP session. + * @param tls_lib Updated with the library type. + * + * @return The session TLS ptr or @c NULL if not set up + */ +void *coap_session_get_tls(const coap_session_t *session, + coap_tls_library_t *tls_lib); + +/** + * Get the session context + * + * @param session The CoAP session. + * + * @return The session's context + */ +coap_context_t *coap_session_get_context(const coap_session_t *session); + +/** + * Set the session type to client. Typically used in a call-home server. + * The session needs to be of type COAP_SESSION_TYPE_SERVER. + * Note: If this function is successful, the session reference count is + * incremented and a subsequent coap_session_release() taking the + * reference count to 0 will cause the session to be freed off. + * + * @param session The CoAP session. + * + * @return @c 1 if updated, @c 0 on failure. + */ +int coap_session_set_type_client(coap_session_t *session); + +/** + * Set the session MTU. This is the maximum message size that can be sent, + * excluding IP and UDP overhead. + * + * @param session The CoAP session. + * @param mtu maximum message size + */ +void coap_session_set_mtu(coap_session_t *session, unsigned mtu); + +/** + * Get maximum acceptable PDU size + * + * @param session The CoAP session. + * @return maximum PDU size, not including header (but including token). + */ +size_t coap_session_max_pdu_size(const coap_session_t *session); + +/** +* Creates a new client session to the designated server. +* @param ctx The CoAP context. +* @param local_if Address of local interface. It is recommended to use NULL to let the operating system choose a suitable local interface. If an address is specified, the port number should be zero, which means that a free port is automatically selected. +* @param server The server's address. If the port number is zero, the default port for the protocol will be used. +* @param proto Protocol. +* +* @return A new CoAP session or NULL if failed. Call coap_session_release to free. +*/ +coap_session_t *coap_new_client_session( + coap_context_t *ctx, + const coap_address_t *local_if, + const coap_address_t *server, + coap_proto_t proto +); + +/** +* Creates a new client session to the designated server with PSK credentials +* @param ctx The CoAP context. +* @param local_if Address of local interface. It is recommended to use NULL to let the operating system choose a suitable local interface. If an address is specified, the port number should be zero, which means that a free port is automatically selected. +* @param server The server's address. If the port number is zero, the default port for the protocol will be used. +* @param proto Protocol. +* @param identity PSK client identity +* @param key PSK shared key +* @param key_len PSK shared key length +* +* @return A new CoAP session or NULL if failed. Call coap_session_release to free. +*/ +coap_session_t *coap_new_client_session_psk( + coap_context_t *ctx, + const coap_address_t *local_if, + const coap_address_t *server, + coap_proto_t proto, + const char *identity, + const uint8_t *key, + unsigned key_len +); + +/** +* Creates a new client session to the designated server with PSK credentials +* @param ctx The CoAP context. +* @param local_if Address of local interface. It is recommended to use NULL to +* let the operating system choose a suitable local interface. +* If an address is specified, the port number should be zero, +* which means that a free port is automatically selected. +* @param server The server's address. If the port number is zero, the default +* port for the protocol will be used. +* @param proto CoAP Protocol. +* @param setup_data PSK parameters. +* +* @return A new CoAP session or NULL if failed. Call coap_session_release() +* to free. +*/ +coap_session_t *coap_new_client_session_psk2( + coap_context_t *ctx, + const coap_address_t *local_if, + const coap_address_t *server, + coap_proto_t proto, + coap_dtls_cpsk_t *setup_data +); + +/** + * Get the server session's current Identity Hint (PSK). + * + * @param session The current coap_session_t object. + * + * @return @c hint if successful, else @c NULL. + */ +const coap_bin_const_t * coap_session_get_psk_hint( + const coap_session_t *session); + +/** + * Get the server session's current PSK identity (PSK). + * + * @param session The current coap_session_t object. + * + * @return PSK identity if successful, else @c NULL. + */ +const coap_bin_const_t *coap_session_get_psk_identity( + const coap_session_t *session); +/** + * Get the session's current pre-shared key (PSK). + * + * @param session The current coap_session_t object. + * + * @return @c psk_key if successful, else @c NULL. + */ +const coap_bin_const_t * coap_session_get_psk_key( + const coap_session_t *session); + +/** +* Creates a new client session to the designated server with PKI credentials +* @param ctx The CoAP context. +* @param local_if Address of local interface. It is recommended to use NULL to +* let the operating system choose a suitable local interface. +* If an address is specified, the port number should be zero, +* which means that a free port is automatically selected. +* @param server The server's address. If the port number is zero, the default +* port for the protocol will be used. +* @param proto CoAP Protocol. +* @param setup_data PKI parameters. +* +* @return A new CoAP session or NULL if failed. Call coap_session_release() +* to free. +*/ +coap_session_t *coap_new_client_session_pki( + coap_context_t *ctx, + const coap_address_t *local_if, + const coap_address_t *server, + coap_proto_t proto, + coap_dtls_pki_t *setup_data +); + +/** + * Initializes the token value to use as a starting point. + * + * @param session The current coap_session_t object. + * @param length The length of the token (0 - 8 bytes). + * @param token The token data. + * + */ +void coap_session_init_token(coap_session_t *session, size_t length, + const uint8_t *token); + +/** + * Creates a new token for use. + * + * @param session The current coap_session_t object. + * @param length Updated with the length of the new token. + * @param token Updated with the new token data (must be 8 bytes long). + * + */ +void coap_session_new_token(coap_session_t *session, size_t *length, + uint8_t *token); + +/** + * @ingroup logging + * Get session description. + * + * @param session The CoAP session. + * @return description string. + */ +const char *coap_session_str(const coap_session_t *session); + +/** +* Create a new endpoint for communicating with peers. +* +* @param context The coap context that will own the new endpoint +* @param listen_addr Address the endpoint will listen for incoming requests on or originate outgoing requests from. Use NULL to specify that no incoming request will be accepted and use a random endpoint. +* @param proto Protocol used on this endpoint +*/ + +coap_endpoint_t *coap_new_endpoint(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto); + +/** +* Set the endpoint's default MTU. This is the maximum message size that can be +* sent, excluding IP and UDP overhead. +* +* @param endpoint The CoAP endpoint. +* @param mtu maximum message size +*/ +void coap_endpoint_set_default_mtu(coap_endpoint_t *endpoint, unsigned mtu); + +void coap_free_endpoint(coap_endpoint_t *ep); + +/** @} */ + +/** + * @ingroup logging +* Get endpoint description. +* +* @param endpoint The CoAP endpoint. +* @return description string. +*/ +const char *coap_endpoint_str(const coap_endpoint_t *endpoint); + +coap_session_t *coap_session_get_by_peer(const coap_context_t *ctx, + const coap_address_t *remote_addr, int ifindex); + + /** + * @ingroup application_api + * @defgroup cc Rate Control + * API for updating transmission parameters for CoAP rate control. + * The transmission parameters for CoAP rate control ("Congestion + * Control" in stream-oriented protocols) are defined in + * https://tools.ietf.org/html/rfc7252#section-4.8 + * @{ + */ + + /** + * Number of seconds when to expect an ACK or a response to an + * outstanding CON message. + * RFC 7252, Section 4.8 Default value of ACK_TIMEOUT is 2 + * + * Configurable using coap_session_set_ack_timeout() + */ +#define COAP_DEFAULT_ACK_TIMEOUT ((coap_fixed_point_t){2,0}) + + /** + * A factor that is used to randomize the wait time before a message + * is retransmitted to prevent synchronization effects. + * RFC 7252, Section 4.8 Default value of ACK_RANDOM_FACTOR is 1.5 + * + * Configurable using coap_session_set_ack_random_factor() + */ +#define COAP_DEFAULT_ACK_RANDOM_FACTOR ((coap_fixed_point_t){1,500}) + + /** + * Number of message retransmissions before message sending is stopped. + * RFC 7252, Section 4.8 Default value of MAX_RETRANSMIT is 4 + * + * Configurable using coap_session_set_max_retransmit() + */ +#define COAP_DEFAULT_MAX_RETRANSMIT (4U) + + /** + * The number of simultaneous outstanding interactions that a client + * maintains to a given server. + * RFC 7252, Section 4.8 Default value of NSTART is 1 + * + * Configurable using coap_session_set_nstart() + */ +#define COAP_DEFAULT_NSTART (1U) + + /** + * The number of seconds to use as bounds for multicast traffic + * RFC 7252, Section 4.8 Default value of DEFAULT_LEISURE is 5.0 + * + * Configurable using coap_session_set_default_leisure() + */ +#define COAP_DEFAULT_DEFAULT_LEISURE ((coap_fixed_point_t){5,0}) + + /** + * The number of bytes/second allowed when there is no response + * RFC 7252, Section 4.8 Default value of PROBING_RATE is 1 + * + * Configurable using coap_session_set_probing_rate() + */ +#define COAP_DEFAULT_PROBING_RATE (1U) + + /** + * The MAX_LATENCY definition. + * RFC 7252, Section 4.8.2 MAX_LATENCY is 100. + */ +#define COAP_DEFAULT_MAX_LATENCY (100U) + +/** +* Set the CoAP initial ack response timeout before the next re-transmit +* +* Number of seconds when to expect an ACK or a response to an +* outstanding CON message. +* RFC7252 ACK_TIMEOUT +* +* @param session The CoAP session. +* @param value The value to set to. The default is 2.0 and should not normally +* get changed. +*/ +void coap_session_set_ack_timeout(coap_session_t *session, + coap_fixed_point_t value); + +/** +* Get the CoAP initial ack response timeout before the next re-transmit +* +* Number of seconds when to expect an ACK or a response to an +* outstanding CON message. +* RFC7252 ACK_TIMEOUT +* +* @param session The CoAP session. +* +* @return Current ack response timeout value +*/ +coap_fixed_point_t coap_session_get_ack_timeout(const coap_session_t *session); + +/** +* Set the CoAP ack randomize factor +* +* A factor that is used to randomize the wait time before a message +* is retransmitted to prevent synchronization effects. +* RFC7252 ACK_RANDOM_FACTOR +* +* @param session The CoAP session. +* @param value The value to set to. The default is 1.5 and should not normally +* get changed. +*/ +void coap_session_set_ack_random_factor(coap_session_t *session, + coap_fixed_point_t value); + +/** +* Get the CoAP ack randomize factor +* +* A factor that is used to randomize the wait time before a message +* is retransmitted to prevent synchronization effects. +* RFC7252 ACK_RANDOM_FACTOR +* +* @param session The CoAP session. +* +* @return Current ack randomize value +*/ +coap_fixed_point_t coap_session_get_ack_random_factor( + const coap_session_t *session); + +/** +* Set the CoAP maximum retransmit count before failure +* +* Number of message retransmissions before message sending is stopped +* RFC7252 MAX_RETRANSMIT +* +* @param session The CoAP session. +* @param value The value to set to. The default is 4 and should not normally +* get changed. +*/ +void coap_session_set_max_retransmit(coap_session_t *session, + uint16_t value); + +/** +* Get the CoAP maximum retransmit before failure +* +* Number of message retransmissions before message sending is stopped +* RFC7252 MAX_RETRANSMIT +* +* @param session The CoAP session. +* +* @return Current maximum retransmit value +*/ +uint16_t coap_session_get_max_retransmit(const coap_session_t *session); + +/** +* Set the CoAP maximum concurrent transmission count of Confirmable messages +* RFC7252 NSTART +* +* @param session The CoAP session. +* @param value The value to set to. The default is 1 and should not normally +* get changed. +*/ +void coap_session_set_nstart(coap_session_t *session, + uint16_t value); + +/** +* Get the CoAP maximum concurrent transmission count of Confirmable messages +* RFC7252 NSTART +* +* @param session The CoAP session. +* +* @return Current nstart value +*/ +uint16_t coap_session_get_nstart(const coap_session_t *session); + +/** +* Set the CoAP default leisure time (for multicast) +* RFC7252 DEFAULT_LEISURE +* +* @param session The CoAP session. +* @param value The value to set to. The default is 5.0 and should not normally +* get changed. +*/ +void coap_session_set_default_leisure(coap_session_t *session, + coap_fixed_point_t value); + +/** +* Get the CoAP default leisure time +* RFC7252 DEFAULT_LEISURE +* +* @param session The CoAP session. +* +* @return Current default_leisure value +*/ +coap_fixed_point_t coap_session_get_default_leisure( + const coap_session_t *session); + +/** +* Set the CoAP probing rate when there is no response +* RFC7252 PROBING_RATE +* +* @param session The CoAP session. +* @param value The value to set to. The default is 1 and should not normally +* get changed. +*/ +void coap_session_set_probing_rate(coap_session_t *session, uint32_t value); + +/** +* Get the CoAP probing rate when there is no response +* RFC7252 PROBING_RATE +* +* @param session The CoAP session. +* +* @return Current probing_rate value +*/ +uint32_t coap_session_get_probing_rate(const coap_session_t *session); + + /** @} */ +/** + * Send a ping message for the session. + * @param session The CoAP session. + * + * @return COAP_INVALID_MID if there is an error + */ +coap_mid_t coap_session_send_ping(coap_session_t *session); + +/** + * Disable client automatically sending observe cancel on session close + * + * @param session The CoAP session. + */ +void coap_session_set_no_observe_cancel(coap_session_t *session); + +#endif /* COAP_SESSION_H */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_session_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_session_internal.h new file mode 100644 index 000000000..476239636 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_session_internal.h @@ -0,0 +1,436 @@ +/* + * coap_session_internal.h -- Structures, Enums & Functions that are not + * exposed to application programming + * + * Copyright (C) 2010-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_session_internal.h + * @brief CoAP session internal information + */ + +#ifndef COAP_SESSION_INTERNAL_H_ +#define COAP_SESSION_INTERNAL_H_ + +#include "coap_internal.h" +#include "coap_io_internal.h" + +#define COAP_DEFAULT_SESSION_TIMEOUT 300 +#define COAP_PARTIAL_SESSION_TIMEOUT_TICKS (30 * COAP_TICKS_PER_SECOND) +#define COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS 100 + +/** + * @ingroup internal_api + * @defgroup session_internal Sessions + * Internal API for handling Sessions + * @{ + */ + +/** + * Only used for servers for hashing incoming packets. Cannot have local IP + * address as this may be an initial multicast and subsequent unicast address + */ +struct coap_addr_hash_t { + coap_address_t remote; /**< remote address and port */ + uint16_t lport; /**< local port */ + coap_proto_t proto; /**< CoAP protocol */ +}; + +/** + * Abstraction of virtual session that can be attached to coap_context_t + * (client) or coap_endpoint_t (server). + */ +struct coap_session_t { + coap_proto_t proto; /**< protocol used */ + coap_session_type_t type; /**< client or server side socket */ + coap_session_state_t state; /**< current state of relationaship with + peer */ + unsigned ref; /**< reference count from queues */ + size_t tls_overhead; /**< overhead of TLS layer */ + size_t mtu; /**< path or CSM mtu (xmt) */ + size_t csm_rcv_mtu; /**< CSM mtu (rcv) */ + coap_addr_hash_t addr_hash; /**< Address hash for server incoming packets */ + UT_hash_handle hh; + coap_addr_tuple_t addr_info; /**< key: remote/local address info */ + int ifindex; /**< interface index */ + coap_socket_t sock; /**< socket object for the session, if + any */ +#if COAP_SERVER_SUPPORT + coap_endpoint_t *endpoint; /**< session's endpoint */ +#endif /* COAP_SERVER_SUPPORT */ + coap_context_t *context; /**< session's context */ + void *tls; /**< security parameters */ + uint16_t tx_mid; /**< the last message id that was used in + this session */ + uint8_t con_active; /**< Active CON request sent */ + uint8_t csm_block_supported; /**< CSM TCP blocks supported */ + coap_mid_t last_ping_mid; /**< the last keepalive message id that was + used in this session */ + coap_queue_t *delayqueue; /**< list of delayed messages waiting to + be sent */ + coap_lg_xmit_t *lg_xmit; /**< list of large transmissions */ +#if COAP_CLIENT_SUPPORT + coap_lg_crcv_t *lg_crcv; /**< Client list of expected large receives */ +#endif /* COAP_CLIENT_SUPPORT */ +#if COAP_SERVER_SUPPORT + coap_lg_srcv_t *lg_srcv; /**< Server list of expected large receives */ +#endif /* COAP_SERVER_SUPPORT */ + size_t partial_write; /**< if > 0 indicates number of bytes + already written from the pdu at the + head of sendqueue */ + uint8_t read_header[8]; /**< storage space for header of incoming + message header */ + size_t partial_read; /**< if > 0 indicates number of bytes + already read for an incoming message */ + coap_pdu_t *partial_pdu; /**< incomplete incoming pdu */ + coap_tick_t last_rx_tx; + coap_tick_t last_tx_rst; + coap_tick_t last_ping; + coap_tick_t last_pong; + coap_tick_t csm_tx; + coap_dtls_cpsk_t cpsk_setup_data; /**< client provided PSK initial setup + data */ + coap_bin_const_t *psk_identity; /**< If client, this field contains the + current identity for server; When this + field is NULL, the current identity is + contained in cpsk_setup_data + + If server, this field contains the client + provided identity. + + Value maintained internally */ + coap_bin_const_t *psk_key; /**< If client, this field contains the + current pre-shared key for server; + When this field is NULL, the current + key is contained in cpsk_setup_data + + If server, this field contains the + client's current key. + + Value maintained internally */ + coap_bin_const_t *psk_hint; /**< If client, this field contains the + server provided identity hint. + + If server, this field contains the + current hint for the client; When this + field is NULL, the current hint is + contained in context->spsk_setup_data + + Value maintained internally */ + void *app; /**< application-specific data */ + coap_fixed_point_t ack_timeout; /**< timeout waiting for ack + (default 2.0 secs) */ + coap_fixed_point_t ack_random_factor; /**< ack random factor backoff (default + 1.5) */ + uint16_t max_retransmit; /**< maximum re-transmit count + (default 4) */ + uint16_t nstart; /**< maximum concurrent confirmable xmits + (default 1) */ + coap_fixed_point_t default_leisure; /**< Mcast leisure time + (default 5.0 secs) */ + uint32_t probing_rate; /**< Max transfer wait when remote is not + respoding (default 1 byte/sec) */ + unsigned int dtls_timeout_count; /**< dtls setup retry counter */ + int dtls_event; /**< Tracking any (D)TLS events on this + sesison */ + uint8_t csm_bert_rem_support; /**< CSM TCP BERT blocks supported (remote) */ + uint8_t csm_bert_loc_support; /**< CSM TCP BERT blocks supported (local) */ + uint8_t block_mode; /**< Zero or more COAP_BLOCK_ or'd options */ + uint8_t doing_first; /**< Set if doing client's first request */ + uint8_t proxy_session; /**< Set if this is an ongoing proxy session */ + uint8_t delay_recursive; /**< Set if in coap_client_delay_first() */ + uint8_t no_observe_cancel; /**< Set if do not cancel observe on session + close */ + uint32_t tx_rtag; /**< Next Request-Tag number to use */ + uint64_t tx_token; /**< Next token number to use */ + coap_bin_const_t *last_token; /** last token used to make a request */ + coap_bin_const_t *echo; /**< Echo value to send with next request */ + coap_mid_t last_ack_mid; /**< The last ACK mid that has been + been processed */ + coap_mid_t last_con_mid; /**< The last CON mid that has been + been processed */ +}; + +#if COAP_SERVER_SUPPORT +/** + * Abstraction of virtual endpoint that can be attached to coap_context_t. The + * keys (port, bind_addr) must uniquely identify this endpoint. + */ +struct coap_endpoint_t { + struct coap_endpoint_t *next; + coap_context_t *context; /**< endpoint's context */ + coap_proto_t proto; /**< protocol used on this interface */ + uint16_t default_mtu; /**< default mtu for this interface */ + coap_socket_t sock; /**< socket object for the interface, if + any */ + coap_address_t bind_addr; /**< local interface address */ + coap_session_t *sessions; /**< hash table or list of active sessions */ +}; +#endif /* COAP_SERVER_SUPPORT */ + +/** + * Notify session transport has just connected and CSM exchange can now start. + * + * @param session The CoAP session. + */ +void coap_session_send_csm(coap_session_t *session); + +/** + * Notify session that it has just connected or reconnected. + * + * @param session The CoAP session. + */ +void coap_session_connected(coap_session_t *session); + +/** + * Refresh the session's current Identity Hint (PSK). + * Note: A copy of @p psk_hint is maintained in the session by libcoap. + * + * @param session The current coap_session_t object. + * @param psk_hint If NULL, the Identity Hint will revert to the + * initial Identity Hint used at session setup. + * + * @return @c 1 if successful, else @c 0. + */ +int coap_session_refresh_psk_hint(coap_session_t *session, + const coap_bin_const_t *psk_hint); + +/** + * Refresh the session's current pre-shared key (PSK). + * Note: A copy of @p psk_key is maintained in the session by libcoap. + * + * @param session The current coap_session_t object. + * @param psk_key If NULL, the pre-shared key will revert to the + * initial pre-shared key used at session setup. + * + * @return @c 1 if successful, else @c 0. + */ +int coap_session_refresh_psk_key(coap_session_t *session, + const coap_bin_const_t *psk_key); + +/** + * Refresh the session's current pre-shared identity (PSK). + * Note: A copy of @p psk_identity is maintained in the session by libcoap. + * + * @param session The current coap_session_t object. + * @param psk_identity If NULL, the pre-shared identity will revert to the + * initial pre-shared key used as session setup. + * + * @return @c 1 if successful, else @c 0. + */ +int coap_session_refresh_psk_identity(coap_session_t *session, + const coap_bin_const_t *psk_identity); + +#if COAP_SERVER_SUPPORT +/** + * Creates a new server session for the specified endpoint. + * @param ctx The CoAP context. + * @param ep An endpoint where an incoming connection request is pending. + * + * @return A new CoAP session or NULL if failed. Call coap_session_release to + * add to unused queue. + */ +coap_session_t *coap_new_server_session( + coap_context_t *ctx, + coap_endpoint_t *ep +); +#endif /* COAP_SERVER_SUPPORT */ + +/** + * Function interface for datagram data transmission. This function returns + * the number of bytes that have been transmitted, or a value less than zero + * on error. + * + * @param session Session to send data on. + * @param data The data to send. + * @param datalen The actual length of @p data. + * + * @return The number of bytes written on success, or a value + * less than zero on error. + */ +ssize_t coap_session_send(coap_session_t *session, + const uint8_t *data, size_t datalen); + +/** + * Function interface for stream data transmission. This function returns + * the number of bytes that have been transmitted, or a value less than zero + * on error. The number of bytes written may be less than datalen because of + * congestion control. + * + * @param session Session to send data on. + * @param data The data to send. + * @param datalen The actual length of @p data. + * + * @return The number of bytes written on success, or a value + * less than zero on error. + */ +ssize_t coap_session_write(coap_session_t *session, + const uint8_t *data, size_t datalen); + +/** + * Send a pdu according to the session's protocol. This function returns + * the number of bytes that have been transmitted, or a value less than zero + * on error. + * + * @param session Session to send pdu on. + * @param pdu The pdu to send. + * + * @return The number of bytes written on success, or a value + * less than zero on error. + */ +ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu); + +ssize_t +coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, + coap_queue_t *node); + +#if COAP_SERVER_SUPPORT +/** + * Lookup the server session for the packet received on an endpoint, or create + * a new one. + * + * @param endpoint Active endpoint the packet was received on. + * @param packet Received packet. + * @param now The current time in ticks. + * @return The CoAP session or @c NULL if error. + */ +coap_session_t *coap_endpoint_get_session(coap_endpoint_t *endpoint, + const coap_packet_t *packet, coap_tick_t now); +#endif /* COAP_SERVER_SUPPORT */ + +/** + * Get maximum acceptable receive PDU size + * + * @param session The CoAP session. + * @return maximum PDU size, not including header (but including token). + */ +size_t coap_session_max_pdu_rcv_size(const coap_session_t *session); + +/** + * Create a new DTLS session for the @p session. + * Note: the @p session is released if no DTLS server session can be created. + * + * @ingroup dtls_internal + * + * @param session Session to add DTLS session to + * @param now The current time in ticks. + * + * @return CoAP session or @c NULL if error. + */ +coap_session_t *coap_session_new_dtls_session(coap_session_t *session, + coap_tick_t now); + +void coap_session_free(coap_session_t *session); +void coap_session_mfree(coap_session_t *session); + +#define COAP_SESSION_REF(s) ((s)->ref + +/* RFC7252 */ +#define COAP_ACK_TIMEOUT(s) ((s)->ack_timeout) +#define COAP_ACK_RANDOM_FACTOR(s) ((s)->ack_random_factor) +#define COAP_MAX_RETRANSMIT(s) ((s)->max_retransmit) +#define COAP_NSTART(s) ((s)->nstart) +#define COAP_DEFAULT_LEISURE(s) ((s)->default_leisure) +#define COAP_PROBING_RATE(s) ((s)->probing_rate) + + /** + * The DEFAULT_LEISURE definition for the session (s). + * + * RFC 7252, Section 4.8 + * Initial value 5.0 seconds + */ +#define COAP_DEFAULT_LEISURE_TICKS(s) \ + (COAP_DEFAULT_LEISURE(s).integer_part * COAP_TICKS_PER_SECOND + \ + COAP_DEFAULT_LEISURE(s).fractional_part * COAP_TICKS_PER_SECOND / 1000) + /** + * The MAX_TRANSMIT_SPAN definition for the session (s). + * + * RFC 7252, Section 4.8.2 Calculation of MAX_TRAMSMIT_SPAN + * ACK_TIMEOUT * ((2 ** (MAX_RETRANSMIT)) - 1) * ACK_RANDOM_FACTOR + */ +#define COAP_MAX_TRANSMIT_SPAN(s) \ + (((s)->ack_timeout.integer_part * 1000 + (s)->ack_timeout.fractional_part) * \ + ((1 << ((s)->max_retransmit)) -1) * \ + ((s)->ack_random_factor.integer_part * 1000 + \ + (s)->ack_random_factor.fractional_part) \ + / 1000000) + + /** + * The MAX_TRANSMIT_WAIT definition for the session (s). + * + * RFC 7252, Section 4.8.2 Calculation of MAX_TRAMSMIT_WAIT + * ACK_TIMEOUT * ((2 ** (MAX_RETRANSMIT + 1)) - 1) * ACK_RANDOM_FACTOR + */ +#define COAP_MAX_TRANSMIT_WAIT(s) \ + (((s)->ack_timeout.integer_part * 1000 + (s)->ack_timeout.fractional_part) * \ + ((1 << ((s)->max_retransmit + 1)) -1) * \ + ((s)->ack_random_factor.integer_part * 1000 + \ + (s)->ack_random_factor.fractional_part) \ + / 1000000) + +#define COAP_MAX_TRANSMIT_WAIT_TICKS(s) \ + (COAP_MAX_TRANSMIT_WAIT(s) * COAP_TICKS_PER_SECOND) + + /** + * The PROCESSING_DELAY definition for the session (s). + * + * RFC 7252, Section 4.8.2 Calculation of PROCESSING_DELAY + * PROCESSING_DELAY set to ACK_TIMEOUT + */ +#define COAP_PROCESSING_DELAY(s) \ + (((s)->ack_timeout.integer_part * 1000 + (s)->ack_timeout.fractional_part + \ + 500) / 1000) + + /** + * The MAX_RTT definition for the session (s). + * + * RFC 7252, Section 4.8.2 Calculation of MAX_RTT + * (2 * MAX_LATENCY) + PROCESSING_DELAY + */ +#define COAP_MAX_RTT(s) \ + ((2 * COAP_DEFAULT_MAX_LATENCY) + COAP_PROCESSING_DELAY(s)) + + /** + * The EXCHANGE_LIFETIME definition for the session (s). + * + * RFC 7252, Section 4.8.2 Calculation of EXCHANGE_LIFETIME + * MAX_TRANSMIT_SPAN + (2 * MAX_LATENCY) + PROCESSING_DELAY + */ +#define COAP_EXCHANGE_LIFETIME(s) \ + (COAP_MAX_TRANSMIT_SPAN(s) + (2 * COAP_DEFAULT_MAX_LATENCY) + \ + COAP_PROCESSING_DELAY(s)) + + /** + * The NON_LIFETIME definition for the session (s). + * + * RFC 7252, Section 4.8.2 Calculation of NON_LIFETIME + * MAX_TRANSMIT_SPAN + MAX_LATENCY + */ +#define COAP_NON_LIFETIME(s) \ + (COAP_MAX_TRANSMIT_SPAN(s) + COAP_DEFAULT_MAX_LATENCY) + +/** @} */ + +#define SESSIONS_ADD(e, obj) \ + HASH_ADD(hh, (e), addr_hash, sizeof((obj)->addr_hash), (obj)) + +#define SESSIONS_DELETE(e, obj) \ + HASH_DELETE(hh, (e), (obj)) + +#define SESSIONS_ITER(e, el, rtmp) \ + HASH_ITER(hh, (e), el, rtmp) + +#define SESSIONS_ITER_SAFE(e, el, rtmp) \ +for ((el) = (e); (el) && ((rtmp) = (el)->hh.next, 1); (el) = (rtmp)) + +#define SESSIONS_FIND(e, k, res) { \ + HASH_FIND(hh, (e), &(k), sizeof(k), (res)); \ + } + +#endif /* COAP_SESSION_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_subscribe.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_subscribe.h new file mode 100644 index 000000000..9a02e81b8 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_subscribe.h @@ -0,0 +1,69 @@ +/* + * coap_subscribe.h -- subscription handling for CoAP + * see RFC7641 + * + * Copyright (C) 2010-2012,2014-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_subscribe.h + * @brief Defines the application visible subscribe information + */ + +#ifndef COAP_SUBSCRIBE_H_ +#define COAP_SUBSCRIBE_H_ + +/** + * @ingroup application_api + * @defgroup observe Resource Observation + * API for interfacing with the observe handling (RFC7641) + * @{ + */ + +/** + * The value COAP_OBSERVE_ESTABLISH in a GET/FETCH request option + * COAP_OPTION_OBSERVE indicates a new observe relationship for (sender + * address, token) is requested. + */ +#define COAP_OBSERVE_ESTABLISH 0 + +/** + * The value COAP_OBSERVE_CANCEL in a GET/FETCH request option + * COAP_OPTION_OBSERVE indicates that the observe relationship for (sender + * address, token) must be cancelled. + */ +#define COAP_OBSERVE_CANCEL 1 + +/** + * Set whether a @p resource is observable. If the resource is observable + * and the client has set the COAP_OPTION_OBSERVE in a request packet, then + * whenever the state of the resource changes (a call to + * coap_resource_trigger_observe()), an Observer response will get sent. + * + * @param resource The CoAP resource to use. + * @param mode @c 1 if Observable is to be set, @c 0 otherwise. + * + */ +void coap_resource_set_get_observable(coap_resource_t *resource, int mode); + +/** + * Initiate the sending of an Observe packet for all observers of @p resource, + * optionally matching @p query if not NULL + * + * @param resource The CoAP resource to use. + * @param query The Query to match against or NULL + * + * @return @c 1 if the Observe has been triggered, @c 0 otherwise. + */ +int +coap_resource_notify_observers(coap_resource_t *resource, + const coap_string_t *query); + +/** @} */ + +#endif /* COAP_SUBSCRIBE_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_subscribe_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_subscribe_internal.h new file mode 100644 index 000000000..9fe548064 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_subscribe_internal.h @@ -0,0 +1,162 @@ +/* + * coap_subscribe_internal.h -- Structures, Enums & Functions that are not + * exposed to application programming + * + * Copyright (C) 2010-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_subscribe_internal.h + * @brief CoAP subscribe internal information + */ + +#ifndef COAP_SUBSCRIBE_INTERNAL_H_ +#define COAP_SUBSCRIBE_INTERNAL_H_ + +#include "coap_internal.h" + +#if COAP_SERVER_SUPPORT + +/** + * @ingroup internal_api + * @defgroup subscribe_internal Observe Subscription + * Internal API for handling CoAP Observe Subscriptions (RFC7641) + * @{ + */ + +/** + * Number of notifications that may be sent non-confirmable before a confirmable + * message is sent to detect if observers are alive. The maximum allowed value + * here is @c 255. + */ +#ifndef COAP_OBS_MAX_NON +#define COAP_OBS_MAX_NON 5 +#endif /* COAP_OBS_MAX_NON */ +#if COAP_OBS_MAX_NON > 255 +#error COAP_OBS_MAX_NON is too large +#endif /* COAP_OBS_MAX_NON > 255 */ + +/** + * Number of different confirmable notifications that may fail (i.e. those + * that have hit MAX_RETRANSMIT multiple times) before an observer is removed. + * The maximum value for COAP_OBS_MAX_FAIL is @c 255. + */ +#ifndef COAP_OBS_MAX_FAIL +#define COAP_OBS_MAX_FAIL 1 +#endif /* COAP_OBS_MAX_FAIL */ +#if COAP_OBS_MAX_FAIL > 255 +#error COAP_OBS_MAX_FAIL is too large +#endif /* COAP_OBS_MAX_FAIL > 255 */ + +/** Subscriber information */ +struct coap_subscription_t { + struct coap_subscription_t *next; /**< next element in linked list */ + struct coap_session_t *session; /**< subscriber session */ + + uint8_t non_cnt; /**< up to 255 non-confirmable notifies allowed */ + uint8_t fail_cnt; /**< up to 255 confirmable notifies can fail */ + uint8_t dirty; /**< set if the notification temporarily could not be + * sent (in that case, the resource's partially + * dirty flag is set too) */ + coap_cache_key_t *cache_key; /** cache_key to identify requester */ + coap_pdu_t *pdu; /**< PDU to use for additional requests */ +}; + +void coap_subscription_init(coap_subscription_t *); + +/** + * Handles a failed observe notify. + * + * @param context The context holding the resource. + * @param session The session that the observe notify failed on. + * @param token The token used when the observe notify failed. + */ +void +coap_handle_failed_notify(coap_context_t *context, + coap_session_t *session, + const coap_binary_t *token); + +/** + * Checks all known resources to see if they are dirty and then notifies + * subscribed observers. + * + * @param context The context to check for dirty resources. + */ +void coap_check_notify(coap_context_t *context); + +/** + * Adds the specified peer as observer for @p resource. The subscription is + * identified by the given @p token. This function returns the registered + * subscription information if the @p observer has been added, or @c NULL on + * error. + * + * @param resource The observed resource. + * @param session The observer's session + * @param token The token that identifies this subscription. + * @param pdu The requesting pdu. + * + * @return A pointer to the added/updated subscription + * information or @c NULL on error. + */ +coap_subscription_t *coap_add_observer(coap_resource_t *resource, + coap_session_t *session, + const coap_binary_t *token, + const coap_pdu_t *pdu); + +/** + * Returns a subscription object for given @p peer. + * + * @param resource The observed resource. + * @param session The observer's session + * @param token The token that identifies this subscription or @c NULL for + * any token. + * @return A valid subscription if exists or @c NULL otherwise. + */ +coap_subscription_t *coap_find_observer(coap_resource_t *resource, + coap_session_t *session, + const coap_binary_t *token); + +/** + * Flags that data is ready to be sent to observers. + * + * @param context The CoAP context to use. + * @param session The observer's session + * @param token The corresponding token that has been used for the + * subscription. + */ +void coap_touch_observer(coap_context_t *context, + coap_session_t *session, + const coap_binary_t *token); + +/** + * Removes any subscription for @p observer from @p resource and releases the + * allocated storage. The result is @c 1 if an observation relationship with @p + * observer and @p token existed, @c 0 otherwise. + * + * @param resource The observed resource. + * @param session The observer's session. + * @param token The token that identifies this subscription or @c NULL for + * any token. + * @return @c 1 if the observer has been deleted, @c 0 otherwise. + */ +int coap_delete_observer(coap_resource_t *resource, + coap_session_t *session, + const coap_binary_t *token); + +/** + * Removes any subscription for @p session and releases the allocated storage. + * + * @param context The CoAP context to use. + * @param session The observer's session. + */ +void coap_delete_observers(coap_context_t *context, coap_session_t *session); + +/** @} */ + +#endif /* COAP_SERVER_SUPPORT */ +#endif /* COAP_SUBSCRIBE_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_tcp_internal.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_tcp_internal.h new file mode 100644 index 000000000..c0e20ca88 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_tcp_internal.h @@ -0,0 +1,112 @@ +/* + * coap_tcp_internal.h -- TCP functions for libcoap + * + * Copyright (C) 2019--2020 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_tcp_internal.h + * @brief CoAP TCP internal information + */ + +#ifndef COAP_TCP_INTERNAL_H_ +#define COAP_TCP_INTERNAL_H_ + +#include "coap_internal.h" +#include "coap_io.h" + +/** + * @ingroup internal_api + * @defgroup tcp TCP Support + * Internal API for handling CoAP TCP (RFC8283) + * @{ + */ + +#if !COAP_DISABLE_TCP + +/** + * Create a new TCP socket and initiate the connection + * + * Internal function. + * + * @param sock Where socket information is to be filled in + * @param local_if The local address to use or NULL + * @param server The address to connect to + * @param default_port The port to use if not set in @p server + * @param local_addr Filled in after connection initiation with + * the local address + * @param remote_addr Filled in after connection initiation with + * the remote address + * + * @return @c 1 if succesful, @c 0 if failure of some sort +*/ +int +coap_socket_connect_tcp1(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr); + +/** + * Complete the TCP Connection + * + * Internal function. + * + * @param sock The socket information to use + * @param local_addr Filled in with the final local address + * @param remote_addr Filled in with the final remote address + * + * @return @c 1 if succesful, @c 0 if failure of some sort +*/ +int +coap_socket_connect_tcp2(coap_socket_t *sock, + coap_address_t *local_addr, + coap_address_t *remote_addr); + +/** + * Create a new TCP socket and then listen for new incoming TCP sessions + * + * Internal function. + * + * @param sock Where socket information is to be filled in + * @param listen_addr The address to be listening for new incoming sessions + * @param bound_addr Filled in with the address that the TCP layer + * is listening on for new incoming TCP sessions + * + * @return @c 1 if succesful, @c 0 if failure of some sort +*/ +int +coap_socket_bind_tcp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr); + +/** + * Accept a new incoming TCP session + * + * Internal function. + * + * @param server The socket information to use to accept the TCP connection + * @param new_client Filled in socket information with the new incoming + * session information + * @param local_addr Filled in with the local address + * @param remote_addr Filled in with the remote address + * + * @return @c 1 if succesful, @c 0 if failure of some sort +*/ +int +coap_socket_accept_tcp(coap_socket_t *server, + coap_socket_t *new_client, + coap_address_t *local_addr, + coap_address_t *remote_addr); + +#endif /* !COAP_DISABLE_TCP */ + +/** @} */ + +#endif /* COAP_TCP_INTERNAL_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/coap_time.h b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_time.h new file mode 100644 index 000000000..64880455c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/coap_time.h @@ -0,0 +1,204 @@ +/* + * coap_time.h -- Clock Handling + * + * Copyright (C) 2010-2019 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_time.h + * @brief Clock Handling + */ + +#ifndef COAP_TIME_H_ +#define COAP_TIME_H_ + +/** + * @ingroup application_api + * @defgroup clock Clock Handling + * API for internal clock assess + * @{ + */ + +#if defined(WITH_LWIP) + +#include +#include + +/* lwIP provides ms in sys_now */ +#define COAP_TICKS_PER_SECOND 1000 + +typedef uint32_t coap_tick_t; +typedef uint32_t coap_time_t; +typedef int32_t coap_tick_diff_t; + +COAP_STATIC_INLINE void coap_ticks_impl(coap_tick_t *t) { + *t = sys_now(); +} + +COAP_STATIC_INLINE void coap_clock_init_impl(void) { +} + +#define coap_clock_init coap_clock_init_impl +#define coap_ticks coap_ticks_impl + +COAP_STATIC_INLINE coap_time_t coap_ticks_to_rt(coap_tick_t t) { + return t / COAP_TICKS_PER_SECOND; +} + +COAP_STATIC_INLINE uint64_t coap_ticks_to_rt_us(coap_tick_t t) { + return (uint64_t)t * 1000000 / COAP_TICKS_PER_SECOND; +} + +#elif defined(WITH_CONTIKI) + +#include "clock.h" + +typedef clock_time_t coap_tick_t; +typedef clock_time_t coap_time_t; + +/** + * This data type is used to represent the difference between two clock_tick_t + * values. This data type must have the same size in memory as coap_tick_t to + * allow wrapping. + */ +typedef int coap_tick_diff_t; + +#define COAP_TICKS_PER_SECOND CLOCK_SECOND + +COAP_STATIC_INLINE void coap_clock_init(void) { + clock_init(); +} + +COAP_STATIC_INLINE void coap_ticks(coap_tick_t *t) { + *t = clock_time(); +} + +COAP_STATIC_INLINE coap_time_t coap_ticks_to_rt(coap_tick_t t) { + return t / COAP_TICKS_PER_SECOND; +} + +COAP_STATIC_INLINE uint64_t coap_ticks_to_rt_us(coap_tick_t t) { + return (uint64_t)t * 1000000 / COAP_TICKS_PER_SECOND; +} + +#elif defined(RIOT_VERSION) +#include + +#ifdef XTIMER_HZ +#define COAP_TICKS_PER_SECOND (XTIMER_HZ) +#else /* XTIMER_HZ */ +#define COAP_TICKS_PER_SECOND (XTIMER_HZ_BASE) +#endif /* XTIMER_HZ */ + +typedef uint64_t coap_tick_t; +typedef int64_t coap_tick_diff_t; +typedef uint32_t coap_time_t; + +static inline void coap_clock_init(void) {} + +static inline void coap_ticks(coap_tick_t *t) { + *t = xtimer_now_usec64(); +} + +static inline coap_time_t coap_ticks_to_rt(coap_tick_t t) { + return t / 1000000UL; +} + +static inline uint64_t coap_ticks_to_rt_us(coap_tick_t t) { + return t; +} + +static inline coap_tick_t coap_ticks_from_rt_us(uint64_t t) { + return t / 1000000UL; +} +#else /* !WITH_LWIP && !WITH_CONTIKI && !RIOT_VERSION */ + +#include + +/** + * This data type represents internal timer ticks with COAP_TICKS_PER_SECOND + * resolution. + */ +typedef uint64_t coap_tick_t; + +/** + * CoAP time in seconds since epoch. + */ +typedef time_t coap_time_t; + +/** + * This data type is used to represent the difference between two clock_tick_t + * values. This data type must have the same size in memory as coap_tick_t to + * allow wrapping. + */ +typedef int64_t coap_tick_diff_t; + +/** Use ms resolution on POSIX systems */ +#define COAP_TICKS_PER_SECOND ((coap_tick_t)(1000U)) + +/** + * Initializes the internal clock. + */ +void coap_clock_init(void); + +/** + * Sets @p t to the internal time with COAP_TICKS_PER_SECOND resolution. + */ +void coap_ticks(coap_tick_t *t); + +/** + * Helper function that converts coap ticks to wallclock time. On POSIX, this + * function returns the number of seconds since the epoch. On other systems, it + * may be the calculated number of seconds since last reboot or so. + * + * @param t Internal system ticks. + * + * @return The number of seconds that has passed since a specific reference + * point (seconds since epoch on POSIX). + */ +coap_time_t coap_ticks_to_rt(coap_tick_t t); + +/** +* Helper function that converts coap ticks to POSIX wallclock time in us. +* +* @param t Internal system ticks. +* +* @return The number of seconds that has passed since a specific reference +* point (seconds since epoch on POSIX). +*/ +uint64_t coap_ticks_to_rt_us(coap_tick_t t); + +/** +* Helper function that converts POSIX wallclock time in us to coap ticks. +* +* @param t POSIX time is us +* +* @return coap ticks +*/ +coap_tick_t coap_ticks_from_rt_us(uint64_t t); +#endif + +/** + * Returns @c 1 if and only if @p a is less than @p b where less is defined on a + * signed data type. + */ +COAP_STATIC_INLINE int coap_time_lt(coap_tick_t a, coap_tick_t b) { + return ((coap_tick_diff_t)(a - b)) < 0; +} + +/** + * Returns @c 1 if and only if @p a is less than or equal @p b where less is + * defined on a signed data type. + */ +COAP_STATIC_INLINE int coap_time_le(coap_tick_t a, coap_tick_t b) { + return a == b || coap_time_lt(a,b); +} + +/** @} */ + +#endif /* COAP_TIME_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/encode.h b/examples/espidf-coap-server/components/libcoap/include/coap3/encode.h new file mode 100644 index 000000000..cc1623d2d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/encode.h @@ -0,0 +1,128 @@ +/* + * encode.h -- encoding and decoding of CoAP data types + * + * Copyright (C) 2010-2012 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file encode.h + * @brief Encoding and decoding of CoAP data types + */ + +#ifndef COAP_ENCODE_H_ +#define COAP_ENCODE_H_ + +#if (BSD >= 199103) || defined(WITH_CONTIKI) || defined(_WIN32) +# include +#else +# include +#endif + +#include + +#ifndef HAVE_FLS +/* include this only if fls() is not available */ +extern int coap_fls(unsigned int i); +#else +#define coap_fls(i) fls(i) +#endif + +#ifndef HAVE_FLSLL + /* include this only if flsll() is not available */ +extern int coap_flsll(long long i); +#else +#define coap_flsll(i) flsll(i) +#endif + +/** + * @ingroup application_api + * @defgroup encode Encode / Decode API + * API for endoding/decoding CoAP options. + * @{ + */ + +/** + * Decodes multiple-length byte sequences. @p buf points to an input byte + * sequence of length @p length. Returns the up to 4 byte decoded value. + * + * @param buf The input byte sequence to decode from + * @param length The length of the input byte sequence + * + * @return The decoded value + */ +unsigned int coap_decode_var_bytes(const uint8_t *buf, size_t length); + +/** + * Decodes multiple-length byte sequences. @p buf points to an input byte + * sequence of length @p length. Returns the up to 8 byte decoded value. + * + * @param buf The input byte sequence to decode from + * @param length The length of the input byte sequence + * + * @return The decoded value + */ +uint64_t coap_decode_var_bytes8(const uint8_t *buf, size_t length); + +/** + * Encodes multiple-length byte sequences. @p buf points to an output buffer of + * sufficient length to store the encoded bytes. @p value is the 4 byte value + * to encode. + * Returns the number of bytes used to encode @p value or 0 on error. + * + * @param buf The output buffer to encode into + * @param length The output buffer size to encode into (must be sufficient) + * @param value The value to encode into the buffer + * + * @return The number of bytes used to encode @p value (which can be 0 + * when encoding value of 0) or @c 0 on error. + */ +unsigned int coap_encode_var_safe(uint8_t *buf, + size_t length, + unsigned int value); + +/** + * Encodes multiple-length byte sequences. @p buf points to an output buffer of + * sufficient length to store the encoded bytes. @p value is the 8 byte value + * to encode. + * Returns the number of bytes used to encode @p value or 0 on error. + * + * @param buf The output buffer to encode into + * @param length The output buffer size to encode into (must be sufficient) + * @param value The value to encode into the buffer + * + * @return The number of bytes used to encode @p value (which can be 0 + * when encoding value of 0) or @c 0 on error. + */ +unsigned int coap_encode_var_safe8(uint8_t *buf, + size_t length, + uint64_t value); + +/** @} */ + +/** + * @deprecated Use coap_encode_var_safe() instead. + * Provided for backward compatibility. As @p value has a + * maximum value of 0xffffffff, and buf is usually defined as an array, it + * is unsafe to continue to use this variant if buf[] is less than buf[4]. + * + * For example + * char buf[1],oops; + * .. + * coap_encode_var_bytes(buf, 0xfff); + * would cause oops to get overwritten. This error can only be found by code + * inspection. + * coap_encode_var_safe(buf, sizeof(buf), 0xfff); + * would catch this error at run-time and should be used instead. + */ +COAP_STATIC_INLINE COAP_DEPRECATED int +coap_encode_var_bytes(uint8_t *buf, unsigned int value +) { + return (int)coap_encode_var_safe(buf, sizeof(value), value); +} + +#endif /* COAP_ENCODE_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/libcoap.h b/examples/espidf-coap-server/components/libcoap/include/coap3/libcoap.h new file mode 100644 index 000000000..db5854255 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/libcoap.h @@ -0,0 +1,68 @@ +/* + * libcoap.h -- platform specific header file for CoAP stack + * + * Copyright (C) 2015 Carsten Schoenert + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file libcoap.h + * @brief Platform specific header file for CoAP stack + */ + +#ifndef COAP_LIBCOAP_H_ +#define COAP_LIBCOAP_H_ + +/* The non posix embedded platforms like Contiki, TinyOS, RIOT, ... doesn't have + * a POSIX compatible header structure so we have to slightly do some platform + * related things. Currently there is only Contiki available so we check for a + * CONTIKI environment and do *not* include the POSIX related network stuff. If + * there are other platforms in future there need to be analogous environments. + * + * The CONTIKI variable is within the Contiki build environment! */ + +#if defined(_WIN32) +#pragma comment(lib,"Ws2_32.lib") +#include +typedef SSIZE_T ssize_t; +typedef USHORT in_port_t; +#elif !defined (CONTIKI) +#include +#include +#endif /* CONTIKI */ + +#ifndef COAP_STATIC_INLINE +# if defined(__cplusplus) +# define COAP_STATIC_INLINE inline +# else +# if defined(_MSC_VER) +# define COAP_STATIC_INLINE static __inline +# else +# define COAP_STATIC_INLINE static inline +# endif +# endif +#endif +#ifndef COAP_DEPRECATED +# if defined(_MSC_VER) +# define COAP_DEPRECATED __declspec(deprecated) +# else +# define COAP_DEPRECATED __attribute__ ((deprecated)) +# endif +#endif +#ifndef COAP_UNUSED +# ifdef __GNUC__ +# define COAP_UNUSED __attribute__((unused)) +# else /* __GNUC__ */ +# define COAP_UNUSED +# endif /* __GNUC__ */ +#endif /* COAP_UNUSED */ + +void coap_startup(void); + +void coap_cleanup(void); + +#endif /* COAP_LIBCOAP_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/lwippools.h b/examples/espidf-coap-server/components/libcoap/include/coap3/lwippools.h new file mode 100644 index 000000000..4b1dd6fec --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/lwippools.h @@ -0,0 +1,117 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/* Memory pool definitions for the libcoap when used with lwIP (which has its + * own mechanism for quickly allocating chunks of data with known sizes). Has + * to be findable by lwIP (ie. an #include must either directly + * include this or include something more generic which includes this), and + * MEMP_USE_CUSTOM_POOLS has to be set in lwipopts.h. */ + +#include "coap_internal.h" +#include "net.h" +#include "resource.h" +#include "coap_subscribe.h" + +#ifndef MEMP_NUM_COAPCONTEXT +#define MEMP_NUM_COAPCONTEXT 1 +#endif + +#ifndef MEMP_NUM_COAPENDPOINT +#define MEMP_NUM_COAPENDPOINT 1 +#endif + +/* 1 is sufficient as this is very short-lived */ +#ifndef MEMP_NUM_COAPPACKET +#define MEMP_NUM_COAPPACKET 1 +#endif + +#ifndef MEMP_NUM_COAPNODE +#define MEMP_NUM_COAPNODE 4 +#endif + +#ifndef MEMP_NUM_COAPPDU +#define MEMP_NUM_COAPPDU MEMP_NUM_COAPNODE +#endif + +#ifndef MEMP_NUM_COAPSESSION +#define MEMP_NUM_COAPSESSION 2 +#endif + +#ifndef MEMP_NUM_COAP_SUBSCRIPTION +#define MEMP_NUM_COAP_SUBSCRIPTION 4 +#endif + +#ifndef MEMP_NUM_COAPRESOURCE +#define MEMP_NUM_COAPRESOURCE 10 +#endif + +#ifndef MEMP_NUM_COAPRESOURCEATTR +#define MEMP_NUM_COAPRESOURCEATTR 20 +#endif + +#ifndef MEMP_NUM_COAPOPTLIST +#define MEMP_NUM_COAPOPTLIST 1 +#endif + +#ifndef MEMP_LEN_COAPOPTLIST +#define MEMP_LEN_COAPOPTLIST 12 +#endif + +#ifndef MEMP_NUM_COAPSTRING +#define MEMP_NUM_COAPSTRING 10 +#endif + +#ifndef MEMP_LEN_COAPSTRING +#define MEMP_LEN_COAPSTRING 40 +#endif + +#ifndef MEMP_NUM_COAPCACHE_KEYS +#define MEMP_NUM_COAPCACHE_KEYS (2U) +#endif /* MEMP_NUM_COAPCACHE_KEYS */ + +#ifndef MEMP_NUM_COAPCACHE_ENTRIES +#define MEMP_NUM_COAPCACHE_ENTRIES (2U) +#endif /* MEMP_NUM_COAPCACHE_ENTRIES */ + +#ifndef MEMP_NUM_COAPPDUBUF +#define MEMP_NUM_COAPPDUBUF 2 +#endif + +#ifndef MEMP_LEN_COAPPDUBUF +#define MEMP_LEN_COAPPDUBUF 32 +#endif + +#ifndef MEMP_NUM_COAPLGXMIT +#define MEMP_NUM_COAPLGXMIT 2 +#endif + +#ifndef MEMP_NUM_COAPLGCRCV +#define MEMP_NUM_COAPLGCRCV 2 +#endif + +#ifndef MEMP_NUM_COAPLGSRCV +#define MEMP_NUM_COAPLGSRCV 2 +#endif + +LWIP_MEMPOOL(COAP_CONTEXT, MEMP_NUM_COAPCONTEXT, sizeof(coap_context_t), "COAP_CONTEXT") +LWIP_MEMPOOL(COAP_ENDPOINT, MEMP_NUM_COAPENDPOINT, sizeof(coap_endpoint_t), "COAP_ENDPOINT") +LWIP_MEMPOOL(COAP_PACKET, MEMP_NUM_COAPPACKET, sizeof(coap_packet_t), "COAP_PACKET") +LWIP_MEMPOOL(COAP_NODE, MEMP_NUM_COAPNODE, sizeof(coap_queue_t), "COAP_NODE") +LWIP_MEMPOOL(COAP_PDU, MEMP_NUM_COAPPDU, sizeof(coap_pdu_t), "COAP_PDU") +LWIP_MEMPOOL(COAP_SESSION, MEMP_NUM_COAPSESSION, sizeof(coap_session_t), "COAP_SESSION") +LWIP_MEMPOOL(COAP_subscription, MEMP_NUM_COAP_SUBSCRIPTION, sizeof(coap_subscription_t), "COAP_subscription") +LWIP_MEMPOOL(COAP_RESOURCE, MEMP_NUM_COAPRESOURCE, sizeof(coap_resource_t), "COAP_RESOURCE") +LWIP_MEMPOOL(COAP_RESOURCEATTR, MEMP_NUM_COAPRESOURCEATTR, sizeof(coap_attr_t), "COAP_RESOURCEATTR") +LWIP_MEMPOOL(COAP_OPTLIST, MEMP_NUM_COAPOPTLIST, sizeof(coap_optlist_t)+MEMP_LEN_COAPOPTLIST, "COAP_OPTLIST") +LWIP_MEMPOOL(COAP_STRING, MEMP_NUM_COAPSTRING, sizeof(coap_string_t)+MEMP_LEN_COAPSTRING, "COAP_STRING") +LWIP_MEMPOOL(COAP_CACHE_KEY, MEMP_NUM_COAPCACHE_KEYS, sizeof(coap_cache_key_t), "COAP_CACHE_KEY") +LWIP_MEMPOOL(COAP_CACHE_ENTRY, MEMP_NUM_COAPCACHE_ENTRIES, sizeof(coap_cache_entry_t), "COAP_CACHE_ENTRY") +LWIP_MEMPOOL(COAP_PDU_BUF, MEMP_NUM_COAPPDUBUF, MEMP_LEN_COAPPDUBUF, "COAP_PDU_BUF") +LWIP_MEMPOOL(COAP_LG_XMIT, MEMP_NUM_COAPLGXMIT, sizeof(coap_lg_xmit_t), "COAP_LG_XMIT") +LWIP_MEMPOOL(COAP_LG_CRCV, MEMP_NUM_COAPLGCRCV, sizeof(coap_lg_crcv_t), "COAP_LG_CRCV") +LWIP_MEMPOOL(COAP_LG_SRCV, MEMP_NUM_COAPLGSRCV, sizeof(coap_lg_srcv_t), "COAP_LG_SRCV") + diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/mem.h b/examples/espidf-coap-server/components/libcoap/include/coap3/mem.h new file mode 100644 index 000000000..cf47d6148 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/mem.h @@ -0,0 +1,144 @@ +/* + * mem.h -- CoAP memory handling + * + * Copyright (C) 2010-2011,2014-2015 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file mem.h + * @brief CoAP memory handling + */ + +#ifndef COAP_MEM_H_ +#define COAP_MEM_H_ + +#include + +#ifndef WITH_LWIP +/** + * Initializes libcoap's memory management. + * This function must be called once before coap_malloc() can be used on + * constrained devices. + */ +void coap_memory_init(void); +#endif /* WITH_LWIP */ + +/** + * Type specifiers for coap_malloc_type(). Memory objects can be typed to + * facilitate arrays of type objects to be used instead of dynamic memory + * management on constrained devices. + */ +typedef enum { + COAP_STRING, + COAP_ATTRIBUTE_NAME, + COAP_ATTRIBUTE_VALUE, + COAP_PACKET, + COAP_NODE, + COAP_CONTEXT, + COAP_ENDPOINT, + COAP_PDU, + COAP_PDU_BUF, + COAP_RESOURCE, + COAP_RESOURCEATTR, +#ifdef HAVE_LIBTINYDTLS + COAP_DTLS_SESSION, +#endif + COAP_SESSION, + COAP_OPTLIST, + COAP_CACHE_KEY, + COAP_CACHE_ENTRY, + COAP_LG_XMIT, + COAP_LG_CRCV, + COAP_LG_SRCV, +} coap_memory_tag_t; + +#ifndef WITH_LWIP + +/** + * Allocates a chunk of @p size bytes and returns a pointer to the newly + * allocated memory. The @p type is used to select the appropriate storage + * container on constrained devices. The storage allocated by coap_malloc_type() + * must be released with coap_free_type(). + * + * @param type The type of object to be stored. + * @param size The number of bytes requested. + * @return A pointer to the allocated storage or @c NULL on error. + */ +void *coap_malloc_type(coap_memory_tag_t type, size_t size); + +/** + * Reallocates a chunk @p p of bytes created by coap_malloc_type() or + * coap_realloc_type() and returns a pointer to the newly allocated memory of + * @p size. + * Only COAP_STRING type is supported. + * + * Note: If there is an error, @p p will separately need to be released by + * coap_free_type(). + * + * @param type The type of object to be stored. + * @param p A pointer to memory that was allocated by coap_malloc_type(). + * @param size The number of bytes requested. + * @return A pointer to the allocated storage or @c NULL on error. + */ +void *coap_realloc_type(coap_memory_tag_t type, void *p, size_t size); + +/** + * Releases the memory that was allocated by coap_malloc_type(). The type tag @p + * type must be the same that was used for allocating the object pointed to by + * @p . + * + * @param type The type of the object to release. + * @param p A pointer to memory that was allocated by coap_malloc_type(). + */ +void coap_free_type(coap_memory_tag_t type, void *p); + +/** + * Wrapper function to coap_malloc_type() for backwards compatibility. + */ +COAP_STATIC_INLINE void *coap_malloc(size_t size) { + return coap_malloc_type(COAP_STRING, size); +} + +/** + * Wrapper function to coap_free_type() for backwards compatibility. + */ +COAP_STATIC_INLINE void coap_free(void *object) { + coap_free_type(COAP_STRING, object); +} + +#endif /* not WITH_LWIP */ + +#ifdef WITH_LWIP + +#include + +/* no initialization needed with lwip (or, more precisely: lwip must be + * completely initialized anyway by the time coap gets active) */ +COAP_STATIC_INLINE void coap_memory_init(void) {} + +/* It would be nice to check that size equals the size given at the memp + * declaration, but i currently don't see a standard way to check that without + * sourcing the custom memp pools and becoming dependent of its syntax + */ +#define coap_malloc_type(type, size) memp_malloc(MEMP_ ## type) +#define coap_free_type(type, p) memp_free(MEMP_ ## type, p) + +/* Those are just here to make uri.c happy where string allocation has not been + * made conditional. + */ +COAP_STATIC_INLINE void *coap_malloc(size_t size) { + LWIP_ASSERT("coap_malloc must not be used in lwIP", 0); +} + +COAP_STATIC_INLINE void coap_free(void *pointer) { + LWIP_ASSERT("coap_free must not be used in lwIP", 0); +} + +#endif /* WITH_LWIP */ + +#endif /* COAP_MEM_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/net.h b/examples/espidf-coap-server/components/libcoap/include/coap3/net.h new file mode 100644 index 000000000..89a0cfe52 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/net.h @@ -0,0 +1,825 @@ +/* + * net.h -- CoAP context interface + * + * Copyright (C) 2010-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file net.h + * @brief CoAP context interface + */ + +#ifndef COAP_NET_H_ +#define COAP_NET_H_ + +#include +#include +#ifndef _WIN32 +#include +#include +#endif +#include + +#ifdef WITH_LWIP +#include +#endif + +#include "coap_io.h" +#include "coap_dtls.h" +#include "coap_event.h" +#include "pdu.h" +#include "coap_session.h" + +/** + * @ingroup application_api + * @defgroup context Context Handling + * API for handling PDUs using CoAP Contexts + * @{ + */ + +typedef enum coap_response_t { + COAP_RESPONSE_FAIL, /**< Response not liked - send CoAP RST packet */ + COAP_RESPONSE_OK /**< Response is fine */ +} coap_response_t; + +/** + * Response handler that is used as callback in coap_context_t. + * + * @param session CoAP session. + * @param sent The PDU that was transmitted. + * @param received The PDU that was received. + * @param mid CoAP transaction ID. + + * @return @c COAP_RESPONSE_OK if successful, else @c COAP_RESPONSE_FAIL which + * triggers sending a RST packet. + */ +typedef coap_response_t (*coap_response_handler_t)(coap_session_t *session, + const coap_pdu_t *sent, + const coap_pdu_t *received, + const coap_mid_t mid); + +/** + * Negative Acknowedge handler that is used as callback in coap_context_t. + * + * @param session CoAP session. + * @param sent The PDU that was transmitted. + * @param reason The reason for the NACK. + * @param mid CoAP message ID. + */ +typedef void (*coap_nack_handler_t)(coap_session_t *session, + const coap_pdu_t *sent, + const coap_nack_reason_t reason, + const coap_mid_t mid); + +/** + * Received Ping handler that is used as callback in coap_context_t. + * + * @param session CoAP session. + * @param received The PDU that was received. + * @param mid CoAP message ID. + */ +typedef void (*coap_ping_handler_t)(coap_session_t *session, + const coap_pdu_t *received, + const coap_mid_t mid); + +/** + * Received Pong handler that is used as callback in coap_context_t. + * + * @param session CoAP session. + * @param received The PDU that was received. + * @param mid CoAP message ID. + */ +typedef void (*coap_pong_handler_t)(coap_session_t *session, + const coap_pdu_t *received, + const coap_mid_t mid); + +/** + * Registers a new message handler that is called whenever a response is + * received. + * + * @param context The context to register the handler for. + * @param handler The response handler to register. + */ +void +coap_register_response_handler(coap_context_t *context, + coap_response_handler_t handler); + +/** + * Registers a new message handler that is called whenever a confirmable + * message (request or response) is dropped after all retries have been + * exhausted, or a rst message was received, or a network or TLS level + * event was received that indicates delivering the message is not possible. + * + * @param context The context to register the handler for. + * @param handler The nack handler to register. + */ +void +coap_register_nack_handler(coap_context_t *context, + coap_nack_handler_t handler); + +/** + * Registers a new message handler that is called whenever a CoAP Ping + * message is received. + * + * @param context The context to register the handler for. + * @param handler The ping handler to register. + */ +void +coap_register_ping_handler(coap_context_t *context, + coap_ping_handler_t handler); + +/** + * Registers a new message handler that is called whenever a CoAP Pong + * message is received. + * + * @param context The context to register the handler for. + * @param handler The pong handler to register. + */ +void +coap_register_pong_handler(coap_context_t *context, + coap_pong_handler_t handler); + +/** + * Registers the option type @p type with the given context object @p ctx. + * + * @param ctx The context to use. + * @param type The option type to register. + */ +void +coap_register_option(coap_context_t *ctx, uint16_t type); + +/** + * Creates a new coap_context_t object that will hold the CoAP stack status. + */ +coap_context_t *coap_new_context(const coap_address_t *listen_addr); + +/** + * Set the context's default PSK hint and/or key for a server. + * + * @param context The current coap_context_t object. + * @param hint The default PSK server hint sent to a client. If NULL, PSK + * authentication is disabled. Empty string is a valid hint. + * @param key The default PSK key. If NULL, PSK authentication will fail. + * @param key_len The default PSK key's length. If @p 0, PSK authentication will + * fail. + * + * @return @c 1 if successful, else @c 0. + */ +int coap_context_set_psk( coap_context_t *context, const char *hint, + const uint8_t *key, size_t key_len ); + +/** + * Set the context's default PSK hint and/or key for a server. + * + * @param context The current coap_context_t object. + * @param setup_data If NULL, PSK authentication will fail. PSK + * information required. + * + * @return @c 1 if successful, else @c 0. + */ +int coap_context_set_psk2(coap_context_t *context, + coap_dtls_spsk_t *setup_data); + +/** + * Set the context's default PKI information for a server. + * + * @param context The current coap_context_t object. + * @param setup_data If NULL, PKI authentication will fail. Certificate + * information required. + * + * @return @c 1 if successful, else @c 0. + */ +int +coap_context_set_pki(coap_context_t *context, + const coap_dtls_pki_t *setup_data); + +/** + * Set the context's default Root CA information for a client or server. + * + * @param context The current coap_context_t object. + * @param ca_file If not NULL, is the full path name of a PEM encoded + * file containing all the Root CAs to be used. + * @param ca_dir If not NULL, points to a directory containing PEM + * encoded files containing all the Root CAs to be used. + * + * @return @c 1 if successful, else @c 0. + */ +int +coap_context_set_pki_root_cas(coap_context_t *context, + const char *ca_file, + const char *ca_dir); + +/** + * Set the context keepalive timer for sessions. + * A keepalive message will be sent after if a session has been inactive, + * i.e. no packet sent or received, for the given number of seconds. + * For unreliable protocols, a CoAP Empty message will be sent. If a + * CoAP RST is not received, the CoAP Empty messages will get resent based + * on the Confirmable retry parameters until there is a failure timeout, + * at which point the session will be considered as disconnected. + * For reliable protocols, a CoAP PING message will be sent. If a CoAP PONG + * has not been received before the next PING is due to be sent, the session + * will be considered as disconnected. + * + * @param context The coap_context_t object. + * @param seconds Number of seconds for the inactivity timer, or zero + * to disable CoAP-level keepalive messages. + */ +void coap_context_set_keepalive(coap_context_t *context, unsigned int seconds); + +/** + * Get the libcoap internal file descriptor for using in an application's + * select() or returned as an event in an application's epoll_wait() call. + * + * @param context The coap_context_t object. + * + * @return The libcoap file descriptor or @c -1 if epoll is not available. + */ +int coap_context_get_coap_fd(const coap_context_t *context); + +/** + * Set the maximum idle sessions count. The number of server sessions that + * are currently not in use. If this number is exceeded, the least recently + * used server session is completely removed. + * 0 (the default) means that the number is not monitored. + * + * @param context The coap_context_t object. + * @param max_idle_sessions The maximum idle session count. + */ +void +coap_context_set_max_idle_sessions(coap_context_t *context, + unsigned int max_idle_sessions); + +/** + * Get the maximum idle sessions count. + * + * @param context The coap_context_t object. + * + * @return The count of max idle sessions. + */ +unsigned int +coap_context_get_max_idle_sessions(const coap_context_t *context); + +/** + * Set the session timeout value. The number of seconds of inactivity after + * which an unused server session will be closed. + * 0 means use default (300 secs). + * + * @param context The coap_context_t object. + * @param session_timeout The session timeout value. + */ +void +coap_context_set_session_timeout(coap_context_t *context, + unsigned int session_timeout); + +/** + * Get the session timeout value + * + * @param context The coap_context_t object. + * + * @return The session timeout value. + */ +unsigned int +coap_context_get_session_timeout(const coap_context_t *context); + +/** + * Set the CSM timeout value. The number of seconds to wait for a (TCP) CSM + * negotiation response from the peer. + * 0 (the default) means use wait forever. + * + * @param context The coap_context_t object. + * @param csm_tmeout The CSM timeout value. + */ +void +coap_context_set_csm_timeout(coap_context_t *context, + unsigned int csm_tmeout); + +/** + * Get the CSM timeout value + * + * @param context The coap_context_t object. + * + * @return The CSM timeout value. + */ +unsigned int +coap_context_get_csm_timeout(const coap_context_t *context); + +/** + * Set the CSM max session size value. The largest PDU that can be received. + * + * @param context The coap_context_t object. + * @param csm_max_message_size The CSM max message size value. + */ +void +coap_context_set_csm_max_message_size(coap_context_t *context, + uint32_t csm_max_message_size); + +/** + * Get the CSM max session size value + * + * @param context The coap_context_t object. + * + * @return The CSM max session size value. + */ +uint32_t +coap_context_get_csm_max_message_size(const coap_context_t *context); + +/** + * Set the maximum number of sessions in (D)TLS handshake value. If this number + * is exceeded, the least recently used server session in handshake is + * completely removed. + * 0 (the default) means that the number is not monitored. + * + * @param context The coap_context_t object. + * @param max_handshake_sessions The maximum number of sessions in handshake. + */ +void +coap_context_set_max_handshake_sessions(coap_context_t *context, + unsigned int max_handshake_sessions); + +/** + * Get the session timeout value + * + * @param context The coap_context_t object. + * + * @return The maximim number of sessions in (D)TLS handshake value. + */ +unsigned int +coap_context_get_max_handshake_sessions(const coap_context_t *context); + +/** + * Returns a new message id and updates @p session->tx_mid accordingly. The + * message id is returned in network byte order to make it easier to read in + * tracing tools. + * + * @param session The current coap_session_t object. + * + * @return Incremented message id in network byte order. + */ +uint16_t coap_new_message_id(coap_session_t *session); + +/** + * CoAP stack context must be released with coap_free_context(). This function + * clears all entries from the receive queue and send queue and deletes the + * resources that have been registered with @p context, and frees the attached + * endpoints. + * + * @param context The current coap_context_t object to free off. + */ +void coap_free_context(coap_context_t *context); + +/** + * Stores @p data with the given CoAP context. This function + * overwrites any value that has previously been stored with @p + * context. + * + * @param context The CoAP context. + * @param data The data to store with wih the context. Note that this data + * must be valid during the lifetime of @p context. + */ +void coap_set_app_data(coap_context_t *context, void *data); + +/** + * Returns any application-specific data that has been stored with @p + * context using the function coap_set_app_data(). This function will + * return @c NULL if no data has been stored. + * + * @param context The CoAP context. + * + * @return The data previously stored or @c NULL if not data stored. + */ +void *coap_get_app_data(const coap_context_t *context); + +/** + * Creates a new ACK PDU with specified error @p code. The options specified by + * the filter expression @p opts will be copied from the original request + * contained in @p request. Unless @c SHORT_ERROR_RESPONSE was defined at build + * time, the textual reason phrase for @p code will be added as payload, with + * Content-Type @c 0. + * This function returns a pointer to the new response message, or @c NULL on + * error. The storage allocated for the new message must be released with + * coap_free(). + * + * @param request Specification of the received (confirmable) request. + * @param code The error code to set. + * @param opts An option filter that specifies which options to copy from + * the original request in @p node. + * + * @return A pointer to the new message or @c NULL on error. + */ +coap_pdu_t *coap_new_error_response(const coap_pdu_t *request, + coap_pdu_code_t code, + coap_opt_filter_t *opts); + +/** + * Sends an error response with code @p code for request @p request to @p dst. + * @p opts will be passed to coap_new_error_response() to copy marked options + * from the request. This function returns the message id if the message was + * sent, or @c COAP_INVALID_MID otherwise. + * + * @param session The CoAP session. + * @param request The original request to respond to. + * @param code The response code. + * @param opts A filter that specifies the options to copy from the + * @p request. + * + * @return The message id if the message was sent, or @c + * COAP_INVALID_MID otherwise. + */ +coap_mid_t coap_send_error(coap_session_t *session, + const coap_pdu_t *request, + coap_pdu_code_t code, + coap_opt_filter_t *opts); + +/** + * Helper function to create and send a message with @p type (usually ACK or + * RST). This function returns @c COAP_INVALID_MID when the message was not + * sent, a valid transaction id otherwise. + * + * @param session The CoAP session. + * @param request The request that should be responded to. + * @param type Which type to set. + * @return message id on success or @c COAP_INVALID_MID + * otherwise. + */ +coap_mid_t +coap_send_message_type(coap_session_t *session, const coap_pdu_t *request, + coap_pdu_type_t type); + +/** + * Sends an ACK message with code @c 0 for the specified @p request to @p dst. + * This function returns the corresponding message id if the message was + * sent or @c COAP_INVALID_MID on error. + * + * @param session The CoAP session. + * @param request The request to be acknowledged. + * + * @return The message id if ACK was sent or @c + * COAP_INVALID_MID on error. + */ +coap_mid_t coap_send_ack(coap_session_t *session, const coap_pdu_t *request); + +/** + * Sends an RST message with code @c 0 for the specified @p request to @p dst. + * This function returns the corresponding message id if the message was + * sent or @c COAP_INVALID_MID on error. + * + * @param session The CoAP session. + * @param request The request to be reset. + * + * @return The message id if RST was sent or @c + * COAP_INVALID_MID on error. + */ +COAP_STATIC_INLINE coap_mid_t +coap_send_rst(coap_session_t *session, const coap_pdu_t *request) { + return coap_send_message_type(session, request, COAP_MESSAGE_RST); +} + +/** +* Sends a CoAP message to given peer. The memory that is +* allocated for the pdu will be released by coap_send(). +* The caller must not use or delete the pdu after calling coap_send(). +* +* @param session The CoAP session. +* @param pdu The CoAP PDU to send. +* +* @return The message id of the sent message or @c +* COAP_INVALID_MID on error. +*/ +coap_mid_t coap_send( coap_session_t *session, coap_pdu_t *pdu ); + +#define coap_send_large(session, pdu) coap_send(session, pdu) + +/** + * Invokes the event handler of @p context for the given @p event and + * @p data. + * + * @param context The CoAP context whose event handler is to be called. + * @param event The event to deliver. + * @param session The session related to @p event. + * @return The result from the associated event handler or 0 if none was + * registered. + */ +int coap_handle_event(coap_context_t *context, + coap_event_t event, + coap_session_t *session); +/** + * Returns 1 if there are no messages to send or to dispatch in the context's + * queues. + * + * @param context The CoAP context to check. + * + * @return @c 0 if there are still pending transmits else @c 1 if nothing + * queued for transmission. Note that @c 0 does not mean there has + * been a response to a transmitted request. + */ +int coap_can_exit(coap_context_t *context); + +/** + * Returns the current value of an internal tick counter. The counter counts \c + * COAP_TICKS_PER_SECOND ticks every second. + */ +void coap_ticks(coap_tick_t *); + +/** + * Function interface for joining a multicast group for listening for the + * currently defined endpoints that are UDP. + * + * @param ctx The current context. + * @param groupname The name of the group that is to be joined for listening. + * @param ifname Network interface to join the group on, or NULL if first + * appropriate interface is to be chosen by the O/S. + * + * @return 0 on success, -1 on error + */ +int +coap_join_mcast_group_intf(coap_context_t *ctx, const char *groupname, + const char *ifname); + +#define coap_join_mcast_group(ctx, groupname) \ + (coap_join_mcast_group_intf(ctx, groupname, NULL)) + +/** + * Function interface for defining the hop count (ttl) for sending + * multicast traffic + * + * @param session The current session. + * @param hops The number of hops (ttl) to use before the multicast + * packet expires. + * + * @return 1 on success, 0 on error + */ +int +coap_mcast_set_hops(coap_session_t *session, size_t hops); + +/** + * Function interface to enable processing mcast requests on a per resource + * basis. This then enables a set of configuration flags set up when + * configuring the resources (coap_resource_init()). + * + * @param context The current context. + */ +void +coap_mcast_per_resource(coap_context_t *context); + +/**@}*/ + +/** + * @ingroup application_api + * @defgroup app_io Application I/O Handling + * API for Application Input / Output checking + * @{ + */ + +#define COAP_IO_WAIT 0 +#define COAP_IO_NO_WAIT ((uint32_t)-1) + +/** + * The main I/O processing function. All pending network I/O is completed, + * and then optionally waits for the next input packet. + * + * This internally calls coap_io_prepare_io(), then select() for the appropriate + * sockets, updates COAP_SOCKET_CAN_xxx where appropriate and then calls + * coap_io_do_io() before returning with the time spent in the function. + * + * Alternatively, if libcoap is compiled with epoll support, this internally + * calls coap_io_prepare_epoll(), then epoll_wait() for waiting for any file + * descriptors that have (internally) been set up with epoll_ctl() and + * finally coap_io_do_epoll() before returning with the time spent in the + * function. + * + * @param ctx The CoAP context + * @param timeout_ms Minimum number of milliseconds to wait for new packets + * before returning after doing any processing. + * If COAP_IO_WAIT, the call will block until the next + * internal action (e.g. packet retransmit) if any, or block + * until the next packet is received whichever is the sooner + * and do the necessary processing. + * If COAP_IO_NO_WAIT, the function will return immediately + * after processing without waiting for any new input + * packets to arrive. + * + * @return Number of milliseconds spent in function or @c -1 if there was + * an error + */ +int coap_io_process(coap_context_t *ctx, uint32_t timeout_ms); + +#ifndef RIOT_VERSION +/** + * The main message processing loop with additional fds for internal select. + * + * @param ctx The CoAP context + * @param timeout_ms Minimum number of milliseconds to wait for new packets + * before returning after doing any processing. + * If COAP_IO_WAIT, the call will block until the next + * internal action (e.g. packet retransmit) if any, or block + * until the next packet is received whichever is the sooner + * and do the necessary processing. + * If COAP_IO_NO_WAIT, the function will return immediately + * after processing without waiting for any new input + * packets to arrive. + * @param nfds The maximum FD set in readfds, writefds or exceptfds + * plus one, + * @param readfds Read FDs to additionally check for in internal select() + * or NULL if not required. + * @param writefds Write FDs to additionally check for in internal select() + * or NULL if not required. + * @param exceptfds Except FDs to additionally check for in internal select() + * or NULL if not required. + * + * + * @return Number of milliseconds spent in coap_io_process_with_fds, or @c -1 + * if there was an error. If defined, readfds, writefds, exceptfds + * are updated as returned by the internal select() call. + */ +int coap_io_process_with_fds(coap_context_t *ctx, uint32_t timeout_ms, + int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds); +#endif /* !RIOT_VERSION */ + +/**@}*/ + +/** + * @ingroup internal_api + * @defgroup app_io_internal Application I/O Handling + * Internal API for Application Input / Output checking + * @{ + */ + +/** +* Iterates through all the coap_socket_t structures embedded in endpoints or +* sessions associated with the @p ctx to determine which are wanting any +* read, write, accept or connect I/O (COAP_SOCKET_WANT_xxx is set). If set, +* the coap_socket_t is added to the @p sockets. +* +* Any now timed out delayed packet is transmitted, along with any packets +* associated with requested observable response. +* +* In addition, it returns when the next expected I/O is expected to take place +* (e.g. a packet retransmit). +* +* Prior to calling coap_io_do_io(), the @p sockets must be tested to see +* if any of the COAP_SOCKET_WANT_xxx have the appropriate information and if +* so, COAP_SOCKET_CAN_xxx is set. This typically will be done after using a +* select() call. +* +* Note: If epoll support is compiled into libcoap, coap_io_prepare_epoll() must +* be used instead of coap_io_prepare_io(). +* +* Internal function. +* +* @param ctx The CoAP context +* @param sockets Array of socket descriptors, filled on output +* @param max_sockets Size of socket array. +* @param num_sockets Pointer to the number of valid entries in the socket +* arrays on output. +* @param now Current time. +* +* @return timeout Maxmimum number of milliseconds that can be used by a +* select() to wait for network events or 0 if wait should be +* forever. +*/ +unsigned int +coap_io_prepare_io(coap_context_t *ctx, + coap_socket_t *sockets[], + unsigned int max_sockets, + unsigned int *num_sockets, + coap_tick_t now +); + +/** + * Processes any outstanding read, write, accept or connect I/O as indicated + * in the coap_socket_t structures (COAP_SOCKET_CAN_xxx set) embedded in + * endpoints or sessions associated with @p ctx. + * + * Note: If epoll support is compiled into libcoap, coap_io_do_epoll() must + * be used instead of coap_io_do_io(). + * + * Internal function. + * + * @param ctx The CoAP context + * @param now Current time + */ +void coap_io_do_io(coap_context_t *ctx, coap_tick_t now); + +/** + * Any now timed out delayed packet is transmitted, along with any packets + * associated with requested observable response. + * + * In addition, it returns when the next expected I/O is expected to take place + * (e.g. a packet retransmit). + * + * Note: If epoll support is compiled into libcoap, coap_io_prepare_epoll() must + * be used instead of coap_io_prepare_io(). + * + * Internal function. + * + * @param ctx The CoAP context + * @param now Current time. + * + * @return timeout Maxmimum number of milliseconds that can be used by a + * epoll_wait() to wait for network events or 0 if wait should be + * forever. + */ +unsigned int +coap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now); + +struct epoll_event; + +/** + * Process all the epoll events + * + * Note: If epoll support is compiled into libcoap, coap_io_do_epoll() must + * be used instead of coap_io_do_io(). + * + * Internal function + * + * @param ctx The current CoAP context. + * @param events The list of events returned from an epoll_wait() call. + * @param nevents The number of events. + * + */ +void coap_io_do_epoll(coap_context_t *ctx, struct epoll_event* events, + size_t nevents); + +/**@}*/ + +/** + * @deprecated Use coap_io_process() instead. + * + * This function just calls coap_io_process(). + * + * @param ctx The CoAP context + * @param timeout_ms Minimum number of milliseconds to wait for new packets + * before returning after doing any processing. + * If COAP_IO_WAIT, the call will block until the next + * internal action (e.g. packet retransmit) if any, or block + * until the next packet is received whichever is the sooner + * and do the necessary processing. + * If COAP_IO_NO_WAIT, the function will return immediately + * after processing without waiting for any new input + * packets to arrive. + * + * @return Number of milliseconds spent in function or @c -1 if there was + * an error + */ +COAP_STATIC_INLINE COAP_DEPRECATED int +coap_run_once(coap_context_t *ctx, uint32_t timeout_ms) +{ + return coap_io_process(ctx, timeout_ms); +} + +/** +* @deprecated Use coap_io_prepare_io() instead. +* +* This function just calls coap_io_prepare_io(). +* +* Internal function. +* +* @param ctx The CoAP context +* @param sockets Array of socket descriptors, filled on output +* @param max_sockets Size of socket array. +* @param num_sockets Pointer to the number of valid entries in the socket +* arrays on output. +* @param now Current time. +* +* @return timeout Maxmimum number of milliseconds that can be used by a +* select() to wait for network events or 0 if wait should be +* forever. +*/ +COAP_STATIC_INLINE COAP_DEPRECATED unsigned int +coap_write(coap_context_t *ctx, + coap_socket_t *sockets[], + unsigned int max_sockets, + unsigned int *num_sockets, + coap_tick_t now +) { + return coap_io_prepare_io(ctx, sockets, max_sockets, num_sockets, now); +} + +/** + * @deprecated Use coap_io_do_io() instead. + * + * This function just calls coap_io_do_io(). + * + * Internal function. + * + * @param ctx The CoAP context + * @param now Current time + */ +COAP_STATIC_INLINE COAP_DEPRECATED void +coap_read(coap_context_t *ctx, coap_tick_t now +) { + coap_io_do_io(ctx, now); +} + +/* Old definitions which may be hanging around in old code - be helpful! */ +#define COAP_RUN_NONBLOCK COAP_RUN_NONBLOCK_deprecated_use_COAP_IO_NO_WAIT +#define COAP_RUN_BLOCK COAP_RUN_BLOCK_deprecated_use_COAP_IO_WAIT + +#endif /* COAP_NET_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/pdu.h b/examples/espidf-coap-server/components/libcoap/include/coap3/pdu.h new file mode 100644 index 000000000..29331b335 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/pdu.h @@ -0,0 +1,603 @@ +/* + * pdu.h -- CoAP message structure + * + * Copyright (C) 2010-2014 Olaf Bergmann + * Copyright (C) 2021-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file pdu.h + * @brief Pre-defined constants that reflect defaults for CoAP + */ + +#ifndef COAP_PDU_H_ +#define COAP_PDU_H_ + +#include "uri.h" +#include "coap_option.h" + +#ifdef WITH_LWIP +#include +#endif + +#include + +/** + * @ingroup application_api + * @defgroup pdu PDU + * API for PDUs + * @{ + */ + +#define COAP_DEFAULT_PORT 5683 /* CoAP default UDP/TCP port */ +#define COAPS_DEFAULT_PORT 5684 /* CoAP default UDP/TCP port for secure transmission */ +#define COAP_DEFAULT_MAX_AGE 60 /* default maximum object lifetime in seconds */ +#ifndef COAP_DEFAULT_MTU +#define COAP_DEFAULT_MTU 1152 +#endif /* COAP_DEFAULT_MTU */ + +#define COAP_BERT_BASE 1152 + +#ifndef COAP_DEFAULT_HOP_LIMIT +#define COAP_DEFAULT_HOP_LIMIT 16 +#endif /* COAP_DEFAULT_HOP_LIMIT */ + +#define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */ + +/** well-known resources URI */ +#define COAP_DEFAULT_URI_WELLKNOWN ".well-known/core" + +/* CoAP message types */ + +/** + * CoAP PDU message type definitions + */ +typedef enum coap_pdu_type_t { + COAP_MESSAGE_CON, /* 0 confirmable message (requires ACK/RST) */ + COAP_MESSAGE_NON, /* 1 non-confirmable message (one-shot message) */ + COAP_MESSAGE_ACK, /* 2 used to acknowledge confirmable messages */ + COAP_MESSAGE_RST /* 3 indicates error in received messages */ +} coap_pdu_type_t; + +/** + * CoAP PDU Request methods + */ +typedef enum coap_request_t { + COAP_REQUEST_GET = 1, + COAP_REQUEST_POST, /* 2 */ + COAP_REQUEST_PUT, /* 3 */ + COAP_REQUEST_DELETE, /* 4 */ + COAP_REQUEST_FETCH, /* 5 RFC 8132 */ + COAP_REQUEST_PATCH, /* 6 RFC 8132 */ + COAP_REQUEST_IPATCH, /* 7 RFC 8132 */ +} coap_request_t; + +/* + * CoAP option numbers (be sure to update coap_option_check_critical() and + * coap_add_option() when adding options + */ + +/* + * The C, U, and N flags indicate the properties + * Critical, Unsafe, and NoCacheKey, respectively. + * If U is set, then N has no meaning as per + * https://tools.ietf.org/html/rfc7252#section-5.10 + * and is set to a -. + * + * Separately, R is for the options that can be repeated + * + * The least significant byte of the option is set as followed + * as per https://tools.ietf.org/html/rfc7252#section-5.4.6 + * + * 0 1 2 3 4 5 6 7 + * --+---+---+---+---+---+---+---+ + * | NoCacheKey| U | C | + * --+---+---+---+---+---+---+---+ + * + * https://tools.ietf.org/html/rfc8613#section-4 goes on to define E, I and U + * properties Encrypted and Integrity Protected, Integrity Protected Only, and + * Unprotected respectively. Integrity Protected Only is not currently used. + * + * An Option is tagged with CUNREIU with any of the letters replaced with _ if + * not set, or - for N if U is set (see above) for aiding understanding of the + * Option. + */ + +#define COAP_OPTION_IF_MATCH 1 /* C__RE__, opaque, 0-8 B, RFC7252 */ +#define COAP_OPTION_URI_HOST 3 /* CU-___U, String, 1-255 B, RFC7252 */ +#define COAP_OPTION_ETAG 4 /* ___RE__, opaque, 1-8 B, RFC7252 */ +#define COAP_OPTION_IF_NONE_MATCH 5 /* C___E__, empty, 0 B, RFC7252 */ +#define COAP_OPTION_OBSERVE 6 /* _U-_E_U, empty/uint,0/0-3 B, RFC7641 */ +#define COAP_OPTION_URI_PORT 7 /* CU-___U, uint, 0-2 B, RFC7252 */ +#define COAP_OPTION_LOCATION_PATH 8 /* ___RE__, String, 0-255 B, RFC7252 */ +#define COAP_OPTION_OSCORE 9 /* C_____U, *, 0-255 B, RFC8613 */ +#define COAP_OPTION_URI_PATH 11 /* CU-RE__, String, 0-255 B, RFC7252 */ +#define COAP_OPTION_CONTENT_FORMAT 12 /* ____E__, uint, 0-2 B, RFC7252 */ +#define COAP_OPTION_CONTENT_TYPE COAP_OPTION_CONTENT_FORMAT +/* COAP_OPTION_MAXAGE default 60 seconds if not set */ +#define COAP_OPTION_MAXAGE 14 /* _U-_E_U, uint, 0-4 B, RFC7252 */ +#define COAP_OPTION_URI_QUERY 15 /* CU-RE__, String, 1-255 B, RFC7252 */ +#define COAP_OPTION_HOP_LIMIT 16 /* ______U, uint, 1 B, RFC8768 */ +#define COAP_OPTION_ACCEPT 17 /* C___E__, uint, 0-2 B, RFC7252 */ +#define COAP_OPTION_LOCATION_QUERY 20 /* ___RE__, String, 0-255 B, RFC7252 */ +#define COAP_OPTION_BLOCK2 23 /* CU-_E_U, uint, 0-3 B, RFC7959 */ +#define COAP_OPTION_BLOCK1 27 /* CU-_E_U, uint, 0-3 B, RFC7959 */ +#define COAP_OPTION_SIZE2 28 /* __N_E_U, uint, 0-4 B, RFC7959 */ +#define COAP_OPTION_PROXY_URI 35 /* CU-___U, String, 1-1034 B, RFC7252 */ +#define COAP_OPTION_PROXY_SCHEME 39 /* CU-___U, String, 1-255 B, RFC7252 */ +#define COAP_OPTION_SIZE1 60 /* __N_E_U, uint, 0-4 B, RFC7252 */ +#define COAP_OPTION_ECHO 252 /* _N__E_U, opaque, 0-40 B, RFC9175 */ +#define COAP_OPTION_NORESPONSE 258 /* _U-_E_U, uint, 0-1 B, RFC7967 */ +#define COAP_OPTION_RTAG 292 /* ___RE_U, opaque, 0-8 B, RFC9175 */ + +#define COAP_MAX_OPT 65535 /**< the highest option number we know */ + +/* CoAP result codes (HTTP-Code / 100 * 40 + HTTP-Code % 100) */ + +/* As of draft-ietf-core-coap-04, response codes are encoded to base + * 32, i.e. the three upper bits determine the response class while + * the remaining five fine-grained information specific to that class. + */ +#define COAP_RESPONSE_CODE(N) (((N)/100 << 5) | (N)%100) + +/* Determines the class of response code C */ +#define COAP_RESPONSE_CLASS(C) (((C) >> 5) & 0xFF) + +#ifndef SHORT_ERROR_RESPONSE +/** + * Returns a human-readable response phrase for the specified CoAP response @p + * code. This function returns @c NULL if not found. + * + * @param code The response code for which the literal phrase should be + * retrieved. + * + * @return A zero-terminated string describing the error, or @c NULL if not + * found. + */ +const char *coap_response_phrase(unsigned char code); + +#define COAP_ERROR_PHRASE_LENGTH 32 /**< maximum length of error phrase */ + +#else +#define coap_response_phrase(x) ((char *)NULL) + +#define COAP_ERROR_PHRASE_LENGTH 0 /**< maximum length of error phrase */ +#endif /* SHORT_ERROR_RESPONSE */ + +#define COAP_SIGNALING_CODE(N) (((N)/100 << 5) | (N)%100) + +typedef enum coap_pdu_signaling_proto_t { + COAP_SIGNALING_CSM = COAP_SIGNALING_CODE(701), + COAP_SIGNALING_PING = COAP_SIGNALING_CODE(702), + COAP_SIGNALING_PONG = COAP_SIGNALING_CODE(703), + COAP_SIGNALING_RELEASE = COAP_SIGNALING_CODE(704), + COAP_SIGNALING_ABORT = COAP_SIGNALING_CODE(705), +} coap_pdu_signaling_proto_t; + +/* Applies to COAP_SIGNALING_CSM */ +#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE 2 +#define COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER 4 +/* Applies to COAP_SIGNALING_PING / COAP_SIGNALING_PONG */ +#define COAP_SIGNALING_OPTION_CUSTODY 2 +/* Applies to COAP_SIGNALING_RELEASE */ +#define COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS 2 +#define COAP_SIGNALING_OPTION_HOLD_OFF 4 +/* Applies to COAP_SIGNALING_ABORT */ +#define COAP_SIGNALING_OPTION_BAD_CSM_OPTION 2 + +/* CoAP media type encoding */ + +#define COAP_MEDIATYPE_TEXT_PLAIN 0 /* text/plain (UTF-8) */ +#define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT 40 /* application/link-format */ +#define COAP_MEDIATYPE_APPLICATION_XML 41 /* application/xml */ +#define COAP_MEDIATYPE_APPLICATION_OCTET_STREAM 42 /* application/octet-stream */ +#define COAP_MEDIATYPE_APPLICATION_RDF_XML 43 /* application/rdf+xml */ +#define COAP_MEDIATYPE_APPLICATION_EXI 47 /* application/exi */ +#define COAP_MEDIATYPE_APPLICATION_JSON 50 /* application/json */ +#define COAP_MEDIATYPE_APPLICATION_CBOR 60 /* application/cbor */ +#define COAP_MEDIATYPE_APPLICATION_CWT 61 /* application/cwt, RFC 8392 */ + +/* Content formats from RFC 7390 */ +#define COAP_MEDIATYPE_APPLICATION_COAP_GROUP_JSON 256 /* application/coap-group+json */ + +/* Content formats from RFC 8152 */ +#define COAP_MEDIATYPE_APPLICATION_COSE_SIGN 98 /* application/cose; cose-type="cose-sign" */ +#define COAP_MEDIATYPE_APPLICATION_COSE_SIGN1 18 /* application/cose; cose-type="cose-sign1" */ +#define COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT 96 /* application/cose; cose-type="cose-encrypt" */ +#define COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0 16 /* application/cose; cose-type="cose-encrypt0" */ +#define COAP_MEDIATYPE_APPLICATION_COSE_MAC 97 /* application/cose; cose-type="cose-mac" */ +#define COAP_MEDIATYPE_APPLICATION_COSE_MAC0 17 /* application/cose; cose-type="cose-mac0" */ + +#define COAP_MEDIATYPE_APPLICATION_COSE_KEY 101 /* application/cose-key */ +#define COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET 102 /* application/cose-key-set */ + +/* Content formats from RFC 8428 */ +#define COAP_MEDIATYPE_APPLICATION_SENML_JSON 110 /* application/senml+json */ +#define COAP_MEDIATYPE_APPLICATION_SENSML_JSON 111 /* application/sensml+json */ +#define COAP_MEDIATYPE_APPLICATION_SENML_CBOR 112 /* application/senml+cbor */ +#define COAP_MEDIATYPE_APPLICATION_SENSML_CBOR 113 /* application/sensml+cbor */ +#define COAP_MEDIATYPE_APPLICATION_SENML_EXI 114 /* application/senml-exi */ +#define COAP_MEDIATYPE_APPLICATION_SENSML_EXI 115 /* application/sensml-exi */ +#define COAP_MEDIATYPE_APPLICATION_SENML_XML 310 /* application/senml+xml */ +#define COAP_MEDIATYPE_APPLICATION_SENSML_XML 311 /* application/sensml+xml */ + +/* Content formats from RFC 8782 */ +#define COAP_MEDIATYPE_APPLICATION_DOTS_CBOR 271 /* application/dots+cbor */ + +/* Content formats from RFC 9200 */ +#define COAP_MEDIATYPE_APPLICATION_ACE_CBOR 19 /* application/ace+cbor */ + +/* Note that identifiers for registered media types are in the range 0-65535. We + * use an unallocated type here and hope for the best. */ +#define COAP_MEDIATYPE_ANY 0xff /* any media type */ + +/** + * coap_mid_t is used to store the CoAP Message ID of a CoAP PDU. + * Valid message ids are 0 to 2^16. Negative values are error codes. + */ +typedef int coap_mid_t; + +/** Indicates an invalid message id. */ +#define COAP_INVALID_MID -1 + +/** + * Indicates an invalid message id. + * @deprecated Use COAP_INVALID_MID instead. + */ +#define COAP_INVALID_TID COAP_INVALID_MID + +/** + * @deprecated Use coap_optlist_t instead. + * + * Structures for more convenient handling of options. (To be used with ordered + * coap_list_t.) The option's data will be added to the end of the coap_option + * structure (see macro COAP_OPTION_DATA). + */ +COAP_DEPRECATED typedef struct { + uint16_t key; /* the option key (no delta coding) */ + unsigned int length; +} coap_option; + +#define COAP_OPTION_KEY(option) (option).key +#define COAP_OPTION_LENGTH(option) (option).length +#define COAP_OPTION_DATA(option) ((unsigned char *)&(option) + sizeof(coap_option)) + +#ifdef WITH_LWIP +/** + * Creates a CoAP PDU from an lwIP @p pbuf, whose reference is passed on to this + * function. + * + * The pbuf is checked for being contiguous, and for having only one reference. + * The reference is stored in the PDU and will be freed when the PDU is freed. + * + * (For now, these are fatal errors; in future, a new pbuf might be allocated, + * the data copied and the passed pbuf freed). + * + * This behaves like coap_pdu_init(0, 0, 0, pbuf->tot_len), and afterwards + * copying the contents of the pbuf to the pdu. + * + * @return A pointer to the new PDU object or @c NULL on error. + */ +coap_pdu_t * coap_pdu_from_pbuf(struct pbuf *pbuf); +#endif + +/** +* CoAP protocol types +*/ +typedef enum coap_proto_t { + COAP_PROTO_NONE = 0, + COAP_PROTO_UDP, + COAP_PROTO_DTLS, + COAP_PROTO_TCP, + COAP_PROTO_TLS, +} coap_proto_t; + +/** + * Set of codes available for a PDU. + */ +typedef enum coap_pdu_code_t { + COAP_EMPTY_CODE = 0, + + COAP_REQUEST_CODE_GET = COAP_REQUEST_GET, + COAP_REQUEST_CODE_POST = COAP_REQUEST_POST, + COAP_REQUEST_CODE_PUT = COAP_REQUEST_PUT, + COAP_REQUEST_CODE_DELETE = COAP_REQUEST_DELETE, + COAP_REQUEST_CODE_FETCH = COAP_REQUEST_FETCH, + COAP_REQUEST_CODE_PATCH = COAP_REQUEST_PATCH, + COAP_REQUEST_CODE_IPATCH = COAP_REQUEST_IPATCH, + + COAP_RESPONSE_CODE_CREATED = COAP_RESPONSE_CODE(201), + COAP_RESPONSE_CODE_DELETED = COAP_RESPONSE_CODE(202), + COAP_RESPONSE_CODE_VALID = COAP_RESPONSE_CODE(203), + COAP_RESPONSE_CODE_CHANGED = COAP_RESPONSE_CODE(204), + COAP_RESPONSE_CODE_CONTENT = COAP_RESPONSE_CODE(205), + COAP_RESPONSE_CODE_CONTINUE = COAP_RESPONSE_CODE(231), + COAP_RESPONSE_CODE_BAD_REQUEST = COAP_RESPONSE_CODE(400), + COAP_RESPONSE_CODE_UNAUTHORIZED = COAP_RESPONSE_CODE(401), + COAP_RESPONSE_CODE_BAD_OPTION = COAP_RESPONSE_CODE(402), + COAP_RESPONSE_CODE_FORBIDDEN = COAP_RESPONSE_CODE(403), + COAP_RESPONSE_CODE_NOT_FOUND = COAP_RESPONSE_CODE(404), + COAP_RESPONSE_CODE_NOT_ALLOWED = COAP_RESPONSE_CODE(405), + COAP_RESPONSE_CODE_NOT_ACCEPTABLE = COAP_RESPONSE_CODE(406), + COAP_RESPONSE_CODE_INCOMPLETE = COAP_RESPONSE_CODE(408), + COAP_RESPONSE_CODE_CONFLICT = COAP_RESPONSE_CODE(409), + COAP_RESPONSE_CODE_PRECONDITION_FAILED = COAP_RESPONSE_CODE(412), + COAP_RESPONSE_CODE_REQUEST_TOO_LARGE = COAP_RESPONSE_CODE(413), + COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT = COAP_RESPONSE_CODE(415), + COAP_RESPONSE_CODE_UNPROCESSABLE = COAP_RESPONSE_CODE(422), + COAP_RESPONSE_CODE_TOO_MANY_REQUESTS = COAP_RESPONSE_CODE(429), + COAP_RESPONSE_CODE_INTERNAL_ERROR = COAP_RESPONSE_CODE(500), + COAP_RESPONSE_CODE_NOT_IMPLEMENTED = COAP_RESPONSE_CODE(501), + COAP_RESPONSE_CODE_BAD_GATEWAY = COAP_RESPONSE_CODE(502), + COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE = COAP_RESPONSE_CODE(503), + COAP_RESPONSE_CODE_GATEWAY_TIMEOUT = COAP_RESPONSE_CODE(504), + COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED = COAP_RESPONSE_CODE(505), + COAP_RESPONSE_CODE_HOP_LIMIT_REACHED = COAP_RESPONSE_CODE(508), + + COAP_SIGNALING_CODE_CSM = COAP_SIGNALING_CSM, + COAP_SIGNALING_CODE_PING = COAP_SIGNALING_PING, + COAP_SIGNALING_CODE_PONG = COAP_SIGNALING_PONG, + COAP_SIGNALING_CODE_RELEASE = COAP_SIGNALING_RELEASE, + COAP_SIGNALING_CODE_ABORT = COAP_SIGNALING_ABORT +} coap_pdu_code_t; + +/** + * Creates a new CoAP PDU with at least enough storage space for the given + * @p size maximum message size. The function returns a pointer to the + * node coap_pdu_t object on success, or @c NULL on error. The storage allocated + * for the result must be released with coap_delete_pdu() if coap_send() + * is not called. + * + * @param type The type of the PDU (one of COAP_MESSAGE_CON, COAP_MESSAGE_NON, + * COAP_MESSAGE_ACK, COAP_MESSAGE_RST). + * @param code The message code of the PDU. + * @param mid The message id to set or 0 if unknown / not applicable. + * @param size The maximum allowed number of byte for the message. + * @return A pointer to the new PDU object or @c NULL on error. + */ +coap_pdu_t *coap_pdu_init(coap_pdu_type_t type, coap_pdu_code_t code, + coap_mid_t mid, size_t size); + +/** + * Creates a new CoAP PDU. + * + * @param type The type of the PDU (one of COAP_MESSAGE_CON, COAP_MESSAGE_NON, + * COAP_MESSAGE_ACK, COAP_MESSAGE_RST). + * @param code The message code of the PDU. + * @param session The session that will be using this PDU + * + * @return The skeletal PDU or @c NULL if failure. + */ +coap_pdu_t *coap_new_pdu(coap_pdu_type_t type, coap_pdu_code_t code, + coap_session_t *session); + +/** + * Dispose of an CoAP PDU and frees associated storage. + * Not that in general you should not call this function directly. + * When a PDU is sent with coap_send(), coap_delete_pdu() will be called + * automatically for you. + * + * @param pdu The PDU for free off. + */ +void coap_delete_pdu(coap_pdu_t *pdu); + +/** + * Duplicate an existing PDU. Specific options can be ignored and not copied + * across. The PDU data payload is not copied across. + * + * @param old_pdu The PDU to duplicate + * @param session The session that will be using this PDU. + * @param token_length The length of the token to use in this duplicated PDU. + * @param token The token to use in this duplicated PDU. + * @param drop_options A list of options not to copy into the duplicated PDU. + * If @c NULL, then all options are copied across. + * + * @return The duplicated PDU or @c NULL if failure. + */ +coap_pdu_t * +coap_pdu_duplicate(const coap_pdu_t *old_pdu, + coap_session_t *session, + size_t token_length, + const uint8_t *token, + coap_opt_filter_t *drop_options); + +/** + * Parses @p data into the CoAP PDU structure given in @p result. + * The target pdu must be large enough to hold the token, options and data. + * This function returns @c 0 on error or a number greater than zero on success. + * + * @param proto Session's protocol + * @param data The raw data to parse as CoAP PDU. + * @param length The actual size of @p data. + * @param pdu The PDU structure to fill. Note that the structure must + * provide space to hold the token, optional options and + * optional data. + * + * @return 1 on success or @c 0 on error. + */ +int coap_pdu_parse(coap_proto_t proto, + const uint8_t *data, + size_t length, + coap_pdu_t *pdu); + +/** + * Adds token of length @p len to @p pdu. + * + * This function will fail if a token has already been added to the @p pdu. + * + * Hence options and data must be added after optional coap_add_token() has + * been called. + * + * @param pdu The PDU where the token is to be added. + * @param len The length of the new token. + * @param data The token to add. + * + * @return A value greater than zero on success, or @c 0 on error. + */ +int coap_add_token(coap_pdu_t *pdu, + size_t len, + const uint8_t *data); + +/** + * Adds option of given @p number to @p pdu that is passed as first + * parameter. + * + * This function will fail if data has aready been added to the @p pdu. + * + * Hence data must be added after optional coap_add_option() has been called. + * + * Note: Where possible, the option data needs to be stripped of leading zeros + * (big endian) to reduce the amount of data needed in the PDU, as well as in + * some cases the maximum data size of an opton can be exceeded if not stripped + * and hence be illegal. This is done by using coap_encode_var_safe() or + * coap_encode_var_safe8(). + * + * @param pdu The PDU where the option is to be added. + * @param number The number of the new option. + * @param len The length of the new option. + * @param data The data of the new option. + * + * @return The overall length of the option or @c 0 on failure. + */ +size_t coap_add_option(coap_pdu_t *pdu, + coap_option_num_t number, + size_t len, + const uint8_t *data); + +/** + * Adds given data to the pdu that is passed as first parameter. + * + * This function will fail if data has aready been added to the @p pdu. + * + * @param pdu The PDU where the data is to be added. + * @param len The length of the data. + * @param data The data to add. + * + * @return @c 1 if success, else @c 0 if failure. + */ +int coap_add_data(coap_pdu_t *pdu, + size_t len, + const uint8_t *data); + +/** + * Adds given data to the pdu that is passed as first parameter but does not + * + * This function will fail if data has aready been added to the @p pdu. + * + * The actual data must be copied at the returned location. + * + * @param pdu The PDU where the data is to be added. + * @param len The length of the data. + * + * @return Where to copy the data of len to, or @c NULL is error. + */ +uint8_t *coap_add_data_after(coap_pdu_t *pdu, size_t len); + +/** + * Retrieves the length and data pointer of specified PDU. Returns 0 on error or + * 1 if *len and *data have correct values. Note that these values are destroyed + * with the pdu. + * + * @param pdu The specified PDU. + * @param len Returns the length of the current data + * @param data Returns the ptr to the current data + * + * @return @c 1 if len and data are correctly filled in, else + * @c 0 if there is no data. + */ +int coap_get_data(const coap_pdu_t *pdu, + size_t *len, + const uint8_t **data); + +/** + * Retrieves the data from a PDU, with support for large bodies of data that + * spans multiple PDUs. + * + * Note: The data pointed to on return is destroyed when the PDU is destroyed. + * + * @param pdu The specified PDU. + * @param len Returns the length of the current data + * @param data Returns the ptr to the current data + * @param offset Returns the offset of the current data from the start of the + * body comprising of many blocks (RFC7959) + * @param total Returns the total size of the body. + * If offset + length < total, then there is more data to follow. + * + * @return @c 1 if len, data, offset and total are correctly filled in, else + * @c 0 if there is no data. + */ +int coap_get_data_large(const coap_pdu_t *pdu, + size_t *len, + const uint8_t **data, + size_t *offset, + size_t *total); + +/** + * Gets the PDU code associated with @p pdu. + * + * @param pdu The PDU object. + * + * @return The PDU code. + */ +coap_pdu_code_t coap_pdu_get_code(const coap_pdu_t *pdu); + +/** + * Sets the PDU code in the @p pdu. + * + * @param pdu The PDU object. + * @param code The code to set in the PDU. + */ +void coap_pdu_set_code(coap_pdu_t *pdu, coap_pdu_code_t code); + +/** + * Gets the PDU type associated with @p pdu. + * + * @param pdu The PDU object. + * + * @return The PDU type. + */ +coap_pdu_type_t coap_pdu_get_type(const coap_pdu_t *pdu); + +/** + * Sets the PDU type in the @p pdu. + * + * @param pdu The PDU object. + * @param type The type to set for the PDU. + */ +void coap_pdu_set_type(coap_pdu_t *pdu, coap_pdu_type_t type); + +/** + * Gets the token associated with @p pdu. + * + * @param pdu The PDU object. + * + * @return The token information. + */ +coap_bin_const_t coap_pdu_get_token(const coap_pdu_t *pdu); + +/** + * Gets the message id associated with @p pdu. + * + * @param pdu The PDU object. + * + * @return The message id. + */ +coap_mid_t coap_pdu_get_mid(const coap_pdu_t *pdu); + +/** + * Sets the message id in the @p pdu. + * + * @param pdu The PDU object. + * @param mid The message id value to set in the PDU. + * + */ +void coap_pdu_set_mid(coap_pdu_t *pdu, coap_mid_t mid); + +/** @} */ + +#endif /* COAP_PDU_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/resource.h b/examples/espidf-coap-server/components/libcoap/include/coap3/resource.h new file mode 100644 index 000000000..50aadcebd --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/resource.h @@ -0,0 +1,499 @@ +/* + * resource.h -- generic resource handling + * + * Copyright (C) 2010,2011,2014-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file resource.h + * @brief Generic resource handling + */ + +#ifndef COAP_RESOURCE_H_ +#define COAP_RESOURCE_H_ + +#ifndef COAP_RESOURCE_CHECK_TIME +/** The interval in seconds to check if resources have changed. */ +#define COAP_RESOURCE_CHECK_TIME 2 +#endif /* COAP_RESOURCE_CHECK_TIME */ + +#include "coap_async.h" +#include "block.h" +#include "str.h" +#include "pdu.h" +#include "net.h" +#include "coap_subscribe.h" + +/** + * @ingroup application_api + * @defgroup coap_resource Resource Configuraton + * API for setting up resources + * @{ + */ + +/** + * Definition of message handler function + */ +typedef void (*coap_method_handler_t) + (coap_resource_t *, + coap_session_t *, + const coap_pdu_t * /* request */, + const coap_string_t * /* query string */, + coap_pdu_t * /* response */); + +#define COAP_ATTR_FLAGS_RELEASE_NAME 0x1 +#define COAP_ATTR_FLAGS_RELEASE_VALUE 0x2 + +/** The URI passed to coap_resource_init() is free'd by coap_delete_resource(). */ +#define COAP_RESOURCE_FLAGS_RELEASE_URI 0x1 + +/** + * Observe Notifications will be sent non-confirmable by default. RFC 7641 + * Section 4.5 + * https://tools.ietf.org/html/rfc7641#section-4.5 + * Libcoap will always send every fifth packet as confirmable. + */ +#define COAP_RESOURCE_FLAGS_NOTIFY_NON 0x0 + +/** + * Observe Notifications will be sent confirmable. RFC 7641 Section 4.5 + * https://tools.ietf.org/html/rfc7641#section-4.5 + */ +#define COAP_RESOURCE_FLAGS_NOTIFY_CON 0x2 + +/** + * Observe Notifications will always be sent non-confirmable. This is in + * violation of RFC 7641 Section 4.5 + * https://tools.ietf.org/html/rfc7641#section-4.5 + * but required by the DOTS signal channel protocol which needs to operate in + * lossy DDoS attack environments. + * https://tools.ietf.org/html/rfc8782#section-4.4.2.1 + */ +#define COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS 0x4 + +/** + * This resource has support for multicast requests. + * https://datatracker.ietf.org/doc/html/rfc7252#section-11.3 + * https://datatracker.ietf.org/doc/html/rfc7390#section-2.8 + * https://datatracker.ietf.org/doc/html/draft-ietf-core-groupcomm-bis-06.txt#section-3.6 + * Note: ".well-known/core" always supports multicast. + * Note: Only tested if coap_mcast_per_resource() has been called. + */ +#define COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT 0x8 + +/** + * Disable libcoap library from adding in delays to multicast requests before + * releasing the response back to the client. It is then the responsibility of + * the app to delay the responses for multicast requests. + * https://datatracker.ietf.org/doc/html/rfc7252#section-8.2 + * https://datatracker.ietf.org/doc/html/rfc7390#section-2.8 + * https://datatracker.ietf.org/doc/html/draft-ietf-core-groupcomm-bis-06.txt#section-3.6 + * Note: Only tested if coap_mcast_per_resource() has been called. + */ +#define COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_DELAYS 0x10 + +/** + * Enable libcoap library suppression of 205 multicast responses that are empty + * (overridden by RFC7969 No-Response option) for multicast requests. + * https://datatracker.ietf.org/doc/html/rfc7390#section-2.7 + * https://datatracker.ietf.org/doc/html/draft-ietf-core-groupcomm-bis-06.txt#section-3.1.2 + * Note: Only tested if coap_mcast_per_resource() has been called. + */ +#define COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_05 0x20 + +/** + * Enable libcoap library suppressing 2.xx multicast responses (overridden by + * RFC7969 No-Response option) for multicast requests. + * https://datatracker.ietf.org/doc/html/rfc7390#section-2.7 + * https://datatracker.ietf.org/doc/html/draft-ietf-core-groupcomm-bis-06.txt#section-3.1.2 + * Note: Only tested if coap_mcast_per_resource() has been called. + */ +#define COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_XX 0x40 + +/** + * Disable libcoap library suppressing 4.xx multicast responses (overridden by + * RFC7969 No-Response option) for multicast requests. + * https://datatracker.ietf.org/doc/html/rfc7390#section-2.7 + * https://datatracker.ietf.org/doc/html/draft-ietf-core-groupcomm-bis-06.txt#section-3.1.2 + * Note: Only tested if coap_mcast_per_resource() has been called. + */ +#define COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_SUPPRESS_4_XX 0x80 + +/** + * Disable libcoap library suppressing 5.xx multicast responses (overridden by + * RFC7969 No-Response option) for multicast requests. + * https://datatracker.ietf.org/doc/html/rfc7390#section-2.7 + * https://datatracker.ietf.org/doc/html/draft-ietf-core-groupcomm-bis-06.txt#section-3.1.2 + * Note: Only tested if coap_mcast_per_resource() has been called. + */ +#define COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_SUPPRESS_5_XX 0x100 + +#define COAP_RESOURCE_FLAGS_MCAST_LIST \ + (COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT | \ + COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_DELAYS | \ + COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_05 | \ + COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_XX | \ + COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_SUPPRESS_4_XX | \ + COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_SUPPRESS_5_XX) + +/** + * Creates a new resource object and initializes the link field to the string + * @p uri_path. This function returns the new coap_resource_t object. + * + * If the string is going to be freed off by coap_delete_resource() when + * COAP_RESOURCE_FLAGS_RELEASE_URI is set in @p flags, then either the 's' + * variable of coap_str_const_t has to point to constant text, or point to data + * within the allocated coap_str_const_t parameter. + * + * @param uri_path The string URI path of the new resource. The leading '/' is + * not normally required - e.g. just "full/path/for/resource". + * @param flags Flags for memory management, observe handling and multicast + * support, comprising of zero or more COAP_RESOURCE_FLAGS_* + * ored together. + * If flags is set to 0 then the + * COAP_RESOURCE_FLAGS_NOTIFY_NON is assumed. + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_resource_t *coap_resource_init(coap_str_const_t *uri_path, + int flags); + +/** + * Creates a new resource object for the unknown resource handler with support + * for PUT. + * + * In the same way that additional handlers can be added to the resource + * created by coap_resource_init() by using coap_register_handler(), POST, + * GET, DELETE etc. handlers can be added to this resource. It is the + * responsibility of the application to manage the unknown resources by either + * creating new resources with coap_resource_init() (which should have a + * DELETE handler specified for the resource removal) or by maintaining an + * active resource list. + * + * Note: There can only be one unknown resource handler per context - attaching + * a new one overrides the previous definition. + * + * Note: It is not possible to observe the unknown resource with a GET request + * - a separate resource needs to be created by the PUT (or POST) + * handler, and make that resource observable. + * + * This function returns the new coap_resource_t object. + * + * @param put_handler The PUT handler to register with @p resource for + * unknown Uri-Path. + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_resource_t *coap_resource_unknown_init(coap_method_handler_t put_handler); + +/** + * Creates a new resource object for the unknown resource handler with support + * for PUT and configurable control over multicast requests packets. + * + * In the same way that additional handlers can be added to the resource + * created by coap_resource_init() by using coap_register_handler(), POST, + * GET, DELETE etc. handlers can be added to this resource. It is the + * responsibility of the application to manage the unknown resources by either + * creating new resources with coap_resource_init() (which should have a + * DELETE handler specified for the resource removal) or by maintaining an + * active resource list. + * + * Note: There can only be one unknown resource handler per context - attaching + * a new one overrides the previous definition. + * + * Note: It is not possible to observe the unknown resource with a GET request + * - a separate resource needs to be created by the PUT (or POST) + * handler, and make that resource observable. + * + * This function returns the new coap_resource_t object. + * + * @param put_handler The PUT handler to register with @p resource for + * unknown Uri-Path. + * @param flags Zero or more COAP_RESOURCE_FLAGS_*MCAST* ored together to + * indicate what to do with multicast packets. + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_resource_t *coap_resource_unknown_init2(coap_method_handler_t put_handler, + int flags); + +/** + * Creates a new resource object for handling proxy URIs. + * This function returns the new coap_resource_t object. + * + * Note: There can only be one proxy resource handler per context - attaching + * a new one overrides the previous definition. + * + * @param handler The PUT/POST/GET etc. handler that handles all request types. + * @param host_name_count The number of provided host_name_list entries. A + * minimum of 1 must be provided. + * @param host_name_list Array of depth host_name_count names that this proxy + * is known by. + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_resource_t *coap_resource_proxy_uri_init(coap_method_handler_t handler, + size_t host_name_count, const char *host_name_list[]); + +/** + * Creates a new resource object for handling proxy URIs with configurable + * control over multicast request packets. + * This function returns the new coap_resource_t object. + * + * Note: There can only be one proxy resource handler per context - attaching + * a new one overrides the previous definition. + * + * @param handler The PUT/POST/GET etc. handler that handles all request types. + * @param host_name_count The number of provided host_name_list entries. A + * minimum of 1 must be provided. + * @param host_name_list Array of depth host_name_count names that this proxy + * is known by. + * @param flags Zero or more COAP_RESOURCE_FLAGS_*MCAST* ored together to + * indicate what to do with multicast packets. + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_resource_t *coap_resource_proxy_uri_init2(coap_method_handler_t handler, + size_t host_name_count, + const char *host_name_list[], + int flags); + +/** + * Returns the resource identified by the unique string @p uri_path. If no + * resource was found, this function returns @c NULL. + * + * @param context The context to look for this resource. + * @param uri_path The unique string uri of the resource. + * + * @return A pointer to the resource or @c NULL if not found. + */ +coap_resource_t *coap_get_resource_from_uri_path(coap_context_t *context, + coap_str_const_t *uri_path); + +/** + * Get the uri_path from a @p resource. + * + * @param resource The CoAP resource to check. + * + * @return The uri_path if it exists or @c NULL otherwise. + */ +coap_str_const_t* coap_resource_get_uri_path(coap_resource_t *resource); + +/** + * Sets the notification message type of resource @p resource to given + * @p mode + + * @param resource The resource to update. + * @param mode Must be one of @c COAP_RESOURCE_FLAGS_NOTIFY_NON + * or @c COAP_RESOURCE_FLAGS_NOTIFY_CON. + */ +void coap_resource_set_mode(coap_resource_t *resource, int mode); + +/** + * Sets the user_data. The user_data is exclusively used by the library-user + * and can be used as user defined context in the handler functions. + * + * @param resource Resource to attach the data to + * @param data Data to attach to the user_data field. This pointer is + * only used for storage, the data remains under user control + */ +void coap_resource_set_userdata(coap_resource_t *resource, void *data); + +/** + * Gets the user_data. The user_data is exclusively used by the library-user + * and can be used as context in the handler functions. + * + * @param resource Resource to retrieve the user_data from + * + * @return The user_data pointer + */ +void *coap_resource_get_userdata(coap_resource_t *resource); + +/** + * Definition of release resource user_data callback function + */ +typedef void (*coap_resource_release_userdata_handler_t)(void *user_data); + +/** + * Defines the context wide callback to use to when the resource is deleted + * to release the data held in the resource's user_data. + * + * @param context The context to associate the release callback with + * @param callback The callback to invoke when the resource is deleted or NULL + * + */ +void coap_resource_release_userdata_handler(coap_context_t *context, + coap_resource_release_userdata_handler_t callback); + +/** + * Registers the given @p resource for @p context. The resource must have been + * created by coap_resource_init() or coap_resource_unknown_init(), the + * storage allocated for the resource will be released by coap_delete_resource(). + * + * @param context The context to use. + * @param resource The resource to store. + */ +void coap_add_resource(coap_context_t *context, coap_resource_t *resource); + +/** + * Deletes a resource identified by @p resource. The storage allocated for that + * resource is freed, and removed from the context. + * + * @param context This parameter is ignored, but kept for backward + * compatability. + * @param resource The resource to delete. + * + * @return @c 1 if the resource was found (and destroyed), + * @c 0 otherwise. + */ +int coap_delete_resource(coap_context_t *context, coap_resource_t *resource); + +/** + * Registers the specified @p handler as message handler for the request type + * @p method + * + * @param resource The resource for which the handler shall be registered. + * @param method The CoAP request method to handle. + * @param handler The handler to register with @p resource. + */ +void coap_register_handler(coap_resource_t *resource, + coap_request_t method, + coap_method_handler_t handler); + +/** + * Registers the specified @p handler as message handler for the request type + * @p method + * + * @param resource The resource for which the handler shall be registered. + * @param method The CoAP request method to handle. + * @param handler The handler to register with @p resource. + */ +void coap_register_request_handler(coap_resource_t *resource, + coap_request_t method, + coap_method_handler_t handler); + +/** + * Registers a new attribute with the given @p resource. As the + * attribute's coap_str_const_ fields will point to @p name and @p value the + * caller must ensure that these pointers are valid during the + * attribute's lifetime. + + * If the @p name and/or @p value string is going to be freed off at attribute + * removal time by the setting of COAP_ATTR_FLAGS_RELEASE_NAME or + * COAP_ATTR_FLAGS_RELEASE_VALUE in @p flags, then either the 's' + * variable of coap_str_const_t has to point to constant text, or point to data + * within the allocated coap_str_const_t parameter. + * + * @param resource The resource to register the attribute with. + * @param name The attribute's name as a string. + * @param value The attribute's value as a string or @c NULL if none. + * @param flags Flags for memory management (in particular release of + * memory). Possible values:@n + * + * COAP_ATTR_FLAGS_RELEASE_NAME + * If this flag is set, the name passed to + * coap_add_attr_release() is free'd + * when the attribute is deleted@n + * + * COAP_ATTR_FLAGS_RELEASE_VALUE + * If this flag is set, the value passed to + * coap_add_attr_release() is free'd + * when the attribute is deleted@n + * + * @return A pointer to the new attribute or @c NULL on error. + */ +coap_attr_t *coap_add_attr(coap_resource_t *resource, + coap_str_const_t *name, + coap_str_const_t *value, + int flags); + +/** + * Returns @p resource's coap_attr_t object with given @p name if found, @c NULL + * otherwise. + * + * @param resource The resource to search for attribute @p name. + * @param name Name of the requested attribute as a string. + * @return The first attribute with specified @p name or @c NULL if none + * was found. + */ +coap_attr_t *coap_find_attr(coap_resource_t *resource, + coap_str_const_t *name); + +/** + * Returns @p attribute's value. + * + * @param attribute Pointer to attribute. + * + * @return Attribute's value or @c NULL. + */ +coap_str_const_t *coap_attr_get_value(coap_attr_t *attribute); + +/** + * Status word to encode the result of conditional print or copy operations such + * as coap_print_link(). The lower 28 bits of coap_print_status_t are used to + * encode the number of characters that has actually been printed, bits 28 to 31 + * encode the status. When COAP_PRINT_STATUS_ERROR is set, an error occurred + * during output. In this case, the other bits are undefined. + * COAP_PRINT_STATUS_TRUNC indicates that the output is truncated, i.e. the + * printing would have exceeded the current buffer. + */ +typedef unsigned int coap_print_status_t; + +#define COAP_PRINT_STATUS_MASK 0xF0000000u +#define COAP_PRINT_OUTPUT_LENGTH(v) ((v) & ~COAP_PRINT_STATUS_MASK) +#define COAP_PRINT_STATUS_ERROR 0x80000000u +#define COAP_PRINT_STATUS_TRUNC 0x40000000u + +/** + * Writes a description of this resource in link-format to given text buffer. @p + * len must be initialized to the maximum length of @p buf and will be set to + * the number of characters actually written if successful. This function + * returns @c 1 on success or @c 0 on error. + * + * @param resource The resource to describe. + * @param buf The output buffer to write the description to. + * @param len Must be initialized to the length of @p buf and + * will be set to the length of the printed link description. + * @param offset The offset within the resource description where to + * start writing into @p buf. This is useful for dealing + * with the Block2 option. @p offset is updated during + * output as it is consumed. + * + * @return If COAP_PRINT_STATUS_ERROR is set, an error occured. Otherwise, + * the lower 28 bits will indicate the number of characters that + * have actually been output into @p buffer. The flag + * COAP_PRINT_STATUS_TRUNC indicates that the output has been + * truncated. + */ +coap_print_status_t coap_print_link(const coap_resource_t *resource, + unsigned char *buf, + size_t *len, + size_t *offset); + +/** @} */ + +/** + * Returns the resource identified by the unique string @p uri_path. If no + * resource was found, this function returns @c NULL. + * + * @param context The context to look for this resource. + * @param uri_path The unique string uri of the resource. + * + * @return A pointer to the resource or @c NULL if not found. + */ +coap_resource_t *coap_get_resource_from_uri_path(coap_context_t *context, + coap_str_const_t *uri_path); + +/** + * @deprecated use coap_resource_notify_observers() instead. + */ +COAP_DEPRECATED int +coap_resource_set_dirty(coap_resource_t *r, + const coap_string_t *query); + +#endif /* COAP_RESOURCE_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/str.h b/examples/espidf-coap-server/components/libcoap/include/coap3/str.h new file mode 100644 index 000000000..f9ea4f1f7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/str.h @@ -0,0 +1,210 @@ +/* + * str.h -- strings to be used in the CoAP library + * + * Copyright (C) 2010-2011 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file str.h + * @brief Strings to be used in the CoAP library + */ + +#ifndef COAP_STR_H_ +#define COAP_STR_H_ + +#include + + +/** + * @ingroup application_api + * @defgroup string String handling support + * API for handling strings and binary data + * @{ + */ + +/* + * Note: string and binary use equivalent objects. + * string is likely to contain readable textual information, binary will not. + */ + +/** + * CoAP string data definition + */ +typedef struct coap_string_t { + size_t length; /**< length of string */ + uint8_t *s; /**< string data */ +} coap_string_t; + +/** + * CoAP string data definition with const data + */ +typedef struct coap_str_const_t { + size_t length; /**< length of string */ + const uint8_t *s; /**< read-only string data */ +} coap_str_const_t; + +#define COAP_SET_STR(st,l,v) { (st)->length = (l), (st)->s = (v); } + +/** + * CoAP binary data definition + */ +typedef struct coap_binary_t { + size_t length; /**< length of binary data */ + uint8_t *s; /**< binary data */ +} coap_binary_t; + +/** + * CoAP binary data definition with const data + */ +typedef struct coap_bin_const_t { + size_t length; /**< length of binary data */ + const uint8_t *s; /**< read-only binary data */ +} coap_bin_const_t; + +/** + * Returns a new string object with at least size+1 bytes storage allocated. + * It is the responsibility of the caller to fill in all the appropriate + * information. + * The string must be released using coap_delete_string(). + * + * @param size The size to allocate for the string data. + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_string_t *coap_new_string(size_t size); + +/** + * Deletes the given string and releases any memory allocated. + * + * @param string The string to free off. + */ +void coap_delete_string(coap_string_t *string); + +/** + * Returns a new const string object with at least size+1 bytes storage + * allocated, and the provided data copied into the string object. + * The string must be released using coap_delete_str_const(). + * + * @param data The data to put in the new string object. + * @param size The size to allocate for the binary string data. + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_str_const_t *coap_new_str_const(const uint8_t *data, size_t size); + +/** + * Deletes the given const string and releases any memory allocated. + * + * @param string The string to free off. + */ +void coap_delete_str_const(coap_str_const_t *string); + +/** + * Returns a new binary object with at least size bytes storage allocated. + * It is the responsibility of the caller to fill in all the appropriate + * information. + * The coap_binary_t object must be released using coap_delete_binary(). + * + * @param size The size to allocate for the binary data. + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_binary_t *coap_new_binary(size_t size); + +/** + * Deletes the given coap_binary_t object and releases any memory allocated. + * + * @param binary The coap_binary_t object to free off. + */ +void coap_delete_binary(coap_binary_t *binary); + +/** + * Resizes the given coap_binary_t object. + * It is the responsibility of the caller to fill in all the appropriate + * additional information. + * + * Note: If there is an error, @p binary will separately need to be released by + * coap_delete_binary(). + * + * @param binary The coap_binary_t object to resize. + * @param new_size The new size to allocate for the binary data. + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_binary_t *coap_resize_binary(coap_binary_t *binary, size_t new_size); + +/** + * Take the specified byte array (text) and create a coap_bin_const_t * + * Returns a new const binary object with at least size bytes storage + * allocated, and the provided data copied into the binary object. + * The binary data must be released using coap_delete_bin_const(). + * + * @param data The data to put in the new string object. + * @param size The size to allocate for the binary data. + * + * @return A pointer to the new object or @c NULL on error. + */ +coap_bin_const_t *coap_new_bin_const(const uint8_t *data, size_t size); + +/** + * Deletes the given const binary data and releases any memory allocated. + * + * @param binary The binary data to free off. + */ +void coap_delete_bin_const(coap_bin_const_t *binary); + +#ifndef COAP_MAX_STR_CONST_FUNC +#define COAP_MAX_STR_CONST_FUNC 2 +#endif /* COAP_MAX_STR_CONST_FUNC */ + +/** + * Take the specified byte array (text) and create a coap_str_const_t * + * + * Note: the array is 2 deep as there are up to two callings of + * coap_make_str_const in a function call. e.g. coap_add_attr(). + * Caution: If there are local variable assignments, these will cycle around + * the var[COAP_MAX_STR_CONST_FUNC] set. No current examples do this. + * + * @param string The const string to convert to a coap_str_const_t * + * + * @return A pointer to one of two static variables containing the + * coap_str_const_t * result + */ +coap_str_const_t *coap_make_str_const(const char *string); + +/** + * Compares the two strings for equality + * + * @param string1 The first string. + * @param string2 The second string. + * + * @return @c 1 if the strings are equal + * @c 0 otherwise. + */ +#define coap_string_equal(string1,string2) \ + ((string1)->length == (string2)->length && ((string1)->length == 0 || \ + ((string1)->s && (string2)->s && \ + memcmp((string1)->s, (string2)->s, (string1)->length) == 0))) + +/** + * Compares the two binary data for equality + * + * @param binary1 The first binary data. + * @param binary2 The second binary data. + * + * @return @c 1 if the binary data is equal + * @c 0 otherwise. + */ +#define coap_binary_equal(binary1,binary2) \ + ((binary1)->length == (binary2)->length && ((binary1)->length == 0 || \ + ((binary1)->s && (binary2)->s && \ + memcmp((binary1)->s, (binary2)->s, (binary1)->length) == 0))) + +/** @} */ + +#endif /* COAP_STR_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/uri.h b/examples/espidf-coap-server/components/libcoap/include/coap3/uri.h new file mode 100644 index 000000000..02136afb8 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/uri.h @@ -0,0 +1,182 @@ +/* + * uri.h -- helper functions for URI treatment + * + * Copyright (C) 2010-2020 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file uri.h + * @brief Helper functions for URI treatment + */ + +#ifndef COAP_URI_H_ +#define COAP_URI_H_ + +#include + +#include "str.h" + +/** + * The scheme specifiers. Secure schemes have an odd numeric value, + * others are even. + */ +typedef enum coap_uri_scheme_t { + COAP_URI_SCHEME_COAP = 0, + COAP_URI_SCHEME_COAPS, /* 1 */ + COAP_URI_SCHEME_COAP_TCP, /* 2 */ + COAP_URI_SCHEME_COAPS_TCP, /* 3 */ + COAP_URI_SCHEME_HTTP, /* 4 Proxy-Uri only */ + COAP_URI_SCHEME_HTTPS /* 5 Proxy-Uri only */ +} coap_uri_scheme_t; + +/** This mask can be used to check if a parsed URI scheme is secure. */ +#define COAP_URI_SCHEME_SECURE_MASK 0x01 + +/** + * Representation of parsed URI. Components may be filled from a string with + * coap_split_uri() or coap_split_proxy_uri() and can be used as input for + * option-creation functions. + */ +typedef struct { + coap_str_const_t host; /**< host part of the URI */ + uint16_t port; /**< The port in host byte order */ + coap_str_const_t path; /**< Beginning of the first path segment. + Use coap_split_path() to create Uri-Path options */ + coap_str_const_t query; /**< The query part if present */ + + /** The parsed scheme specifier. */ + enum coap_uri_scheme_t scheme; +} coap_uri_t; + +static inline int +coap_uri_scheme_is_secure(const coap_uri_t *uri) { + return uri && ((uri->scheme & COAP_URI_SCHEME_SECURE_MASK) != 0); +} + +/** + * Creates a new coap_uri_t object from the specified URI. Returns the new + * object or NULL on error. The memory allocated by the new coap_uri_t + * must be released using coap_free(). + * + * @param uri The URI path to copy. + * @param length The length of uri. + * + * @return New URI object or NULL on error. + */ +coap_uri_t *coap_new_uri(const uint8_t *uri, unsigned int length); + +/** + * Clones the specified coap_uri_t object. Thie function allocates sufficient + * memory to hold the coap_uri_t structure and its contents. The object must + * be released with coap_free(). */ +coap_uri_t *coap_clone_uri(const coap_uri_t *uri); + +/** + * @ingroup application_api + * @defgroup uri_parse URI Parsing Functions + * API for parsing URIs. + * CoAP PDUs contain normalized URIs with their path and query split into + * multiple segments. The functions in this module help splitting strings. + * @{ + */ + +/** + * Parses a given string into URI components. The identified syntactic + * components are stored in the result parameter @p uri. Optional URI + * components that are not specified will be set to { 0, 0 }, except for the + * port which is set to the default port for the protocol. This function + * returns @p 0 if parsing succeeded, a value less than zero otherwise. + * + * @param str_var The string to split up. + * @param len The actual length of @p str_var + * @param uri The coap_uri_t object to store the result. + * + * @return @c 0 on success, or < 0 on error. + * + */ +int coap_split_uri(const uint8_t *str_var, size_t len, coap_uri_t *uri); + +/** + * Parses a given string into URI components. The identified syntactic + * components are stored in the result parameter @p uri. Optional URI + * components that are not specified will be set to { 0, 0 }, except for the + * port which is set to default port for the protocol. This function returns + * @p 0 if parsing succeeded, a value less than zero otherwise. + * Note: This function enforces that the given string is in Proxy-Uri format + * as well as supports different schema such as http. + * + * @param str_var The string to split up. + * @param len The actual length of @p str_var + * @param uri The coap_uri_t object to store the result. + * + * @return @c 0 on success, or < 0 on error. + * + */ +int coap_split_proxy_uri(const uint8_t *str_var, size_t len, coap_uri_t *uri); + +/** + * Splits the given URI path into segments. Each segment is preceded + * by an option pseudo-header with delta-value 0 and the actual length + * of the respective segment after percent-decoding. + * + * @param s The path string to split. + * @param length The actual length of @p s. + * @param buf Result buffer for parsed segments. + * @param buflen Maximum length of @p buf. Will be set to the actual number + * of bytes written into buf on success. + * + * @return The number of segments created or @c -1 on error. + */ +int coap_split_path(const uint8_t *s, + size_t length, + unsigned char *buf, + size_t *buflen); + +/** + * Splits the given URI query into segments. Each segment is preceded + * by an option pseudo-header with delta-value 0 and the actual length + * of the respective query term. + * + * @param s The query string to split. + * @param length The actual length of @p s. + * @param buf Result buffer for parsed segments. + * @param buflen Maximum length of @p buf. Will be set to the actual number + * of bytes written into buf on success. + * + * @return The number of segments created or @c -1 on error. + * + * @bug This function does not reserve additional space for delta > 12. + */ +int coap_split_query(const uint8_t *s, + size_t length, + unsigned char *buf, + size_t *buflen); + +/** + * Extract query string from request PDU according to escape rules in 6.5.8. + * @param request Request PDU. + * @return Reconstructed and escaped query string part or @c NULL if + * no query was contained in @p request. The coap_string_t + * object returned by this function must be released with + * coap_delete_string. + */ +coap_string_t *coap_get_query(const coap_pdu_t *request); + +/** + * Extract uri_path string from request PDU + * @param request Request PDU. + * @return Reconstructed and escaped uri path string part or @c NULL + * if no URI-Path was contained in @p request. The + * coap_string_t object returned by this function must be + * released with coap_delete_string. + */ +coap_string_t *coap_get_uri_path(const coap_pdu_t *request); + +/** @} */ + +#endif /* COAP_URI_H_ */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/uthash.h b/examples/espidf-coap-server/components/libcoap/include/coap3/uthash.h new file mode 100644 index 000000000..9a396b617 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/uthash.h @@ -0,0 +1,1136 @@ +/* +Copyright (c) 2003-2021, Troy D. Hanson http://troydhanson.github.io/uthash/ +All rights reserved. + +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. + +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. +*/ + +#ifndef UTHASH_H +#define UTHASH_H + +#define UTHASH_VERSION 2.3.0 + +#include /* memcmp, memset, strlen */ +#include /* ptrdiff_t */ +#include /* exit */ + +#if defined(HASH_DEFINE_OWN_STDINT) && HASH_DEFINE_OWN_STDINT +/* This codepath is provided for backward compatibility, but I plan to remove it. */ +#warning "HASH_DEFINE_OWN_STDINT is deprecated; please use HASH_NO_STDINT instead" +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#elif defined(HASH_NO_STDINT) && HASH_NO_STDINT +#else +#include /* uint8_t, uint32_t */ +#endif + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if !defined(DECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#endif +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE(x) +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while (0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while (0) +#endif + +#ifndef uthash_malloc +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#endif +#ifndef uthash_free +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ +#endif +#ifndef uthash_bzero +#define uthash_bzero(a,n) memset(a,'\0',n) +#endif +#ifndef uthash_strlen +#define uthash_strlen(s) strlen(s) +#endif + +#ifndef HASH_FUNCTION +#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv) +#endif + +#ifndef HASH_KEYCMP +#define HASH_KEYCMP(a,b,n) memcmp(a,b,n) +#endif + +#ifndef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#endif +#ifndef uthash_expand_fyi +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ +#endif + +#ifndef HASH_NONFATAL_OOM +#define HASH_NONFATAL_OOM 0 +#endif + +#if HASH_NONFATAL_OOM +/* malloc failures can be recovered from */ + +#ifndef uthash_nonfatal_oom +#define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0) +#define IF_HASH_NONFATAL_OOM(x) x + +#else +/* malloc failures result in lost memory, hash tables are unusable */ + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory") +#define IF_HASH_NONFATAL_OOM(x) + +#endif + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhp */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) +/* calculate the hash handle from element address elp */ +#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle*)(void*)(((char*)(elp)) + ((tbl)->hho))) + +#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ +do { \ + struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ + unsigned _hd_bkt; \ + HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + (head)->hh.tbl->buckets[_hd_bkt].count++; \ + _hd_hh_item->hh_next = NULL; \ + _hd_hh_item->hh_prev = NULL; \ +} while (0) + +#define HASH_VALUE(keyptr,keylen,hashv) \ +do { \ + HASH_FUNCTION(keyptr, keylen, hashv); \ +} while (0) + +#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ + } \ + } \ +} while (0) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ + } \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl,oomed) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!(tbl)->bloom_bv) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ + } \ +} while (0) + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0) + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) + +#else +#define HASH_BLOOM_MAKE(tbl,oomed) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) (1) +#define HASH_BLOOM_BYTELEN 0U +#endif + +#define HASH_MAKE_TABLE(hh,head,oomed) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \ + if (!(head)->hh.tbl) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ + if (!(head)->hh.tbl->buckets) { \ + HASH_RECORD_OOM(oomed); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } else { \ + uthash_bzero((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + uthash_free((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } \ + ) \ + } \ + } \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ +} while (0) + +#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ +} while (0) + +#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ +} while (0) + +#define HASH_APPEND_LIST(hh, head, add) \ +do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ +} while (0) + +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + do { \ + if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ + break; \ + } \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) + +#ifdef NO_DECLTYPE +#undef HASH_AKBI_INNER_LOOP +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + char *_hs_saved_head = (char*)(head); \ + do { \ + DECLTYPE_ASSIGN(head, _hs_iter); \ + if (cmpfcn(head, add) > 0) { \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + break; \ + } \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) +#endif + +#if HASH_NONFATAL_OOM + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + if (!(oomed)) { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + if (oomed) { \ + HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ + HASH_DELETE_HH(hh, head, &(add)->hh); \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } else { \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + } \ + } else { \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } \ +} while (0) + +#else + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ +} while (0) + +#endif + + +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + void *_hs_iter = (head); \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ +} while (0) + +#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ +do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) + +#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) + +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (const void*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ +} while (0) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) + +#define HASH_TO_BKT(hashv,num_bkts,bkt) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1U)); \ +} while (0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ + HASH_DELETE_HH(hh, head, &(delptr)->hh) + +#define HASH_DELETE_HH(hh,head,delptrhh) \ +do { \ + struct UT_hash_handle *_hd_hh_del = (delptrhh); \ + if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } else { \ + unsigned _hd_bkt; \ + if (_hd_hh_del == (head)->hh.tbl->tail) { \ + (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ + } \ + if (_hd_hh_del->prev != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ + } else { \ + DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ + } \ + HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ +} while (0) + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ +do { \ + unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \ + HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ +} while (0) +#define HASH_ADD_STR(head,strfield,add) \ +do { \ + unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ +} while (0) +#define HASH_REPLACE_STR(head,strfield,add,replaced) \ +do { \ + unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ +} while (0) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_REPLACE_INT(head,intfield,add,replaced) \ + HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ + HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#include /* fprintf, stderr */ +#define HASH_OOPS(...) do { fprintf(stderr, __VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head,where) \ +do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ + unsigned _bkt_i; \ + unsigned _count = 0; \ + char *_prev; \ + for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ + (where), (void*)_thh->hh_prev, (void*)_prev); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \ + (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev != (char*)_thh->prev) { \ + HASH_OOPS("%s: invalid prev %p, actual %p\n", \ + (where), (void*)_thh->prev, (void*)_prev); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head,where) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ +#define HASH_BER(key,keylen,hashv) \ +do { \ + unsigned _hb_keylen = (unsigned)keylen; \ + const unsigned char *_hb_key = (const unsigned char*)(key); \ + (hashv) = 0; \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ +} while (0) + + +/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at + * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ +#define HASH_SAX(key,keylen,hashv) \ +do { \ + unsigned _sx_i; \ + const unsigned char *_hs_key = (const unsigned char*)(key); \ + hashv = 0; \ + for (_sx_i=0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ +} while (0) +/* FNV-1a variation */ +#define HASH_FNV(key,keylen,hashv) \ +do { \ + unsigned _fn_i; \ + const unsigned char *_hf_key = (const unsigned char*)(key); \ + (hashv) = 2166136261U; \ + for (_fn_i=0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ +} while (0) + +#define HASH_OAT(key,keylen,hashv) \ +do { \ + unsigned _ho_i; \ + const unsigned char *_ho_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ +} while (0) + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,hashv) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + unsigned const char *_hj_key=(unsigned const char*)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned)(keylen); \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ + case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ + case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \ + default: ; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ +} while (0) + +/* The Paul Hsieh hash function */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif +#define HASH_SFH(key,keylen,hashv) \ +do { \ + unsigned const char *_sfh_key=(unsigned const char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ + \ + unsigned _sfh_rem = _sfh_len & 3U; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabeu; \ + \ + /* Main loop */ \ + for (;_sfh_len > 0U; _sfh_len--) { \ + hashv += get16bits (_sfh_key); \ + _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2U*sizeof (uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + break; \ + default: ; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ +} while (0) + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ +do { \ + if ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ + if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \ + break; \ + } \ + } \ + if ((out)->hh.hh_next != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ + } else { \ + (out) = NULL; \ + } \ + } \ +} while (0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \ +do { \ + UT_hash_bucket *_ha_head = &(head); \ + _ha_head->count++; \ + (addhh)->hh_next = _ha_head->hh_head; \ + (addhh)->hh_prev = NULL; \ + if (_ha_head->hh_head != NULL) { \ + _ha_head->hh_head->hh_prev = (addhh); \ + } \ + _ha_head->hh_head = (addhh); \ + if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \ + && !(addhh)->tbl->noexpand) { \ + HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + HASH_DEL_IN_BKT(head,addhh); \ + } \ + ) \ + } \ +} while (0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(head,delhh) \ +do { \ + UT_hash_bucket *_hd_head = &(head); \ + _hd_head->count--; \ + if (_hd_head->hh_head == (delhh)) { \ + _hd_head->hh_head = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_prev) { \ + (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_next) { \ + (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ + } \ +} while (0) + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ + if (!_he_new_buckets) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero(_he_new_buckets, \ + sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ + (tbl)->ideal_chain_maxlen = \ + ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \ + ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ + (tbl)->nonideal_items = 0; \ + for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \ + _he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[_he_bkt]); \ + if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ + (tbl)->nonideal_items++; \ + if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \ + _he_newbkt->expand_mult++; \ + } \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { \ + _he_newbkt->hh_head->hh_prev = _he_thh; \ + } \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->num_buckets *= 2U; \ + (tbl)->log2_num_buckets++; \ + (tbl)->buckets = _he_new_buckets; \ + (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \ + ((tbl)->ineff_expands+1U) : 0U; \ + if ((tbl)->ineff_expands > 1U) { \ + (tbl)->noexpand = 1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ + } \ +} while (0) + + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ + _hs_psize++; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + if (_hs_q == NULL) { \ + break; \ + } \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else if ((cmpfcn( \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)) \ + )) <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail != NULL ) { \ + _hs_tail->next = ((_hs_e != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail != NULL) { \ + _hs_tail->next = NULL; \ + } \ + if (_hs_nmerges <= 1U) { \ + _hs_looping = 0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh, head, "HASH_SRT"); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt = NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if ((src) != NULL) { \ + for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \ + _dst_hh = (UT_hash_handle*)(void*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh != NULL) { \ + _last_elt_hh->next = _elt; \ + } \ + if ((dst) == NULL) { \ + DECLTYPE_ASSIGN(dst, _elt); \ + HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + uthash_nonfatal_oom(_elt); \ + (dst) = NULL; \ + continue; \ + } \ + ) \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \ + (dst)->hh_dst.tbl->num_items++; \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ + HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ + _dst_hh->tbl = NULL; \ + uthash_nonfatal_oom(_elt); \ + continue; \ + } \ + ) \ + HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if ((head) != NULL) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } \ +} while (0) + +#define HASH_OVERHEAD(hh,head) \ + (((head) != NULL) ? ( \ + (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ + sizeof(UT_hash_table) + \ + (HASH_BLOOM_BYTELEN))) : 0U) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) + +typedef struct UT_hash_bucket { + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1u +#define HASH_BLOOM_SIGNATURE 0xb12220f2u + +typedef struct UT_hash_table { + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + uint8_t bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle { + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + const void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ diff --git a/examples/espidf-coap-server/components/libcoap/include/coap3/utlist.h b/examples/espidf-coap-server/components/libcoap/include/coap3/utlist.h new file mode 100644 index 000000000..1979448a7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/include/coap3/utlist.h @@ -0,0 +1,1073 @@ +/* +Copyright (c) 2007-2021, Troy D. Hanson http://troydhanson.github.io/uthash/ +All rights reserved. + +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. + +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. +*/ + +#ifndef UTLIST_H +#define UTLIST_H + +#define UTLIST_VERSION 2.3.0 + +#include + +/* + * This file contains macros to manipulate singly and doubly-linked lists. + * + * 1. LL_ macros: singly-linked lists. + * 2. DL_ macros: doubly-linked lists. + * 3. CDL_ macros: circular doubly-linked lists. + * + * To use singly-linked lists, your structure must have a "next" pointer. + * To use doubly-linked lists, your structure must "prev" and "next" pointers. + * Either way, the pointer to the head of the list must be initialized to NULL. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *prev, *next; + * } + * + * struct item *list = NULL: + * + * int main() { + * struct item *item; + * ... allocate and populate item ... + * DL_APPEND(list, item); + * } + * -------------------------------------------------- + * + * For doubly-linked lists, the append and delete macros are O(1) + * For singly-linked lists, append and delete are O(n) but prepend is O(1) + * The sort macro is O(n log(n)) for all types of single/double/circular lists. + */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if !defined(LDECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define LDECLTYPE(x) decltype(x) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#endif +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#else /* GNU, Sun and other compilers */ +#define LDECLTYPE(x) __typeof(x) +#endif +#endif + +/* for VS2008 we use some workarounds to get around the lack of decltype, + * namely, we always reassign our tmp variable to the list head if we need + * to dereference its prev/next pointers, and save/restore the real head.*/ +#ifdef NO_DECLTYPE +#define IF_NO_DECLTYPE(x) x +#define LDECLTYPE(x) char* +#define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } +#define UTLIST_NEXT(elt,list,next) ((char*)((list)->next)) +#define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } +/* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */ +#define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } +#define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } +#define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } +#else +#define IF_NO_DECLTYPE(x) +#define UTLIST_SV(elt,list) +#define UTLIST_NEXT(elt,list,next) ((elt)->next) +#define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to) +/* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */ +#define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) +#define UTLIST_RS(list) +#define UTLIST_CASTASGN(a,b) (a)=(b) +#endif + +/****************************************************************************** + * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * + * Unwieldy variable names used here to avoid shadowing passed-in variables. * + *****************************************************************************/ +#define LL_SORT(list, cmp) \ + LL_SORT2(list, cmp, next) + +#define LL_SORT2(list, cmp, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ + } \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + + +#define DL_SORT(list, cmp) \ + DL_SORT2(list, cmp, prev, next) + +#define DL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if ((_ls_qsize == 0) || (!_ls_q)) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev, _ls_tail); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +#define CDL_SORT(list, cmp) \ + CDL_SORT2(list, cmp, prev, next) + +#define CDL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + UTLIST_CASTASGN(_ls_oldhead,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); \ + if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \ + _ls_q = NULL; \ + } else { \ + _ls_q = UTLIST_NEXT(_ls_q,list,next); \ + } \ + UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev,_ls_tail); \ + UTLIST_CASTASGN(_tmp,list); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +/****************************************************************************** + * singly linked list macros (non-circular) * + *****************************************************************************/ +#define LL_PREPEND(head,add) \ + LL_PREPEND2(head,add,next) + +#define LL_PREPEND2(head,add,next) \ +do { \ + (add)->next = (head); \ + (head) = (add); \ +} while (0) + +#define LL_CONCAT(head1,head2) \ + LL_CONCAT2(head1,head2,next) + +#define LL_CONCAT2(head1,head2,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head1) { \ + _tmp = (head1); \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(head2); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#define LL_APPEND(head,add) \ + LL_APPEND2(head,add,next) + +#define LL_APPEND2(head,add,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + (add)->next=NULL; \ + if (head) { \ + _tmp = (head); \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(add); \ + } else { \ + (head)=(add); \ + } \ +} while (0) + +#define LL_INSERT_INORDER(head,add,cmp) \ + LL_INSERT_INORDER2(head,add,cmp,next) + +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + LL_APPEND_ELEM2(head, _tmp, add, next); \ + } else { \ + (head) = (add); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define LL_LOWER_BOUND(head,elt,like,cmp) \ + LL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define LL_LOWER_BOUND2(head,elt,like,cmp,next) \ + do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if (cmp((elt)->next, like) >= 0) { \ + break; \ + } \ + } \ + } \ + } while (0) + +#define LL_DELETE(head,del) \ + LL_DELETE2(head,del,next) + +#define LL_DELETE2(head,del,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (del))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (del)->next; \ + } \ + } \ +} while (0) + +#define LL_COUNT(head,el,counter) \ + LL_COUNT2(head,el,counter,next) \ + +#define LL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + LL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define LL_FOREACH(head,el) \ + LL_FOREACH2(head,el,next) + +#define LL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +#define LL_FOREACH_SAFE(head,el,tmp) \ + LL_FOREACH_SAFE2(head,el,tmp,next) + +#define LL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +#define LL_SEARCH_SCALAR(head,out,field,val) \ + LL_SEARCH_SCALAR2(head,out,field,val,next) + +#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define LL_SEARCH(head,out,elt,cmp) \ + LL_SEARCH2(head,out,elt,cmp,next) + +#define LL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ +} while (0) + +#define LL_REPLACE_ELEM(head, el, add) \ + LL_REPLACE_ELEM2(head, el, add, next) + +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_PREPEND_ELEM(head, el, add) \ + LL_PREPEND_ELEM2(head, el, add, next) + +#define LL_APPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (el)->next = (add); \ + } else { \ + LL_PREPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_APPEND_ELEM(head, el, add) \ + LL_APPEND_ELEM2(head, el, add, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef LL_CONCAT2 +#define LL_CONCAT2(head1,head2,next) \ +do { \ + char *_tmp; \ + if (head1) { \ + _tmp = (char*)(head1); \ + while ((head1)->next) { (head1) = (head1)->next; } \ + (head1)->next = (head2); \ + UTLIST_RS(head1); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#undef LL_APPEND2 +#define LL_APPEND2(head,add,next) \ +do { \ + if (head) { \ + (add)->next = head; /* use add->next as a temp variable */ \ + while ((add)->next->next) { (add)->next = (add)->next->next; } \ + (add)->next->next=(add); \ + } else { \ + (head)=(add); \ + } \ + (add)->next=NULL; \ +} while (0) + +#undef LL_INSERT_INORDER2 +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, add)) >= 0) { \ + (add)->next = (head); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) + +#undef LL_DELETE2 +#define LL_DELETE2(head,del,next) \ +do { \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && ((head)->next != (del))) { \ + (head) = (head)->next; \ + } \ + if ((head)->next) { \ + (head)->next = ((del)->next); \ + } \ + UTLIST_RS(head); \ + } \ +} while (0) + +#undef LL_REPLACE_ELEM2 +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = head; \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el)->next; \ +} while (0) + +#undef LL_PREPEND_ELEM2 +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = (head); \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el); \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#endif /* NO_DECLTYPE */ + +/****************************************************************************** + * doubly linked list macros (non-circular) * + *****************************************************************************/ +#define DL_PREPEND(head,add) \ + DL_PREPEND2(head,add,prev,next) + +#define DL_PREPEND2(head,add,prev,next) \ +do { \ + (add)->next = (head); \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev = (add); \ + } else { \ + (add)->prev = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define DL_APPEND(head,add) \ + DL_APPEND2(head,add,prev,next) + +#define DL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev->next = (add); \ + (head)->prev = (add); \ + (add)->next = NULL; \ + } else { \ + (head)=(add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_INSERT_INORDER(head,add,cmp) \ + DL_INSERT_INORDER2(head,add,cmp,prev,next) + +#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + DL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_LOWER_BOUND(head,elt,like,cmp) \ + DL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define DL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) + +#define DL_CONCAT(head1,head2) \ + DL_CONCAT2(head1,head2,prev,next) + +#define DL_CONCAT2(head1,head2,prev,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head2) { \ + if (head1) { \ + UTLIST_CASTASGN(_tmp, (head2)->prev); \ + (head2)->prev = (head1)->prev; \ + (head1)->prev->next = (head2); \ + UTLIST_CASTASGN((head1)->prev, _tmp); \ + } else { \ + (head1)=(head2); \ + } \ + } \ +} while (0) + +#define DL_DELETE(head,del) \ + DL_DELETE2(head,del,prev,next) + +#define DL_DELETE2(head,del,prev,next) \ +do { \ + assert((head) != NULL); \ + assert((del)->prev != NULL); \ + if ((del)->prev == (del)) { \ + (head)=NULL; \ + } else if ((del)==(head)) { \ + (del)->next->prev = (del)->prev; \ + (head) = (del)->next; \ + } else { \ + (del)->prev->next = (del)->next; \ + if ((del)->next) { \ + (del)->next->prev = (del)->prev; \ + } else { \ + (head)->prev = (del)->prev; \ + } \ + } \ +} while (0) + +#define DL_COUNT(head,el,counter) \ + DL_COUNT2(head,el,counter,next) \ + +#define DL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + DL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define DL_FOREACH(head,el) \ + DL_FOREACH2(head,el,next) + +#define DL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +/* this version is safe for deleting the elements during iteration */ +#define DL_FOREACH_SAFE(head,el,tmp) \ + DL_FOREACH_SAFE2(head,el,tmp,next) + +#define DL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +/* these are identical to their singly-linked list counterparts */ +#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR +#define DL_SEARCH LL_SEARCH +#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 +#define DL_SEARCH2 LL_SEARCH2 + +#define DL_REPLACE_ELEM2(head, el, add, prev, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + (add)->next = (el)->next; \ + if ((el)->next == NULL) { \ + (add)->prev = (add); \ + } else { \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + } \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->prev->next = (add); \ + if ((el)->next == NULL) { \ + (head)->prev = (add); \ + } else { \ + (add)->next->prev = (add); \ + } \ + } \ +} while (0) + +#define DL_REPLACE_ELEM(head, el, add) \ + DL_REPLACE_ELEM2(head, el, add, prev, next) + +#define DL_PREPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->prev->next = (add); \ + } \ + } else { \ + DL_APPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_PREPEND_ELEM(head, el, add) \ + DL_PREPEND_ELEM2(head, el, add, prev, next) + +#define DL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } else { \ + DL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_APPEND_ELEM(head, el, add) \ + DL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef DL_INSERT_INORDER2 +#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = NULL; \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ + +/****************************************************************************** + * circular doubly linked list macros * + *****************************************************************************/ +#define CDL_APPEND(head,add) \ + CDL_APPEND2(head,add,prev,next) + +#define CDL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } \ +} while (0) + +#define CDL_PREPEND(head,add) \ + CDL_PREPEND2(head,add,prev,next) + +#define CDL_PREPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define CDL_INSERT_INORDER(head,add,cmp) \ + CDL_INSERT_INORDER2(head,add,cmp,prev,next) + +#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->next = (head); \ + (head)->prev = (head); \ + } \ +} while (0) + +#define CDL_LOWER_BOUND(head,elt,like,cmp) \ + CDL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) + +#define CDL_DELETE(head,del) \ + CDL_DELETE2(head,del,prev,next) + +#define CDL_DELETE2(head,del,prev,next) \ +do { \ + if (((head)==(del)) && ((head)->next == (head))) { \ + (head) = NULL; \ + } else { \ + (del)->next->prev = (del)->prev; \ + (del)->prev->next = (del)->next; \ + if ((del) == (head)) (head)=(del)->next; \ + } \ +} while (0) + +#define CDL_COUNT(head,el,counter) \ + CDL_COUNT2(head,el,counter,next) \ + +#define CDL_COUNT2(head, el, counter,next) \ +do { \ + (counter) = 0; \ + CDL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define CDL_FOREACH(head,el) \ + CDL_FOREACH2(head,el,next) + +#define CDL_FOREACH2(head,el,next) \ + for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next)) + +#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ + CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) + +#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ + for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \ + (el) && ((tmp2) = (el)->next, 1); \ + (el) = ((el) == (tmp1) ? NULL : (tmp2))) + +#define CDL_SEARCH_SCALAR(head,out,field,val) \ + CDL_SEARCH_SCALAR2(head,out,field,val,next) + +#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define CDL_SEARCH(head,out,elt,cmp) \ + CDL_SEARCH2(head,out,elt,cmp,next) + +#define CDL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((el)->next == (el)) { \ + (add)->next = (add); \ + (add)->prev = (add); \ + (head) = (add); \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } \ +} while (0) + +#define CDL_REPLACE_ELEM(head, el, add) \ + CDL_REPLACE_ELEM2(head, el, add, prev, next) + +#define CDL_PREPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } else { \ + CDL_APPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_PREPEND_ELEM(head, el, add) \ + CDL_PREPEND_ELEM2(head, el, add, prev, next) + +#define CDL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + (add)->next->prev = (add); \ + } else { \ + CDL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_APPEND_ELEM(head, el, add) \ + CDL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef CDL_INSERT_INORDER2 +#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (add)->prev->next = (add); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (add)->next->prev = (add); \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ + +#endif /* UTLIST_H */ diff --git a/examples/espidf-coap-server/components/libcoap/libcoap-3.map b/examples/espidf-coap-server/components/libcoap/libcoap-3.map new file mode 100644 index 000000000..5d3dc00de --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/libcoap-3.map @@ -0,0 +1,252 @@ +VER_3 { +global: + coap_add_attr; + coap_add_block; + coap_add_block_b_data; + coap_add_data; + coap_add_data_after; + coap_add_data_blocked_response; + coap_add_data_large_request; + coap_add_data_large_response; + coap_add_option; + coap_add_optlist_pdu; + coap_add_resource; + coap_address_equals; + coap_address_get_port; + coap_address_init; + coap_address_set_port; + coap_add_token; + coap_async_get_app_data; + coap_async_is_supported; + coap_async_set_app_data; + coap_async_set_delay; + coap_async_trigger; + coap_attr_get_value; + coap_block_build_body; + coap_cache_derive_key; + coap_cache_derive_key_w_ignore; + coap_cache_get_app_data; + coap_cache_get_by_key; + coap_cache_get_by_pdu; + coap_cache_get_pdu; + coap_cache_ignore_options; + coap_cache_set_app_data; + coap_cancel_observe; + coap_can_exit; + coap_check_option; + coap_cleanup; + coap_clear_event_handler; + coap_clock_init; + coap_clone_uri; + coap_context_get_coap_fd; + coap_context_get_csm_max_message_size; + coap_context_get_csm_timeout; + coap_context_get_max_handshake_sessions; + coap_context_get_max_idle_sessions; + coap_context_get_session_timeout; + coap_context_set_block_mode; + coap_context_set_csm_max_message_size; + coap_context_set_csm_timeout; + coap_context_set_keepalive; + coap_context_set_max_handshake_sessions; + coap_context_set_max_idle_sessions; + coap_context_set_pki; + coap_context_set_pki_root_cas; + coap_context_set_psk; + coap_context_set_psk2; + coap_context_set_session_timeout; + coap_debug_send_packet; + coap_debug_set_packet_loss; + coap_decode_var_bytes; + coap_decode_var_bytes8; + coap_delete_binary; + coap_delete_bin_const; + coap_delete_cache_entry; + coap_delete_cache_key; + coap_delete_optlist; + coap_delete_pdu; + coap_delete_resource; + coap_delete_str_const; + coap_delete_string; + coap_dtls_get_log_level; + coap_dtls_is_supported; + coap_dtls_set_log_level; + coap_encode_var_safe; + coap_encode_var_safe8; + coap_endpoint_set_default_mtu; + coap_endpoint_str; + coap_find_async; + coap_find_attr; + coap_fls; + coap_flsll; + coap_free_async; + coap_free_context; + coap_free_endpoint; + coap_free_type; + coap_get_app_data; + coap_get_block; + coap_get_block_b; + coap_get_data; + coap_get_data_large; + coap_get_log_level; + coap_get_query; + coap_get_resource_from_uri_path; + coap_get_tls_library_version; + coap_get_uri_path; + coap_handle_event; + coap_hash_impl; + coap_insert_optlist; + coap_io_do_epoll; + coap_io_do_io; + coap_io_prepare_epoll; + coap_io_prepare_io; + coap_io_process; + coap_io_process_with_fds; + coap_is_mcast; + coap_join_mcast_group_intf; + coap_log_impl; + coap_make_str_const; + coap_malloc_type; + coap_mcast_per_resource; + coap_mcast_set_hops; + coap_memory_init; + coap_new_binary; + coap_new_bin_const; + coap_new_cache_entry; + coap_new_client_session; + coap_new_client_session_pki; + coap_new_client_session_psk; + coap_new_client_session_psk2; + coap_new_context; + coap_new_endpoint; + coap_new_error_response; + coap_new_message_id; + coap_new_optlist; + coap_new_pdu; + coap_new_str_const; + coap_new_string; + coap_new_uri; + coap_opt_block_num; + coap_opt_encode; + coap_opt_encode_size; + coap_option_filter_clear; + coap_option_filter_get; + coap_option_filter_set; + coap_option_filter_unset; + coap_option_iterator_init; + coap_option_next; + coap_opt_length; + coap_opt_parse; + coap_opt_setheader; + coap_opt_size; + coap_opt_value; + coap_package_build; + coap_package_name; + coap_package_version; + coap_pdu_duplicate; + coap_pdu_get_code; + coap_pdu_get_mid; + coap_pdu_get_token; + coap_pdu_get_type; + coap_pdu_init; + coap_pdu_parse; + coap_pdu_set_code; + coap_pdu_set_mid; + coap_pdu_set_type; + coap_print_addr; + coap_print_link; + coap_prng; + coap_prng_init; + coap_realloc_type; + coap_register_async; + coap_register_event_handler; + coap_register_handler; + coap_register_nack_handler; + coap_register_option; + coap_register_ping_handler; + coap_register_pong_handler; + coap_register_request_handler; + coap_register_response_handler; + coap_resize_binary; + coap_resource_get_uri_path; + coap_resource_get_userdata; + coap_resource_init; + coap_resource_notify_observers; + coap_resource_proxy_uri_init; + coap_resource_proxy_uri_init2; + coap_resource_release_userdata_handler; + coap_resource_set_dirty; + coap_resource_set_get_observable; + coap_resource_set_mode; + coap_resource_set_userdata; + coap_resource_unknown_init; + coap_resource_unknown_init2; + coap_response_phrase; + coap_send; + coap_send_ack; + coap_send_error; + coap_send_message_type; + coap_session_disconnected; + coap_session_get_ack_random_factor; + coap_session_get_ack_timeout; + coap_session_get_addr_local; + coap_session_get_addr_remote; + coap_session_get_app_data; + coap_session_get_by_peer; + coap_session_get_context; + coap_session_get_default_leisure; + coap_session_get_ifindex; + coap_session_get_max_retransmit; + coap_session_get_nstart; + coap_session_get_probing_rate; + coap_session_get_proto; + coap_session_get_psk_hint; + coap_session_get_psk_identity; + coap_session_get_psk_key; + coap_session_get_state; + coap_session_get_tls; + coap_session_get_type; + coap_session_init_token; + coap_session_max_pdu_size; + coap_session_new_token; + coap_session_reference; + coap_session_release; + coap_session_send_ping; + coap_session_set_ack_random_factor; + coap_session_set_ack_timeout; + coap_session_set_app_data; + coap_session_set_default_leisure; + coap_session_set_max_retransmit; + coap_session_set_mtu; + coap_session_set_no_observe_cancel; + coap_session_set_nstart; + coap_session_set_probing_rate; + coap_session_set_type_client; + coap_session_str; + coap_set_app_data; + coap_set_event_handler; + coap_set_log_handler; + coap_set_log_level; + coap_set_prng; + coap_set_show_pdu_output; + coap_show_pdu; + coap_show_tls_version; + coap_socket_strerror; + coap_split_path; + coap_split_proxy_uri; + coap_split_query; + coap_split_uri; + coap_startup; + coap_string_tls_support; + coap_string_tls_version; + coap_tcp_is_supported; + coap_ticks; + coap_ticks_from_rt_us; + coap_ticks_to_rt; + coap_ticks_to_rt_us; + coap_tls_is_supported; + coap_write_block_b_opt; + coap_write_block_opt; +local: + *; +}; diff --git a/examples/espidf-coap-server/components/libcoap/libcoap-3.pc.in b/examples/espidf-coap-server/components/libcoap/libcoap-3.pc.in new file mode 100644 index 000000000..26e2fc691 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/libcoap-3.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: @PACKAGE_NAME@ +Description: C-Implementation of CoAP. +Version: @PACKAGE_VERSION@ +URL: @PACKAGE_URL@ +Libs: -L${libdir} -lcoap-@LIBCOAP_NAME_SUFFIX@ +Libs.private: @DTLS_LIBS@ +Cflags: -I${includedir} diff --git a/examples/espidf-coap-server/components/libcoap/libcoap-3.sym b/examples/espidf-coap-server/components/libcoap/libcoap-3.sym new file mode 100644 index 000000000..b56071e00 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/libcoap-3.sym @@ -0,0 +1,247 @@ +coap_add_attr +coap_add_block +coap_add_block_b_data +coap_add_data +coap_add_data_after +coap_add_data_blocked_response +coap_add_data_large_request +coap_add_data_large_response +coap_add_option +coap_add_optlist_pdu +coap_add_resource +coap_address_equals +coap_address_get_port +coap_address_init +coap_address_set_port +coap_add_token +coap_async_get_app_data +coap_async_is_supported +coap_async_set_app_data +coap_async_set_delay +coap_async_trigger +coap_attr_get_value +coap_block_build_body +coap_cache_derive_key +coap_cache_derive_key_w_ignore +coap_cache_get_app_data +coap_cache_get_by_key +coap_cache_get_by_pdu +coap_cache_get_pdu +coap_cache_ignore_options +coap_cache_set_app_data +coap_cancel_observe +coap_can_exit +coap_check_option +coap_cleanup +coap_clear_event_handler +coap_clock_init +coap_clone_uri +coap_context_get_coap_fd +coap_context_get_csm_max_message_size +coap_context_get_csm_timeout +coap_context_get_max_handshake_sessions +coap_context_get_max_idle_sessions +coap_context_get_session_timeout +coap_context_set_block_mode +coap_context_set_csm_max_message_size +coap_context_set_csm_timeout +coap_context_set_keepalive +coap_context_set_max_handshake_sessions +coap_context_set_max_idle_sessions +coap_context_set_pki +coap_context_set_pki_root_cas +coap_context_set_psk +coap_context_set_psk2 +coap_context_set_session_timeout +coap_debug_send_packet +coap_debug_set_packet_loss +coap_decode_var_bytes +coap_decode_var_bytes8 +coap_delete_binary +coap_delete_bin_const +coap_delete_cache_entry +coap_delete_cache_key +coap_delete_optlist +coap_delete_pdu +coap_delete_resource +coap_delete_str_const +coap_delete_string +coap_dtls_get_log_level +coap_dtls_is_supported +coap_dtls_set_log_level +coap_encode_var_safe +coap_encode_var_safe8 +coap_endpoint_set_default_mtu +coap_endpoint_str +coap_find_async +coap_find_attr +coap_fls +coap_flsll +coap_free_async +coap_free_context +coap_free_endpoint +coap_free_type +coap_get_app_data +coap_get_block +coap_get_block_b +coap_get_data +coap_get_data_large +coap_get_log_level +coap_get_query +coap_get_resource_from_uri_path +coap_get_tls_library_version +coap_get_uri_path +coap_handle_event +coap_hash_impl +coap_insert_optlist +coap_io_do_epoll +coap_io_do_io +coap_io_prepare_epoll +coap_io_prepare_io +coap_io_process +coap_io_process_with_fds +coap_is_mcast +coap_join_mcast_group_intf +coap_log_impl +coap_make_str_const +coap_malloc_type +coap_mcast_per_resource +coap_mcast_set_hops +coap_memory_init +coap_new_binary +coap_new_bin_const +coap_new_cache_entry +coap_new_client_session +coap_new_client_session_pki +coap_new_client_session_psk +coap_new_client_session_psk2 +coap_new_context +coap_new_endpoint +coap_new_error_response +coap_new_message_id +coap_new_optlist +coap_new_pdu +coap_new_str_const +coap_new_string +coap_new_uri +coap_opt_block_num +coap_opt_encode +coap_opt_encode_size +coap_option_filter_clear +coap_option_filter_get +coap_option_filter_set +coap_option_filter_unset +coap_option_iterator_init +coap_option_next +coap_opt_length +coap_opt_parse +coap_opt_setheader +coap_opt_size +coap_opt_value +coap_package_build +coap_package_name +coap_package_version +coap_pdu_duplicate +coap_pdu_get_code +coap_pdu_get_mid +coap_pdu_get_token +coap_pdu_get_type +coap_pdu_init +coap_pdu_parse +coap_pdu_set_code +coap_pdu_set_mid +coap_pdu_set_type +coap_print_addr +coap_print_link +coap_prng +coap_prng_init +coap_realloc_type +coap_register_async +coap_register_event_handler +coap_register_handler +coap_register_nack_handler +coap_register_option +coap_register_ping_handler +coap_register_pong_handler +coap_register_request_handler +coap_register_response_handler +coap_resize_binary +coap_resource_get_uri_path +coap_resource_get_userdata +coap_resource_init +coap_resource_notify_observers +coap_resource_proxy_uri_init +coap_resource_proxy_uri_init2 +coap_resource_release_userdata_handler +coap_resource_set_dirty +coap_resource_set_get_observable +coap_resource_set_mode +coap_resource_set_userdata +coap_resource_unknown_init +coap_resource_unknown_init2 +coap_response_phrase +coap_send +coap_send_ack +coap_send_error +coap_send_message_type +coap_session_disconnected +coap_session_get_ack_random_factor +coap_session_get_ack_timeout +coap_session_get_addr_local +coap_session_get_addr_remote +coap_session_get_app_data +coap_session_get_by_peer +coap_session_get_context +coap_session_get_default_leisure +coap_session_get_ifindex +coap_session_get_max_retransmit +coap_session_get_nstart +coap_session_get_probing_rate +coap_session_get_proto +coap_session_get_psk_hint +coap_session_get_psk_identity +coap_session_get_psk_key +coap_session_get_state +coap_session_get_tls +coap_session_get_type +coap_session_init_token +coap_session_max_pdu_size +coap_session_new_token +coap_session_reference +coap_session_release +coap_session_send_ping +coap_session_set_ack_random_factor +coap_session_set_ack_timeout +coap_session_set_app_data +coap_session_set_default_leisure +coap_session_set_max_retransmit +coap_session_set_mtu +coap_session_set_no_observe_cancel +coap_session_set_nstart +coap_session_set_probing_rate +coap_session_set_type_client +coap_session_str +coap_set_app_data +coap_set_event_handler +coap_set_log_handler +coap_set_log_level +coap_set_prng +coap_set_show_pdu_output +coap_show_pdu +coap_show_tls_version +coap_socket_strerror +coap_split_path +coap_split_proxy_uri +coap_split_query +coap_split_uri +coap_startup +coap_string_tls_support +coap_string_tls_version +coap_tcp_is_supported +coap_ticks +coap_ticks_from_rt_us +coap_ticks_to_rt +coap_ticks_to_rt_us +coap_tls_is_supported +coap_write_block_b_opt +coap_write_block_opt diff --git a/examples/espidf-coap-server/components/libcoap/m4/ac_check_cryptolibs.m4 b/examples/espidf-coap-server/components/libcoap/m4/ac_check_cryptolibs.m4 new file mode 100644 index 000000000..2ae862954 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/m4/ac_check_cryptolibs.m4 @@ -0,0 +1,84 @@ +# +# SYNOPSIS +# +# AX_CHECK_{GNUTLS|OPENSSL}_VERSION +# +# DESCRIPTION +# +# This m4 file contains helper functions for checking the version of the +# respective cryptographic library version of GnuTLS, Mbed TLS or OpenSSL on +# the host. The variables '$gnutls_version_required', +# '$mbedtls_version_required' and '$openssl_version_required' hold the +# minimum required version and are set up externaly in configure.ac. +# +# Example: +# +# AX_CHECK_GNUTLS_VERSION +# or +# AX_CHECK_OPENSSL_VERSION +# +# LICENSE +# +# Copyright (c) 2017 Carsten Schoenert +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +AC_DEFUN([AX_CHECK_GNUTLS_VERSION], + [AC_MSG_CHECKING([for compatible GnuTLS version (>= $gnutls_version_required)]) + AS_VERSION_COMPARE([$gnutls_version], + [$gnutls_version_required], + [AC_MSG_RESULT([no]) + GNUTLSV=""], + [AC_MSG_RESULT([yes $gnutls_version]) + GNUTLSV="$gnutls_version"], + [AC_MSG_RESULT([yes $gnutls_version]) + GNUTLSV="$gnutls_version"]) + if test "x$GNUTLSV" = "x"; then + AC_MSG_ERROR([==> GnuTLS $gnutls_version too old. GnuTLS >= $gnutls_version_required required for suitable DTLS support build.]) + fi +]) dnl AX_CHECK_GNUTLS_VERSION + +AC_DEFUN([AX_CHECK_OPENSSL_VERSION], + [AC_MSG_CHECKING([for compatible OpenSSL version (>= $openssl_version_required)]) + AS_VERSION_COMPARE([$openssl_version], [$openssl_version_required], + [AC_MSG_RESULT([no]) + OPENSSLV=""], + [AC_MSG_RESULT([yes $openssl_version]) + OPENSSLV="$openssl_version"], + [AC_MSG_RESULT([yes $openssl_version]) + OPENSSLV="$openssl_version"]) + if test "x$OPENSSLV" = "x"; then + AC_MSG_ERROR([==> OpenSSL $openssl_version too old. OpenSSL >= $openssl_version_required required for suitable DTLS support build.]) + fi +]) dnl AX_CHECK_OPENSSL_VERSION + +AC_DEFUN([AX_CHECK_MBEDTLS_VERSION], + [AC_MSG_CHECKING([for compatible Mbed TLS version (>= $mbedtls_version_required)]) + AS_VERSION_COMPARE([$mbedtls_version], [$mbedtls_version_required], + [AC_MSG_RESULT([no]) + MBEDTLSV=""], + [AC_MSG_RESULT([yes $mbedtls_version]) + MBEDTLSV="$mbedtls_version"], + [AC_MSG_RESULT([yes $mbedtls_version]) + MBEDTLSV="$mbedtls_version"]) + if test "x$MBEDTLSV" = "x"; then + AC_MSG_ERROR([==> Mbed TLS $mbedtls_version too old. Mbed TLS >= $mbedtls_version_required required for suitable DTLS support build.]) + fi +]) dnl AX_CHECK_MBEDTLS_VERSION + +AC_DEFUN([AX_CHECK_TINYDTLS_VERSION], + [AC_MSG_CHECKING([for compatible TinyDTLS version (>= $tinydtls_version_required)]) + AS_VERSION_COMPARE([$tinydtls_version], [$tinydtls_version_required], + [AC_MSG_RESULT([no]) + TINYDTLSV=""], + [AC_MSG_RESULT([yes $tinydtls_version]) + TINYDTLSV="$tinydtls_version"], + [AC_MSG_RESULT([yes $tinydtls_version]) + TINYDTLSV="$tinydtls_version"]) + if test "x$TINYDTLSV" = "x"; then + AC_MSG_ERROR([==> TinyDTLS $tinydtls_version too old. TinyDTLS >= $tinydtls_version_required required for suitable DTLS support build.]) + fi +]) dnl AX_CHECK_TINYDTLS_VERSION diff --git a/examples/espidf-coap-server/components/libcoap/m4/ax_check_a2x_to_man.m4 b/examples/espidf-coap-server/components/libcoap/m4/ax_check_a2x_to_man.m4 new file mode 100644 index 000000000..61e95d0ae --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/m4/ax_check_a2x_to_man.m4 @@ -0,0 +1,57 @@ +# +# SYNOPSIS +# +# AX_CHECK_A2X_TO_MANPAGE([action-if-positive [, action-if-negative]]) +# +# DESCRIPTION +# +# This macro checks if an installed a2x can be used to create manual +# pages. +# +# Examples: +# +# AX_CHECK_A2X_TO_MANPAGE +# or +# AX_CHECK_A2X_TO_MANPAGE([], [AC_MSG_ERROR([docbook-xml is missing])]) +# +# LICENSE +# +# Copyright (c) 2018 Olaf Bergmann +# +# This file is part of the CoAP library libcoap. Please see README for terms +# of use. + +AC_DEFUN([AX_CHECK_A2X_TO_MANPAGE], +[ + AC_CACHE_CHECK([manpage creation with a2x], [ac_cv_a2x_man], + [ + if test "x$A2X" = "x"; then + AC_MSG_NOTICE([a2x not in path, skipping test]) + ac_cv_a2x_man=no + else + cat <conftestman.txt +foo(7) +====== + +NAME +---- +foo - manual + +AUTHORS +------- +author +EOF + $A2X --verbose --doctype manpage --format manpage conftestman.txt >conftest.out 2>&1 + if test "$?" = 0; then + ac_cv_a2x_man=yes + $1 + else + ac_cv_a2x_man=no + cat conftest.out >&AS_MESSAGE_LOG_FD 2>&1 + $2 + fi + rm -f conftestman.txt conftest.out foo.7 + fi + ]) + HAVE_A2X_MAN="$ac_cv_a2x_man" +]) diff --git a/examples/espidf-coap-server/components/libcoap/m4/ax_check_compile_flag.m4 b/examples/espidf-coap-server/components/libcoap/m4/ax_check_compile_flag.m4 new file mode 100644 index 000000000..ca3639715 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/m4/ax_check_compile_flag.m4 @@ -0,0 +1,74 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 4 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/examples/espidf-coap-server/components/libcoap/m4/ax_check_link_flag.m4 b/examples/espidf-coap-server/components/libcoap/m4/ax_check_link_flag.m4 new file mode 100644 index 000000000..eb01a6ce1 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/m4/ax_check_link_flag.m4 @@ -0,0 +1,74 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the linker or gives an error. +# (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the linker's default flags +# when the check is done. The check is thus made with the flags: "LDFLAGS +# EXTRA-FLAGS FLAG". This can for example be used to force the linker to +# issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_LINK_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 4 + +AC_DEFUN([AX_CHECK_LINK_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl +AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS $4 $1" + AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + LDFLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_LINK_FLAGS diff --git a/examples/espidf-coap-server/components/libcoap/man/Makefile.am b/examples/espidf-coap-server/components/libcoap/man/Makefile.am new file mode 100644 index 000000000..4a04b588f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/Makefile.am @@ -0,0 +1,162 @@ +# man/Makefile.am +# +# Copyright (C) 2018-2022 Jon Shallow +# +# This file is part of the CoAP C library libcoap. Please see README and +# COPYING for terms of use. + +# picking up the default warning CFLAGS into AM_CFLAGS +AM_CFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include \ + -I$(top_srcdir)/include/coap$(LIBCOAP_API_VERSION) \ + $(WARNING_CFLAGS) $(DTLS_CFLAGS) -std=c99 $(EXTRA_CFLAGS) + +# Build, not install +noinst_PROGRAMS = examples-code-check + +# build manuals only if 'BUILD_MANPAGES' is defined +if BUILD_MANPAGES + +# building the manpages + +TXT3 = coap_async.txt \ + coap_attribute.txt \ + coap_block.txt \ + coap_cache.txt \ + coap_context.txt \ + coap_endpoint_server.txt \ + coap_encryption.txt \ + coap_endpoint_client.txt \ + coap_handler.txt \ + coap_io.txt \ + coap_keepalive.txt \ + coap_logging.txt \ + coap_observe.txt \ + coap_pdu_access.txt \ + coap_pdu_setup.txt \ + coap_recovery.txt \ + coap_resource.txt \ + coap_session.txt \ + coap_string.txt \ + coap_tls_library.txt + +MAN3 = $(TXT3:%.txt=%.3) + +man3_MANS = $(MAN3) + +TXT5 = coap-client.txt \ + coap-rd.txt \ + coap-server.txt + +MAN5 = $(TXT5:%.txt=%.5) + +man5_MANS = $(MAN5) + +TXT7 = coap.txt + +MAN7 = $(TXT7:%.txt=%.7) + +man7_MANS = $(MAN7) + +.txt.3: + $(A2X) --doctype manpage --format manpage $< + @NEWLIST=`${SED} -ne '/^NAME/,/^SYNOPSIS/p;/^SYNOPSIS/q' $< | ${SED} 's/^- /\\\\\\\- /g' | egrep -v 'NAME|----|SYNOPSIS|^\$$' | tr '\n' ' '` ;\ + NAME=`echo $< | ${SED} -ne 's/^\(coap_[a-zA-Z_0-9]\+\).*$$/\1.3/p'` ;\ + ${SED} -i '/.SH "NAME"/{n;d;}' $${NAME} ;\ + ${SED} -i "/\.SH \"NAME\"/a $${NEWLIST}" $${NAME} + $(A2X) --doctype manpage --format xhtml $< + @NEWLIST=`${SED} -ne '/^NAME/,/^SYNOPSIS/p;/^SYNOPSIS/q' $< | ${SED} 's^/^\\\\/^g' | egrep -v 'NAME|----|SYNOPSIS|^\$$' | tr '\n' ' '` ;\ + NAME=`echo $< | ${SED} -ne 's/^\(coap_[a-zA-Z_0-9]\+\).*$$/\1.html/p'` ;\ + ${SED} -i "s^Name

.*

^Name

$${NEWLIST}

^" $${NAME} + +.txt.5: + $(A2X) --doctype manpage --format manpage $< + $(A2X) --doctype manpage --format xhtml $< + +.txt.7: + $(A2X) --doctype manpage --format manpage $< + $(A2X) --doctype manpage --format xhtml $< + +# Man pages built by a2x based on the NAMES section of the .txt file. +# Note - this list includes all the defined entries, but a2x only builds the first 10. +A2X_EXTRA_PAGES_3 = @DOLLAR_SIGN@(shell for fil in $(TXT3) ; do sed -ne '/^NAME/,/^SYNOPSIS/p;/^SYNOPSIS/q' $${fil} | \ + sed -ne '/coap_/{ s/ *, */\n/g; p }' | sed -ne 's/^\(coap_[a-zA-Z_0-9]\+\).*$$/\1.3/p' ; done) +A2X_EXTRA_PAGES_5 = @DOLLAR_SIGN@(shell for fil in $(TXT5) ; do sed -ne '/^NAME/,/^SYNOPSIS/p;/^SYNOPSIS/q' $${fil} | \ + sed -ne '/coap-/{ s/ *, */\n/g; p }' | sed -ne 's/^\(coap-[a-zA-Z0-9-]\+\).*$$/\1.5/p' ; done) + +# a2x builds alternative .3 files up to a limit of 10 names from the +# NAME section, so that 'man' works against the alternative different +# function names. +# +# However, if there are more alternative names, they need to be defined +# as per below +# +# Then all the alternative names as well as the extras defined below need +# to be cleaned up in a 'make unistall'. +install-man: install-man3 install-man5 install-man7 + @echo ".so man3/coap_cache.3" > coap_cache_get_pdu.3 + @echo ".so man3/coap_cache.3" > coap_cache_get_app_data.3 + @echo ".so man3/coap_cache.3" > coap_cache_set_app_data.3 + @echo ".so man3/coap_context.3" > coap_context_get_session_timeout.3 + @echo ".so man3/coap_context.3" > coap_context_set_csm_timeout.3 + @echo ".so man3/coap_context.3" > coap_context_get_csm_timeout.3 + @echo ".so man3/coap_logging.3" > coap_show_pdu.3 + @echo ".so man3/coap_logging.3" > coap_endpoint_str.3 + @echo ".so man3/coap_logging.3" > coap_session_str.3 + @echo ".so man3/coap_pdu_access.3" > coap_option_filter_set.3 + @echo ".so man3/coap_pdu_access.3" > coap_option_filter_unset.3 + @echo ".so man3/coap_pdu_access.3" > coap_option_iterator_init.3 + @echo ".so man3/coap_pdu_access.3" > coap_option_next.3 + @echo ".so man3/coap_pdu_access.3" > coap_pdu_get_code.3 + @echo ".so man3/coap_pdu_access.3" > coap_pdu_get_mid.3 + @echo ".so man3/coap_pdu_access.3" > coap_pdu_get_token.3 + @echo ".so man3/coap_pdu_access.3" > coap_pdu_get_type.3 + @echo ".so man3/coap_pdu_access.3" > coap_get_uri_path.3 + @echo ".so man3/coap_pdu_setup.3" > coap_delete_optlist.3 + @echo ".so man3/coap_pdu_setup.3" > coap_encode_var_safe.3 + @echo ".so man3/coap_pdu_setup.3" > coap_encode_var_safe8.3 + @echo ".so man3/coap_pdu_setup.3" > coap_add_optlist_pdu.3 + @echo ".so man3/coap_pdu_setup.3" > coap_add_option.3 + @echo ".so man3/coap_pdu_setup.3" > coap_add_data.3 + @echo ".so man3/coap_pdu_setup.3" > coap_add_data_blocked_response.3 + @echo ".so man3/coap_pdu_setup.3" > coap_send.3 + @echo ".so man3/coap_pdu_setup.3" > coap_split_path.3 + @echo ".so man3/coap_pdu_setup.3" > coap_split_query.3 + @echo ".so man3/coap_pdu_setup.3" > coap_pdu_set_mid.3 + @echo ".so man3/coap_pdu_setup.3" > coap_pdu_set_code.3 + @echo ".so man3/coap_pdu_setup.3" > coap_pdu_set_type.3 + @echo ".so man3/coap_recovery.3" > coap_session_set_nstart.3 + @echo ".so man3/coap_recovery.3" > coap_session_get_nstart.3 + @echo ".so man3/coap_recovery.3" > coap_session_set_probing_wait.3 + @echo ".so man3/coap_recovery.3" > coap_session_get_probing_wait.3 + @echo ".so man3/coap_recovery.3" > coap_debug_set_packet_loss.3 + @echo ".so man3/coap_resource.3" > coap_resource_set_mode.3 + @echo ".so man3/coap_resource.3" > coap_resource_set_userdata.3 + @echo ".so man3/coap_resource.3" > coap_resource_get_userdata.3 + @echo ".so man3/coap_resource.3" > coap_resource_release_userdata_handler.3 + @echo ".so man3/coap_resource.3" > coap_resource_get_uri_path.3 + @echo ".so man3/coap_session.3" > coap_session_get_context.3 + @echo ".so man3/coap_session.3" > coap_session_get_ifindex.3 + @echo ".so man3/coap_session.3" > coap_session_get_proto.3 + @echo ".so man3/coap_session.3" > coap_session_get_psk_hint.3 + @echo ".so man3/coap_session.3" > coap_session_get_psk_key.3 + @echo ".so man3/coap_session.3" > coap_session_get_state.3 + @echo ".so man3/coap_session.3" > coap_session_get_tls.3 + @echo ".so man3/coap_session.3" > coap_session_get_type.3 + @echo ".so man3/coap_string.3" > coap_delete_bin_const.3 + @echo ".so man3/coap_string.3" > coap_make_str_const.3 + @echo ".so man3/coap_string.3" > coap_string_equal.3 + @echo ".so man3/coap_string.3" > coap_binary_equal.3 + $(INSTALL_DATA) $(A2X_EXTRA_PAGES_3) "$(DESTDIR)$(man3dir)" + $(INSTALL_DATA) $(A2X_EXTRA_PAGES_5) "$(DESTDIR)$(man5dir)" + +# As well as removing the base 'man' pages, remove other .3 files built by +# a2x, as well as build by install-man specials. +uninstall-man: uninstall-man3 uninstall-man5 uninstall-man7 + -(cd $(DESTDIR)$(man3dir) ; rm -f $(A2X_EXTRA_PAGES_3) $(A2X_EXTRA_PAGES_5) ) + +endif # BUILD_MANPAGES + +CLEANFILES = *.3 *.5 *.7 *.xml *.html docbook-xsl.css *.o examples-code-check + +clean-local: + -rm -rf tmp diff --git a/examples/espidf-coap-server/components/libcoap/man/coap-client.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap-client.txt.in new file mode 100644 index 000000000..28f0baaad --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap-client.txt.in @@ -0,0 +1,299 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap-client(5) +============== +:doctype: manpage +:man source: coap-client +:man version: @PACKAGE_VERSION@ +:man manual: coap-client Manual + +NAME +----- +coap-client, +coap-client-gnutls, +coap-client-mbedtls, +coap-client-openssl, +coap-client-notls +- CoAP Client based on libcoap + +SYNOPSIS +-------- +*coap-client* [*-a* addr] [*-b* [num,]size] [*-e* text] [*-f* file] [*-l* loss] + [*-m* method] [*-o* file] [*-p* port] [*-r*] [*-s duration*] + [*-t* type] [*-v* num] [*-w*] [*-A* type] [*-B* seconds] + [*-G* count] [*-H* hoplimit] [*-K* interval] [*-L* value] [*-N*] + [*-O* num,text] [*-P* scheme://addr[:port]] [*-T* token] [*-U*] + [*-X* size] + [[*-h* match_hint_file] [*-k* key] [*-u* user]] + [[*-c* certfile] [*-j* keyfile] [-n] [*-C* cafile] + [*-J* pkcs11_pin] [*-M* rpk_file] [*-R* trust_casfile]] URI + +For *coap-client* versions that use libcoap compiled for different +(D)TLS libraries, *coap-client-notls*, *coap-client-gnutls*, +*coap-client-openssl*, *coap-client-mbedtls* or *coap-client-tinydtls* may be +available. Otherwise, *coap-client* uses the default libcoap (D)TLS support. + +DESCRIPTION +----------- +*coap-client* is a CoAP client to communicate with 6LoWPAN devices via +the protocol CoAP (RFC 7252) using the URI given as argument on the +command line. The URI must have the scheme 'coap', 'coap+tcp', 'coaps' or +'coaps+tcp'. 'coaps' and 'coaps+tcp' are only supported when coap-client is +built with support for secure (D)TLS communication. + +If 'coaps' or 'coaps+tcp' is being used, provided the CoAP server supports PKI +and is configured with a certificate and private key, the coap-client does not +need to have a Pre-Shared Key (-k) or certificate (-c) configured. + +The URI's host part may be a DNS name or a literal IP address. Note that, for +IPv6 address references, angle brackets are required (c.f. EXAMPLES). + +OPTIONS - General +----------------- +*-a* addr:: + The local address of the interface that has to be used. + + Note: Do not use this option if the interface is likely to be transient - + i.e. it is a tunnel interface that may come and go, as this is likely to + cause "No such device" errors on transmission. + +*-b* [num,]size:: + The block size to be used in GET/PUT/POST requests (value must be a + multiple of 16 not larger than 1024 as libcoap uses a fixed maximum + PDU size of 1400 bytes). If 'num' is present, the request + chain will start at block 'num'. When the server includes a Block2 + option in its response to a GET request, coap-client will automatically + retrieve the subsequent block from the server until there are no more + outstanding blocks for the requested content. + +*-e* text:: + Include text as payload (use percent-encoding for non-ASCII characters). + +*-f* file:: + File to send with PUT/POST (use '-' for STDIN). + +*-l* list:: + Fail to send some datagrams specified by a comma separated list of + numbers or number ranges (debugging only). + +*-l* loss%:: + Randomly failed to send datagrams with the specified probability - 100% + all datagrams, 0% no datagrams (debugging only). + +*-m* method:: + The request method for action (get|put|post|delete), default is 'get'. + (Note that the string passed to *-m* is compared case-insensitive.) + +*-o* file:: + A filename to store data retrieved with GET. + +*-p* port:: + The port to listen on. + +*-r*:: + Use reliable protocol (TCP or TLS). + +*-s* duration:: + Subscribe to / observe the resource specified by URI for the given + 'duration' in seconds. + +*-t* type:: + Content format for given resource for PUT/POST. 'type' must be either + a numeric value reflecting a valid CoAP content format or a string + describing a registered format. The following registered content format + descriptors are supported, with alternative shortcuts given in + parentheses: + + text/plain (plain) + application/link-format (link, link-format) + application/xml (xml) + application/octet-stream (binary, octet-stream) + application/exi (exi) + application/json (json) + application/cbor (cbor) + +*-v* num:: + The verbosity level to use (default 3, maximum is 9). Above 7, there is + increased verbosity in GnuTLS and OpenSSL logging. + +*-w*:: + Append a newline to received data. + +*-A* type:: + Accepted media type. 'type' must be either a numeric value reflecting a + valid CoAP content format or a string that specifies a registered format as + described for option *-t*. + +*-B* seconds:: + Break operation after waiting given seconds (default is 90). + +*-G* count :: + Repeat the Request 'count' times with a second delay between each one. + Must have a value between 1 and 255 inclusive. Default is '1'. + +*-H* hoplimit:: + Set the Hop Limit count to hoplimit for proxies. Must have a value between + 1 and 255 inclusive. Default is '16'. + +*-K* interval:: + Send a ping after interval seconds of inactivity. + If not specified (or 0), keep-alive is disabled (default). + +*-L* value:: + Sum of one or more COAP_BLOCK_* flag values for different block handling + methods. Default is 1 (COAP_BLOCK_USE_LIBCOAP). + + COAP_BLOCK_USE_LIBCOAP 1 + COAP_BLOCK_SINGLE_BODY 2 + +*-N* :: + Send NON-confirmable message. If option *-N* is not specified, a + confirmable message will be sent. + +*-O* num,text:: + Add option 'num' with contents of 'text' to the request. If the text begins + with 0x, then the hex text (two [0-9a-f] per byte) is converted to binary + data. + +*-P* scheme://addr[:port]:: + Scheme, address and optional port to define how to connect to a CoAP proxy + (automatically adds Proxy-Uri option to request) to forward the request to. + Scheme is one of coap, coaps, coap+tcp and coaps+tcp. + +*-T* token:: + Define the initial starting 'token' for the request. + +*-U* :: + Never include Uri-Host or Uri-Port options. + +*-X* size:: + Maximum message size to use for TCP based connections (default is 8388864). + Maximum value of 2^32 -1. + +OPTIONS - PSK +------------- +(If supported by underlying (D)TLS library) + +*-h* match_hint_file:: + This is a file that contains one or more lines of received Identity Hints + to match to use different user identity and associated pre-shared key (PSK) + (comma separated) instead of the *-k key* and *-u user* options. E.g., per + line + + hint_to_match,use_user,with_key + + A line that starts with # is treated as a comment. + + Note: *-k key* and *-u user* still need to be defined for the default case in + case there is no match. + +*-k* key:: + Pre-shared key for the specified user identity (*-u* option also required). + +*-u* user:: + User identity to send for pre-shared key mode (*-k* option also required). + +OPTIONS - PKI +------------- +(If supported by underlying (D)TLS library) + +*Note:* If any one of *certfile*, *keyfile* or *cafile* is in PKCS11 URI +naming format (pkcs11: prefix), then any remaining non PKCS11 URI file +definitions have to be in DER, not PEM, format. Otherwise all of +*certfile*, *keyfile* or *cafile* are in PEM format. + +*-c* certfile:: + PEM file or PKCS11 URI for the certificate. The private key can also be in + the PEM file, or has the same PKCS11 URI. If not, the private key is defined + by *-j keyfile*. + +*-j* keyfile:: + PEM file or PKCS11 URI for the private key for the certificate in *-c + certfile* if the parameter is different from certfile in *-c certfile*. + +*-n* :: + Disable remote peer certificate checking. + +*-C* cafile:: +PEM file or PKCS11 URI for the CA certificate that was used to sign the server + certfile. Ideally the client certificate should be signed by the same CA so + that mutual authentication can take place. The contents of cafile are added + to the trusted store of root CAs. Using the *-C* or *-R* options will trigger + the validation of the server certificate unless overridden by the *-n* option. + +*-J* pkcs11_pin:: + The user pin to unlock access to the PKCS11 token. + +*-M* rpk_file:: + Raw Public Key (RPK) PEM file or PKCS11 URI that contains both PUBLIC KEY + and PRIVATE KEY or just EC PRIVATE KEY. (GnuTLS and TinyDTLS(PEM) support + only). *-C cafile* or *-R trust_casfile* are not required. + +*-R* trust_casfile:: + PEM file containing the set of trusted root CAs that are to be used to + validate the server certificate. Alternatively, this can point to a + directory containing a set of CA PEM files. The *-C cafile* CA does not have + to be in this list and is trusted for the validation. Using + *-R trust_casfile* disables common CA mutual authentication which can only + be done by using *-C cafile*. Using the *-C* or *-R* options will will + trigger the validation of the server certificate unless overridden by the + *-n* option. + +EXAMPLES +-------- +* Example +---- +coap-client coap://coap.me +---- +Query the resource '/' from server 'coap.me' (using the GET method). + +* Example +---- +coap-client -m get coap://[::1]/ +---- +Query the resource '/' on localhost using the 'GET' method to get back the +summary defined attributes. + +* Example +---- +coap-client -m get coap://[::1]/.well-known/core +---- +Query on the resource '.well-known/core' on localhost to get back a list of +the known resources along with their attribute definitions. + +* Example +---- +echo -n "mode=on" | coap-client -m put \ +coap://[2001:db8:c001:f00d:221:2eff:ff00:2704]:5683/actuators/leds?color=r -f- +---- +Send text 'mode=on' to resource 'actuators/leds?color=r' on the endpoint with +address '2001:db8:c001:f00d:221:2eff:ff00:2704' and port '5683'. Note that the +port '5683' is the default port and isn't actually required in this instance. + +* Example +---- +coap-client -m put coap://[fec0::3]/ck -T 3a -t binary -f to_upload +---- +Put the contents of file 'to_upload' with content type 'binary' (i.e. +application/octet-stream) into resource 'ck' on 'fec0::3' using a token of +'3a' via the 'PUT' method. + +FILES +------ +There are no configuration files. + +EXIT STATUS +----------- +*0*:: + Success + +*1*:: + Failure (syntax or usage error; configuration error; document + processing failure; unexpected error) + +BUGS +----- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap-rd.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap-rd.txt.in new file mode 100644 index 000000000..14dc15155 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap-rd.txt.in @@ -0,0 +1,163 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap-rd(5) +========== +:doctype: manpage +:man source: coap-rd +:man version: @PACKAGE_VERSION@ +:man manual: coap-rd Manual + +NAME +----- +coap-rd, +coap-rd-gnutls , +coap-rd-mbedtls, +coap-rd-openssl, +coap-rd-notls +- A CoAP Resource Directory based on libcoap + +SYNOPSIS +-------- +*coap-rd* [*-g* group] [*-G* group_if] [*-p* port] [*-v* num] [*-A* address] + [[*-h* hint] [*-k* key]] + [[*-c* certfile] [*-n*] [*-C* cafile] [*-R* trusted_casfile]] + +For *coap-rd* versions that use libcoap compiled for different +(D)TLS libraries, *coap-rd-notls*, *coap-rd-gnutls*, +*coap-rd-openssl*, *coap-rd-mbedtls* or *coap-rd-tinydtls* may be +available. Otherwise, *coap-rd* uses the default libcoap (D)TLS support. + +DESCRIPTION +----------- +*coap-rd* is a simple CoAP Resource Directory server that can handle resource +registrations using the protocol CoAP (RFC 7252). + +OPTIONS +------- +*-g* group:: + Join specified multicast 'group' on startup. + *Note:* DTLS over multicast is not currently supported. + +*-G* group_if:: + Use this interface for listening for the multicast group. This can be + different from the implied interface if the *-A* option is used. + +*-p* port:: + The 'port' on the given address will be listening for incoming connections. + If (D)TLS is supported, then 'port' + 1 will also be listened on for + (D)TLS connections. + The default port is 5683 if not given any other value. + +*-v* num:: + The verbosity level to use (default: 3, maximum is 9). Above 7, there is + increased verbosity in GnuTLS and OpenSSL logging. + +*-A* address:: + The local address of the interface which the server has to listen on. + +OPTIONS - PSK +------------- +(If supported by underlying (D)TLS library) + +*-h* hint:: + Identity Hint to send. Default is *CoAP*. Zero length is no hint. + +*-k* key:: + Pre-shared key to use for inbound connections. This cannot be empty if + defined. + *Note:* if *-c cafile* is defined, you need to define *-k key* as well to + have the server support both PSK and PKI. + +OPTIONS - PKI +------------- +(If supported by underlying (D)TLS library) + +*-c* certfile:: + Use the specified PEM file which contains the CERTIFICATE and PRIVATE + KEY information. + Note: if *-k key* is defined, you need to define *-c certfile* as well to + have the server support both PSK and PKI. + +*-n* :: + Disable remote peer certificate checking. This gives clients the ability to + use PKI, but without any defined certificates. + +*-C* cafile:: + PEM file that contains a list of one or more CAs that are to + be passed to the client for the client to determine what client certificate + to use. Normally, this list of CAs would be the root CA and and any + intermediate CAs. Ideally the server certificate should be signed by the + same CA so that mutual authentication can take place. The contents of + *cafile* are added to the trusted store of root CAs. Using the *-C* or *-R* + options will will trigger the validation of the client certificate unless + overridden by the *-n* option. + +*-R* trust_casfile:: + PEM file containing the set of trusted root CAs that are to be used to + validate the client certificate. Alternatively, this can point to a + directory containing a set of CA PEM files. The *-C cafile* CA does not have + to be in this list and is trusted for the validation. Using + *-R trust_casfile* disables common CA mutual authentication which can only + be done by using *-C cafile*. Using the *-C* or *-R* options will will + trigger the validation of the server certificate unless overridden by the + *-n* option. + +EXAMPLES +-------- +* Example +---- +coap-rd -A ::1 +---- +Let the server listen on localhost (port 5683). + +* Example +---- +coap-rd -A ::1 -k mysecretKey -h myhint +---- +Let the server listen on localhost (port '5683' and '5684') with the server +set up for PSK authentication. + +* Example +---- +coap-rd -A ::1 -p 13011 +---- +Quite the same, except listening port is '13011' (and not the default port +5683). + +* Example +---- +coap-rd -A 2001:db8:81a8:0:6ef0:dead:feed:beef -v 5 +---- +The listening address is set to '2001:db8:81a8:0:6ef0:dead:feed:beef' and the +verbosity level is set to '5'. + +* Example +---- +coap-rd -A 2001:db8:81a8:0:6ef0:dead:feed:beef -g FF02::FD +---- +Set listening address to '2001:db8:81a8:0:6ef0:dead:feed:beef' and join the +All CoAP Nodes multicast group 'FF02::FD'. + +FILES +------ +There are no configuration files. + +EXIT STATUS +----------- +*0*:: + Success + +*1*:: + Failure (syntax or usage error; configuration error; document + processing failure; unexpected error) + +BUGS +----- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap-server.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap-server.txt.in new file mode 100644 index 000000000..27726690b --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap-server.txt.in @@ -0,0 +1,268 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap-server(5) +============== +:doctype: manpage +:man source: coap-server +:man version: @PACKAGE_VERSION@ +:man manual: coap-server Manual + +NAME +----- +coap-server, +coap-server-gnutls, +coap-server-mbedtls, +coap-server-openssl, +coap-server-notls +- CoAP Server based on libcoap + +SYNOPSIS +-------- +*coap-server* [*-d* max] [*-e*] [*-g* group] [*-G* group_if] [*-l* loss] + [*-p* port] [-r] [*-v* num] [*-A* address] [*-L* value] [*-N*] + [*-P* scheme://addr[:port],[name1[,name2..]]] [*-X* size] + [[*-h* hint] [*-i* match_identity_file] [*-k* key] + [*-s* match_psk_sni_file] [*-u* user]] + [[*-c* certfile] [*-j* keyfile] [*-n*] [*-C* cafile] + [*-J* pkcs11_pin] [*-M* rpk_file] [*-R* trust_casfile] + [*-S* match_pki_sni_file]] + +For *coap-server* versions that use libcoap compiled for different +(D)TLS libraries, *coap-server-notls*, *coap-server-gnutls*, +*coap-server-openssl*, *coap-server-mbedtls* or *coap-server-tinydtls* may be +available. Otherwise, *coap-server* uses the default libcoap (D)TLS support. + +DESCRIPTION +----------- +*coap-server* is an example server for the 'Constrained Application Protocol` +(RFC 7252). + +OPTIONS - General +----------------- +*-d* max:: + Enable support for creation of dynamic resources when doing a PUT up to a + limit of 'max'. If 'max' is reached, a 4.06 code is returned until one of + the dynamic resources has been deleted. + +*-e* :: + Echo back the data sent with a PUT. + +*-g* group:: + Join specified multicast 'group' on start up. + *Note:* DTLS over multicast is not currently supported. + +*-G* group_if:: + Use this interface for listening for the multicast group. This can be + different from the implied interface if the *-A* option is used. + +*-l* list:: + Fail to send some datagrams specified by a comma separated list of + numbers or number ranges (debugging only). + +*-l* loss%:: + Randomly failed to send datagrams with the specified probability - 100% + all datagrams, 0% no datagrams (debugging only). + +*-p* port:: + The 'port' on the given address will be listening for incoming connections. + If (D)TLS is supported, then 'port' + 1 will also be listened on for + (D)TLS connections. + The default port is 5683 if not given any other value. + +*-r* :: + Enable multicast per resource support. If enabled, only '/', '/async' + and '/.well-known/core' are enabled for multicast requests support, + otherwise all resources are enabled. + +*-v* num:: + The verbosity level to use (default 3, maximum is 9). Above 7, there is + increased verbosity in GnuTLS and OpenSSL logging. + +*-A* address:: + The local address of the interface which the server has to listen on. + +*-L* value:: + Sum of one or more COAP_BLOCK_* flag values for different block handling + methods. Default is 1 (COAP_BLOCK_USE_LIBCOAP). + + COAP_BLOCK_USE_LIBCOAP 1 + COAP_BLOCK_SINGLE_BODY 2 + +*-N* :: + Send NON-confirmable message for "observe" responses. If option *-N* is + not specified, a confirmable response will be sent. Even if set, every + fifth response will still be sent as a confirmable response + (RFC 7641 requirement). + +*-P* scheme://address[:port],[name1[,name2[,name3..]]] :: + Scheme, address, optional port of how to connect to the next proxy server + and zero or more names (comma separated) that this proxy server is known by. + The , (comma) is required. If there is no name1 or + if the hostname of the incoming proxy request matches one of these names, + then this server is considered to be the final endpoint. If + scheme://address[:port] is not defined before the leading , (comma) of the + first name, then the ongoing connection will be a direct connection. + Scheme is one of coap, coaps, coap+tcp and coaps+tcp. + +*-X* size:: + Maximum message size to use for TCP based connections (default is 8388864). + Maximum value of 2^32 -1. + +OPTIONS - PSK +------------- +(If supported by underlying (D)TLS library) + +*-h* hint:: + Identity Hint to send. Default is *CoAP*. Zero length is no hint. + +*-i* match_identiity_file:: + This is a file that contains one or more lines of Identity Hints and (user) + Identities to match for a different new Pre-Shared Key (PSK) (comma + separated) to be used. E.g., per line + + hint_to_match,identity_to_match,use_key + + A line that starts with # is treated as a comment. + + Note: *-k* still needs to be defined for the default case. + + Note: A match using the *-s* option may mean that the current Identity Hint + is different to that defined by *-h*. + +*-k* key:: + Pre-shared key to use for inbound connections. This cannot be empty if + defined. + + Note: if *-c cafile* is defined, you need to define *-k key* as well to + have the server support both PSK and PKI. + +*-s* match_psk_sni_file:: + This is a file that contains one or more lines of received Subject Name + Identifier (SNI) to match to use a different Identity Hint and associated + Pre-Shared Key (PSK) (comma separated) instead of the *-h hint* and + *-k key* options. E.g., per line + + sni_to_match,use_hint,with_key + + Note: *-k key* still needs to be defined for the default case if there is + not a match. + + Note: The associated Pre-Shared Key will get updated if there is also a *-i* + match. The update checking order is *-s* followed by *-i*. + +*-u* user :: + User identity for pre-shared key mode (only used if option *-P* is set). + +OPTIONS - PKI +------------- +(If supported by underlying (D)TLS library) + +*Note:* If any one of *certfile*, *keyfile* or *cafile* is in PKCS11 URI +naming format (pkcs11: prefix), then any remaining non PKCS11 URI file +definitions have to be in DER, not PEM, format. Otherwise all of +*certfile*, *keyfile* or *cafile* are in PEM format. + +*-c* certfile:: + PEM file or PKCS11 URI for the certificate. The private key can also be in + the PEM file, or has the same PKCS11 URI. If not, the private key is defined + by *-j keyfile*. + + Note: if *-k key* is defined, you need to define *-c certfile* as well to + have the server support both PSK and PKI. + +*-j* keyfile:: + PEM file or PKCS11 URI for the private key for the certificate in *-c + certfile* if the parameter is different from certfile in *-c certfile*. + +*-n* :: + Disable remote peer certificate checking. This gives clients the ability to + use PKI, but without any defined certificates. + +*-C* cafile:: + PEM file or PKCS11 URI that contains a list of one or more CAs that are to + be passed to the client for the client to determine what client certificate + to use. Normally, this list of CAs would be the root CA and and any + intermediate CAs. Ideally the server certificate should be signed by the + same CA so that mutual authentication can take place. The contents of + *cafile* are added to the trusted store of root CAs. Using the *-C* or *-R* + options will will trigger the validation of the client certificate unless + overridden by the *-n* option. + +*-J* pkcs11_pin:: + The user pin to unlock access to the PKCS11 token. + +*-M*:: + Raw Public Key (RPK) PEM file or PKCS11 URI that contains both PUBLIC KEY + and PRIVATE KEY or just EC PRIVATE KEY. (GnuTLS and TinyDTLS(PEM) support + only). *-C cafile* or *-R trust_casfile* are not required. + +*-R* trust_casfile:: + PEM file containing the set of trusted root CAs that are to be used to + validate the client certificate. Alternatively, this can point to a + directory containing a set of CA PEM files. The *-C cafile* CA does not have + to be in this list and is trusted for the validation. Using + *-R trust_casfile* disables common CA mutual authentication which can only + be done by using *-C cafile*. Using the *-C* or *-R* options will will + trigger the validation of the server certificate unless overridden by the + *-n* option. + +*-S* match_pki_sni_file:: + This option denotes a file that contains one or more lines of Subject Name + Identifier (SNI) to match for new certificate File and new CA File (comma + separated) to be used. E.g., entry per line + + sni_to_match,new_cert_file,new_ca_file + + A line that starts with # is treated as a comment. + + Note: *-c certfile* and *-C cafile* still needs to be defined for the + default case + +EXAMPLES +-------- +* Example +---- +coap-server -A ::1 +---- +Let the server listen on localhost (port '5683') for UDP/TCP. + +* Example +---- +coap-server -A ::1 -k mysecretKey -h myhint +---- +Let the server listen on localhost (port '5683' for UDP/TCP and port '5684' for +DTLS/TLS) with the server set up for PSK authentication if the client uses +coaps:// or coaps+tcp://. + +* Example +---- +coap-server -A ::1 -k mysecretKey -h myhint -p 13011 +---- +The same, except the UDP/TCP listening port is '13011' and the DTLS/TLS +listening port is '13012' (and not the default ports '5683' and '5684'). + +* Example +---- +coap-server -A 2001:db8:81a8:0:6ef0:dead:feed:beef -v 5 +---- +The listening address is set to '2001:db8:81a8:0:6ef0:dead:feed:beef' and the +verbosity level is set to '5'. + +* Example +---- +coap-server -A 2001:db8:81a8:0:6ef0:dead:feed:beef -g FF02::FD +---- +Set listening address to '2001:db8:81a8:0:6ef0:dead:feed:beef' and join the +All CoAP Nodes multicast group 'FF02::FD'. + +FILES +------ +There are no configuration files. + +EXIT STATUS +----------- +*0*:: + Success + +*1*:: + Failure (syntax or usage error; configuration error; document + processing failure; unexpected error) + +BUGS +----- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap.txt.in new file mode 100644 index 000000000..f9fd82e8d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap.txt.in @@ -0,0 +1,87 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap(7) +======= +:doctype: manpage +:man source: coap +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap - Overview of the libcoap library + +SYNOPSIS +-------- +Summary of the different libcoap API manual pages. + +DESCRIPTION +----------- + +libcoap is a C implementation of a lightweight application-protocol for +devices that are constrained by their resources such as computing power, RF +range, memory, bandwidth, or network packet sizes. This protocol, CoAP, is +standardized by the IETF as RFC 7252. For further information related to +CoAP, see http://coap.technology. + +Documentation for the specific library calls with examples can be found in the +man pages referred to in SEE ALSO. + +Further information can be found in the include header files with example +code provided in the examples directory. + +*NOTE:* This documentation is a work in progress. Any missing information can +be found in the include header files along with example code provided in the +examples directory. + + +SEE ALSO +-------- +*coap_async*(3), *coap_attribute*(3), *coap_block*(3), *coap_cache*(3), +*coap_context*(3), *coap_encryption*(3), *coap_endpoint_client*(3), +*coap_endpoint_server*(3), *coap_handler*(3), *coap_io*(3), +*coap_keepalive*(3), *coap_logging*(3), *coap_observe*(3), +*coap_pdu_access*(3), *coap_pdu_setup*(3), *coap_recovery*(3), +*coap_resource*(3), *coap_session*(3), *coap_string*(3) and +*coap_tls_library*(3) + +For example executables, see *coap-client*(5), *coap-rd*(5) and *coap-server*(5) + +FURTHER INFORMATION +------------------- +See + +"RFC7252: The Constrained Application Protocol (CoAP)" + +"RFC7390: Group Communication for the Constrained Application Protocol (CoAP)" + +"RFC7641: Observing Resources in the Constrained Application Protocol (CoAP)" + +"RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP)" + +"RFC7967: Constrained Application Protocol (CoAP) Option for No Server Response" + +"RFC8132: PATCH and FETCH Methods for the Constrained Application Protocol (CoAP)" + +"RFC8323: CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets" + +"RFC8516: "Too Many Requests" Response Code for the Constrained Application Protocol" + +"RFC8613: Object Security for Constrained RESTful Environments (OSCORE)" + +"RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option" + +"RFC9175: CoAP: Echo, Request-Tag, and Token Processing" + +for further information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_async.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_async.txt.in new file mode 100644 index 000000000..379f58596 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_async.txt.in @@ -0,0 +1,203 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_async(3) +============= +:doctype: manpage +:man source: coap_async +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_async, +coap_async_is_supported, +coap_register_async, +coap_async_trigger, +coap_async_set_delay, +coap_find_async, +coap_free_async, +coap_async_set_app_data, +coap_async_get_app_data +- Work with CoAP async support + +SYNOPSIS +-------- +*#include * + +*int coap_async_is_supported(void);* + +*coap_async_t *coap_register_async(coap_session_t *_session_, +const coap_pdu_t *_request_, coap_tick_t _delay_);* + +*void coap_async_trigger(coap_async_t *_async_);* + +*void coap_async_set_delay(coap_async_t *_async_, coap_tick_t _delay_);* + +*void coap_free_async(coap_session_t *_session_, coap_async_t *_async_);* + +*coap_async_t *coap_find_async(coap_session_t *_session_, +coap_bin_const_t _token_);* + +*void coap_async_set_app_data(coap_async_t *_async_, void *_app_data_);* + +*void *coap_async_get_app_data(const coap_async_t *_async_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +CoAP server responses can be piggybacked (RFC7252 5.2.1) or separate +(RFC7252 5.2.2). + +For piggybacked responses, the response packet contains both the status and +any data. + +For separate responses, there is an initial empty ACK response (Confirmable +only - to stop the client re-transmitting the request) followed at a later time +by the packet containing the status and any data. + +Usually responses are piggybacked, but this man page focuses on separate +(async) support. + +The function *coap_async_is_supported*() is used to determine if there is +async support or not. + +The *coap_register_async*() function is used to set up an asynchronous delayed +request for the _request_ PDU associated with the _session_. The +application request handler will get called with a copy of _request_ after +_delay_ ticks which will then cause a response to be sent. If _delay_ is 0, +then the application request handler will not get called until +*coap_async_trigger*() or *coap_async_set_delay*() is called. + +The *coap_async_trigger*() function is used to expire the delay for the +_async_ definition, so the application request handler is almost +immediately called. + +The *coap_async_set_delay*() function is used to update the remaining _delay_ +before the application request handler is called for the _async_ definition. If +_delay_ is set to 0, then the application request handler will not get called. + +An example of usage here is *coap_register_async*() sets _delay_ to 0, and +then when the response is ready at an indeterminate point in the future, +*coap_async_set_delay*() is called setting _delay_ to 1. Alternatively, +*coap_async_trigger*() can be called. + +The *coap_free_async*() function is used to delete an _async_ definition. + +The *coap_find_async*() function is used to determine if there is an async +definition based on the _session_ and token _token_. + +The *coap_async_set_app_data*() function is used to add in user defined +_app_data_ to the _async_ definition. It is the responsibility of the +application to release this data if appropriate. This would usually be done +when the application request handler is called under 'async' control. + +The *coap_async_get_app_data*() function is used to retrieve any defined +application data from the _async_ definition. + +RETURN VALUES +------------- + +*coap_async_is_supported*() returns 1 if support is available, 0 otherwise. + +*coap_register_async*() and *coap_find_async*() return a pointer to an async +definition or NULL if there is an error. + +*coap_async_get_app_data*() returns a pointer to the user defined data. + +EXAMPLES +-------- +*CoAP Server Non-Encrypted Setup* + +[source, c] +---- +#include + +/* + * This example is used to demonstrate how to set up and use a "separate" + * response (empty ACK followed by data response at a later stage). + */ +static void +hnd_get_with_delay(coap_session_t *session, + coap_resource_t *resource, + coap_pdu_t *request, + coap_string_t *query, + coap_pdu_t *response) { + unsigned long delay = 5; + size_t size; + coap_async_t *async; + coap_bin_const_t token = coap_pdu_get_token(request); + + /* + * See if this is the initial, or delayed request + */ + + async = coap_find_async(session, token); + if (!async) { + /* Set up an async request to trigger delay in the future */ + if (query) { + const uint8_t *p = query->s; + + delay = 0; + for (size = query->length; size; --size, ++p) + delay = delay * 10 + (*p - '0'); + if (delay == 0) { + coap_log(LOG_INFO, "async: delay of 0 not supported\n"); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); + return; + } + } + async = coap_register_async(session, + request, + COAP_TICKS_PER_SECOND * delay); + if (async == NULL) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE); + return; + } + /* + * Not setting response code will cause empty ACK to be sent + * if Confirmable + */ + return; + } + /* async is set up, so this is the delayed request */ + + /* remove any stored app data associated with 'async' here */ + + /* Send back the appropriate data */ + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, -1, 0, 4, + (const uint8_t *)"done", NULL, NULL); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + + /* async is automatically removed by libcoap on return from this handler */ +} + +---- + +SEE ALSO +-------- +*coap_handler*(3) + +FURTHER INFORMATION +------------------- +See + +"RFC7252: The Constrained Application Protocol (CoAP)" + +for further information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_attribute.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_attribute.txt.in new file mode 100644 index 000000000..52423150e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_attribute.txt.in @@ -0,0 +1,158 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_attribute(3) +================= +:doctype: manpage +:man source: coap_attribute +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_attribute, +coap_add_attr, +coap_find_attr, +coap_attr_get_value +- Work with CoAP attributes + +SYNOPSIS +-------- +*#include * + +*coap_attr_t *coap_add_attr(coap_resource_t *_resource_, +coap_str_const_t *_name_, coap_str_const_t *_value_, int _flags_);* + +*coap_attr_t *coap_find_attr(coap_resource_t *_resource_, +coap_str_const_t *_name_);* + +*coap_str_const_t *coap_attr_get_value(coap_attr_t *_attribute_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +CoAP Resources on a CoAP Server need to be created, updated etc. The URI in +the request packet defines the resource to work with, with possibly the Query +referring to a sub-resource. + +When resources are configured on the CoAP server, the URI to match against +is specified. +Callback Handlers are then added to the resource to handle the different +request methods. + +Adding Attributes allows textual information to be added to the resource +which can then be reported back to any client doing a Resource Discovery using +a "GET /.well-known/core" request with an optional query. +See https://tools.ietf.org/html/rfc6690#section-5 for some examples of +resource discovery usage. Common attribute names are rt, if, sz, ct, obs, rel, +anchor, rev, hreflang, media, title and type. href cannot be an attribute name. + +Attributes are automatically deleted when a Resource is deleted. + +The *coap_add_attr*() function +registers a new attribute called _name_ for the _resource_. +The value of the attribute is _value_ which can be NULL. + +_flags_ can be one or more of the following, which, if set, defines what is +to be internally freed off when the attribute is deleted with +*coap_delete_resource*(). + +[horizontal] +*COAP_ATTR_FLAGS_RELEASE_NAME*:: +Free off _name_ when attribute is deleted with *coap_delete_resource*(). + +*COAP_ATTR_FLAGS_RELEASE_VALUE*:: +Free off _value_ when attribute is deleted with *coap_delete_resource*(). + +The *coap_find_attr*() function returns the attribute with the _name_, +if found, associated with _resource_. + +The *coap_attr_get_value*() function returns the _value_ associated with the +specified _attribute_. + +RETURN VALUES +------------- +*coap_add_attr*() function returns a pointer to +the attribute that was created or NULL if there is a malloc failure. + +*coap_find_attr*() function returns a pointer to the first matching +attribute or NULL if the _name_ was not found. + +*coap_attr_get_value*() function returns a pointer to the value held within +the attribute. The pointer can be NULL if the _value_ id NULL, or NULL if +_attribute_ does not exist. + +EXAMPLE +------- +*Initialize Resources* + +[source, c] +-- +#include + +static void +init_resources(coap_context_t *ctx) { + + coap_resource_t *r; + + /* Create a resource to return general information */ + r = coap_resource_init(NULL, 0); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_index); + + /* Document resource for '.well-known/core' request */ + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), + coap_make_str_const("\"General Info\""), 0); + + coap_add_resource(ctx, r); + + /* Create a resource to return return or update time */ + r = coap_resource_init(coap_make_str_const("time"), + COAP_RESOURCE_FLAGS_NOTIFY_CON); + coap_resource_set_get_observable(r, 1); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_time); + coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_time); + coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_time); + + /* Document resource for 'time' request */ + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), + coap_make_str_const("\"Internal Clock\""), 0); + coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"secs\""), + 0); + coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""), + 0); + + coap_add_resource(ctx, r); + +} +-- + +SEE ALSO +-------- +*coap_resource*(3) and *coap_handler*(3) + +FURTHER INFORMATION +------------------- +See + +"RFC7252: The Constrained Application Protocol (CoAP)" + +"RFC6690: Constrained RESTful Environments (CoRE) Link Format" + +for further information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_block.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_block.txt.in new file mode 100644 index 000000000..4e6a99900 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_block.txt.in @@ -0,0 +1,534 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_block(3) +============= +:doctype: manpage +:man source: coap_block +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_block, +coap_context_set_block_mode, +coap_add_data_large_request, +coap_add_data_large_response, +coap_get_data_large, +coap_block_build_body +- Work with CoAP Blocks + +SYNOPSIS +-------- +*#include * + +*void coap_context_set_block_mode(coap_context_t *_context_, +uint8_t _block_mode_);* + +*int coap_add_data_large_request(coap_session_t *_session_, +coap_pdu_t *_pdu_, size_t _length_, const uint8_t *_data_, +coap_release_large_data_t _release_func_, void *_app_ptr_);* + +*int coap_add_data_large_response(coap_resource_t *_resource_, +coap_session_t *_session_, const coap_pdu_t *_request_, coap_pdu_t *_response_, +const coap_string_t *query, uint16_t _media_type_, int _maxage_, +uint64_t etag, size_t _length_, const uint8_t *_data_, +coap_release_large_data_t _release_func_, void *_app_ptr_);* + +*int coap_get_data_large(const coap_pdu_t *_pdu_, size_t *_length, +const uint8_t **_data_, size_t *_offset_, size_t *_total_);* + +*coap_binary_t *coap_block_build_body(coap_binary_t *_body_data_, +size_t _length_, const uint8_t *_data_, size_t _offset_, size_t _total_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +Regular setting up of a PDU and transmission is covered in *coap_pdu_setup*(3) +where all the payload data can fit in a single packet. This man page covers +how to work with PDUs where the overall body of information may need to be +split across several packets by using CoAP Block-Wise Transfers (RFC 7959). + +The block-wise transfers can be controlled by the application, or libcoap is +instructed to do all the requests for the next blocks and only present the +final body of the result to the application. In summary, the following three +ways handle processing a body of data that has to be split across multiple +payloads (blocks). + +1. Application does all the work + +It is the responsibility of the application to analyze each block transmission +at receipt and then generate the next request as per RFC 7959. In this case, +*coap_context_set_block_mode*() function must not be called to maintain +backward compatability with applications that did the block handling within the +application. + +2. Application sees individual blocks + +By calling *coap_context_set_block_mode(context, COAP_BLOCK_USE_LIBCOAP)* and +using the appropriate functions, the requests for the next block of data is +handled automatically by the libcoap layer. Each individual block of data is +presented to the application for processing. + +By calling *coap_get_data_large*(), the application can determine if this is +the first block or not (using _offset_ value), whether the first block is all +the data (_offset_ = 0, _length_ = _total_) and whether this is the last block +(_offset_ + _length_ = _total_). It is the responsibility of the application to +re-assemble the individual blocks into a single body of data. + +*NOTE:* _total_ is only an approximation (it will be > _offset_ + _length_) +until the final block is received. + +If this is the request handler in a server, the server still needs to return a +COAP_RESPONSE_CODE_CONTINUE 2.31 (Continue) response code if the received data +is not for the final block, otherwise a COAP_RESPONSE_CODE_CREATED 2.01 +(Created) or COAP_RESPONSE_CODE_CHANGED 2.04 (Changed) should be returned. + +3. Application only sees all of the body + +By calling *coap_context_set_block_mode(context, +COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY)* and using the appropriate +functions, the requests for all the blocks of data is handled automatically by +the libcoap layer. Only the complete body of the data is presented to the +application, unless there is an error. + +*coap_get_data_large*() will only return the entire body of data (_offset_ +always 0, _length_ = _total_) and there is no need to re-assemble individual +blocks into a large body of data. + +In RAM constrained environments, option 2 may be the preferred method. + +This man page focuses on getting libcoap to do all the work, not how to do it +all in the application. + +However, if the client supplies a Block1 or Block2 Option in the PDU where the +block number is not 0, this is assumed to be a random access request and any +other blocks will not be requested by libcoap even if instructed otherwise. + +The functions that are named *_large* are intended as replacements for the +equivalent functions as described in *coap_pdu_setup*(3). + +CALLBACK HANDLER +---------------- + +*Callback Type: coap_release_large_data_t* + +[source, c] +---- +/** + * Callback handler for de-allocating the data based on @p app_ptr provided to + * coap_add_data_large_*() functions following transmission of the supplied + * data. + * + * @param session The session that this data is associated with + * @param app_ptr The application provided pointer to the + * coap_add_data_large_*() functions + */ +typedef void (*coap_release_large_data_t)(coap_session_t *session, + void *app_ptr); +---- + +FUNCTIONS +--------- + +*Function: coap_context_set_block_mode()* + +The *coap_context_set_block_mode*() function is used to set up the _context_ +level _block_mode_ block handling bits for supporting RFC7959. _block_mode_ +flows down to a session when a session is created and if the peer does not +support the respective block mode, an appropriate bit may get disabled in the +session _block_mode_. + +[source, c] +---- +#define COAP_BLOCK_USE_LIBCOAP 0x01 /* Use libcoap to do block requests */ +#define COAP_BLOCK_SINGLE_BODY 0x02 /* Deliver the data as a single body */ +---- +_block_mode_ is an or'd set of zero or more COAP_BLOCK_* definitions. + +If COAP_BLOCK_USE_LIBCOAP is not set, then everything works as per Option 1 +above. + +If COAP_BLOCK_SINGLE_BODY is set, then the entire body of data is presented to +the receiving handler, otherwise each individual block is presented on arrival. +To obtain the data, length and current offset, *coap_get_data_large*() must +be used instead of *coap_get_data*(). It may be appropriate not to set +COAP_BLOCK_SINGLE_BODY if there are RAM limitations. + +*NOTE:* It is the responsibility of the receiving application to re-assemble +the _data_ as appropriate (e.g., using *coap_block_build_body*()) if +COAP_BLOCK_SINGLE_BODY is not set. + +*NOTE:* If COAP_BLOCK_SINGLE_BODY is not set, then the CoAP server on receiving +request data that is split over multiple data blocks must respond with +COAP_RESPONSE_CODE_CONTINUE 2.31 (Continue) response code if the received data +is not for the final block, otherwise a COAP_RESPONSE_CODE_CREATED 2.01 +(Created) or COAP_RESPONSE_CODE_CHANGED 2.04 (Changed) should be returned. + +If COAP_BLOCK_USE_LIBCOAP is set, then any PDUs presented to the application +handlers will get the tokens set back to the initiating token so that requests +can be matched with responses even if different tokens had to be used for the +series of packet interchanges. Furthermore, if COAP_BLOCK_SINGLE_BODY is set, +then the PDU that presents the entire body will have any BlockX option removed. + +*NOTE:* COAP_BLOCK_USE_LIBCOAP must be set if libcoap is to do all the +block tracking and requesting, otherwise the application will have to do all +of this work (the default if *coap_context_set_block_mode*() is not called). + +*Function: coap_add_data_large_request()* + +The *coap_add_data_large_request*() function is similar to *coap_add_data*(), +but supports the transmission of data that has a body size that is potentially +larger than can be fitted into a single client request PDU. The specified +payload _data_ of length _length_ is associated with the _session_ with the +first block of data added to the PDU _pdu_ along with the appropriate CoAP +options such as Block1, Size1 and Request-Tag if the data does not fit in +a single PDU. + +When the block receipt has been acknowledged by the peer, the library +will then send the next block of data until all the data has been transmitted. + +The _data_ passed to the +function *coap_add_data_large_request*() must exist until all blocks have been +transmitted. The callback function _release_func_ can be used to release +storage that has been dynamically allocated to hold the transmit data. If not +NULL, the callback function is called once the final block of _data_ has been +transmitted. The user-defined parameter _app_ptr_ is the same value that was +passed to *coap_add_data_large_request*(). + +*NOTE:* This function must only be called once per _pdu_. + +*NOTE:* Options cannot be added to the _pdu_ after +coap_add_data_large_request() is called. + +*Function: coap_add_data_large_response()* + +The *coap_add_data_large_response*() function is responsible for handling +the server's large responses to requests. *coap_add_data_large_response*() +should be used as a direct replacement for *coap_add_data*() if it is possible +that the _length_ of _data_ will not fit in a single server's response pdu. +This function adds in the initial part of the payload _data_ of length +_length_ to the PDU _pdu_. + +The _data_ passed to the function +*coap_add_data_large_response*() must exist until all blocks have been +transmitted. The callback function _release_func_ can be used to release +storage that has been dynamically allocated to hold the transmit data. If not +NULL, the callback function is called once the final block of _data_ has been +transmitted. The user-defined parameter _app_ptr_ is the same value that was +passed to *coap_add_data_large_response*(). + +It also adds in the appropriate CoAP options such as Block2, Size2 and ETag to +handle block-wise transfer if the data does not fit in a single PDU. + +_resource_, _query_, _session_, _request_, and _response_ are the same +parameters as in the called resource handler that invokes +*coap_add_data_large_response*(). If _etag_ is 0, then a unique ETag value will +be generated, else is the ETag value to use. +The _media_type_ is for the format of the _data_ and _maxage_ defines the +lifetime of the response. If _maxage_ is set to -1, then the Max-Age option +does not get included (which indicates the default value of 60 seconds +according to RFC 7252). + +The application request handler for the resource is only called once instead of +potentially multiple times. + +*NOTE:* This function must only be called once per _pdu_. + +*NOTE:* Options cannot be added to the _pdu_ after +coap_add_data_large_request() is called. + +*Function: coap_get_data_large()* + +The *coap_get_data_large*() function is used abstract from the _pdu_ +information about the received data by updating _length_ with the length of +data available, _data_ with a pointer to where the data is located, _offset_ +with where this block of data starts and _total_ with the total amount of data. +_offset_ will always be zero if block_mode includes COAP_BLOCK_SINGLE_BODY. +All of the body's data has been received if "_offset_ + _length_ == _total_". + +*NOTE:* _total_ is potentially only an indication of the total size of the +body and is only exact when all of the data has been received. + +*Function: coap_block_build_body()* + +The *coap_block_build_body*() function is used to re-assemble the received +data as returned by *coap_get_data_large*() into a single blob of data. Data +from _data_ of length _length_ starting from offset _offset_ is added to +_body_data_. The resultant state of _body_data_ is returned. If _body_data_ +is NULL, or _total_ is larger than the current size of _body_data_, then +_body_data_ is re-allocated and returned. If there is an error, _body_data_ +gets de-allocated. + +If _block_mode_ (as set by *coap_context_set_block_mode*()) includes +COAP_BLOCK_SINGLE_BODY, then the request/response handler will only get called +once with the entire body containing the data from all of the individual +blocks. If there is a change of data during the blocks receipt (e.g., ETag +value changes), then the entire set of data is re-requested and the partial +body dropped. + +RETURN VALUES +------------- +The *coap_add_data_large_request*(), *coap_add_data_large_response*(), and +*coap_get_data_large*() functions return 0 on failure, 1 on success. + +The *coap_block_build_body*() returns the current state of the body's data +(which may have some missing gaps) or NULL on error. + +EXAMPLES +-------- +*Setup PDU and Transmit* + +[source, c] +---- +#include + +static int +build_send_pdu(coap_context_t *context, coap_session_t *session, +uint8_t msgtype, uint8_t request_code, const char *uri, const char *query, +unsigned char *data, size_t length, int observe) { + + coap_pdu_t *pdu; + uint8_t buf[1024]; + size_t buflen; + uint8_t *sbuf = buf; + int res; + coap_optlist_t *optlist_chain = NULL; + /* Remove (void) definition if variable is used */ + (void)context; + + /* Create the pdu with the appropriate options */ + pdu = coap_pdu_init(msgtype, request_code, coap_new_message_id(session), + coap_session_max_pdu_size(session)); + if (!pdu) + return 0; + + /* + * Create unique token for this request for handling unsolicited / + * delayed responses + */ + coap_session_new_token(session, &buflen, buf); + if (!coap_add_token(pdu, buflen, buf)) { + coap_log(LOG_DEBUG, "cannot add token to request\n"); + goto error; + } + + if (uri) { + /* Add in the URI options */ + buflen = sizeof(buf); + res = coap_split_path((const uint8_t*)uri, strlen(uri), sbuf, &buflen); + while (res--) { + if (!coap_insert_optlist(&optlist_chain, + coap_new_optlist(COAP_OPTION_URI_PATH, + coap_opt_length(sbuf), coap_opt_value(sbuf)))) + goto error; + sbuf += coap_opt_size(sbuf); + } + } + + if (query) { + /* Add in the QUERY options */ + buflen = sizeof(buf); + res = coap_split_query((const uint8_t*)query, strlen(query), sbuf, &buflen); + while (res--) { + if (!coap_insert_optlist(&optlist_chain, + coap_new_optlist(COAP_OPTION_URI_QUERY, + coap_opt_length(sbuf), coap_opt_value(sbuf)))) + goto error; + sbuf += coap_opt_size(sbuf); + } + } + + if (request_code == COAP_REQUEST_GET && observe) { + /* Indicate that we want to observe this resource */ + if (!coap_insert_optlist(&optlist_chain, + coap_new_optlist(COAP_OPTION_OBSERVE, + coap_encode_var_safe(buf, sizeof(buf), + COAP_OBSERVE_ESTABLISH), buf) + )) + goto error; + } + + /* ... Other code / options etc. ... */ + + /* Add in all the options (after internal sorting) to the pdu */ + if (!coap_add_optlist_pdu(pdu, &optlist_chain)) + goto error; + + if (data && length) { + /* Add in the specified data */ + if (!coap_add_data_large_request(session, pdu, length, data, NULL, NULL)) + goto error; + } + + if (coap_send(session, pdu) == COAP_INVALID_MID) + goto error; + return 1; + +error: + + if (pdu) + coap_delete_pdu(pdu); + return 0; + +} + +int main(int argc, char *argv[]) { + coap_context_t *context = NULL; + coap_session_t *session = NULL; + unsigned char *data = NULL; + size_t data_length = 0; + + (void)argc; + (void)argv; + + /* ... Set up context, session etc. ... */ + + /* Set up using libcoap to do the block work */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + /* ... Other code etc. ... */ + + /* .. build data and define data_length ... */ + + build_send_pdu(context, session, COAP_MESSAGE_CON, COAP_REQUEST_PUT, + "/example/uri", NULL, data, data_length, 0); + + /* ... Other code etc. ... */ + + return 0; +} +---- + +*Resource Request Handler Response PDU Update* + +[source, c] +---- +#include + +#include + +static void +hnd_get_time(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + + unsigned char buf[40]; + size_t len; + time_t now; + + /* ... Additional analysis code for resource, request pdu etc. ... */ + + /* After analysis, generate a failure response and return if needed */ + + now = time(NULL); + + if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) { + /* Output secs since Jan 1 1970 */ + len = snprintf((char *)buf, sizeof(buf), "%lu", now); + } + else { + /* Output human-readable time */ + struct tm *tmp; + tmp = gmtime(&now); + if (!tmp) { + /* If 'now' is not valid */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp); + } + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + /* + * Invoke coap_add_data_large_response() to do all the hard work. + * [A good practice, even though ins this case, the amount of data is small] + * + * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in + * Define how long this response is valid for (secs) - 1 - to add in. + * + * Observe Option added internally if needed within the function + * Block2 Option added internally if output too large + * Size2 Option added internally + * ETag Option added internally + */ + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0, + len, + buf, + NULL, NULL); + /* + * When request handler returns, the response pdu will get automatically + * sent, unless the pdu code is not updated and this is a NON or TCP based + * request. + */ +} + +int main(int argc, char *argv[]) { + coap_context_t *context = NULL; + coap_resource_t *r; + coap_resource_t *time_resource; + int not_exit = 1; + + (void)argc; + (void)argv; + + /* ... Set up context etc. ... */ + + /* Set up using libcoap to do the block work */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + /* Create a resource to return time */ + r = coap_resource_init(coap_make_str_const("time"), + COAP_RESOURCE_FLAGS_NOTIFY_CON); + coap_resource_set_get_observable(r, 1); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_time); + + /* Document resource for 'time' request */ + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), + coap_make_str_const("\"Internal Clock\""), 0); + coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"secs\""), + 0); + coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""), + 0); + + coap_add_resource(context, r); + time_resource = r; + + /* ... Loop waiting for incoming traffic ... */ + while (!not_exit) { + coap_io_process(context, 1000); + + /* Cause a notification to anyone Observing 'time' */ + coap_resource_notify_observers(time_resource, NULL); + } + + /* Clean up */ + + coap_free_context(context); + coap_cleanup(); + +} +---- + +SEE ALSO +-------- +*coap_pdu_setup*(3), *coap_observe*(3), and *coap_resource*(3) + +FURTHER INFORMATION +------------------- +See + +"RFC7252: The Constrained Application Protocol (CoAP)" + +"RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP)" + +for further information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_cache.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_cache.txt.in new file mode 100644 index 000000000..d5e7ff75f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_cache.txt.in @@ -0,0 +1,390 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_cache(3) +============= +:doctype: manpage +:man source: coap_cache +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_cache, +coap_cache_derive_key, +coap_cache_derive_key_w_ignore, +coap_delete_cache_key, +coap_cache_ignore_options, +coap_new_cache_entry, +coap_delete_cache_entry, +coap_cache_get_by_key, +coap_cache_get_by_pdu, +coap_cache_get_pdu, +coap_cache_set_app_data, +coap_cache_get_app_data +- Work with CoAP cache functions + +SYNOPSIS +-------- +*#include * + +*coap_cache_key_t *coap_cache_derive_key(const coap_session_t *_session_, +const coap_pdu_t *_pdu_, coap_cache_session_based_t _session_based_);* + +*coap_cache_key_t *coap_cache_derive_key_w_ignore( +const coap_session_t *_session_, const coap_pdu_t *_pdu_, +coap_cache_session_based_t _session_based_, +const uint16_t *_ignore_options_, size_t _ignore_count_);* + +*void coap_delete_cache_key(coap_cache_key_t *_cache_key_);* + +*int coap_cache_ignore_options(coap_context_t *_context_, +const uint16_t *_options_, size_t _count_);* + +*coap_cache_entry_t *coap_new_cache_entry(coap_session_t *_session_, +const coap_pdu_t *_pdu_, coap_cache_record_pdu_t _record_pdu_, +coap_cache_session_based_t _session_based_, unsigned int _idle_timeout_);* + +*void coap_delete_cache_entry(coap_context_t *_context_, +coap_cache_entry_t *_cache_entry_);* + +*coap_cache_entry_t *coap_cache_get_by_key(coap_context_t *_context_, +const coap_cache_key_t *_cache_key_);* + +*coap_cache_entry_t *coap_cache_get_by_pdu(coap_session_t *_session_, +const coap_pdu_t *_pdu_, coap_cache_session_based_t _session_based_);* + +*const coap_pdu_t *coap_cache_get_pdu(const coap_cache_entry_t *_cache_entry_);* + +*void coap_cache_set_app_data(coap_cache_entry_t *_cache_entry_, void *_data_, +coap_cache_app_data_free_callback_t _callback_);* + +*void *coap_cache_get_app_data(const coap_cache_entry_t *_cache_entry_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- + +The CoAP Cache provides support for two opaque objects that can be used for +tracking requests and responses. + +The first is the ability to derive a Cache Key from the cacheable parts of a +CoAP PDU as defined in +https://tools.ietf.org/html/rfc7252#section-5.6 updated by +https://tools.ietf.org/html/rfc7641#section-2 and +https://tools.ietf.org/html/rfc8132#section-2 . + +The Cache Key is a SHA256 digest if libcoap was built with TLS support, +otherwise it uses the coap_hash() function, using the information abstracted +from the PDU and (optionally) the CoAP session. + +This Cache Key can then be used to match against incoming PDUs and then +appropriate action logic can take place. + +There is support for excluding specific CoAP options from the Cache Key. +Examples could be to exclude CoAP BLOCK1 and BLOCK2 Options for the client or +server for ease of tracking a large PUT or GET response, but to not exclude +these CoAP options in a proxy where it makes sense to cache the individual +blocks. + +The second is providing Cache Entries (which can be looked up by PDU and hence +by Cache Key) which hold additional information to make information tracking +simpler. These Cache Entries are automatically deleted when a session closes +or a context is deleted. These Cache Entries are maintained on a hashed list +for speed of lookup. + +The following enums are defined. + +[source, c] +---- +typedef enum coap_cache_session_based_t { + COAP_CACHE_NOT_SESSION_BASED, + COAP_CACHE_IS_SESSION_BASED +} coap_cache_session_based_t; + +typedef enum coap_cache_record_pdu_t { + COAP_CACHE_NOT_RECORD_PDU, + COAP_CACHE_RECORD_PDU +} coap_cache_record_pdu_t; +---- + +The *coap_cache_derive_key*() function abstracts all the non NoCacheKey CoAP +options, ignores the CoAP Observer option and includes a FETCH body from _pdu_. +If _session_based_ is COAP_CACHE_IS_SESSION_BASED, then _session_ pointer is +also included. CoAP options can be specifically ignored by the use of +*coap_cache_ignore_options*(). A digest is then built from all of the +information and returned. NULL is returned on error. + +The *coap_cache_derive_key_w_ignore*() function abstracts all the non +NoCacheKey CoAP options, ignores the CoAP Observer option and includes a FETCH +body from _pdu_. Further options to ignore are specified by the _ignore_count_ +of _ignore_options_. If _session_based_ is COAP_CACHE_IS_SESSION_BASED, then +_session_ pointer is also included. A digest is then built from all of the +information and returned. NULL is returned on error. + +The *coap_delete_cache_key*() function deletes the _cache_key_ that was +returned from a *coap_cache_derive_key*() call. + +The *coap_cache_ignore_options*() function is used to store in _context_ a +list of _count_ options held in _options_. The specified _options_ will not +be included in the data used for the *coap_cache_derive_key*() function. + +The *coap_new_cache_entry*() function will create a new Cache Entry based on +the Cache Key derived from the _pdu_, _session_based_ and _session_. If +_record_pdu_ is COAP_CACHE_RECORD_PDU, then a copy of the _pdu_ is stored in +the Cache Entry for subsequent retrieval. The Cache Entry can also store +application specific data (*coap_cache_set_app_data*() and +*coap_cache_get_app_data*()). _idle_timeout_ in seconds defines the length of +time not being used before it gets deleted. If _idle_timeout_ is set to +0, then the Cache Entry will not get idle expired. The created Cache +Entry is returned, or NULL on error. + +The *coap_delete_cache_entry*() function can be used to delete the Cache Entry +_cache_entry_ held within _context_. This will remove the Cache Entry from +the hash lookup list and +free off any internally held data. If the Cache Entry is session based, then +it will automatically get deleted when the session is freed off or when the +idle timeout expires. + +The *coap_cache_get_by_key*() function will locate the Cache Entry held in the +_context_ environment that has Cache Key _cache_key_. Returns NULL if the +Cache Key was not found. + +The *coap_cache_get_by_pdu*() function will locate the Cache Entry held in the +_session_ environment that has a Cache Key derived from the _pdu_ and +whether _session_based_ or not. This function calls *coap_cache_derive_key*() +internally, and so normally *coap_cache_ignore_options*() would have +previously been called with COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2 to +ignore the values held within these options. + +The *coap_cache_get_pdu*() function returns the PDU that was stored with the +Cache Entry when it was created with *coap_new_cache_entry*() and _record_pdu_ +was set to COAP_CACHE_RECORD_PDU. If a PDU was not initially stored, NULL is +returned. + +*NOTE:* A copy of the returned PDU must be taken for using in sending a CoAP +packet using *coap_pdu_duplicate*(). + +The *coap_cache_set_app_data*() function is used to associate _data_ with the +_cache_entry_. If _callback_ is not NULL, it points to a function to free off +_data_ when the _cache_entry_ is deleted. If any data has been previously +stored in the _cache_entry_, the pointer to the old data will get overwritten, +but the old data will not get freed off. + +The _callback_ handler function prototype is defined as: +[source, c] +---- +typedef void (*coap_cache_app_data_free_callback_t)(void *data); +---- +where _data_ is passed into the callback function whenever the Cache Entry is +deleted. + +The *coap_cache_get_app_data*() function is used to get the previously stored +_data_ in the _cache_entry_. + +RETURN VALUES +------------- +*coap_cache_derive_key*() and *coap_cache_derive_key_w_ignore*() functions +returns a newly created Cache Key or NULL if there is a creation failure. + +*coap_cache_ignore_options*() function returns 1 if success, 0 on failure. + +*coap_new_cache_entry*(), *coap_cache_get_by_key*() and +*coap_cache_get_by_pdu*() functions return the Cache Entry or NULL if there +is a failure. + +*coap_cache_get_pdu*() function the PDU that is held within the Cache Entry or +NULL if there is no PDU available. + +EXAMPLES +-------- +*PUT Handler supporting BLOCK1* + +[source, c] +---- +#include + +static coap_binary_t *example_data_ptr = NULL; +static int example_data_media_type = COAP_MEDIATYPE_TEXT_PLAIN; + +static void +cache_free_app_data(void *data) { + coap_binary_t *bdata = (coap_binary_t*)data; + coap_delete_binary(bdata); +} + +/* + * Large Data PUT handler + */ + +static void +hnd_put_example_data(coap_context_t *ctx, + coap_resource_t *resource, + coap_session_t *session, + coap_pdu_t *request, + coap_binary_t *token, + coap_string_t *query, + coap_pdu_t *response +) { + size_t size; + const uint8_t *data; + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + size_t offset; + size_t total; + coap_binary_t *data_so_far; + + /* Remove (void) definition if variable is used */ + (void)ctx; + (void)token; + (void)query; + + if (coap_get_data_large(request, &size, &data, &offset, &total) && + size != total) { + /* + * A part of the data has been received (COAP_BLOCK_SINGLE_BODY not set). + * However, total unfortunately is only an indication, so it is not safe to + * allocate a block based on total. As per + * https://tools.ietf.org/html/rfc7959#section-4 + * o In a request carrying a Block1 Option, to indicate the current + * estimate the client has of the total size of the resource + * representation, measured in bytes ("size indication"). + * + * coap_cache_ignore_options() must have previously been called with at + * least COAP_OPTION_BLOCK1 set as the option value will change per block. + */ + coap_cache_entry_t *cache_entry = coap_cache_get_by_pdu(session, + request, + COAP_CACHE_IS_SESSION_BASED); + + if (offset == 0) { + if (!cache_entry) { + /* + * Set idle_timeout parameter to COAP_MAX_TRANSMIT_WAIT if you want + * early removal on transmission failure. 0 means only delete when + * the session is deleted as session_based is set here. + */ + cache_entry = coap_new_cache_entry(session, request, + COAP_CACHE_NOT_RECORD_PDU, + COAP_CACHE_IS_SESSION_BASED, 0); + } + else { + data_so_far = coap_cache_get_app_data(cache_entry); + if (data_so_far) { + coap_delete_binary(data_so_far); + data_so_far = NULL; + } + coap_cache_set_app_data(cache_entry, NULL, NULL); + } + } + if (!cache_entry) { + if (offset == 0) { + coap_log(LOG_WARNING, "Unable to create a new cache entry\n"); + } + else { + coap_log(LOG_WARNING, + "No cache entry available for the non-first BLOCK\n"); + } + coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); + return; + } + + if (size) { + /* Add in the new data to cache entry */ + data_so_far = coap_cache_get_app_data(cache_entry); + data_so_far = coap_block_build_body(data_so_far, size, data, + offset, total); + /* Yes, data_so_far can be NULL if error */ + coap_cache_set_app_data(cache_entry, data_so_far, cache_free_app_data); + } + if (offset + size == total) { + /* All the data is now in */ + data_so_far = coap_cache_get_app_data(cache_entry); + coap_cache_set_app_data(cache_entry, NULL, NULL); + } + else { + /* Give us the next block response */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTINUE); + return; + } + } + else { + /* single body of data received */ + data_so_far = coap_new_binary(size); + if (data_so_far) { + memcpy(data_so_far->s, data, size); + } + } + + if (example_data_ptr) { + /* pre-existed response */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); + coap_delete_binary(example_data_ptr); + } + else + /* just generated response */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); + + example_data_ptr = data_so_far; + if ((option = coap_check_option(request, COAP_OPTION_CONTENT_FORMAT, + &opt_iter)) != NULL) { + example_data_media_type = + coap_decode_var_bytes (coap_opt_value (option), + coap_opt_length (option)); + } + else { + example_data_media_type = COAP_MEDIATYPE_TEXT_PLAIN; + } + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); + coap_resource_notify_observers(resource, NULL); +} + +int main(int argc, char* argv[]){ + coap_context_t *ctx = NULL; /* Set up as normal */ + /* ... */ + uint16_t cache_ignore_options[] = { COAP_OPTION_BLOCK1, + COAP_OPTION_BLOCK2 }; + + /* Remove (void) definition if variable is used */ + (void)argc; + (void)argv; + + /* ... */ + + /** Define the options to ignore when setting up cache-keys */ + coap_cache_ignore_options(ctx, cache_ignore_options, + sizeof(cache_ignore_options)/sizeof(cache_ignore_options[0])); + + /* ... */ + +} +---- + +SEE ALSO +-------- +*coap_block*(3), *coap_pdu_setup*(3), *coap_resource*(3) and *coap_string*(3) + +FURTHER INFORMATION +------------------- +See + +"RFC7252: The Constrained Application Protocol (CoAP)" + +"RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP)" + +for further information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_context.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_context.txt.in new file mode 100644 index 000000000..53579d292 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_context.txt.in @@ -0,0 +1,149 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_context(3) +=============== +:doctype: manpage +:man source: coap_context +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_context, +coap_new_context, +coap_free_context, +coap_context_set_max_idle_sessions, +coap_context_get_max_idle_sessions, +coap_context_set_max_handshake_sessions, +coap_context_get_max_handshake_sessions, +coap_context_set_session_timeout, +coap_context_get_session_timeout, +coap_context_set_csm_timeout, +coap_context_get_csm_timeout +- Work with CoAP contexts + +SYNOPSIS +-------- +*#include * + +*coap_context_t *coap_new_context(const coap_address_t *_listen_addr_);* + +*void coap_free_context(coap_context_t *_context_);* + +*void coap_context_set_max_idle_sessions(coap_context_t *_context_, +unsigned int _max_idle_sessions_);* + +*unsigned int coap_context_get_max_idle_sessions( +const coap_context_t *_context_);* + +*void coap_context_set_max_handshake_sessions(coap_context_t *_context_, +unsigned int _max_handshake_sessions_);* + +*unsigned int coap_context_get_max_handshake_sessions( +const coap_context_t *_context_);* + +*void coap_context_set_session_timeout(coap_context_t *_context_, +unsigned int _session_timeout_);* + +*unsigned int coap_context_get_session_timeout( +const coap_context_t *_context_);* + +*void coap_context_set_csm_timeout(coap_context_t *_context_, +unsigned int _csm_timeout_);* + +*unsigned int coap_context_get_csm_timeout(const coap_context_t *_context_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +This man page focuses on the CoAP Context and how to update or get information +from the opaque coap_context_t structure. + +The CoAP stack's global state is stored in a coap_context_t Context object. +Resources, Endpoints and Sessions are associated with this context object. +There can be more than one coap_context_t object per application, it is up to +the application to manage each one accordingly. + +The *coap_new_context*() function creates a new Context that is then used +to keep all the CoAP Resources, Endpoints and Sessions information. +The optional _listen_addr_ parameter, if set for a CoAP server, creates an +Endpoint that is added to the _context_ that is listening for un-encrypted +traffic on the IP address and port number defined by _listen_addr_. + +The *coap_free_context*() function must be used to release the CoAP stack +_context_. It clears all entries from the receive queue and send queue and +deletes the Resources that have been registered with _context_, and frees the +attached Sessions and Endpoints. + +The *coap_context_set_max_idle_sessions*() function sets the maximum number of +idle server sessions to _max_idle_sessions_ for _context_. If this number is +exceeded, the least recently used server session is completely removed. 0 (the +initial default) means that the number of idle sessions is not monitored. + +The *coap_context_get_max_idle_sessions*() function returns the maximum number +of idle server sessions for _context_. + +The *coap_context_set_max_handshake_sessions*() function sets the maximum +number of outstanding server sessions in (D)TLS handshake to +_max_handshake_sessions_ for _context_. If this number is exceeded, the least +recently used server session in handshake is completely removed. 0 (the default) +means that the number of handshakes is not monitored. + +The *coap_context_get_max_handshake_sessions*() function returns the maximum +number of outstanding server sessions in (D)TLS handshake for _context_. + +The *coap_context_set_session_timeout*() function sets the number of seconds of +inactivity to _session_timeout_ for _context_ before an idle server session is +removed. 0 (the default) means wait for the default of 300 seconds. + +The *coap_context_get_session_timeout*() function returns the seconds to wait +before timing out an idle server session for _context_. + +The *coap_context_set_csm_timeout*() function sets the number of seconds to +wait for a (TCP) CSM negotiation response from the peer to _csm_timeout_ for +_context_. 0 (the default) means wait forever. + +The *coap_context_get_csm_timeout*() function returns the seconds to wait for +a (TCP) CSM negotiation response from the peer for _context_, + +RETURN VALUES +------------- +*coap_new_context*() function returns a newly created context or +NULL if there is a creation failure. + +*coap_context_get_max_idle_sessions*() returns the maximum number of idle +server sessions. + +*coap_context_get_max_handshake_sessions*() returns the maximum number of +outstanding server sessions in (D)TLS handshake. + +*coap_context_get_session_timeout*() returns the seconds to wait before timing +out an idle server session. + +*coap_context_get_csm_timeout*() returns the seconds to wait for a (TCP) CSM +negotiation response from the peer. + +SEE ALSO +-------- +*coap_session*(3) + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_encryption.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_encryption.txt.in new file mode 100644 index 000000000..da81c024e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_encryption.txt.in @@ -0,0 +1,1237 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_encryption(3) +=================== +:doctype: manpage +:man source: coap_encryption +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_encryption, +coap_dtls_cpsk_t, +coap_dtls_spsk_t, +coap_dtls_pki_t +- Work with CoAP TLS/DTLS + +SYNOPSIS +-------- +*#include * + +*struct coap_dtls_cpsk_t;* + +*struct coap_dtls_spsk_t;* + +*struct coap_dtls_pki_t;* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +This man page focuses on setting up CoAP to use encryption. + +When the libcoap library was built, it will have been compiled using a +specific underlying TLS implementation type (e.g. OpenSSL, GnuTLS, Mbed TLS, +TinyDTLS or noTLS). +When the libcoap library is linked into an application, it is possible +that the application needs to dynamically determine whether DTLS or TLS is +supported, what type of TLS implementation libcoap was compiled with, as well +as detect what is the version of the currently loaded TLS library. + +*NOTE:* If OpenSSL is being used, then the minimum supported OpenSSL library +version is 1.1.0. + +*NOTE:* If GnuTLS is being used, then the minimum GnuTLS library version is +3.3.0. + +*NOTE:* If Mbed TLS is being used, then the minimum Mbed TLS library version is +2.7.10. + +*NOTE:* If GnuTLS is going to interoperate with TinyDTLS, then a minimum +revision of GnuTLS 3.5.5 which supports CCM algorithms is required +by TinyDTLS as TinyDTLS currently only supports CCM. + +*NOTE:* For Raw Public Key support, GnuTLS library version must be 3.6.6 or +later. TinyDTLS only supports TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, curve +secp256r1 and hash SHA-256. There currently is no OpenSSL or Mbed TLS RPK support +(respective library limitations). + +Network traffic can be un-encrypted or encrypted with libcoap if there is an +underlying TLS library. + +If TLS is going to be used for encrypting the network traffic, then the TLS +information for Pre-Shared Keys (PSK), Public Key Infrastructure (PKI) or +Raw Public Key (RPK) needs to be configured before any network traffic starts +to flow. For Servers, this has to be done before the Endpoint is created, +for Clients, this is done during the Client Session set up. + +For Servers, all the encryption information is held internally by the TLS +Context level and the CoAP Context level as the Server is listening for new +incoming traffic based on the Endpoint definition. The TLS and CoAP session +will not get built until the new traffic starts, which is done by the libcoap +library, with the session having a reference count of 1. + +For Clients, all the encryption information will be held internally by the TLS +Context and/or TLS Session level and internally by the CoAP Session level. + +In principle the set-up sequence for CoAP Servers looks like +---- +coap_new_context() +coap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI +coap_context_set_pki() and/or coap_context_set_psk2() - if encryption is required +coap_new_endpoint() +---- + +Multiple endpoints can be set up per Context, each listening for a new traffic +flow with different TCP/UDP protocols, TLS protocols, port numbers etc. When a +new traffic flow is started, then the CoAP library will create and start a new +server session. + +In principle the set-up sequence for CoAP Clients looks like +---- +coap_new_context() +coap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI +coap_new_client_session(), coap_new_client_session_pki() or coap_new_client_session_psk2() +---- + +Multiple client sessions are supported per Context. + +Due to the nature of TLS, there are Callbacks that are invoked as the TLS +session negotiates encryption algorithms, encryption keys etc. +Where possible, the CoAP layer handles all this automatically based on +different configuration options passed in by the coap_context_set_pki(), +coap_new_client_session_pki(), coap_context_set_psk2() and +coap_new_client_session_psk2() functions. + +PSK CLIENT INFORMATION +---------------------- + +For Client PSK setup, the required information needs to be provided in the setup +calls with optional application callbacks defined to update the Identity and +PSK. Initially, the Client has to provide an Identity and a Pre-Shared Key. + +Libcoap will put the Identity and Pre-Shared Key as appropriate into the TLS +environment. + +*SECTION: PSK Client: coap_dtls_cpsk_t* +[source, c] +---- +typedef struct coap_dtls_cpsk_t { + uint8_t version; /** Set to COAP_DTLS_CPSK_SETUP_VERSION + to support the version of the struct */ + + /* Options to enable different TLS functionality in libcoap */ + uint8_t reserved[7]; /* Reserved - must be set to 0 for + future compatibility */ + + /** Identity Hint check callback function. + * If not NULL, is called when the Identity Hint (TLS1.2 or earlier) is + * provided by the server. + * The appropriate Identity and Pre-Shared Key to use can then be returned. + */ + coap_dtls_ih_callback_t validate_ih_call_back; + void *ih_call_back_arg; /* Passed in to the Identity Hint callback + function */ + + char* client_sni; /* If not NULL, SNI to use in client TLS setup. + Owned by the client app and must remain valid + during the call to coap_new_client_session_pki(). + Note: Not supported by TinyDTLS. */ + + coap_dtls_cpsk_info_t psk_info; /* Client PSK definition */ +} coap_dtls_cpsk_t; +---- + +More detailed explanation of the coap_dtls_cpsk_t structure follows. + +*WARNING*: For all the parameter definitions that are pointers to other +locations, these locations must remain valid during the lifetime of all the +underlying TLS sessions that are, or will get created based on this PSK +definition. + +*SECTION: PSK Client: coap_dtls_cpsk_t: Version* +[source, c] +---- +#define COAP_DTLS_CPSK_SETUP_VERSION 1 /**< Latest CPSK setup version */ +---- + +*version* is set to COAP_DTLS_CPSK_SETUP_VERSION. This will then allow +support for different versions of the coap_dtls_cpsk_t structure in the future. + +*SECTION: PSK Client: coap_dtls_cpsk_t: Reserved* + +*reserved* All must be set to 0. Future functionality updates will make use of +these reserved definitions. + +*SECTION: PSK Client: coap_dtls_cpsk_t: Identity Hint Callback* +[source, c] +---- +/** + * Identity Hint Validation callback that can be set up by + * coap_new_client_session_psk2(). + * Invoked when libcoap has done the validation checks at the TLS level, + * but the application needs to check that the Identity Hint is allowed, and + * needs to use the appropriate PSK information for the (D)TLS session. + * Note: Identity Hint is not supported in (D)TLS1.3. + * + * @param hint The server provided Identity Hint + * @param coap_session The CoAP session associated with the Identity Hint + * @param arg The same as was passed into coap_new_client_session_psk2() + * in setup_data->ih_call_back_arg + * + * @return New coap_dtls_cpsk_info_t object or @c NULL on error. + */ +typedef const coap_dtls_cpsk_info_t *(*coap_dtls_ih_callback_t)( + coap_str_const_t *hint, + coap_session_t *coap_session, + void *arg); +---- + +*validate_ih_call_back* points to an application provided Identity Hint callback +function or NULL. The application can make use of this Identity Hint information +to decide what Identity and Pre-Shared Key should be used for this session. +The Callback returns the new coap_dtls_cpsk_info_t on success, +or NULL if the Identity Hint is unacceptable. + +*NOTE:* The Server may not provide a hint, or a zero length hint to indicate +there is no hint. In this case the initially provided Identity and +Pre-Shared Key should be used. + +*ih_call_back_arg* points to a user defined set of data that will get passed +in to the validate_ih_call_back() function's arg parameter and can be used by +that function. An example would be a set of Identity Hints that map into new +Identity / Pre-Shared Key to use. + +*SECTION: PSK Client: coap_dtls_cpsk_t: Subject Name Indicator (SNI) Definition* + +*client_sni* points to the SNI name that will be added in as a TLS extension, +if not NULL. This typically is the DNS name of the server that the client is +trying to contact. The server is then able to decide, based on the name in the +SNI extension, whether, for example, a different Hint and/or Pre-Shared Key is +to be used. + +Note: Not supported by TinyDTLS. + +*SECTION: PSK Client: coap_dtls_cpsk_t: PSK Client Definitions* +[source, c] +---- +typedef struct coap_dtls_cpsk_info_t { + coap_bin_const_t identity; /* The Identity */ + coap_bin_const_t key; /* The Pre-Shared Key */ +} coap_dtls_cpsk_info_t; +---- + +*identity* defines the Identity to use. + +*key* defines the Pre-Shared Key to use + +PSK SERVER INFORMATION +---------------------- + +For PSK setup, the required information needs to be provided in the setup +calls with optional application Callbacks defined to update the Identity Hint +and Pre-SHared Key. Initially, the Server has to provided with an (optional) +Identity Hint and a (required) Pre-Shared Key. + +Libcoap will put the Hint and Pre-Shared Key as appropriate into the TLS +environment. + +*SECTION: PSK Server: coap_dtls_spsk_t* +[source, c] +---- +typedef struct coap_dtls_spsk_t { + uint8_t version; /** Set to COAP_DTLS_SPSK_SETUP_VERSION + to support the version of the struct */ + + /* Options to enable different TLS functionality in libcoap */ + uint8_t reserved[7]; /* Reserved - must be set to 0 for + future compatibility */ + + /** Identity check callback function. + * If not @p NULL, is called when the Identity is provided by the client. + * The appropriate Pre-Shared Key to use can then be returned. + */ + coap_dtls_id_callback_t validate_id_call_back; + void *id_call_back_arg; /* Passed in to the Identity callback function */ + + /** SNI check callback function. + * If not @p NULL, called if the SNI is not previously seen and exexuted + * prior to sending an Identity Hint back to the client so that the + * appropriate PSK information can be used based on the requesting SNI. + */ + coap_dtls_psk_sni_callback_t validate_sni_call_back; + void *sni_call_back_arg; /* Passed in to the SNI callback function */ + + coap_dtls_spsk_info_t psk_info; /* Server PSK definition */ +} coap_dtls_spsk_t; +---- + +More detailed explanation of the coap_dtls_spsk_t structure follows. + +*WARNING*: For all the parameter definitions that are pointers to other +locations, these locations must remain valid during the lifetime of all the +underlying TLS sessions that are, or will get created based on this PSK +definition. + +*SECTION: PSK Server: coap_dtls_spsk_t: Version* +[source, c] +---- +#define COAP_DTLS_SPSK_SETUP_VERSION 1 /**< Latest SPSK setup version */ +---- + +*version* is set to COAP_DTLS_SPSK_SETUP_VERSION. This will then allow +support for different versions of the coap_dtls_spsk_t structure in the future. + +*SECTION: PSK Server: coap_dtls_spsk_t: Reserved* + +*reserved* All must be set to 0. Future functionality updates will make use of +these reserved definitions. + +*SECTION: PSK Server: coap_dtls_spsk_t: Identity Validation Callback* +[source, c] +---- +/** + * Identity Validation callback that can be set up by + * coap_context_set_psk2(). + * Invoked when libcoap has done the validation checks at the TLS level, + * but the application needs to check that the Identity is allowed, and + * needs to use the appropriate Pre-Shared Key for the (D)TLS session. + * + * @param identity The client provided Identity (should be NULL terminated) + * @param coap_session The CoAP session associated with the Identity Hint + * @param arg The same as was passed into coap_context_set_psk2() + * in setup_data->id_call_back_arg + * + * @return New coap_bin_const_t Pre-Shared Key object or @c NULL on error. + */ +typedef const coap_bin_const_t *(*coap_dtls_id_callback_t)( + coap_bin_const_t *identity, + coap_session_t *coap_session, + void *arg); +---- + +*WARNING:* If both *validate_id_call_back* and *validate_sni_call_back* are +defined, validate_id_call_back() is invoked after validate_sni_call_back(), +and so if the Pre-Shared Key is changed in validate_sni_call_back(), +validate_id_call_back() needs to be sure that the appropriate Pre-Shared Key +is provided. + +*validate_id_call_back* points to an application provided Identity callback +function or NULL. The application can make use of this Identity information +to decide what PSK should be used for this session. +The Callback returns the new coap_bin_const_t Pre-Shared Key on success, +or NULL if the Identity is unacceptable. + +*NOTE:* The Client may be using a binary Identity that contains an embedded +zero. However OpenSSL and GnuTLS do not currently support this. + +*id_call_back_arg* points to a user defined set of data that will get passed +in to the validate_id_call_back() function and can be used by that function. +An example would be a set of Identities that map into new Pre-Shared Keys +to use. + +*SECTION: PSK Server: coap_dtls_spsk_t: Subject Name Identifier (SNI) Callback* +[source, c] +---- +/** + * PSK SNI callback that can be set up by coap_context_set_psk2(). + * Invoked when libcoap has done the validation checks at the TLS level, + * but the application needs to check that the SNI is allowed, and needs + * to use the appropriate PSK information for the (D)TLS session. + * + * @param sni The client provided SNI + * @param coap_session The CoAP session associated with the SNI + * @param arg The same as was passed into coap_new_client_session_psk2() + * in setup_data->sni_call_back_arg + * + * @return New coap_dtls_spsk_info_t object or @c NULL on error. + */ +typedef const coap_dtls_spsk_info_t *(*coap_dtls_psk_sni_callback_t)( + const char *sni, + coap_session_t *coap_session, + void *arg); +---- + +*validate_sni_call_back* points to an application provided SNI callback +checking function or NULL. The application can make use of this SNI information +to decide whether the SNI is valid, and hence what new Hint and Pre-Shared Key +to use. +Thus it is possible for the coap server to host multiple domains with +different Hints and PSKs allocated to each SNI domain. +The Callback returns a coap_dtls_spsk_info_t pointer to the Hint and +Pre-Shared Key to use for this SNI, or NULL if the connection is to get +rejected. Libcoap remembers the association between a specific SNI and Hint + +Pre-Shared Key set and will only invoke this callback if the SNI is unknown. + +Note: Not supported by TinyDTLS. + +*sni_call_back_arg* points to a user defined set of data that will get passed +in to the validate_sni_call_back() function and can be used by that function. +An example would be a set of SNIs that are allowed with their matching +Hint + Pre-Shared Key sets. + +*SECTION: PSK Server: coap_dtls_spsk_t: PSK Information Definitions* +[source, c] +---- +typedef struct coap_dtls_spsk_info_t { + coap_bin_const_t hint; /* The identity hint to use */ + coap_bin_const_t key; /* The Pre-Shared Key to use */ +} coap_dtls_spsk_info_t; +---- + +*identity* defines the Identity Hint to use. + +*key* defines the Pre-Shared Key to use + +PKI/RPK CLIENT AND SERVER INFORMATION +------------------------------------- + +For PKI or RPK setup, if the libcoap PKI/RPK configuration options do not +handle a specific requirement as defined by the available options, then an +application defined Callback can called to do the additional specific checks. + +The information passed to this Application Callback will be the +TLS session (as well the configuration information), but the structures +containing this information will be different as they will be based on the +underlying TLS library type. coap_get_tls_library_version() is provided to help +here. + +Libcoap will add in the defined Certificate (or Public Key), Private Key and +CA Certificate into the TLS environment. The CA Certificate is also added +in to the list of valid CAs for Certificate checking. + +The internal Callbacks (and optionally the Application Callback) will then +check the required information as defined in the coap_dtls_pki_t described +below. + +*SECTION: PKI/RPK: coap_dtls_pki_t* +[source, c] +---- +typedef struct coap_dtls_pki_t { + uint8_t version; /* COAP_DTLS_PKI_SETUP_VERSION */ + + /* Options to enable different TLS functionality in libcoap */ + uint8_t verify_peer_cert; /* 1 if peer cert is to be verified */ + uint8_t check_common_ca; /* 1 if peer cert is to be signed by + * the same CA as the local cert */ + uint8_t allow_self_signed; /* 1 if self-signed certs are allowed */ + uint8_t allow_self_signed; /* 1 if self-signed certs are allowed. + * Ignored if check_common_ca set */ + uint8_t allow_expired_certs; /* 1 if expired certs are allowed */ + uint8_t cert_chain_validation; /* 1 if to check cert_chain_verify_depth */ + uint8_t cert_chain_verify_depth; /* recommended depth is 3 */ + uint8_t check_cert_revocation; /* 1 if revocation checks wanted */ + uint8_t allow_no_crl; /* 1 ignore if CRL not there */ + uint8_t allow_expired_crl; /* 1 if expired crl is allowed */ + uint8_t allow_bad_md_hash; /* 1 if unsupported MD hashes are allowed */ + uint8_t allow_short_rsa_length; /* 1 if small RSA keysizes are allowed */ + uint8_t is_rpk_not_cert; /* 1 is RPK instead of Public Certificate. + * If set, PKI key format type cannot be + * COAP_PKI_KEY_PEM */ + uint8_t reserved[3]; /* Reserved - must be set to 0 for + future compatibility */ + + /** CN check callback function + * If not NULL, is called when the TLS connection has passed the configured + * TLS options above for the application to verify if the CN is valid. + */ + coap_dtls_cn_callback_t validate_cn_call_back; + void *cn_call_back_arg; /* Passed in to the CN callback function */ + + /** SNI check callback function + * If not NULL, called if the SNI is not previously seen and prior to sending + * a certificate set back to the client so that the appropriate certificate + * set can be used based on the requesting SNI. + */ + coap_dtls_sni_callback_t validate_sni_call_back; + void *sni_call_back_arg; /* Passed in to the SNI callback function */ + + /** Additional Security callback handler that is invoked when libcoap has + * done the standard, defined validation checks at the TLS level, + * If not NULL, called from within the TLS Client Hello connection + * setup. + */ + coap_dtls_security_setup_t additional_tls_setup_call_back; + + char* client_sni; /* If not NULL, SNI to use in client TLS setup. + Owned by the client app and must remain valid + during the call to coap_new_client_session_pki() */ + + coap_dtls_key_t pki_key; /* PKI key definition */ +} coap_dtls_pki_t; +---- + +More detailed explanation of the coap_dtls_pki_t structure follows. + +*WARNING*: For all the parameter definitions that are pointers to other +locations, these locations must remain valid during the lifetime of all the +underlying TLS sessions that are, or will get created based on this PKI/RPK +definition. + +The first parameter in each subsection enables/disables the functionality, the +remaining parameter(s) control what happens when the functionality is +enabled. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Version* +[source, c] +---- +#define COAP_DTLS_PKI_SETUP_VERSION 1 +---- + +*version* is set to COAP_DTLS_PKI_SETUP_VERSION. This will then allow support +for different versions of the coap_dtls_pki_t structure in the future. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Peer Certificate Checking* + +*verify_peer_cert* Set to 1 to check that the peer's certificate is valid if +provided, else 0. If not set, check_common_ca, allow_self_signed, +allow_expired_certs, cert_chain_validation, cert_chain_verify_depth, +check_cert_revocation, allow_no_crl, allow_expired_crl, allow_bad_md_hash +and allow_short_rsa_length settings are all ignored. + +*check_common_ca* Set to 1 to check that the CA that signed the peer's +certificate is the same CA that signed the local certificate +else 0. If set to 1 and *verify_peer_cert* is set to 1, then for the server, a +list of valid CAs are sent to client. For the client, the logic will check +that both the client and server certificates are signed by the same CA. + +*allow_self_signed* Set to 1 to allow the peer (or any certificate in the +certificate chain) to be a self-signed certificate, else 0. If +*check_common_ca* is set, then a self-signed certificate will not be allowed. + +*allow_expired_certs* Set to 1 to allow certificates that have either expired, +or are not yet valid to be allowed, else 0. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Certificate Chain Validation* + +*cert_chain_validation* Set to 1 to check that the certificate chain is valid, +else 0. + +*cert_chain_verify_depth* Set to the chain depth that is to be checked. This +is the number of intermediate CAs in the chain. If set to 0, then there can be +no intermediate CA in the chain. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Certificate Revocation* + +*check_cert_revocation* Set to 1 to check whether any certificate in the chain +has been revoked, else 0. + +*allow_no_crl* Set to 1 to not check any certificate that does not have a CRL, +else 0. + +*allow_expired_crl* Set to 1 to allow an certificate that has an expired CRL +definition to be valid, else 0. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Other* + +*allow_bad_md_hash* Set to 1 if unsupported MD hashes are allowed, else 0. + +*allow_short_rsa_length* Set to 1 if small RSA keysizes are allowed, else 0. + +*is_rpk_not_cert* Set to 1 if the Certificate is actually a Raw Public Key. +If set, PKI key format type cannot be COAP_PKI_KEY_PEM. If set, +check_common_ca, allow_self_signed, allow_expired_certs, +cert_chain_validation, cert_chain_verify_depth, check_cert_revocation, +allow_no_crl, allow_expired_crl, allow_bad_md_hash and +allow_short_rsa_length settings are all ignored. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Reserved* + +*reserved* All must be set to 0. Future functionality updates will make use of +these reserved definitions. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Common Name (CN) Callback* +[source, c] +---- +#define COAP_DTLS_RPK_CERT_CN "RPK" + +/** + * CN Validation callback that can be set up by coap_context_set_pki(). + * Invoked when libcoap has done the validation checks at the TLS level, + * but the application needs to check that the CN is allowed. + * CN is the SubjectAltName in the cert, if not present, then the leftmost + * Common Name (CN) component of the subject name. + * NOTE: If using RPK, then the Public Key does not contain a CN, but the + * content of COAP_DTLS_RPK_CERT_CN is presented for the @p cn parameter. + * + * @param cn The determined CN from the certificate + * @param asn1_public_cert The ASN.1 encoded (DER) X.509 certificate + * @param asn1_length The ASN.1 length + * @param session The coap session associated with the certificate update + * @param depth Depth in cert chain. If 0, then client cert, else a CA + * @param validated TLS can find no issues if 1 + * @param arg The same as was passed into coap_context_set_pki() + * in setup_data->cn_call_back_arg + * + * @return 1 if accepted, else 0 if to be rejected + */ +typedef int (*coap_dtls_cn_callback_t)(const char *cn, + const uint8_t *asn1_public_cert, + size_t asn1_length, + coap_session_t *session, + unsigned int depth, + int validated, + void *arg); +---- + +*validate_cn_call_back* points to an application provided CN callback +checking function or NULL. The application can make use of this CN information +to decide, for example, that the CN is valid coming from a particular peer. +The Callback returns 1 on success, 0 if the TLS connection is to be aborted. + +*cn_call_back_arg* points to a user defined set of data that will get passed +in to the validate_cn_call_back() function and can be used by that function. +An example would be a set of CNs that are allowed. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Subject Name Identifier (SNI) Callback* +[source, c] +---- +typedef struct coap_dtls_key_t { + coap_pki_key_t key_type; /* key format type */ + union { + coap_pki_key_pem_t pem; /* for PEM file keys */ + coap_pki_key_pem_buf_t pem_buf; /* for PEM memory keys */ + coap_pki_key_asn1_t asn1; /* for ASN.1 (DER) memory keys */ + coap_pki_key_pkcs11_t pkcs11; /* for PKCS11 keys */ + } key; +} coap_dtls_key_t; + +/** + * SNI Validation callback that can be set up by coap_context_set_pki(). + * Invoked if the SNI is not previously seen and prior to sending a certificate + * set back to the client so that the appropriate certificate set can be used + * based on the requesting SNI. + * + * @param sni The requested SNI + * @param arg The same as was passed into coap_context_set_pki() + * in setup_data->sni_call_back_arg + * + * @return new set of certificates to use, or NULL if SNI is to be rejected. + */ +typedef coap_dtls_key_t *(*coap_dtls_sni_callback_t)(const char *sni, + void* arg); +---- + +*validate_sni_call_back* points to an application provided SNI callback +checking function or NULL. The application can make use of this SNI information +to decide whether the SNI is valid, and what set of certificates to give to the +client. Thus it is possible for the coap server to host multiple domains with +different certificates allocated to each domain. +The Callback returns a pointer to the certificates to use for this SNI, or NULL +if the connection it to get rejected. libcoap remembers the association +between the SNI and Certificate set and will only invoke this callback if the +SNI is unknown. + +*sni_call_back_arg* points to a user defined set of data that will get passed +in to the validate_sni_call_back() function and can be used by that function. +An example would be a set of SNIs that are allowed with their matching +certificate sets. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Application Additional Setup Callback* +[source, c] +---- +/** + * Additional Security setup handler that can be set up by + * coap_context_set_pki(). + * Invoked when libcoap has done the validation checks at the TLS level, + * but the application needs to do some additional checks/changes/updates. + * + * @param session The security session definition - e.g. SSL * for OpenSSL. + * This will be dependent on the underlying TLS library + * - see coap_get_tls_library_version() + * @param setup_data A structure containing setup data originally passed into + * coap_context_set_pki() or coap_new_client_session_pki(). + * @return 1 if successful, else 0 + */ +typedef int (*coap_dtls_security_setup_t)(void *context, void* session, + coap_dtls_pki_t *setup_data); +---- + +*additional_tls_setup_call_back* points to an application provided callback +function that will do additional checking/changes/updates after libcoap has +done all of the configured TLS setup checking, or NULL to do no additional +checking. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Subject Name Indicator (SNI) Definition* + +*client_sni* points to the SNI name that will be added in as a TLS extension, +or set NULL. This typically is the DNS name of the server that the client is +trying to contact. This is only used by a client application and the server +is then able to decide, based on the name in the SNI extension, whether, for +example, a different certificate should be provided. + +*SECTION: PKI/RPK: coap_dtls_pki_t: Key Type Definition* +[source, c] +---- +typedef enum coap_pki_key_t { + COAP_PKI_KEY_PEM, /* The PKI key type is PEM file */ + COAP_PKI_KEY_ASN1, /* The PKI key type is ASN.1 (DER) buffer */ + COAP_PKI_KEY_PEM_BUF, /* The PKI key type is PEM buffer */ + COAP_PKI_KEY_PKCS11, /* The PKI key type is PKCS11 (DER) */ +} coap_pki_key_t; +---- + +*key_type* defines the format that the certificates / keys are provided in. +This can be COAP_PKI_KEY_PEM, COAP_PKI_KEY_PEM_BUF, COAP_PKI_KEY_ASN1 or +COAP_PKI_KEY_PKCS11. + +*SECTION: PKI: coap_dtls_pki_t: PEM Key Definitions* +[source, c] +---- +typedef struct coap_pki_key_pem_t { + const char *ca_file; /* File location of Common CA in PEM format */ + const char *public_cert; /* File location of Public Cert */ + const char *private_key; /* File location of Private Key in PEM format */ +} coap_pki_key_pem_t; +---- + +*key.pem.ca_file* points to the CA File location on disk which will be in +PEM format, or NULL. This file should only contain one CA (that has signed the +public certificate) as this is passed from the server to the client when +requesting the client's certificate. This certificate is also added into +the valid root CAs list if not already present. + +*key.pem.public_cert* points to the public certificate location on disk which +will be in PEM format. + +*key.pem.private_key* points to the private key location on disk which +will be in PEM format. This file cannot be password protected. + +*SECTION: PKI/RPK: coap_dtls_pki_t: PEM Memory Key Definitions* +[source, c] +---- +typedef struct coap_pki_key_pem_buf_t { + const uint8_t *ca_cert; /* PEM buffer Common CA Cert */ + const uint8_t *public_cert; /* PEM buffer Public Cert, or Public Key if RPK */ + const uint8_t *private_key; /* PEM buffer Private Key */ + If RPK and 'EC PRIVATE KEY' this can be used + for both the public_cert and private_key */ + size_t ca_cert_len; /* PEM buffer CA Cert length */ + size_t public_cert_len; /* PEM buffer Public Cert length */ + size_t private_key_len; /* PEM buffer Private Key length */ +} coap_pki_key_pem_buf_t; +---- + +*key.pem_buf.ca_cert* points to the CA location in memory which will be in +PEM format, or NULL. This file should only contain one CA (that has signed the +public certificate) as this is passed from the server to the client when +requesting the client's certificate. This certificate is also added into +the valid root CAs list if not already present. + +*key.pem_buf.ca_cert_len* is the length of the CA. + +*key.pem_buf.public_cert* points to the public certificate (or public key if +RPK) location in memory which will be in PEM format. + +*key.pem_buf.public_cert_len* is the length of the public certificate. + +*key.pem_buf.private_key* points to the private key location in memory which +will be in PEM format. This data cannot be password protected. If RPK and +'EC PRIVATE KEY' this can be used for both the public_cert and private_key. + +*key.pem_buf.private_key* is the length of the private key. + +* Note:* The PEM buffer Certs and Key should be be NULL terminated strings for +performance reasons (to save a potential buffer copy) and the length include +this NULL terminator. It is not a requirement to have the NULL terminator +though and the length must then reflect the actual data size. + +*SECTION: PKI/RPK: coap_dtls_pki_t: ASN1 Key Definitions* +[source, c] +---- +typedef struct coap_pki_key_asn1_t { + const uint8_t *ca_cert; /* ASN1 Common CA Certificate */ + const uint8_t *public_cert; /* ASN1 (DER) Public Cert, or Public Key if RPK */ + const uint8_t *private_key; /* ASN1 Private Key */ + int ca_cert_len; /* ASN1 CA Certificate length */ + int public_cert_len; /* ASN1 Public Certificate length */ + int private_key_len; /* ASN1 Private Key length */ + coap_asn1_privatekey_type_t private_key_type; /* Private Key Type + COAP_ASN1_PKEY_* */ +} coap_pki_key_asn1_t; + +typedef enum coap_asn1_privatekey_type_t { + COAP_ASN1_PKEY_NONE, + COAP_ASN1_PKEY_RSA, + COAP_ASN1_PKEY_RSA2, + COAP_ASN1_PKEY_DSA, + COAP_ASN1_PKEY_DSA1, + COAP_ASN1_PKEY_DSA2, + COAP_ASN1_PKEY_DSA3, + COAP_ASN1_PKEY_DSA4, + COAP_ASN1_PKEY_DH, + COAP_ASN1_PKEY_DHX, + COAP_ASN1_PKEY_EC, + COAP_ASN1_PKEY_HMAC, + COAP_ASN1_PKEY_CMAC, + COAP_ASN1_PKEY_TLS1_PRF, + COAP_ASN1_PKEY_HKDF +} coap_asn1_privatekey_type_t; +---- + +*key.asn1.ca_cert* points to a DER encoded ASN.1 definition of the CA +Certificate, or NULL. This certificate is passed from the server to the client +when requesting the client's certificate. This certificate is also added into +the valid root CAs list if not already present. + +*key.asn1.public_cert* points to a DER encoded ASN.1 definition of the +public certificate (or public key if RPK). + +*key.asn1.private_key* points to DER encoded ASN.1 definition of the +private key. + +*key.asn1.ca_cert_len* is the length of the DER encoded ASN.1 definition of +the CA Certificate. + +*key.asn1.public_cert_len* is the length of the DER encoded ASN.1 definition +of the public certificate. + +*key.asn1.private_key_len* is the length of the DER encoded ASN.1 definition +of the private key. + +*key.asn1.private_key_type* is the encoding type of the DER encoded ASN.1 +definition of the private key. This will be one of the COAP_ASN1_PKEY_* +definitions. + +*SECTION: PKI: coap_dtls_pki_t: PKCS11 Key Definitions* +[source, c] +---- +typedef struct coap_pki_key_pkcs11_t { + const char *ca; /* pkcs11: URI for Common CA Certificate */ + const char *public_cert; /* pkcs11: URI for Public Cert */ + const char *private_key; /* pkcs11: URI for Private Key */ + const char *pin; /* pin to access PKCS11. If NULL, then + pin-value= parameter must be set in + pkcs11: URI as a query. */ +} coap_pki_key_pkcs11_t; +---- + +*key.pkcs11.ca* is a pkcs11: URI for the CA certificate or NULL. This is for +the CA (that has signed the public certificate) as this is passed from the +server to the client when requesting the client's certificate. This certificate +is also added into the valid root CAs list if not already present. +An example URI is 'pkcs11:pkcs11:token=My%20Token;id=%aa%bb%cc%dd' which is +for token 'My Token' and (hex) id of 'aabbccdd'. + +*key.pkcs11.public_cert* is a pkcs11: URI for the Public Certificate which +was signed by *key.pkcs11.ca* or NULL. + +*key.pkcs11.private_key* is a pkcs11: URI for the Private Key for the +public certificate defined by *key.pkcs11.public_cert* or NULL. + +*key.pkcs11.user_pin* is the user pin used to unlock the token or NULL. +If NULL, the pin can be defined on the other pkcs11: URI entries by using +pin-value=XXX as a query - e.g. +'pkcs11:pkcs11:token=My%20Token;id=%aa%bb%cc%dd?pin-value=XXX' where XXX is +the user pin. + +EXAMPLES +-------- +*CoAP Server DTLS PKI Setup* +[source, c] +---- +#include + +typedef struct valid_cns_t { + int count; + char **cn_list; +} valid_cns_t; + +/** + * CN Validation callback that can be set up by coap_context_set_pki(). + * Invoked when libcoap has done the validation checks at the TLS level, + * but the application needs to check that the CN is allowed. + * CN is the SubjectAltName in the cert, if not present, then the leftmost + * Common Name (CN) component of the subject name. + * NOTE: If using RPK, then the Public Key does not contain a CN, but "RPK" + * is presented for the cn parameter. + * + * @param cn The determined CN from the certificate + * @param asn1_public_cert The ASN.1 encoded (DER) X.509 certificate + * @param asn1_length The ASN.1 length + * @param session The coap session associated with the certificate update + * @param depth Depth in cert chain. If 0, then client cert, else a CA + * @param validated TLS can find no issues if 1 + * @param arg The same as was passed into coap_context_set_pki() + * in setup_data->cn_call_back_arg + * + * @return 1 if accepted, else 0 if to be rejected + */ +static int +verify_cn_callback(const char *cn, + const uint8_t *asn1_public_cert, + size_t asn1_length, + coap_session_t *c_session, + unsigned depth, + int validated, + void *arg +) { + valid_cns_t *valid_cn_list = (valid_cns_t*)arg; + int i; + /* Remove (void) definition if variable is used */ + (void)asn1_public_cert; + (void)asn1_length; + (void)c_session; + (void)depth; + (void)validated; + + /* Check that the CN is valid */ + for (i = 0; i < valid_cn_list->count; i++) { + if (!strcasecmp(cn, valid_cn_list->cn_list[i])) { + return 1; + } + } + return 0; +} + +typedef struct sni_def_t { + char* sni; + coap_dtls_key_t key; +} sni_def_t; + +typedef struct valid_snis_t { + int count; + sni_def_t *sni_list; +} valid_snis_t; + +/** + * SNI Validation callback that is set up by coap_context_set_pki(). + * Invoked if the SNI is not previously seen and prior to sending a certificate + * set back to the client so that the appropriate certificate set can be used + * based on the requesting SNI. + * + * @param sni The requested SNI + * @param arg The same as was passed into coap_context_set_pki() + * in setup_data->sni_call_back_arg + * + * @return new set of certificates to use, or NULL if SNI is to be rejected. + */ +static coap_dtls_key_t * +verify_pki_sni_callback(const char *sni, + void *arg +) { + valid_snis_t *valid_sni_list = (valid_snis_t *)arg; + int i; + + /* Check that the SNI is valid */ + for (i = 0; i < valid_sni_list->count; i++) { + if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) { + return &valid_sni_list->sni_list[i].key; + } + } + return NULL; +} + +/* + * Set up PKI encryption information + */ +static coap_context_t * +setup_server_context_pki (const char *public_cert_file, + const char *private_key_file, + const char *ca_file, + valid_cns_t *valid_cn_list, + valid_snis_t *valid_sni_list +) { + coap_endpoint_t *endpoint; + coap_address_t listen_addr; + coap_dtls_pki_t dtls_pki; + coap_context_t *context; + + /* See coap_tls_library(3) */ + if (!coap_dtls_is_supported()) + return NULL; + + /* See coap_context(3) */ + context = coap_new_context(NULL); + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + memset (&dtls_pki, 0, sizeof (dtls_pki)); + + dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; + dtls_pki.verify_peer_cert = 1; + dtls_pki.check_common_ca = 1; + dtls_pki.allow_self_signed = 1; + dtls_pki.allow_expired_certs = 1; + dtls_pki.cert_chain_validation = 1; + dtls_pki.cert_chain_verify_depth = 1; + dtls_pki.check_cert_revocation = 1; + dtls_pki.allow_no_crl = 1; + dtls_pki.allow_expired_crl = 1; + dtls_pki.allow_bad_md_hash = 0; + dtls_pki.allow_short_rsa_length = 0; + dtls_pki.is_rpk_not_cert = 0; /* Set to 1 if RPK */ + dtls_pki.validate_cn_call_back = verify_cn_callback; + dtls_pki.cn_call_back_arg = valid_cn_list; + dtls_pki.validate_sni_call_back = verify_pki_sni_callback; + dtls_pki.sni_call_back_arg = valid_sni_list; + dtls_pki.additional_tls_setup_call_back = NULL; + dtls_pki.client_sni = NULL; + dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM; + dtls_pki.pki_key.key.pem.ca_file = ca_file; + dtls_pki.pki_key.key.pem.public_cert = public_cert_file; + dtls_pki.pki_key.key.pem.private_key = private_key_file; + + /* See coap_context(3) */ + if (coap_context_set_pki(context, &dtls_pki)) { + coap_free_context(context); + return NULL; + } + + coap_address_init(&listen_addr); + listen_addr.addr.sa.sa_family = AF_INET; + listen_addr.addr.sin.sin_port = htons (5684); + + /* See coap_context(3) */ + endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS); + if (!endpoint) { + coap_free_context(context); + return NULL; + } + + /* Initialize resources - See coap_resource(3) init_resources() example */ + + return context; +} +---- + +*CoAP Server DTLS PSK Setup* +[source, c] +---- +#include + +typedef struct id_def_t { + char *hint_match; + coap_bin_const_t id; + coap_bin_const_t key; +} id_def_t; + +typedef struct valid_ids_t { + size_t count; + id_def_t *id_list; +} valid_ids_t; + +/* + * PSK Identity Pre-Shared Key selection Callback function + */ +static const coap_bin_const_t * +verify_id_callback(coap_bin_const_t *identity, + coap_session_t *c_session, + void *arg +) { + valid_ids_t *valid_id_list = (valid_ids_t*)arg; + const coap_bin_const_t *s_psk_hint = coap_session_get_psk_hint(c_session); + size_t i; + + /* Check that the Identity is valid */ + for (i = 0; i < valid_id_list->count; i++) { + if (s_psk_hint && + strcmp((const char *)s_psk_hint->s, + valid_id_list->id_list[i].hint_match)) { + continue; + } + if (coap_binary_equal(identity, &valid_id_list->id_list[i].id)) { + return &valid_id_list->id_list[i].key; + } + } + return NULL; +} + +typedef struct sni_psk_def_t { + char* sni; + coap_dtls_spsk_info_t psk_info; +} sni_psk_def_t; + +typedef struct valid_psk_snis_t { + int count; + sni_psk_def_t *sni_list; +} valid_psk_snis_t; + +/* + * PSK Subject Name Identifier (SNI) callback verifier + */ +static const coap_dtls_spsk_info_t * +verify_psk_sni_callback(const char *sni, + coap_session_t *c_session, + void *arg +) { + valid_psk_snis_t *valid_sni_list = (valid_psk_snis_t *)arg; + int i; + /* Remove (void) definition if variable is used */ + (void)c_session; + + /* Check that the SNI is valid */ + for (i = 0; i < valid_sni_list->count; i++) { + if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) { + return &valid_sni_list->sni_list[i].psk_info; + } + } + return NULL; +} + +static coap_context_t * +setup_server_context_psk (const char *hint, + const uint8_t *key, + unsigned int key_len, + valid_ids_t *valid_id_list, + valid_psk_snis_t *valid_sni_list +) { + coap_endpoint_t *endpoint; + coap_address_t listen_addr; + coap_context_t *context; + coap_dtls_spsk_t dtls_psk; + + /* See coap_tls_library(3) */ + if (!coap_dtls_is_supported()) + return NULL; + + context = coap_new_context(NULL); + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + memset (&dtls_psk, 0, sizeof (dtls_psk)); + + /* see coap_encryption(3) */ + dtls_psk.version = COAP_DTLS_SPSK_SETUP_VERSION; + dtls_psk.validate_id_call_back = verify_id_callback; + dtls_psk.id_call_back_arg = valid_id_list; + dtls_psk.validate_sni_call_back = verify_psk_sni_callback; + dtls_psk.sni_call_back_arg = valid_sni_list; + dtls_psk.psk_info.hint.s = (const uint8_t*)hint; + dtls_psk.psk_info.hint.length = hint ? strlen(hint) : 0; + dtls_psk.psk_info.key.s = key; + dtls_psk.psk_info.key.length = key_len; + + if (coap_context_set_psk2(context, &dtls_psk)) { + coap_free_context(context); + return NULL; + } + + coap_address_init(&listen_addr); + listen_addr.addr.sa.sa_family = AF_INET; + listen_addr.addr.sin.sin_port = htons (5684); + + endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS); + if (!endpoint) { + coap_free_context(context); + return NULL; + } + + /* Initialize resources - See coap_resource(3) init_resources() example */ + + return context; +} +---- + +*CoAP Client DTLS PSK Setup* +[source, c] +---- +#include + +#include + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +static const coap_dtls_cpsk_info_t * +verify_ih_callback(coap_str_const_t *hint, + coap_session_t *c_session, + void *arg +) { + coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg; + /* Remove (void) definition if variable is used */ + (void)c_session; + + coap_log(LOG_INFO, "Identity Hint '%.*s' provided\n", (int)hint->length, hint->s); + + /* Just use the defined information for now as passed in by arg */ + return psk_info; +} + +static coap_dtls_cpsk_t dtls_psk; +static char client_sni[256]; + +static coap_session_t * +setup_client_session_psk (const char *uri, + struct in_addr ip_address, + const uint8_t *identity, + unsigned int identity_len, + const uint8_t *key, + unsigned int key_len +) { + coap_session_t *session; + coap_address_t server; + /* See coap_context(3) */ + coap_context_t *context = coap_new_context(NULL); + + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + coap_address_init(&server); + server.addr.sa.sa_family = AF_INET; + server.addr.sin.sin_addr = ip_address; + server.addr.sin.sin_port = htons (5684); + + /* See coap_encryption(3) */ + memset (&dtls_psk, 0, sizeof(dtls_psk)); + dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION; + dtls_psk.validate_ih_call_back = verify_ih_callback; + dtls_psk.ih_call_back_arg = &dtls_psk.psk_info; + if (uri) + memcpy(client_sni, uri, min(strlen(uri), sizeof(client_sni)-1)); + else + memcpy(client_sni, "localhost", 9); + dtls_psk.client_sni = client_sni; + dtls_psk.psk_info.identity.s = identity; + dtls_psk.psk_info.identity.length = identity_len; + dtls_psk.psk_info.key.s = key; + dtls_psk.psk_info.key.length = key_len; + session = coap_new_client_session_psk2(context, NULL, &server, + COAP_PROTO_DTLS, &dtls_psk); + if (!session) { + coap_free_context(context); + return NULL; + } + /* The context is in session->context */ + return session; +} +---- + +SEE ALSO +-------- +*coap_block*(3), *coap_context*(3), *coap_resource*(3), *coap_session*(3) and +*coap_tls_library*(3) + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_endpoint_client.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_endpoint_client.txt.in new file mode 100644 index 000000000..a94eb7e73 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_endpoint_client.txt.in @@ -0,0 +1,421 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_endpoint_client(3) +======================= +:doctype: manpage +:man source: coap_endpoint_client +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_endpoint_client, +coap_new_client_session, +coap_new_client_session_psk2, +coap_new_client_session_pki, +coap_session_set_mtu, +coap_session_max_pdu_size +- Work with CoAP client endpoints + +SYNOPSIS +-------- +*#include * + +*coap_session_t *coap_new_client_session(coap_context_t *_context_, +const coap_address_t *_local_if_, const coap_address_t *_server_, +coap_proto_t _proto_);* + +*coap_session_t *coap_new_client_session_psk2(coap_context_t *_context_, +const coap_address_t *_local_if_, const coap_address_t *_server_, coap_proto_t +_proto_, coap_dtls_cpsk_t *_setup_data_);* + +*coap_session_t *coap_new_client_session_pki(coap_context_t *_context_, +const coap_address_t *_local_if_, const coap_address_t *_server_, coap_proto_t +_proto_, coap_dtls_pki_t *_setup_data_);* + +*void coap_session_set_mtu(coap_session_t *_session_, unsigned _mtu_);* + +*size_t coap_session_max_pdu_size(const coap_session_t *_session_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +This man page focuses on the setting up of a CoAP client endpoint and hence +creation of a CoAP Session used to connect to a server. For a CoAP server +endpoint, see *coap_endpoint_server*(3). There is no need to call +*coap_new_endpoint*(3) for a client as well as one of the +*coap_new_client_server**() functions. + +The CoAP stack's global state is stored in a coap_context_t Context object. +Resources, Endpoints and Sessions are associated with this context object. +There can be more than one coap_context_t object per application, it is up to +the application to manage each one accordingly. + +A CoAP Ssssion maintains the state of an ongoing connection between a Client +and Server which is stored in a coap_session_t Session object. A CoAP session +is tracked by local port, CoAP protocol, remote IP address and remote port. + +The Session network traffic can be encrypted or un-encrypted if there is an +underlying TLS library. + +If TLS is going to be used for encrypting the network traffic, then the TLS +information for Pre-Shared Keys (PSK) or Public Key Infrastructure (PKI) needs +to be configured before any network traffic starts to flow. For Servers, this +has to be done before the Endpoint is created, for Clients, this is done +during the Client Endpoint/Session set up. + +For Clients, all the encryption information can be held at the TLS Context and +CoAP Context levels, or at the TLS Session and CoAP Session levels. If +defined at the Context level, then when Sessions are created, they will +inherit the Context definitions, unless they have separately been defined for +the Session level, in which case the Session version will get used. +Typically the information will be configured at the Session level for Clients. + +In principle the set-up sequence for CoAP client endpoints looks like +---- +coap_new_context() +coap_context_set_pki_root_cas() if the root CAs need to be updated and PKI +coap_new_client_session(), coap_new_client_session_pki() or coap_new_client_session_psk2() +---- + +Multiple client endpoints and hence sessions are supported per Context. + +Different CoAP protocols can be defined for _proto_ - the current supported +list is: + +[source, c] +---- +COAP_PROTO_UDP +COAP_PROTO_DTLS +COAP_PROTO_TCP +COAP_PROTO_TLS +---- + +*coap_tcp_is_supported*(), *coap_dtls_is_supported*() and +*coap_tls_is_supported*() can be used for checking whether the underlying +TCP or (D)TLS protocol support is available. See *coap_tls_library(3)* for +further information. + +The *coap_new_client_session*() function creates a client endpoint for a +specific _context_ and initiates a new client session to the specified _server_ +using the CoAP protocol +_proto_. If the port is set to 0 in _server_, then the default CoAP +port is used. Normally _local_if_ would be set to NULL, but by specifying +_local_if_ the source of the network session can be bound to a specific IP +address or port. The session will initially have a reference count of 1. + +The *coap_new_client_session_pki*() function, for a specific _context_, is +used to configure the TLS context using the _setup_data_ variables as defined +in the coap_dtls_pki_t structure in the newly created endpoint session - +see *coap_encryption*(3). The connection is to the specified _server_ using +the CoAP protocol _proto_. If the port is set to 0 in _server_, then the +default CoAP port is used. Normally _local_if_ would be set to NULL, but by +specifying _local_if_ the source of the network session can be bound to a +specific IP address or port. The session will initially have a reference count +of 1. + +The *coap_new_client_session_psk2*() function, for a specific _context_, is +used to configure the TLS context using the _setup_data_ variables as defined +in the coap_dtls_cpsk_t structure in the newly created endpoint session - +see *coap_encryption*(3). The connection is to the specified _server_ using +the CoAP protocol _proto_. If the port is set to 0 in _server_, then the +default CoAP port is used. Normally _local_if_ would be set to NULL, but by +specifying _local_if_ the source of the network session can be bound to a +specific IP address or port. The session will initially have a reference count +of 1. + +To stop using a client session, the reference count must be decremented to 0 +by calling *coap_session_release*(). See *coap_session*(3). This will remove +the client endpoint. + +The *coap_sesson_set_default_mtu*() function is used to set the MTU size +(the maximum message size) of the data in a packet, excluding any IP or +TCP/UDP overhead to _mtu_ for the client endpoint's _session_. The default +MTU is 1152. + +The *coap_session_max_pdu_size*() function is used to get the maximum MTU +size of the data for the client endpoint's _session_. + +RETURN VALUES +------------- +*coap_new_client_session*(), *coap_new_client_session_psk2*(), +*coap_new_client_session_pki*() functions returns a newly created client +session or NULL if there is a creation failure. + +*coap_session_max_pdu_size*() function returns the MTU size. + +EXAMPLES +-------- +*CoAP Client Non-Encrypted Setup* +[source, c] +---- +#include + +#include + +static coap_session_t * +setup_client_session (struct in_addr ip_address) { + coap_session_t *session; + coap_address_t server; + /* See coap_context(3) */ + coap_context_t *context = coap_new_context(NULL); + + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + coap_address_init(&server); + server.addr.sa.sa_family = AF_INET; + server.addr.sin.sin_addr = ip_address; + server.addr.sin.sin_port = htons (5683); + + session = coap_new_client_session(context, NULL, &server, COAP_PROTO_UDP); + if (!session) { + coap_free_context(context); + return NULL; + } + /* The context is in session->context */ + return session; +} +---- + +*CoAP Client PKI Setup* +[source, c] +---- +#include + +#include + +static int +verify_cn_callback(const char *cn, + const uint8_t *asn1_public_cert, + size_t asn1_length, + coap_session_t *c_session, + unsigned int depth, + int validated, + void *arg +) { + /* Remove (void) definition if variable is used */ + (void)cn; + (void)asn1_public_cert; + (void)asn1_length; + (void)c_session; + (void)depth; + (void)validated; + (void)arg; + + /* Check that the CN is valid */ + + /* ... */ + + return 1; +} + +static coap_session_t * +setup_client_session_pki (struct in_addr ip_address, + const char *public_cert_file, + const char *private_key_file, + const char *ca_file +) { + coap_session_t *session; + coap_address_t server; + coap_dtls_pki_t dtls_pki; + /* See coap_context(3) */ + coap_context_t *context = coap_new_context(NULL); + + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + coap_address_init(&server); + server.addr.sa.sa_family = AF_INET; + server.addr.sin.sin_addr = ip_address; + server.addr.sin.sin_port = htons (5684); + + memset (&dtls_pki, 0, sizeof (dtls_pki)); + + /* See coap_encryption(3) */ + dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; + dtls_pki.verify_peer_cert = 1; + dtls_pki.check_common_ca = 1; + dtls_pki.allow_self_signed = 1; + dtls_pki.allow_expired_certs = 1; + dtls_pki.cert_chain_validation = 1; + dtls_pki.cert_chain_verify_depth = 1; + dtls_pki.check_cert_revocation = 1; + dtls_pki.allow_no_crl = 1; + dtls_pki.allow_expired_crl = 1; + dtls_pki.allow_bad_md_hash = 0; + dtls_pki.allow_short_rsa_length = 0; + dtls_pki.is_rpk_not_cert = 0; /* Set to 1 if RPK */ + dtls_pki.validate_cn_call_back = verify_cn_callback; + dtls_pki.cn_call_back_arg = NULL; + dtls_pki.validate_sni_call_back = NULL; + dtls_pki.sni_call_back_arg = NULL; + dtls_pki.additional_tls_setup_call_back = NULL; + dtls_pki.client_sni = NULL; + dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM; + dtls_pki.pki_key.key.pem.ca_file = ca_file; + dtls_pki.pki_key.key.pem.public_cert = public_cert_file; + dtls_pki.pki_key.key.pem.private_key = private_key_file; + + session = coap_new_client_session_pki(context, NULL, &server, + COAP_PROTO_DTLS, &dtls_pki); + if (!session) { + coap_free_context(context); + return NULL; + } + /* The context is in session->context */ + return session; +} +---- + +*CoAP Client PSK Setup* +[source, c] +---- +#include + +#include +#include + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +static const coap_dtls_cpsk_info_t * +verify_ih_callback(coap_str_const_t *hint, + coap_session_t *c_session, + void *arg +) { + coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg; + /* Remove (void) definition if variable is used */ + (void)c_session; + + coap_log(LOG_INFO, "Identity Hint '%.*s' provided\n", (int)hint->length, hint->s); + + /* Just use the defined information for now as passed in by arg */ + return psk_info; +} + +static coap_dtls_cpsk_t dtls_psk; +static char client_sni[256]; + +static coap_session_t * +setup_client_session_psk (const char *uri, + struct in_addr ip_address, + const uint8_t *identity, + unsigned int identity_len, + const uint8_t *key, + unsigned int key_len +) { + coap_session_t *session; + coap_address_t server; + /* See coap_context(3) */ + coap_context_t *context = coap_new_context(NULL); + + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + coap_address_init(&server); + server.addr.sa.sa_family = AF_INET; + server.addr.sin.sin_addr = ip_address; + server.addr.sin.sin_port = htons (5684); + + /* See coap_encryption(3) */ + memset (&dtls_psk, 0, sizeof(dtls_psk)); + dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION; + dtls_psk.validate_ih_call_back = verify_ih_callback; + dtls_psk.ih_call_back_arg = &dtls_psk.psk_info; + if (uri) + memcpy(client_sni, uri, min(strlen(uri), sizeof(client_sni)-1)); + else + memcpy(client_sni, "localhost", 9); + dtls_psk.client_sni = client_sni; + dtls_psk.psk_info.identity.s = identity; + dtls_psk.psk_info.identity.length = identity_len; + dtls_psk.psk_info.key.s = key; + dtls_psk.psk_info.key.length = key_len; + session = coap_new_client_session_psk2(context, NULL, &server, + COAP_PROTO_DTLS, &dtls_psk); + if (!session) { + coap_free_context(context); + return NULL; + } + /* The context is in session->context */ + return session; +} +---- + +*CoAP Client Anonymous PKI Setup* +[source, c] +---- +#include + +#include + +static coap_session_t * +setup_client_session_dtls (struct in_addr ip_address) { + coap_session_t *session; + coap_address_t server; + /* See coap_context(3) */ + coap_context_t *context = coap_new_context(NULL); + + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + coap_address_init(&server); + server.addr.sa.sa_family = AF_INET; + server.addr.sin.sin_addr = ip_address; + server.addr.sin.sin_port = htons (5683); + + session = coap_new_client_session(context, NULL, &server, + COAP_PROTO_DTLS); + if (!session) { + coap_free_context(context); + return NULL; + } + /* The context is in session->context */ + return session; +} +---- + +SEE ALSO +-------- +*coap_block*(3), *coap_context*(3), *coap_encryption*(3), +*coap_endpoint_server*(3), *coap_resource*(3), *coap_session*(3) and +*coap_tls_library*(3) + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_endpoint_server.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_endpoint_server.txt.in new file mode 100644 index 000000000..c4270b078 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_endpoint_server.txt.in @@ -0,0 +1,584 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_endpoint_server(3) +======================= +:doctype: manpage +:man source: coap_endpoint_server +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_endpoint_server, +coap_context_set_pki, +coap_context_set_pki_root_cas, +coap_context_set_psk2, +coap_new_endpoint, +coap_free_endpoint, +coap_endpoint_set_default_mtu, +coap_join_mcast_group_intf, +coap_mcast_per_resource +- Work with CoAP server endpoints + +SYNOPSIS +-------- +*#include * + +*int coap_context_set_pki(coap_context_t *_context_, +const coap_dtls_pki_t *_setup_data_);* + +*int coap_context_set_pki_root_cas(coap_context_t *_context_, +const char *_ca_file_, const char *_ca_dir_);* + +*int coap_context_set_psk2(coap_context_t *_context_, +coap_dtls_spsk_t *setup_data);* + +*coap_endpoint_t *coap_new_endpoint(coap_context_t *_context_, +const coap_address_t *_listen_addr_, coap_proto_t _proto_);* + +*void coap_free_endpoint(coap_endpoint_t *_endpoint_);* + +*void coap_endpoint_set_default_mtu(coap_endpoint_t *_endpoint_, +unsigned _mtu_);* + +*int coap_join_mcast_group_intf(coap_context_t *_context_, +const char *_groupname_, const char *_ifname_);* + +*void coap_mcast_per_resource(coap_context_t *_context_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +This man page focuses on the setting up of a CoAP server endpoint. For a CoAP +client endpoint, see *coap_endpoint_client*(3). + +The CoAP stack's global state is stored in a coap_context_t Context object. +Resources, Endpoints and Sessions are associated with this context object. +There can be more than one coap_context_t object per application, it is up to +the application to manage each one accordingly. + +A CoAP Session maintains the state of an ongoing connection between a Client +and Server which is stored in a coap_session_t Session object. A CoAP session +is tracked by local port, CoAP protocol, remote IP address and remote port. + +The Session network traffic can be encrypted or un-encrypted if there is an +underlying TLS library. + +If TLS is going to be used for encrypting the network traffic, then the TLS +information for Pre-Shared Keys (PSK) or Public Key Infrastructure (PKI) needs +to be configured before any network traffic starts to flow. For Servers, this +has to be done before the Endpoint is created, for Clients, this is done +during the Client Session set up. + +For Servers, all the encryption information is held internally by the TLS +Context level and the CoAP Context level as the Server is listening for new +incoming traffic based on the Endpoint definition. The TLS and CoAP session +will not get built until the new traffic starts, which is done by the libcoap +library. + +In principle the set-up sequence for CoAP Servers looks like +---- +coap_new_context() +coap_context_set_pki_root_cas() - if the root CAs need to be updated and PKI +coap_context_set_pki() and/or coap_context_set_psk2() - if encryption is required +coap_new_endpoint() +---- + +Multiple endpoints can be set up per Context, each listening for a new traffic +flow with different TCP/UDP protocols, TLS protocols, port numbers etc. When a +new traffic flow is started, then the CoAP library will create and start a new +server session. + +The *coap_context_set_pki*() function, for a specific _context_, is used to +configure the TLS context using the _setup_data_ variables as defined in the +coap_dtls_pki_t structure - see *coap_encryption*(3). + +The *coap_context_set_pki_root_cas*() function is used to define a set of +root CAs to be used instead of the default set of root CAs provided as a part +of the TLS library. _ca_file_ points to a PEM encoded file containing the +list of CAs. _ca_file can be NULL. _ca_dir_ points to a directory +containing a set of PEM encoded files containing rootCAs. _ca_dir_ can be +NULL. One or both of _ca_file_ and _ca_dir_ must be set. + +*NOTE:* Some TLS libraries send the full list of CAs added by this function +during the (D)TLS session setup handshakes. To stop this, either provide a +single CA using the _ca_file_ definition in _pki_key_ in _setup_data_ variable +when calling *coap_context_set_pki*(), or set _check_common_ca to 0 in +_setup_data_ variable. See *coap_encryption*(3). + +The *coap_context_set_psk2*() function is used to configure the TLS context +using the _setup_data_ variables as defined in the +coap_dtls_spsk_t structure - see *coap_encryption*(3). +This function can only be used for servers as _setup_data_ provides +a _hint_, not an _identity_. + +The *coap_new_endpoint*() function creates a new endpoint for _context_ that +is listening for new traffic on the IP address and port number defined by +_listen_addr_. If the port number is 0, then the default CoAP port is used. +Different CoAP protocols can be defined for _proto_ - the current supported +list is: + +[source, c] +---- +COAP_PROTO_UDP +COAP_PROTO_DTLS +COAP_PROTO_TCP +COAP_PROTO_TLS +---- + +*coap_tcp_is_supported*(), *coap_dtls_is_supported*() and +*coap_tls_is_supported*() can be used for checking whether the underlying +TCP or (D)TLS protocol support is available. See *coap_tls_library*(3) for +further information. + +When traffic starts to come in from a client, a server CoAP Session is created +associated with this endpoint. This CoAP Session is created with a reference +count of 0. This means that if the server session is not used for 5 minutes, +then it will get completely freed off. See coap_session_reference(3) and +coap_session_release(3) for further information. + +The *coap_free_endpoint*() function must be used to free off the _endpoint_. +It clears out all the sessions associated with this endpoint. + +The *coap_endpoint_set_default_mtu*() function is used to set the MTU size +(the maximum message size) of the data in a packet, excluding any IP or +TCP/UDP overhead to _mtu_ for the _endpoint_. A sensible default is 1280. + +The *coap_join_mcast_group_intf*() function is used to join the currently +defined endpoints that are UDP, associated with _context_, to the defined +multicast group _groupname_. If _ifname_ is not NULL, then the multicast group +is associated with this interface, otherwise the underlying O/S will choose the +first appropriate interface. When the endpoint is freed off, the associated +multicast group will be removed. The registered multicast addresses for CoAP +are 224.0.1.187, ff0x::fd (Variable-Scope) - i.e. ff02::fd (Link-Local) and +ff05::fd (Site-Local). + +The *coap_mcast_per_resource*() function enables mcast to be controlled on a +per resource basis giving the server application flexibility in how to respond +to mcast requests. With this enabled, this is done through additional flag +definitions when setting up each resource. + +RETURN VALUES +------------- +*coap_context_set_pki*(), *coap_context_set_pki_root_cas*() and +*coap_context_set_psk2*() functions return 1 on success, 0 on failure. + +*coap_new_endpoint*() function returns a newly created endpoint or +NULL if there is a creation failure. + +*coap_join_mcast_group_intf*() returns 0 on success, -1 on failure. + +EXAMPLES +-------- +*CoAP Server Non-Encrypted Setup* + +[source, c] +---- +#include + +static coap_context_t * +setup_server_context (void) { + coap_endpoint_t *endpoint; + coap_address_t listen_addr; + coap_context_t *context = coap_new_context(NULL); + + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + coap_address_init(&listen_addr); + listen_addr.addr.sa.sa_family = AF_INET; + listen_addr.addr.sin.sin_port = htons (5683); + + endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_UDP); + if (!endpoint) { + coap_free_context(context); + return NULL; + } + + /* Initialize resources - See coap_resource(3) init_resources() example */ + + return context; +} +---- + +*CoAP Server DTLS PKI Setup* +[source, c] +---- +#include + +typedef struct valid_cns_t { + size_t count; + char **cn_list; +} valid_cns_t; + +/* + * Common Name (CN) Callback verifier + */ +static int +verify_cn_callback(const char *cn, + const uint8_t *asn1_public_cert, + size_t asn1_length, + coap_session_t *c_session, + unsigned depth, + int validated, + void *arg +) { + valid_cns_t *valid_cn_list = (valid_cns_t*)arg; + size_t i; + /* Remove (void) definition if variable is used */ + (void)asn1_public_cert; + (void)asn1_length; + (void)c_session; + (void)depth; + (void)validated; + + /* Check that the CN is valid */ + for (i = 0; i < valid_cn_list->count; i++) { + if (!strcasecmp(cn, valid_cn_list->cn_list[i])) { + return 1; + } + } + return 0; +} + +typedef struct sni_def_t { + char* sni; + coap_dtls_key_t key; +} sni_def_t; + +typedef struct valid_snis_t { + size_t count; + sni_def_t *sni_list; +} valid_snis_t; + +/* + * Subject Name Identifier (SNI) callback verifier + */ +static coap_dtls_key_t * +verify_pki_sni_callback(const char *sni, + void *arg +) { + valid_snis_t *valid_sni_list = (valid_snis_t *)arg; + size_t i; + + /* Check that the SNI is valid */ + for (i = 0; i < valid_sni_list->count; i++) { + if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) { + return &valid_sni_list->sni_list[i].key; + } + } + return NULL; +} + +/* + * Set up PKI encryption information + */ +static coap_context_t * +setup_server_context_pki (const char *public_cert_file, + const char *private_key_file, + const char *ca_file, + valid_cns_t *valid_cn_list, + valid_snis_t *valid_sni_list +) { + coap_endpoint_t *endpoint; + coap_address_t listen_addr; + coap_dtls_pki_t dtls_pki; + coap_context_t *context; + + /* See coap_tls_library(3) */ + if (!coap_dtls_is_supported()) + return NULL; + + context = coap_new_context(NULL); + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + memset (&dtls_pki, 0, sizeof (dtls_pki)); + + /* see coap_encryption(3) */ + dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; + dtls_pki.verify_peer_cert = 1; + dtls_pki.check_common_ca = 1; + dtls_pki.allow_self_signed = 1; + dtls_pki.allow_expired_certs = 1; + dtls_pki.cert_chain_validation = 1; + dtls_pki.cert_chain_verify_depth = 1; + dtls_pki.check_cert_revocation = 1; + dtls_pki.allow_no_crl = 1; + dtls_pki.allow_expired_crl = 1; + dtls_pki.allow_bad_md_hash = 0; + dtls_pki.allow_short_rsa_length = 0; + dtls_pki.is_rpk_not_cert = 0; /* Set to 1 if RPK */ + dtls_pki.validate_cn_call_back = verify_cn_callback; + dtls_pki.cn_call_back_arg = valid_cn_list; + dtls_pki.validate_sni_call_back = verify_pki_sni_callback; + dtls_pki.sni_call_back_arg = valid_sni_list; + dtls_pki.additional_tls_setup_call_back = NULL; + dtls_pki.client_sni = NULL; + dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM; + dtls_pki.pki_key.key.pem.ca_file = ca_file; + dtls_pki.pki_key.key.pem.public_cert = public_cert_file; + dtls_pki.pki_key.key.pem.private_key = private_key_file; + + if (coap_context_set_pki(context, &dtls_pki)) { + coap_free_context(context); + return NULL; + } + + coap_address_init(&listen_addr); + listen_addr.addr.sa.sa_family = AF_INET; + listen_addr.addr.sin.sin_port = htons (5684); + + endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS); + if (!endpoint) { + coap_free_context(context); + return NULL; + } + + /* Initialize resources - See coap_resource(3) init_resources() example */ + + return context; +} +---- + +*CoAP Server DTLS PSK Setup* +[source, c] +---- +#include + +typedef struct id_def_t { + char* id; + coap_bin_const_t key; +} id_def_t; + +typedef struct valid_ids_t { + int count; + id_def_t *id_list; +} valid_ids_t; + +/* + * PSK Identity Pre-Shared Key selection Callback function + */ +static const coap_bin_const_t * +verify_id_callback(coap_bin_const_t *identity, + coap_session_t *c_session, + void *arg +) { + valid_ids_t *valid_id_list = (valid_ids_t*)arg; + int i; + /* Remove (void) definition if variable is used */ + (void)c_session; + + /* Check that the Identity is valid */ + for (i = 0; i < valid_id_list->count; i++) { + if (!strcasecmp((const char*)identity->s, valid_id_list->id_list[i].id)) { + return &valid_id_list->id_list[i].key; + } + } + return NULL; +} + +typedef struct sni_psk_def_t { + char* sni; + coap_dtls_spsk_info_t psk_info; +} sni_psk_def_t; + +typedef struct valid_psk_snis_t { + int count; + sni_psk_def_t *sni_list; +} valid_psk_snis_t; + +/* + * PSK Subject Name Identifier (SNI) callback verifier + */ +static const coap_dtls_spsk_info_t * +verify_psk_sni_callback(const char *sni, + coap_session_t *c_session, + void *arg +) { + valid_psk_snis_t *valid_sni_list = (valid_psk_snis_t *)arg; + int i; + /* Remove (void) definition if variable is used */ + (void)c_session; + + /* Check that the SNI is valid */ + for (i = 0; i < valid_sni_list->count; i++) { + if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) { + return &valid_sni_list->sni_list[i].psk_info; + } + } + return NULL; +} + +static coap_context_t * +setup_server_context_psk (const char *hint, + const uint8_t *key, + unsigned int key_len, + valid_ids_t *valid_id_list, + valid_psk_snis_t *valid_sni_list +) { + coap_endpoint_t *endpoint; + coap_address_t listen_addr; + coap_context_t *context; + coap_dtls_spsk_t dtls_psk; + + /* See coap_tls_library(3) */ + if (!coap_dtls_is_supported()) + return NULL; + + context = coap_new_context(NULL); + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + memset (&dtls_psk, 0, sizeof (dtls_psk)); + + /* see coap_encryption(3) */ + dtls_psk.version = COAP_DTLS_SPSK_SETUP_VERSION; + dtls_psk.validate_id_call_back = verify_id_callback; + dtls_psk.id_call_back_arg = valid_id_list; + dtls_psk.validate_sni_call_back = verify_psk_sni_callback; + dtls_psk.sni_call_back_arg = valid_sni_list; + dtls_psk.psk_info.hint.s = (const uint8_t*)hint; + dtls_psk.psk_info.hint.length = hint ? strlen(hint) : 0; + dtls_psk.psk_info.key.s = key; + dtls_psk.psk_info.key.length = key_len; + + if (coap_context_set_psk2(context, &dtls_psk)) { + coap_free_context(context); + return NULL; + } + + coap_address_init(&listen_addr); + listen_addr.addr.sa.sa_family = AF_INET; + listen_addr.addr.sin.sin_port = htons (5684); + + endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS); + if (!endpoint) { + coap_free_context(context); + return NULL; + } + + /* Initialize resources - See coap_resource(3) init_resources() example */ + + return context; +} +---- + +*CoAP Client DTLS PSK Setup* +[source, c] +---- +#include + +#include + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +static const coap_dtls_cpsk_info_t * +verify_ih_callback(coap_str_const_t *hint, + coap_session_t *c_session, + void *arg +) { + coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg; + char lhint[COAP_DTLS_HINT_LENGTH]; + /* Remove (void) definition if variable is used */ + (void)c_session; + + snprintf(lhint, sizeof(lhint), "%.*s", (int)hint->length, hint->s); + coap_log(LOG_INFO, "Identity Hint '%s' provided\n", lhint); + + /* Just use the defined information for now as passed in by arg */ + return psk_info; +} + +static coap_dtls_cpsk_t dtls_psk; +static char client_sni[256]; + +static coap_session_t * +setup_client_session_psk (const char *uri, + struct in_addr ip_address, + const uint8_t *identity, + unsigned int identity_len, + const uint8_t *key, + unsigned int key_len +) { + coap_session_t *session; + coap_address_t server; + coap_context_t *context = coap_new_context(NULL); + + if (!context) + return NULL; + /* See coap_block(3) */ + coap_context_set_block_mode(context, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + coap_address_init(&server); + server.addr.sa.sa_family = AF_INET; + server.addr.sin.sin_addr = ip_address; + server.addr.sin.sin_port = htons (5684); + + /* See coap_encryption(3) */ + memset (&dtls_psk, 0, sizeof(dtls_psk)); + dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION; + dtls_psk.validate_ih_call_back = verify_ih_callback; + dtls_psk.ih_call_back_arg = &dtls_psk.psk_info; + if (uri) + memcpy(client_sni, uri, min(strlen(uri), sizeof(client_sni)-1)); + else + memcpy(client_sni, "localhost", 9); + dtls_psk.client_sni = client_sni; + dtls_psk.psk_info.identity.s = identity; + dtls_psk.psk_info.identity.length = identity_len; + dtls_psk.psk_info.key.s = key; + dtls_psk.psk_info.key.length = key_len; + session = coap_new_client_session_psk2(context, NULL, &server, + COAP_PROTO_DTLS, &dtls_psk); + if (!session) { + coap_free_context(context); + return NULL; + } + /* The context is in session->context */ + return session; +} + +---- + +SEE ALSO +-------- +*coap_block*(3), *coap_context*(3), *coap_encryption*(3), +*coap_endpoint_client*(3), *coap_resource*(3), *coap_session*(3) and +*coap_tls_library*(3) + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_handler.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_handler.txt.in new file mode 100644 index 000000000..9f453b455 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_handler.txt.in @@ -0,0 +1,348 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_handler(3) +================= +:doctype: manpage +:man source: coap_handler +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_handler, +coap_register_request_handler, +coap_register_response_handler, +coap_register_nack_handler, +coap_register_ping_handler, +coap_register_pong_handler, +coap_register_event_handler +- Work with CoAP handlers + +SYNOPSIS +-------- +*#include * + +*void coap_register_request_handler(coap_resource_t *_resource_, +coap_request_t _method_, coap_method_handler_t _handler_);* + +*void coap_register_response_handler(coap_context_t *_context_, +coap_response_handler_t _handler_)*; + +*void coap_register_nack_handler(coap_context_t *_context_, +coap_nack_handler_t _handler_)*; + +*void coap_register_ping_handler(coap_context_t *_context_, +coap_ping_handler_t _handler_)*; + +*void coap_register_pong_handler(coap_context_t *_context_, +coap_pong_handler_t _handler_)*; + +*void coap_register_event_handler(coap_context_t *_context_, +coap_event_handler_t _handler_)*; + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- + +The *coap_register_request_handler*() is a server side function that registers +a callback handler _handler_ that is called when there is an incoming request +PDU and there is a URI match against the _resource_ and there is a _method_ +(e.g. PUT, POST etc.) match. _method_ can be one of the following. +---- +COAP_REQUEST_GET +COAP_REQUEST_POST +COAP_REQUEST_PUT +COAP_REQUEST_DELETE +COAP_REQUEST_FETCH +COAP_REQUEST_PATCH +COAP_REQUEST_IPATCH +---- + +The method handler function prototype is defined as: +[source, c] +---- +typedef void (*coap_method_handler_t)(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *incoming_pdu, + const coap_string_t *query, + coap_pdu_t *response_pdu); +---- + +In _handler_, data from _incoming_pdu_ can be abstracted as described in +*coap_pdu_access*(3) for analysis and then updates _response_pdu_ as +appropriate as described in *coap_pdu_setup*(3). _response_pdu_ is already +pre-populated with the _incoming_pdu_'s token and the PDU type. If this +handler is called as a result of an unsolicited Observe trigger, then the +option OBSERVE (and potentially option BLOCK2) are also added in. The + _response_pdu_'s response code should always be updated. + +*NOTE:* Any data associated with _incoming_pdu_ is no longer be available after +exiting this function as _incoming_pdu_ is deleted. In particular +_incoming_pdu_'s data must not be used if calling +*coap_add_data_large_response*(). However, it is safe to use the data if +*coap_add_data*() is used to update _response_pdu_ where a copy of the data is +taken. + +*NOTE:* A request callback handler can be called with a generic resource (i.e. +set up using *coap_resource_unknown_init2*(3)), so +*coap_resource_get_uri_path*(3) can be used to determine the URI in this case. + +The *coap_register_response_handler*() is a client side function that registers +a request's response callback _handler_ for traffic associated with the +_context_. The application can use this for handling any response packets, +including sending a RST packet if this response was unexpected. If _handler_ +is NULL, then the handler is de-registered. + +The response handler function prototype is defined as: +[source, c] +---- +typedef enum coap_response_t { + COAP_RESPONSE_FAIL, /* Response not liked - send CoAP RST packet */ + COAP_RESPONSE_OK /* Response is fine */ +} coap_response_t; + +typedef coap_response_t (*coap_response_handler_t)(coap_session_t *session, + const coap_pdu_t *sent, + const coap_pdu_t *received, + const coap_mid_t id); +---- + +In _handler_, data from _received_ (and optionally _sent_ if set) can be +abstracted as described in *coap_pdu_access*(3) for analysis. + +*NOTE:* _sent_ will only be non NULL when the request PDU is Confirmable and +this is an ACK or RST response to the request. In general, matching of +Requests and Responses whould be done by generating unique Tokens for each +Request and then matching up based on the Token in _received_ Response. + +*NOTE:* If the returned value is COAP_RESPONSE_FAIL, then a CoAP RST packet +will get sent to the server by libcoap. The returned value of COAP_RESPONSE_OK +indicates that all is OK. + +The *coap_register_nack_handler*() is a client side function that registers a +request's negative response callback _handler_ for traffic associated with the +_context_. If _handler_ is NULL, then the handler is de-registered. + +The nack handler function prototype is defined as: +[source, c] +---- +typedef void (*coap_nack_handler_t)(coap_session_t *session, + const coap_pdu_t *sent, + const coap_nack_reason_t reason, + const coap_mid_t mid); +---- +NACK _reason_ can be one of the following +---- +COAP_NACK_TOO_MANY_RETRIES +COAP_NACK_NOT_DELIVERABLE +COAP_NACK_RST +COAP_NACK_TLS_FAILED +COAP_NACK_ICMP_ISSUE +---- + +_sent_ can be NULL. _mid_ can be used for determing which is the transmitting +request. + +The *coap_register_ping_handler*() function registers a callback _handler_ for +tracking receipt of CoAP ping traffic associated with the _context_. If +_handler_ is NULL, then the handler is de-registered. It can be used both +client and server side. + +The ping handler function prototype is defined as: +[source, c] +---- +typedef void (*coap_ping_handler_t)(coap_session_t *session, + const coap_pdu_t *received, + const coap_mid_t mid); +---- + +The *coap_register_pong_handler*() function registers a callback _handler_ for +tracking receipt of CoAP ping response traffic associated with the _context_. +If _handler_ is NULL, then the handler is de-registered. It can be used both +client and server side. + +The pong handler function prototype is defined as: +[source, c] +---- +typedef void (*coap_pong_handler_t)(coap_session_t *session, + const coap_pdu_t *received, + const coap_mid_t mid); +---- + +The *coap_register_event_handler*() function registers a callback _handler_ +for tracking network events associated with the _context_. If _handler_ is +NULL, then the handler is de-registered. It can be used both client and server +side. + +The event handler function prototype is defined as: +[source, c] +---- +typedef void (*coap_event_handler_t)(coap_session_t *session, + const coap_event_t event); +---- +Events can be one of the following +---- +/** + * (D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS + */ +COAP_EVENT_DTLS_CLOSED 0x0000 +COAP_EVENT_DTLS_CONNECTED 0x01DE +COAP_EVENT_DTLS_RENEGOTIATE 0x01DF +COAP_EVENT_DTLS_ERROR 0x0200 +/** + * TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS + */ +COAP_EVENT_TCP_CONNECTED 0x1001 +COAP_EVENT_TCP_CLOSED 0x1002 +COAP_EVENT_TCP_FAILED 0x1003 +/** + * CSM exchange events for reliable protocols only + */ +COAP_EVENT_SESSION_CONNECTED 0x2001 +COAP_EVENT_SESSION_CLOSED 0x2002 +COAP_EVENT_SESSION_FAILED 0x2003 +/** + * (Q-)BLOCK errors + */ +COAP_EVENT_PARTIAL_BLOCK 0x3001 +COAP_EVENT_XMIT_BLOCK_FAIL 0x3002 +/** + * Server session state management events + */ +COAP_EVENT_SERVER_SESSION_NEW 0x4001 +COAP_EVENT_SERVER_SESSION_DEL 0x4002 +---- + +EXAMPLES +-------- +*GET Resource Callback Handler* + +[source, c] +---- +#include + +#include + +static void +hnd_get_time(coap_resource_t *resource, coap_session_t *session, +coap_pdu_t *request, coap_string_t *query, coap_pdu_t *response) { + + unsigned char buf[40]; + size_t len; + time_t now; + + /* ... Additional analysis code for resource, request pdu etc. ... */ + + /* After analysis, generate a suitable response */ + + now = time(NULL); + + if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) { + /* Output secs since Jan 1 1970 */ + len = snprintf((char *)buf, sizeof(buf), "%lu", now); + } + else { + /* Output human-readable time */ + struct tm *tmp; + tmp = gmtime(&now); + if (!tmp) { + /* If 'now' is not valid */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp); + } + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + /* + * Invoke coap_add_data_large_response() to do all the hard work. + * + * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in + * Define how long this response is valid for (secs) - 1 - to add in. + * + * OBSERVE Option added internally if needed within the function + * BLOCK2 Option added internally if output too large + * ETAG Option added internally + */ + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0, + len, + buf, NULL, 0); + +} +---- +*Packet Response Handler* + +[source, c] +---- +#include + +static int check_token(coap_pdu_t *received) { + /* Remove (void) definition if variable is used */ + (void)received; + + /* Code to validate the token is what we expect */ + + return 1; +} + +static coap_response_t +response_handler(coap_context_t *ctx, coap_session_t *session, +coap_pdu_t *sent, coap_pdu_t *received, const coap_mid_t mid) { + /* Remove (void) definition if variable is used */ + (void)ctx; + (void)session; + (void)mid; + coap_pdu_type_t rcv_type = coap_pdu_get_type(received); + coap_pdu_code_t rcv_code = coap_pdu_get_code(received); + + /* check if this is a response to our original request */ + if (!check_token(received)) { + /* drop if this was just some message, or send RST in case of notification */ + if (!sent && (rcv_type == COAP_MESSAGE_CON || + rcv_type == COAP_MESSAGE_NON)) { + /* Cause a CoAP RST to be sent */ + return COAP_RESPONSE_FAIL; + } + return COAP_RESPONSE_OK; + } + + if (rcv_type == COAP_MESSAGE_RST) { + coap_log(LOG_INFO, "got RST\n"); + return COAP_RESPONSE_OK; + } + + /* Output the received data, if any */ + if (COAP_RESPONSE_CLASS(rcv_code) == 2) { + /* Additional code to deal with the response */ + + } + return COAP_RESPONSE_OK; + +} +---- + +SEE ALSO +-------- +*coap_block*(3), *coap_observe*(3), *coap_pdu_access*(3), *coap_pdu_setup*(3) +and *coap_resource*(3) + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_io.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_io.txt.in new file mode 100644 index 000000000..c0e18396b --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_io.txt.in @@ -0,0 +1,463 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_io(3) +========== +:doctype: manpage +:man source: coap_io +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_io, +coap_io_process, +coap_io_process_with_fds, +coap_context_get_coap_fd, +coap_io_prepare_io, +coap_io_do_io, +coap_io_prepare_epoll, +coap_io_do_epoll, +coap_io_can_exit +- Work with CoAP I/O to do the packet send and receives + +SYNOPSIS +-------- +*#include * + +*int coap_io_process(coap_context_t *_context_, uint32_t _timeout_ms_)*; + +*int coap_io_process_with_fds(coap_context_t *_context_, +uint32_t _timeout_ms_, int _nfds_, fd_set *_readfds_, fd_set *_writefds_, +fd_set *_exceptfds_)*; + +*int coap_context_get_coap_fd(const coap_context_t *_context_)*; + +*unsigned int coap_io_prepare_io(coap_context_t *_context_, +coap_socket_t *_sockets_[], unsigned int _max_sockets_, +unsigned int *_num_sockets_, coap_tick_t _now_)*; + +*void coap_io_do_io(coap_context_t *_context_, coap_tick_t _now_)*; + +*unsigned int coap_io_prepare_epoll(coap_context_t *_context_, +coap_tick_t _now_)*; + +*void coap_io_do_epoll(coap_context_t *_context_, struct epoll_event *_events_, +size_t _nevents_)*; + +*int coap_can_exit(coap_context_t *_context_)*; + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +After setting up all the contexts, resources, endpoints sessions etc., the +underlying CoAP and (D)TLS need to send (and possible re-send) created packets +as well as receive packets for processing. + +The *coap_io_process*() function will process any outstanding packets to send +for the specified _context_, process any available input packets and then wait +for processing any new input packets, or for when to re-transmit a packet, for +up to _timeout_ms_ milli-seconds before returning. There are 2 special case +_timeout_ms_ values. +[source, c] +---- +#define COAP_IO_WAIT 0 +#define COAP_IO_NO_WAIT ((uint32_t)-1) +---- +If _timeout_ms_ is set to COAP_IO_WAIT, then *coap_io_process*() will block +until the next internal action (e.g. packet retransmit) if any, or block until +the next packet is received whichever is the sooner and do the necessary +processing. If _timeout_ms_ is set to COAP_IO_NO_WAIT, then *coap_io_process*() +will return immediately after processing without waiting for any new input +packets to arrive. + +*NOTE:* *coap_io_process*() should not be called from within a callback +handler as defined using the coap_register_*_handler() as *coap_io_process*() +will likely recursively call the same handler. + +There are two methods of how to call *coap_io_process*(). + +1. Have *coap_io_process*() called from within a while() loop. Under idle +conditions (no input traffic) *coap_io_process*() will then get called every +_timeout_ms_, but more frequently if there is input / retransmission traffic. + +2. Wait on the file descriptor returned by *coap_context_get_coap_fd*() +using *select*(), *poll*() or an event returned by epoll_wait(). If 'read' is +available on the CoAP file descriptor, call *coap_io_process*() with +_timeout_ms_ set to COAP_IO_NO_WAIT. + +*NOTE*: This second method is only available for environments that support epoll +(mostly Linux) with libcoap compiled to use *epoll* (the default) as libcoap +will then be using *epoll* internally to process all the file descriptors of +the different sessions. + +See EXAMPLES below. + +The *coap_io_process*() function is the primary function applications should +use. There are internal functions that *coap_io_process*() calls which are +available to use if absolutely necessary. These internal functions and how to +use them is different depending on whether libcoap has been compiled to use +*epoll* (Linux systems only) or not. + +For *epoll* libcoap, *coap_io_process*() in simple terms calls +*coap_io_prepare_epoll*(), does an *epoll_wait*() and then calls +*coap_io_do_epoll*() if needed to make sure that all event based i/o has been +completed. + +For *non-epoll* libcoap, *coap_io_process*() in simple terms calls +*coap_io_prepare_io*() to set up sockets[], sets up all of the *select*() +parameters based on the COAP_SOCKET_WANT* values in the sockets[], does a +*select*(), updates the sockets[] with COAP_SOCKET_CAN_* as appropriate and +then calls *coap_io_do_io*() to make sure that all current i/o has been +completed. + +The *coap_io_prepare_epoll*() function for the specified _context_ will +iterate through the endpoints and sessions to transmit any triggered observer +responses as well as handling any timed out packet re-transmissions. Returned, +based on _now_, is the number of milli-secs needed to delay until the next +time that *coap_io_prepare_epoll*() needs to get called. After this call an +*epoll_wait*() should done. + +The *coap_io_do_epoll*() function for the specified _context_ will +iterate through the _nevents_ of _events_ returned by *epoll_wait*() and +execute the appropriate low level i/o function to send / receive / process the +packets. Where appropriate, structure information (endpoints, sessions etc.) +is updated with the value of _now_ in the lower level functions. + +The *coap_io_prepare_io*() function for the specified _context_ will iterate +through the endpoints and sessions to add all of sockets waiting for network +traffic (COAP_SOCKET_WANT_* is set) found to _sockets_ (limited by +_max_sockets_) and updates _num_sockets_ with the number of sockets found. +Furthermore, any triggered observer responses are transmitted +as well as handling any timed out packet re-transmissions. Returned, based on +_now_, is the number of milli-secs needed to delay until the next time that +*coap_io_prepare_io*() needs to get called. After this call a *select*() should +done on all the file descriptors (COAP_WANT_READ for readfds etc.), and any +that are returned active should set the appropriate COAP_SOCKET_CAN_* in the +_sockets_. + +The *coap_io_do_io*() function for the specified _context_ will +iterate through the endpoints and sessions to find all of sockets that have +COAP_SOCKET_CAN_* set and then execute the appropriate low level i/o function +to send / receive / process the packets. Where appropriate, structure +information (endpoints, sessions etc.) is updated with the value of _now_ in +the lower level functions. + +The *coap_io_process_with_fds*() function is the same as *coap_process_io*() +but supports additional select() style parameters _nfds_, _readfds_, +_writefds_ and _exceptfds_. This provides the ability to add in additional +non libcoap FDs to test for in the internal select() call which can then +tested after the return from coap_io_process_with_fds(). _readfds_, +_writefds_ and _exceptfds_ can either point to a defined and pre-filled fd_set +structure or NULL if not required. _nfds_ needs to be set to the maximum FD to +test for in _readfds_, _writefds_ or _exceptfds_ if any of them are set plus 1. +If none of them are set, then _nfds_ should be set to 0. + +NOTE: The additional parameters for *coap_io_process_with_fds*() are only used +if there is no epoll support in libcoap. If there is epoll support, then +*coap_context_get_coap_fd*() should be used and this returned FD along with +other non libcoap FDs can separately be monitored using method 2 above. + +The *coap_context_get_coap_fd*() function obtains from the specified +_context_ a single file descriptor that can be monitored by a *select*() or +as an event returned from a *epoll_wait*() call. This file descriptor will get +updated with information (read, write etc. available) whenever any of the +internal to libcoap file descriptors (sockets) change state. + +The *coap_can_exit*() function checks to see if there are any outstanding +PDUs to transmit associated with _context_ and returns 1 if there is nothing +outstanding else 0. This function does not check that all requests transmitted +have been responded to. + +RETURN VALUES +------------- +*coap_io_process*() and *coap_io_process_with_fds*() returns the time, in +milli-seconds, that was spent in the function. If -1 is returned, there was +an unexpected error. + +*coap_context_get_coap_fd*() returns a non-negative number as the file +descriptor to monitor, or -1 if epoll is not configured in libcoap. + +*coap_io_prepare_io*() and *coap_io_prepare_epoll*() returns the number of +milli-seconds that need to be waited before the function should next be called. + +*coap_can_exit*() returns 1 if there is nothing outstanding to transmit else +returns 0. + +EXAMPLES +-------- +*Method One - use coap_io_process()* + +[source, c] +---- +#include + +int main(int argc, char *argv[]){ + + coap_context_t *ctx = NULL; + unsigned wait_ms; + /* Remove (void) definition if variable is used */ + (void)argc; + (void)argv; + + /* Create the libcoap context */ + ctx = coap_new_context(NULL); + if (!ctx) { + exit(1); + } + /* See coap_block(3) */ + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + /* Other Set up Code */ + + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; + + while (1) { + int result = coap_io_process(ctx, wait_ms); + if (result < 0) { + /* There is an internal issue */ + break; + } + /* Do any other housekeeping */ + } + coap_free_context(ctx); + + /* Do any other cleanup */ + + exit(0); + +} +---- + +*Method One - coap_io_process_with_fds* + +[source, c] +---- +#include + +int main(int argc, char *argv[]){ + + coap_context_t *ctx = NULL; + unsigned wait_ms; + fd_set readfds; + int nfds = 0; + /* Remove (void) definition if variable is used */ + (void)argc; + (void)argv; + + /* Create the libcoap context */ + ctx = coap_new_context(NULL); + if (!ctx) { + exit(1); + } + /* See coap_block(3) */ + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + + FD_ZERO(&readfds); + /* Set up readfds and nfds to handle other non libcoap FDs */ + + /* Other Set up Code */ + + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; + + while (1) { + int result = coap_io_process_with_fds(ctx, wait_ms, nfds, &readfds, NULL, NULL); + if (result < 0) { + /* There is an internal issue */ + break; + } + /* Check if set non libcoap FDs and process accordingly */ + + /* Do any other housekeeping */ + } + coap_free_context(ctx); + + /* Do any other cleanup */ + + exit(0); + +} +---- + +*Method Two - select() based on monitorable file descriptor* + +[source, c] +---- +#include + +#include + +int main(int argc, char *argv[]){ + + coap_context_t *ctx = NULL; + int coap_fd; + fd_set m_readfds; + int nfds; + /* Remove (void) definition if variable is used */ + (void)argc; + (void)argv; + + /* Create the libcoap context */ + ctx = coap_new_context(NULL); + if (!ctx) { + exit(1); + } + /* See coap_block(3) */ + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + coap_fd = coap_context_get_coap_fd(ctx); + if (coap_fd == -1) { + /* epoll is not supported */ + exit(1); + } + FD_ZERO(&m_readfds); + FD_SET(coap_fd, &m_readfds); + nfds = coap_fd + 1; + + /* Other Set up Code */ + + while (1) { + fd_set readfds = m_readfds; + int result; + /* Wait until any i/o takes place */ + result = select (nfds, &readfds, NULL, NULL, NULL); + if (result == -1) { + if (errno != EAGAIN) { + coap_log(LOG_DEBUG, "select: %s (%d)\n", coap_socket_strerror(), errno); + break; + } + } + if (result > 0) { + if (FD_ISSET(coap_fd, &readfds)) { + result = coap_io_process(ctx, COAP_IO_NO_WAIT); + if (result < 0) { + /* There is an internal issue */ + break; + } + } + } + /* Do any other housekeeping */ + } + coap_free_context(ctx); + + /* Do any other cleanup */ + + exit(0); + +} +---- + +*Method Two - epoll_wait() based on monitorable file descriptor* + +[source, c] +---- +#include + +#include + +#include + +#define MAX_EVENTS 10 + +int main(int argc, char *argv[]){ + + coap_context_t *ctx = NULL; + int coap_fd; + int epoll_fd; + struct epoll_event ev; + struct epoll_event events[MAX_EVENTS]; + int nevents; + int i; + /* Remove (void) definition if variable is used */ + (void)argc; + (void)argv; + + /* Create the libcoap context */ + ctx = coap_new_context(NULL); + if (!ctx) { + exit(1); + } + /* See coap_block(3) */ + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + coap_fd = coap_context_get_coap_fd(ctx); + if (coap_fd == -1) { + exit(1); + } + epoll_fd = epoll_create1(0); + if (epoll_fd == -1) { + exit(2); + } + ev.events = EPOLLIN; + ev.data.fd = coap_fd; + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, coap_fd, &ev) == -1) { + exit(3); + } + + /* Other Set up Code */ + + while (1) { + int result; + /* Wait until any i/o takes place */ + nevents = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); + if (nevents == -1) { + if (errno != EAGAIN) { + coap_log(LOG_DEBUG, "epoll_wait: %s (%d)\n", coap_socket_strerror(), errno); + break; + } + } + for (i = 0; i < nevents; i++) { + if (events[i].data.fd == coap_fd) { + result = coap_io_process(ctx, COAP_IO_NO_WAIT); + if (result < 0) { + /* There is an internal issue */ + break; + } + } + else { + /* Process other events */ + } + } + /* Do any other housekeeping */ + } + + if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, coap_fd, &ev) == -1) { + coap_log(LOG_DEBUG, "epoll_ctl: %s (%d)\n", coap_socket_strerror(), errno); + } + coap_free_context(ctx); + + /* Do any other cleanup */ + + exit(0); + +} +---- + +SEE ALSO +-------- +*coap_block*(3) and *coap_context*(3) + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_keepalive.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_keepalive.txt.in new file mode 100644 index 000000000..06f5e4a57 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_keepalive.txt.in @@ -0,0 +1,78 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_keepalive(3) +================= +:doctype: manpage +:man source: coap_keepalive +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_keepalive, +coap_context_set_keepalive +- Work with CoAP keepalive + +SYNOPSIS +-------- +*#include * + +*void coap_context_set_keepalive(coap_context_t *_context_, +unsigned int _seconds_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +There may be a requirement to send out keepalive traffic when the CoAP session +is idle (no packets have been sent or received for a specified period) to keep, +say, an interim NAT device "warm" with the NAT translation state, or to +periodically check whether the device at the other end of the session +has "gone away". + +For UDP/DTLS, this is done with the confirmable CoAP (0.00) Ping packet, which +solicits a CoAP RST response. For TCP/TLS, this is done with CoAP (7.02) Ping +packet, which solicits a CoAP (7.03) Pong response, all handled by libcoap. + +The *coap_context_set_keepalive*() function needs to be called to update the +_context_ with the keepalive for idle traffic timeout of _seconds_. If +_seconds_ is set to 0 (the default), then the sending of keepalives is +disabled. Any sessions created from this _context_ will use the same +_seconds_ value to determine whether a keepalive "ping" is to be sent out or +not. + +Applications can track the usage of the receipt of "pings" and receipt of +"responses" by defining the respective handlers to use by using +*coap_register_ping_handler*() and *coap_register_pong_handler*(). + +If the keepalive fails to solicit a response, then this can be tracked by +defining the handler to use by using *coap_register_nack_handler*() which will +be called with a reason of COAP_NACK_TOO_MANY_RETRIES. + +*NOTE:* *coap_context_set_keepalive*() is supported by both the CoAP client and +CoAP server. + +SEE ALSO +-------- +*coap_handler*(3) + +FURTHER INFORMATION +------------------- +"RFC7252: The Constrained Application Protocol (CoAP)" + +"RFC8323: CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets" + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_logging.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_logging.txt.in new file mode 100644 index 000000000..5a10d5e99 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_logging.txt.in @@ -0,0 +1,185 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_logging(3) +================= +:doctype: manpage +:man source: coap_logging +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_logging, +coap_log, +coap_get_log_level, +coap_set_log_level, +coap_set_log_handler, +coap_package_name, +coap_package_version, +coap_package_build, +coap_set_show_pdu_output, +coap_show_pdu, +coap_endpoint_str, +coap_session_str +- Work with CoAP logging + +SYNOPSIS +-------- +*#include * + +*void coap_log(coap_log_t _level_, const char *_format_, ...);* + +*void coap_set_log_level(coap_log_t _level_);* + +*coap_log_t coap_get_log_level(void);* + +*void coap_dtls_set_log_level(int _level_);* + +*int coap_dtls_get_log_level(void);* + +*void coap_set_log_handler(coap_log_handler_t _handler_);* + +*const char *coap_package_name(void);* + +*const char *coap_package_version(void);* + +*const char *coap_package_build(void);* + +*void coap_set_show_pdu_output(int _use_fprintf_);* + +*void coap_show_pdu(coap_log_t _level_, const coap_pdu_t *_pdu_);* + +*const char *coap_endpoint_str(const coap_endpoint_t *_endpoint_);* + +*const char *coap_session_str(const coap_session_t *_session_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +The logging sub-system supports logging at different levels, and depending on +the selected logging level, outputs the appropriate information. + +Logging by default is to stderr or stdout depending on the logging level of +the log entry. It ia possible to send the logging information to an +application logging callback handler for processing by the application. + +The *coap_log*() function is used to log information at the appropriate _level_. +The rest of the parameters follow the standard *printf*() function format. + +Logging levels (*coap_log_t*) are defined by (the same as for *syslog*()), which +are numerically incrementing in value: + +*LOG_EMERG*:: +Emergency level (0). + +*LOG_ALERT*:: +Alert level (1). + +*LOG_CRIT*:: +Critical level (2). + +*LOG_ERR*:: +Error level (3). + +*LOG_WARNING*:: +Warning level (the default) (4). + +*LOG_NOTICE*:: +Notice level (5). + +*LOG_INFO*:: +Information level (6). + +*LOG_DEBUG*:: +Debug level (7). + +The *coap_set_log_level*() function is used to set the current logging _level_ +for output by any subsequent *coap_log*() calls. Output is only logged if the +*coap_log*() _level_ definition is smaller than or equal to the current logging +_level_. + +The *coap_get_log_level*() function is used to get the current logging level. + +The *coap_dtls_set_log_level*() function is used to set the logging _level_ +for output by the DTLS library for specific DTLS information. Usually, both +*coap_set_log_level*() and *coap_dtls_set_log_level*() would be set to the +same _level_ value. If the logging level is set to greater than LOG_DEBUG, +the underlying TLS library may get more verbose in its output. + +The *coap_dtls_get_log_level*() function is used to get the current logging +level for the DTLS library. + +The *coap_set_log_handler*()* function can be used to define an alternative +logging handler for processing the logging messages. The logging handler +prototype is defined as: + +[source, c] +---- +typedef void (*coap_log_handler_t) (coap_log_t level, const char *message); +---- + +The *coap_package_name*() function returns the name of this library. + +The *coap_package_version*() function returns the version of this library. + +The *coap_package_build*() function returns the git information (as in +"git describe --tags") for the build of this library or version of this +library if git is not used. + +The *coap_set_show_pdu_output*() function defines whether the output from +*coap_show_pdu*() is to be either sent to stdout/stderr, or output using +*coap_log*(). _use_fprintf_ is set to 1 for stdout/stderr (the default), and +_use_fprintf_ is set to 0 for *coap_log*(). + +The *coap_show_pdu*() function is used to decode the _pdu_, outputting as +appropriate for logging _level_. Where the output goes is dependent on +*coap_set_show_pdu_output*(). + +The *coap_endpoint_str*() function returns a description string of the +_endpoint_. + +The *coap_session_str*() function is used to get a string containing the +information about the _session_. + +RETURN VALUES +------------- + +The *coap_package_name*(), *coap_package_version*() and +*coap_package_build*() return the appropriate zero-terminated character +string. + +The *coap_get_log_level*() function returns the current logging level. + +The *coap_dtls_get_log_level*() function returns the current logging level +for the DTLS library specifics. + +The *coap_endpoint_str*() function returns a description string of the +_endpoint_. + +The *coap_session_str*() function returns a description string of the +_session_. + +SEE ALSO +-------- +*coap_context*(3) and *coap_session*(3) + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_observe.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_observe.txt.in new file mode 100644 index 000000000..275154f44 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_observe.txt.in @@ -0,0 +1,405 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_observe(3) +================= +:doctype: manpage +:man source: coap_observe +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_observe, +coap_resource_set_get_observable, +coap_resource_notify_observers, +coap_cancel_observe, +coap_session_set_no_observe_cancel +- work with CoAP observe + +SYNOPSIS +-------- +*#include * + +*void coap_resource_set_get_observable(coap_resource_t *_resource_, +int _mode_);* + +*int coap_resource_notify_observers(coap_resource_t *_resource_, +const coap_string_t *_query_);* + +*int coap_cancel_observe(coap_session_t *_session_, coap_binary_t *_token_, +coap_pdu_type_t _message_type_);* + +*void coap_session_set_no_observe_cancel(coap_session_t *_session_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +RFC 7641 extends the CoAP protocol to be able to monitor the state of a +resource over time. + +This enables clients to "observe" resources with a defined query, i.e., to +retrieve a representation of a resource and keep this representation updated +by the server over a period of time. + +The server has to flag a resource as "observable", and then the client has +to request in a GET request that it wants to observe this resource by the use +of the COAP_OPTION_OBSERVE Option with a value of COAP_OBSERVE_ESTABLISH. +Optionally, the client can specify query options for the resource, or by using +a FETCH request instead of a GET to define a query (RFC8132). + +To remove the "observe" subscription, the client has to issue a GET (or FETCH) +request with the COAP_OPTION_OBSERVE Option with a value of +COAP_OBSERVE_CANCEL using the same token and other options used for making the +initial "observe" request. Alternatively, "observe" can be cancelled using +*coap_cancel_observe*() instead. + +The underlying library adds in and removes "subscribers" to "observe" the +resource as appropriate in the server side logic. + +Within the server application, it needs to determine that there is a change of +state of the resource under observation, and then cause the CoAP library +layer to initiate a "fake GET/FETCH request" so that an observe GET/FETCH +response gets sent back to all the clients that are observing the resource. The +appropriate GET/FETCH handler within the server application is called to fill +in the response packet with the appropriate information. This "fake GET/FETCH +request" is triggered by a call to *coap_resource_notify_observers*(). + +The call to *coap_io_process*() in the main server application i/o loop will do +all the necessary processing of sending any outstanding "fake GET/FETCH +requests". + +Whenever the server sends a copy of the state of the "observed" resource to +the client, it will use the same token used by the client when the client +requested the "observe". The client will receive this observe response +in the handler defined by *coap_register_response_handler*(3). It is the +responsibility of the client application to match the supplied token and +update the appropriate internal information. + +The *coap_resource_set_get_observable*() function enables or disables the +observable status of the _resource_ by the setting of _mode_. If _mode_ is +1, then the _resource_ is observable. If _mode_ is 0, then the +_resource_ is no longer observable. + +*NOTE:* It is not possible for the Unknown Resource, created by +*coap_resource_unknown_init*(3), to be observable as the Uri-Path is not known +when libcoap creates a "fake GET/FETCH request". The Unknown Resource PUT +handler must create a new resource and mark the resource as "observable" if +a specific resource needs to be observable. The application must then +manage the deletion of the resource at the appropriate time. + +*NOTE:* The type (confirmable or non-confirmable) of the triggered observe +GET response is determined not by the initial GET/FETCH request, but +independently by the server as per +https://tools.ietf.org/html/rfc7641#section-3.5. This is controlled by the +flags (one of COAP_RESOURCE_FLAGS_NOTIFY_NON, +COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS or COAP_RESOURCE_FLAGS_NOTIFY_CON) +used when creating the resource using *coap_resource_init*(3). + +*NOTE:* Furthermore, the server must send at least one "observe" response as +confirmable, when generally sending non-confirmable, at least every 24 hours +as per https://tools.ietf.org/html/rfc7641#section-4.5. +Libcoap automatically handles this by sending every fifth (COAP_OBS_MAX_NON) +response as a confirmable response for detection that the client is still +responding unless if COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS is set, which is a +RFC7641 violation, where non-confirmable "observe" responses are always sent +as required by some higher layer protocols. + +The *coap_resource_notify_observers*() function needs to be called whenever the +server application determines that there has been a change to the state of +_resource_. The _query_ parameter is obsolete and ignored. + +The *coap_cancel_observe*() function can be used by the client to cancel an +observe request that is being tracked. This will cause the +appropriate PDU to be sent to the server to cancel the observation, based on +the _session_ and _token_ used to set up the observe and the PDU is of type +_message_type_ (use COAP_MESSAGE_NON or COAP_MESSAGE_CON). + +The *coap_session_set_no_observe_cancel*() function can be called by the +client to disable calling *coap_cancel_observe*() when the _session_ is being +closed down / freed off. *coap_cancel_observe*() can still be called directly +by the client application. + +RETURN VALUES +------------- +The *coap_resource_set_get_observable*() function return 0 on failure, 1 on +success. + +The *coap_cancel_observe*() function return 0 on failure, 1 on success. + +EXAMPLES +-------- +*Simple Time Server* + +[source, c] +---- +#include + +#include + +coap_resource_t *time_resource = NULL; + +/* specific GET "time" handler, called from hnd_get_generic() */ + +static void +hnd_get_time(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + + unsigned char buf[40]; + size_t len; + time_t now; + (void)resource; + (void)session; + + /* ... Additional analysis code for resource, request pdu etc. ... */ + + /* After analysis, generate a suitable response */ + + /* Note that token, if set, is already in the response pdu */ + + now = time(NULL); + + if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) { + /* Output secs since Jan 1 1970 */ + len = snprintf((char *)buf, sizeof(buf), "%lu", now); + } + else { + /* Output human-readable time */ + struct tm *tmp; + tmp = gmtime(&now); + if (!tmp) { + /* If 'now' is not valid */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp); + } + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + /* + * Invoke coap_add_data_large_response() to do all the hard work. + * + * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in + * Define how long this response is valid for (secs) - 1 - to add in. + * ETAG Option added internally with unique value as param set to 0 + * + * OBSERVE Option added internally if needed within the function + * BLOCK2 Option added internally if output too large + * SIZE2 Option added internally + */ + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0, + len, + buf, NULL, NULL); +} + +/* Generic GET handler */ + +static void +hnd_get_generic(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + + coap_str_const_t *uri_path = coap_resource_get_uri_path(resource); + + if (!uri_path) { + /* Unexpected Failure */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); + return; + } + + /* Is this the "time" resource" ? */ + if (coap_string_equal(uri_path, coap_make_str_const("time"))) { + hnd_get_time(resource, session, request, query, response); + return; + } + + /* Other resources code */ + + /* Failure response */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); +} + +/* Initialize generic GET handler */ + +static void +init_resources(coap_context_t *ctx) +{ + + coap_resource_t *r; + + /* Create a resource to return return or update time */ + r = coap_resource_init(coap_make_str_const("time"), + COAP_RESOURCE_FLAGS_NOTIFY_CON); + + /* We are using a generic GET handler here */ + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_generic); + + coap_resource_set_get_observable(r, 1); + + coap_add_resource(ctx, r); + time_resource = r; + +} + +int main(int argc, char *argv[]){ + + coap_context_t *ctx = NULL; + coap_endpoint_t *ep = NULL; + coap_address_t addr; + unsigned wait_ms; + struct timeval tv_last = {0, 0}; + /* Remove (void) definition if variable is used */ + (void)argc; + (void)argv; + + memset (&tv_last, 0, sizeof(tv_last)); + + /* Create the libcoap context */ + ctx = coap_new_context(NULL); + if (!ctx) { + exit(1); + } + /* See coap_block(3) */ + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); + + coap_address_init(&addr); + addr.addr.sa.sa_family = AF_INET; + addr.addr.sin.sin_port = ntohs(COAP_DEFAULT_PORT); + ep = coap_new_endpoint(ctx, &addr, COAP_PROTO_UDP); + + /* Other Set up Code */ + + init_resources(ctx); + + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; + + while (1) { + int result = coap_io_process( ctx, wait_ms ); + if ( result < 0 ) { + break; + } else if ( result && (unsigned)result < wait_ms ) { + /* decrement if there is a result wait time returned */ + wait_ms -= result; + } else { + /* + * result == 0, or result >= wait_ms + * (wait_ms could have decremented to a small value, below + * the granularity of the timer in coap_io_process() and hence + * result == 0) + */ + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; + } + if (time_resource) { + struct timeval tv_now; + if (gettimeofday (&tv_now, NULL) == 0) { + if (tv_last.tv_sec != tv_now.tv_sec) { + /* Happens once per second */ + tv_last = tv_now; + coap_resource_notify_observers(time_resource, NULL); + } + /* need to wait until next second starts if wait_ms is too large */ + unsigned next_sec_ms = 1000 - (tv_now.tv_usec / 1000); + + if (next_sec_ms && next_sec_ms < wait_ms) + wait_ms = next_sec_ms; + } + } + } + exit(0); + +} +---- + +*Client Observe Request Setup* + +[source, c] +---- +#include + +/* Usually, requests are sent confirmable */ + +static unsigned char msgtype = COAP_MESSAGE_CON; + +static unsigned int token = 0; + +static coap_pdu_t * +coap_new_request(coap_context_t *context, coap_session_t *session, char request_code, +coap_optlist_t **options, unsigned char *data, size_t length, int observe) { + + coap_pdu_t *pdu; + /* Remove (void) definition if variable is used */ + (void)context; + + /* Create the pdu with the appropriate options */ + pdu = coap_pdu_init(msgtype, request_code, coap_new_message_id(session), + coap_session_max_pdu_size(session)); + if (!pdu) + return NULL; + + /* + * Create uniqueness token for this request for handling unsolicited / + * delayed responses + */ + token++; + if (!coap_add_token(pdu, sizeof(token), (unsigned char*)&token)) { + coap_log(LOG_DEBUG, "cannot add token to request\n"); + goto error; + } + + if (request_code == COAP_REQUEST_GET && observe) { + /* Indicate that we want to observe this resource */ + if (!coap_insert_optlist(options, + coap_new_optlist(COAP_OPTION_OBSERVE, + COAP_OBSERVE_ESTABLISH, NULL))) + goto error; + } + + /* ... Other code / options etc. ... */ + + /* Add in all the options (after internal sorting) to the pdu */ + if (!coap_add_optlist_pdu(pdu, options)) + goto error; + + if (data && length) { + /* Add in the specified data */ + if (!coap_add_data(pdu, length, data)) + goto error; + } + + return pdu; + +error: + + coap_delete_pdu(pdu); + return NULL; + +} +---- + +SEE ALSO +-------- +*coap_block*(3), *coap_context*(3), *coap_handler*(3), +*coap_pdu_setup*(3), *coap_resource*(3) and *coap_session*(3) + +FURTHER INFORMATION +------------------- +"RFC7252: The Constrained Application Protocol (CoAP)" + +"RFC7641: Observing Resources in the Constrained Application Protocol (CoAP)" + +"RFC8132: PATCH and FETCH Methods for the Constrained Application Protocol (CoAP)" + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_pdu_access.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_pdu_access.txt.in new file mode 100644 index 000000000..2d5a40dca --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_pdu_access.txt.in @@ -0,0 +1,393 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_pdu_access(3) +================= +:doctype: manpage +:man source: coap_pdu_access +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_pdu_access, +coap_check_option, +coap_decode_var_bytes, +coap_decode_var_bytes8, +coap_get_data, +coap_opt_length, +coap_opt_value, +coap_option_filter_clear, +coap_option_filter_get, +coap_option_filter_set, +coap_option_filter_unset, +coap_option_iterator_init, +coap_option_next, +coap_pdu_get_code, +coap_pdu_get_mid, +coap_pdu_get_token, +coap_pdu_get_type, +coap_get_uri_path +- Accessing CoAP PDUs + +SYNOPSIS +-------- +*#include * + +*coap_opt_t *coap_check_option(const coap_pdu_t *_pdu_, +coap_option_num_t _number_, coap_opt_iterator_t *_oi_);* + +*unsigned int coap_decode_var_bytes(const uint8_t *_buf_, size_t _length_);* + +*uint64_t coap_decode_var_bytes8(const uint8_t *_buf_, size_t _length_);* + +*int coap_get_data(const coap_pdu_t *_pdu_, size_t *_length, +const uint8_t **_data_);* + +*uint32_t coap_opt_length(const coap_opt_t *_opt_);* + +*const uint8_t *coap_opt_value(const coap_opt_t *_opt_);* + +*void coap_option_filter_clear(coap_opt_filter_t *_filter_);* + +*int coap_option_filter_get(coap_opt_filter_t *_filter_, +coap_option_num_t _number_);* + +*int coap_option_filter_set(coap_opt_filter_t *_filter_, +coap_option_num_t _number_)*; + +*int coap_option_filter_unset(coap_opt_filter_t *_filter_, +coap_option_num_t _number_);* + +*coap_opt_iterator_t *coap_option_iterator_init(const coap_pdu_t *_pdu_, +coap_opt_iterator_t *_oi_, const coap_opt_filter_t *_filter_);* + +*coap_opt_t *coap_option_next(coap_opt_iterator_t *_oi_);* + +*coap_pdu_code_t coap_pdu_get_code(const coap_pdu_t *_pdu_);* + +*coap_mid_t coap_pdu_get_mid(const coap_pdu_t *_pdu_);* + +*coap_bin_const_t coap_pdu_get_token(const coap_pdu_t *_pdu_);* + +*coap_pdu_type_t coap_pdu_get_type(const coap_pdu_t *_pdu_);* + +*coap_string_t *coap_get_uri_path(const coap_pdu_t *_pdu_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +The CoAP PDU is of the form + +--header--|--optional token--|--optional options--|--optional payload-- + +The terminology used is taken mainly from +https://tools.ietf.org/html/rfc7252#section-1.2 + +The following functions provide access to the information held within a PDU. + +*Header:* + +The *coap_pdu_get_type*() function returns one of the messages types below from +the PDU _pdu_. + +[source, c] +---- +COAP_MESSAGE_CON Type confirmable. +COAP_MESSAGE_NON Type non-confirmable. +COAP_MESSAGE_ACK Type acknowledge +COAP_MESSAGE_RST Type reset. +---- + +The *coap_pdu_get_code*() function returns one of the codes below from the +PDU _pdu_. It is possible that new codes are added in over time. + +[source, c] +---- +COAP_EMPTY_CODE 0.00 +COAP_REQUEST_CODE_GET 0.01 +COAP_REQUEST_CODE_POST 0.02 +COAP_REQUEST_CODE_PUT 0.03 +COAP_REQUEST_CODE_DELETE 0.04 +COAP_REQUEST_CODE_FETCH 0.05 +COAP_REQUEST_CODE_PATCH 0.06 +COAP_REQUEST_CODE_IPATCH 0.07 +COAP_RESPONSE_CODE_OK 2.00 +COAP_RESPONSE_CODE_CREATED 2.01 +COAP_RESPONSE_CODE_DELETED 2.02 +COAP_RESPONSE_CODE_VALID 2.03 +COAP_RESPONSE_CODE_CHANGED 2.04 +COAP_RESPONSE_CODE_CONTENT 2.05 +COAP_RESPONSE_CODE_CONTINUE 2.31 +COAP_RESPONSE_CODE_BAD_REQUEST 4.00 +COAP_RESPONSE_CODE_UNAUTHORIZED 4.01 +COAP_RESPONSE_CODE_BAD_OPTION 4.02 +COAP_RESPONSE_CODE_FORBIDDEN 4.03 +COAP_RESPONSE_CODE_NOT_FOUND 4.04 +COAP_RESPONSE_CODE_NOT_ALLOWED 4.05 +COAP_RESPONSE_CODE_NOT_ACCEPTABLE 4.06 +COAP_RESPONSE_CODE_INCOMPLETE 4.08 +COAP_RESPONSE_CODE_CONFLICT 4.09 +COAP_RESPONSE_CODE_PRECONDITION_FAILED 4.12 +COAP_RESPONSE_CODE_REQUEST_TOO_LARGE 4.13 +COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT 4.15 +COAP_RESPONSE_CODE_UNPROCESSABLE 4.22 +COAP_RESPONSE_CODE_TOO_MANY_REQUESTS 4.29 +COAP_RESPONSE_CODE_INTERNAL_ERROR 5.00 +COAP_RESPONSE_CODE_NOT_IMPLEMENTED 5.01 +COAP_RESPONSE_CODE_BAD_GATEWAY 5.02 +COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE 5.03 +COAP_RESPONSE_CODE_GATEWAY_TIMEOUT 5.04 +COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED 5.05 +COAP_RESPONSE_CODE_HOP_LIMIT_REACHED 5.08 +COAP_SIGNALING_CODE_CSM 7.01 +COAP_SIGNALING_CODE_PING 7.02 +COAP_SIGNALING_CODE_PONG 7.03 +COAP_SIGNALING_CODE_RELEASE 7.04 +COAP_SIGNALING_CODE_ABORT 7.05 +---- + +The *coap_pdu_get_mid*() returns the message id from the PDU _pdu_. + +*Token:* + +The *coap_pdu_get_token*() returns the token information held in the PDU _pdu_ +which may be zero length. + +*Options:* + +The following is the current list of options with their numeric value +---- +/* + * The C, U, and N flags indicate the properties + * Critical, Unsafe, and NoCacheKey, respectively. + * If U is set, then N has no meaning as per + * https://tools.ietf.org/html/rfc7252#section-5.10 + * and is set to a -. + * Separately, R is for the options that can be repeated + * + * The least significant byte of the option is set as followed + * as per https://tools.ietf.org/html/rfc7252#section-5.4.6 + * + * 0 1 2 3 4 5 6 7 + * --+---+---+---+---+---+---+---+ + * | NoCacheKey| U | C | + * --+---+---+---+---+---+---+---+ + * + * https://tools.ietf.org/html/rfc8613#section-4 goes on to define E, I and U + * properties Encrypted and Integrity Protected, Integrity Protected Only and + * Unprotected respectively. Integrity Protected Only is not currently used. + * + * An Option is tagged with CUNREIU with any of the letters replaced with _ if + * not set, or - for N if U is set (see above) for aiding understanding of the + * Option. + */ + +COAP_OPTION_IF_MATCH 1 /* C__RE__, opaque, 0-8 B, RFC7252 */ +COAP_OPTION_URI_HOST 3 /* CU-___U, String, 1-255 B, RFC7252 */ +COAP_OPTION_ETAG 4 /* ___RE__, opaque, 1-8 B, RFC7252 */ +COAP_OPTION_IF_NONE_MATCH 5 /* C___E__, empty, 0 B, RFC7252 */ +COAP_OPTION_OBSERVE 6 /* _U-_E_U, empty/uint, 0 B/0-3 B, RFC7641 */ +COAP_OPTION_URI_PORT 7 /* CU-___U, uint, 0-2 B, RFC7252 */ +COAP_OPTION_LOCATION_PATH 8 /* ___RE__, String, 0-255 B, RFC7252 */ +COAP_OPTION_OSCORE 9 /* C_____U, *, 0-255 B, RFC8613 */ +COAP_OPTION_URI_PATH 11 /* CU-RE__, String, 0-255 B, RFC7252 */ +COAP_OPTION_CONTENT_FORMAT 12 /* ____E__, uint, 0-2 B, RFC7252 */ +/* COAP_OPTION_MAXAGE default 60 seconds if not set */ +COAP_OPTION_MAXAGE 14 /* _U-_E_U, uint, 0-4 B, RFC7252 */ +COAP_OPTION_URI_QUERY 15 /* CU-RE__, String, 1-255 B, RFC7252 */ +COAP_OPTION_HOP_LIMIT 16 /* ______U, uint, 1 B, RFC8768 */ +COAP_OPTION_ACCEPT 17 /* C___E__, uint, 0-2 B, RFC7252 */ +COAP_OPTION_LOCATION_QUERY 20 /* ___RE__, String, 0-255 B, RFC7252 */ +COAP_OPTION_BLOCK2 23 /* CU-_E_U, uint, 0-3 B, RFC7959 */ +COAP_OPTION_BLOCK1 27 /* CU-_E_U, uint, 0-3 B, RFC7959 */ +COAP_OPTION_SIZE2 28 /* __N_E_U, uint, 0-4 B, RFC7959 */ +COAP_OPTION_PROXY_URI 35 /* CU-___U, String, 1-1034 B, RFC7252 */ +COAP_OPTION_PROXY_SCHEME 39 /* CU-___U, String, 1-255 B, RFC7252 */ +COAP_OPTION_SIZE1 60 /* __N_E_U, uint, 0-4 B, RFC7252 */ +COAP_OPTION_NORESPONSE 258 /* _U-_E_U, uint, 0-1 B, RFC7967 */ +---- +See FURTHER INFORMATION as to how to get the latest list. + +The *coap_check_option*() function is used to check whether the specified option +_number_ is in the PDU _pdu_. The option iterator _oi_ is used as an internal +storage location while iterating through the options looking for the specific +_number_. If the _number_ is repeated in the _pdu_, only the first occurrence +will be returned. If the option is not found, NULL is returned. + +Alternatively, the *coap_option_iterator_init*() function can be used to +initialize option iterator _oi_, applying a filter _filter_ to indicate which +options are to be ignored when iterating through the options. The _filter_ can +be NULL (or COAP_OPT_ALL) if all of the options are required. Then this is +followed by using the *coap_option_next*() function in a loop to return all +the appropriate options until NULL is returned - indicating the end of +available the options. See EXAMPLES below for further information. + +To set up the filter, the following 4 functions are available. + +The *coap_option_filter_clear*() function initializes _filter_ to have no +options set. + +The *coap_option_filter_get*() function is used to check whether option _number_ +is set in _filter_. + +The *coap_option_filter_set*() function is used to set option _number_ in +_filter_. + +The *coap_option_filter_unset*() function is used to remove option _number_ in +_filter_. + +The *coap_opt_length*() function returns the length of the option _opt_. + +The *coap_opt_value*() function returns a pointer to the start of the data for +the option. + +The *coap_decode_var_bytes*() function will decode an option up to 4 bytes +long from _buf_ and _length_ into an unsigned 32bit number. + +The *coap_decode_var_bytes8*() function will decode an option up to 8 bytes +long from _buf_ and _length_ into an unsigned 64bit number. + +The *coap_get_uri_path*() function will abstract the uri path from the +specified _pdu_. The returned uri path will need to be freed off when no +longer required. + +*Payload:* + +The *coap_get_data*() function is used abstract from the _pdu_ +information about the received data by updating _length_ with the length of +data available, and _data_ with a pointer to where the data is located. + +*NOTE:* This function has been updated by *coap_get_data_large*() when large +transfers may take place. See coap_block(3). + +RETURN VALUES +------------- + +*coap_check_option*() and *coap_option_next*() returns a coap_opt_t* or +NULL if not found. + +*coap_decode_var_bytes*() and *coap_decode_var_bytes8*() return the decoded +value. + +*coap_pdu_get_code*(), *coap_pdu_get_mid*(), *coap_pdu_get_type*() return +the appropriate value. + +*coap_option_filter_set*(), *coap_option_filter_set*() and +*coap_option_filter_unset*() return 1 on success or 0 on failure. + +*coap_get_data*() returns 1 if data, else 0. + +*coap_opt_length*() returns the option length. + +*coap_opt_value*() returns a pointer to the start of the option value or +NULL if error. + +*coap_option_iterator_init*() returns ap pointer to the provided interator +or NULL on error. + +*coap_pdu_get_token*() returns a pointer to the token in the pdu. + +*coap_get_uri_path*() returns an allocated pointer to the uri path in the +pdu or NULL on error. This pointer will need to be freed off. + +EXAMPLES +-------- +*Abstract information from PDU* + +[source, c] +---- +#include + +static void +get_pdu_information(coap_pdu_t *pdu) { + + int ret; + /* Header variables */ + coap_pdu_type_t pdu_type; + coap_pdu_code_t pdu_code; + coap_mid_t pdu_mid; + /* Token variables */ + coap_bin_const_t pdu_token; + /* Option variables */ + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_opt_filter_t ignore_options; + + /* Data payload variables */ + size_t pdu_data_length; + const uint8_t *pdu_data; + size_t pdu_data_offset; + size_t pdu_data_total_length; + + /* Pull in the header information */ + pdu_type = coap_pdu_get_type(pdu); + pdu_code = coap_pdu_get_code(pdu); + pdu_mid = coap_pdu_get_mid(pdu); + + /* Pull in the token information */ + pdu_token = coap_pdu_get_token(pdu); + + /* Pull in the option information */ + /* Specific option check */ + option = coap_check_option(pdu, COAP_OPTION_OBSERVE, &opt_iter); + if (option) { + uint32_t value = coap_decode_var_bytes(coap_opt_value(option), + coap_opt_length(option)); + coap_log(LOG_INFO, "Option OBSERVE, value %u\n", value); + } + /* Iterate through all options */ + coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_iter))) { + coap_log(LOG_INFO, "A: Option %d, Length %u\n", + opt_iter.number, coap_opt_length(option)); + } + /* Iterate through options, some ignored */ + coap_option_filter_clear(&ignore_options); + coap_option_filter_set(&ignore_options, COAP_OPTION_OBSERVE); + coap_option_iterator_init(pdu, &opt_iter, &ignore_options); + while ((option = coap_option_next(&opt_iter))) { + coap_log(LOG_INFO, "I: Option %d, Length %u\n", + opt_iter.number, coap_opt_length(option)); + } + + /* Pull in the payload information */ + ret = coap_get_data(pdu, &pdu_data_length, &pdu_data); + /* or */ + ret = coap_get_data_large(pdu, &pdu_data_length, &pdu_data, + &pdu_data_offset, &pdu_data_total_length); + +} +---- + +SEE ALSO +-------- +*coap_block*(3) and *coap_pdu_setup*(3) + +FURTHER INFORMATION +------------------- +See + +"RFC7252: The Constrained Application Protocol (CoAP)" + +"RFC8613: Object Security for Constrained RESTful Environments (OSCORE)" + +for further information. + +See https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#option-numbers +for the current set of defined CoAP Options. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_pdu_setup.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_pdu_setup.txt.in new file mode 100644 index 000000000..a18b5cd81 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_pdu_setup.txt.in @@ -0,0 +1,721 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_pdu_setup(3) +================= +:doctype: manpage +:man source: coap_pdu_setup +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_pdu_setup, +coap_new_pdu, +coap_pdu_init, +coap_session_init_token, +coap_session_new_token, +coap_add_token, +coap_new_optlist, +coap_insert_optlist, +coap_delete_optlist, +coap_encode_var_safe, +coap_encode_var_safe8, +coap_add_optlist_pdu, +coap_add_option, +coap_add_data, +coap_add_data_blocked_response, +coap_send, +coap_split_path, +coap_split_query, +coap_pdu_set_mid, +coap_pdu_set_code, +coap_pdu_set_type +- Setting up CoAP PDUs + +SYNOPSIS +-------- +*#include * + +*coap_pdu_t *coap_new_pdu(coap_pdu_type_t _type_, coap_pdu_code_t _code_, +coap_session_t *_session_);* + +*coap_pdu_t *coap_pdu_init(coap_pdu_type_t _type_, coap_pdu_code_t _code_, +coap_mid_t _message_id_, size_t _max_size_);* + +*void coap_session_init_token(coap_session_t *_session_, size_t _length_, +const uint8_t *_token_);* + +*void coap_session_new_token(coap_session_t *_session_, size_t *_length_, +uint8_t *_token_);* + +*int coap_add_token(coap_pdu_t *_pdu_, size_t _length_, +const uint8_t *_data_);* + +*coap_optlist_t *coap_new_optlist(uint16_t _number_, size_t _length_, +const uint8_t *_data_);* + +*int coap_insert_optlist(coap_optlist_t **_optlist_chain_, +coap_optlist_t *_optlist_);* + +*void coap_delete_optlist(coap_optlist_t *_optlist_chain_);* + +*unsigned int coap_encode_var_safe(uint8_t *_buffer_, size_t _size_, +unsigned int _value_);* + +*unsigned int coap_encode_var_safe8(uint8_t *_buffer_, size_t _size_, +uint64_t _value_);* + +*int coap_add_optlist_pdu(coap_pdu_t *_pdu_, coap_optlist_t **_optlist_chain_);* + +*size_t coap_add_option(coap_pdu_t *_pdu_, uint16_t _number_, size_t _length_, +const uint8_t *_data_);* + +*int coap_add_data(coap_pdu_t *_pdu_, size_t _length_, const uint8_t *_data_);* + +*void coap_add_data_blocked_response(const coap_pdu_t *_request_, +coap_pdu_t *_response_, uint16_t _media_type_, int _maxage_, size_t _length_, +const uint8_t *_data_);* + +*coap_mid_t coap_send(coap_session_t *_session_, coap_pdu_t *_pdu_);* + +*int coap_split_path(const uint8_t *_path_, size_t _length_, uint8_t *_buffer_, +size_t *_buflen_);* + +*int coap_split_query(const uint8_t *_query_, size_t _length_, +uint8_t *_buffer_, size_t *_buflen_);* + +*void coap_pdu_set_mid(coap_pdu_t *_pdu_, coap_mid_t _mid_);* + +*void coap_pdu_set_code(coap_pdu_t *_pdu_, coap_pdu_code_t _code_);* + +*void coap_pdu_set_type(coap_pdu_t *_pdu_, coap_pdu_type_t _type_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +The CoAP PDU is of the form + +--header--|--optional token--|--optional options--|--optional payload-- + +The terminology used is taken mainly from +https://tools.ietf.org/html/rfc7252#section-1.2 + +The PDU must be built in the correct order, from left to right. In particular, +the options need to be added in the correct numerical option order as they are +stored in the PDU using relative numeric offsets from the previous option +number. + +There are option list functions available where options can be added to a +chained list of options and then the chain list is sorted and then be added to +the PDU. + +Typically for clients, when creating a request, the PDU needs to be created +before filling it with the appropriate information. + +Typically with a server, the response PDU, with the optional token already added +in, will already be created before the response handler is called, and the +response PDU will need to be updated as appropriate starting with the optional +options. Note that updating the response pdu's code variable will cause the +response pdu to get transmitted. If code does not get updated, and the PDU is +of type CONFIRMABLE, then the response PDU is transmitted as an empty ACK +packet. The response pdu is always freed off by the underlying library. + +For handling situations where the data to be transmitted does not fit into a +single packet, see *coap_block*(3). + +PDU CREATE AND HEADER +--------------------- + +*Function: coap_new_pdu()* + +The *coap_new_pdu*() function returns a newly created PDU of type +_coap_pdu_t_. + +The _type_ is one of the following + +[source, c] +---- +COAP_MESSAGE_CON Set the _PDU_ to be of type confirmable. +COAP_MESSAGE_NON Set the _PDU_ to be of type non-confirmable. +COAP_MESSAGE_ACK Set the _PDU_ to be of type acknowledge (for internal use). +COAP_MESSAGE_RST Set the _PDU_ to be of type reset. +---- + +The _code_ is one of the following + +[source, c] +---- +COAP_EMPTY_CODE 0.00 +COAP_REQUEST_CODE_GET 0.01 +COAP_REQUEST_CODE_POST 0.02 +COAP_REQUEST_CODE_PUT 0.03 +COAP_REQUEST_CODE_DELETE 0.04 +COAP_REQUEST_CODE_FETCH 0.05 +COAP_REQUEST_CODE_PATCH 0.06 +COAP_REQUEST_CODE_IPATCH 0.07 +COAP_RESPONSE_CODE_OK 2.00 +COAP_RESPONSE_CODE_CREATED 2.01 +COAP_RESPONSE_CODE_DELETED 2.02 +COAP_RESPONSE_CODE_VALID 2.03 +COAP_RESPONSE_CODE_CHANGED 2.04 +COAP_RESPONSE_CODE_CONTENT 2.05 +COAP_RESPONSE_CODE_CONTINUE 2.31 +COAP_RESPONSE_CODE_BAD_REQUEST 4.00 +COAP_RESPONSE_CODE_UNAUTHORIZED 4.01 +COAP_RESPONSE_CODE_BAD_OPTION 4.02 +COAP_RESPONSE_CODE_FORBIDDEN 4.03 +COAP_RESPONSE_CODE_NOT_FOUND 4.04 +COAP_RESPONSE_CODE_NOT_ALLOWED 4.05 +COAP_RESPONSE_CODE_NOT_ACCEPTABLE 4.06 +COAP_RESPONSE_CODE_INCOMPLETE 4.08 +COAP_RESPONSE_CODE_CONFLICT 4.09 +COAP_RESPONSE_CODE_PRECONDITION_FAILED 4.12 +COAP_RESPONSE_CODE_REQUEST_TOO_LARGE 4.13 +COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT 4.15 +COAP_RESPONSE_CODE_UNPROCESSABLE 4.22 +COAP_RESPONSE_CODE_TOO_MANY_REQUESTS 4.29 +COAP_RESPONSE_CODE_INTERNAL_ERROR 5.00 +COAP_RESPONSE_CODE_NOT_IMPLEMENTED 5.01 +COAP_RESPONSE_CODE_BAD_GATEWAY 5.02 +COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE 5.03 +COAP_RESPONSE_CODE_GATEWAY_TIMEOUT 5.04 +COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED 5.05 +COAP_RESPONSE_CODE_HOP_LIMIT_REACHED 5.08 +COAP_SIGNALING_CODE_CSM 7.01 +COAP_SIGNALING_CODE_PING 7.02 +COAP_SIGNALING_CODE_PONG 7.03 +COAP_SIGNALING_CODE_RELEASE 7.04 +COAP_SIGNALING_CODE_ABORT 7.05 +---- + +and _session_ is used to set up other default values. + +*Function: coap_pdu_init()* + +The *coap_pdu_init*() function does the same work as *coap_new_pdu*() but gives +the additional ability to define the default values for _message_id_ and +_max_size_ that *coap_new_pdu*() creates. + +The _message_id_ must be unique per request (which is not the same as the +token), and must not be reused within EXCHANGE_LIFETIME (usually 247 seconds). +To automate this, the function *coap_new_message_id*(_session_) should be +called. + +At the CoAP protocol level, requests and responses are matched by _message_id_ +which is why it needs to be unique. At the application level, for "separate" +responses, the initial empty ACK response matches the _message_id_ of the +request (handled by libcoap) but the actual response has the same token as the +request and this must be used for the match. For "piggybacked" responses the +token must still be used as the valid match for request and response. and the +_message_id_ just happens to match (but unsafe in case the server is sending +back a "separate" response). + +The _max_size_ parameter defines the maximum size of a _PDU_ and is usually +determined by calling coap_session_max_pdu_size(session); + +*Function: coap_pdu_set_mid()* + +The *coap_pdu_set_mid*() function is used to set the message id _mid_ in the +PDU _pdu_. + +*Function: coap_pdu_set_code()* + +The *coap_pdu_set_code*() function is used to set the code _code_ in the PDU +_pdu_. + +*Function: coap_pdu_set_type()* + +The *coap_pdu_set_type*() function is used to set the _type_ of the PDU _pdu_. + +*NOTE:* A PDU does not need to be created by the server application to send +back a response. The libcoap server logic creates the initial PDU with +COAP_EMPTY_CODE, appropriate message_id, matching token and potentially some +other options before calling the appropriate request handler (See +*coap_register_request_handler*(3)). + +PDU TOKEN +--------- + +*Function: coap_session_init_token()* + +The *coap_session_init_token*() function is used to initialize the starting +_token_ of _length_ for the _session_. + +*Function: coap_session_new_token()* + +The *coap_session_new_token*() function is used to obtain the next available +_token_ of _length_ for the _session_. Note that the same token must be used +for doing an observe cancellation that was used for doing the observe +registration. Otherwise tokens should be unique for each request/response so +that they can be correctly matched. + +*Function: coap_add_token()* + +The *coap_add_token*() function adds in the specified token's _data_ of length +_length_ to the PDU _pdu_. The maximum length of the token is 8 bytes. +Adding the token must be done before any options or data are added. +This function must only be called once per _pdu_, and must not be called +in the appropriate request handler. + +If a token is not added, then the token in the PDU is zero length, but still a +valid token which is used for matching. The exception is an empty ACK packet. + +*NOTE:* The token provided by the client application may not be the same as +used internally by libcoap - for example when doing data transmission where +the body of data is spread over multiple payloads (see *coap_block*(3)). +However, when the data transfers complete, the application will receive the +corrected token in the response PDU. + +PDU OPTIONS +----------- + +The following is the current list of options with their numeric value +---- +/* + * The C, U, and N flags indicate the properties + * Critical, Unsafe, and NoCacheKey, respectively. + * If U is set, then N has no meaning as per + * https://tools.ietf.org/html/rfc7252#section-5.10 + * and is set to a -. + * Separately, R is for the options that can be repeated + * + * The least significant byte of the option is set as followed + * as per https://tools.ietf.org/html/rfc7252#section-5.4.6 + * + * 0 1 2 3 4 5 6 7 + * --+---+---+---+---+---+---+---+ + * | NoCacheKey| U | C | + * --+---+---+---+---+---+---+---+ + * + * https://tools.ietf.org/html/rfc8613#section-4 goes on to define E, I and U + * properties Encrypted and Integrity Protected, Integrity Protected Only and + * Unprotected respectively. Integrity Protected Only is not currently used. + * + * An Option is tagged with CUNREIU with any of the letters replaced with _ if + * not set, or - for N if U is set (see above) for aiding understanding of the + * Option. + */ + +COAP_OPTION_IF_MATCH 1 /* C__RE__, opaque, 0-8 B, RFC7252 */ +COAP_OPTION_URI_HOST 3 /* CU-___U, String, 1-255 B, RFC7252 */ +COAP_OPTION_ETAG 4 /* ___RE__, opaque, 1-8 B, RFC7252 */ +COAP_OPTION_IF_NONE_MATCH 5 /* C___E__, empty, 0 B, RFC7252 */ +COAP_OPTION_OBSERVE 6 /* _U-_E_U, empty/uint, 0 B/0-3 B, RFC7641 */ +COAP_OPTION_URI_PORT 7 /* CU-___U, uint, 0-2 B, RFC7252 */ +COAP_OPTION_LOCATION_PATH 8 /* ___RE__, String, 0-255 B, RFC7252 */ +COAP_OPTION_OSCORE 9 /* C_____U, *, 0-255 B, RFC8613 */ +COAP_OPTION_URI_PATH 11 /* CU-RE__, String, 0-255 B, RFC7252 */ +COAP_OPTION_CONTENT_FORMAT 12 /* ____E__, uint, 0-2 B, RFC7252 */ +/* COAP_OPTION_MAXAGE default 60 seconds if not set */ +COAP_OPTION_MAXAGE 14 /* _U-_E_U, uint, 0-4 B, RFC7252 */ +COAP_OPTION_URI_QUERY 15 /* CU-RE__, String, 1-255 B, RFC7252 */ +COAP_OPTION_HOP_LIMIT 16 /* ______U, uint, 1 B, RFC8768 */ +COAP_OPTION_ACCEPT 17 /* C___E__, uint, 0-2 B, RFC7252 */ +COAP_OPTION_LOCATION_QUERY 20 /* ___RE__, String, 0-255 B, RFC7252 */ +COAP_OPTION_BLOCK2 23 /* CU-_E_U, uint, 0-3 B, RFC7959 */ +COAP_OPTION_BLOCK1 27 /* CU-_E_U, uint, 0-3 B, RFC7959 */ +COAP_OPTION_SIZE2 28 /* __N_E_U, uint, 0-4 B, RFC7959 */ +COAP_OPTION_PROXY_URI 35 /* CU-___U, String, 1-1034 B, RFC7252 */ +COAP_OPTION_PROXY_SCHEME 39 /* CU-___U, String, 1-255 B, RFC7252 */ +COAP_OPTION_SIZE1 60 /* __N_E_U, uint, 0-4 B, RFC7252 */ +COAP_OPTION_ECHO 252 /* _N__E_U, opaque, 0-40 B, RFC9175 */ +COAP_OPTION_NORESPONSE 258 /* _U-_E_U, uint, 0-1 B, RFC7967 */ +COAP_OPTION_RTAG 292 /* ___RE_U, opaque, 0-8 B, RFC9175 */ +---- +See FURTHER INFORMATION as to how to get the latest list. + +*Function: coap_new_optlist()* + +The *coap_new_optlist*() function returns a newly created _optlist_ entry of +type _coap_optlist_t_*. The _number_ specifies which CoAP option is to be +used, and is one of the COAP_OPTION_* definitions. The _length_ is the length +of the data of the option, and _data_ points to the content of the option. + +*NOTE:* Where possible, the option data needs to be stripped of leading zeros +(big endian) to reduce the amount of data needed in the PDU, as well as in +some cases the maximum data size of an option can be exceeded if not stripped +and hence be illegal. This is done by using *coap_encode_var_safe*() or +*coap_encode_var_safe8*(). + +*Function: coap_insert_optlist()* + +The *coap_insert_optlist*() function adds the _optlist_ entry onto the +_optlist_chain_ and then sorts the _optlist_chain_ before returning. +The initial _optlist_chain_ entry needs to be set to NULL before this function +is first called. The *coap_delete_optlist*() function has to be called to free +off all the _optlist_chain_ entries. + +*Function: coap_delete_optlist()* + +The *coap_delete_optlist*() function deletes and frees off all the optlist +entries in the _optlist_chain_. + +*Function: coap_add_optlist_pdu()* + +The *coap_add_optlist_pdu*() function sorts all of the entries in +_optlist_chain_ into ascending option numeric order and adds all the entries +to the _pdu_. This function does not free off the entries in _optlist_chain_. +This function must be called after adding any token and before adding in the +payload data. + +*Function: coap_add_option()* + +The *coap_add_option*() function adds in the specified option of type _number_ +with _data_ of length _length_ to the PDU _pdu_. +It is important that options are added to the _pdu_ with _number_ either +being the same or greater than the previous option _number_ that was added. + +*NOTE:* Where possible, the option data needs to be stripped of leading zeros +(big endian) to reduce the amount of data needed in the PDU, as well as in +some cases the maximum data size of an option can be exceeded if not stripped +and hence be illegal. This is done by using *coap_encode_var_safe*() or +*coap_encode_var_safe8*(). + +*Function: coap_encode_var_safe()* + +The *coap_encode_var_safe*() function encodes _value_ into _buffer_ which has +a size of _size_ in bytes. Normally, the _buffer_ size should be at least +the sizeof(int) bytes unless you definitely know less space is required. + +*Function: coap_encode_var_safe8()* + +The *coap_encode_var_safe8*() function encodes 8 byte _value_ into _buffer_ +which has a size of _size_ in bytes. Normally, the _buffer_ size should be at +least 8 bytes unless you definitely know less space is required. + +*Function: coap_split_path()* + +The *coap_split_path*() function splits up _path_ of length _length_ and +places the result in _buffer_ which has a size of _buflen_ with the nul +character separating each path component. _buflen_ needs +to be preset with the size of _buffer_ before the function call, and then +_buflen_ is updated with the actual size of _buffer_ used. The return +value indicates the number of components that individual COAP_OPTION_URI_PATH +options need to be created for. + +*Function: coap_split_query()* + +The *coap_split_query*() function splits up _query_ of length _length_ and +places the result in _buffer_ which has a size of _buflen_ with the nul +character separating each path component. _buflen_ needs +to be preset with the size of _buffer_ before the function call, and then +_buflen_ is updated with the actual size of _buffer_ used. The return +value indicates the number of components that individual COAP_OPTION_URI_QUERY +options need to be created for. + +PDU OPTIONS - LIBCOAP HANDLING +------------------------------ +Most of the options are under the control of the applications, but the +following are primarily used internally by libcoap. + +*COAP_OPTION_BLOCK1* and *COAP_OPTION_BLOCK2* + +These Block options are used when a large body needs to be split up into +multiple payloads. Following the introduction of +*coap_context_set_block_mode*(3), libcoap can internally handle the setting +of these options (see *coap_block*(3)). Applications can continue to include +these options to set hint block size values. + +It is recommended that +*coap_context_set_block_mode(context, COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY)* +is used to reduce the programming requirements for block handling within +the applications. + +*COAP_OPTION_ECHO* + +This option can be set by the server application to indicate that the state of +the client's freshness is confirmed. The libcoap client logic will detect the +use of the Echo option by the server and reflect back the Echo value in the +next request without involving the client application. The opaque +option Echo may be seen by the client application. + +*COAP_OPTION_ETAG* + +This option is normally set by the server libcoap logic when sending back +multiple payloads so that the (libcoap logic) client can re-assemble the +correct body. + +*COAP_OPTION_HOP_LIMIT* + +When using proxy logic, the value of the Hop-Limit option is decremented by +one for each proxy hop. If the count decrements to zero, then a 5.08 (Hop +Limit Reached) error code is returned to the sender. The initial count is +16, unless the client application sets its own limit using the Hop-Limit option. + +*COAP_OPTION_RTAG* + +This option is set by the libcoap client logic when transmitting multiple +bodies with multiple payloads so that the (libcoap logic) server can +differentiate and re-assemble the correct body. + +*COAP_OPTION_SIZE1* and *COAP_OPTION_SIZE2* + +These options are added by the libcoap logic to provide a size (Size1 by +libcoap client logic, Size2 by libcoap server logic) indication to the +recipient of the size of the large body that is to be transferred. See +*coap_block*(3). + +PDU PAYLOAD DATA +---------------- + +*Function: coap_add_data()* + +The *coap_add_data*() function adds in the specified payload _data_ of length +_length_ to the PDU _pdu_. Adding the payload data must be done after any +token or options are added. This function must only be called once per _pdu_. + +*Function: coap_add_data_blocked_response()* + +The *coap_add_data_blocked_response*() function adds in the appropriate part +of the payload _data_ of length _length_ to the PDU _pdu_. It should be used +as a direct replacement for *coap_add_data*() if it is possible that the data +will not fit into a single pdu. It also adds in the appropriate +CoAP options to handle Block-Wise transfer. This function is usually used for +a server's GET / FETCH response. The _request_ and _response_ are the same +parameters for the registered GET / FETCH resource handler. +The _media_type_ is for the format of the _data_ and _maxage_ defines the +lifetime of the response. If set to -1, then the Max-Age option does not get +included. This function must only be called once per _pdu_. +It is the responsibility of the client to recognize that it has only +received a part of the data and request the next block (with the appropriate +Block options) from the server. Returning the next requested block is handled +by this function. + +*NOTE:* This function has been superseded by *coap_add_data_large_response*(). +See *coap_block*(3). + +PDU TRANSMIT +------------ + +*Function: coap_send()* + +The *coap_send*() function is used to initiate the transmission of the _pdu_ +associated with the _session_. The caller must not access or delete _pdu_ +after calling *coap_send*() - even if there is a return error. + +*NOTE:* For request handlers, returning from the request handler will cause +the response PDU to be transmitted as appropriate and there is no need to call +*coap_send*() to do this. + +RETURN VALUES +------------- +The *coap_new_pdu*() and *coap_pdu_init*() function returns a newly created +_PDU_ or NULL if there is a malloc or parameter failure. + +The *coap_new_optlist*() function returns a newly created _optlist_ or NULL +if there is a malloc failure. + +The *coap_add_token*(), *coap_insert_optlist*(), *coap_delete_optlist*(), +*coap_add_optlist_pdu*() and *coap_add_data*() +functions return 0 on failure, 1 on success. + +The *coap_add_optlist*() function returns either the length of the option +or 0 on failure. + +The *coap_encode_var_safe*() function returns either the length of bytes +encoded (which can be 0 when encoding 0) or 0 on failure. + +The *coap_encode_var_safe8*() function returns either the length of bytes +encoded (which can be 0 when encoding 0) or 0 on failure. + +The *coap_send*() function returns the CoAP message ID on success or +COAP_INVALID_MID on failure. + +The *coap_split_path*() and *coap_split_query*() functions return the number +of components found. + +EXAMPLES +-------- +*Setup PDU and Transmit* + +[source, c] +---- +#include + +static int +build_send_pdu(coap_context_t *context, coap_session_t *session, +uint8_t msgtype, uint8_t request_code, const char *uri, const char *query, +unsigned char *data, size_t length, int observe) { + + coap_pdu_t *pdu; + uint8_t buf[1024]; + size_t buflen; + uint8_t *sbuf = buf; + int res; + coap_optlist_t *optlist_chain = NULL; + /* Remove (void) definition if variable is used */ + (void)context; + + /* Create the pdu with the appropriate options */ + pdu = coap_pdu_init(msgtype, request_code, coap_new_message_id(session), + coap_session_max_pdu_size(session)); + if (!pdu) + return 0; + + /* + * Create unique token for this request for handling unsolicited / + * delayed responses + */ + coap_session_new_token(session, &buflen, buf); + if (!coap_add_token(pdu, buflen, buf)) { + coap_log(LOG_DEBUG, "cannot add token to request\n"); + goto error; + } + + if (uri) { + /* Add in the URI options */ + buflen = sizeof(buf); + res = coap_split_path((const uint8_t*)uri, strlen(uri), sbuf, &buflen); + while (res--) { + if (!coap_insert_optlist(&optlist_chain, + coap_new_optlist(COAP_OPTION_URI_PATH, + coap_opt_length(sbuf), coap_opt_value(sbuf)))) + goto error; + sbuf += coap_opt_size(sbuf); + } + } + + if (query) { + /* Add in the QUERY options */ + buflen = sizeof(buf); + res = coap_split_query((const uint8_t*)query, strlen(query), sbuf, &buflen); + while (res--) { + if (!coap_insert_optlist(&optlist_chain, + coap_new_optlist(COAP_OPTION_URI_QUERY, + coap_opt_length(sbuf), coap_opt_value(sbuf)))) + goto error; + sbuf += coap_opt_size(sbuf); + } + } + + if (request_code == COAP_REQUEST_GET && observe) { + /* Indicate that we want to observe this resource */ + if (!coap_insert_optlist(&optlist_chain, + coap_new_optlist(COAP_OPTION_OBSERVE, + coap_encode_var_safe(buf, sizeof(buf), + COAP_OBSERVE_ESTABLISH), buf) + )) + goto error; + } + + /* ... Other code / options etc. ... */ + + /* Add in all the options (after internal sorting) to the pdu */ + if (!coap_add_optlist_pdu(pdu, &optlist_chain)) + goto error; + + if (data && length) { + /* Add in the specified data */ + if (!coap_add_data(pdu, length, data)) + goto error; + } + + if (coap_send(session, pdu) == COAP_INVALID_MID) + goto error; + return 1; + +error: + + if (pdu) + coap_delete_pdu(pdu); + return 0; + +} +---- + +*Resource Request Handler Response PDU Update* + +[source, c] +---- +#include + +#include + +static void +hnd_get_time(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + + unsigned char buf[40]; + size_t len; + time_t now; + + /* ... Additional analysis code for resource, request pdu etc. ... */ + + /* After analysis, generate a suitable response */ + + now = time(NULL); + + if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) { + /* Output secs since Jan 1 1970 */ + len = snprintf((char *)buf, sizeof(buf), "%lu", now); + } + else { + /* Output human-readable time */ + struct tm *tmp; + tmp = gmtime(&now); + if (!tmp) { + /* If 'now' is not valid */ + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp); + } + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + /* + * Invoke coap_add_data_large_response() to do all the hard work. + * + * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in + * Define how long this response is valid for (secs) - 1 - to add in. + * Etag Option added internally with unique value as param set to 0 + * + * Observe Option added internally if needed within the function + * Block2 Option added internally if output too large + * Size2 Option added internally + */ + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0, + len, + buf, NULL, NULL); + /* + * When request handler returns, the response pdu will get automatically + * sent, unless the pdu code is not updated and this is a NON or TCP based + * request. + */ + +} +---- + +SEE ALSO +-------- +*coap_block*(3), *coap_observe*(3), *coap_pdu_access*(3) and *coap_resource*(3) + +FURTHER INFORMATION +------------------- +See + +"RFC7252: The Constrained Application Protocol (CoAP)" + +"RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP)" + +"RFC9175: CoAP: Echo, Request-Tag, and Token Processing" + +for further information. + +See https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#option-numbers +for the current set of defined CoAP Options. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_recovery.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_recovery.txt.in new file mode 100644 index 000000000..d81a08fdb --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_recovery.txt.in @@ -0,0 +1,216 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_recovery(3) +================= +:doctype: manpage +:man source: coap_recovery +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_recovery, +coap_session_set_ack_random_factor, +coap_session_get_ack_random_factor, +coap_session_set_ack_timeout, +coap_session_get_ack_timeout, +coap_session_set_default_leisure, +coap_session_get_default_leisure, +coap_session_set_max_retransmit, +coap_session_get_max_retransmit, +coap_session_set_nstart, +coap_session_get_nstart, +coap_session_set_probing_wait, +coap_session_get_probing_wait, +coap_debug_set_packet_loss +- Work with CoAP packet transmissions + +SYNOPSIS +-------- +*#include * + +*void coap_session_set_ack_random_factor(coap_session_t *_session_, +coap_fixed_point_t _value_)*; + +*coap_fixed_point_t coap_session_get_ack_random_factor( +const coap_session_t *_session_)*; + +*void coap_session_set_ack_timeout(coap_session_t *_session_, +coap_fixed_point_t _value_)*; + +*coap_fixed_point_t coap_session_get_ack_timeout( +const coap_session_t *_session_)*; + +*void coap_session_set_default_leisure(coap_session_t *_session_, +coap_fixed_point_t _value_)*; + +*coap_fixed_point_t coap_session_get_default_leisure( +const coap_session_t *_session_)*; + +*void coap_session_set_max_retransmit(coap_session_t *_session_, +uint16_t _value_)*; + +*uint16_t coap_session_get_max_retransmit(const coap_session_t *_session_)*; + +*void coap_session_set_nstart(coap_session_t *_session_, uint16_t _value_)*; + +*uint16_t coap_session_get_nstart(const coap_session_t *_session_)*; + +*void coap_session_set_probing_rate(coap_session_t *_session_, +uint32_t _value_)*; + +*uint32_t coap_session_get_probing_rate(const coap_session_t *_session_)*; + +*int coap_debug_set_packet_loss(const char *_loss_level_)*; + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +For CoAP Confirmable messages, it is possible to define the retry counts, +repeat rate etc. for error recovery. Further information can be found in +"RFC7272: 4.2. Messages Transmitted Reliably", with the default values +defined in "RFC7272: 4.8 Transmission Parameters". + +It is not recommended that the suggested default setting are changed, but +there may be some special requirements that need different values and the +consequences of changing these values is fully understood. + +Some of the parameters or return values are in fixed point format as defined +by the coap_fixed_point_t structure as below +---- +typedef struct coap_fixed_point_t { + uint16_t integer_part; /* Integer part of fixed point variable */ + uint16_t fractional_part; /* Fractional part of fixed point variable + 1/1000 (3 points) precision */ +} coap_fixed_point_t; +---- + +The CoAP message retry rules are (with the default values to compute the time) +---- +1st retransmit after 1 * ack_timeout * ack_random factor (3 seconds) +2nd retransmit after 2 * ack_timeout * ack_random factor (6 seconds) +3rd retransmit after 3 * ack_timeout * ack_random factor (12 seconds) +4th retransmit after 4 * ack_timeout * ack_random factor (24 seconds) +5th retransmit after 5 * ack_timeout * ack_random factor (48 seconds) + +As max_retransmit (by default) is 4, then the 5th retransmit does not get sent, +but at that point COAP_NACK_TOO_MANY_RETRIES gets raised in the nack_handler +(if defined). Note that the sum of the seconds is 93 matching RFC7252. +---- + +It should be noted that these retries are separate from the DTLS or TLS +encrypted session setup retry timeouts. For DTLS, the initial requesting +packet will get sent max_retransmit times before reporting failure. +For TLS the initial TCP connection will timeout before reporting failure. + +It is also possible to set up packet losses, for both confirmable, and +non-confirmable messages. This can be used for stress testing packet +transmission recovery as well as application handling of lossy networks. + +The following functions reflect the RFC7252 uppercase names in lowercase +following the coap_session[sg]_ function prefix. + +The *coap_session_set_ack_random_factor*() function updates the _session_ ack +random wait factor, used to randomize re-transmissions, with the new _value_. +The default value is 1.5. + +The *coap_session_get_ack_random_factor*() function returns the current +_session_ ack random wait factor. + +The *coap_session_set_ack_timeout*() function updates the _session_ initial +ack or response timeout with the new _value_. The default value is 2.0. + +The *coap_session_get_ack_timeout*() function returns the current _session_ +initial ack or response timeout. + +The *coap_session_set_default_leisure*() function updates the _session_ +default leisure time with the new _value_. The initial default value is 5.0. + +The *coap_session_get_default_leisure*() function returns the current _session_ +default leisure time. + +The *coap_session_set_max_retransmit*() function updates the _session_ maximum +retransmit count with the new _value_. The default value is 4. + +The *coap_session_get_max_retransmit*() function returns the current _session_ +maximum retransmit count. + +The *coap_session_set_nstart*() function updates the _session_ nstart +with the new _value_. The default value is 1. + +The *coap_session_get_nstart*() function returns the current _session_ +nstart value. + +The *coap_session_set_probing_rate*() function updates the _session_ probing +rate with the new _value_. The default value is 1 byte per second. + +The *coap_session_get_probing_rate*() function returns the current _session_ +probing rate value. + +The *coap_debug_set_packet_loss*() function is uses to set the packet loss +levels as defined in _loss_level_. _loss_level_ can be set as a percentage +from "0%" to "100%". +Alternatively, it is possible to specify which packets of a packet sequence +are dropped. A definition of "1,5-9,11-20,101" means that packets 1, 5 +through 9, 11 through 20 and 101 will get dropped. A maximum of 10 different +packet sets is supported. The packet count is reset to 0 when +coap_debug_set_packet_loss() is called. +To remove any packet losses, set the _loss_level_ to "0%". + +RETURN VALUES +------------- +*coap_session_get_ack_random_factor*(), *coap_session_get_ack_timeout*(), +*coap_session_get_default_leisure*(), *coap_session_get_max_retransmit*(), +*coap_session_get_nstart*() and *coap_session_get_probing_rate*() return their +respective current values. + +*coap_debug_set_packet_loss*() returns 0 if _loss_level_ does not parse +correctly, otherwise 1 if successful. + +TESTING +------- + +The libcoap recovery/re-transmit logic will only work for confirmable requests. + +To see what is happening (other than by sniffing the network traffic), the +logging level needs to be set to LOG_DEBUG in the client by using +coap_set_log_level(LOG_DEBUG) and coap_dtls_set_log_level(LOG_DEBUG). + +The client needs to be sending confirmable requests during the test. + +The server can either be stopped, or if packet loss levels are set to 100% by +using coap_debug_set_packet_loss("100%") when receiving the client requests. + +*NOTE:* If the server end of the connection is returning ICMP unreachable +packets after being turned off, you will get a debug message of the form +"coap_network_read: unreachable", so libcoap will stop doing the retries. If +this is the case, then you need to make use of (on the server) +coap_debug_set_packet_loss("100%") or put in some packet filtering to drop the +packets. + +The client should then restart transmitting the requests based on the +ack_timeout, ack_random_factor and max_retransmit values. The client's +nack_handler will get called with COAP_NACK_TOO_MANY_RETRIES when the +confirmable request cannot be successfully transmitted. + + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_resource.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_resource.txt.in new file mode 100644 index 000000000..d37f47ee3 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_resource.txt.in @@ -0,0 +1,584 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_resource(3) +================= +:doctype: manpage +:man source: coap_resource +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_resource, +coap_resource_init, +coap_resource_unknown_init, +coap_resource_unknown_init2, +coap_resource_proxy_uri_init, +coap_resource_proxy_uri_init2, +coap_add_resource, +coap_delete_resource, +coap_resource_set_mode, +coap_resource_set_userdata, +coap_resource_get_userdata, +coap_resource_release_userdata_handler, +coap_resource_get_uri_path +- Work with CoAP resources + +SYNOPSIS +-------- +*#include * + +*coap_resource_t *coap_resource_init(coap_str_const_t *_uri_path_, +int _flags_);* + +*coap_resource_t *coap_resource_unknown_init(coap_method_handler_t +_put_handler_);* + +*coap_resource_t *coap_resource_unknown_init2(coap_method_handler_t +_put_handler_, int _flags_);* + +*coap_resource_t *coap_resource_proxy_uri_init(coap_method_handler_t +_proxy_handler_, size_t _host_name_count_, const char *_host_name_list_[]);* + +*coap_resource_t *coap_resource_proxy_uri_init2(coap_method_handler_t +_proxy_handler_, size_t _host_name_count_, const char *_host_name_list_[], +int flags);* + +*void coap_add_resource(coap_context_t *_context_, +coap_resource_t *_resource_);* + +*int coap_delete_resource(coap_context_t *_context_, +coap_resource_t *_resource_);* + +*void coap_resource_set_mode(coap_resource_t *_resource_, int _mode_);* + +*void coap_resource_set_userdata(coap_resource_t *_resource_, void *_data_);* + +*void *coap_resource_get_userdata(coap_resource_t *_resource_);* + +*void coap_resource_release_userdata_handler(coap_context_t *_context_, +coap_resource_release_userdata_handler_t _callback_);* + +*coap_str_const_t *coap_resource_get_uri_path(coap_resource_t *_resource_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +CoAP Resources on a CoAP Server need to be created and updated etc. The URI in +the request packet defines the resource to work with, with possibly the Query +referring to a sub-resource. + +When resources are configured on the CoAP server, the URI to match against +in the request packet is specified. + +Callback Handlers are then added to the resource to handle the different +request methods. See *coap_register_request_handler*(3) for further information. + +Adding Attributes allows textual information to be added to the resource +which can then be reported back to any client doing a "GET .well-known/core" +request. See *coap_add_attr*(3) for further information. + +If an incoming packet request matches a resource's URI and Method, then +the appropriate callback resource handler is invoked to process the packet +which should then update a suitable response packet for returning back to the +requester. + +There is support for handling incoming packets where the URI is unknown (no +specific resource has been created). +This could, for example, happen when a PUT request is trying to create a new +resource. It is the responsibility of the unknown resource callback handler +to either create a new resource for the URI or just manage things separately. + +CoAP Observe (RFC 7641) is not supported for unknown resources, so a new +resource with GET handler must be created by the unknown resource callback +handle matching the URI which then can be Observable. + +There is support for handling incoming proxy based requests using the Proxy-Uri +or Proxy-Scheme options. + +FUNCTIONS +--------- + +*Function: coap_resource_init()* + +The *coap_resource_init*() function returns a newly created _resource_ of +type _coap_resource_t_ * . _uri_path_ specifies the uri string path to match +against. Normally there is no need for the leading '/' - e.g. just +"full/path/for/resource". _flags_ is used to define whether the +_resource_ is of type Confirmable Message or Non-Confirmable Message for +any "observe" responses. See *coap_observe*(3). +_flags_ can be one of the following definitions ored together. + +[horizontal] +*COAP_RESOURCE_FLAGS_NOTIFY_NON*:: +Set the notification message type to non-confirmable for any trigggered +"observe" responses with type set to confirmable every 5 packets as required by +RFC7641 section-4.5. + +*COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS*:: +Set the notification message type to always non-confirmable for any trigggered +"observe" responses. This should only be used if a upper layer protocol +requires it. + +*COAP_RESOURCE_FLAGS_NOTIFY_CON*:: +Set the notification message type to confirmable for any trigggered +"observe" responses. + +*COAP_RESOURCE_FLAGS_RELEASE_URI*:: +Free off the coap_str_const_t for _uri_path_ when the _resource_ is deleted. + +*NOTE:* The following flags are only tested against if +*coap_mcast_per_resource*() has been called. If *coap_mcast_per_resource*() +has not been called, then all resources have multicast support, libcoap adds +in random delays to the responses, and 4.xx / 5.xx responses are dropped. + +[horizontal] +*COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT*:: +This resource has support for multicast requests. + +*COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_DELAYS*:: +Disable libcoap library from adding in delays to multicast requests before +releasing the response back to the client. It is then the responsibility of +the app to delay the responses for multicast requests. See +https://datatracker.ietf.org/doc/html/rfc7252#section-8.2. However, the +pseudo resource for ".well-known/core" always has multicast support enabled. + +*COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_05*:: +Enable libcoap library suppression of 205 multicast responses that are empty +(overridden by RFC7969 No-Response option) for multicast requests. + +*COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_XX*:: +Enable libcoap library suppressing 2.xx multicast responses (overridden by +RFC7969 No-Response option) for multicast requests. + +*COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_SUPPRESS_4_XX*:: +Disable libcoap library suppressing 4.xx multicast responses (overridden by +RFC7969 No-Response option) for multicast requests. + +*COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_SUPPRESS_5_XX*:: +Disable libcoap library suppressing 5.xx multicast responses (overridden by +RFC7969 No-Response option) for multicast requests. + +*NOTE:* _uri_path_, if not 7 bit readable ASCII, binary bytes must be hex +encoded according to the rules defined in RFC3968 Section 2.1. + +*Function: coap_resource_unknown_init()* + +The *coap_resource_unknown_init*() function returns a newly created _resource_ +of type _coap_resource_t_ *. _put_handler_ is automatically added to the +_resource_ to handle PUT requests to resources that are unknown. Additional +handlers can be added to this resource if required. + +*Function: coap_resource_unknown_init2()* + +The *coap_resource_unknown_init2*() function returns a newly created _resource_ +of type _coap_resource_t_ *. _put_handler_ is automatically added to the +_resource_ to handle PUT requests to resources that are unknown. Additional +handlers can be added to this resource if required. _flags_ can be zero or +more COAP_RESOURCE_FLAGS MCAST definitions. + +*Function: coap_resource_proxy_uri_init()* + +The *coap_resource_proxy_uri_init*() function returns a newly created +_resource_ of type _coap_resource_t_ *. _proxy_handler_ is automatically added +to the _resource_ to handle PUT/POST/GET etc. requests that use the Proxy-Uri +option. There is no need to add explicit request type handlers. One or more +names by which the proxy is known by (IP address, DNS name etc.) must be +supplied in the array defined by _host_name_list_[] which has a count of +_host_name_count_. This is used to check whether the current endpoint is +the proxy target address, or the request has to be passed on to an upstream +server. + +*Function: coap_resource_proxy_uri_init2()* + +The *coap_resource_proxy_uri_init2*() function returns a newly created +_resource_ of type _coap_resource_t_ *. _proxy_handler_ is automatically added +to the _resource_ to handle PUT/POST/GET etc. requests that use the Proxy-Uri +option. There is no need to add explicit request type handlers. One or more +names by which the proxy is known by (IP address, DNS name etc.) must be +supplied in the array defined by _host_name_list_[] which has a count of +_host_name_count_. This is used to check whether the current endpoint is +the proxy target address, or the request has to be passed on to an upstream +server. _flags_ can be zero or more COAP_RESOURCE_FLAGS MCAST definitions. + +*Function: coap_add_resource()* + +The *coap_add_resource*() function registers the given _resource_ with the +_context_. The _resource_ must have been created by *coap_resource_init*(), +*coap_resource_unknown_init*(), *coap_resource_unknown_init2*(), +*coap_resource_proxy_uri_init*() or *coap_resource_proxy_uri_init2*(). The +storage allocated for the _resource_ will be released by +*coap_delete_resource*(). + +As the _uri_path_ of the resource has to be unique across all of the resources +associated with a _context_, *coap_add_resource*() will delete any previous +_resource_ with the same _uri_path_ before adding in the new _resource_. + +*Function: coap_delete_resource()* + +The *coap_delete_resource*() function deletes a resource identified by +_resource_. The _context_ parameter is ignored. The storage allocated for that +_resource_ is freed, along with any attributes associated with the _resource_. + +*Function: coap_resource_set_mode()* + +The *coap_resource_set_mode*() changes the notification message type of +_resource_ to the given _mode_ which must be one of +COAP_RESOURCE_FLAGS_NOTIFY_NON, COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS or +COAP_RESOURCE_FLAGS_NOTIFY_CON. + +*Function: coap_resource_set_userdata()* + +The *coap_resource_set_userdata*() function allows a pointer to user _data_ +to be associated with a _resource_ that can accessed in any callback that +includes _resource_ as a parameter. + +*NOTE:* _data_ must point to a static, or allocated, block of memory. + +*Function: coap_resource_get_userdata()* + +The *coap_resource_get_userdata*() function obtains the user data pointer +from the _resource_ that had previously been set up by +*coap_resource_set_userdata*(). + +*Function: coap_resource_release_userdata_handler()* + +The *coap_resource_release_userdata_handler*() function defines the _context_ +wide _callback_ handler to call to release the allocated user data that has +been added to the resource using *coap_resource_set_userdata*() when the +resource is deleted. _callback_ can be NULL (which is the default) if nothing +needs to be freed off. + +*Function: coap_resource_get_uri_path()* + +The *coap_resource_get_uri_path*() function is used to obtain the UriPath of +the _resource_ definion. + +RETURN VALUES +------------- +The *coap_resource_init*(), *coap_resource_unknown_init*(), +*coap_resource_unknown_init2*(), *coap_resource_proxy_uri_init*() and +*coap_resource_proxy_uri_init2*() functions return a newly created resource +or NULL if there is a malloc failure. + +The *coap_delete_resource*() function return 0 on failure (_resource_ not +found), 1 on success. + +The *coap_resource_get_userdata*() function returns the value previously set +by the *coap_resource_set_userdata*() function or NULL. + +The *coap_resource_get_uri_path*() function returns the uri_path or NULL if +there was a failure. + +EXAMPLES +-------- +*Fixed Resources Set Up* + +[source, c] +---- +#include + +#define INDEX "This is an example server using libcoap\n" + +static void +hnd_get_index(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + unsigned char buf[3]; + /* Remove (void) definition if variable is used */ + (void)resource; + (void)session; + (void)request; + (void)query; + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + + coap_add_option(response, + COAP_OPTION_CONTENT_TYPE, + coap_encode_var_safe(buf, sizeof(buf), + COAP_MEDIATYPE_TEXT_PLAIN), + buf); + + coap_add_option(response, + COAP_OPTION_MAXAGE, + coap_encode_var_safe(buf, sizeof(buf), 0x2ffff), buf); + + coap_add_data(response, strlen(INDEX), (const uint8_t *)INDEX); + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); +} + +static void +hnd_delete_time(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + /* Remove (void) definition if variable is used */ + (void)resource; + (void)session; + (void)request; + (void)query; + + /* .. code .. */ + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); +} + +static void +hnd_get_time(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + /* Remove (void) definition if variable is used */ + (void)resource; + (void)session; + (void)request; + (void)query; + (void)response; + + /* .. code .. */ + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); +} + +static void +hnd_put_time(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + /* Remove (void) definition if variable is used */ + (void)resource; + (void)session; + (void)request; + (void)query; + (void)response; + + /* .. code .. */ + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); +} + +static void +init_resources(coap_context_t *ctx) { + + coap_resource_t *r; + + /* Create a resource to return general information */ + r = coap_resource_init(NULL, 0); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_index); + + /* Document resource for '.well-known/core' request */ + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), + coap_make_str_const("\"General Info\""), 0); + + coap_add_resource(ctx, r); + + /* Create a resource to return return or update time */ + r = coap_resource_init(coap_make_str_const("time"), + COAP_RESOURCE_FLAGS_NOTIFY_CON); + coap_resource_set_get_observable(r, 1); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_time); + coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_time); + coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_time); + + /* Document resource for 'time' request */ + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), + coap_make_str_const("\"Internal Clock\""), 0); + coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"secs\""), + 0); + coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""), + 0); + + coap_add_resource(ctx, r); + +} +---- + +*Dynamic Resources Set Up* + +[source, c] +---- +#include + +/* Regular DELETE handler - used by resources created by the + * Unknown Resource PUT handler */ + +static void +hnd_delete(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + /* Remove (void) definition if variable is used */ + (void)session; + (void)request; + (void)query; + (void)response; + + /* .. code .. */ + + /* Dynamic resource no longer required - delete it */ + coap_delete_resource(NULL, resource); + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); +} + +/* Regular GET handler - used by resources created by the + * Unknown Resource PUT handler */ + +static void +hnd_get(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + + coap_str_const_t *get_uri_path; + + /* Remove (void) definition if variable is used */ + (void)resource; + (void)session; + (void)request; + (void)query; + + /* + * Get the specific resouce being requested to determine what the response is + * The uri_path string is a const pointer + */ + + get_uri_path = coap_resource_get_uri_path(resource); + + /* .. code .. */ + + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); +} + +/* Regular PUT handler - used by resources created by the + * Unknown Resource PUT handler */ + +static void +hnd_put(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + /* Remove (void) definition if variable is used */ + (void)resource; + (void)session; + (void)query; + + coap_string_t *put_uri_path; + size_t length; + const uint8_t *data; + size_t offset; + size_t total; + int new_resource = 0; + + /* get the uri_path */ + put_uri_path = coap_get_uri_path(request); + if (!put_uri_path) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + coap_get_data_large(request, &length, &data, &offset, &total); + + /* .. code .. */ + + /* Need to do this as coap_get_uri_path() created it */ + coap_delete_string(put_uri_path); + + if (length + offset < total) + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTINUE); + else if (new_resource) + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); + else + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); +} + +static int +check_url_fn(coap_string_t *uri_path, uint8_t code) { + /* Remove (void) definition if variable is used */ + (void)uri_path; + (void)code; + + /* Code to determine whether the uri is valid or not */ + + return 1; +} + +/* Unknown Resource PUT handler */ + +static void +hnd_put_unknown(coap_resource_t *resource, coap_session_t *session, +const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { + /* Remove (void) definition if variable is used */ + (void)resource; + coap_pdu_code_t req_code = coap_pdu_get_code(request); + + coap_resource_t *r; + coap_string_t *uri_path; + + /* get the uri_path - which will get used by coap_resource_init() */ + uri_path = coap_get_uri_path(request); + if (!uri_path) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + return; + } + + /* Check if new URI Path is valid */ + if (!check_url_fn (uri_path, req_code)) { + coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); + coap_delete_string(uri_path); + return; + } + + /* + * Create a resource to handle the new URI + * uri_path will get deleted when the resource is removed + */ + r = coap_resource_init((coap_str_const_t*)uri_path, + COAP_RESOURCE_FLAGS_RELEASE_URI | COAP_RESOURCE_FLAGS_NOTIFY_NON); + coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put); + coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete); + /* We possibly want to Observe the GETs */ + coap_resource_set_get_observable(r, 1); + coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get); + coap_add_resource(coap_session_get_context(session), r); + + /* Do the PUT for this first call */ + hnd_put(r, session, request, query, response); + + return; + +} + +/* Initialize single Unknown Resource PUT handler */ + +static void +init_resources(coap_context_t *ctx) { + + coap_resource_t *r; + + /* Create a resource to handle PUTs to unknown URIs */ + r = coap_resource_unknown_init2(hnd_put_unknown, 0); + /* + * Additional handlers can be added - for example + * coap_register_request_handler(r, COAP_REQUEST_POST, hnd_post_unknown); + * coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_unknown); + * coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_delete_unknown); + */ + coap_add_resource(ctx, r); + +} +---- + +SEE ALSO +-------- +*coap_attribute*(3), *coap_context*(3), *coap_handler*(3) and *coap_observe*(3) + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_session.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_session.txt.in new file mode 100644 index 000000000..8e66a7192 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_session.txt.in @@ -0,0 +1,238 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_session(3) +=============== +:doctype: manpage +:man source: coap_session +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_session, +coap_session_reference, +coap_session_release, +coap_session_disconnected, +coap_session_set_type_client, +coap_session_set_app_data, +coap_session_get_app_data, +coap_session_get_addr_local, +coap_session_get_addr_remote, +coap_session_get_context, +coap_session_get_ifindex, +coap_session_get_proto, +coap_session_get_state, +coap_session_get_tls, +coap_session_get_type, +coap_session_get_psk_hint, +coap_session_get_psk_key +- Work with CoAP sessions + +SYNOPSIS +-------- +*#include * + +*coap_session_t *coap_session_reference(coap_session_t *_session_);* + +*void coap_session_release(coap_session_t *_session_);* + +*void coap_session_disconnected(coap_session_t *_session_, coap_nack_reason_t _reason_);* + +*int coap_session_set_type_client(coap_session_t *_session_);* + +*void coap_session_set_app_data(coap_session_t *_session_, void *_data_);* + +*void *coap_session_get_app_data(const coap_session_t *_session_);* + +*const coap_address_t *coap_session_get_addr_local( +const coap_session_t *_session_);* + +*const coap_address_t *coap_session_get_addr_remote( +const coap_session_t *_session_);* + +*coap_context_t *coap_session_get_context(const coap_session_t *_session_);* + +*int coap_session_get_ifindex(const coap_session_t *_session_);* + +*coap_proto_t coap_session_get_proto(const coap_session_t *_session_);* + +*coap_session_state_t coap_session_get_state(const coap_session_t *_session_);* + +*void *coap_session_get_tls(const coap_session_t *_session_, +coap_tls_library_t *tls_lib);* + +*coap_session_type_t coap_session_get_type(const coap_session_t *_session_);* + +*const coap_bin_const_t *coap_session_get_psk_hint( +const coap_session_t *_session_);* + +*const coap_bin_const_t *coap_session_get_psk_key( +const coap_session_t *_session_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +This man page focuses on the CoAP Session and how to update or get information +from the opaque coap_session_t structure. + +A CoAP Session maintains the state of an ongoing connection between a Client +and Server which is stored in a coap_session_t Session object. A CoAP session +is tracked by local port, CoAP protocol, remote IP address and remote port. + +The Session network traffic can be encrypted or un-encrypted if there is an +underlying TLS library. + +The *coap_session_reference*() function is used to increment the reference +count of the _session_. Incrementing the reference count by an application +means that the library will not inadvertently remove the session when it has +finished processing the session. + +The *coap_session_release*() function is be used to decrement the _session_ +reference count, which when it gets to 0, will:- + +If type Client, free off the session which then clears all entries from the +receive queue and send queue. *NOTE:* All client sessions start off with a +reference count of 1. + +If type Server, then the _session_ is added to an idle pool ready for subsequent +re-use. If the Server _session_ is not used for 5 minutes, then it will get +completely freed off. *NOTE:* Unless the application increments the +reference count, this is the case for all type server sessions as they start +with a reference count of 0. + +The *coap_session_disconnected*() function is used to force the closure of a +_session_ for the reason _reason_. It will cause any outstanding traffic to +get dropped. + +The *coap_session_set_type_client*() function is used to convert the _session_ +frrm a session endpoint type of Server to Client. This typically is used in a +Call-Home type environment where the roles have to change following the +establishment of a session. The reference count is incremented by 1. + +The *coap_session_set_app_data*() function is used to define a _data_ pointer +for the _session_ which can then be retrieved at a later date. + +The *coap_session_get_app_data*() function is used to retrieve the data +pointer previously defined by *coap_session_set_app_data*(). + +The *coap_session_get_addr_local*() function is used to get the local IP +address and port information from the _session_. + +The *coap_session_get_addr_remote*() function is used to get the remote (peer) +IP address and port information from the _session_. + +The *coap_session_get_context*() function is used to get the CoAP context +associated with the _session_. + +The *coap_session_get_ifindex*() function is used to get the network interface +index that the traffic came in over from the _session_. + +[source, c] +---- +COAP_PROTO_UDP +COAP_PROTO_DTLS +COAP_PROTO_TCP +COAP_PROTO_TLS +---- + +The *coap_session_get_proto*() function is used to get the CoAP protocol from +the _session_. + +[source, c] +---- +COAP_SESSION_STATE_NONE +COAP_SESSION_STATE_CONNECTING +COAP_SESSION_STATE_HANDSHAKE +COAP_SESSION_STATE_CSM +COAP_SESSION_STATE_ESTABLISHED +---- + +The *coap_session_get_state*() function is used to get the current state +of the _session_. + +[source, c] +---- +OpenSSL: SSL* +GnuTLS: gnutls_session_t (implicit *) +Mbed TLS: mbedtls_ssl_context* +TinyDTLS: struct dtls_context* +---- + +The *coap_session_get_tls*() function is used to get the pointer to the TLS +information from the _session_. This is TLS library specific. _tls_lib_ is +updated with the underlying (D)TLS library type. + +[source, c] +---- +COAP_SESSION_TYPE_CLIENT +COAP_SESSION_TYPE_SERVER +COAP_SESSION_TYPE_HELLO /* Negotiating a (D)TLS session */ +---- + +The *coap_session_get_type*() function is used to get the session type from the +_session_. + +The *coap_session_get_psk_hint*() function is used to get the current server +_session_'s pre-shared-key identity hint. + +The *coap_session_get_psk_key*() function is used to get the current +_session_'s pre-shared-key key information. + +RETURN VALUES +------------- + +*coap_session_reference*() function returns a pointer to the session. + +*coap_session_set_type_client*() function returns 1 on success, otherwise 0. + +*coap_session_get_app_data*() function return a previously defined pointer. + +*coap_session_get_addr_local*() and *coap_session_get_addr_remote*() return +a pointer to the IP address / port or NULL on error. + +*coap_session_get_context*() returns a pointer to the current CoAP Context or +NULL on error. + +*coap_session_get_ifindex*() returns the network interface the traffic last +came in over, or -1 on error. + +*coap_session_get_proto*() returns the current session's protocol or 0 on error. + +*coap_session_get_state*() returns the current session's state or 0 on error. + +*coap_session_get_tls*() returns a pointer to the current session's TLS +information (TLS library dependent) or NULL if there is none or there is an +error. + +*coap_session_get_type*() returns the current session's type or 0 on error. + +*coap_session_get_psk_hint*() returns the current server session's +pre-shared-key identity hint, or NULL if not defined. + +*coap_session_get_psk_key*() returns the current session's pre-shared-key +key information, or NULL if not defined. + +SEE ALSO +-------- +*coap_context*(3), *coap_endpoint_client*(3) and *coap_endpoint_server*(3) + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_string.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_string.txt.in new file mode 100644 index 000000000..ad349db76 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_string.txt.in @@ -0,0 +1,182 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_string(3) +============== +:doctype: manpage +:man source: coap_string +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_string, +coap_new_string, +coap_delete_string, +coap_new_str_const, +coap_delete_str_const, +coap_new_binary, +coap_delete_binary, +coap_resize_binary, +coap_new_bin_const, +coap_delete_bin_const, +coap_make_str_const, +coap_string_equal, +coap_binary_equal +- Work with CoAP string functions + +SYNOPSIS +-------- +*#include * + +*coap_string_t *coap_new_string(size_t _size_);* + +*void coap_delete_string(coap_string_t *_string_);* + +*coap_str_const_t *coap_new_str_const(const uint8_t *_data_, size_t _size_);* + +*void coap_delete_str_const(coap_str_const_t *_string_);* + +*coap_str_const_t *coap_make_str_const(const char *_string_);* + +*int coap_string_equal(coap_string_t *_string1_, coap_string_t *_string2_);* + +*coap_binary_t *coap_new_binary(size_t _size_);* + +*void coap_delete_binary(coap_binary_t *_binary_);* + +*coap_binary_t *coap_resize_binary(coap_binary_t *_binary_, size_t _new_size_);* + +*coap_bin_const_t *coap_new_bin_const(const uint8_t *_data_, size_t _size_);* + +*void coap_delete_bin_const(coap_bin_const_t *_binary_);* + +*int coap_binary_equal(coap_binary_t *_binary1_, coap_binary_t *_binary2_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +There is support for storing strings (usually readable data) and for storing +binary data. These are used by a number of functions and provide the +information in some of the callbacks. + +There are 4 supported string/binary types as follows + +[source, c] +---- +/* + * Coap string data definition + */ +typedef struct coap_string_t { + size_t length; /* length of string */ + uint8_t *s; /* string data */ +} coap_string_t; + +/* + * Coap string data definition with const data + */ +typedef struct coap_str_const_t { + size_t length; /* length of string */ + const uint8_t *s; /* read-only string data */ +} coap_str_const_t; + +/* + * Coap binary data definition + */ +typedef struct coap_binary_t { + size_t length; /* length of binary data */ + uint8_t *s; /* binary data */ +} coap_binary_t; + +/* + * Coap binary data definition with const data + */ +typedef struct coap_bin_const_t { + size_t length; /* length of binary data */ + const uint8_t *s; /* read-only binary data */ +} coap_bin_const_t; +---- + +The *coap_new_string*() function allocates a new coap_string_t of _size_ +where _s_ points to uninitialized data of length _size_ with an extra trailing +NULL at _size_ + 1. _length_ is set to _size_. + +The *coap_delete_string*() function is used to delete the coap_string_t +created by *coap_new_string*(). + +The *coap_new_str_const*() function allocates a coap_str_const_t of _size_ +where _s_ is filled in with _data_ and has a trailing NULL added. +_length_ is set to _size_. _s_ is read-only. + +The *coap_delete_str_const*() function is used to delete the coap_str_const_t +created by *coap_new_str_const*(). + +The *coap_make_str_const*() function is used to take some read-only text and +uses a static coap_str_const_t for use in different function calls. There are +two static entries that are cycled through so that a single function call can +call *coap_make_str_const*() twice. + +The *coap_string_equal*() function is used to compare two different string +objects _string1_ and _string2_. + +The *coap_new_binary*() function allocates a new coap_binary_t of _size_ +where _s_ points to uninitialized data of length _size_. _length_ is set +to _size_. + +The *coap_resize_binary*() function is used resize the size of _s_ to the new +size of _new_size_. The data between the old _length_ and the _new_size_ is +unitialized. _length_ is set to _new_size_. + +The *coap_delete_binary*() function is used to delete the coap_binary_t +created by *coap_new_binary*(). + +The *coap_new_bin_const*() function allocates a coap_bin_const_t of _size_ +where _s_ is filled in with in with _data_ and has a trailing NULL added. +_length_ is set to _size_. _s_ is read-only. + +The *coap_delete_bin_const*() function is used to delete the coap_bin_const_t +created by *coap_new_bin_const*(). + +The *coap_binary_equal*() function is used to compare two different binary +objects _binary1_ and _binary2_. + +RETURN VALUES +------------- +The *coap_new_string*() function returns a pointer to an allocated +coap_string_t or NULL if there was a failure. + +The *coap_new_str_const*() function returns a pointer to an allocated +coap_str_const_t or NULL if there was a failure. + +The *coap_new_binary*() function returns a pointer to an allocated +coap_binary_t or NULL if there was a failure. + +The *coap_resize_binary*() function returns a pointer to an re-allocated +coap_binary_t or NULL if there was a failure. + +The *coap_new_bin_const*() function returns a pointer to an allocated +coap_bin_const_t or NULL if there was a failure. + +SEE ALSO +-------- +*coap_attribute*(3), *coap_context*(3), *coap_handler*(3), *coap_pdu_setup*(3) +and *coap_resource*(3) + +FURTHER INFORMATION +------------------- +"RFC7252: The Constrained Application Protocol (CoAP)" + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/coap_tls_library.txt.in b/examples/espidf-coap-server/components/libcoap/man/coap_tls_library.txt.in new file mode 100644 index 000000000..ce3deeacd --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/coap_tls_library.txt.in @@ -0,0 +1,153 @@ +// -*- mode:doc; -*- +// vim: set syntax=asciidoc,tw=0: + +coap_tls_library(3) +=================== +:doctype: manpage +:man source: coap_tls_library +:man version: @PACKAGE_VERSION@ +:man manual: libcoap Manual + +NAME +---- +coap_tls_library, +coap_dtls_is_supported, +coap_tls_is_supported, +coap_tcp_is_supported, +coap_get_tls_library_version, +coap_string_tls_support, +coap_string_tls_version, +coap_show_tls_version +- Work with CoAP TLS libraries + +SYNOPSIS +-------- +*#include * + +*int coap_dtls_is_supported(void);* + +*int coap_tls_is_supported(void);* + +*int coap_tcp_is_supported(void);* + +*coap_tls_version_t *coap_get_tls_library_version(void);* + +*char *coap_string_tls_support(char *_buffer_, size_t _bufsize_);* + +*char *coap_string_tls_version(char *_buffer_, size_t _bufsize_);* + +*void coap_show_tls_version(coap_log_t _level_);* + +For specific (D)TLS library support, link with +*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, +*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* +or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with +*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. + +DESCRIPTION +----------- +When the libcoap library was built, it will have been compiled using a +specific TLS implementation type (e.g. OpenSSL, GnuTLS, Mbed TLS, TinyDTLS or +noTLS). +When the libcoap library is linked into an application, it is possible that +the application needs to dynamically determine whether DTLS or TLS is +supported, what type of TLS implementation libcoap was compiled with, as well +as detect what is the version of the currently loaded TLS library is. + +*NOTE:* If OpenSSL is being used, then the minimum OpenSSL library version is +1.1.0. + +*NOTE:* If GnuTLS is being used, then the minimum GnuTLS library version is +3.3.0. + +*NOTE:* If GnuTLS is going to interoperate with TinyDTLS, then a minimum +revision of GnuTLS 3.5.5 which supports CCM algorithms is required +by TinyDTLS as TinyDTLS currently only supports CCM. + +Network traffic can be encrypted or un-encrypted with libcoap - how to set +this up is described in *coap_context*(3). + +Due to the nature of TLS, there can be Callbacks that are invoked as the TLS +session negotiates encryption algorithms, encryption keys etc. +Where possible, by default, the CoAP layer handles all this automatically. +However, there is the flexibility of the Callbacks for imposing additional +security checks etc. when PKI is being used. These callbacks need to need to +match the TLS implementation type. + +The *coap_dtls_is_supported*() function returns 1 if support for DTLS is +enabled, otherwise 0; + +The *coap_tls_is_supported*() function returns 1 if support for TLS is +enabled, otherwise 0; + +The *coap_tcp_is_supported*() function returns 1 if support for TCP is +enabled, otherwise 0. + +The *coap_get_tls_library_version*() function returns the TLS implementation +type and library version in a coap_tls_version_t* structure. + +The *coap_string_tls_support*() function is used to update the provided buffer +with ascii readable information about what type of PSK, PKI etc. keys the +current (D)TLS library supports. +_buffer_ defines the buffer to provide the information and _bufsize_ is the +size of _buffer_. + +The *coap_string_tls_version*() function is used to update the provided buffer +with information about the current (D)TLS library that libcoap was built +against, as well as the current linked version of the (D)TLS library. +_buffer_ defines the buffer to provide the information and _bufsize_ is the +size of _buffer_. + +The *coap_show_tls_version*() function is used log information about the +current (D)TLS library that libcoap was built against, as well as the current +linked version of the (D)TLS library. _level_ defines the minimum logging level +for this information to be output using coap_log(). + +[source, c] +---- +typedef enum coap_tls_library_t { + COAP_TLS_LIBRARY_NOTLS = 0, /* No DTLS library */ + COAP_TLS_LIBRARY_TINYDTLS, /* Using TinyDTLS library */ + COAP_TLS_LIBRARY_OPENSSL, /* Using OpenSSL library */ + COAP_TLS_LIBRARY_GNUTLS, /* Using GnuTLS library */ + COAP_TLS_LIBRARY_MBEDTLS, /* Using Mbed TLS library */ +} coap_tls_library_t; + +typedef struct coap_tls_version_t { + uint64_t version; /* (D)TLS runtime Library Version */ + coap_tls_library_t type; /* Library type. One of COAP_TLS_LIBRARY_* */ + uint64_t built_version; /* (D)TLS Built against Library Version */ +} +---- + +RETURN VALUES +------------- +*coap_dtls_is_supported*() and *coap_tls_is_supported*() functions +return 0 if there is no support, 1 if support is available. + +*coap_get_tls_library_version*() function returns the TLS implementation type +and library version in a coap_tls_version_t* structure. + +The *coap_tcp_is_supported*() function returns 1 if support for TCP is +enabled, otherwise 0. + +*coap_string_tls_version*() function returns a pointer to the provided buffer. + +SEE ALSO +-------- +*coap_encryption*(3) + +FURTHER INFORMATION +------------------- +See "RFC7252: The Constrained Application Protocol (CoAP)" for further +information. + +BUGS +---- +Please report bugs on the mailing list for libcoap: +libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at +https://github.com/obgm/libcoap/issues + +AUTHORS +------- +The libcoap project diff --git a/examples/espidf-coap-server/components/libcoap/man/examples-code-check.c b/examples/espidf-coap-server/components/libcoap/man/examples-code-check.c new file mode 100644 index 000000000..6a55d5890 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/man/examples-code-check.c @@ -0,0 +1,437 @@ +/* +* examples_code_check.c -- Validate the code in EXAMPLES of the man pages +* +* Exits with a non-zero value if there is a coding error. +* +* Copyright (C) 2020 Jon Shallow +* +* SPDX-License-Identifier: BSD-2-Clause +* +* This file is part of the CoAP library libcoap. Please see README for terms +* of use. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#define GCC_OPTIONS "-I../include" +#else /* ! _WIN32 */ +#define GCC_OPTIONS "\ + -I../include \ + -std=c99 \ + -g \ + -O2 \ + -pedantic \ + -Wall \ + -Wcast-qual \ + -Wextra \ + -Wformat-security \ + -Winline \ + -Wmissing-declarations \ + -Wmissing-prototypes \ + -Wnested-externs \ + -Wpointer-arith \ + -Wshadow \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wswitch-enum \ + -Wunused \ + -Wwrite-strings \ + -Wno-unused-function \ + -Wno-unused-but-set-variable \ + -Werror \ + " +#endif /* ! _WIN32 */ + +const char *inline_list[] = { + "coap_malloc(", + "coap_free(", +}; + +const char *define_list[] = { + "coap_string_equal(", + "coap_binary_equal(", + "coap_log(", +}; + +const char *struct_list[] = { + "coap_fixed_point_t ", + "coap_string_t ", + "coap_str_const_t ", + "coap_binary_t ", + "coap_bin_const_t ", + "coap_opt_iterator_t ", + "coap_opt_t ", +}; + +const char *number_list[] = { + "coap_log_t ", + "coap_pdu_type_t ", + "coap_mid_t ", + "coap_pdu_code_t ", + "coap_proto_t ", + "coap_session_state_t ", + "coap_session_type_t ", + "int ", + "uint16_t ", + "uint32_t ", + "uint64_t ", + "unsigned int ", + "size_t ", + "const uint8_t ", +}; + +int exit_code = 0; + +static void check_synopsis(const char* file) { + char buffer[1024]; + char file_name[300]; + FILE *fpcode; + int status; + + snprintf(file_name, sizeof (file_name), "tmp/%s-header.c", file); + fpcode = fopen(file_name, "w"); + if (!fpcode) { + fprintf(stderr, "fopen: %s: %s (%d)\n", file_name, strerror(errno), errno); + exit_code = 1; + return; + } + fprintf(fpcode, "#include \n"); + fprintf(fpcode, "#ifdef __GNUC__\n"); + fprintf(fpcode, "#define U __attribute__ ((unused))\n"); + fprintf(fpcode, "#else /* not a GCC */\n"); + fprintf(fpcode, "#define U\n"); + fprintf(fpcode, "#endif /* GCC */\n"); + fprintf(fpcode, "\n"); + fprintf(fpcode, "#include \"%s.h\"\n", file); + fclose(fpcode); + file_name[strlen(file_name)-1] = '\000'; + snprintf (buffer, sizeof (buffer), + "gcc " GCC_OPTIONS " -c %sc -o %so", + file_name, file_name); + status = system(buffer); + if (WEXITSTATUS(status)) { + exit_code = WEXITSTATUS(status); + } + return; +} + +int main(int argc, char* argv[]) +{ + DIR *pdir; + struct dirent *pdir_ent; + char buffer[1024]; + int status; + + if (argc != 2) { + fprintf(stderr, "usage: %s man_directory\n", argv[0]); + exit (1); + } + + pdir = opendir(argv[1]); + if (pdir == NULL) { + fprintf(stderr, "opendir: %s: %s (%d)\n", argv[1], strerror(errno), errno); + exit(1); + } + if (chdir(argv[1]) == -1) { + fprintf(stderr, "chdir: %s: %s (%d)\n", argv[1], strerror(errno), errno); + exit(1); + } + if (mkdir("tmp", 0777) == -1 && errno != EEXIST) { + fprintf(stderr, "mkdir: %s: %s (%d)\n", "tmp", strerror(errno), errno); + exit(1); + } + + while ((pdir_ent = readdir (pdir)) != NULL) { + if (!strncmp(pdir_ent->d_name, "coap_", sizeof ("coap_")-1) && + strstr (pdir_ent->d_name, ".txt.in")) { + FILE* fp; + int skip = 1; + int in_examples = 0; + int in_synopsis = 0; + int count = 1; + char keep_line[1024] = {0}; + FILE* fpcode = NULL; + FILE* fpheader = NULL; + char file_name[300]; + int is_void_func = 0; + int is_number_func = 0; + int is_inline_func = 0; + int is_struct_func = 0; + char *func_start = NULL; + int is_struct = 0; + unsigned int i; + + fprintf(stderr, "Processing: %s\n", pdir_ent->d_name); + + snprintf(buffer, sizeof (buffer), "%s", pdir_ent->d_name); + fp = fopen(buffer, "r"); + if (fp == NULL) { + fprintf(stderr, "fopen: %s: %s (%d)\n", buffer, strerror(errno), errno); + continue; + } + while (fgets(buffer, sizeof (buffer), fp) != NULL) { + if (strncmp(buffer, "SYNOPSIS", sizeof("SYNOPSIS")-1) == 0) { + in_synopsis = 1; + snprintf(file_name, sizeof (file_name), "tmp/%s.h", + pdir_ent->d_name); + fpheader = fopen(file_name, "w"); + if (!fpheader) { + fprintf(stderr, "fopen: %s: %s (%d)\n", file_name, + strerror(errno), errno); + goto bad; + } + continue; + } + if (strncmp(buffer, "DESCRIPTION", sizeof("DESCRIPTION")-1) == 0) { + in_synopsis = 0; + if (fpheader) + fclose(fpheader); + fpheader = NULL; + check_synopsis(pdir_ent->d_name); + continue; + } + if (strncmp(buffer, "EXAMPLES", sizeof("EXAMPLES")-1) == 0) { + in_synopsis = 0; + in_examples = 1; + continue; + } + if (strncmp(buffer, "SEE ALSO", sizeof("SEE ALSO")-1) == 0) { + break; + } + if (in_synopsis) { + /* Working in SYNOPSIS section */ + size_t len; + char outbuf[1024]; + char *cp; + char *ecp; + + if (buffer[0] == '\n') + continue; + if (buffer[0] == '-') + continue; + if (buffer[0] == 'F') { + /* For specific ..... is the end */ + in_synopsis = 0; + if (fpheader) + fclose(fpheader); + fpheader = NULL; + check_synopsis(pdir_ent->d_name); + continue; + } + if (buffer[0] == '*' && buffer[1] == '#') + continue; + if (buffer[0] == '*') { + /* start of a new function */ + is_void_func = 0; + is_number_func = 0; + is_struct_func = 0; + is_inline_func = 0; + is_struct = 0; + func_start = NULL; + + if (strncmp(buffer, "*void ", sizeof("*void ")-1) == 0) { + if (strncmp(buffer, "*void *", sizeof("*void *")-1) == 0) { + func_start = &buffer[sizeof("*void *")-1]; + } + else { + is_void_func = 1; + func_start = &buffer[sizeof("*void ")-1]; + } + } + + for (i = 0; i < sizeof(number_list)/sizeof(number_list[0]); i++) { + if (strncmp(&buffer[1], number_list[i], + strlen(number_list[i])) == 0) { + if (buffer[1 + strlen(number_list[i])] == '*') { + func_start = &buffer[2 + strlen(number_list[i])]; + } + else { + is_number_func = 1; + func_start = &buffer[1 + strlen(number_list[i])]; + } + break; + } + } + + for (i = 0; i < sizeof(struct_list)/sizeof(struct_list[0]); i++) { + if (strncmp(&buffer[1], struct_list[i], + strlen(struct_list[i])) == 0) { + if (buffer[1 + strlen(struct_list[i])] == '*') { + func_start = &buffer[2 + strlen(struct_list[i])]; + } + else { + is_struct_func = i + 1; + func_start = &buffer[1 + strlen(struct_list[i])]; + } + break; + } + } + + if (strncmp(buffer, "*struct ", sizeof("*struct ")-1) == 0) { + is_struct = 1; + } + } + + if (func_start) { + /* see if COAP_STATIC_INLINE function */ + for (i = 0; i < sizeof(inline_list)/sizeof(inline_list[0]); i++) { + if (strncmp(func_start, inline_list[i], + strlen(inline_list[i])) == 0) { + is_inline_func = 1; + break; + } + } + /* see if #define function */ + for (i = 0; i < sizeof(define_list)/sizeof(define_list[0]); i++) { + if (strncmp(func_start, define_list[i], strlen(define_list[i])) == 0) { + break; + } + } + if (i != sizeof(define_list)/sizeof(define_list[0])) + continue; + } + + /* Need to include use of U for unused parameters just before comma */ + cp = buffer; + ecp = strchr(cp, ','); + if (!ecp) ecp = strchr(cp, ')'); + outbuf[0] = '\000'; + while (ecp) { + len = strlen(outbuf); + if (strncmp(cp, "void", ecp-cp) == 0) + snprintf(&outbuf[len], sizeof(outbuf)-len, "%*.*s%c", + (int)(ecp-cp), (int)(ecp-cp), cp, *ecp); + else + snprintf(&outbuf[len], sizeof(outbuf)-len, "%*.*s U%c", + (int)(ecp-cp), (int)(ecp-cp), cp, *ecp); + cp = ecp+1; + if(*cp) { + ecp = strchr(cp, ','); + if (!ecp) ecp = strchr(cp, ')'); + } + else { + ecp = NULL; + } + } + if (*cp) { + len = strlen(outbuf); + snprintf(&outbuf[len], sizeof(outbuf)-len, "%s", cp); + } + + len = strlen(outbuf); + if (len > 3 && ((outbuf[len-3] == ';' && outbuf[len-2] == '*') || + (outbuf[len-3] == '*' && outbuf[len-2] == ';'))) { + if (is_inline_func) { + strcpy(&outbuf[len-3], ";\n"); + } + /* Replace ;* or ;* with simple function definition */ + else if (is_void_func) { + strcpy(&outbuf[len-3], "{}\n"); + } + else if (is_number_func) { + strcpy(&outbuf[len-3], "{return 0;}\n"); + } + else if (is_struct_func) { + snprintf(&outbuf[len-3], sizeof(outbuf)-(len-3), + "{%s v; memset(&v, 0, sizeof(v)); return v;}\n", + struct_list[is_struct_func - 1]); + } + else if (is_struct) { + strcpy(&outbuf[len-3], ";\n"); + } + else { + strcpy(&outbuf[len-3], "{return NULL;}\n"); + } + } + if (outbuf[0] == '*') { + fprintf(fpheader, "%s", &outbuf[1]); + } + else { + fprintf(fpheader, "%s", outbuf); + } + continue; + } + + if (!in_examples) { + continue; + } + /* Working in EXAMPLES section */ + if (skip) { + if (!strcmp(buffer, "----\n") || !strcmp(buffer, "---\n") || + !strcmp(buffer, "--\n") || !strcmp(buffer, "-\n") || + !strcmp(buffer, "-----\n")) { + /* Found start of code */ + if (strcmp(buffer, "----\n")) { + fprintf(stderr, + "Unexpected start of code '%.*s' - expected ----\n", + (int)strlen(buffer)-1, buffer); + } + snprintf(file_name, sizeof (file_name), "tmp/%s-%d.c", + pdir_ent->d_name, count++); + fpcode = fopen(file_name, "w"); + if (!fpcode) { + fprintf(stderr, "fopen: %s: %s (%d)\n", file_name, + strerror(errno), errno); + goto bad; + } + else { + fprintf(fpcode, "/* %s */\n", keep_line); + } + skip = 0; + fprintf(stderr, "Processing: %s EXAMPLE - '%d'\n", + pdir_ent->d_name, + count-1); + } + else if (buffer[0] == '*') { + snprintf(keep_line, sizeof (keep_line), "%s", buffer); + } + continue; + } + if (!strcmp(buffer, "----\n") || !strcmp(buffer, "---\n") || + !strcmp(buffer, "--\n") || !strcmp(buffer, "-\n") || + !strcmp(buffer, "-----\n")) { + /* Found end of code */ + + skip = 1; + if (fpcode) fclose(fpcode); + keep_line[0] = '\000'; + file_name[strlen(file_name)-1] = '\000'; + snprintf (buffer, sizeof (buffer), + "gcc " GCC_OPTIONS " -c %sc -o %so", + file_name, file_name); + status = system(buffer); + if (WEXITSTATUS(status)) { + exit_code = WEXITSTATUS(status); + } + continue; + } + if (fpcode) { + if (strstr (buffer, "LIBCOAP_API_VERSION")) { + fprintf(fpcode, "#include \n"); + fprintf(fpcode, "#ifdef __GNUC__\n"); + fprintf(fpcode, "#define U __attribute__ ((unused))\n"); + fprintf(fpcode, "#else /* not a GCC */\n"); + fprintf(fpcode, "#define U\n"); + fprintf(fpcode, "#endif /* GCC */\n"); + fprintf(fpcode, "#include \"%s.h\"\n", pdir_ent->d_name); + fprintf(fpcode, "#undef U\n"); + continue; + } + fprintf(fpcode, "%s", buffer); + } + } +bad: + fclose(fp); + } + } + closedir (pdir); + exit(exit_code); +} diff --git a/examples/espidf-coap-server/components/libcoap/scripts/api-version-bump.sh b/examples/espidf-coap-server/components/libcoap/scripts/api-version-bump.sh new file mode 100644 index 000000000..d39e00287 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/scripts/api-version-bump.sh @@ -0,0 +1,60 @@ +#! /bin/bash + +if ! test -f configure.ac; then + >&2 echo "$(basename $0): script must be called from the package's top directory" + exit 1 +fi + +declare $(sed -ne '/^LIBCOAP_API_VERSION=[0-9]\+/{p; q}' configure.ac) +NEW_VERSION=${1:-$LIBCOAP_API_VERSION} + +if test "x$NEW_VERSION" = "x$LIBCOAP_API_VERSION"; then + >&2 echo "no version change requested, exiting (current version is $LIBCOAP_API_VERSION)" + exit 1 +fi + +echo $(basename $0): increase version $LIBCOAP_API_VERSION to $NEW_VERSION + +# command for move operations on version-controlled files and directories +MV="git mv" +move() { + source=$1 + dest=$2 + test -e "$1" && $MV "$1" "$2" +} + +move include/coap$LIBCOAP_API_VERSION include/coap$NEW_VERSION +move libcoap-$LIBCOAP_API_VERSION.pc.in libcoap-$NEW_VERSION.pc.in +move libcoap-$LIBCOAP_API_VERSION.map libcoap-$NEW_VERSION.map +move libcoap-$LIBCOAP_API_VERSION.sym libcoap-$NEW_VERSION.sym + +# sed pattern for include path prefix substitution +pat='\(#\s*include ["<]coap\)'$LIBCOAP_API_VERSION/ + +find \( -name \*.h -o -name \*.c \) \ + -exec grep -q "^$pat" {} \; -print | \ + (while read fn ; do test -f ${fn}.in || sed -i "s,^$pat,\1$NEW_VERSION/," $fn ; done ) + +# examples-code-check.c generates new files with include statements +sed -i "s,$pat,\1$NEW_VERSION/," man/examples-code-check.c + +pathpat='\(include/coap\)'$LIBCOAP_API_VERSION + +# autogen.sh +for fn in autogen.sh .gitignore build-env/Dockerfile.* ; do + sed -i "s,$pathpat,\1$NEW_VERSION,g" $fn +done + +# Adjust LIBCOAP_API_VERSION in CMakeLists.txt +sed -i "s/^\(set(LIBCOAP_API_VERSION \+\)$LIBCOAP_API_VERSION\( *)\)/\1$NEW_VERSION\2/" CMakeLists.txt + +# Adjust LibCoAPIncludeDir in win32/libcoap.props +sed -i "s/\(include\\\coap\)$LIBCOAP_API_VERSION/\1$NEW_VERSION/" win32/libcoap.props + +# Adjust API version in in win32/libcoap.vcxproj +sed -i "s/\(\$(ProjectName)-\)$LIBCOAP_API_VERSION/\1$NEW_VERSION/" win32/libcoap.vcxproj +sed -i "s/\(libcoap-\)$LIBCOAP_API_VERSION/\1$NEW_VERSION/g" win32/install/install.vcxproj + +# Finally, increase LIBCOAP_API_VERSION in configure.ac and re-run autoconf +sed -i "s/^\(LIBCOAP_API_VERSION=\)$LIBCOAP_API_VERSION/\1$NEW_VERSION/" configure.ac && autoreconf diff --git a/examples/espidf-coap-server/components/libcoap/scripts/build.sh b/examples/espidf-coap-server/components/libcoap/scripts/build.sh new file mode 100644 index 000000000..6501a3621 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/scripts/build.sh @@ -0,0 +1,86 @@ +#! /bin/sh + +#SILENT="--disable-silent-rules" + +if test "x$TESTS" = "xyes" -o "x$TESTS" = "xtrue" ; then + WITH_TESTS="`scripts/fix-cunit.sh` --enable-tests" + test -f `pwd`/cunit.pc && echo cat `pwd`/cunit.pc +fi + +TEST_LD_LIBRARY_PATH= +case "x${TLS}" in + xno) WITH_TLS="--disable-dtls" + ;; + xopenssl) WITH_TLS="--with-openssl" + ;; + xgnutls) WITH_TLS="--with-gnutls" + ;; + xmbedtls) WITH_TLS="--with-mbedtls" + ;; + xtinydtls) WITH_TLS="--with-tinydtls" + # Need this as libtinydtls.so has not been installed + # as a part of the travis build + TEST_LD_LIBRARY_PATH="ext/tinydtls" + ;; + *) WITH_TLS="--with-gnutls" + ;; +esac + +case "x${DOCS}" in + xyes) WITH_DOCS="--enable-documentation" + ;; + *) WITH_DOCS="--disable-documentation" + ;; +esac + +# Building with epoll support can be disabled by setting EPOLL=no. +# Otherwise, it is enabled by default and used if available. +if test "x$EPOLL" = "xno" ; then + OTHER_OPTS="$OTHER_OPTS --without-epoll" +fi + +# Enable constrained stack build when SMALL_STACK is set to yes. +if test "x$SMALL_STACK" = "xyes" ; then + OTHER_OPTS="$OTHER_OPTS --enable-small-stack" +fi + +config() { + echo "./configure $SILENT $*" + ./configure $SILENT $* || cat config.log +} + +case "${PLATFORM}" in + contiki) config "--disable-tests $WITH_DOCS --disable-examples $WITH_TLS" && \ + make -C examples/contiki + ;; + lwip) config "--disable-tests $WITH_DOCS --disable-examples $WITH_TLS" && \ + make -C examples/lwip + ;; + posix|*) config "$WITH_TESTS $WITH_DOCS --enable-examples $WITH_TLS $OTHER_OPTS" && \ + make && make check + ;; +esac + +err=$? +if test $err = 0 -a -n "$WITH_TESTS" ; then + EXEC_FILE=tests/testdriver + # then run valgrind on the actual executable + LD_LIBRARY_PATH=$TEST_LD_LIBRARY_PATH libtool --mode=execute valgrind --track-origins=yes --leak-check=yes --show-reachable=yes --error-exitcode=123 --quiet --suppressions=tests/valgrind_suppression $EXEC_FILE + err=$? +fi + +# invoke OSS-Fuzz syntax checks +if test $err = 0 -a -n "$WITH_TESTS" ; then + make -C tests/oss-fuzz -f Makefile.ci check clean + err=$? +fi + +# invoke man page examples code compiles checks +if test $err = 0 -a -n "$WITH_TESTS" ; then + make -C man + EXEC_FILE=man/examples-code-check + $EXEC_FILE man + err=$? +fi + +exit $err diff --git a/examples/espidf-coap-server/components/libcoap/scripts/dist.sh b/examples/espidf-coap-server/components/libcoap/scripts/dist.sh new file mode 100644 index 000000000..06d397fe7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/scripts/dist.sh @@ -0,0 +1,70 @@ +#! /bin/sh + +# This script creates a libcoap archive, unpacks it and does an +# out-of-tree build and installation afterwards. The environment +# variables PLATFORM, TESTS, TLS and DOCS control the build +# configuration. Suggested invocation from travis CI is: +# +# PLATFORM=posix TESTS=yes TLS=no DOCS=yes scripts/dist.sh +# +# Copyright (C) 2018 Olaf Bergmann +# +# This file is part of the CoAP C library libcoap. Please see README +# and COPYING for terms of use. +# + +if test "x${PLATFORM}" != "xposix"; then + exit 0 +fi + +# where to install the library +WORK=`pwd`/libcoap-build +mkdir -p $WORK || exit 1 +PREFIX="--prefix=`pwd`/libcoap-installation" +SILENT="--enable-silent-rules" + +WITH_TESTS="`scripts/fix-cunit.sh` --enable-tests" +test -f `pwd`/cunit.pc && echo cat `pwd`/cunit.pc + +case "x${TLS}" in + xno) WITH_TLS="--disable-dtls" + ;; + xopenssl) WITH_TLS="--with-openssl" + ;; + xgnutls) WITH_TLS="--with-gnutls" + ;; + xmbedtls) WITH_TLS="--with-mbedtls" + ;; + xtinydtls) WITH_TLS="--with-tinydtls --disable-shared" + ;; + *) WITH_TLS="--with-gnutls" + ;; +esac + +case "x${DOCS}" in + xyes) WITH_DOCS="--enable-documentation" + ;; + *) WITH_DOCS="--disable-documentation" + ;; +esac + +config() { + echo "./configure $*" + ./configure $* || cat config.log +} + +work_dir=$PWD +config "$WITH_TESTS $SILENT --enable-documentation --enable-examples --disable-dtls" && make dist + +err=$? +ARCHIVE=`ls -1t libcoap-*.tar.bz2 |head -1` +echo $ARCHIVE +if test $err = 0 -a "x$ARCHIVE" != "x"; then + DIR=`pwd`/`tar taf $ARCHIVE |cut -d/ -f1|head -1` + tar xaf $ARCHIVE && cd $WORK && \ + $DIR/configure $PREFIX $WITH_TESTS $SILENT $WITH_DOCS --enable-examples $WITH_TLS && \ + make && make install + err=$? +fi + +exit $err diff --git a/examples/espidf-coap-server/components/libcoap/scripts/fix-cunit.sh b/examples/espidf-coap-server/components/libcoap/scripts/fix-cunit.sh new file mode 100644 index 000000000..05ab658eb --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/scripts/fix-cunit.sh @@ -0,0 +1,15 @@ +#! /bin/sh + +# only continue if `pkgconfig cunit` fails +pkg-config cunit 2>/dev/null && exit 0 + +# Check if the system has a cunit.pc. +# If not, exit with success (the configure script will raise +# a more descriptive error). +CUNIT_PC=`dpkg -L libcunit1-dev 2>/dev/null|grep cunit.pc` +if test "x$CUNIT_PC" != "x"; then + grep -q Version: $CUNIT_PC || (dpkg -l|sed -ne 's/^ii\s\+libcunit1-dev\s\+\([0-9]\+.[0-9]\+-[0-9]\+\).*$/Version: \1/p; T; q'|cat - $CUNIT_PC |sed -e 's/={exec_prefix/=${exec_prefix/' >`pwd`/cunit.pc) +fi + +# output location of generated cunit.pc +echo PKG_CONFIG_PATH=`pwd` diff --git a/examples/espidf-coap-server/components/libcoap/scripts/format_cmake.sh b/examples/espidf-coap-server/components/libcoap/scripts/format_cmake.sh new file mode 100644 index 000000000..2d8a94c57 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/scripts/format_cmake.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +cmakeFormat="cmake-format" + +path_to_cmake_format="$(which $cmakeFormat)" +echo "$path_to_cmake_format" + +if [ -z "$cmakeFormat" ] +then + echo "$cmakeFormat is not installed. Cannot format cmake files..." + echo "run: pip install cmake-format" + exit 1 +fi + +echo "$cmakeFormat was found, going to format your cmake scripts..." >&2 + +find $(dirname "$0")/ \ +-not \( -path "*/build/*" -prune \) \ +\( -name *.cmake -o -name CMakeLists.txt \) \ +| xargs $cmakeFormat -c cmake-format.yaml -i + + +echo "done formatting with cmake-format" diff --git a/examples/espidf-coap-server/components/libcoap/scripts/github_dist.sh b/examples/espidf-coap-server/components/libcoap/scripts/github_dist.sh new file mode 100644 index 000000000..4a82c0ad5 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/scripts/github_dist.sh @@ -0,0 +1,24 @@ +#! /bin/sh + +# This script creates a libcoap archive, unpacks it and does an +# out-of-tree build and installation afterwards. +# +# Copyright (C) 2021-2022 Olaf Bergmann +# +# This file is part of the CoAP C library libcoap. Please see README +# and COPYING for terms of use. +# + +PREFIX=--prefix=`pwd`/libcoap-install +ARCHIVE=`ls -1t libcoap-*.tar.bz2 |head -1` +err=$? +echo $ARCHIVE +if test $err = 0 -a "x$ARCHIVE" != "x"; then + DIR=`pwd`/`tar taf $ARCHIVE |cut -d/ -f1|head -1` + tar xaf $ARCHIVE && cd $DIR && \ + $DIR/configure $PREFIX --enable-tests --enable-silent-rules --enable-documentation --enable-examples --disable-dtls && \ + make EXTRA_CFLAGS=-Werror && make install EXTRA_CFLAGS=-Werror + err=$? +fi + +exit $err diff --git a/examples/espidf-coap-server/components/libcoap/scripts/msbuild.sln.cmd b/examples/espidf-coap-server/components/libcoap/scripts/msbuild.sln.cmd new file mode 100644 index 000000000..7c22c98a7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/scripts/msbuild.sln.cmd @@ -0,0 +1,16 @@ +@echo off +pushd "%~dp0" + +if exist Debug rd /s /q Debug +if exist Release rd /s /q Release +if exist x64 rd /s /q x64 +if exist NoTLS rd /s /q NoTLS + +cd .. + +rem MSBuild.exe ./win32/libcoap.sln /p:Configuration=NoTLS /p:Platform=x64 /warnaserror +MSBuild.exe ./win32/libcoap.sln /p:Platform=x64 /warnaserror + +:exit +popd +@echo on diff --git a/examples/espidf-coap-server/components/libcoap/src/block.c b/examples/espidf-coap-server/components/libcoap/src/block.c new file mode 100644 index 000000000..f13c97e2e --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/block.c @@ -0,0 +1,2451 @@ +/* block.c -- block transfer + * + * Copyright (C) 2010--2012,2015-2022 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file block.c + * @brief CoAP Block handling + */ + +#include "coap3/coap_internal.h" + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#define STATE_TOKEN_BASE(t) ((t) & 0xffffffffffffULL) +#define STATE_TOKEN_RETRY(t) ((uint64_t)(t) >> 48) +#define STATE_TOKEN_FULL(t,r) (STATE_TOKEN_BASE(t) + ((uint64_t)(r) << 48)) + +unsigned int +coap_opt_block_num(const coap_opt_t *block_opt) { + unsigned int num = 0; + uint16_t len; + + len = coap_opt_length(block_opt); + + if (len == 0) { + return 0; + } + + if (len > 1) { + num = coap_decode_var_bytes(coap_opt_value(block_opt), + coap_opt_length(block_opt) - 1); + } + + return (num << 4) | ((*COAP_OPT_BLOCK_LAST(block_opt) & 0xF0) >> 4); +} + +int +coap_get_block_b(const coap_session_t *session, const coap_pdu_t *pdu, + coap_option_num_t number, coap_block_b_t *block) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + + assert(block); + memset(block, 0, sizeof(coap_block_b_t)); + + if (pdu && (option = coap_check_option(pdu, number, &opt_iter)) != NULL) { + unsigned int num; + + block->aszx = block->szx = COAP_OPT_BLOCK_SZX(option); + if (block->szx == 7) { + size_t length; + const uint8_t *data; + + if (session == NULL || COAP_PROTO_NOT_RELIABLE(session->proto) || + !(session->csm_bert_rem_support && session->csm_bert_loc_support)) + /* No BERT support */ + return 0; + + block->szx = 6; /* BERT is 1024 block chunks */ + block->bert = 1; + if (coap_get_data(pdu, &length, &data)) + block->chunk_size = (uint32_t)length; + else + block->chunk_size = 0; + } else { + block->chunk_size = (size_t)1 << (block->szx + 4); + } + block->defined = 1; + if (COAP_OPT_BLOCK_MORE(option)) + block->m = 1; + + /* The block number is at most 20 bits, so values above 2^20 - 1 + * are illegal. */ + num = coap_opt_block_num(option); + if (num > 0xFFFFF) { + return 0; + } + block->num = num; + return 1; + } + + return 0; +} + +int +coap_get_block(const coap_pdu_t *pdu, coap_option_num_t number, + coap_block_t *block) { + coap_block_b_t block_b; + + assert(block); + memset(block, 0, sizeof(coap_block_t)); + + if (coap_get_block_b(NULL, pdu, number, &block_b)) { + block->num = block_b.num; + block->m = block_b.m; + block->szx = block_b.szx; + return 1; + } + return 0; +} + +static int +setup_block_b(coap_session_t *session, coap_pdu_t *pdu, coap_block_b_t *block, + unsigned int num, + unsigned int blk_size, size_t total) { + size_t token_options = pdu->data ? (size_t)(pdu->data - pdu->token) : pdu->used_size; + size_t avail = pdu->max_size - token_options; + unsigned int start = num << (blk_size + 4); + unsigned int can_use_bert = block->defined == 0 || block->bert; + + assert(start <= total); + memset(block, 0, sizeof(*block)); + block->num = num; + block->szx = block->aszx = blk_size; + if (can_use_bert && blk_size == 6 && avail >= 1024 && session != NULL && + COAP_PROTO_RELIABLE(session->proto) && + session->csm_bert_rem_support && session->csm_bert_loc_support) { + block->bert = 1; + block->aszx = 7; + block->chunk_size = (uint32_t)((avail / 1024) * 1024); + } else { + block->chunk_size = (size_t)1 << (blk_size + 4); + if (avail < block->chunk_size && (total - start) >= avail) { + /* Need to reduce block size */ + unsigned int szx; + int new_blk_size; + + if (avail < 16) { /* bad luck, this is the smallest block size */ + coap_log(LOG_DEBUG, + "not enough space, even the smallest block does not fit\n"); + return 0; + } + new_blk_size = coap_flsll((long long)avail) - 5; + coap_log(LOG_DEBUG, + "decrease block size for %zu to %d\n", avail, new_blk_size); + szx = block->szx; + block->szx = new_blk_size; + block->num <<= szx - block->szx; + block->chunk_size = (size_t)1 << (new_blk_size + 4); + } + } + block->m = block->chunk_size < total - start; + return 1; +} + +int +coap_write_block_opt(coap_block_t *block, coap_option_num_t number, + coap_pdu_t *pdu, size_t data_length) { + size_t start; + unsigned char buf[4]; + coap_block_b_t block_b; + + assert(pdu); + + start = block->num << (block->szx + 4); + if (block->num != 0 && data_length <= start) { + coap_log(LOG_DEBUG, "illegal block requested\n"); + return -2; + } + + assert(pdu->max_size > 0); + + block_b.defined = 1; + block_b.bert = 0; + if (!setup_block_b(NULL, pdu, &block_b, block->num, + block->szx, data_length)) + return -3; + + /* to re-encode the block option */ + coap_update_option(pdu, number, coap_encode_var_safe(buf, sizeof(buf), + ((block_b.num << 4) | + (block_b.m << 3) | + block_b.szx)), + buf); + + return 1; +} + +int +coap_write_block_b_opt(coap_session_t *session, coap_block_b_t *block, + coap_option_num_t number, + coap_pdu_t *pdu, size_t data_length) { + size_t start; + unsigned char buf[4]; + + assert(pdu); + + start = block->num << (block->szx + 4); + if (block->num != 0 && data_length <= start) { + coap_log(LOG_DEBUG, "illegal block requested\n"); + return -2; + } + + assert(pdu->max_size > 0); + + if (!setup_block_b(session, pdu, block, block->num, + block->szx, data_length)) + return -3; + + /* to re-encode the block option */ + coap_update_option(pdu, number, coap_encode_var_safe(buf, sizeof(buf), + ((block->num << 4) | + (block->m << 3) | + block->aszx)), + buf); + + return 1; +} + +int +coap_add_block(coap_pdu_t *pdu, size_t len, const uint8_t *data, + unsigned int block_num, unsigned char block_szx) { + unsigned int start; + start = block_num << (block_szx + 4); + + if (len <= start) + return 0; + + return coap_add_data(pdu, + min(len - start, ((size_t)1 << (block_szx + 4))), + data + start); +} + +int +coap_add_block_b_data(coap_pdu_t *pdu, size_t len, const uint8_t *data, + coap_block_b_t *block) { + unsigned int start = block->num << (block->szx + 4); + size_t max_size; + + if (len <= start) + return 0; + + if (block->bert) { + size_t token_options = pdu->data ? (size_t)(pdu->data - pdu->token) : pdu->used_size; + max_size = ((pdu->max_size - token_options) / 1024) * 1024; + } else { + max_size = (size_t)1 << (block->szx + 4); + } + block->chunk_size = (uint32_t)max_size; + + return coap_add_data(pdu, + min(len - start, max_size), + data + start); +} + +/* + * Note that the COAP_OPTION_ have to be added in the correct order + */ +void +coap_add_data_blocked_response(const coap_pdu_t *request, + coap_pdu_t *response, + uint16_t media_type, + int maxage, + size_t length, + const uint8_t* data +) { + coap_key_t etag; + unsigned char buf[4]; + coap_block_t block2; + int block2_requested = 0; + + memset(&block2, 0, sizeof(block2)); + /* + * Need to check that a valid block is getting asked for so that the + * correct options are put into the PDU. + */ + if (request) { + if (coap_get_block(request, COAP_OPTION_BLOCK2, &block2)) { + block2_requested = 1; + if (block2.num != 0 && length <= (block2.num << (block2.szx + 4))) { + coap_log(LOG_DEBUG, "Illegal block requested (%d > last = %zu)\n", + block2.num, + length >> (block2.szx + 4)); + response->code = COAP_RESPONSE_CODE(400); + goto error; + } + } + } + response->code = COAP_RESPONSE_CODE(205); + + /* add etag for the resource */ + memset(etag, 0, sizeof(etag)); + coap_hash(data, length, etag); + coap_add_option_internal(response, COAP_OPTION_ETAG, sizeof(etag), etag); + + coap_insert_option(response, COAP_OPTION_CONTENT_FORMAT, + coap_encode_var_safe(buf, sizeof(buf), + media_type), + buf); + + if (maxage >= 0) { + coap_insert_option(response, + COAP_OPTION_MAXAGE, + coap_encode_var_safe(buf, sizeof(buf), maxage), buf); + } + + if (block2_requested) { + int res; + + res = coap_write_block_opt(&block2, COAP_OPTION_BLOCK2, response, length); + + switch (res) { + case -2: /* illegal block (caught above) */ + response->code = COAP_RESPONSE_CODE(400); + goto error; + case -1: /* should really not happen */ + assert(0); + /* fall through if assert is a no-op */ + case -3: /* cannot handle request */ + response->code = COAP_RESPONSE_CODE(500); + goto error; + default: /* everything is good */ + ; + } + + coap_add_option_internal(response, + COAP_OPTION_SIZE2, + coap_encode_var_safe8(buf, sizeof(buf), length), + buf); + + coap_add_block(response, length, data, + block2.num, block2.szx); + return; + } + + /* + * Block2 not requested + */ + if (!coap_add_data(response, length, data)) { + /* + * Insufficient space to add in data - use block mode + * set initial block size, will be lowered by + * coap_write_block_opt() automatically + */ + block2.num = 0; + block2.szx = 6; + coap_write_block_opt(&block2, COAP_OPTION_BLOCK2, response, length); + + coap_add_option_internal(response, + COAP_OPTION_SIZE2, + coap_encode_var_safe8(buf, sizeof(buf), length), + buf); + + coap_add_block(response, length, data, + block2.num, block2.szx); + } + return; + +error: + coap_add_data(response, + strlen(coap_response_phrase(response->code)), + (const unsigned char *)coap_response_phrase(response->code)); +} + +void +coap_context_set_block_mode(coap_context_t *context, + uint8_t block_mode) { + context->block_mode = block_mode &= (COAP_BLOCK_USE_LIBCOAP | + COAP_BLOCK_SINGLE_BODY); + if (!(block_mode & COAP_BLOCK_USE_LIBCOAP)) + context->block_mode = 0; +} + +COAP_STATIC_INLINE int +full_match(const uint8_t *a, size_t alen, + const uint8_t *b, size_t blen) { + return alen == blen && (alen == 0 || memcmp(a, b, alen) == 0); +} + +#if COAP_CLIENT_SUPPORT +int +coap_cancel_observe(coap_session_t *session, coap_binary_t *token, + coap_pdu_type_t type) { + coap_lg_crcv_t *cq; + + assert(session); + if (!session) + return 0; + + if (!(session->block_mode & COAP_BLOCK_USE_LIBCOAP)) { + coap_log(LOG_DEBUG, + "** %s: coap_cancel_observe: COAP_BLOCK_USE_LIBCOAP not enabled\n", + coap_session_str(session)); + return 0; + } + + LL_FOREACH(session->lg_crcv, cq) { + if (cq->observe_set) { + if ((!token && !cq->app_token->length) || (token && + full_match(token->s, token->length, cq->app_token->s, + cq->app_token->length))) { + uint8_t buf[8]; + coap_mid_t mid; + size_t size; + const uint8_t *data; + coap_binary_t *otoken = cq->obs_token ? cq->obs_token : cq->app_token; + coap_pdu_t * pdu = coap_pdu_duplicate(&cq->pdu, + session, + otoken->length, + otoken->s, + NULL); + + cq->observe_set = 0; + if (pdu == NULL) + return 0; + /* Need to make sure that this is the correct type */ + pdu->type = type; + + if (coap_get_data(&cq->pdu, &size, &data)) { + coap_add_data(pdu, size, data); + } + coap_update_option(pdu, COAP_OPTION_OBSERVE, + coap_encode_var_safe(buf, sizeof(buf), + COAP_OBSERVE_CANCEL), + buf); + mid = coap_send_internal(session, pdu); + if (mid != COAP_INVALID_MID) + return 1; + break; + } + } + } + return 0; +} +#endif /* COAP_CLIENT_SUPPORT */ + +static int +coap_add_data_large_internal(coap_session_t *session, + coap_pdu_t *pdu, + coap_resource_t *resource, + const coap_string_t *query, + int maxage, + uint64_t etag, + size_t length, + const uint8_t *data, + coap_release_large_data_t release_func, + void *app_ptr, + coap_pdu_code_t request_method) { + + ssize_t avail; + coap_block_b_t block; + size_t chunk; + coap_lg_xmit_t *lg_xmit = NULL; + uint8_t buf[8]; + int have_block_defined = 0; + uint8_t blk_size; + uint16_t option; + size_t token_options; + + assert(pdu); + if (pdu->data) { + coap_log(LOG_WARNING, "coap_add_data_large: PDU already contains data\n"); + if (release_func) + release_func(session, app_ptr); + return 0; + } + + if (!(session->block_mode & COAP_BLOCK_USE_LIBCOAP)) { + coap_log(LOG_DEBUG, + "** %s: coap_add_data_large: COAP_BLOCK_USE_LIBCOAP not enabled\n", + coap_session_str(session)); + goto add_data; + } + + /* Block NUM max 20 bits and block size is "2**(SZX + 4)" + and using SZX max of 6 gives maximum size = 1,073,740,800 + CSM Max-Message-Size theoretical maximum = 4,294,967,295 + So, if using blocks, we are limited to 1,073,740,800. + */ +#define MAX_BLK_LEN (((1 << 20) - 1) * (1 << (6 + 4))) + + if (length > MAX_BLK_LEN) { + coap_log(LOG_WARNING, + "Size of large buffer restricted to 0x%x bytes\n", MAX_BLK_LEN); + length = MAX_BLK_LEN; + } + /* Determine the block size to use, adding in sensible options if needed */ + if (COAP_PDU_IS_REQUEST(pdu)) { + coap_lg_xmit_t *q; + + option = COAP_OPTION_BLOCK1; + + /* See if this token is already in use for large bodies (unlikely) */ + LL_FOREACH_SAFE(session->lg_xmit, lg_xmit, q) { + if (full_match(pdu->token, pdu->token_length, + lg_xmit->b.b1.app_token->s, + lg_xmit->b.b1.app_token->length)) { + /* Unfortunately need to free this off as potential size change */ + LL_DELETE(session->lg_xmit, lg_xmit); + coap_block_delete_lg_xmit(session, lg_xmit); + lg_xmit = NULL; + coap_handle_event(session->context, COAP_EVENT_XMIT_BLOCK_FAIL, session); + break; + } + } + } + else { + /* Have to assume that it is a response even if code is 0.00 */ + coap_lg_xmit_t *q; + coap_string_t empty = { 0, NULL}; + + assert(resource); + option = COAP_OPTION_BLOCK2; + /* Check if resource+query is already in use for large bodies (unlikely) */ + LL_FOREACH_SAFE(session->lg_xmit, lg_xmit, q) { + if (resource == lg_xmit->b.b2.resource && + request_method == lg_xmit->b.b2.request_method && + coap_string_equal(query ? query : &empty, + lg_xmit->b.b2.query ? lg_xmit->b.b2.query : &empty)) { + /* Unfortunately need to free this off as potential size change */ + LL_DELETE(session->lg_xmit, lg_xmit); + coap_block_delete_lg_xmit(session, lg_xmit); + lg_xmit = NULL; + coap_handle_event(session->context, COAP_EVENT_XMIT_BLOCK_FAIL, session); + break; + } + } + } + + token_options = pdu->data ? (size_t)(pdu->data - pdu->token) : pdu->used_size; + avail = pdu->max_size - token_options; + /* There may be a response with Echo option */ + avail -= coap_opt_encode_size(COAP_OPTION_ECHO, 40); + /* May need token of length 8, so account for this */ + avail -= (pdu->token_length < 8) ? 8 - pdu->token_length : 0; + blk_size = coap_flsll((long long)avail) - 4 - 1; + if (blk_size > 6) + blk_size = 6; + + /* see if BlockX defined - if so update blk_size as given by app */ + if (coap_get_block_b(session, pdu, option, &block)) { + if (block.szx < blk_size) + blk_size = block.szx; + have_block_defined = 1; + } + + if (avail < 16 && ((ssize_t)length > avail || have_block_defined)) { + /* bad luck, this is the smallest block size */ + coap_log(LOG_DEBUG, + "not enough space, even the smallest block does not fit\n"); + goto fail; + } + + chunk = (size_t)1 << (blk_size + 4); + if (have_block_defined && block.num != 0) { + /* App is defining a single block to send */ + size_t rem; + + if (length >= block.num * chunk) { + rem = chunk; + if (chunk > length - block.num * chunk) + rem = length - block.num * chunk; + if (!coap_add_data(pdu, rem, &data[block.num * chunk])) + goto fail; + } + if (release_func) + release_func(session, app_ptr); + } + else if ((have_block_defined && length > chunk) || (ssize_t)length > avail) { + /* Only add in lg_xmit if more than one block needs to be handled */ + size_t rem; + + lg_xmit = coap_malloc_type(COAP_LG_XMIT, sizeof(coap_lg_xmit_t)); + if (!lg_xmit) + goto fail; + + /* Set up for displaying all the data in the pdu */ + pdu->body_data = data; + pdu->body_length = length; + coap_log(LOG_DEBUG, "PDU presented by app.\n"); + coap_show_pdu(LOG_DEBUG, pdu); + pdu->body_data = NULL; + pdu->body_length = 0; + + coap_log(LOG_DEBUG, "** %s: lg_xmit %p initialized\n", + coap_session_str(session), (void*)lg_xmit); + /* Update lg_xmit with large data information */ + memset(lg_xmit, 0, sizeof(coap_lg_xmit_t)); + lg_xmit->blk_size = blk_size; + lg_xmit->option = option; + lg_xmit->last_block = 0; + lg_xmit->data = data; + lg_xmit->length = length; + lg_xmit->release_func = release_func; + lg_xmit->app_ptr = app_ptr; + coap_ticks(&lg_xmit->last_obs); + coap_ticks(&lg_xmit->last_sent); + if (COAP_PDU_IS_REQUEST(pdu)) { + /* Need to keep original token for updating response PDUs */ + lg_xmit->b.b1.app_token = coap_new_binary(pdu->token_length); + if (!lg_xmit->b.b1.app_token) + goto fail; + memcpy(lg_xmit->b.b1.app_token->s, pdu->token, pdu->token_length); + /* + * Need to set up new token for use during transmits + */ + lg_xmit->b.b1.count = 1; + lg_xmit->b.b1.state_token = STATE_TOKEN_FULL(++session->tx_token, + lg_xmit->b.b1.count); + /* + * Token will be updated in pdu later as original pdu may be needed in + * coap_send() + */ + coap_update_option(pdu, + COAP_OPTION_SIZE1, + coap_encode_var_safe(buf, sizeof(buf), + (unsigned int)length), + buf); + coap_update_option(pdu, + COAP_OPTION_RTAG, + coap_encode_var_safe8(buf, sizeof(buf), + ++session->tx_rtag), + buf); + } else { + /* + * resource+query match is used for Block2 large body transmissions + * token match is used for Block1 large body transmissions + */ + lg_xmit->b.b2.resource = resource; + if (query) { + lg_xmit->b.b2.query = coap_new_string(query->length); + if (lg_xmit->b.b2.query) { + memcpy(lg_xmit->b.b2.query->s, query->s, query->length); + } + } + else { + lg_xmit->b.b2.query = NULL; + } + lg_xmit->b.b2.etag = etag; + lg_xmit->b.b2.request_method = request_method; + if (maxage >= 0) { + coap_tick_t now; + + coap_ticks(&now); + lg_xmit->b.b2.maxage_expire = coap_ticks_to_rt(now) + maxage; + } + else { + lg_xmit->b.b2.maxage_expire = 0; + } + coap_update_option(pdu, + COAP_OPTION_SIZE2, + coap_encode_var_safe(buf, sizeof(buf), + (unsigned int)length), + buf); + if (etag == 0) { + if (++session->context->etag == 0) + ++session->context->etag; + etag = session->context->etag; + } + coap_update_option(pdu, + COAP_OPTION_ETAG, + coap_encode_var_safe8(buf, sizeof(buf), etag), + buf); + } + + if (!setup_block_b(session, pdu, &block, block.num, + blk_size, lg_xmit->length)) + goto fail; + + /* Add in with requested block num, more bit and block size */ + coap_update_option(pdu, + lg_xmit->option, + coap_encode_var_safe(buf, sizeof(buf), + (block.num << 4) | (block.m << 3) | block.aszx), + buf); + + /* Set up skeletal PDU to use as a basis for all the subsequent blocks */ + memcpy(&lg_xmit->pdu, pdu, sizeof(lg_xmit->pdu)); + lg_xmit->pdu.token = coap_malloc_type(COAP_PDU_BUF, + lg_xmit->pdu.used_size + lg_xmit->pdu.max_hdr_size); + if (!lg_xmit->pdu.token) + goto fail; + + lg_xmit->pdu.alloc_size = lg_xmit->pdu.used_size; + lg_xmit->pdu.token += lg_xmit->pdu.max_hdr_size; + memcpy(lg_xmit->pdu.token, pdu->token, lg_xmit->pdu.used_size); + if (pdu->data) + lg_xmit->pdu.data = lg_xmit->pdu.token + (pdu->data - pdu->token); + + /* Check we still have space after adding in some options */ + token_options = pdu->data ? (size_t)(pdu->data - pdu->token) : pdu->used_size; + avail = pdu->max_size - token_options; + /* There may be a response with Echo option */ + avail -= coap_opt_encode_size(COAP_OPTION_ECHO, 40); + /* May need token of length 8, so account for this */ + avail -= (pdu->token_length < 8) ? 8 - pdu->token_length : 0; + if (avail < (ssize_t)chunk) { + /* chunk size change down */ + if (avail < 16) { + coap_log(LOG_WARNING, + "not enough space, even the smallest block does not fit\n"); + goto fail; + } + blk_size = coap_flsll((long long)avail) - 4 - 1; + block.num = block.num << (lg_xmit->blk_size - blk_size); + lg_xmit->blk_size = blk_size; + chunk = (size_t)1 << (lg_xmit->blk_size + 4); + block.chunk_size = (uint32_t)chunk; + block.bert = 0; + coap_update_option(pdu, + lg_xmit->option, + coap_encode_var_safe(buf, sizeof(buf), + (block.num << 4) | (block.m << 3) | lg_xmit->blk_size), + buf); + } + + rem = block.chunk_size; + if (rem > lg_xmit->length - block.num * chunk) + rem = lg_xmit->length - block.num * chunk; + if (!coap_add_data(pdu, rem, &data[block.num * chunk])) + goto fail; + + if (COAP_PDU_IS_REQUEST(pdu)) + lg_xmit->b.b1.bert_size = rem; + + lg_xmit->last_block = -1; + + /* Link the new lg_xmit in */ + LL_PREPEND(session->lg_xmit,lg_xmit); + } + else { + /* No need to use blocks */ + if (have_block_defined) { + coap_update_option(pdu, + option, + coap_encode_var_safe(buf, sizeof(buf), + (0 << 4) | (0 << 3) | blk_size), buf); + } +add_data: + if (!coap_add_data(pdu, length, data)) + goto fail; + + if (release_func) + release_func(session, app_ptr); + } + return 1; + +fail: + if (lg_xmit) { + coap_block_delete_lg_xmit(session, lg_xmit); + } else if (release_func) { + release_func(session, app_ptr); + } + return 0; +} + +#if COAP_CLIENT_SUPPORT +int +coap_add_data_large_request(coap_session_t *session, + coap_pdu_t *pdu, + size_t length, + const uint8_t *data, + coap_release_large_data_t release_func, + void *app_ptr) { + /* + * Delay if session->doing_first is set. + * E.g. Reliable and CSM not in yet for checking block support + */ + if (coap_client_delay_first(session) == 0) { + if (release_func) + release_func(session, app_ptr); + return 0; + } + return coap_add_data_large_internal(session, pdu, NULL, NULL, -1, 0, length, + data, release_func, app_ptr, 0); +} +#endif /* ! COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +int +coap_add_data_large_response(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + coap_pdu_t *response, + const coap_string_t *query, + uint16_t media_type, + int maxage, + uint64_t etag, + size_t length, + const uint8_t *data, + coap_release_large_data_t release_func, + void *app_ptr +) { + unsigned char buf[4]; + coap_block_b_t block; + int block_requested = 0; + uint16_t block_opt = COAP_OPTION_BLOCK2; + + memset(&block, 0, sizeof(block)); + /* + * Need to check that a valid block is getting asked for so that the + * correct options are put into the PDU. + */ + if (request) { + if (coap_get_block_b(session, request, COAP_OPTION_BLOCK2, &block)) { + block_requested = 1; + if (block.num != 0 && length <= (block.num << (block.szx + 4))) { + coap_log(LOG_DEBUG, "Illegal block requested (%d > last = %zu)\n", + block.num, + length >> (block.szx + 4)); + response->code = COAP_RESPONSE_CODE(400); + goto error; + } + } + } + + if (media_type != 0) + coap_insert_option(response, COAP_OPTION_CONTENT_FORMAT, + coap_encode_var_safe(buf, sizeof(buf), + media_type), + buf); + + if (maxage >= 0) { + coap_insert_option(response, + COAP_OPTION_MAXAGE, + coap_encode_var_safe(buf, sizeof(buf), maxage), buf); + } + + if (block_requested) { + int res; + + res = coap_write_block_b_opt(session, &block, block_opt, response, + length); + + switch (res) { + case -2: /* illegal block (caught above) */ + response->code = COAP_RESPONSE_CODE(400); + goto error; + case -1: /* should really not happen */ + assert(0); + /* fall through if assert is a no-op */ + case -3: /* cannot handle request */ + response->code = COAP_RESPONSE_CODE(500); + goto error; + default: /* everything is good */ + ; + } + } + + /* add data body */ + if (request && + !coap_add_data_large_internal(session, response, resource, query, + maxage, etag, length, data, + release_func, app_ptr, + request->code)) { + response->code = COAP_RESPONSE_CODE(500); + goto error_released; + } + + return 1; + +error: + if (release_func) + release_func(session, app_ptr); +error_released: +#if COAP_ERROR_PHRASE_LENGTH > 0 + coap_add_data(response, + strlen(coap_response_phrase(response->code)), + (const unsigned char *)coap_response_phrase(response->code)); +#endif /* COAP_ERROR_PHRASE_LENGTH > 0 */ + return 0; +} +#endif /* ! COAP_SERVER_SUPPORT */ + +/* + * return 1 if there is a future expire time, else 0. + * update tim_rem with remaining value if return is 1. + */ +int +coap_block_check_lg_xmit_timeouts(coap_session_t *session, coap_tick_t now, + coap_tick_t *tim_rem) { + coap_lg_xmit_t *p; + coap_lg_xmit_t *q; + coap_tick_t idle_timeout = 8 * COAP_TICKS_PER_SECOND; + coap_tick_t partial_timeout = COAP_MAX_TRANSMIT_WAIT_TICKS(session); + int ret = 0; + + *tim_rem = -1; + + LL_FOREACH_SAFE(session->lg_xmit, p, q) { + if (p->last_all_sent) { + if (p->last_all_sent + idle_timeout <= now) { + /* Expire this entry */ + LL_DELETE(session->lg_xmit, p); + coap_block_delete_lg_xmit(session, p); + } + else { + /* Delay until the lg_xmit needs to expire */ + if (*tim_rem > p->last_all_sent + idle_timeout - now) { + *tim_rem = p->last_all_sent + idle_timeout - now; + ret = 1; + } + } + } + else if (p->last_sent) { + if (p->last_sent + partial_timeout <= now) { + /* Expire this entry */ + LL_DELETE(session->lg_xmit, p); + coap_block_delete_lg_xmit(session, p); + coap_handle_event(session->context, COAP_EVENT_XMIT_BLOCK_FAIL, session); + } + else { + /* Delay until the lg_xmit needs to expire */ + if (*tim_rem > p->last_sent + partial_timeout - now) { + *tim_rem = p->last_sent + partial_timeout - now; + ret = 1; + } + } + } + } + return ret; +} + +#if COAP_CLIENT_SUPPORT +/* + * return 1 if there is a future expire time, else 0. + * update tim_rem with remaining value if return is 1. + */ +int +coap_block_check_lg_crcv_timeouts(coap_session_t *session, coap_tick_t now, + coap_tick_t *tim_rem) { + coap_lg_crcv_t *p; + coap_lg_crcv_t *q; + coap_tick_t partial_timeout = COAP_MAX_TRANSMIT_WAIT_TICKS(session); + int ret = 0; + + *tim_rem = -1; + + LL_FOREACH_SAFE(session->lg_crcv, p, q) { + if (!p->observe_set && p->last_used && + p->last_used + partial_timeout <= now) { + /* Expire this entry */ + LL_DELETE(session->lg_crcv, p); + coap_block_delete_lg_crcv(session, p); + } + else if (!p->observe_set && p->last_used) { + /* Delay until the lg_crcv needs to expire */ + if (*tim_rem > p->last_used + partial_timeout - now) { + *tim_rem = p->last_used + partial_timeout - now; + ret = 1; + } + } + } + return ret; +} +#endif /* COAP_CLIENT_SUPPORT */ + +static int +check_if_received_block(coap_rblock_t *rec_blocks, uint32_t block_num) { + uint32_t i; + + for (i = 0; i < rec_blocks->used; i++) { + if (block_num < rec_blocks->range[i].begin) + return 0; + if (block_num <= rec_blocks->range[i].end) + return 1; + } + return 0; +} + +static int +check_all_blocks_in(coap_rblock_t *rec_blocks, size_t total_blocks) { + uint32_t i; + uint32_t block = 0; + + for (i = 0; i < rec_blocks->used; i++) { + if (block < rec_blocks->range[i].begin) + return 0; + if (block < rec_blocks->range[i].end) + block = rec_blocks->range[i].end; + } + /* total_blocks counts from 1 */ + if (block + 1 < total_blocks) + return 0; + + return 1; +} + +#if COAP_SERVER_SUPPORT +/* + * return 1 if there is a future expire time, else 0. + * update tim_rem with remaining value if return is 1. + */ +int +coap_block_check_lg_srcv_timeouts(coap_session_t *session, coap_tick_t now, + coap_tick_t *tim_rem) { + coap_lg_srcv_t *p; + coap_lg_srcv_t *q; + coap_tick_t partial_timeout = COAP_MAX_TRANSMIT_WAIT_TICKS(session); + int ret = 0; + + *tim_rem = -1; + + LL_FOREACH_SAFE(session->lg_srcv, p, q) { + if (p->last_used && p->last_used + partial_timeout <= now) { + /* Expire this entry */ + LL_DELETE(session->lg_srcv, p); + coap_block_delete_lg_srcv(session, p); + } + else if (p->last_used) { + /* Delay until the lg_srcv needs to expire */ + if (*tim_rem > p->last_used + partial_timeout - now) { + *tim_rem = p->last_used + partial_timeout - now; + ret = 1; + } + } + } + return ret; +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +coap_lg_crcv_t * +coap_block_new_lg_crcv(coap_session_t *session, coap_pdu_t *pdu) { + coap_lg_crcv_t *lg_crcv; + uint64_t state_token = STATE_TOKEN_FULL(++session->tx_token, 1); + + lg_crcv = coap_malloc_type(COAP_LG_CRCV, sizeof(coap_lg_crcv_t)); + + if (lg_crcv == NULL) + return NULL; + + coap_log(LOG_DEBUG, + "** %s: lg_crcv %p initialized - stateless token xxxx%012llx\n", + coap_session_str(session), (void*)lg_crcv, + STATE_TOKEN_BASE(state_token)); + memset(lg_crcv, 0, sizeof(coap_lg_crcv_t)); + lg_crcv->initial = 1; + coap_ticks(&lg_crcv->last_used); + /* Set up skeletal PDU to use as a basis for all the subsequent blocks */ + memcpy(&lg_crcv->pdu, pdu, sizeof(lg_crcv->pdu)); + lg_crcv->pdu.token = coap_malloc_type(COAP_PDU_BUF, + lg_crcv->pdu.alloc_size + lg_crcv->pdu.max_hdr_size); + if (!lg_crcv->pdu.token) { + coap_block_delete_lg_crcv(session, lg_crcv); + return NULL; + } + lg_crcv->pdu.token += lg_crcv->pdu.max_hdr_size; + memcpy(lg_crcv->pdu.token, pdu->token, lg_crcv->pdu.used_size); + if (lg_crcv->pdu.data) + lg_crcv->pdu.data = lg_crcv->pdu.token + (pdu->data - pdu->token); + /* Check that there is space for increased token + option change */ + if (lg_crcv->pdu.max_size < lg_crcv->pdu.used_size + 9) + lg_crcv->pdu.max_size = lg_crcv->pdu.used_size + 9; + + /* Need to keep original token for updating response PDUs */ + lg_crcv->app_token = coap_new_binary(pdu->token_length); + if (!lg_crcv->app_token) { + coap_block_delete_lg_crcv(session, lg_crcv); + return NULL; + } + memcpy(lg_crcv->app_token->s, pdu->token, pdu->token_length); + + /* Need to set up a base token for actual communications if retries needed */ + lg_crcv->retry_counter = 1; + lg_crcv->state_token = state_token; + + /* In case it is there - must not be in continuing request PDUs */ + coap_remove_option(&lg_crcv->pdu, COAP_OPTION_BLOCK1); + + return lg_crcv; +} + +void +coap_block_delete_lg_crcv(coap_session_t *session, + coap_lg_crcv_t *lg_crcv) { + if (lg_crcv == NULL) + return; + + if (lg_crcv->pdu.token) + coap_free_type(COAP_PDU_BUF, lg_crcv->pdu.token - lg_crcv->pdu.max_hdr_size); + coap_free_type(COAP_STRING, lg_crcv->body_data); + coap_log(LOG_DEBUG, "** %s: lg_crcv %p released\n", + coap_session_str(session), (void*)lg_crcv); + coap_delete_binary(lg_crcv->app_token); + coap_delete_binary(lg_crcv->obs_token); + coap_free_type(COAP_LG_CRCV, lg_crcv); +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +void +coap_block_delete_lg_srcv(coap_session_t *session, + coap_lg_srcv_t *lg_srcv) { + if (lg_srcv == NULL) + return; + + coap_delete_str_const(lg_srcv->uri_path); + coap_free_type(COAP_STRING, lg_srcv->body_data); + coap_log(LOG_DEBUG, "** %s: lg_srcv %p released\n", + coap_session_str(session), (void*)lg_srcv); + coap_free_type(COAP_LG_SRCV, lg_srcv); +} +#endif /* COAP_SERVER_SUPPORT */ + +void +coap_block_delete_lg_xmit(coap_session_t *session, + coap_lg_xmit_t *lg_xmit) { + if (lg_xmit == NULL) + return; + + if (lg_xmit->release_func) { + lg_xmit->release_func(session, lg_xmit->app_ptr); + } + if (lg_xmit->pdu.token) { + coap_free_type(COAP_PDU_BUF, lg_xmit->pdu.token - lg_xmit->pdu.max_hdr_size); + } + if (COAP_PDU_IS_REQUEST(&lg_xmit->pdu)) + coap_delete_binary(lg_xmit->b.b1.app_token); + else + coap_delete_string(lg_xmit->b.b2.query); + + coap_log(LOG_DEBUG, "** %s: lg_xmit %p released\n", + coap_session_str(session), (void*)lg_xmit); + coap_free_type(COAP_LG_XMIT, lg_xmit); +} + +#if COAP_SERVER_SUPPORT +static int +add_block_send(uint32_t num, uint32_t *out_blocks, + uint32_t *count, uint32_t max_count) { + uint32_t i; + + for (i = 0; i < *count && *count < max_count; i++) { + if (num == out_blocks[i]) + return 0; + else if (num < out_blocks[i]) { + if (*count - i > 1) + memmove(&out_blocks[i], &out_blocks[i+1], *count - i -1); + out_blocks[i] = num; + (*count)++; + return 1; + } + } + if (*count < max_count) { + out_blocks[i] = num; + (*count)++; + return 1; + } + return 0; +} + +/* + * Need to see if this is a request for the next block of a large body + * transfer. If so, need to initiate the response with the next blocks + * and not trouble the application. + * + * If additional responses needed, then these are expicitly sent out and + * 'response' is updated to be the last response to be sent. + * + * This is set up using coap_add_data_large_response() + * + * Server is sending a large data response to GET / observe (Block2) + * + * Return: 0 Call application handler + * 1 Do not call application handler - just send the built response + */ +int +coap_handle_request_send_block(coap_session_t *session, + coap_pdu_t *pdu, + coap_pdu_t *response, + coap_resource_t *resource, + coap_string_t *query) { + coap_lg_xmit_t *p = NULL; + coap_block_b_t block; + uint16_t block_opt = 0; + uint32_t out_blocks[1]; + const char *error_phrase; + + if (!coap_get_block_b(session, pdu, COAP_OPTION_BLOCK2, &block)) + return 0; + if (block.num == 0) { + /* Get a fresh copy of the data */ + return 0; + } + block_opt = COAP_OPTION_BLOCK2; + LL_FOREACH(session->lg_xmit, p) { + size_t chunk; + coap_opt_iterator_t opt_iter; + coap_opt_iterator_t opt_b_iter; + coap_opt_t *option; + uint32_t request_cnt, i; + coap_opt_t *etag_opt = NULL; + coap_pdu_t *out_pdu = response; + static coap_string_t empty = { 0, NULL}; + + if (COAP_PDU_IS_REQUEST(&p->pdu) || resource != p->b.b2.resource || + pdu->code != p->b.b2.request_method || + !coap_string_equal(query ? query : &empty, + p->b.b2.query ? p->b.b2.query : &empty)) { + /* try out the next one */ + continue; + } + p->last_all_sent = 0; + etag_opt = coap_check_option(pdu, COAP_OPTION_ETAG, &opt_iter); + if (etag_opt) { + uint64_t etag = coap_decode_var_bytes8(coap_opt_value(etag_opt), + coap_opt_length(etag_opt)); + if (etag != p->b.b2.etag) { + /* try out the next one */ + continue; + } + out_pdu->code = COAP_RESPONSE_CODE(203); + coap_ticks(&p->last_sent); + goto skip_app_handler; + } + else { + out_pdu->code = p->pdu.code; + } + + /* lg_xmit (response) found */ + coap_ticks(&p->last_obs); + + chunk = (size_t)1 << (p->blk_size + 4); + if (block_opt) { + if (block.bert) { + coap_log(LOG_DEBUG, + "found Block option, block is BERT, block nr. %u\n", + block.num); + } else { + coap_log(LOG_DEBUG, + "found Block option, block size is %u, block nr. %u\n", + 1 << (block.szx + 4), block.num); + } + if (block.bert == 0 && block.szx != p->blk_size) { + if ((p->offset + chunk) % ((size_t)1 << (block.szx + 4)) == 0) { + /* + * Recompute the block number of the previous packet given + * the new block size + */ + block.num = (uint32_t)(((p->offset + chunk) >> (block.szx + 4)) - 1); + p->blk_size = block.szx; + chunk = (size_t)1 << (p->blk_size + 4); + p->offset = block.num * chunk; + coap_log(LOG_DEBUG, + "new Block size is %u, block number %u completed\n", + 1 << (block.szx + 4), block.num); + } else { + coap_log(LOG_DEBUG, + "ignoring request to increase Block size, " + "next block is not aligned on requested block size " + "boundary. (%zu x %u mod %u = %zu (which is not 0)\n", + p->offset/chunk + 1, (1 << (p->blk_size + 4)), + (1 << (block.szx + 4)), + (p->offset + chunk) % ((size_t)1 << (block.szx + 4))); + } + } + } + + request_cnt = 0; + coap_option_iterator_init(pdu, &opt_b_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_b_iter))) { + unsigned int num; + if (opt_b_iter.number != p->option) + continue; + num = coap_opt_block_num(option); + if (num > 0xFFFFF) /* 20 bits max for num */ + continue; + if (block.aszx != COAP_OPT_BLOCK_SZX(option)) { + coap_add_data(response, + sizeof("Changing blocksize during request invalid")-1, + (const uint8_t *)"Changing blocksize during request invalid"); + response->code = COAP_RESPONSE_CODE(400); + return 1; + } + add_block_send(num, out_blocks, &request_cnt, 1); + break; + } + if (request_cnt == 0) { + /* Block2 not found - give them the first block */ + block.szx = p->blk_size; + p->offset = 0; + out_blocks[0] = 0; + request_cnt = 1; + } + + for (i = 0; i < request_cnt; i++) { + uint8_t buf[8]; + + block.num = out_blocks[i]; + p->offset = block.num * chunk; + + if (i + 1 < request_cnt) { + /* Need to set up a copy of the pdu to send */ + coap_opt_filter_t drop_options; + + memset(&drop_options, 0, sizeof(coap_opt_filter_t)); + coap_option_filter_set(&drop_options, COAP_OPTION_OBSERVE); + out_pdu = coap_pdu_duplicate(&p->pdu, session, pdu->token_length, + pdu->token, &drop_options); + if (!out_pdu) { + goto internal_issue; + } + } + else { + /* + * Copy the options across and then fix the block option + * + * Need to drop Observe option if Block2 and block.num != 0 + */ + coap_option_iterator_init(&p->pdu, &opt_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_iter))) { + if (opt_iter.number == COAP_OPTION_OBSERVE) + continue; + if (opt_iter.number == p->option) + continue; + if (!coap_insert_option(response, opt_iter.number, + coap_opt_length(option), + coap_opt_value(option))) { + goto internal_issue; + } + } + out_pdu = response; + } + if (pdu->type == COAP_MESSAGE_NON) + out_pdu->type = COAP_MESSAGE_NON; + if (block.bert) { + size_t token_options = pdu->data ? (size_t)(pdu->data - pdu->token) : pdu->used_size; + block.m = (p->length - p->offset) > + ((out_pdu->max_size - token_options) /1024) * 1024; + } else { + block.m = (p->offset + chunk) < p->length; + } + if (!coap_update_option(out_pdu, p->option, + coap_encode_var_safe(buf, + sizeof(buf), + (block.num << 4) | + (block.m << 3) | + block.aszx), + buf)) { + goto internal_issue; + } + if (!(p->offset + chunk < p->length)) { + /* Last block - keep in cache for 4 * ACK_TIMOUT */ + coap_ticks(&p->last_all_sent); + } + if (p->b.b2.maxage_expire) { + coap_tick_t now; + coap_time_t rem; + + coap_ticks(&now); + rem = coap_ticks_to_rt(now); + if (p->b.b2.maxage_expire > rem) { + rem = p->b.b2.maxage_expire - rem; + } + else { + rem = 0; + /* Entry needs to be expired */ + coap_ticks(&p->last_all_sent); + } + if (!coap_update_option(out_pdu, COAP_OPTION_MAXAGE, + coap_encode_var_safe8(buf, + sizeof(buf), + rem), + buf)) { + goto internal_issue; + } + } + + if (!etag_opt && !coap_add_block_b_data(out_pdu, + p->length, + p->data, + &block)) { + goto internal_issue; + } + if (i + 1 < request_cnt) { + coap_ticks(&p->last_sent); + coap_send_internal(session, out_pdu); + } + } + coap_ticks(&p->last_payload); + goto skip_app_handler; + + } /* end of LL_FOREACH() */ + return 0; + +internal_issue: + response->code = COAP_RESPONSE_CODE(500); + error_phrase = coap_response_phrase(response->code); + coap_add_data(response, strlen(error_phrase), + (const uint8_t *)error_phrase); + /* Keep in cache for 4 * ACK_TIMOUT incase of retry */ + if (p) + coap_ticks(&p->last_all_sent); + +skip_app_handler: + return 1; +} +#endif /* COAP_SERVER_SUPPORT */ + +static int +update_received_blocks(coap_rblock_t *rec_blocks, uint32_t block_num) { + uint32_t i; + + /* Reset as there is activity */ + rec_blocks->retry = 0; + + for (i = 0; i < rec_blocks->used; i++) { + if (block_num >= rec_blocks->range[i].begin && + block_num <= rec_blocks->range[i].end) + break; + + if (block_num < rec_blocks->range[i].begin) { + if (block_num + 1 == rec_blocks->range[i].begin) { + rec_blocks->range[i].begin = block_num; + } + else { + /* Need to insert a new range */ + if (rec_blocks->used == COAP_RBLOCK_CNT -1) + /* Too many losses */ + return 0; + memmove(&rec_blocks->range[i+1], &rec_blocks->range[i], + (rec_blocks->used - i) * sizeof (rec_blocks->range[0])); + rec_blocks->range[i].begin = rec_blocks->range[i].end = block_num; + rec_blocks->used++; + } + break; + } + if (block_num == rec_blocks->range[i].end + 1) { + rec_blocks->range[i].end = block_num; + if (i + 1 < rec_blocks->used) { + if (rec_blocks->range[i+1].begin == block_num + 1) { + /* Merge the 2 ranges */ + rec_blocks->range[i].end = rec_blocks->range[i+1].end; + if (i+2 < rec_blocks->used) { + memmove (&rec_blocks->range[i+1], &rec_blocks->range[i+2], + (rec_blocks->used - (i+2)) * sizeof (rec_blocks->range[0])); + } + rec_blocks->used--; + } + } + break; + } + } + if (i == rec_blocks->used) { + if (rec_blocks->used == COAP_RBLOCK_CNT -1) + /* Too many losses */ + return 0; + rec_blocks->range[i].begin = rec_blocks->range[i].end = block_num; + rec_blocks->used++; + } + coap_ticks(&rec_blocks->last_seen); + return 1; +} + +#if COAP_SERVER_SUPPORT +/* + * Need to check if this is a large PUT / POST using multiple blocks + * + * Server receiving PUT/POST etc. of a large amount of data (Block1) + * + * Return: 0 Call application handler + * 1 Do not call application handler - just send the built response + */ +int +coap_handle_request_put_block(coap_context_t *context, + coap_session_t *session, + coap_pdu_t *pdu, + coap_pdu_t *response, + coap_resource_t *resource, + coap_string_t *uri_path, + coap_opt_t *observe, + coap_string_t *query, + coap_method_handler_t h, + int *added_block) { + size_t length = 0; + const uint8_t *data = NULL; + size_t offset = 0; + size_t total = 0; + coap_block_b_t block; + coap_opt_iterator_t opt_iter; + uint16_t block_option = 0; + + coap_get_data_large(pdu, &length, &data, &offset, &total); + pdu->body_offset = 0; + pdu->body_total = length; + + if (coap_get_block_b(session, pdu, COAP_OPTION_BLOCK1, &block)) { + block_option = COAP_OPTION_BLOCK1; + } + if (block_option) { + coap_lg_srcv_t *p; + coap_opt_t *size_opt = coap_check_option(pdu, + COAP_OPTION_SIZE1, + &opt_iter); + coap_opt_t *fmt_opt = coap_check_option(pdu, + COAP_OPTION_CONTENT_FORMAT, + &opt_iter); + uint16_t fmt = fmt_opt ? coap_decode_var_bytes(coap_opt_value(fmt_opt), + coap_opt_length(fmt_opt)) : + COAP_MEDIATYPE_TEXT_PLAIN; + coap_opt_t *rtag_opt = coap_check_option(pdu, + COAP_OPTION_RTAG, + &opt_iter); + size_t rtag_length = rtag_opt ? coap_opt_length(rtag_opt) : 0; + const uint8_t *rtag = rtag_opt ? coap_opt_value(rtag_opt) : NULL; + + total = size_opt ? coap_decode_var_bytes(coap_opt_value(size_opt), + coap_opt_length(size_opt)) : 0; + offset = block.num << (block.szx + 4); + + LL_FOREACH(session->lg_srcv, p) { + if (rtag_opt || p->rtag_set == 1) { + if (!(rtag_opt && p->rtag_set == 1)) + continue; + if (p->rtag_length != rtag_length || + memcmp(p->rtag, rtag, rtag_length) != 0) + continue; + } + if (resource == p->resource) { + break; + } + if ((p->resource == context->unknown_resource || + resource == context->proxy_uri_resource) && + coap_string_equal(uri_path, p->uri_path)) + break; + } + if (!p && block.num != 0) { + /* random access - no need to track */ + pdu->body_data = data; + pdu->body_length = length; + pdu->body_offset = offset; + pdu->body_total = length + offset + (block.m ? 1 : 0); + } + /* Do not do this if this is a single block */ + else if (!p && !(offset == 0 && block.m == 0)) { + p = coap_malloc_type(COAP_LG_SRCV, sizeof(coap_lg_srcv_t)); + if (p == NULL) { + coap_add_data(response, sizeof("Memory issue")-1, + (const uint8_t *)"Memory issue"); + response->code = COAP_RESPONSE_CODE(500); + goto skip_app_handler; + } + coap_log(LOG_DEBUG, "** %s: lg_srcv %p initialized\n", + coap_session_str(session), (void*)p); + memset(p, 0, sizeof(coap_lg_srcv_t)); + coap_ticks(&p->last_used); + p->resource = resource; + if (resource == context->unknown_resource || + resource == context->proxy_uri_resource) + p->uri_path = coap_new_str_const(uri_path->s, uri_path->length); + p->content_format = fmt; + p->total_len = total; + p->amount_so_far = length; + p->szx = block.szx; + p->block_option = block_option; + if (observe) { + p->observe_length = min(coap_opt_length(observe), 3); + memcpy(p->observe, coap_opt_value(observe), p->observe_length); + p->observe_set = 1; + } + if (rtag_opt) { + p->rtag_length = (uint8_t)rtag_length; + memcpy(p->rtag, rtag, rtag_length); + p->rtag_set = 1; + } + p->body_data = NULL; + LL_PREPEND(session->lg_srcv, p); + } + if (p) { + if (fmt != p->content_format) { + coap_add_data(response, sizeof("Content-Format mismatch")-1, + (const uint8_t *)"Content-Format mismatch"); + response->code = COAP_RESPONSE_CODE(408); + goto free_lg_srcv; + } + p->last_mid = pdu->mid; + p->last_type = pdu->type; + memcpy(p->last_token, pdu->token, pdu->token_length); + p->last_token_length = pdu->token_length; + if ((session->block_mode & COAP_BLOCK_SINGLE_BODY) || block.bert) { + size_t chunk = (size_t)1 << (block.szx + 4); + int update_data = 0; + unsigned int saved_num = block.num; + size_t saved_offset = offset; + + while (offset < saved_offset + length) { + if (!check_if_received_block(&p->rec_blocks, block.num)) { + /* Update list of blocks received */ + if (!update_received_blocks(&p->rec_blocks, block.num)) { + coap_handle_event(context, COAP_EVENT_PARTIAL_BLOCK, session); + coap_add_data(response, sizeof("Too many missing blocks")-1, + (const uint8_t *)"Too many missing blocks"); + response->code = COAP_RESPONSE_CODE(408); + goto free_lg_srcv; + } + update_data = 1; + } + block.num++; + offset = block.num << (block.szx + 4); + } + block.num--; + if (update_data) { + /* Update saved data */ + p->body_data = coap_block_build_body(p->body_data, length, data, + saved_offset, p->total_len); + if (!p->body_data) + goto call_app_handler; + + } + if (block.m || + !check_all_blocks_in(&p->rec_blocks, + (uint32_t)(p->total_len + chunk -1)/chunk)) { + /* Not all the payloads of the body have arrived */ + if (block.m) { + uint8_t buf[4]; + + /* Ask for the next block */ + coap_insert_option(response, block_option, + coap_encode_var_safe(buf, sizeof(buf), + (saved_num << 4) | + (block.m << 3) | + block.aszx), + buf); + response->code = COAP_RESPONSE_CODE(231); + goto skip_app_handler; + } + goto skip_app_handler; + } + + /* + * Remove the Block1 option as passing all of the data to + * application layer. Add back in observe option if appropriate. + * Adjust all other information. + */ + if (p->observe_set) { + coap_update_option(pdu, COAP_OPTION_OBSERVE, + p->observe_length, p->observe); + } + coap_remove_option(pdu, block_option); + pdu->body_data = p->body_data->s; + pdu->body_length = p->total_len; + pdu->body_offset = 0; + pdu->body_total = p->total_len; + coap_log(LOG_DEBUG, "Server app version of updated PDU\n"); + coap_show_pdu(LOG_DEBUG, pdu); + coap_log(LOG_DEBUG, "call custom handler for resource '%*.*s'\n", + (int)resource->uri_path->length, + (int)resource->uri_path->length, resource->uri_path->s); + /* Need to do this here as we need to free off p */ + h(resource, session, pdu, query, response); + /* Check if lg_xmit generated and update PDU code if so */ + coap_check_code_lg_xmit(session, response, resource, query, pdu->code); + /* Check to see if the server is doing a 4.01 + Echo response */ + if (response->code == COAP_RESPONSE_CODE(401) && + coap_check_option(response, COAP_OPTION_ECHO, &opt_iter)) { + /* Need to keep lg_srcv around for client's response */ + goto skip_app_handler; + } else { + /* Last chunk - lg_srcv no longer needed */ + goto free_lg_srcv; + } + } + else { + /* No need to update body_data and body_length as a single PDU */ + pdu->body_offset = offset; + /* Exact match if last block */ + if (block.m) { + uint8_t buf[4]; + + if (total > offset + length + block.m) + pdu->body_total = total; + else + pdu->body_total = offset + length + block.m; + + coap_insert_option(response, block_option, + coap_encode_var_safe(buf, sizeof(buf), + (block.num << 4) | + (block.m << 3) | + block.aszx), + buf); + coap_log(LOG_DEBUG, "call custom handler for resource '%*.*s'\n", + (int)resource->uri_path->length, + (int)resource->uri_path->length, resource->uri_path->s); + h(resource, session, pdu, query, response); + /* Check if lg_xmit generated and update PDU code if so */ + coap_check_code_lg_xmit(session, response, resource, query, + pdu->code); + if (COAP_RESPONSE_CLASS(response->code) == 2) { + /* Just in case, as there are more to go */ + response->code = COAP_RESPONSE_CODE(231); + } + *added_block = 1; + goto skip_app_handler; + } + else { + pdu->body_total = offset + length + block.m; + } + } + + if (block.m == 0) { + /* Last chunk - free off all */ + coap_ticks(&p->last_used); + } + goto call_app_handler; + +free_lg_srcv: + LL_DELETE(session->lg_srcv, p); + coap_block_delete_lg_srcv(session, p); + goto skip_app_handler; + } + } +call_app_handler: + return 0; + +skip_app_handler: + return 1; +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +static int +check_freshness(coap_session_t *session, coap_pdu_t *rcvd, coap_pdu_t *sent, + coap_lg_xmit_t *lg_xmit, coap_lg_crcv_t *lg_crcv) +{ + /* Check for Echo option for freshness */ + coap_opt_iterator_t opt_iter; + coap_opt_t *opt = coap_check_option(rcvd, COAP_OPTION_ECHO, &opt_iter); + + if (opt) { + if (sent || lg_xmit || lg_crcv) { + /* Need to retransmit original request with Echo option added */ + coap_pdu_t *echo_pdu; + coap_mid_t mid; + const uint8_t *data; + size_t data_len; + int have_data = 0; + uint8_t ltoken[8]; + size_t ltoken_len; + uint64_t token; + + if (sent) { + if (coap_get_data(sent, &data_len, &data)) + have_data = 1; + } else if (lg_xmit) { + sent = &lg_xmit->pdu; + if (lg_xmit->length) { + size_t blk_size = (size_t)1 << (lg_xmit->blk_size + 4); + size_t offset = (lg_xmit->last_block + 1) * blk_size; + have_data = 1; + data = &lg_xmit->data[offset]; + data_len = (lg_xmit->length - offset) > blk_size ? blk_size : + lg_xmit->length - offset; + } + } else /* lg_crcv */ { + sent = &lg_crcv->pdu; + if (coap_get_data(sent, &data_len, &data)) + have_data = 1; + } + if (lg_xmit) { + token = STATE_TOKEN_FULL(lg_xmit->b.b1.state_token, + ++lg_xmit->b.b1.count); + } else { + token = STATE_TOKEN_FULL(lg_crcv->state_token, + ++lg_crcv->retry_counter); + } + ltoken_len = coap_encode_var_safe8(ltoken, sizeof(token), token); + echo_pdu = coap_pdu_duplicate(sent, session, ltoken_len, ltoken, NULL); + if (!echo_pdu) + return 0; + if (!coap_insert_option(echo_pdu, COAP_OPTION_ECHO, + coap_opt_length(opt), coap_opt_value(opt))) + goto not_sent; + if (have_data) { + coap_add_data(echo_pdu, data_len, data); + } + + mid = coap_send_internal(session, echo_pdu); + if (mid == COAP_INVALID_MID) + goto not_sent; + return 1; + } else { + /* Need to save Echo option value to add to next reansmission */ +not_sent: + coap_delete_bin_const(session->echo); + session->echo = coap_new_bin_const(coap_opt_value(opt), + coap_opt_length(opt)); + } + } + return 0; +} + +static void +track_echo(coap_session_t *session, coap_pdu_t *rcvd) +{ + coap_opt_iterator_t opt_iter; + coap_opt_t *opt = coap_check_option(rcvd, COAP_OPTION_ECHO, &opt_iter); + + if (opt) { + coap_delete_bin_const(session->echo); + session->echo = coap_new_bin_const(coap_opt_value(opt), + coap_opt_length(opt)); + } +} + +/* + * Need to see if this is a response to a large body request transfer. If so, + * need to initiate the request containing the next block and not trouble the + * application. Note that Token must unique per request/response. + * + * Client receives large data acknowledgement from server (Block1) + * + * This is set up using coap_add_data_large_request() + * + * Client is using GET etc. + * + * Return: 0 Call application handler + * 1 Do not call application handler - just send the built response + */ +int +coap_handle_response_send_block(coap_session_t *session, coap_pdu_t *sent, + coap_pdu_t *rcvd) { + coap_lg_xmit_t *p; + coap_lg_xmit_t *q; + uint64_t token_match = STATE_TOKEN_BASE(coap_decode_var_bytes8(rcvd->token, + rcvd->token_length)); + coap_lg_crcv_t *lg_crcv = NULL; + + LL_FOREACH_SAFE(session->lg_xmit, p, q) { + if (!COAP_PDU_IS_REQUEST(&p->pdu) || + (token_match != STATE_TOKEN_BASE(p->b.b1.state_token) && + token_match != + STATE_TOKEN_BASE(coap_decode_var_bytes8(p->b.b1.app_token->s, + p->b.b1.app_token->length)))) { + /* try out the next one */ + continue; + } + /* lg_xmit found */ + size_t chunk = (size_t)1 << (p->blk_size + 4); + coap_block_b_t block; + + if (COAP_RESPONSE_CLASS(rcvd->code) == 2 && + coap_get_block_b(session, rcvd, p->option, &block)) { + + if (block.bert) { + coap_log(LOG_DEBUG, + "found Block option, block is BERT, block nr. %u (%zu)\n", + block.num, p->b.b1.bert_size); + } else { + coap_log(LOG_DEBUG, + "found Block option, block size is %u, block nr. %u\n", + 1 << (block.szx + 4), block.num); + } + if (block.szx != p->blk_size) { + if ((p->offset + chunk) % ((size_t)1 << (block.szx + 4)) == 0) { + /* + * Recompute the block number of the previous packet given the + * new block size + */ + block.num = (uint32_t)(((p->offset + chunk) >> (block.szx + 4)) - 1); + p->blk_size = block.szx; + chunk = (size_t)1 << (p->blk_size + 4); + p->offset = block.num * chunk; + coap_log(LOG_DEBUG, + "new Block size is %u, block number %u completed\n", + 1 << (block.szx + 4), block.num); + block.bert = 0; + block.aszx = block.szx; + } else { + coap_log(LOG_DEBUG, "ignoring request to increase Block size, " + "next block is not aligned on requested block size boundary. " + "(%zu x %u mod %u = %zu != 0)\n", + p->offset/chunk + 1, (1 << (p->blk_size + 4)), + (1 << (block.szx + 4)), + (p->offset + chunk) % ((size_t)1 << (block.szx + 4))); + } + } + track_echo(session, rcvd); + if (p->last_block == (int)block.num) { + /* + * Duplicate Block1 ACK + * + * RFCs not clear here, but on a lossy connection, there could + * be multiple Block1 ACKs, causing the client to retransmit the + * same block multiple times, or the server retransmitting the + * same ACK. + * + * Once a block has been ACKd, there is no need to retransmit it. + */ + return 1; + } + if (block.bert) + block.num += (unsigned int)(p->b.b1.bert_size / 1024 - 1); + p->last_block = block.num; + p->offset = (block.num + 1) * chunk; + if (p->offset < p->length) { + /* Build the next PDU request based off the skeletal PDU */ + uint8_t buf[8]; + coap_pdu_t *pdu; + uint64_t token = STATE_TOKEN_FULL(p->b.b1.state_token, ++p->b.b1.count); + size_t len = coap_encode_var_safe8(buf, sizeof(token), token); + + pdu = coap_pdu_duplicate(&p->pdu, session, len, buf, NULL); + if (!pdu) + goto fail_body; + + block.num++; + if (block.bert) { + size_t token_options = pdu->data ? (size_t)(pdu->data - pdu->token) : pdu->used_size; + block.m = (p->length - p->offset) > + ((pdu->max_size - token_options) /1024) * 1024; + } else { + block.m = (p->offset + chunk) < p->length; + } + coap_update_option(pdu, p->option, + coap_encode_var_safe(buf, sizeof(buf), + (block.num << 4) | + (block.m << 3) | + block.aszx), + buf); + + if (!coap_add_block_b_data(pdu, + p->length, + p->data, + &block)) + goto fail_body; + p->b.b1.bert_size = block.chunk_size; + coap_ticks(&p->last_sent); + if (coap_send_internal(session, pdu) == COAP_INVALID_MID) + goto fail_body; + return 1; + } + } else if (rcvd->code == COAP_RESPONSE_CODE(401)) { + if (check_freshness(session, rcvd, sent, p, NULL)) + return 1; + } + goto lg_xmit_finished; + } /* end of LL_FOREACH_SAFE */ + return 0; + +fail_body: + coap_handle_event(session->context, COAP_EVENT_XMIT_BLOCK_FAIL, session); + /* There has been an internal error of some sort */ + rcvd->code = COAP_RESPONSE_CODE(500); +lg_xmit_finished: + if (session->lg_crcv) { + LL_FOREACH(session->lg_crcv, lg_crcv) { + if (STATE_TOKEN_BASE(p->b.b1.state_token) == + STATE_TOKEN_BASE(lg_crcv->state_token)) { + /* In case of observe */ + lg_crcv->state_token = p->b.b1.state_token; + break; + } + } + } + if (!lg_crcv) { + /* need to put back original token into rcvd */ + if (p->b.b1.app_token) + coap_update_token(rcvd, p->b.b1.app_token->length, + p->b.b1.app_token->s); + coap_log(LOG_DEBUG, "PDU given to app\n"); + coap_show_pdu(LOG_DEBUG, rcvd); + } + + LL_DELETE(session->lg_xmit, p); + coap_block_delete_lg_xmit(session, p); + return 0; +} +#endif /* COAP_CLIENT_SUPPORT */ + +/* + * Re-assemble payloads into a body + */ +coap_binary_t * +coap_block_build_body(coap_binary_t *body_data, size_t length, + const uint8_t *data, size_t offset, size_t total) +{ + if (data == NULL) + return NULL; + if (body_data == NULL && total) { + body_data = coap_new_binary(total); + } + if (body_data == NULL) + return NULL; + + /* Update saved data */ + if (offset + length <= total && body_data->length >= total) { + memcpy(&body_data->s[offset], data, length); + } + else { + /* + * total may be inaccurate as per + * https://tools.ietf.org/html/rfc7959#section-4 + * o In a request carrying a Block1 Option, to indicate the current + * estimate the client has of the total size of the resource + * representation, measured in bytes ("size indication"). + * o In a response carrying a Block2 Option, to indicate the current + * estimate the server has of the total size of the resource + * representation, measured in bytes ("size indication"). + */ + coap_binary_t *new = coap_resize_binary(body_data, offset + length); + + if (new) { + body_data = new; + memcpy(&body_data->s[offset], data, length); + } + else { + coap_delete_binary(body_data); + return NULL; + } + } + return body_data; +} + +#if COAP_CLIENT_SUPPORT +/* + * Need to see if this is a large body response to a request. If so, + * need to initiate the request for the next block and not trouble the + * application. Note that Token must be unique per request/response. + * + * This is set up using coap_send() + * Client receives large data from server (Block2) + * + * Return: 0 Call application handler + * 1 Do not call application handler - just sent the next request + */ +int +coap_handle_response_get_block(coap_context_t *context, + coap_session_t *session, + coap_pdu_t *sent, + coap_pdu_t *rcvd, + coap_recurse_t recursive) { + coap_lg_crcv_t *p; + int app_has_response = 0; + coap_block_b_t block; + int have_block = 0; + uint16_t block_opt = 0; + size_t offset; + uint64_t token_match = STATE_TOKEN_BASE(coap_decode_var_bytes8(rcvd->token, + rcvd->token_length)); + + memset(&block, 0, sizeof(block)); + LL_FOREACH(session->lg_crcv, p) { + size_t chunk = 0; + uint8_t buf[8]; + coap_opt_iterator_t opt_iter; + + if (token_match != STATE_TOKEN_BASE(p->state_token) && + !full_match(rcvd->token, rcvd->token_length, + p->app_token->s, p->app_token->length)) { + /* try out the next one */ + continue; + } + + /* lg_crcv found */ + + if (COAP_RESPONSE_CLASS(rcvd->code) == 2) { + size_t length; + const uint8_t *data; + coap_opt_t *size_opt = coap_check_option(rcvd, COAP_OPTION_SIZE2, + &opt_iter); + size_t size2 = size_opt ? + coap_decode_var_bytes(coap_opt_value(size_opt), + coap_opt_length(size_opt)) : 0; + + /* length and data are cleared on error */ + (void)coap_get_data(rcvd, &length, &data); + rcvd->body_offset = 0; + rcvd->body_total = length; + if (coap_get_block_b(session, rcvd, COAP_OPTION_BLOCK2, &block)) { + have_block = 1; + block_opt = COAP_OPTION_BLOCK2; + } + track_echo(session, rcvd); + if (have_block && (block.m || length)) { + coap_opt_t *fmt_opt = coap_check_option(rcvd, + COAP_OPTION_CONTENT_FORMAT, + &opt_iter); + uint16_t fmt = fmt_opt ? + coap_decode_var_bytes(coap_opt_value(fmt_opt), + coap_opt_length(fmt_opt)) : + COAP_MEDIATYPE_TEXT_PLAIN; + coap_opt_t *etag_opt = coap_check_option(rcvd, + COAP_OPTION_ETAG, + &opt_iter); + size_t saved_offset; + int updated_block; + + /* Possibility that Size2 not sent, or is too small */ + chunk = (size_t)1 << (block.szx + 4); + offset = block.num * chunk; + if (size2 < (offset + length)) { + if (block.m) + size2 = offset + length + 1; + else + size2 = offset + length; + } + saved_offset = offset; + + if (p->initial) { + p->initial = 0; + if (etag_opt) { + p->etag_length = coap_opt_length(etag_opt); + memcpy(p->etag, coap_opt_value(etag_opt), p->etag_length); + p->etag_set = 1; + } + else { + p->etag_set = 0; + } + p->total_len = size2; + p->content_format = fmt; + p->szx = block.szx; + p->block_option = block_opt; + p->last_type = rcvd->type; + p->rec_blocks.used = 0; + } + if (p->total_len < size2) + p->total_len = size2; + + if (etag_opt) { + if (!full_match(coap_opt_value(etag_opt), + coap_opt_length(etag_opt), + p->etag, p->etag_length)) { + /* body of data has changed - need to restart request */ + coap_pdu_t *pdu; + uint64_t token = STATE_TOKEN_FULL(p->state_token, + ++p->retry_counter); + size_t len = coap_encode_var_safe8(buf, sizeof(token), token); + coap_opt_filter_t drop_options; + + coap_log(LOG_WARNING, + "Data body updated during receipt - new request started\n"); + if (!(session->block_mode & COAP_BLOCK_SINGLE_BODY)) + coap_handle_event(context, COAP_EVENT_PARTIAL_BLOCK, session); + + p->initial = 1; + coap_free_type(COAP_STRING, p->body_data); + p->body_data = NULL; + + coap_session_new_token(session, &len, buf); + memset(&drop_options, 0, sizeof(coap_opt_filter_t)); + coap_option_filter_set(&drop_options, COAP_OPTION_OBSERVE); + pdu = coap_pdu_duplicate(&p->pdu, session, len, buf, &drop_options); + if (!pdu) + goto fail_resp; + + coap_update_option(pdu, block_opt, + coap_encode_var_safe(buf, sizeof(buf), + (0 << 4) | (0 << 3) | block.aszx), + buf); + + if (coap_send_internal(session, pdu) == COAP_INVALID_MID) + goto fail_resp; + + goto skip_app_handler; + } + } + else if (p->etag_set) { + /* Cannot handle this change in ETag to not being there */ + coap_log(LOG_WARNING, "Not all blocks have ETag option\n"); + session->block_mode &= ~(COAP_BLOCK_SINGLE_BODY); + goto block_mode; + } + + if (fmt != p->content_format) { + coap_log(LOG_WARNING, "Content-Format option mismatch\n"); + session->block_mode &= ~(COAP_BLOCK_SINGLE_BODY); + goto block_mode; + } + if (block.num == 0) { + coap_opt_t *obs_opt = coap_check_option(rcvd, + COAP_OPTION_OBSERVE, + &opt_iter); + if (obs_opt) { + p->observe_length = min(coap_opt_length(obs_opt), 3); + memcpy(p->observe, coap_opt_value(obs_opt), p->observe_length); + p->observe_set = 1; + /* Need to keep observe response token for later cancellation */ + coap_delete_binary(p->obs_token); + p->obs_token = coap_new_binary(rcvd->token_length); + if (!p->obs_token) { + goto fail_resp; + } + memcpy(p->obs_token->s, rcvd->token, rcvd->token_length); + } + else { + p->observe_set = 0; + } + } + updated_block = 0; + while (offset < saved_offset + length) { + if (!check_if_received_block(&p->rec_blocks, block.num)) { + /* Update list of blocks received */ + if (!update_received_blocks(&p->rec_blocks, block.num)) { + coap_handle_event(context, COAP_EVENT_PARTIAL_BLOCK, session); + goto fail_resp; + } + updated_block = 1; + } + block.num++; + offset = block.num << (block.szx + 4); + if (!block.bert) + break; + } + block.num--; + if (updated_block) { + if ((session->block_mode & COAP_BLOCK_SINGLE_BODY) || block.bert) { + p->body_data = coap_block_build_body(p->body_data, length, data, + saved_offset, size2); + if (p->body_data == NULL) { + /* Need to do it block by block */ + session->block_mode &= ~(COAP_BLOCK_SINGLE_BODY); + goto block_mode; + } + } + if (block.m || !check_all_blocks_in(&p->rec_blocks, + (size2 + chunk -1) / chunk)) { + /* Not all the payloads of the body have arrived */ + size_t len; + coap_pdu_t *pdu; + uint64_t token; + + if (block.m) { + block.m = 0; + + /* Ask for the next block */ + token = STATE_TOKEN_FULL(p->state_token, ++p->retry_counter); + len = coap_encode_var_safe8(buf, sizeof(token), token); + pdu = coap_pdu_duplicate(&p->pdu, session, len, buf, NULL); + if (!pdu) + goto fail_resp; + + if (rcvd->type == COAP_MESSAGE_NON) + pdu->type = COAP_MESSAGE_NON; /* Server is using NON */ + + /* Only sent with the first block */ + coap_remove_option(pdu, COAP_OPTION_OBSERVE); + + coap_update_option(pdu, block_opt, + coap_encode_var_safe(buf, sizeof(buf), + ((block.num + 1) << 4) | + (block.m << 3) | block.aszx), + buf); + + if (coap_send_internal(session, pdu) == COAP_INVALID_MID) + goto fail_resp; + } + if (session->block_mode & (COAP_BLOCK_SINGLE_BODY) || block.bert) + goto skip_app_handler; + + /* need to put back original token into rcvd */ + coap_update_token(rcvd, p->app_token->length, p->app_token->s); + rcvd->body_offset = saved_offset; + rcvd->body_total = size2; + goto call_app_handler; + } + /* need to put back original token into rcvd */ + coap_update_token(rcvd, p->app_token->length, p->app_token->s); + if (session->block_mode & (COAP_BLOCK_SINGLE_BODY) || block.bert) { + /* Pretend that there is no block */ + coap_remove_option(rcvd, block_opt); + if (p->observe_set) { + coap_update_option(rcvd, COAP_OPTION_OBSERVE, + p->observe_length, p->observe); + } + rcvd->body_data = p->body_data->s; + rcvd->body_length = saved_offset + length; + rcvd->body_offset = 0; + rcvd->body_total = rcvd->body_length; + } + else { + rcvd->body_offset = saved_offset; + rcvd->body_total = size2; + } + if (context->response_handler) { + if (block.m != 0 || block.num != 0) { + coap_log(LOG_DEBUG, "Client app version of updated PDU\n"); + coap_show_pdu(LOG_DEBUG, rcvd); + } + context->response_handler(session, sent, rcvd, rcvd->mid); + } + app_has_response = 1; + /* Set up for the next data body if observing */ + p->initial = 1; + if (p->body_data) { + coap_free_type(COAP_STRING, p->body_data); + p->body_data = NULL; + } + else { + goto skip_app_handler; + } + } + else { +block_mode: + /* need to put back original token into rcvd */ + coap_update_token(rcvd, p->app_token->length, p->app_token->s); + rcvd->body_offset = saved_offset; + /* slightly oversize if there is more data */ + if (block.m) { + if(size2 > saved_offset + length + block.m) + rcvd->body_total = size2; + else + rcvd->body_total = saved_offset + length + block.m; + } + else { + rcvd->body_total = saved_offset + length; + /* Set up for the next data body if observing */ + p->initial = 1; + } + if (context->response_handler) { + coap_log(LOG_DEBUG, "Client app version of updated PDU\n"); + coap_show_pdu(LOG_DEBUG, rcvd); + context->response_handler(session, sent, rcvd, rcvd->mid); + } + app_has_response = 1; + } + } + else { + coap_opt_t *obs_opt = coap_check_option(rcvd, + COAP_OPTION_OBSERVE, + &opt_iter); + if (obs_opt) { + p->observe_length = min(coap_opt_length(obs_opt), 3); + memcpy(p->observe, coap_opt_value(obs_opt), p->observe_length); + p->observe_set = 1; + /* Need to keep observe response token for later cancellation */ + coap_delete_binary(p->obs_token); + p->obs_token = coap_new_binary(rcvd->token_length); + if (!p->obs_token) { + goto fail_resp; + } + memcpy(p->obs_token->s, rcvd->token, rcvd->token_length); + } + else { + p->observe_set = 0; + /* Expire this entry */ + goto expire_lg_crcv; + } + } + coap_ticks(&p->last_used); + } else if (rcvd->code == COAP_RESPONSE_CODE(401)) { + if (check_freshness(session, rcvd, sent, NULL, p)) + goto skip_app_handler; + goto expire_lg_crcv; + } else { + /* Not 2.xx or 4.01 - assume it is a failure of some sort */ + goto expire_lg_crcv; + } + if (!block.m && !p->observe_set) { +fail_resp: + /* lg_crcv no longer required - cache it for 1 sec */ + coap_ticks(&p->last_used); + p->last_used = p->last_used - COAP_MAX_TRANSMIT_WAIT_TICKS(session) + + COAP_TICKS_PER_SECOND; + } + /* need to put back original token into rcvd */ + coap_update_token(rcvd, p->app_token->length, p->app_token->s); + break; + } /* LL_FOREACH() */ + + /* Check if receiving a block response and if blocks can be set up */ + if (recursive == COAP_RECURSE_OK && !p) { + if (!sent) { + if (coap_get_block_b(session, rcvd, COAP_OPTION_BLOCK2, &block)) { + coap_log(LOG_DEBUG, "** %s: large body receive internal issue\n", + coap_session_str(session)); + goto skip_app_handler; + } + } + else if (COAP_RESPONSE_CLASS(rcvd->code) == 2) { + if (coap_get_block_b(session, rcvd, COAP_OPTION_BLOCK2, &block)) { + have_block = 1; + block_opt = COAP_OPTION_BLOCK2; + if (block.num != 0) { + /* Assume random access and just give the single response to app */ + size_t length; + const uint8_t *data; + size_t chunk = (size_t)1 << (block.szx + 4); + + coap_get_data(rcvd, &length, &data); + rcvd->body_offset = block.num*chunk; + rcvd->body_total = block.num*chunk + length + (block.m ? 1 : 0); + goto call_app_handler; + } + } + if (have_block) { + coap_lg_crcv_t *lg_crcv = coap_block_new_lg_crcv(session, sent); + + if (lg_crcv) { + uint8_t buf[8]; + size_t length = coap_encode_var_safe8(buf, + sizeof(lg_crcv->state_token), + lg_crcv->state_token); + if (coap_update_token(rcvd, length, buf)) { + LL_PREPEND(session->lg_crcv, lg_crcv); + return coap_handle_response_get_block(context, session, sent, rcvd, + COAP_RECURSE_NO); + } + coap_block_delete_lg_crcv(session, lg_crcv); + } + } + track_echo(session, rcvd); + } else if (rcvd->code == COAP_RESPONSE_CODE(401)) { + coap_lg_crcv_t *lg_crcv = coap_block_new_lg_crcv(session, sent); + + if (lg_crcv) { + LL_PREPEND(session->lg_crcv, lg_crcv); + return coap_handle_response_get_block(context, session, sent, rcvd, + COAP_RECURSE_NO); + } + } + } + return app_has_response; + +expire_lg_crcv: + /* need to put back original token into rcvd */ + coap_update_token(rcvd, p->app_token->length, p->app_token->s); + /* Expire this entry */ + LL_DELETE(session->lg_crcv, p); + coap_block_delete_lg_crcv(session, p); + +call_app_handler: + return 0; + +skip_app_handler: + return 1; +} +#endif /* COAP_CLIENT_SUPPORT */ + +/* Check if lg_xmit generated and update PDU code if so */ +void +coap_check_code_lg_xmit(coap_session_t *session, coap_pdu_t *response, + coap_resource_t *resource, coap_string_t *query, + coap_pdu_code_t request_method) { + coap_lg_xmit_t *lg_xmit; + coap_string_t empty = { 0, NULL}; + + if (response->code == 0) + return; + LL_FOREACH(session->lg_xmit, lg_xmit) { + if (!COAP_PDU_IS_REQUEST(&lg_xmit->pdu) && + lg_xmit->b.b2.resource == resource && + lg_xmit->b.b2.request_method == request_method && + coap_string_equal(query ? query : &empty, + lg_xmit->b.b2.query ? lg_xmit->b.b2.query : &empty)) { + /* lg_xmit found */ + if (lg_xmit->pdu.code == 0) { + lg_xmit->pdu.code = response->code; + return; + } + } + } +} diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_address.c b/examples/espidf-coap-server/components/libcoap/src/coap_address.c new file mode 100644 index 000000000..5aa257a19 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_address.c @@ -0,0 +1,115 @@ +/* coap_address.c -- representation of network addresses + * + * Copyright (C) 2015-2016,2019-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_address.c + * @brief Handling of network addresses + */ + +#include "coap3/coap_internal.h" + +#if !defined(WITH_CONTIKI) && !defined(WITH_LWIP) +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +#ifdef RIOT_VERSION +/* FIXME */ +#define IN_MULTICAST(Address) (0) +#endif /* RIOT_VERSION */ + +uint16_t +coap_address_get_port(const coap_address_t *addr) { + assert(addr != NULL); + switch (addr->addr.sa.sa_family) { + case AF_INET: return ntohs(addr->addr.sin.sin_port); + case AF_INET6: return ntohs(addr->addr.sin6.sin6_port); + default: /* undefined */ + ; + } + return 0; +} + +void +coap_address_set_port(coap_address_t *addr, uint16_t port) { + assert(addr != NULL); + switch (addr->addr.sa.sa_family) { + case AF_INET: + addr->addr.sin.sin_port = htons(port); + break; + case AF_INET6: + addr->addr.sin6.sin6_port = htons(port); + break; + default: /* undefined */ + ; + } +} + +int +coap_address_equals(const coap_address_t *a, const coap_address_t *b) { + assert(a); assert(b); + + if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family) + return 0; + + /* need to compare only relevant parts of sockaddr_in6 */ + switch (a->addr.sa.sa_family) { + case AF_INET: + return + a->addr.sin.sin_port == b->addr.sin.sin_port && + memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr, + sizeof(struct in_addr)) == 0; + case AF_INET6: + return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port && + memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr, + sizeof(struct in6_addr)) == 0; + default: /* fall through and signal error */ + ; + } + return 0; +} + +int coap_is_mcast(const coap_address_t *a) { + if (!a) + return 0; + + switch (a->addr.sa.sa_family) { + case AF_INET: + return IN_MULTICAST(ntohl(a->addr.sin.sin_addr.s_addr)); + case AF_INET6: + return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr) || + (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr) && + IN_MULTICAST(ntohl(a->addr.sin6.sin6_addr.s6_addr[12]))); + default: /* fall through and signal error */ + ; + } + return 0; +} + +#endif /* !defined(WITH_CONTIKI) && !defined(WITH_LWIP) */ + +void coap_address_init(coap_address_t *addr) { + assert(addr); + memset(addr, 0, sizeof(coap_address_t)); +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) + /* lwip and Contiki have constant address sizes and don't need the .size part */ + addr->size = sizeof(addr->addr); +#endif +} + diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_asn1.c b/examples/espidf-coap-server/components/libcoap/src/coap_asn1.c new file mode 100644 index 000000000..ee2263f7a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_asn1.c @@ -0,0 +1,107 @@ +/* coap_asn1.c -- ASN.1 handling functions +* +* Copyright (C) 2020 Jon Shallow +* + * SPDX-License-Identifier: BSD-2-Clause + * +* This file is part of the CoAP library libcoap. Please see +* README for terms of use. +*/ + +/** + * @file coap_asn1.c + * @brief CoAP specific ASN.1 handling + */ + +#include "coap3/coap_internal.h" + +size_t +asn1_len(const uint8_t **ptr) +{ + size_t len = 0; + + if ((**ptr) & 0x80) { + size_t octets = (**ptr) & 0x7f; + (*ptr)++; + while (octets) { + len = (len << 8) + (**ptr); + (*ptr)++; + octets--; + } + } + else { + len = (**ptr) & 0x7f; + (*ptr)++; + } + return len; +} + +coap_asn1_tag_t +asn1_tag_c(const uint8_t **ptr, int *constructed, int *class) +{ + coap_asn1_tag_t tag = 0; + uint8_t byte; + + byte = (**ptr); + *constructed = (byte & 0x20) ? 1 : 0; + *class = byte >> 6; + tag = byte & 0x1F; + (*ptr)++; + if (tag < 0x1F) + return tag; + + /* Tag can be one byte or more based on B8 */ + byte = (**ptr); + while (byte & 0x80) { + tag = (tag << 7) + (byte & 0x7F); + (*ptr)++; + byte = (**ptr); + } + /* Do the final one */ + tag = (tag << 7) + (byte & 0x7F); + (*ptr)++; + return tag; +} + +/* caller must free off returned coap_binary_t* */ +coap_binary_t * +get_asn1_tag(coap_asn1_tag_t ltag, const uint8_t *ptr, size_t tlen, + asn1_validate validate) +{ + int constructed; + int class; + const uint8_t *acp = ptr; + uint8_t tag = asn1_tag_c(&acp, &constructed, &class); + size_t len = asn1_len(&acp); + coap_binary_t *tag_data; + + while (tlen > 0 && len <= tlen) { + if (class == 2 && constructed == 1) { + /* Skip over element description */ + tag = asn1_tag_c(&acp, &constructed, &class); + len = asn1_len(&acp); + } + if (tag == ltag) { + if (!validate || validate(acp, len)) { + tag_data = coap_new_binary(len); + if (tag_data == NULL) + return NULL; + tag_data->length = len; + memcpy(tag_data->s, acp, len); + return tag_data; + } + } + if (tag == 0x10 && constructed == 1) { + /* SEQUENCE or SEQUENCE OF */ + tag_data = get_asn1_tag(ltag, acp, len, validate); + if (tag_data) + return tag_data; + } + acp += len; + tlen -= len; + tag = asn1_tag_c(&acp, &constructed, &class); + len = asn1_len(&acp); + } + return NULL; +} + diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_async.c b/examples/espidf-coap-server/components/libcoap/src/coap_async.c new file mode 100644 index 000000000..5c7cce4d1 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_async.c @@ -0,0 +1,237 @@ +/* coap_async.c -- state management for asynchronous messages + * + * Copyright (C) 2010,2011,2021-2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_async.c + * @brief State handling for asynchronous messages + */ + +#include "coap3/coap_internal.h" + +#ifndef WITHOUT_ASYNC +#include + +/* utlist-style macros for searching pairs in linked lists */ +#define SEARCH_PAIR(head,out,field1,val1,field2,val2,field3,val3) \ + SEARCH_PAIR3(head,out,field1,val1,field2,val2,field3,val3,next) + +#define SEARCH_PAIR3(head,out,field1,val1,field2,val2,field3,val3,next) \ + do { \ + LL_FOREACH2(head,out,next) { \ + if ((out)->field1 == (val1) && (out)->field2 == (val2) && \ + ((val2) == 0 || memcmp((out)->field3, (val3), (val2)) == 0)) break; \ + } \ +} while(0) + +int +coap_async_is_supported(void) { + return 1; +} + +coap_async_t * +coap_register_async(coap_session_t *session, + const coap_pdu_t *request, coap_tick_t delay) { + coap_async_t *s; + size_t len; + const uint8_t *data; + + if (!COAP_PDU_IS_REQUEST(request)) + return NULL; + + SEARCH_PAIR(session->context->async_state, s, + session, session, + pdu->token_length, request->token_length, + pdu->token, request->token); + + if (s != NULL) { + size_t i; + char outbuf[2*8 + 1]; + size_t outbuflen; + + outbuf[0] = '\000'; + for (i = 0; i < request->token_length; i++) { + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, + "%02x", request->token[i]); + } + coap_log(LOG_DEBUG, + "asynchronous state for token '%s' already registered\n", outbuf); + return NULL; + } + + /* store information for handling the asynchronous task */ + s = (coap_async_t *)coap_malloc(sizeof(coap_async_t)); + if (!s) { + coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n"); + return NULL; + } + + memset(s, 0, sizeof(coap_async_t)); + + /* Note that this generates a new MID */ + s->pdu = coap_pdu_duplicate(request, session, request->token_length, + request->token, NULL); + if (s->pdu == NULL) { + coap_free_async(session, s); + coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n"); + return NULL; + } + + if (coap_get_data(request, &len, &data)) { + coap_add_data(s->pdu, len, data); + } + + s->session = coap_session_reference( session ); + + coap_async_set_delay(s, delay); + + LL_PREPEND(session->context->async_state, s); + + return s; +} + +void +coap_async_trigger(coap_async_t *async) { + assert(async != NULL); + coap_ticks(&async->delay); + + coap_log(LOG_DEBUG, " %s: Async request triggered\n", + coap_session_str(async->session)); +#ifdef COAP_EPOLL_SUPPORT + coap_update_epoll_timer(async->session->context, 0); +#endif /* COAP_EPOLL_SUPPORT */ +} + + +void +coap_async_set_delay(coap_async_t *async, coap_tick_t delay) { + coap_tick_t now; + + assert(async != NULL); + coap_ticks(&now); + + if (delay) { + async->delay = now + delay; +#ifdef COAP_EPOLL_SUPPORT + coap_update_epoll_timer(async->session->context, delay); +#endif /* COAP_EPOLL_SUPPORT */ + coap_log(LOG_DEBUG, " %s: Async request delayed for %u.%03u secs\n", + coap_session_str(async->session), + (unsigned int)(delay / COAP_TICKS_PER_SECOND), + (unsigned int)((delay % COAP_TICKS_PER_SECOND) * + 1000 / COAP_TICKS_PER_SECOND)); + } + else { + async->delay = 0; + coap_log(LOG_DEBUG, " %s: Async request indefinately delayed\n", + coap_session_str(async->session)); + } +} + +coap_async_t * +coap_find_async(coap_session_t *session, coap_bin_const_t token) { + coap_async_t *tmp; + SEARCH_PAIR(session->context->async_state, tmp, + session, session, + pdu->token_length, token.length, + pdu->token, token.s); + return tmp; +} + +static void +coap_free_async_sub(coap_context_t *context, coap_async_t *s) { + if (s) { + LL_DELETE(context->async_state,s); + if (s->session) { + coap_session_release(s->session); + } + if (s->pdu) { + coap_delete_pdu(s->pdu); + s->pdu = NULL; + } + coap_free(s); + } +} + +void +coap_free_async(coap_session_t *session, coap_async_t *s) { + coap_free_async_sub(session->context, s); +} + +void +coap_delete_all_async(coap_context_t *context) { + coap_async_t *astate, *tmp; + + LL_FOREACH_SAFE(context->async_state, astate, tmp) { + coap_free_async_sub(context, astate); + } + context->async_state = NULL; +} + +void +coap_async_set_app_data(coap_async_t *async, void *app_data) { + async->appdata = app_data; +} + +void * +coap_async_get_app_data(const coap_async_t *async) { + return async->appdata; +} + +#else /* WITHOUT_ASYNC */ + +int +coap_async_is_supported(void) { + return 0; +} + +coap_async_t * +coap_register_async(coap_session_t *session, + const coap_pdu_t *request, + coap_tick_t delay) { + (void)session; + (void)request; + (void)delay; + return NULL; +} + +void +coap_async_set_delay(coap_async_t *async, coap_tick_t delay) { + (void)async; + (void)delay; +} + +void +coap_free_async(coap_session_t *session, coap_async_t *async) { + (void)session; + (void)async; +} + +coap_async_t * +coap_find_async(coap_session_t *session, + coap_bin_const_t token) { + (void)session; + (void)token; + return NULL; +} + +void +coap_async_set_app_data(coap_async_t *async, void *app_data) { + (void)async; + (void)app_data; +} + +void * +coap_async_get_app_data(const coap_async_t *async) { + (void)async; + return NULL; +} + +#endif /* WITHOUT_ASYNC */ diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_cache.c b/examples/espidf-coap-server/components/libcoap/src/coap_cache.c new file mode 100644 index 000000000..211d7cebb --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_cache.c @@ -0,0 +1,281 @@ +/* coap_cache.c -- Caching of CoAP requests +* +* Copyright (C) 2020 Olaf Bergmann +* + * SPDX-License-Identifier: BSD-2-Clause + * +* This file is part of the CoAP library libcoap. Please see +* README for terms of use. +*/ + +/** + * @file coap_cache.c + * @brief CoAP Cache handling + */ + +#include "coap3/coap_internal.h" + +#if COAP_SERVER_SUPPORT +/* Determines if the given option_type denotes an option type that can + * be used as CacheKey. Options that can be cache keys are not Unsafe + * and not marked explicitly as NoCacheKey. */ +static int +is_cache_key(uint16_t option_type, size_t cache_ignore_count, + const uint16_t *cache_ignore_options) { + size_t i; + + /* https://tools.ietf.org/html/rfc7252#section-5.4.6 Nocachekey definition */ + if ((option_type & 0x1e) == 0x1c) + return 0; + /* + * https://tools.ietf.org/html/rfc7641#section-2 Observe is not a + * part of the cache-key. + */ + if (option_type == COAP_OPTION_OBSERVE) + return 0; + + /* Check for option user has defined as not part of cache-key */ + for (i = 0; i < cache_ignore_count; i++) { + if (cache_ignore_options[i] == option_type) { + return 0; + } + } + + return 1; +} + +int +coap_cache_ignore_options(coap_context_t *ctx, + const uint16_t *options, + size_t count) { + if (ctx->cache_ignore_options) { + coap_free(ctx->cache_ignore_options); + } + if (count) { + assert(options); + ctx->cache_ignore_options = coap_malloc(count * sizeof(options[0])); + if (ctx->cache_ignore_options) { + memcpy(ctx->cache_ignore_options, options, count * sizeof(options[0])); + ctx->cache_ignore_count = count; + } + else { + coap_log(LOG_WARNING, "Unable to create cache_ignore_options\n"); + return 0; + } + } + else { + ctx->cache_ignore_options = NULL; + ctx->cache_ignore_count = count; + } + return 1; +} + +coap_cache_key_t * +coap_cache_derive_key_w_ignore(const coap_session_t *session, + const coap_pdu_t *pdu, + coap_cache_session_based_t session_based, + const uint16_t *cache_ignore_options, + size_t cache_ignore_count) { + coap_opt_t *option; + coap_opt_iterator_t opt_iter; + coap_digest_ctx_t *dctx; + coap_digest_t digest; + coap_cache_key_t *cache_key; + + if (!coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL)) { + return NULL; + } + + dctx = coap_digest_setup(); + if (!dctx) + return NULL; + + if (session_based == COAP_CACHE_IS_SESSION_BASED) { + /* Include the session ptr */ + if (!coap_digest_update(dctx, (const uint8_t*)&session, sizeof(session))) { + goto update_fail; + } + } + while ((option = coap_option_next(&opt_iter))) { + if (is_cache_key(opt_iter.number, cache_ignore_count, + cache_ignore_options)) { + if (!coap_digest_update(dctx, (const uint8_t *)&opt_iter.number, + sizeof(opt_iter.number))) { + goto update_fail; + } + if (!coap_digest_update(dctx, coap_opt_value(option), + coap_opt_length(option))) { + goto update_fail; + } + } + } + + /* The body of a FETCH payload is part of the cache key, + * see https://tools.ietf.org/html/rfc8132#section-2 */ + if (pdu->code == COAP_REQUEST_CODE_FETCH) { + size_t len; + const uint8_t *data; + if (coap_get_data(pdu, &len, &data)) { + if (!coap_digest_update(dctx, data, len)) { + goto update_fail; + } + } + } + + if (!coap_digest_final(dctx, &digest)) { + /* coap_digest_final() is guaranteed to free off dctx no matter what */ + return NULL; + } + cache_key = coap_malloc_type(COAP_CACHE_KEY, sizeof(coap_cache_key_t)); + if (cache_key) { + memcpy(cache_key->key, digest.key, sizeof(cache_key->key)); + } + return cache_key; +update_fail: + coap_digest_free(dctx); + return NULL; +} + +coap_cache_key_t * +coap_cache_derive_key(const coap_session_t *session, + const coap_pdu_t *pdu, + coap_cache_session_based_t session_based) { + return coap_cache_derive_key_w_ignore(session, pdu, session_based, + session->context->cache_ignore_options, + session->context->cache_ignore_count); +} + +void +coap_delete_cache_key(coap_cache_key_t *cache_key) { + coap_free_type(COAP_CACHE_KEY, cache_key); +} + +coap_cache_entry_t * +coap_new_cache_entry(coap_session_t *session, const coap_pdu_t *pdu, + coap_cache_record_pdu_t record_pdu, + coap_cache_session_based_t session_based, + unsigned int idle_timeout) { + coap_cache_entry_t *entry = coap_malloc_type(COAP_CACHE_ENTRY, + sizeof(coap_cache_entry_t)); + if (!entry) { + return NULL; + } + + memset(entry, 0, sizeof(coap_cache_entry_t)); + entry->session = session; + if (record_pdu == COAP_CACHE_RECORD_PDU) { + entry->pdu = coap_pdu_init(pdu->type, pdu->code, pdu->mid, pdu->alloc_size); + if (entry->pdu) { + if (!coap_pdu_resize(entry->pdu, pdu->alloc_size)) { + coap_delete_pdu(entry->pdu); + coap_free_type(COAP_CACHE_ENTRY, entry); + return NULL; + } + /* Need to get the appropriate data across */ + memcpy(entry->pdu, pdu, offsetof(coap_pdu_t, token)); + memcpy(entry->pdu->token, pdu->token, pdu->used_size); + /* And adjust all the pointers etc. */ + entry->pdu->data = entry->pdu->token + (pdu->data - pdu->token); + } + } + entry->cache_key = coap_cache_derive_key(session, pdu, session_based); + if (!entry->cache_key) { + coap_free_type(COAP_CACHE_ENTRY, entry); + return NULL; + } + entry->idle_timeout = idle_timeout; + if (idle_timeout > 0) { + coap_ticks(&entry->expire_ticks); + entry->expire_ticks += idle_timeout * COAP_TICKS_PER_SECOND; + } + + HASH_ADD(hh, session->context->cache, cache_key[0], sizeof(coap_cache_key_t), entry); + return entry; +} + +coap_cache_entry_t * +coap_cache_get_by_key(coap_context_t *ctx, const coap_cache_key_t *cache_key) { + coap_cache_entry_t *cache_entry = NULL; + + assert(cache_key); + if (cache_key) { + HASH_FIND(hh, ctx->cache, cache_key, sizeof(coap_cache_key_t), cache_entry); + } + if (cache_entry && cache_entry->idle_timeout > 0) { + coap_ticks(&cache_entry->expire_ticks); + cache_entry->expire_ticks += cache_entry->idle_timeout * COAP_TICKS_PER_SECOND; + } + return cache_entry; +} + +coap_cache_entry_t * +coap_cache_get_by_pdu(coap_session_t *session, + const coap_pdu_t *request, + coap_cache_session_based_t session_based) { + coap_cache_key_t *cache_key = coap_cache_derive_key(session, request, session_based); + coap_cache_entry_t *cache_entry; + + if (!cache_key) + return NULL; + + cache_entry = coap_cache_get_by_key(session->context, cache_key); + coap_delete_cache_key(cache_key); + if (cache_entry && cache_entry->idle_timeout > 0) { + coap_ticks(&cache_entry->expire_ticks); + cache_entry->expire_ticks += cache_entry->idle_timeout * COAP_TICKS_PER_SECOND; + } + return cache_entry; +} + +void +coap_delete_cache_entry(coap_context_t *ctx, coap_cache_entry_t *cache_entry) { + + assert(cache_entry); + + if (cache_entry) { + HASH_DELETE(hh, ctx->cache, cache_entry); + } + if (cache_entry->pdu) { + coap_delete_pdu(cache_entry->pdu); + } + coap_delete_cache_key(cache_entry->cache_key); + if (cache_entry->callback && cache_entry->app_data) { + cache_entry->callback(cache_entry->app_data); + } + coap_free_type(COAP_CACHE_ENTRY, cache_entry); +} + +const coap_pdu_t * +coap_cache_get_pdu(const coap_cache_entry_t *cache_entry) { + return cache_entry->pdu; +} + +void +coap_cache_set_app_data(coap_cache_entry_t *cache_entry, + void *data, + coap_cache_app_data_free_callback_t callback) { + cache_entry->app_data = data; + cache_entry->callback = callback; +} + +void * +coap_cache_get_app_data(const coap_cache_entry_t *cache_entry) { + return cache_entry->app_data; +} + +void +coap_expire_cache_entries(coap_context_t *ctx) { + coap_tick_t now; + coap_cache_entry_t *cp, *ctmp; + + coap_ticks(&now); + HASH_ITER(hh, ctx->cache, cp, ctmp) { + if (cp->idle_timeout > 0) { + if (cp->expire_ticks <= now) { + coap_delete_cache_entry(ctx, cp); + } + } + } +} + +#endif /* ! COAP_SERVER_SUPPORT */ diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_debug.c b/examples/espidf-coap-server/components/libcoap/src/coap_debug.c new file mode 100644 index 000000000..dda64b1e7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_debug.c @@ -0,0 +1,1052 @@ +/* coap_debug.c -- debug utilities + * + * Copyright (C) 2010--2012,2014--2022 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_debug.c + * @brief Debug utilities + */ + +#include "coap3/coap_internal.h" + +#if defined(HAVE_STRNLEN) && defined(__GNUC__) && !defined(_GNU_SOURCE) +#define _GNU_SOURCE 1 +#endif + +#include +#include +#include +#include + +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef WITH_LWIP +# define fprintf(fd, ...) LWIP_PLATFORM_DIAG((__VA_ARGS__)) +# define fflush(...) +#endif + +#ifdef WITH_CONTIKI +# ifndef DEBUG +# define DEBUG DEBUG_PRINT +# endif /* DEBUG */ +#include "net/ip/uip-debug.h" +#endif + +static coap_log_t maxlog = LOG_WARNING; /* default maximum log level */ + +static int use_fprintf_for_show_pdu = 1; /* non zero to output with fprintf */ + +const char *coap_package_name(void) { + return PACKAGE_NAME; +} + +const char *coap_package_version(void) { + return PACKAGE_STRING; +} + +const char *coap_package_build(void) { +#ifdef LIBCOAP_PACKAGE_BUILD + return LIBCOAP_PACKAGE_BUILD; +#else /* !LIBCOAP_PACKAGE_BUILD */ + return PACKAGE_STRING; +#endif /* !LIBCOAP_PACKAGE_BUILD */ +} + +void +coap_set_show_pdu_output(int use_fprintf) { + use_fprintf_for_show_pdu = use_fprintf; +} + +coap_log_t +coap_get_log_level(void) { + return maxlog; +} + +void +coap_set_log_level(coap_log_t level) { + maxlog = level; +} + +/* this array has the same order as the type log_t */ +static const char *loglevels[] = { + "EMRG", "ALRT", "CRIT", "ERR ", "WARN", "NOTE", "INFO", "DEBG", "????", "CIPH" +}; + +#ifdef HAVE_TIME_H + +COAP_STATIC_INLINE size_t +print_timestamp(char *s, size_t len, coap_tick_t t) { + struct tm *tmp; + size_t lensofar; + time_t now = coap_ticks_to_rt(t); + tmp = localtime(&now); + lensofar = strftime(s, len, "%b %d %H:%M:%S", tmp); + if (len > lensofar + 4) { + lensofar += snprintf(&s[lensofar], len-lensofar, ".%03u", + (unsigned int)((coap_ticks_to_rt_us(t) % 1000000)/1000)); + } + return lensofar; +} + +#else /* alternative implementation: just print the timestamp */ + +COAP_STATIC_INLINE size_t +print_timestamp(char *s, size_t len, coap_tick_t t) { +#ifdef HAVE_SNPRINTF + return snprintf(s, len, "%u.%03u", + (unsigned int)coap_ticks_to_rt(t), + (unsigned int)((coap_ticks_to_rt_us(t) % 1000000)/1000)); +#else /* HAVE_SNPRINTF */ + /* @todo do manual conversion of timestamp */ + return 0; +#endif /* HAVE_SNPRINTF */ +} + +#endif /* HAVE_TIME_H */ + +#ifndef HAVE_STRNLEN +/** + * A length-safe strlen() fake. + * + * @param s The string to count characters != 0. + * @param maxlen The maximum length of @p s. + * + * @return The length of @p s. + */ +static inline size_t +strnlen(const char *s, size_t maxlen) { + size_t n = 0; + while(*s++ && n < maxlen) + ++n; + return n; +} +#endif /* HAVE_STRNLEN */ + +static size_t +print_readable( const uint8_t *data, size_t len, + unsigned char *result, size_t buflen, int encode_always ) { + const uint8_t hex[] = "0123456789ABCDEF"; + size_t cnt = 0; + assert(data || len == 0); + + if (buflen == 0) { /* there is nothing we can do here but return */ + return 0; + } + + while (len) { + if (!encode_always && isprint(*data)) { + if (cnt+1 < buflen) { /* keep one byte for terminating zero */ + *result++ = *data; + ++cnt; + } else { + break; + } + } else { + if (cnt+4 < buflen) { /* keep one byte for terminating zero */ + *result++ = '\\'; + *result++ = 'x'; + *result++ = hex[(*data & 0xf0) >> 4]; + *result++ = hex[*data & 0x0f]; + cnt += 4; + } else + break; + } + + ++data; --len; + } + + *result = '\0'; /* add a terminating zero */ + return cnt; +} + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* + * Returned buf is always NULL terminated. + * Returned size is number of characters, not including NULL terminator. + */ +size_t +coap_print_addr(const coap_address_t *addr, unsigned char *buf, size_t len) { +#if defined( HAVE_ARPA_INET_H ) || defined( HAVE_WS2TCPIP_H ) + const void *addrptr = NULL; + in_port_t port; + unsigned char *p = buf; + size_t need_buf; + + assert(buf); + assert(len); + buf[0] = '\000'; + + switch (addr->addr.sa.sa_family) { + case AF_INET: + if (len < INET_ADDRSTRLEN + 1) /* Include : */ + return 0; + addrptr = &addr->addr.sin.sin_addr; + port = ntohs(addr->addr.sin.sin_port); + need_buf = INET_ADDRSTRLEN; + break; + case AF_INET6: + if (len < INET6_ADDRSTRLEN + 3) /* Include [ ] : */ + return 0; + + *p++ = '['; + + addrptr = &addr->addr.sin6.sin6_addr; + port = ntohs(addr->addr.sin6.sin6_port); + need_buf = INET6_ADDRSTRLEN; + + break; + default: + /* Include trailing NULL if possible */ + memcpy(buf, "(unknown address type)", min(22+1, len)); + buf[len-1] = '\000'; + return min(22, len); + } + + /* Cast needed for Windows, since it doesn't have the correct API signature. */ + if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)p, + min(len, need_buf)) == 0) { + perror("coap_print_addr"); + buf[0] = '\000'; + return 0; + } + + p += strlen((char *)p); + + if (addr->addr.sa.sa_family == AF_INET6) { + if (p + 1 < buf + len) { + *p++ = ']'; + } else + return p - buf; /* Already NULL terminated */ + } + + /* Cannot rely on snprintf() return value for short buffers */ + snprintf((char *)p, buf + len - p, ":%d", port); + + return strlen((char *)buf); +#else /* HAVE_ARPA_INET_H */ +# if WITH_CONTIKI + unsigned char *p = buf; + uint8_t i; +# if NETSTACK_CONF_WITH_IPV6 + const uint8_t hex[] = "0123456789ABCDEF"; + + assert(buf); + assert(len); + buf[0] = '\000'; + if (len < 42) + return 0; + + *p++ = '['; + + for (i=0; i < 16; i += 2) { + if (i) { + *p++ = ':'; + } + *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4]; + *p++ = hex[(addr->addr.u8[i] & 0x0f)]; + *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4]; + *p++ = hex[(addr->addr.u8[i+1] & 0x0f)]; + } + *p++ = ']'; +# else /* WITH_UIP6 */ +# warning "IPv4 network addresses will not be included in debug output" + + if (len < 21) { + *p = '\000'; + return 0; + } +# endif /* WITH_UIP6 */ + if (buf + len - p < 6) { + *p = '\000'; + return p - buf; + } + +#ifdef HAVE_SNPRINTF + /* Cannot rely on snprintf() return value for short buffers */ + snprintf((char *)p, buf + len - p, ":%d", uip_htons(addr->port)); +#else /* HAVE_SNPRINTF */ + /* @todo manual conversion of port number */ + *p = '\000'; +#endif /* HAVE_SNPRINTF */ + + return strlen((char *)p); +# else /* WITH_CONTIKI */ + /* TODO: output addresses manually */ +# warning "inet_ntop() not available, network addresses will not be included in debug output" +# endif /* WITH_CONTIKI */ + buf[0] = '\000'; + return 0; +#endif +} + +#ifdef WITH_CONTIKI +# define fprintf(fd, ...) { (void)fd; PRINTF(__VA_ARGS__); } +# define fflush(...) + +# ifdef HAVE_VPRINTF +# define vfprintf(fd, ...) { (void)fd; vprintf(__VA_ARGS__); } +# else /* HAVE_VPRINTF */ +# define vfprintf(fd, ...) { (void)fd; PRINTF(__VA_ARGS__); } +# endif /* HAVE_VPRINTF */ +#endif /* WITH_CONTIKI */ + +/** Returns a textual description of the message type @p t. */ +static const char * +msg_type_string(uint16_t t) { + static const char *types[] = { "CON", "NON", "ACK", "RST", "???" }; + + return types[min(t, sizeof(types)/sizeof(char *) - 1)]; +} + +/** Returns a textual description of the method or response code. */ +static const char * +msg_code_string(uint16_t c) { + static const char *methods[] = { "0.00", "GET", "POST", "PUT", "DELETE", + "FETCH", "PATCH", "iPATCH" }; + static const char *signals[] = { "7.00", "CSM", "Ping", "Pong", "Release", + "Abort" }; + static char buf[5]; + + if (c < sizeof(methods)/sizeof(const char *)) { + return methods[c]; + } else if (c >= 224 && c - 224 < (int)(sizeof(signals)/sizeof(const char *))) { + return signals[c-224]; + } else { + snprintf(buf, sizeof(buf), "%u.%02u", (c >> 5) & 0x7, c & 0x1f); + return buf; + } +} + +/** Returns a textual description of the option name. */ +static const char * +msg_option_string(uint8_t code, uint16_t option_type) { + struct option_desc_t { + uint16_t type; + const char *name; + }; + + static struct option_desc_t options[] = { + { COAP_OPTION_IF_MATCH, "If-Match" }, + { COAP_OPTION_URI_HOST, "Uri-Host" }, + { COAP_OPTION_ETAG, "ETag" }, + { COAP_OPTION_IF_NONE_MATCH, "If-None-Match" }, + { COAP_OPTION_OBSERVE, "Observe" }, + { COAP_OPTION_URI_PORT, "Uri-Port" }, + { COAP_OPTION_LOCATION_PATH, "Location-Path" }, + { COAP_OPTION_URI_PATH, "Uri-Path" }, + { COAP_OPTION_CONTENT_FORMAT, "Content-Format" }, + { COAP_OPTION_MAXAGE, "Max-Age" }, + { COAP_OPTION_URI_QUERY, "Uri-Query" }, + { COAP_OPTION_HOP_LIMIT, "Hop-Limit" }, + { COAP_OPTION_ACCEPT, "Accept" }, + { COAP_OPTION_LOCATION_QUERY, "Location-Query" }, + { COAP_OPTION_BLOCK2, "Block2" }, + { COAP_OPTION_BLOCK1, "Block1" }, + { COAP_OPTION_SIZE2, "Size2" }, + { COAP_OPTION_PROXY_URI, "Proxy-Uri" }, + { COAP_OPTION_PROXY_SCHEME, "Proxy-Scheme" }, + { COAP_OPTION_SIZE1, "Size1" }, + { COAP_OPTION_ECHO, "Echo" }, + { COAP_OPTION_NORESPONSE, "No-Response" }, + { COAP_OPTION_RTAG, "Request-Tag" } + }; + + static struct option_desc_t options_csm[] = { + { COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE, "Max-Message-Size" }, + { COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER, "Block-Wise-Transfer" } + }; + + static struct option_desc_t options_pingpong[] = { + { COAP_SIGNALING_OPTION_CUSTODY, "Custody" } + }; + + static struct option_desc_t options_release[] = { + { COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS, "Alternative-Address" }, + { COAP_SIGNALING_OPTION_HOLD_OFF, "Hold-Off" } + }; + + static struct option_desc_t options_abort[] = { + { COAP_SIGNALING_OPTION_BAD_CSM_OPTION, "Bad-CSM-Option" } + }; + + static char buf[6]; + size_t i; + + if (code == COAP_SIGNALING_CSM) { + for (i = 0; i < sizeof(options_csm)/sizeof(struct option_desc_t); i++) { + if (option_type == options_csm[i].type) { + return options_csm[i].name; + } + } + } else if (code == COAP_SIGNALING_PING || code == COAP_SIGNALING_PONG) { + for (i = 0; i < sizeof(options_pingpong)/sizeof(struct option_desc_t); i++) { + if (option_type == options_pingpong[i].type) { + return options_pingpong[i].name; + } + } + } else if (code == COAP_SIGNALING_RELEASE) { + for (i = 0; i < sizeof(options_release)/sizeof(struct option_desc_t); i++) { + if (option_type == options_release[i].type) { + return options_release[i].name; + } + } + } else if (code == COAP_SIGNALING_ABORT) { + for (i = 0; i < sizeof(options_abort)/sizeof(struct option_desc_t); i++) { + if (option_type == options_abort[i].type) { + return options_abort[i].name; + } + } + } else { + /* search option_type in list of known options */ + for (i = 0; i < sizeof(options)/sizeof(struct option_desc_t); i++) { + if (option_type == options[i].type) { + return options[i].name; + } + } + } + /* unknown option type, just print to buf */ + snprintf(buf, sizeof(buf), "%u", option_type); + return buf; +} + +static unsigned int +print_content_format(unsigned int format_type, + unsigned char *result, unsigned int buflen) { + struct desc_t { + unsigned int type; + const char *name; + }; + + static struct desc_t formats[] = { + { COAP_MEDIATYPE_TEXT_PLAIN, "text/plain" }, + { COAP_MEDIATYPE_APPLICATION_LINK_FORMAT, "application/link-format" }, + { COAP_MEDIATYPE_APPLICATION_XML, "application/xml" }, + { COAP_MEDIATYPE_APPLICATION_OCTET_STREAM, "application/octet-stream" }, + { COAP_MEDIATYPE_APPLICATION_RDF_XML, "application/rdf+xml" }, + { COAP_MEDIATYPE_APPLICATION_EXI, "application/exi" }, + { COAP_MEDIATYPE_APPLICATION_JSON, "application/json" }, + { COAP_MEDIATYPE_APPLICATION_CBOR, "application/cbor" }, + { COAP_MEDIATYPE_APPLICATION_CWT, "application/cwt" }, + { COAP_MEDIATYPE_APPLICATION_COSE_SIGN, "application/cose; cose-type=\"cose-sign\"" }, + { COAP_MEDIATYPE_APPLICATION_COSE_SIGN1, "application/cose; cose-type=\"cose-sign1\"" }, + { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT, "application/cose; cose-type=\"cose-encrypt\"" }, + { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0, "application/cose; cose-type=\"cose-encrypt0\"" }, + { COAP_MEDIATYPE_APPLICATION_COSE_MAC, "application/cose; cose-type=\"cose-mac\"" }, + { COAP_MEDIATYPE_APPLICATION_COSE_MAC0, "application/cose; cose-type=\"cose-mac0\"" }, + { COAP_MEDIATYPE_APPLICATION_COSE_KEY, "application/cose-key" }, + { COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET, "application/cose-key-set" }, + { COAP_MEDIATYPE_APPLICATION_SENML_JSON, "application/senml+json" }, + { COAP_MEDIATYPE_APPLICATION_SENSML_JSON, "application/sensml+json" }, + { COAP_MEDIATYPE_APPLICATION_SENML_CBOR, "application/senml+cbor" }, + { COAP_MEDIATYPE_APPLICATION_SENSML_CBOR, "application/sensml+cbor" }, + { COAP_MEDIATYPE_APPLICATION_SENML_EXI, "application/senml-exi" }, + { COAP_MEDIATYPE_APPLICATION_SENSML_EXI, "application/sensml-exi" }, + { COAP_MEDIATYPE_APPLICATION_SENML_XML, "application/senml+xml" }, + { COAP_MEDIATYPE_APPLICATION_SENSML_XML, "application/sensml+xml" }, + { COAP_MEDIATYPE_APPLICATION_COAP_GROUP_JSON, "application/coap-group+json" }, + { COAP_MEDIATYPE_APPLICATION_DOTS_CBOR, "application/dots+cbor" }, + { 75, "application/dcaf+cbor" } + }; + + size_t i; + + /* search format_type in list of known content formats */ + for (i = 0; i < sizeof(formats)/sizeof(struct desc_t); i++) { + if (format_type == formats[i].type) { + return snprintf((char *)result, buflen, "%s", formats[i].name); + } + } + + /* unknown content format, just print numeric value to buf */ + return snprintf((char *)result, buflen, "%d", format_type); +} + +/** + * Returns 1 if the given @p content_format is either unknown or known + * to carry binary data. The return value @c 0 hence indicates + * printable data which is also assumed if @p content_format is @c 01. + */ +COAP_STATIC_INLINE int +is_binary(int content_format) { + return !(content_format == -1 || + content_format == COAP_MEDIATYPE_TEXT_PLAIN || + content_format == COAP_MEDIATYPE_APPLICATION_LINK_FORMAT || + content_format == COAP_MEDIATYPE_APPLICATION_XML || + content_format == COAP_MEDIATYPE_APPLICATION_JSON); +} + +#define COAP_DO_SHOW_OUTPUT_LINE \ + do { \ + if (use_fprintf_for_show_pdu) { \ + fprintf(COAP_DEBUG_FD, "%s", outbuf); \ + } \ + else { \ + coap_log(level, "%s", outbuf); \ + } \ + } while (0) + +/* + * It is possible to override the output debug buffer size and hence control + * the amount of information printed out about a CoAP PDU. + * Note: Adding a byte may be insufficient to output the next byte of the PDU. + * + * This is done by the adding of a -DCOAP_DEBUG_BUF_SIZE=nnnn option to the + * CPPFLAGS parameter that is optionally used on the ./configure command line. + * + * E.g. ./configure CPPFLAGS="-DCOAP_DEBUG_BUF_SIZE=4096" + * + */ + +#if COAP_DEBUG_BUF_SIZE < 5 +#error "COAP_DEBUG_BUF_SIZE must be at least 5, should be >= 32 to be useful" +#endif /* COAP_DEBUG_BUF_SIZE < 5 */ + +void +coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu) { +#if COAP_CONSTRAINED_STACK + static coap_mutex_t static_show_pdu_mutex = COAP_MUTEX_INITIALIZER; + /* Proxy-Uri: can be 1034 bytes long */ + static unsigned char buf[min(COAP_DEBUG_BUF_SIZE, 1035)]; + static char outbuf[COAP_DEBUG_BUF_SIZE]; +#else /* ! COAP_CONSTRAINED_STACK */ + /* Proxy-Uri: can be 1034 bytes long */ + unsigned char buf[min(COAP_DEBUG_BUF_SIZE, 1035)]; + char outbuf[COAP_DEBUG_BUF_SIZE]; +#endif /* ! COAP_CONSTRAINED_STACK */ + size_t buf_len = 0; /* takes the number of bytes written to buf */ + int encode = 0, have_options = 0, i; + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + int content_format = -1; + size_t data_len; + const uint8_t *data; + uint32_t opt_len; + const uint8_t* opt_val; + size_t outbuflen = 0; + + /* Save time if not needed */ + if (level > coap_get_log_level()) + return; + +#if COAP_CONSTRAINED_STACK + coap_mutex_lock(&static_show_pdu_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + + snprintf(outbuf, sizeof(outbuf), "v:%d t:%s c:%s i:%04x {", + COAP_DEFAULT_VERSION, msg_type_string(pdu->type), + msg_code_string(pdu->code), pdu->mid); + + for (i = 0; i < pdu->token_length; i++) { + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, + "%02x", pdu->token[i]); + } + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "}"); + + /* show options, if any */ + coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ["); + while ((option = coap_option_next(&opt_iter))) { + buf[0] = '\000'; + if (!have_options) { + have_options = 1; + } else { + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ","); + } + + if (pdu->code == COAP_SIGNALING_CODE_CSM) switch(opt_iter.number) { + case COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE: + buf_len = snprintf((char *)buf, sizeof(buf), "%u", + coap_decode_var_bytes(coap_opt_value(option), + coap_opt_length(option))); + break; + default: + buf_len = 0; + break; + } else if (pdu->code == COAP_SIGNALING_CODE_PING + || pdu->code == COAP_SIGNALING_CODE_PONG) { + buf_len = 0; + } else if (pdu->code == COAP_SIGNALING_CODE_RELEASE) switch(opt_iter.number) { + case COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS: + buf_len = print_readable(coap_opt_value(option), + coap_opt_length(option), + buf, sizeof(buf), 0); + break; + case COAP_SIGNALING_OPTION_HOLD_OFF: + buf_len = snprintf((char *)buf, sizeof(buf), "%u", + coap_decode_var_bytes(coap_opt_value(option), + coap_opt_length(option))); + break; + default: + buf_len = 0; + break; + } else if (pdu->code == COAP_SIGNALING_CODE_ABORT) switch(opt_iter.number) { + case COAP_SIGNALING_OPTION_BAD_CSM_OPTION: + buf_len = snprintf((char *)buf, sizeof(buf), "%u", + coap_decode_var_bytes(coap_opt_value(option), + coap_opt_length(option))); + break; + default: + buf_len = 0; + break; + } else switch (opt_iter.number) { + case COAP_OPTION_CONTENT_FORMAT: + case COAP_OPTION_ACCEPT: + content_format = (int)coap_decode_var_bytes(coap_opt_value(option), + coap_opt_length(option)); + + buf_len = print_content_format(content_format, buf, sizeof(buf)); + break; + + case COAP_OPTION_BLOCK1: + case COAP_OPTION_BLOCK2: + /* split block option into number/more/size where more is the + * letter M if set, the _ otherwise */ + if (COAP_OPT_BLOCK_SZX(option) == 7) { + if (coap_get_data(pdu, &data_len, &data)) + buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/BERT(%zu)", + coap_opt_block_num(option), /* block number */ + COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */ + data_len); + else + buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/BERT", + coap_opt_block_num(option), /* block number */ + COAP_OPT_BLOCK_MORE(option) ? 'M' : '_'); /* M bit */ + } else { + buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/%u", + coap_opt_block_num(option), /* block number */ + COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */ + (1 << (COAP_OPT_BLOCK_SZX(option) + 4))); /* block size */ + } + + break; + + case COAP_OPTION_URI_PORT: + case COAP_OPTION_MAXAGE: + case COAP_OPTION_OBSERVE: + case COAP_OPTION_SIZE1: + case COAP_OPTION_SIZE2: + case COAP_OPTION_HOP_LIMIT: + /* show values as unsigned decimal value */ + buf_len = snprintf((char *)buf, sizeof(buf), "%u", + coap_decode_var_bytes(coap_opt_value(option), + coap_opt_length(option))); + break; + + case COAP_OPTION_IF_MATCH: + case COAP_OPTION_ETAG: + case COAP_OPTION_ECHO: + case COAP_OPTION_NORESPONSE: + case COAP_OPTION_RTAG: + opt_len = coap_opt_length(option); + opt_val = coap_opt_value(option); + snprintf((char *)buf, sizeof(buf), "0x"); + for (i = 0; (uint32_t)i < opt_len; i++) { + buf_len = strlen((char *)buf); + snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len, + "%02x", opt_val[i]); + } + buf_len = strlen((char *)buf); + break; + default: + /* generic output function for all other option types */ + if (opt_iter.number == COAP_OPTION_URI_PATH || + opt_iter.number == COAP_OPTION_PROXY_URI || + opt_iter.number == COAP_OPTION_URI_HOST || + opt_iter.number == COAP_OPTION_LOCATION_PATH || + opt_iter.number == COAP_OPTION_LOCATION_QUERY || + opt_iter.number == COAP_OPTION_PROXY_SCHEME || + opt_iter.number == COAP_OPTION_URI_QUERY) { + encode = 0; + } else { + encode = 1; + } + + buf_len = print_readable(coap_opt_value(option), + coap_opt_length(option), + buf, sizeof(buf), encode); + } + + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, + " %s:%.*s", msg_option_string(pdu->code, opt_iter.number), + (int)buf_len, buf); + } + + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ]"); + + if (coap_get_data(pdu, &data_len, &data)) { + + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " :: "); + + if (is_binary(content_format) || !isprint(data[0])) { + size_t keep_data_len = data_len; + const uint8_t *keep_data = data; + + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, + "binary data length %zu\n", data_len); + COAP_DO_SHOW_OUTPUT_LINE; + /* + * Output hex dump of binary data as a continuous entry + */ + outbuf[0] = '\000'; + snprintf(outbuf, sizeof(outbuf), "<<"); + while (data_len--) { + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, + "%02x", *data++); + } + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>"); + data_len = keep_data_len; + data = keep_data; + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n"); + COAP_DO_SHOW_OUTPUT_LINE; + /* + * Output ascii readable (if possible), immediately under the + * hex value of the character output above to help binary debugging + */ + outbuf[0] = '\000'; + snprintf(outbuf, sizeof(outbuf), "<<"); + while (data_len--) { + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, + "%c ", isprint (*data) ? *data : '.'); + data++; + } + outbuflen = strlen(outbuf); + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>"); + } else { + size_t max_length; + + outbuflen = strlen(outbuf); + max_length = sizeof(outbuf)-outbuflen; + if (max_length > 1) { + outbuf[outbuflen++] = '\''; + outbuf[outbuflen] = '\000'; + max_length--; + } + if (max_length > 1) { + outbuflen += print_readable(data, data_len, + (unsigned char*)&outbuf[outbuflen], + max_length, 0); + } + /* print_readable may be handling unprintables - hence headroom of 4 */ + if (outbuflen < sizeof(outbuf)-4-1) { + outbuf[outbuflen++] = '\''; + outbuf[outbuflen] = '\000'; + } + } + } + + outbuflen = strlen(outbuf); + if (outbuflen == sizeof(outbuf)-1) outbuflen--; + snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n"); + COAP_DO_SHOW_OUTPUT_LINE; + +#if COAP_CONSTRAINED_STACK + coap_mutex_unlock(&static_show_pdu_mutex); +#endif /* COAP_CONSTRAINED_STACK */ +} + +void coap_show_tls_version(coap_log_t level) +{ + char buffer[128]; + coap_string_tls_version(buffer, sizeof(buffer)); + coap_log(level, "%s\n", buffer); +} + +char *coap_string_tls_version(char *buffer, size_t bufsize) +{ + coap_tls_version_t *tls_version = coap_get_tls_library_version(); + char beta[8]; + char sub[2]; + char b_beta[8]; + char b_sub[2]; + + switch (tls_version->type) { + case COAP_TLS_LIBRARY_NOTLS: + snprintf(buffer, bufsize, "TLS Library: None"); + break; + case COAP_TLS_LIBRARY_TINYDTLS: + snprintf(buffer, bufsize, "TLS Library: TinyDTLS - runtime %lu.%lu.%lu, " + "libcoap built for %lu.%lu.%lu", + (unsigned long)(tls_version->version >> 16), + (unsigned long)((tls_version->version >> 8) & 0xff), + (unsigned long)(tls_version->version & 0xff), + (unsigned long)(tls_version->built_version >> 16), + (unsigned long)((tls_version->built_version >> 8) & 0xff), + (unsigned long)(tls_version->built_version & 0xff)); + break; + case COAP_TLS_LIBRARY_OPENSSL: + switch (tls_version->version &0xf) { + case 0: + strcpy(beta, "-dev"); + break; + case 0xf: + strcpy(beta, ""); + break; + default: + strcpy(beta, "-beta"); + beta[5] = (tls_version->version &0xf) + '0'; + beta[6] = '\000'; + break; + } + sub[0] = ((tls_version->version >> 4) & 0xff) ? + ((tls_version->version >> 4) & 0xff) + 'a' -1 : '\000'; + sub[1] = '\000'; + switch (tls_version->built_version &0xf) { + case 0: + strcpy(b_beta, "-dev"); + break; + case 0xf: + strcpy(b_beta, ""); + break; + default: + strcpy(b_beta, "-beta"); + b_beta[5] = (tls_version->built_version &0xf) + '0'; + b_beta[6] = '\000'; + break; + } + b_sub[0] = ((tls_version->built_version >> 4) & 0xff) ? + ((tls_version->built_version >> 4) & 0xff) + 'a' -1 : '\000'; + b_sub[1] = '\000'; + snprintf(buffer, bufsize, "TLS Library: OpenSSL - runtime " + "%lu.%lu.%lu%s%s, libcoap built for %lu.%lu.%lu%s%s", + (unsigned long)(tls_version->version >> 28), + (unsigned long)((tls_version->version >> 20) & 0xff), + (unsigned long)((tls_version->version >> 12) & 0xff), sub, beta, + (unsigned long)(tls_version->built_version >> 28), + (unsigned long)((tls_version->built_version >> 20) & 0xff), + (unsigned long)((tls_version->built_version >> 12) & 0xff), + b_sub, b_beta); + break; + case COAP_TLS_LIBRARY_GNUTLS: + snprintf(buffer, bufsize, "TLS Library: GnuTLS - runtime %lu.%lu.%lu, " + "libcoap built for %lu.%lu.%lu", + (unsigned long)(tls_version->version >> 16), + (unsigned long)((tls_version->version >> 8) & 0xff), + (unsigned long)(tls_version->version & 0xff), + (unsigned long)(tls_version->built_version >> 16), + (unsigned long)((tls_version->built_version >> 8) & 0xff), + (unsigned long)(tls_version->built_version & 0xff)); + break; + case COAP_TLS_LIBRARY_MBEDTLS: + snprintf(buffer, bufsize, "TLS Library: Mbed TLS - runtime %lu.%lu.%lu, " + "libcoap built for %lu.%lu.%lu", + (unsigned long)(tls_version->version >> 24), + (unsigned long)((tls_version->version >> 16) & 0xff), + (unsigned long)((tls_version->version >> 8) & 0xff), + (unsigned long)(tls_version->built_version >> 24), + (unsigned long)((tls_version->built_version >> 16) & 0xff), + (unsigned long)((tls_version->built_version >> 8) & 0xff)); + break; + default: + snprintf(buffer, bufsize, "Library type %d unknown", tls_version->type); + break; + } + return buffer; +} + +char *coap_string_tls_support(char *buffer, size_t bufsize) +{ + coap_tls_version_t *tls_version = coap_get_tls_library_version(); + const int have_tls = coap_tls_is_supported(); + const int have_dtls = coap_dtls_is_supported(); + + if (have_dtls == 0 && have_tls == 0) { + snprintf(buffer, bufsize, "(No DTLS or TLS support)"); + return buffer; + } + switch (tls_version->type) { + case COAP_TLS_LIBRARY_NOTLS: + snprintf(buffer, bufsize, "(No DTLS or TLS support)"); + break; + case COAP_TLS_LIBRARY_TINYDTLS: + snprintf(buffer, bufsize, + "(%sDTLS and%s TLS support; PSK, no PKI, no PKCS11, and RPK support)", + have_dtls ? "" : " no", + have_tls ? "" : " no"); + break; + case COAP_TLS_LIBRARY_OPENSSL: + snprintf(buffer, bufsize, + "(%sDTLS and%s TLS support; PSK, PKI, PKCS11, and no RPK support)", + have_dtls ? "" : " no", + have_tls ? "" : " no"); + break; + case COAP_TLS_LIBRARY_GNUTLS: + if (tls_version->version >= 0x030606) + snprintf(buffer, bufsize, + "(%sDTLS and%s TLS support; PSK, PKI, PKCS11, and RPK support)", + have_dtls ? "" : " no", + have_tls ? "" : " no"); + else + snprintf(buffer, bufsize, + "(%sDTLS and%s TLS support; PSK, PKI, PKCS11, and no RPK support)", + have_dtls ? "" : " no", + have_tls ? "" : " no"); + break; + case COAP_TLS_LIBRARY_MBEDTLS: + snprintf(buffer, bufsize, + "(%sDTLS and%s TLS support; PSK, PKI, no PKCS11, and no RPK support)", + have_dtls ? "" : " no", + have_tls ? "" : " no"); + break; + default: + buffer[0] = '\000'; + break; + } + return buffer; +} + +static coap_log_handler_t log_handler = NULL; + +void coap_set_log_handler(coap_log_handler_t handler) { + log_handler = handler; +} + +void +coap_log_impl(coap_log_t level, const char *format, ...) { + + if (maxlog < level) + return; + + if (log_handler) { +#if COAP_CONSTRAINED_STACK + static coap_mutex_t static_log_mutex = COAP_MUTEX_INITIALIZER; + static char message[COAP_DEBUG_BUF_SIZE]; +#else /* ! COAP_CONSTRAINED_STACK */ + char message[COAP_DEBUG_BUF_SIZE]; +#endif /* ! COAP_CONSTRAINED_STACK */ + va_list ap; + va_start(ap, format); +#if COAP_CONSTRAINED_STACK + coap_mutex_lock(&static_log_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + + vsnprintf( message, sizeof(message), format, ap); + va_end(ap); + log_handler(level, message); +#if COAP_CONSTRAINED_STACK + coap_mutex_unlock(&static_log_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + } else { + char timebuf[32]; + coap_tick_t now; + va_list ap; + FILE *log_fd; + size_t len; + + log_fd = level <= LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD; + + coap_ticks(&now); + len = print_timestamp(timebuf,sizeof(timebuf), now); + if (len) + fprintf(log_fd, "%.*s ", (int)len, timebuf); + + if (level <= COAP_LOG_CIPHERS) + fprintf(log_fd, "%s ", loglevels[level]); + + va_start(ap, format); + vfprintf(log_fd, format, ap); + va_end(ap); + fflush(log_fd); + } +} + +static struct packet_num_interval { + int start; + int end; +} packet_loss_intervals[10]; +static int num_packet_loss_intervals = 0; +static int packet_loss_level = 0; +static int send_packet_count = 0; + +int coap_debug_set_packet_loss(const char *loss_level) { + const char *p = loss_level; + char *end = NULL; + int n = (int)strtol(p, &end, 10), i = 0; + if (end == p || n < 0) + return 0; + if (*end == '%') { + if (n > 100) + n = 100; + packet_loss_level = n * 65536 / 100; + coap_log(LOG_DEBUG, "packet loss level set to %d%%\n", n); + } else { + if (n <= 0) + return 0; + while (i < 10) { + packet_loss_intervals[i].start = n; + if (*end == '-') { + p = end + 1; + n = (int)strtol(p, &end, 10); + if (end == p || n <= 0) + return 0; + } + packet_loss_intervals[i++].end = n; + if (*end == 0) + break; + if (*end != ',') + return 0; + p = end + 1; + n = (int)strtol(p, &end, 10); + if (end == p || n <= 0) + return 0; + } + if (i == 10) + return 0; + num_packet_loss_intervals = i; + } + send_packet_count = 0; + return 1; +} + +int coap_debug_send_packet(void) { + ++send_packet_count; + if (num_packet_loss_intervals > 0) { + int i; + for (i = 0; i < num_packet_loss_intervals; i++) { + if (send_packet_count >= packet_loss_intervals[i].start + && send_packet_count <= packet_loss_intervals[i].end) { + coap_log(LOG_DEBUG, "Packet %u dropped\n", send_packet_count); + return 0; + } + } + } + if ( packet_loss_level > 0 ) { + uint16_t r = 0; + coap_prng( (uint8_t*)&r, 2 ); + if ( r < packet_loss_level ) { + coap_log(LOG_DEBUG, "Packet %u dropped\n", send_packet_count); + return 0; + } + } + return 1; +} diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_event.c b/examples/espidf-coap-server/components/libcoap/src/coap_event.c new file mode 100644 index 000000000..1faba9acf --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_event.c @@ -0,0 +1,38 @@ +/* + * coap_event.c -- libcoap Event API + * + * Copyright (C) 2016 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_event.c + * @brief Event handling + */ + +#include "coap3/coap_internal.h" + +/* + * This replaces coap_set_event_handler() so that handler registration is + * consistent in the naming. + */ +void +coap_register_event_handler(coap_context_t *context, + coap_event_handler_t hnd) { + context->handle_event = hnd; +} + +void +coap_set_event_handler(coap_context_t *context, + coap_event_handler_t hnd) { + context->handle_event = hnd; +} + +void +coap_clear_event_handler(coap_context_t *context) { + context->handle_event = NULL; +} diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_gnutls.c b/examples/espidf-coap-server/components/libcoap/src/coap_gnutls.c new file mode 100644 index 000000000..a502a81dd --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_gnutls.c @@ -0,0 +1,2960 @@ +/* + * coap_gnutls.c -- GnuTLS Datagram Transport Layer Support for libcoap + * + * Copyright (C) 2017 Dag Bjorklund + * Copyright (C) 2018-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_gnutls.c + * @brief GndTLS interafe functions + */ + +/* + * Naming used to prevent confusion between coap sessions, gnutls sessions etc. + * when reading the code. + * + * c_context A coap_context_t * + * c_session A coap_session_t * + * g_context A coap_gnutls_context_t * (held in c_context->dtls_context) + * g_session A gnutls_session_t (which has the * in the typedef) + * g_env A coap_gnutls_env_t * (held in c_session->tls) + */ + +/* + * Notes + * + * There is a memory leak in GnuTLS prior to 3.3.26 when hint is not freed off + * when server psk credentials are freed off. + * + * ca_path in coap_dtls_context_set_pki_root_cas() is not supported until 3.3.6 + * + * Identity Hint is not provided if using DH and versions prior to 3.4.4 + * + * 3.5.5 or later is required to interoperate with TinyDTLS as CCM algorithm + * support is required. + * + * TLS 1.3 is properly supported from 3.6.5 onwards + * (but is not enabled by default in 3.6.4) + * + * Starting with 3.6.3, fixed in 3.6.13, Client Hellos may fail with some + * server implementations (e.g. Californium) as random value is all zeros + * - CVE-2020-11501 - a security weakness. + * 3.6.6 or later is required to support Raw Public Key(RPK) + */ + +#include "coap3/coap_internal.h" + +#ifdef HAVE_LIBGNUTLS + +#define MIN_GNUTLS_VERSION "3.3.0" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (GNUTLS_VERSION_NUMBER >= 0x030606) +#define COAP_GNUTLS_KEY_RPK GNUTLS_KEY_DIGITAL_SIGNATURE | \ + GNUTLS_KEY_NON_REPUDIATION | \ + GNUTLS_KEY_KEY_ENCIPHERMENT | \ + GNUTLS_KEY_DATA_ENCIPHERMENT | \ + GNUTLS_KEY_KEY_AGREEMENT | \ + GNUTLS_KEY_KEY_CERT_SIGN +#endif /* GNUTLS_VERSION_NUMBER >= 0x030606 */ + +#ifndef GNUTLS_CRT_RAW +#define GNUTLS_CRT_RAW GNUTLS_CRT_RAWPK +#endif /* GNUTLS_CRT_RAW */ + +#ifdef _WIN32 +#define strcasecmp _stricmp +#endif + +typedef struct coap_ssl_t { + const uint8_t *pdu; + unsigned pdu_len; + unsigned peekmode; + gnutls_datum_t cookie_key; +} coap_ssl_t; + +/* + * This structure encapsulates the GnuTLS session object. + * It handles both TLS and DTLS. + * c_session->tls points to this. + */ +typedef struct coap_gnutls_env_t { + gnutls_session_t g_session; + gnutls_psk_client_credentials_t psk_cl_credentials; + gnutls_psk_server_credentials_t psk_sv_credentials; + gnutls_certificate_credentials_t pki_credentials; + coap_ssl_t coap_ssl_data; + /* If not set, need to do gnutls_handshake */ + int established; + int doing_dtls_timeout; + coap_tick_t last_timeout; + int sent_alert; +} coap_gnutls_env_t; + +#define IS_PSK (1 << 0) +#define IS_PKI (1 << 1) +#define IS_CLIENT (1 << 6) +#define IS_SERVER (1 << 7) + +typedef struct pki_sni_entry { + char *sni; + coap_dtls_key_t pki_key; + gnutls_certificate_credentials_t pki_credentials; +} pki_sni_entry; + +typedef struct psk_sni_entry { + char *sni; + coap_dtls_spsk_info_t psk_info; + gnutls_psk_server_credentials_t psk_credentials; +} psk_sni_entry; + +typedef struct coap_gnutls_context_t { + coap_dtls_pki_t setup_data; + int psk_pki_enabled; + size_t pki_sni_count; + pki_sni_entry *pki_sni_entry_list; + size_t psk_sni_count; + psk_sni_entry *psk_sni_entry_list; + gnutls_datum_t alpn_proto; /* Will be "coap", but that is a const */ + char *root_ca_file; + char *root_ca_path; + gnutls_priority_t priority_cache; +} coap_gnutls_context_t; + +typedef enum coap_free_bye_t { + COAP_FREE_BYE_AS_TCP, /**< call gnutls_bye() with GNUTLS_SHUT_RDWR */ + COAP_FREE_BYE_AS_UDP, /**< call gnutls_bye() with GNUTLS_SHUT_WR */ + COAP_FREE_BYE_NONE /**< do not call gnutls_bye() */ +} coap_free_bye_t; + +#define VARIANTS_3_6_6 "NORMAL:+ECDHE-PSK:+PSK:+ECDHE-ECDSA:+AES-128-CCM-8:+CTYPE-CLI-ALL:+CTYPE-SRV-ALL:+SHA256" +#define VARIANTS_3_5_5 "NORMAL:+ECDHE-PSK:+PSK:+ECDHE-ECDSA:+AES-128-CCM-8" +#define VARIANTS_BASE "NORMAL:+ECDHE-PSK:+PSK" + +#define VARIANTS_NO_TLS13_3_6_6 VARIANTS_3_6_6 ":-VERS-TLS1.3" +#define VARIANTS_NO_TLS13_3_6_4 VARIANTS_3_5_5 ":-VERS-TLS1.3" + +#define G_ACTION(xx) do { \ + ret = (xx); \ +} while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) + +#define G_CHECK(xx,func) do { \ + if ((ret = (xx)) < 0) { \ + coap_log(LOG_WARNING, "%s: '%s'\n", func, gnutls_strerror(ret)); \ + goto fail; \ + } \ +} while (0) + +#define G_ACTION_CHECK(xx,func) do { \ + G_ACTION(xx); \ + G_CHECK(xx, func); \ +} while 0 + +static int dtls_log_level = 0; + +#if COAP_SERVER_SUPPORT +static int post_client_hello_gnutls_pki(gnutls_session_t g_session); +static int post_client_hello_gnutls_psk(gnutls_session_t g_session); +static int psk_server_callback(gnutls_session_t g_session, + const char *identity, + gnutls_datum_t *key); +#endif /* COAP_SERVER_SUPPORT */ + +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_is_supported(void) { + if (gnutls_check_version(MIN_GNUTLS_VERSION) == NULL) { + coap_log(LOG_ERR, "GnuTLS " MIN_GNUTLS_VERSION " or later is required\n"); + return 0; + } + return 1; +} + +/* + * return 0 failed + * 1 passed + */ +int +coap_tls_is_supported(void) { +#if !COAP_DISABLE_TCP + if (gnutls_check_version(MIN_GNUTLS_VERSION) == NULL) { + coap_log(LOG_ERR, "GnuTLS " MIN_GNUTLS_VERSION " or later is required\n"); + return 0; + } + return 1; +#else /* COAP_DISABLE_TCP */ + return 0; +#endif /* COAP_DISABLE_TCP */ +} + +coap_tls_version_t * +coap_get_tls_library_version(void) { + static coap_tls_version_t version; + const char *vers = gnutls_check_version(NULL); + + version.version = 0; + if (vers) { + int p1, p2, p3; + + sscanf (vers, "%d.%d.%d", &p1, &p2, &p3); + version.version = (p1 << 16) | (p2 << 8) | p3; + } + version.built_version = GNUTLS_VERSION_NUMBER; + version.type = COAP_TLS_LIBRARY_GNUTLS; + return &version; +} + +static void +coap_gnutls_audit_log_func(gnutls_session_t g_session, const char* text) +{ + if (g_session) { + coap_session_t *c_session = + (coap_session_t *)gnutls_transport_get_ptr(g_session); + coap_log(LOG_WARNING, "** %s: %s", + coap_session_str(c_session), text); + } else { + coap_log(LOG_WARNING, "** (null): %s", text); + } +} + +static void +coap_gnutls_log_func(int level, const char* text) +{ + /* debug logging in gnutls starts at 2 */ + if (level > 2) + level = 2; + coap_log(LOG_DEBUG + level - 2, "%s", text); +} + +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_context_set_pki(coap_context_t *c_context, + const coap_dtls_pki_t* setup_data, + const coap_dtls_role_t role COAP_UNUSED) +{ + coap_gnutls_context_t *g_context = + ((coap_gnutls_context_t *)c_context->dtls_context); + + if (!g_context || !setup_data) + return 0; + + g_context->setup_data = *setup_data; + if (!g_context->setup_data.verify_peer_cert) { + /* Needs to be clear so that no CA DNs are transmitted */ + g_context->setup_data.check_common_ca = 0; + if (g_context->setup_data.is_rpk_not_cert) { + /* Disable all of these as they cannot be checked */ + g_context->setup_data.allow_self_signed = 0; + g_context->setup_data.allow_expired_certs = 0; + g_context->setup_data.cert_chain_validation = 0; + g_context->setup_data.cert_chain_verify_depth = 0; + g_context->setup_data.check_cert_revocation = 0; + g_context->setup_data.allow_no_crl = 0; + g_context->setup_data.allow_expired_crl = 0; + g_context->setup_data.allow_bad_md_hash = 0; + g_context->setup_data.allow_short_rsa_length = 0; + } + else { + /* Allow all of these but warn if issue */ + g_context->setup_data.allow_self_signed = 1; + g_context->setup_data.allow_expired_certs = 1; + g_context->setup_data.cert_chain_validation = 1; + g_context->setup_data.cert_chain_verify_depth = 10; + g_context->setup_data.check_cert_revocation = 1; + g_context->setup_data.allow_no_crl = 1; + g_context->setup_data.allow_expired_crl = 1; + g_context->setup_data.allow_bad_md_hash = 1; + g_context->setup_data.allow_short_rsa_length = 1; + } + } + g_context->psk_pki_enabled |= IS_PKI; + return 1; +} + +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_context_set_pki_root_cas(coap_context_t *c_context, + const char *ca_file, + const char *ca_path) +{ + coap_gnutls_context_t *g_context = + ((coap_gnutls_context_t *)c_context->dtls_context); + if (!g_context) { + coap_log(LOG_WARNING, + "coap_context_set_pki_root_cas: (D)TLS environment " + "not set up\n"); + return 0; + } + + if (ca_file == NULL && ca_path == NULL) { + coap_log(LOG_WARNING, + "coap_context_set_pki_root_cas: ca_file and/or ca_path " + "not defined\n"); + return 0; + } + if (g_context->root_ca_file) { + gnutls_free(g_context->root_ca_file); + g_context->root_ca_file = NULL; + } + if (ca_file) { + g_context->root_ca_file = gnutls_strdup(ca_file); + } + if (g_context->root_ca_path) { + gnutls_free(g_context->root_ca_path); + g_context->root_ca_path = NULL; + } + if (ca_path) { +#if (GNUTLS_VERSION_NUMBER >= 0x030306) + g_context->root_ca_path = gnutls_strdup(ca_path); +#else + coap_log(LOG_ERR, "ca_path not supported in GnuTLS < 3.3.6\n"); +#endif + } + return 1; +} + +#if COAP_SERVER_SUPPORT +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_context_set_spsk(coap_context_t *c_context, + coap_dtls_spsk_t *setup_data +) { + coap_gnutls_context_t *g_context = + ((coap_gnutls_context_t *)c_context->dtls_context); + + if (!g_context || !setup_data) + return 0; + + g_context->psk_pki_enabled |= IS_PSK; + return 1; +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_context_set_cpsk(coap_context_t *c_context, + coap_dtls_cpsk_t *setup_data +) { + coap_gnutls_context_t *g_context = + ((coap_gnutls_context_t *)c_context->dtls_context); + + if (!g_context || !setup_data) + return 0; + + g_context->psk_pki_enabled |= IS_PSK; + return 1; +} +#endif /* COAP_CLIENT_SUPPORT */ + +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_context_check_keys_enabled(coap_context_t *c_context) +{ + coap_gnutls_context_t *g_context = + ((coap_gnutls_context_t *)c_context->dtls_context); + return g_context->psk_pki_enabled ? 1 : 0; +} + +void coap_dtls_startup(void) { + gnutls_global_set_audit_log_function(coap_gnutls_audit_log_func); + gnutls_global_set_log_function(coap_gnutls_log_func); +} + +void coap_dtls_shutdown(void) { +} + +void * +coap_dtls_get_tls(const coap_session_t *c_session, + coap_tls_library_t *tls_lib) { + if (tls_lib) + *tls_lib = COAP_TLS_LIBRARY_GNUTLS; + if (c_session && c_session->tls) { + const coap_gnutls_env_t *g_env = (const coap_gnutls_env_t *)c_session->tls; + + return g_env->g_session; + } + return NULL; +} + +void +coap_dtls_set_log_level(int level) { + dtls_log_level = level; + if (level - LOG_DEBUG >= -2) { + /* debug logging in gnutls starts at 2 */ + gnutls_global_set_log_level(2 + level - LOG_DEBUG); + } + else { + gnutls_global_set_log_level(0); + } +} + +/* + * return current logging level + */ +int +coap_dtls_get_log_level(void) { + return dtls_log_level; +} + +/* + * return +ve new g_context + * NULL failure + */ +void * +coap_dtls_new_context(coap_context_t *c_context COAP_UNUSED) { + const char *err; + int ret; + coap_gnutls_context_t *g_context = + (coap_gnutls_context_t *) + gnutls_malloc(sizeof(coap_gnutls_context_t)); + + if (g_context) { + coap_tls_version_t* tls_version = coap_get_tls_library_version(); + const char *priority; + + G_CHECK(gnutls_global_init(), "gnutls_global_init"); + memset(g_context, 0, sizeof(coap_gnutls_context_t)); + g_context->alpn_proto.data = gnutls_malloc(4); + if (g_context->alpn_proto.data) { + memcpy(g_context->alpn_proto.data, "coap", 4); + g_context->alpn_proto.size = 4; + } + + if (tls_version->version >= 0x030606) { + priority = VARIANTS_3_6_6; + } + else if (tls_version->version >= 0x030505) { + priority = VARIANTS_3_5_5; + } + else { + priority = VARIANTS_BASE; + } + ret = gnutls_priority_init(&g_context->priority_cache, priority, &err); + if (ret != GNUTLS_E_SUCCESS) { + if (ret == GNUTLS_E_INVALID_REQUEST) + coap_log(LOG_WARNING, + "gnutls_priority_init: Syntax error at: %s\n", err); + else + coap_log(LOG_WARNING, + "gnutls_priority_init: %s\n", gnutls_strerror(ret)); + goto fail; + } + } + return g_context; + +fail: + if (g_context) + coap_dtls_free_context(g_context); + return NULL; +} + +void +coap_dtls_free_context(void *handle) { + size_t i; + coap_gnutls_context_t *g_context = (coap_gnutls_context_t *)handle; + + gnutls_free(g_context->alpn_proto.data); + gnutls_free(g_context->root_ca_file); + gnutls_free(g_context->root_ca_path); + for (i = 0; i < g_context->pki_sni_count; i++) { + gnutls_free(g_context->pki_sni_entry_list[i].sni); + gnutls_certificate_free_credentials( + g_context->pki_sni_entry_list[i].pki_credentials); + } + if (g_context->pki_sni_entry_list) + gnutls_free(g_context->pki_sni_entry_list); + + for (i = 0; i < g_context->psk_sni_count; i++) { + gnutls_free(g_context->psk_sni_entry_list[i].sni); + /* YUK - A memory leak in 3.3.0 (fixed by 3.3.26) of hint */ + gnutls_psk_free_server_credentials( + g_context->psk_sni_entry_list[i].psk_credentials); + } + if (g_context->psk_sni_entry_list) + gnutls_free(g_context->psk_sni_entry_list); + + gnutls_priority_deinit(g_context->priority_cache); + + gnutls_global_deinit(); + gnutls_free(g_context); +} + +#if COAP_CLIENT_SUPPORT +/* + * gnutls_psk_client_credentials_function return values + * (see gnutls_psk_set_client_credentials_function()) + * + * return -1 failed + * 0 passed + */ +static int +psk_client_callback(gnutls_session_t g_session, + char **username, gnutls_datum_t *key) { + coap_session_t *c_session = + (coap_session_t *)gnutls_transport_get_ptr(g_session); + coap_gnutls_context_t *g_context; + coap_dtls_cpsk_t *setup_data; + const char *hint = gnutls_psk_client_get_hint(g_session); + coap_bin_const_t temp; + const coap_bin_const_t *psk_key; + const coap_bin_const_t *psk_identity; + const coap_dtls_cpsk_info_t *cpsk_info; + + /* Initialize result parameters. */ + *username = NULL; + key->data = NULL; + + if (c_session == NULL) + return -1; + + g_context = (coap_gnutls_context_t *)c_session->context->dtls_context; + if (g_context == NULL) + return -1; + + setup_data = &c_session->cpsk_setup_data; + + temp.s = hint ? (const uint8_t*)hint : (const uint8_t*)""; + temp.length = strlen((const char*)temp.s); + coap_session_refresh_psk_hint(c_session, &temp); + + coap_log(LOG_DEBUG, "got psk_identity_hint: '%.*s'\n", (int)temp.length, + (const char *)temp.s); + + if (setup_data->validate_ih_call_back) { + coap_str_const_t lhint; + + lhint.length = temp.length; + lhint.s = temp.s; + cpsk_info = + setup_data->validate_ih_call_back(&lhint, + c_session, + setup_data->ih_call_back_arg); + + if (cpsk_info == NULL) + return -1; + + coap_session_refresh_psk_identity(c_session, &cpsk_info->identity); + coap_session_refresh_psk_key(c_session, &cpsk_info->key); + psk_identity = &cpsk_info->identity; + psk_key = &cpsk_info->key; + } + else { + psk_identity = coap_get_session_client_psk_identity(c_session); + psk_key = coap_get_session_client_psk_key(c_session); + } + + if (psk_identity == NULL || psk_key == NULL) { + coap_log(LOG_WARNING, "no PSK available\n"); + return -1; + } + + *username = gnutls_malloc(psk_identity->length+1); + if (*username == NULL) + return -1; + memcpy(*username, psk_identity->s, psk_identity->length); + (*username)[psk_identity->length] = '\000'; + + key->data = gnutls_malloc(psk_key->length); + if (key->data == NULL) { + gnutls_free(*username); + *username = NULL; + return -1; + } + memcpy(key->data, psk_key->s, psk_key->length); + key->size = psk_key->length; + return 0; +} +#endif /* COAP_CLIENT_SUPPORT */ + +typedef struct { + gnutls_certificate_type_t certificate_type; + char *san_or_cn; + const gnutls_datum_t *cert_list; + unsigned int cert_list_size; + int self_signed; /* 1 if cert self-signed, 0 otherwise */ +} coap_gnutls_certificate_info_t; + +/* + * return Type of certificate and SAN or CN if appropriate derived from + * certificate. GNUTLS_CRT_UNKNOWN if failure. + */ +static gnutls_certificate_type_t get_san_or_cn(gnutls_session_t g_session, + coap_gnutls_certificate_info_t *cert_info) +{ + gnutls_x509_crt_t cert; + char dn[256]; + size_t size; + int n; + char *cn; + int ret; + +#if (GNUTLS_VERSION_NUMBER >= 0x030606) + cert_info->certificate_type = gnutls_certificate_type_get2(g_session, + GNUTLS_CTYPE_PEERS); +#else /* < 3.6.6 */ + cert_info->certificate_type = gnutls_certificate_type_get(g_session); +#endif /* < 3.6.6 */ + + cert_info->san_or_cn = NULL; + + cert_info->cert_list = gnutls_certificate_get_peers(g_session, + &cert_info->cert_list_size); + if (cert_info->cert_list_size == 0) { + return GNUTLS_CRT_UNKNOWN; + } + + if (cert_info->certificate_type != GNUTLS_CRT_X509) + return cert_info->certificate_type; + + G_CHECK(gnutls_x509_crt_init(&cert), "gnutls_x509_crt_init"); + + /* Interested only in first cert in chain */ + G_CHECK(gnutls_x509_crt_import(cert, &cert_info->cert_list[0], + GNUTLS_X509_FMT_DER), "gnutls_x509_crt_import"); + + cert_info->self_signed = gnutls_x509_crt_check_issuer(cert, cert); + + size = sizeof(dn) -1; + /* See if there is a Subject Alt Name first */ + ret = gnutls_x509_crt_get_subject_alt_name(cert, 0, dn, &size, NULL); + if (ret >= 0) { + dn[size] = '\000'; + gnutls_x509_crt_deinit(cert); + cert_info->san_or_cn = gnutls_strdup(dn); + return cert_info->certificate_type; + } + + size = sizeof(dn); + G_CHECK(gnutls_x509_crt_get_dn(cert, dn, &size), "gnutls_x509_crt_get_dn"); + + gnutls_x509_crt_deinit(cert); + + /* Need to emulate strcasestr() here. Looking for CN= */ + n = strlen(dn) - 3; + cn = dn; + while (n > 0) { + if (((cn[0] == 'C') || (cn[0] == 'c')) && + ((cn[1] == 'N') || (cn[1] == 'n')) && + (cn[2] == '=')) { + cn += 3; + break; + } + cn++; + n--; + } + if (n > 0) { + char *ecn = strchr(cn, ','); + if (ecn) { + cn[ecn-cn] = '\000'; + } + cert_info->san_or_cn = gnutls_strdup(cn); + return cert_info->certificate_type; + } + return GNUTLS_CRT_UNKNOWN; + +fail: + return GNUTLS_CRT_UNKNOWN; +} + +#if (GNUTLS_VERSION_NUMBER >= 0x030606) +#define OUTPUT_CERT_NAME (cert_type == GNUTLS_CRT_X509 ? \ + cert_info.san_or_cn : \ + cert_type == GNUTLS_CRT_RAW ? \ + COAP_DTLS_RPK_CERT_CN : "?") +#else /* GNUTLS_VERSION_NUMBER < 0x030606 */ +#define OUTPUT_CERT_NAME (cert_type == GNUTLS_CRT_X509 ? \ + cert_info.san_or_cn : "?") +#endif /* GNUTLS_VERSION_NUMBER < 0x030606 */ + +#if (GNUTLS_VERSION_NUMBER >= 0x030606) +static int +check_rpk_cert(coap_gnutls_context_t *g_context, + coap_gnutls_certificate_info_t *cert_info, + coap_session_t *c_session) { + int ret; + + if (g_context->setup_data.validate_cn_call_back) { + gnutls_pcert_st pcert; + uint8_t der[2048]; + size_t size; + + G_CHECK(gnutls_pcert_import_rawpk_raw(&pcert, &cert_info->cert_list[0], + GNUTLS_X509_FMT_DER, 0, 0), + "gnutls_pcert_import_rawpk_raw"); + + size = sizeof(der); + G_CHECK(gnutls_pubkey_export(pcert.pubkey, GNUTLS_X509_FMT_DER, der, &size), + "gnutls_pubkey_export"); + gnutls_pcert_deinit(&pcert); + if (!g_context->setup_data.validate_cn_call_back(COAP_DTLS_RPK_CERT_CN, + der, + size, + c_session, + 0, + 1, + g_context->setup_data.cn_call_back_arg)) { + return 0; + } + } + return 1; +fail: + return 0; +} +#endif /* >= 3.6.6 */ + +/* + * return 0 failed + * 1 passed + */ +static int cert_verify_gnutls(gnutls_session_t g_session) +{ + unsigned int status = 0; + unsigned int fail = 0; + coap_session_t *c_session = + (coap_session_t *)gnutls_transport_get_ptr(g_session); + coap_gnutls_context_t *g_context = + (coap_gnutls_context_t *)c_session->context->dtls_context; + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + int alert = GNUTLS_A_BAD_CERTIFICATE; + int ret; + coap_gnutls_certificate_info_t cert_info; + gnutls_certificate_type_t cert_type; + + memset(&cert_info, 0, sizeof(cert_info)); + cert_type = get_san_or_cn(g_session, &cert_info); +#if (GNUTLS_VERSION_NUMBER >= 0x030606) + if (cert_type == GNUTLS_CRT_RAW) { + if (!check_rpk_cert(g_context, &cert_info, c_session)) { + alert = GNUTLS_A_ACCESS_DENIED; + goto fail; + } + goto ok; + } +#endif /* >= 3.6.6 */ + + if (cert_info.cert_list_size == 0 && !g_context->setup_data.verify_peer_cert) + goto ok; + + G_CHECK(gnutls_certificate_verify_peers(g_session, NULL, 0, &status), + "gnutls_certificate_verify_peers"); + + if (status) { + status &= ~(GNUTLS_CERT_INVALID); + if (status & (GNUTLS_CERT_NOT_ACTIVATED|GNUTLS_CERT_EXPIRED)) { + status &= ~(GNUTLS_CERT_NOT_ACTIVATED|GNUTLS_CERT_EXPIRED); + if (g_context->setup_data.allow_expired_certs) { + coap_log(LOG_INFO, + " %s: %s: overridden: '%s'\n", + coap_session_str(c_session), + "The certificate has an invalid usage date", + OUTPUT_CERT_NAME); + } + else { + fail = 1; + coap_log(LOG_WARNING, + " %s: %s: '%s'\n", + coap_session_str(c_session), + "The certificate has an invalid usage date", + OUTPUT_CERT_NAME); + } + } + if (status & (GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED| + GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE)) { + status &= ~(GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED| + GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE); + if (g_context->setup_data.allow_expired_crl) { + coap_log(LOG_INFO, + " %s: %s: overridden: '%s'\n", + coap_session_str(c_session), + "The certificate's CRL entry has an invalid usage date", + OUTPUT_CERT_NAME); + } + else { + fail = 1; + coap_log(LOG_WARNING, + " %s: %s: '%s'\n", + coap_session_str(c_session), + "The certificate's CRL entry has an invalid usage date", + OUTPUT_CERT_NAME); + } + } + if (status & (GNUTLS_CERT_SIGNER_NOT_FOUND)) { + status &= ~(GNUTLS_CERT_SIGNER_NOT_FOUND); + if (cert_info.self_signed) { + if (g_context->setup_data.allow_self_signed && + !g_context->setup_data.check_common_ca) { + coap_log(LOG_INFO, + " %s: %s: overridden: '%s'\n", + coap_session_str(c_session), + "Self-signed", + OUTPUT_CERT_NAME); + } + else { + fail = 1; + alert = GNUTLS_A_UNKNOWN_CA; + coap_log(LOG_WARNING, + " %s: %s: '%s'\n", + coap_session_str(c_session), + "Self-signed", + OUTPUT_CERT_NAME); + } + } + else { + if (!g_context->setup_data.verify_peer_cert) { + coap_log(LOG_INFO, + " %s: %s: overridden: '%s'\n", + coap_session_str(c_session), + "The peer certificate's CA is unknown", + OUTPUT_CERT_NAME); + } + else { + fail = 1; + alert = GNUTLS_A_UNKNOWN_CA; + coap_log(LOG_WARNING, + " %s: %s: '%s'\n", + coap_session_str(c_session), + "The peer certificate's CA is unknown", + OUTPUT_CERT_NAME); + } + } + } + + if (status) { + fail = 1; + coap_log(LOG_WARNING, + " %s: gnutls_certificate_verify_peers() status 0x%x: '%s'\n", + coap_session_str(c_session), + status, OUTPUT_CERT_NAME); + } + } + + if (fail) + goto fail; + + if (g_context->setup_data.validate_cn_call_back) { + gnutls_x509_crt_t cert; + uint8_t der[2048]; + size_t size; + /* status == 0 indicates that the certificate passed to + * setup_data.validate_cn_call_back has been validated. */ + const int cert_is_trusted = !status; + + G_CHECK(gnutls_x509_crt_init(&cert), "gnutls_x509_crt_init"); + + /* Interested only in first cert in chain */ + G_CHECK(gnutls_x509_crt_import(cert, &cert_info.cert_list[0], + GNUTLS_X509_FMT_DER), "gnutls_x509_crt_import"); + + size = sizeof(der); + G_CHECK(gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, der, &size), + "gnutls_x509_crt_export"); + gnutls_x509_crt_deinit(cert); + if (!g_context->setup_data.validate_cn_call_back(OUTPUT_CERT_NAME, + der, + size, + c_session, + 0, + cert_is_trusted, + g_context->setup_data.cn_call_back_arg)) { + alert = GNUTLS_A_ACCESS_DENIED; + goto fail; + } + } + + if (g_context->setup_data.additional_tls_setup_call_back) { + /* Additional application setup wanted */ + if (!g_context->setup_data.additional_tls_setup_call_back(g_session, + &g_context->setup_data)) { + goto fail; + } + } + +ok: + if (cert_info.san_or_cn) + gnutls_free(cert_info.san_or_cn); + + return 1; + +fail: + if (cert_info.san_or_cn) + gnutls_free(cert_info.san_or_cn); + + if (!g_env->sent_alert) { + G_ACTION(gnutls_alert_send(g_session, GNUTLS_AL_FATAL, alert)); + g_env->sent_alert = 1; + } + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + return 0; +} + +/* + * gnutls_certificate_verify_function return values + * (see gnutls_certificate_set_verify_function()) + * + * return -1 failed + * 0 passed + */ +static int cert_verify_callback_gnutls(gnutls_session_t g_session) +{ + if (gnutls_auth_get_type(g_session) == GNUTLS_CRD_CERTIFICATE) { + if (cert_verify_gnutls(g_session) == 0) { + return -1; + } + } + return 0; +} + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +static int +pin_callback(void *user_data, int attempt, + const char *token_url COAP_UNUSED, + const char *token_label COAP_UNUSED, + unsigned int flags COAP_UNUSED, + char *pin, + size_t pin_max) +{ + coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)user_data; + + /* Only do this on first attempt to prevent token lockout */ + if (attempt == 0 && setup_data && setup_data->pki_key.key.pkcs11.user_pin) { + int len = min(pin_max - 1, strlen(setup_data->pki_key.key.pkcs11.user_pin)); + memcpy(pin, setup_data->pki_key.key.pkcs11.user_pin, len); + pin[len] = 0; + return 0; + } + return -1; +} +#if (GNUTLS_VERSION_NUMBER >= 0x030606) +/* first part of Raw public key, this is the start of the Subject Public Key */ +static const unsigned char cert_asn1_header1[] = { + 0x30, 0x59, /* SEQUENCE, length 89 bytes */ + 0x30, 0x13, /* SEQUENCE, length 19 bytes */ + 0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */ + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, +}; +/* PrimeX will get inserted */ +#if 0 + 0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */ + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, +#endif +static const unsigned char cert_asn1_header2[] = { + 0x03, 0x42, /* BIT STRING, length 66 bytes */ +/* Note: 0 bits (0x00) and no compression (0x04) are already in the certificate */ +}; + +static gnutls_datum_t * +get_asn1_spki(const uint8_t *data, size_t size) +{ + coap_binary_t *pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, data, size, NULL); + coap_binary_t *prime = get_asn1_tag(COAP_ASN1_IDENTIFIER, data, size, NULL); + gnutls_datum_t *spki = NULL; + + if (pub_key && prime) { + size_t header_size = sizeof(cert_asn1_header1) + + 2 + + prime->length + + sizeof(cert_asn1_header2); + uint8_t *tmp = gnutls_malloc(sizeof(gnutls_datum_t) + + header_size + + pub_key->length); + + if (tmp) { + spki = (gnutls_datum_t *)tmp; + spki->data = &tmp[sizeof(gnutls_datum_t)]; + memcpy(&spki->data[header_size], pub_key->s, pub_key->length); + memcpy(spki->data, cert_asn1_header1, sizeof(cert_asn1_header1)); + spki->data[sizeof(cert_asn1_header1)] = COAP_ASN1_IDENTIFIER; + spki->data[sizeof(cert_asn1_header1)+1] = prime->length; + memcpy(&spki->data[sizeof(cert_asn1_header1)+2], + prime->s, prime->length); + memcpy(&spki->data[sizeof(cert_asn1_header1)+2+prime->length], + cert_asn1_header2, sizeof(cert_asn1_header2)); + spki->size = header_size + pub_key->length; + } + } + if (pub_key) coap_delete_binary(pub_key); + if (prime) coap_delete_binary(prime); + return spki; +} +#endif /* GNUTLS_VERSION_NUMBER >= 0x030606 */ + +/* + * return 0 Success (GNUTLS_E_SUCCESS) + * neg GNUTLS_E_* error code + */ +static int +setup_pki_credentials(gnutls_certificate_credentials_t *pki_credentials, + gnutls_session_t g_session, + coap_gnutls_context_t *g_context, + coap_dtls_pki_t *setup_data, coap_dtls_role_t role) +{ + int ret; + + G_CHECK(gnutls_certificate_allocate_credentials(pki_credentials), + "gnutls_certificate_allocate_credentials"); + + switch (setup_data->pki_key.key_type) { + case COAP_PKI_KEY_PEM: + if (setup_data->pki_key.key.pem.public_cert && + setup_data->pki_key.key.pem.public_cert[0] && + setup_data->pki_key.key.pem.private_key && + setup_data->pki_key.key.pem.private_key[0]) { + if (setup_data->is_rpk_not_cert) { + coap_log(LOG_WARNING, + "RPK keys cannot be in COAP_PKI_KEY_PEM format\n"); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + else { + G_CHECK(gnutls_certificate_set_x509_key_file(*pki_credentials, + setup_data->pki_key.key.pem.public_cert, + setup_data->pki_key.key.pem.private_key, + GNUTLS_X509_FMT_PEM), + "gnutls_certificate_set_x509_key_file"); + } + } + else if (role == COAP_DTLS_ROLE_SERVER) { + coap_log(LOG_ERR, + "***setup_pki: (D)TLS: No %s Certificate + Private " + "Key defined\n", + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + if (setup_data->pki_key.key.pem.ca_file && + setup_data->pki_key.key.pem.ca_file[0]) { + ret = gnutls_certificate_set_x509_trust_file(*pki_credentials, + setup_data->pki_key.key.pem.ca_file, + GNUTLS_X509_FMT_PEM); + if (ret == 0) { + coap_log(LOG_WARNING, + "gnutls_certificate_set_x509_trust_file: No certificates found\n"); + } + else if (ret < 0) { + coap_log(LOG_WARNING, "%s: '%s'\n", + "gnutls_certificate_set_x509_trust_file", + gnutls_strerror(ret)); + goto fail; + } + } + break; + + case COAP_PKI_KEY_PEM_BUF: + if (setup_data->pki_key.key.pem_buf.public_cert && + setup_data->pki_key.key.pem_buf.public_cert_len && + setup_data->pki_key.key.pem_buf.private_key && + setup_data->pki_key.key.pem_buf.private_key_len) { + gnutls_datum_t cert; + gnutls_datum_t key; + int alloced_cert_memory = 0; + int alloced_key_memory = 0; + + cert.size = setup_data->pki_key.key.pem_buf.public_cert_len; + if (setup_data->pki_key.key.pem_buf.public_cert[cert.size-1] != '\000') { + /* Need to allocate memory, rather than just copying pointers across */ + alloced_cert_memory = 1; + cert.data = gnutls_malloc(cert.size + 1); + if (!cert.data) { + coap_log(LOG_ERR, "gnutls_malloc failure\n"); + return GNUTLS_E_MEMORY_ERROR; + } + memcpy(cert.data, setup_data->pki_key.key.pem_buf.public_cert, + cert.size); + cert.data[cert.size] = '\000'; + cert.size++; + } + else { + /* To get around const issue */ + memcpy(&cert.data, + &setup_data->pki_key.key.pem_buf.public_cert, sizeof(cert.data)); + } + key.size = setup_data->pki_key.key.pem_buf.private_key_len; + if (setup_data->pki_key.key.pem_buf.private_key[key.size-1] != '\000') { + /* Need to allocate memory, rather than just copying pointers across */ + alloced_key_memory = 1; + key.data = gnutls_malloc(key.size + 1); + if (!key.data) { + coap_log(LOG_ERR, "gnutls_malloc failure\n"); + if (alloced_cert_memory) gnutls_free(cert.data); + return GNUTLS_E_MEMORY_ERROR; + } + memcpy(key.data, setup_data->pki_key.key.pem_buf.private_key, key.size); + key.data[key.size] = '\000'; + key.size++; + } + else { + /* To get around const issue */ + memcpy(&key.data, + &setup_data->pki_key.key.pem_buf.private_key, sizeof(key.data)); + } + if (setup_data->is_rpk_not_cert) { +#if (GNUTLS_VERSION_NUMBER >= 0x030606) + int have_done_key = 0; + if (strstr ((char*)key.data, "-----BEGIN EC PRIVATE KEY-----")) { + gnutls_datum_t der_private; + + if (gnutls_pem_base64_decode2("EC PRIVATE KEY", &key, + &der_private) == 0) { + gnutls_datum_t *spki = get_asn1_spki(der_private.data, + der_private.size); + + if (spki) { + ret = gnutls_certificate_set_rawpk_key_mem(*pki_credentials, + spki, + &der_private, + GNUTLS_X509_FMT_DER, NULL, + COAP_GNUTLS_KEY_RPK, + NULL, 0, 0); + if (ret >= 0) { + have_done_key = 1; + } + gnutls_free(spki); + } + gnutls_free(der_private.data); + } + } + if (!have_done_key) { + G_CHECK(gnutls_certificate_set_rawpk_key_mem(*pki_credentials, + &cert, + &key, + GNUTLS_X509_FMT_PEM, NULL, + COAP_GNUTLS_KEY_RPK, + NULL, 0, 0), + "gnutls_certificate_set_rawpk_key_mem"); + } +#else /* GNUTLS_VERSION_NUMBER < 0x030606 */ + coap_log(LOG_ERR, + "RPK Support not available (needs gnutls 3.6.6 or later)\n"); + if (alloced_cert_memory) gnutls_free(cert.data); + if (alloced_key_memory) gnutls_free(key.data); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; +#endif /* GNUTLS_VERSION_NUMBER < 0x030606 */ + } + else { + G_CHECK(gnutls_certificate_set_x509_key_mem(*pki_credentials, + &cert, + &key, + GNUTLS_X509_FMT_PEM), + "gnutls_certificate_set_x509_key_mem"); + } + if (alloced_cert_memory) gnutls_free(cert.data); + if (alloced_key_memory) gnutls_free(key.data); + } + else if (role == COAP_DTLS_ROLE_SERVER) { + coap_log(LOG_ERR, + "***setup_pki: (D)TLS: No Server Certificate + Private " + "Key defined\n"); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + if (setup_data->pki_key.key.pem_buf.ca_cert && + setup_data->pki_key.key.pem_buf.ca_cert_len) { + gnutls_datum_t ca; + int alloced_ca_memory = 0; + + ca.size = setup_data->pki_key.key.pem_buf.ca_cert_len; + if (setup_data->pki_key.key.pem_buf.ca_cert[ca.size-1] != '\000') { + /* Need to allocate memory, rather than just copying pointers across */ + alloced_ca_memory = 1; + ca.data = gnutls_malloc(ca.size + 1); + if (!ca.data) { + coap_log(LOG_ERR, "gnutls_malloc failure\n"); + return GNUTLS_E_MEMORY_ERROR; + } + memcpy(ca.data, setup_data->pki_key.key.pem_buf.ca_cert, ca.size); + ca.data[ca.size] = '\000'; + ca.size++; + } + else { + /* To get around const issue */ + memcpy(&ca.data, + &setup_data->pki_key.key.pem_buf.ca_cert, sizeof(ca.data)); + } + ret = gnutls_certificate_set_x509_trust_mem(*pki_credentials, + &ca, + GNUTLS_X509_FMT_PEM); + if (ret == 0) { + coap_log(LOG_WARNING, + "gnutls_certificate_set_x509_trust_mem: No certificates found\n"); + } + else if (ret < 0) { + coap_log(LOG_WARNING, "%s: '%s'\n", + "gnutls_certificate_set_x509_trust_mem", + gnutls_strerror(ret)); + if (alloced_ca_memory) gnutls_free(ca.data); + goto fail; + } + if (alloced_ca_memory) gnutls_free(ca.data); + } + break; + + case COAP_PKI_KEY_ASN1: + if (setup_data->pki_key.key.asn1.public_cert && + setup_data->pki_key.key.asn1.public_cert_len && + setup_data->pki_key.key.asn1.private_key && + setup_data->pki_key.key.asn1.private_key_len > 0) { + gnutls_datum_t cert; + gnutls_datum_t key; + + /* Kludge to get around const parameters */ + memcpy(&cert.data, &setup_data->pki_key.key.asn1.public_cert, + sizeof(cert.data)); + cert.size = setup_data->pki_key.key.asn1.public_cert_len; + memcpy(&key.data, &setup_data->pki_key.key.asn1.private_key, + sizeof(key.data)); + key.size = setup_data->pki_key.key.asn1.private_key_len; + if (setup_data->is_rpk_not_cert) { +#if (GNUTLS_VERSION_NUMBER >= 0x030606) + int have_done_key = 0; + if (setup_data->pki_key.key.asn1.private_key_type == + COAP_ASN1_PKEY_EC) { + gnutls_datum_t *spki = get_asn1_spki(key.data, + key.size); + + if (spki) { + ret = gnutls_certificate_set_rawpk_key_mem(*pki_credentials, + spki, + &key, + GNUTLS_X509_FMT_DER, NULL, + COAP_GNUTLS_KEY_RPK, + NULL, 0, 0); + if (ret >= 0) { + have_done_key = 1; + } + gnutls_free(spki); + } + } + if (!have_done_key) { + G_CHECK(gnutls_certificate_set_rawpk_key_mem(*pki_credentials, + &cert, + &key, + GNUTLS_X509_FMT_DER, NULL, + COAP_GNUTLS_KEY_RPK, + NULL, 0, 0), + "gnutls_certificate_set_rawpk_key_mem"); + } +#else /* GNUTLS_VERSION_NUMBER < 0x030606 */ + coap_log(LOG_ERR, + "RPK Support not available (needs gnutls 3.6.6 or later)\n"); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; +#endif /* GNUTLS_VERSION_NUMBER < 0x030606 */ + } + else { + G_CHECK(gnutls_certificate_set_x509_key_mem(*pki_credentials, + &cert, + &key, + GNUTLS_X509_FMT_DER), + "gnutls_certificate_set_x509_key_mem"); + } + } + else if (role == COAP_DTLS_ROLE_SERVER) { + coap_log(LOG_ERR, + "***setup_pki: (D)TLS: No %s Certificate + Private " + "Key defined\n", + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + if (setup_data->pki_key.key.asn1.ca_cert && + setup_data->pki_key.key.asn1.ca_cert_len > 0) { + gnutls_datum_t ca_cert; + + /* Kludge to get around const parameters */ + memcpy(&ca_cert.data, &setup_data->pki_key.key.asn1.ca_cert, + sizeof(ca_cert.data)); + ca_cert.size = setup_data->pki_key.key.asn1.ca_cert_len; + ret = gnutls_certificate_set_x509_trust_mem(*pki_credentials, + &ca_cert, + GNUTLS_X509_FMT_DER); + if (ret == 0) { + coap_log(LOG_WARNING, + "gnutls_certificate_set_x509_trust_mem: No certificates found\n"); + } + else if (ret < 0) { + coap_log(LOG_WARNING, "%s: '%s'\n", + "gnutls_certificate_set_x509_trust_mem", + gnutls_strerror(ret)); + goto fail; + } + } + break; + + case COAP_PKI_KEY_PKCS11: + if (setup_data->pki_key.key.pkcs11.public_cert && + setup_data->pki_key.key.pkcs11.public_cert[0] && + setup_data->pki_key.key.pkcs11.private_key && + setup_data->pki_key.key.pkcs11.private_key[0]) { + + gnutls_pkcs11_set_pin_function(pin_callback, setup_data); + if (setup_data->is_rpk_not_cert) { +#if (GNUTLS_VERSION_NUMBER >= 0x030606) + G_CHECK(gnutls_certificate_set_rawpk_key_file(*pki_credentials, + setup_data->pki_key.key.pkcs11.public_cert, + setup_data->pki_key.key.pkcs11.private_key, + GNUTLS_X509_FMT_PEM, NULL, + COAP_GNUTLS_KEY_RPK, + NULL, 0, GNUTLS_PKCS_PLAIN, 0), + "gnutls_certificate_set_rawpk_key_file"); +#else /* GNUTLS_VERSION_NUMBER < 0x030606 */ + coap_log(LOG_ERR, + "RPK Support not available (needs gnutls 3.6.6 or later)\n"); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; +#endif /* GNUTLS_VERSION_NUMBER < 0x030606 */ + } + else { + G_CHECK(gnutls_certificate_set_x509_key_file(*pki_credentials, + setup_data->pki_key.key.pkcs11.public_cert, + setup_data->pki_key.key.pkcs11.private_key, + GNUTLS_X509_FMT_DER), + "gnutls_certificate_set_x509_key_file"); + } + } + else if (role == COAP_DTLS_ROLE_SERVER) { + coap_log(LOG_ERR, + "***setup_pki: (D)TLS: No %s Certificate + Private " + "Key defined\n", + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + if (setup_data->pki_key.key.pkcs11.ca && + setup_data->pki_key.key.pkcs11.ca[0]) { + ret = gnutls_certificate_set_x509_trust_file(*pki_credentials, + setup_data->pki_key.key.pkcs11.ca, + GNUTLS_X509_FMT_DER); + if (ret == 0) { + coap_log(LOG_WARNING, + "gnutls_certificate_set_x509_trust_file: No certificates found\n"); + } + else if (ret < 0) { + coap_log(LOG_WARNING, "%s: '%s'\n", + "gnutls_certificate_set_x509_trust_file", + gnutls_strerror(ret)); + goto fail; + } + } + break; + + default: + coap_log(LOG_ERR, + "***setup_pki: (D)TLS: Unknown key type %d\n", + setup_data->pki_key.key_type); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if (g_context->root_ca_file) { + ret = gnutls_certificate_set_x509_trust_file(*pki_credentials, + g_context->root_ca_file, + GNUTLS_X509_FMT_PEM); + if (ret == 0) { + coap_log(LOG_WARNING, + "gnutls_certificate_set_x509_trust_file: Root CA: No certificates found\n"); + } + } + if (g_context->root_ca_path) { +#if (GNUTLS_VERSION_NUMBER >= 0x030306) + G_CHECK(gnutls_certificate_set_x509_trust_dir(*pki_credentials, + g_context->root_ca_path, + GNUTLS_X509_FMT_PEM), + "gnutls_certificate_set_x509_trust_dir"); +#endif + } + gnutls_certificate_send_x509_rdn_sequence(g_session, + setup_data->check_common_ca ? 0 : 1); + if (!(g_context->psk_pki_enabled & IS_PKI)) { + /* No PKI defined at all - still need a trust set up for 3.6.0 or later */ + G_CHECK(gnutls_certificate_set_x509_system_trust(*pki_credentials), + "gnutls_certificate_set_x509_system_trust"); + } + + /* Verify Peer */ + gnutls_certificate_set_verify_function(*pki_credentials, + cert_verify_callback_gnutls); + + /* Cert chain checking (can raise GNUTLS_E_CONSTRAINT_ERROR) */ + if (setup_data->cert_chain_validation) { + gnutls_certificate_set_verify_limits(*pki_credentials, + 0, + setup_data->cert_chain_verify_depth + 2); + } + + /* + * Check for self signed + * CRL checking (can raise GNUTLS_CERT_MISSING_OCSP_STATUS) + */ + gnutls_certificate_set_verify_flags(*pki_credentials, + (setup_data->check_cert_revocation == 0 ? + GNUTLS_VERIFY_DISABLE_CRL_CHECKS : 0) + ); + + return GNUTLS_E_SUCCESS; + +fail: + return ret; +} + +#if COAP_SERVER_SUPPORT +/* + * return 0 Success (GNUTLS_E_SUCCESS) + * neg GNUTLS_E_* error code + */ +static int +setup_psk_credentials(gnutls_psk_server_credentials_t *psk_credentials, + coap_gnutls_context_t *g_context COAP_UNUSED, + coap_dtls_spsk_t *setup_data) +{ + int ret; + char hint[COAP_DTLS_HINT_LENGTH]; + + G_CHECK(gnutls_psk_allocate_server_credentials(psk_credentials), + "gnutls_psk_allocate_server_credentials"); + gnutls_psk_set_server_credentials_function(*psk_credentials, + psk_server_callback); + if (setup_data->psk_info.hint.s) { + snprintf(hint, sizeof(hint), "%.*s", (int)setup_data->psk_info.hint.length, + setup_data->psk_info.hint.s); + G_CHECK(gnutls_psk_set_server_credentials_hint(*psk_credentials, hint), + "gnutls_psk_set_server_credentials_hint"); + } + + return GNUTLS_E_SUCCESS; + +fail: + return ret; +} + +/* + * return 0 Success (GNUTLS_E_SUCCESS) + * neg GNUTLS_E_* error code + */ +static int +post_client_hello_gnutls_psk(gnutls_session_t g_session) +{ + coap_session_t *c_session = + (coap_session_t *)gnutls_transport_get_ptr(g_session); + coap_gnutls_context_t *g_context = + (coap_gnutls_context_t *)c_session->context->dtls_context; + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + int ret = GNUTLS_E_SUCCESS; + char *name = NULL; + + if (c_session->context->spsk_setup_data.validate_sni_call_back) { + coap_dtls_spsk_t sni_setup_data; + /* DNS names (only type supported) may be at most 256 byte long */ + size_t len = 256; + unsigned int type; + unsigned int i; + + name = gnutls_malloc(len); + if (name == NULL) + return GNUTLS_E_MEMORY_ERROR; + + for (i=0; ; ) { + ret = gnutls_server_name_get(g_session, name, &len, &type, i); + if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { + char *new_name; + new_name = gnutls_realloc(name, len); + if (new_name == NULL) { + ret = GNUTLS_E_MEMORY_ERROR; + goto end; + } + name = new_name; + continue; /* retry call with same index */ + } + + /* check if it is the last entry in list */ + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + break; + i++; + if (ret != GNUTLS_E_SUCCESS) + goto end; + /* unknown types need to be ignored */ + if (type != GNUTLS_NAME_DNS) + continue; + + } + /* If no extension provided, make it a dummy entry */ + if (i == 0) { + name[0] = '\000'; + len = 0; + } + + /* Is this a cached entry? */ + for (i = 0; i < g_context->psk_sni_count; i++) { + if (strcasecmp(name, g_context->psk_sni_entry_list[i].sni) == 0) { + break; + } + } + if (i == g_context->psk_sni_count) { + /* + * New SNI request + */ + const coap_dtls_spsk_info_t *new_entry = + c_session->context->spsk_setup_data.validate_sni_call_back(name, + c_session, + c_session->context->spsk_setup_data.sni_call_back_arg); + if (!new_entry) { + G_ACTION(gnutls_alert_send(g_session, GNUTLS_AL_FATAL, + GNUTLS_A_UNRECOGNIZED_NAME)); + g_env->sent_alert = 1; + ret = GNUTLS_E_NO_CERTIFICATE_FOUND; + goto end; + } + + g_context->psk_sni_entry_list = + gnutls_realloc(g_context->psk_sni_entry_list, + (i+1)*sizeof(psk_sni_entry)); + g_context->psk_sni_entry_list[i].sni = gnutls_strdup(name); + g_context->psk_sni_entry_list[i].psk_info = *new_entry; + sni_setup_data = c_session->context->spsk_setup_data; + sni_setup_data.psk_info = *new_entry; + if ((ret = setup_psk_credentials( + &g_context->psk_sni_entry_list[i].psk_credentials, + g_context, + &sni_setup_data)) < 0) { + int keep_ret = ret; + G_ACTION(gnutls_alert_send(g_session, GNUTLS_AL_FATAL, + GNUTLS_A_BAD_CERTIFICATE)); + g_env->sent_alert = 1; + ret = keep_ret; + goto end; + } + g_context->psk_sni_count++; + } + G_CHECK(gnutls_credentials_set(g_env->g_session, GNUTLS_CRD_PSK, + g_context->psk_sni_entry_list[i].psk_credentials), + "gnutls_credentials_set"); + coap_session_refresh_psk_hint(c_session, + &g_context->psk_sni_entry_list[i].psk_info.hint); + coap_session_refresh_psk_key(c_session, + &g_context->psk_sni_entry_list[i].psk_info.key); + } + +end: + free(name); + return ret; + +fail: + return ret; +} + +/* + * return 0 Success (GNUTLS_E_SUCCESS) + * neg GNUTLS_E_* error code + */ +static int +post_client_hello_gnutls_pki(gnutls_session_t g_session) +{ + coap_session_t *c_session = + (coap_session_t *)gnutls_transport_get_ptr(g_session); + coap_gnutls_context_t *g_context = + (coap_gnutls_context_t *)c_session->context->dtls_context; + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + int ret = GNUTLS_E_SUCCESS; + char *name = NULL; + + if (g_context->setup_data.validate_sni_call_back) { + /* DNS names (only type supported) may be at most 256 byte long */ + size_t len = 256; + unsigned int type; + unsigned int i; + coap_dtls_pki_t sni_setup_data; + + name = gnutls_malloc(len); + if (name == NULL) + return GNUTLS_E_MEMORY_ERROR; + + for (i=0; ; ) { + ret = gnutls_server_name_get(g_session, name, &len, &type, i); + if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { + char *new_name; + new_name = gnutls_realloc(name, len); + if (new_name == NULL) { + ret = GNUTLS_E_MEMORY_ERROR; + goto end; + } + name = new_name; + continue; /* retry call with same index */ + } + + /* check if it is the last entry in list */ + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + break; + i++; + if (ret != GNUTLS_E_SUCCESS) + goto end; + /* unknown types need to be ignored */ + if (type != GNUTLS_NAME_DNS) + continue; + + } + /* If no extension provided, make it a dummy entry */ + if (i == 0) { + name[0] = '\000'; + len = 0; + } + + /* Is this a cached entry? */ + for (i = 0; i < g_context->pki_sni_count; i++) { + if (strcasecmp(name, g_context->pki_sni_entry_list[i].sni) == 0) { + break; + } + } + if (i == g_context->pki_sni_count) { + /* + * New SNI request + */ + coap_dtls_key_t *new_entry = + g_context->setup_data.validate_sni_call_back(name, + g_context->setup_data.sni_call_back_arg); + if (!new_entry) { + G_ACTION(gnutls_alert_send(g_session, GNUTLS_AL_FATAL, + GNUTLS_A_UNRECOGNIZED_NAME)); + g_env->sent_alert = 1; + ret = GNUTLS_E_NO_CERTIFICATE_FOUND; + goto end; + } + + g_context->pki_sni_entry_list = gnutls_realloc( + g_context->pki_sni_entry_list, + (i+1)*sizeof(pki_sni_entry)); + g_context->pki_sni_entry_list[i].sni = gnutls_strdup(name); + g_context->pki_sni_entry_list[i].pki_key = *new_entry; + sni_setup_data = g_context->setup_data; + sni_setup_data.pki_key = *new_entry; + if ((ret = setup_pki_credentials( + &g_context->pki_sni_entry_list[i].pki_credentials, + g_session, + g_context, + &sni_setup_data, COAP_DTLS_ROLE_SERVER)) < 0) { + int keep_ret = ret; + G_ACTION(gnutls_alert_send(g_session, GNUTLS_AL_FATAL, + GNUTLS_A_BAD_CERTIFICATE)); + g_env->sent_alert = 1; + ret = keep_ret; + goto end; + } + g_context->pki_sni_count++; + } + G_CHECK(gnutls_credentials_set(g_env->g_session, GNUTLS_CRD_CERTIFICATE, + g_context->pki_sni_entry_list[i].pki_credentials), + "gnutls_credentials_set"); + } + +end: + free(name); + return ret; + +fail: + return ret; +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +/* + * return 0 Success (GNUTLS_E_SUCCESS) + * neg GNUTLS_E_* error code + */ +static int +setup_client_ssl_session(coap_session_t *c_session, coap_gnutls_env_t *g_env) +{ + coap_gnutls_context_t *g_context = + (coap_gnutls_context_t *)c_session->context->dtls_context; + int ret; + + g_context->psk_pki_enabled |= IS_CLIENT; + if (g_context->psk_pki_enabled & IS_PSK) { + coap_dtls_cpsk_t *setup_data = &c_session->cpsk_setup_data; + G_CHECK(gnutls_psk_allocate_client_credentials(&g_env->psk_cl_credentials), + "gnutls_psk_allocate_client_credentials"); + gnutls_psk_set_client_credentials_function(g_env->psk_cl_credentials, + psk_client_callback); + G_CHECK(gnutls_credentials_set(g_env->g_session, GNUTLS_CRD_PSK, + g_env->psk_cl_credentials), + "gnutls_credentials_set"); + /* Issue SNI if requested */ + if (setup_data->client_sni) { + G_CHECK(gnutls_server_name_set(g_env->g_session, GNUTLS_NAME_DNS, + setup_data->client_sni, + strlen(setup_data->client_sni)), + "gnutls_server_name_set"); + } + if (setup_data->validate_ih_call_back) { + const char *err; + coap_tls_version_t* tls_version = coap_get_tls_library_version(); + + if (tls_version->version >= 0x030604) { + /* Disable TLS1.3 if Identity Hint Callback set */ + const char *priority; + + if (tls_version->version >= 0x030606) { + priority = VARIANTS_NO_TLS13_3_6_6; + } + else { + priority = VARIANTS_NO_TLS13_3_6_4; + } + ret = gnutls_priority_set_direct(g_env->g_session, + priority, &err); + if (ret < 0) { + if (ret == GNUTLS_E_INVALID_REQUEST) + coap_log(LOG_WARNING, + "gnutls_priority_set_direct: Syntax error at: %s\n", err); + else + coap_log(LOG_WARNING, + "gnutls_priority_set_direct: %s\n", gnutls_strerror(ret)); + goto fail; + } + } + } + } + + if ((g_context->psk_pki_enabled & IS_PKI) || + (g_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) { + /* + * If neither PSK or PKI have been set up, use PKI basics. + * This works providing COAP_PKI_KEY_PEM has a value of 0. + */ + coap_dtls_pki_t *setup_data = &g_context->setup_data; + G_CHECK(setup_pki_credentials(&g_env->pki_credentials, g_env->g_session, + g_context, setup_data, + COAP_DTLS_ROLE_CLIENT), + "setup_pki_credentials"); + + G_CHECK(gnutls_credentials_set(g_env->g_session, GNUTLS_CRD_CERTIFICATE, + g_env->pki_credentials), + "gnutls_credentials_set"); + + if (c_session->proto == COAP_PROTO_TLS) + G_CHECK(gnutls_alpn_set_protocols(g_env->g_session, + &g_context->alpn_proto, 1, 0), + "gnutls_alpn_set_protocols"); + + /* Issue SNI if requested (only happens if PKI defined) */ + if (setup_data->client_sni) { + G_CHECK(gnutls_server_name_set(g_env->g_session, GNUTLS_NAME_DNS, + setup_data->client_sni, + strlen(setup_data->client_sni)), + "gnutls_server_name_set"); + } + } + return GNUTLS_E_SUCCESS; + +fail: + return ret; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +/* + * gnutls_psk_server_credentials_function return values + * (see gnutls_psk_set_server_credentials_function()) + * + * return -1 failed + * 0 passed + */ +static int +psk_server_callback(gnutls_session_t g_session, + const char *identity, + gnutls_datum_t *key) +{ + coap_session_t *c_session = + (coap_session_t *)gnutls_transport_get_ptr(g_session); + coap_gnutls_context_t *g_context; + coap_dtls_spsk_t *setup_data; + coap_bin_const_t lidentity; + const coap_bin_const_t *psk_key; + + if (c_session == NULL) + return -1; + + g_context = (coap_gnutls_context_t *)c_session->context->dtls_context; + if (g_context == NULL) + return -1; + setup_data = &c_session->context->spsk_setup_data; + + + /* Track the Identity being used */ + lidentity.s = identity ? (const uint8_t*)identity : (const uint8_t*)""; + lidentity.length = strlen((const char*)lidentity.s); + coap_session_refresh_psk_identity(c_session, &lidentity); + + coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n", + (int)lidentity.length, (const char *)lidentity.s); + + if (setup_data->validate_id_call_back) { + psk_key = setup_data->validate_id_call_back(&lidentity, + c_session, + setup_data->id_call_back_arg); + + coap_session_refresh_psk_key(c_session, psk_key); + } + else { + psk_key = coap_get_session_server_psk_key(c_session); + } + + if (psk_key == NULL) + return -1; + + key->data = gnutls_malloc(psk_key->length); + if (key->data == NULL) + return -1; + memcpy(key->data, psk_key->s, psk_key->length); + key->size = psk_key->length; + return 0; +} + +/* + * return 0 Success (GNUTLS_E_SUCCESS) + * neg GNUTLS_E_* error code + */ +static int +setup_server_ssl_session(coap_session_t *c_session, coap_gnutls_env_t *g_env) +{ + coap_gnutls_context_t *g_context = + (coap_gnutls_context_t *)c_session->context->dtls_context; + int ret = GNUTLS_E_SUCCESS; + + g_context->psk_pki_enabled |= IS_SERVER; + if (g_context->psk_pki_enabled & IS_PSK) { + G_CHECK(setup_psk_credentials( + &g_env->psk_sv_credentials, + g_context, + &c_session->context->spsk_setup_data), + "setup_psk_credentials\n"); + G_CHECK(gnutls_credentials_set(g_env->g_session, + GNUTLS_CRD_PSK, + g_env->psk_sv_credentials), + "gnutls_credentials_set\n"); + gnutls_handshake_set_post_client_hello_function(g_env->g_session, + post_client_hello_gnutls_psk); + } + + if (g_context->psk_pki_enabled & IS_PKI) { + coap_dtls_pki_t *setup_data = &g_context->setup_data; + G_CHECK(setup_pki_credentials(&g_env->pki_credentials, g_env->g_session, + g_context, setup_data, + COAP_DTLS_ROLE_SERVER), + "setup_pki_credentials"); + + if (setup_data->verify_peer_cert) { + gnutls_certificate_server_set_request(g_env->g_session, + GNUTLS_CERT_REQUIRE); + } + else if (setup_data->is_rpk_not_cert) { + gnutls_certificate_server_set_request(g_env->g_session, + GNUTLS_CERT_REQUEST); + } + else { + gnutls_certificate_server_set_request(g_env->g_session, + GNUTLS_CERT_IGNORE); + } + + gnutls_handshake_set_post_client_hello_function(g_env->g_session, + post_client_hello_gnutls_pki); + + G_CHECK(gnutls_credentials_set(g_env->g_session, GNUTLS_CRD_CERTIFICATE, + g_env->pki_credentials), + "gnutls_credentials_set\n"); + } + return GNUTLS_E_SUCCESS; + +fail: + return ret; +} +#endif /* COAP_SERVER_SUPPORT */ + +/* + * return +ve data amount + * 0 no more + * -1 error (error in errno) + */ +static ssize_t +coap_dgram_read(gnutls_transport_ptr_t context, void *out, size_t outl) +{ + ssize_t ret = 0; + coap_session_t *c_session = (coap_session_t *)context; + coap_ssl_t *data; + + if (!c_session->tls) { + errno = EAGAIN; + return -1; + } + data = &((coap_gnutls_env_t *)c_session->tls)->coap_ssl_data; + + if (out != NULL) { + if (data != NULL && data->pdu_len > 0) { + if (outl < data->pdu_len) { + memcpy(out, data->pdu, outl); + ret = outl; + if (!data->peekmode) { + data->pdu += outl; + data->pdu_len -= outl; + } + } else { + memcpy(out, data->pdu, data->pdu_len); + ret = data->pdu_len; + if (!data->peekmode) { + data->pdu_len = 0; + data->pdu = NULL; + } + } + } + else { + errno = EAGAIN; + ret = -1; + } + } + return ret; +} + +/* + * return +ve data amount + * 0 no more + * -1 error (error in errno) + */ +/* callback function given to gnutls for sending data over socket */ +static ssize_t +coap_dgram_write(gnutls_transport_ptr_t context, const void *send_buffer, + size_t send_buffer_length) { + ssize_t result = -1; + coap_session_t *c_session = (coap_session_t *)context; + + if (c_session) { + result = coap_session_send(c_session, send_buffer, send_buffer_length); + if (result != (int)send_buffer_length) { + coap_log(LOG_WARNING, "coap_network_send failed\n"); + result = 0; + } + } else { + result = 0; + } + return result; +} + +/* + * return 1 fd has activity + * 0 timeout + * -1 error (error in errno) + */ +static int +receive_timeout(gnutls_transport_ptr_t context, unsigned int ms COAP_UNUSED) { + coap_session_t *c_session = (coap_session_t *)context; + + if (c_session) { + fd_set readfds, writefds, exceptfds; + struct timeval tv; + int nfds = c_session->sock.fd +1; + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + + /* If data has been read in by libcoap ahead of GnuTLS, say it is there */ + if (c_session->proto == COAP_PROTO_DTLS && g_env && + g_env->coap_ssl_data.pdu_len > 0) { + return 1; + } + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + FD_SET (c_session->sock.fd, &readfds); + if (!(g_env && g_env->doing_dtls_timeout)) { + FD_SET (c_session->sock.fd, &writefds); + FD_SET (c_session->sock.fd, &exceptfds); + } + /* Polling */ + tv.tv_sec = 0; + tv.tv_usec = 0; + + return select(nfds, &readfds, &writefds, &exceptfds, &tv); + } + return 1; +} + +static coap_gnutls_env_t * +coap_dtls_new_gnutls_env(coap_session_t *c_session, int type) +{ + coap_gnutls_context_t *g_context = + ((coap_gnutls_context_t *)c_session->context->dtls_context); + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; +#if (GNUTLS_VERSION_NUMBER >= 0x030606) + int flags = type | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK | GNUTLS_ENABLE_RAWPK; +#else /* < 3.6.6 */ + int flags = type | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK; +#endif /* < 3.6.6 */ + int ret; + + if (g_env) + return g_env; + + g_env = gnutls_malloc(sizeof(coap_gnutls_env_t)); + if (!g_env) + return NULL; + + memset(g_env, 0, sizeof(coap_gnutls_env_t)); + + G_CHECK(gnutls_init(&g_env->g_session, flags), "gnutls_init"); + + gnutls_transport_set_pull_function(g_env->g_session, coap_dgram_read); + gnutls_transport_set_push_function(g_env->g_session, coap_dgram_write); + gnutls_transport_set_pull_timeout_function(g_env->g_session, receive_timeout); + /* So we can track the coap_session_t in callbacks */ + gnutls_transport_set_ptr(g_env->g_session, c_session); + + G_CHECK(gnutls_priority_set(g_env->g_session, g_context->priority_cache), + "gnutls_priority_set"); + + if (type == GNUTLS_SERVER) { +#if COAP_SERVER_SUPPORT + G_CHECK(setup_server_ssl_session(c_session, g_env), + "setup_server_ssl_session"); +#else /* ! COAP_SERVER_SUPPORT */ + goto fail; +#endif /* ! COAP_SERVER_SUPPORT */ + } + else { +#if COAP_CLIENT_SUPPORT + G_CHECK(setup_client_ssl_session(c_session, g_env), + "setup_client_ssl_session"); +#else /* COAP_CLIENT_SUPPORT */ + goto fail; +#endif /* COAP_CLIENT_SUPPORT */ + } + + gnutls_handshake_set_timeout(g_env->g_session, + GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); + gnutls_dtls_set_timeouts(g_env->g_session, COAP_DTLS_RETRANSMIT_MS, + COAP_DTLS_RETRANSMIT_TOTAL_MS); + + return g_env; + +fail: + if (g_env) + gnutls_free(g_env); + return NULL; +} + +static void +coap_dtls_free_gnutls_env(coap_gnutls_context_t *g_context, + coap_gnutls_env_t *g_env, + coap_free_bye_t free_bye) +{ + if (g_env) { + /* It is suggested not to use GNUTLS_SHUT_RDWR in DTLS + * connections because the peer's closure message might + * be lost */ + if (free_bye != COAP_FREE_BYE_NONE && !g_env->sent_alert) { + /* Only do this if appropriate */ + gnutls_bye(g_env->g_session, free_bye == COAP_FREE_BYE_AS_UDP ? + GNUTLS_SHUT_WR : GNUTLS_SHUT_RDWR); + } + gnutls_deinit(g_env->g_session); + g_env->g_session = NULL; + if (g_context->psk_pki_enabled & IS_PSK) { + if ((g_context->psk_pki_enabled & IS_CLIENT) && + g_env->psk_cl_credentials != NULL) { + gnutls_psk_free_client_credentials(g_env->psk_cl_credentials); + g_env->psk_cl_credentials = NULL; + } + else { + /* YUK - A memory leak in 3.3.0 (fixed by 3.3.26) of hint */ + if (g_env->psk_sv_credentials != NULL) + gnutls_psk_free_server_credentials(g_env->psk_sv_credentials); + g_env->psk_sv_credentials = NULL; + } + } + if ((g_context->psk_pki_enabled & IS_PKI) || + (g_context->psk_pki_enabled & + (IS_PSK | IS_PKI | IS_CLIENT)) == IS_CLIENT) { + gnutls_certificate_free_credentials(g_env->pki_credentials); + g_env->pki_credentials = NULL; + } + gnutls_free(g_env->coap_ssl_data.cookie_key.data); + gnutls_free(g_env); + } +} + +#if COAP_SERVER_SUPPORT +void *coap_dtls_new_server_session(coap_session_t *c_session) { + coap_gnutls_env_t *g_env = + (coap_gnutls_env_t *)c_session->tls; + + gnutls_transport_set_ptr(g_env->g_session, c_session); + + return g_env; +} +#endif /* COAP_SERVER_SUPPORT */ + +static void log_last_alert(coap_session_t *c_session, + gnutls_session_t g_session) { + int last_alert = gnutls_alert_get(g_session); + + if (last_alert == GNUTLS_A_CLOSE_NOTIFY) + coap_log(LOG_DEBUG, "***%s: Alert '%d': %s\n", + coap_session_str(c_session), + last_alert, gnutls_alert_get_name(last_alert)); + else + coap_log(LOG_WARNING, "***%s: Alert '%d': %s\n", + coap_session_str(c_session), + last_alert, gnutls_alert_get_name(last_alert)); +} + +/* + * return -1 failure + * 0 not completed + * 1 established + */ +static int +do_gnutls_handshake(coap_session_t *c_session, coap_gnutls_env_t *g_env) { + int ret; + + ret = gnutls_handshake(g_env->g_session); + switch (ret) { + case GNUTLS_E_SUCCESS: + g_env->established = 1; + coap_log(LOG_DEBUG, "* %s: GnuTLS established\n", + coap_session_str(c_session)); + ret = 1; + break; + case GNUTLS_E_INTERRUPTED: + errno = EINTR; + ret = 0; + break; + case GNUTLS_E_AGAIN: + errno = EAGAIN; + ret = 0; + break; + case GNUTLS_E_INSUFFICIENT_CREDENTIALS: + coap_log(LOG_WARNING, + "Insufficient credentials provided.\n"); + ret = -1; + break; + case GNUTLS_E_FATAL_ALERT_RECEIVED: + /* Stop the sending of an alert on closedown */ + g_env->sent_alert = 1; + log_last_alert(c_session, g_env->g_session); + /* Fall through */ + case GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET: + case GNUTLS_E_UNEXPECTED_PACKET: + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + case GNUTLS_E_WARNING_ALERT_RECEIVED: + log_last_alert(c_session, g_env->g_session); + c_session->dtls_event = COAP_EVENT_DTLS_ERROR; + ret = 0; + break; + case GNUTLS_E_NO_CERTIFICATE_FOUND: +#if (GNUTLS_VERSION_NUMBER > 0x030606) + case GNUTLS_E_CERTIFICATE_REQUIRED: +#endif /* GNUTLS_VERSION_NUMBER > 0x030606 */ + coap_log(LOG_WARNING, + "Client Certificate requested and required, but not provided\n" + ); + G_ACTION(gnutls_alert_send(g_env->g_session, GNUTLS_AL_FATAL, + GNUTLS_A_BAD_CERTIFICATE)); + g_env->sent_alert = 1; + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + case GNUTLS_E_DECRYPTION_FAILED: + coap_log(LOG_WARNING, + "do_gnutls_handshake: session establish " + "returned '%s'\n", + gnutls_strerror(ret)); + G_ACTION(gnutls_alert_send(g_env->g_session, GNUTLS_AL_FATAL, + GNUTLS_A_DECRYPT_ERROR)); + g_env->sent_alert = 1; + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + case GNUTLS_E_CERTIFICATE_ERROR: + if (g_env->sent_alert) { + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + } + /* Fall through */ + case GNUTLS_E_UNKNOWN_CIPHER_SUITE: + case GNUTLS_E_NO_CIPHER_SUITES: + case GNUTLS_E_INVALID_SESSION: + coap_log(LOG_WARNING, + "do_gnutls_handshake: session establish " + "returned '%s'\n", + gnutls_strerror(ret)); + if (!g_env->sent_alert) { + G_ACTION(gnutls_alert_send(g_env->g_session, GNUTLS_AL_FATAL, + GNUTLS_A_HANDSHAKE_FAILURE)); + g_env->sent_alert = 1; + } + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + case GNUTLS_E_SESSION_EOF: + case GNUTLS_E_TIMEDOUT: + case GNUTLS_E_PULL_ERROR: + case GNUTLS_E_PUSH_ERROR: + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + default: + coap_log(LOG_WARNING, + "do_gnutls_handshake: session establish " + "returned %d: '%s'\n", + ret, gnutls_strerror(ret)); + ret = -1; + break; + } + return ret; +} + +#if COAP_CLIENT_SUPPORT +void *coap_dtls_new_client_session(coap_session_t *c_session) { + coap_gnutls_env_t *g_env = coap_dtls_new_gnutls_env(c_session, GNUTLS_CLIENT); + int ret; + + if (g_env) { + ret = do_gnutls_handshake(c_session, g_env); + if (ret == -1) { + coap_dtls_free_gnutls_env(c_session->context->dtls_context, + g_env, + COAP_PROTO_NOT_RELIABLE(c_session->proto) ? + COAP_FREE_BYE_AS_UDP : COAP_FREE_BYE_AS_TCP); + return NULL; + } + } + return g_env; +} +#endif /* COAP_CLIENT_SUPPORT */ + +void coap_dtls_free_session(coap_session_t *c_session) { + if (c_session && c_session->context && c_session->tls) { + coap_dtls_free_gnutls_env(c_session->context->dtls_context, + c_session->tls, + COAP_PROTO_NOT_RELIABLE(c_session->proto) ? + COAP_FREE_BYE_AS_UDP : COAP_FREE_BYE_AS_TCP); + c_session->tls = NULL; + coap_handle_event(c_session->context, COAP_EVENT_DTLS_CLOSED, c_session); + } +} + +void coap_dtls_session_update_mtu(coap_session_t *c_session) { + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + int ret; + + if (g_env) + G_CHECK(gnutls_dtls_set_data_mtu(g_env->g_session, + (unsigned int)c_session->mtu), + "gnutls_dtls_set_data_mtu"); +fail: + ;; +} + +/* + * return +ve data amount + * 0 no more + * -1 error + */ +int coap_dtls_send(coap_session_t *c_session, + const uint8_t *data, size_t data_len) { + int ret; + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + + assert(g_env != NULL); + + c_session->dtls_event = -1; + if (g_env->established) { + ret = gnutls_record_send(g_env->g_session, data, data_len); + + if (ret <= 0) { + switch (ret) { + case GNUTLS_E_AGAIN: + ret = 0; + break; + case GNUTLS_E_FATAL_ALERT_RECEIVED: + /* Stop the sending of an alert on closedown */ + g_env->sent_alert = 1; + log_last_alert(c_session, g_env->g_session); + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + default: + coap_log(LOG_DEBUG, + "coap_dtls_send: gnutls_record_send " + "returned %d: '%s'\n", + ret, gnutls_strerror(ret)); + ret = -1; + break; + } + if (ret == -1) { + coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n"); + } + } + } + else { + ret = do_gnutls_handshake(c_session, g_env); + if (ret == 1) { + /* Just connected, so send the data */ + return coap_dtls_send(c_session, data, data_len); + } + ret = -1; + } + + if (c_session->dtls_event >= 0) { + coap_handle_event(c_session->context, c_session->dtls_event, c_session); + if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || + c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + ret = -1; + } + } + + return ret; +} + +int coap_dtls_is_context_timeout(void) { + return 0; +} + +coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED) { + return 0; +} + +coap_tick_t coap_dtls_get_timeout(coap_session_t *c_session, coap_tick_t now) { + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + + assert(c_session->state == COAP_SESSION_STATE_HANDSHAKE); + if (g_env && g_env->g_session) { + unsigned int rem_ms = gnutls_dtls_get_timeout(g_env->g_session); + + if (rem_ms == 0) { + /* + * Need to make sure that we do not do this too frequently as some + * versions of gnutls reset retransmit if a spurious packet is received + * (e.g. duplicate Client Hello), but last_transmit does not get updated + * when gnutls_handshake() is called and there is 'nothing' to resend. + */ + if (g_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS > now) + return g_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS; + } + /* Reset for the next time */ + g_env->last_timeout = now; + return now + rem_ms; + } + + return 0; +} + +/* + * return 1 timed out + * 0 still timing out + */ +int +coap_dtls_handle_timeout(coap_session_t *c_session) { + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + + assert(g_env != NULL && c_session->state == COAP_SESSION_STATE_HANDSHAKE); + g_env->doing_dtls_timeout = 1; + if ((++c_session->dtls_timeout_count > c_session->max_retransmit) || + (do_gnutls_handshake(c_session, g_env) < 0)) { + /* Too many retries */ + g_env->doing_dtls_timeout = 0; + coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + return 1; + } + else { + g_env->doing_dtls_timeout = 0; + return 0; + } +} + +/* + * return +ve data amount + * 0 no more + * -1 error + */ +int +coap_dtls_receive(coap_session_t *c_session, + const uint8_t *data, + size_t data_len +) { + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + int ret = 0; + coap_ssl_t *ssl_data = &g_env->coap_ssl_data; + + uint8_t pdu[COAP_RXBUFFER_SIZE]; + + assert(g_env != NULL); + + if (ssl_data->pdu_len) + coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n", + coap_session_str(c_session), ssl_data->pdu_len); + ssl_data->pdu = data; + ssl_data->pdu_len = data_len; + + c_session->dtls_event = -1; + if (g_env->established) { + if (c_session->state == COAP_SESSION_STATE_HANDSHAKE) { + coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, + c_session); + gnutls_transport_set_ptr(g_env->g_session, c_session); + coap_session_connected(c_session); + } + ret = gnutls_record_recv(g_env->g_session, pdu, (int)sizeof(pdu)); + if (ret > 0) { + return coap_handle_dgram(c_session->context, c_session, pdu, (size_t)ret); + } + else if (ret == 0) { + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + } + else { + switch (ret) { + case GNUTLS_E_FATAL_ALERT_RECEIVED: + /* Stop the sending of an alert on closedown */ + g_env->sent_alert = 1; + log_last_alert(c_session, g_env->g_session); + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + case GNUTLS_E_WARNING_ALERT_RECEIVED: + log_last_alert(c_session, g_env->g_session); + c_session->dtls_event = COAP_EVENT_DTLS_ERROR; + ret = 0; + break; + default: + coap_log(LOG_WARNING, + "coap_dtls_receive: gnutls_record_recv returned %d\n", ret); + ret = -1; + break; + } + } + } + else { + ret = do_gnutls_handshake(c_session, g_env); + if (ret == 1) { + coap_session_connected(c_session); + } + else { + ret = -1; + if (ssl_data->pdu_len && !g_env->sent_alert) { + /* Do the handshake again incase of internal timeout */ + ret = do_gnutls_handshake(c_session, g_env); + if (ret == 1) { + /* Just connected, so send the data */ + coap_session_connected(c_session); + } + } + } + } + + if (c_session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(c_session->context, c_session->dtls_event, c_session); + if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || + c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + ssl_data = NULL; + ret = -1; + } + } + if (ssl_data && ssl_data->pdu_len) { + /* pdu data is held on stack which will not stay there */ + coap_log(LOG_DEBUG, "coap_dtls_receive: ret %d: remaining data %u\n", ret, ssl_data->pdu_len); + ssl_data->pdu_len = 0; + ssl_data->pdu = NULL; + } + return ret; +} + +#if COAP_SERVER_SUPPORT +/* + * return -1 failure + * 0 not completed + * 1 client hello seen + */ +int +coap_dtls_hello(coap_session_t *c_session, + const uint8_t *data, + size_t data_len +) { + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + coap_ssl_t *ssl_data; + int ret; + + if (!g_env) { + g_env = coap_dtls_new_gnutls_env(c_session, GNUTLS_SERVER); + if (g_env) { + c_session->tls = g_env; + gnutls_key_generate(&g_env->coap_ssl_data.cookie_key, + GNUTLS_COOKIE_KEY_SIZE); + } + else { + /* error should have already been reported */ + return -1; + } + } + if (data_len > 0) { + gnutls_dtls_prestate_st prestate; + uint8_t *data_rw; + + memset(&prestate, 0, sizeof(prestate)); + /* Need to do this to not get a compiler warning about const parameters */ + memcpy (&data_rw, &data, sizeof(data_rw)); + ret = gnutls_dtls_cookie_verify(&g_env->coap_ssl_data.cookie_key, + &c_session->addr_info, + sizeof(c_session->addr_info), + data_rw, data_len, + &prestate); + if (ret < 0) { /* cookie not valid */ + coap_log(LOG_DEBUG, "Invalid Cookie - sending Hello Verify\n"); + gnutls_dtls_cookie_send(&g_env->coap_ssl_data.cookie_key, + &c_session->addr_info, + sizeof(c_session->addr_info), + &prestate, + c_session, + coap_dgram_write); + return 0; + } + gnutls_dtls_prestate_set(g_env->g_session, &prestate); + } + + ssl_data = &g_env->coap_ssl_data; + ssl_data->pdu = data; + ssl_data->pdu_len = data_len; + + ret = do_gnutls_handshake(c_session, g_env); + if (ret < 0) { + /* + * as the above failed, need to remove g_env to clean up any + * pollution of the information + */ + coap_dtls_free_gnutls_env( + ((coap_gnutls_context_t *)c_session->context->dtls_context), + g_env, COAP_FREE_BYE_NONE); + c_session->tls = NULL; + ssl_data = NULL; + ret = -1; + } + else { + /* Client Hello has been seen */ + ret = 1; + } + + if (ssl_data && ssl_data->pdu_len) { + /* pdu data is held on stack which will not stay there */ + coap_log(LOG_DEBUG, "coap_dtls_hello: ret %d: remaining data %u\n", ret, ssl_data->pdu_len); + ssl_data->pdu_len = 0; + ssl_data->pdu = NULL; + } + return ret; +} +#endif /* COAP_SERVER_SUPPORT */ + +unsigned int coap_dtls_get_overhead(coap_session_t *c_session COAP_UNUSED) { + return 37; +} + +#if !COAP_DISABLE_TCP +/* + * return +ve data amount + * 0 no more + * -1 error (error in errno) + */ +static ssize_t +coap_sock_read(gnutls_transport_ptr_t context, void *out, size_t outl) { + int ret = 0; + coap_session_t *c_session = (coap_session_t *)context; + + if (out != NULL) { +#ifdef _WIN32 + ret = recv(c_session->sock.fd, (char *)out, (int)outl, 0); +#else + ret = recv(c_session->sock.fd, out, outl, 0); +#endif + if (ret > 0) { + coap_log(LOG_DEBUG, "* %s: received %d bytes\n", + coap_session_str(c_session), ret); + } else if (ret < 0 && errno != EAGAIN) { + coap_log(LOG_DEBUG, "* %s: failed to receive any bytes (%s)\n", + coap_session_str(c_session), coap_socket_strerror()); + } + if (ret == 0) { + /* graceful shutdown */ + c_session->sock.flags &= ~COAP_SOCKET_CAN_READ; + return 0; + } else if (ret == COAP_SOCKET_ERROR) + c_session->sock.flags &= ~COAP_SOCKET_CAN_READ; + else if (ret < (ssize_t)outl) + c_session->sock.flags &= ~COAP_SOCKET_CAN_READ; + return ret; + } + return ret; +} + +/* + * return +ve data amount + * 0 no more + * -1 error (error in errno) + */ +static ssize_t +coap_sock_write(gnutls_transport_ptr_t context, const void *in, size_t inl) { + int ret = 0; + coap_session_t *c_session = (coap_session_t *)context; + + ret = (int)coap_socket_write(&c_session->sock, in, inl); + if (ret > 0) { + coap_log(LOG_DEBUG, "* %s: sent %d bytes\n", + coap_session_str(c_session), ret); + } else if (ret < 0) { + if ((c_session->state == COAP_SESSION_STATE_CSM || + c_session->state == COAP_SESSION_STATE_HANDSHAKE) && + (errno == EPIPE || errno == ECONNRESET)) { + /* + * Need to handle a TCP timing window where an agent continues with + * the sending of the next handshake or a CSM. + * However, the peer does not like a certificate and so sends a + * fatal alert and closes the TCP session. + * The sending of the next handshake or CSM may get terminated because + * of the closed TCP session, but there is still an outstanding alert + * to be read in and reported on. + * In this case, pretend that sending the info was fine so that the + * alert can be read (which effectively is what happens with DTLS). + */ + ret = inl; + } + else { + coap_log(LOG_DEBUG, "* %s: failed to send %zd bytes (%s) state %d\n", + coap_session_str(c_session), inl, coap_socket_strerror(), + c_session->state); + } + } + if (ret == 0) { + errno = EAGAIN; + ret = -1; + } + return ret; +} + +#if COAP_CLIENT_SUPPORT +void *coap_tls_new_client_session(coap_session_t *c_session, int *connected) { + coap_gnutls_env_t *g_env = gnutls_malloc(sizeof(coap_gnutls_env_t)); + coap_gnutls_context_t *g_context = + ((coap_gnutls_context_t *)c_session->context->dtls_context); +#if (GNUTLS_VERSION_NUMBER >= 0x030606) + int flags = GNUTLS_CLIENT | GNUTLS_NONBLOCK | GNUTLS_ENABLE_RAWPK; +#else /* < 3.6.6 */ + int flags = GNUTLS_CLIENT | GNUTLS_NONBLOCK; +#endif /* < 3.6.6 */ + int ret; + + if (!g_env) { + return NULL; + } + memset(g_env, 0, sizeof(coap_gnutls_env_t)); + + *connected = 0; + G_CHECK(gnutls_init(&g_env->g_session, flags), "gnutls_init"); + + gnutls_transport_set_pull_function(g_env->g_session, coap_sock_read); + gnutls_transport_set_push_function(g_env->g_session, coap_sock_write); + gnutls_transport_set_pull_timeout_function(g_env->g_session, receive_timeout); + /* So we can track the coap_session_t in callbacks */ + gnutls_transport_set_ptr(g_env->g_session, c_session); + + gnutls_priority_set(g_env->g_session, g_context->priority_cache); + setup_client_ssl_session(c_session, g_env); + + gnutls_handshake_set_timeout(g_env->g_session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); + + c_session->tls = g_env; + ret = do_gnutls_handshake(c_session, g_env); + if (ret == 1) { + *connected = 1; + coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, c_session); + coap_session_send_csm(c_session); + } + return g_env; + +fail: + if (g_env) + gnutls_free(g_env); + return NULL; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +void *coap_tls_new_server_session(coap_session_t *c_session, int *connected) { + coap_gnutls_env_t *g_env = gnutls_malloc(sizeof(coap_gnutls_env_t)); + coap_gnutls_context_t *g_context = + ((coap_gnutls_context_t *)c_session->context->dtls_context); +#if (GNUTLS_VERSION_NUMBER >= 0x030606) + int flags = GNUTLS_SERVER | GNUTLS_NONBLOCK | GNUTLS_ENABLE_RAWPK; +#else /* < 3.6.6 */ + int flags = GNUTLS_SERVER | GNUTLS_NONBLOCK; +#endif /* < 3.6.6 */ + int ret; + + if (!g_env) + return NULL; + memset(g_env, 0, sizeof(coap_gnutls_env_t)); + + *connected = 0; + G_CHECK(gnutls_init(&g_env->g_session, flags), "gnutls_init"); + + gnutls_transport_set_pull_function(g_env->g_session, coap_sock_read); + gnutls_transport_set_push_function(g_env->g_session, coap_sock_write); + gnutls_transport_set_pull_timeout_function(g_env->g_session, receive_timeout); + /* So we can track the coap_session_t in callbacks */ + gnutls_transport_set_ptr(g_env->g_session, c_session); + + setup_server_ssl_session(c_session, g_env); + + gnutls_priority_set(g_env->g_session, g_context->priority_cache); + gnutls_handshake_set_timeout(g_env->g_session, + GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); + + c_session->tls = g_env; + ret = do_gnutls_handshake(c_session, g_env); + if (ret == 1) { + *connected = 1; + } + return g_env; + +fail: + return NULL; +} +#endif /* COAP_SERVER_SUPPORT */ + +void coap_tls_free_session(coap_session_t *c_session) { + coap_dtls_free_session(c_session); + return; +} + +/* + * return +ve data amount + * 0 no more + * -1 error (error in errno) + */ +ssize_t coap_tls_write(coap_session_t *c_session, + const uint8_t *data, + size_t data_len +) { + int ret; + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + + assert(g_env != NULL); + + c_session->dtls_event = -1; + if (g_env->established) { + ret = gnutls_record_send(g_env->g_session, data, data_len); + + if (ret <= 0) { + switch (ret) { + case GNUTLS_E_AGAIN: + ret = 0; + break; + case GNUTLS_E_PUSH_ERROR: + case GNUTLS_E_PULL_ERROR: + case GNUTLS_E_PREMATURE_TERMINATION: + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + case GNUTLS_E_FATAL_ALERT_RECEIVED: + /* Stop the sending of an alert on closedown */ + g_env->sent_alert = 1; + log_last_alert(c_session, g_env->g_session); + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + default: + coap_log(LOG_WARNING, + "coap_tls_write: gnutls_record_send " + "returned %d: '%s'\n", + ret, gnutls_strerror(ret)); + ret = -1; + break; + } + if (ret == -1) { + coap_log(LOG_INFO, "coap_tls_write: cannot send PDU\n"); + } + } + } + else { + ret = do_gnutls_handshake(c_session, g_env); + if (ret == 1) { + coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, + c_session); + coap_session_send_csm(c_session); + } + else { + ret = -1; + } + } + + if (c_session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(c_session->context, c_session->dtls_event, c_session); + if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || + c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + ret = -1; + } + } + + return ret; +} + +/* + * return +ve data amount + * 0 no more + * -1 error (error in errno) + */ +ssize_t coap_tls_read(coap_session_t *c_session, + uint8_t *data, + size_t data_len +) { + coap_gnutls_env_t *g_env = (coap_gnutls_env_t *)c_session->tls; + int ret = -1; + + if (!g_env) + return -1; + + c_session->dtls_event = -1; + if (!g_env->established && !g_env->sent_alert) { + ret = do_gnutls_handshake(c_session, g_env); + if (ret == 1) { + coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, + c_session); + coap_session_send_csm(c_session); + } + } + if (c_session->state != COAP_SESSION_STATE_NONE && g_env->established) { + ret = gnutls_record_recv(g_env->g_session, data, (int)data_len); + if (ret <= 0) { + switch (ret) { + case 0: + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + break; + case GNUTLS_E_AGAIN: + errno = EAGAIN; + ret = 0; + break; + case GNUTLS_E_PULL_ERROR: + c_session->dtls_event = COAP_EVENT_DTLS_ERROR; + break; + case GNUTLS_E_FATAL_ALERT_RECEIVED: + /* Stop the sending of an alert on closedown */ + g_env->sent_alert = 1; + log_last_alert(c_session, g_env->g_session); + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + case GNUTLS_E_WARNING_ALERT_RECEIVED: + log_last_alert(c_session, g_env->g_session); + c_session->dtls_event = COAP_EVENT_DTLS_ERROR; + ret = 0; + break; + default: + coap_log(LOG_WARNING, + "coap_tls_read: gnutls_record_recv " + "returned %d: '%s'\n", + ret, gnutls_strerror(ret)); + ret = -1; + break; + } + } + } + + if (c_session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(c_session->context, c_session->dtls_event, c_session); + if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || + c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + ret = -1; + } + } + return ret; +} +#endif /* !COAP_DISABLE_TCP */ + +#if COAP_SERVER_SUPPORT +coap_digest_ctx_t * +coap_digest_setup(void) { + gnutls_hash_hd_t digest_ctx; + + if (gnutls_hash_init(&digest_ctx, GNUTLS_DIG_SHA256)) { + return NULL; + } + return digest_ctx; +} + +void +coap_digest_free(coap_digest_ctx_t *digest_ctx) { + gnutls_hash_deinit(digest_ctx, NULL); +} + +int +coap_digest_update(coap_digest_ctx_t *digest_ctx, + const uint8_t *data, + size_t data_len) { + int ret = gnutls_hash(digest_ctx, data, data_len); + + return ret == 0; +} + +int +coap_digest_final(coap_digest_ctx_t *digest_ctx, + coap_digest_t *digest_buffer) { + gnutls_hash_output(digest_ctx, (uint8_t*)digest_buffer); + + coap_digest_free(digest_ctx); + return 1; +} +#endif /* COAP_SERVER_SUPPORT */ + +#else /* !HAVE_LIBGNUTLS */ + +#ifdef __clang__ +/* Make compilers happy that do not like empty modules. As this function is + * never used, we ignore -Wunused-function at the end of compiling this file + */ +#pragma GCC diagnostic ignored "-Wunused-function" +#endif +static inline void dummy(void) { +} + +#endif /* !HAVE_LIBGNUTLS */ diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_hashkey.c b/examples/espidf-coap-server/components/libcoap/src/coap_hashkey.c new file mode 100644 index 000000000..70dadbf0a --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_hashkey.c @@ -0,0 +1,33 @@ +/* coap_hashkey.c -- definition of hash key type and helper functions + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_hashkey.c + * @brief Hashkey functions + */ + +#include "coap3/coap_internal.h" + +void +coap_hash_impl(const unsigned char *s, size_t len, coap_key_t h) { + size_t j; + + while (len--) { + j = sizeof(coap_key_t)-1; + + while (j) { + h[j] = ((h[j] << 7) | (h[j-1] >> 1)) + h[j]; + --j; + } + + h[0] = (h[0] << 7) + h[0] + *s++; + } +} + diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_io.c b/examples/espidf-coap-server/components/libcoap/src/coap_io.c new file mode 100644 index 000000000..8db5613a1 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_io.c @@ -0,0 +1,1615 @@ +/* coap_io.c -- Default network I/O functions for libcoap + * + * Copyright (C) 2012,2014,2016-2022 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_io.c + * @brief Network I/O functions + */ + +#include "coap3/coap_internal.h" + +#ifdef HAVE_STDIO_H +# include +#endif + +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +# define OPTVAL_T(t) (t) +# define OPTVAL_GT(t) (t) +#endif +#ifdef HAVE_SYS_IOCTL_H + #include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_WS2TCPIP_H +#include +# define OPTVAL_T(t) (const char*)(t) +# define OPTVAL_GT(t) (char*)(t) +# undef CMSG_DATA +# define CMSG_DATA WSA_CMSG_DATA +#endif +#ifdef HAVE_SYS_UIO_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#ifdef COAP_EPOLL_SUPPORT +#include +#include +#ifdef HAVE_LIMITS_H +#include +#endif +#endif /* COAP_EPOLL_SUPPORT */ + +#ifdef WITH_CONTIKI +# include "uip.h" +#endif + +#if !defined(WITH_CONTIKI) && !defined(RIOT_VERSION) + /* define generic PKTINFO for IPv4 */ +#if defined(IP_PKTINFO) +# define GEN_IP_PKTINFO IP_PKTINFO +#elif defined(IP_RECVDSTADDR) +# define GEN_IP_PKTINFO IP_RECVDSTADDR +#else +# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS." +#endif /* IP_PKTINFO */ + +/* define generic KTINFO for IPv6 */ +#ifdef IPV6_RECVPKTINFO +# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO +#elif defined(IPV6_PKTINFO) +# define GEN_IPV6_PKTINFO IPV6_PKTINFO +#else +# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS." +#endif /* IPV6_RECVPKTINFO */ +#endif /* !(WITH_CONTIKI || RIOT_VERSION) */ + +#ifdef WITH_CONTIKI +static int ep_initialized = 0; + +coap_endpoint_t * + coap_malloc_endpoint() { + static coap_endpoint_t ep; + + if (ep_initialized) { + return NULL; + } else { + ep_initialized = 1; + return &ep; + } +} + +void +coap_mfree_endpoint(coap_endpoint_t *ep) { + ep_initialized = 0; +} + +int +coap_socket_bind_udp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr) { + sock->conn = udp_new(NULL, 0, NULL); + + if (!sock->conn) { + coap_log(LOG_WARNING, "coap_socket_bind_udp"); + return 0; + } + + coap_address_init(bound_addr); + uip_ipaddr_copy(&bound_addr->addr, &listen_addr->addr); + bound_addr->port = listen_addr->port; + udp_bind((struct uip_udp_conn *)sock->conn, bound_addr->port); + return 1; +} + +int +coap_socket_connect_udp(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + return 0; +} + +ssize_t +coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) { + return -1; +} + +ssize_t +coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) { + return -1; +} + +void coap_socket_close(coap_socket_t *sock) { + if (sock->conn) + uip_udp_remove((struct uip_udp_conn *)sock->conn); + sock->flags = COAP_SOCKET_EMPTY; +} + +#else + +#if COAP_SERVER_SUPPORT +coap_endpoint_t * + coap_malloc_endpoint(void) { + return (coap_endpoint_t *)coap_malloc_type(COAP_ENDPOINT, sizeof(coap_endpoint_t)); +} + +void +coap_mfree_endpoint(coap_endpoint_t *ep) { + coap_free_type(COAP_ENDPOINT, ep); +} +#endif /* COAP_SERVER_SUPPORT */ + +int +coap_socket_bind_udp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr) { +#ifndef RIOT_VERSION + int on = 1, off = 0; +#endif /* RIOT_VERSION */ +#ifdef _WIN32 + u_long u_on = 1; +#endif + + sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_DGRAM, 0); + + if (sock->fd == COAP_INVALID_SOCKET) { + coap_log(LOG_WARNING, + "coap_socket_bind_udp: socket: %s\n", coap_socket_strerror()); + goto error; + } +#ifndef RIOT_VERSION +#ifdef _WIN32 + if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { +#else + if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { +#endif + coap_log(LOG_WARNING, + "coap_socket_bind_udp: ioctl FIONBIO: %s\n", coap_socket_strerror()); + } + +#ifndef RIOT_VERSION + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_bind_udp: setsockopt SO_REUSEADDR: %s\n", + coap_socket_strerror()); +#endif /* RIOT_VERSION */ + + switch (listen_addr->addr.sa.sa_family) { + case AF_INET: + if (setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_ALERT, + "coap_socket_bind_udp: setsockopt IP_PKTINFO: %s\n", + coap_socket_strerror()); + break; + case AF_INET6: + /* Configure the socket as dual-stacked */ + if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR) + coap_log(LOG_ALERT, + "coap_socket_bind_udp: setsockopt IPV6_V6ONLY: %s\n", + coap_socket_strerror()); +#if !defined(ESPIDF_VERSION) + if (setsockopt(sock->fd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_ALERT, + "coap_socket_bind_udp: setsockopt IPV6_PKTINFO: %s\n", + coap_socket_strerror()); +#endif /* !defined(ESPIDF_VERSION) */ + setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)); + /* ignore error, because likely cause is that IPv4 is disabled at the os + level */ + break; + default: + coap_log(LOG_ALERT, "coap_socket_bind_udp: unsupported sa_family\n"); + break; + } +#endif /* RIOT_VERSION */ + + if (bind(sock->fd, &listen_addr->addr.sa, + listen_addr->addr.sa.sa_family == AF_INET ? + (socklen_t)sizeof(struct sockaddr_in) : + (socklen_t)listen_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_bind_udp: bind: %s\n", + coap_socket_strerror()); + goto error; + } + + bound_addr->size = (socklen_t)sizeof(*bound_addr); + if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) { + coap_log(LOG_WARNING, + "coap_socket_bind_udp: getsockname: %s\n", + coap_socket_strerror()); + goto error; + } + + return 1; + +error: + coap_socket_close(sock); + return 0; +} + +#if COAP_CLIENT_SUPPORT +int +coap_socket_connect_udp(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr) { +#ifndef RIOT_VERSION + int on = 1; + int off = 0; +#endif /* RIOT_VERSION */ +#ifdef _WIN32 + u_long u_on = 1; +#endif + coap_address_t connect_addr; + int is_mcast = coap_is_mcast(server); + coap_address_copy(&connect_addr, server); + + sock->flags &= ~(COAP_SOCKET_CONNECTED | COAP_SOCKET_MULTICAST); + sock->fd = socket(connect_addr.addr.sa.sa_family, SOCK_DGRAM, 0); + + if (sock->fd == COAP_INVALID_SOCKET) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: socket: %s\n", + coap_socket_strerror()); + goto error; + } + +#ifndef RIOT_VERSION +#ifdef _WIN32 + if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { +#else + if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { +#endif + coap_log(LOG_WARNING, "coap_socket_connect_udp: ioctl FIONBIO: %s\n", + coap_socket_strerror()); + } +#endif /* RIOT_VERSION */ + + switch (connect_addr.addr.sa.sa_family) { + case AF_INET: + if (connect_addr.addr.sin.sin_port == 0) + connect_addr.addr.sin.sin_port = htons(default_port); + break; + case AF_INET6: + if (connect_addr.addr.sin6.sin6_port == 0) + connect_addr.addr.sin6.sin6_port = htons(default_port); +#ifndef RIOT_VERSION + /* Configure the socket as dual-stacked */ + if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_connect_udp: setsockopt IPV6_V6ONLY: %s\n", + coap_socket_strerror()); +#endif /* RIOT_VERSION */ + break; + default: + coap_log(LOG_ALERT, "coap_socket_connect_udp: unsupported sa_family\n"); + break; + } + + if (local_if && local_if->addr.sa.sa_family) { +#ifndef RIOT_VERSION + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_connect_udp: setsockopt SO_REUSEADDR: %s\n", + coap_socket_strerror()); +#endif /* RIOT_VERSION */ + if (bind(sock->fd, &local_if->addr.sa, + local_if->addr.sa.sa_family == AF_INET ? + (socklen_t)sizeof(struct sockaddr_in) : + (socklen_t)local_if->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: bind: %s\n", + coap_socket_strerror()); + goto error; + } + } + + /* special treatment for sockets that are used for multicast communication */ + if (is_mcast) { + if (!(local_if && local_if->addr.sa.sa_family)) { + /* Bind to a (unused) port to simplify logging */ + coap_address_t bind_addr; + + coap_address_init(&bind_addr); + bind_addr.addr.sa.sa_family = connect_addr.addr.sa.sa_family; + if (bind(sock->fd, &bind_addr.addr.sa, + bind_addr.addr.sa.sa_family == AF_INET ? + (socklen_t)sizeof(struct sockaddr_in) : + (socklen_t)bind_addr.size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: bind: %s\n", + coap_socket_strerror()); + goto error; + } + } + if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, + "coap_socket_connect_udp: getsockname for multicast socket: %s\n", + coap_socket_strerror()); + } + coap_address_copy(remote_addr, &connect_addr); + sock->flags |= COAP_SOCKET_MULTICAST; + return 1; + } + + if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: connect: %s\n", + coap_socket_strerror()); + goto error; + } + + if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: getsockname: %s\n", + coap_socket_strerror()); + } + + if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_udp: getpeername: %s\n", + coap_socket_strerror()); + } + + sock->flags |= COAP_SOCKET_CONNECTED; + return 1; + +error: + coap_socket_close(sock); + return 0; +} +#endif /* COAP_CLIENT_SUPPORT */ + +void coap_socket_close(coap_socket_t *sock) { + if (sock->fd != COAP_INVALID_SOCKET) { +#ifdef COAP_EPOLL_SUPPORT +#if COAP_SERVER_SUPPORT + coap_context_t *context = sock->session ? sock->session->context : + sock->endpoint ? sock->endpoint->context : NULL; +#else /* COAP_SERVER_SUPPORT */ + coap_context_t *context = sock->session ? sock->session->context : NULL; +#endif /* COAP_SERVER_SUPPORT */ + if (context != NULL) { + int ret; + struct epoll_event event; + + /* Kernels prior to 2.6.9 expect non NULL event parameter */ + ret = epoll_ctl(context->epfd, EPOLL_CTL_DEL, sock->fd, &event); + if (ret == -1) { + coap_log(LOG_ERR, + "%s: epoll_ctl DEL failed: %s (%d)\n", + "coap_socket_close", + coap_socket_strerror(), errno); + } + } + sock->endpoint = NULL; + sock->session = NULL; +#endif /* COAP_EPOLL_SUPPORT */ + coap_closesocket(sock->fd); + sock->fd = COAP_INVALID_SOCKET; + } + sock->flags = COAP_SOCKET_EMPTY; +} + +#ifdef COAP_EPOLL_SUPPORT +void +coap_epoll_ctl_mod(coap_socket_t *sock, + uint32_t events, + const char *func +) { + int ret; + struct epoll_event event; + coap_context_t *context; + + if (sock == NULL) + return; + +#if COAP_SERVER_SUPPORT + context = sock->session ? sock->session->context : + sock->endpoint ? sock->endpoint->context : NULL; +#else /* COAP_SERVER_SUPPORT */ + context = sock->session ? sock->session->context : NULL; +#endif /* COAP_SERVER_SUPPORT */ + if (context == NULL) + return; + + event.events = events; + event.data.ptr = sock; + + ret = epoll_ctl(context->epfd, EPOLL_CTL_MOD, sock->fd, &event); + if (ret == -1) { + coap_log(LOG_ERR, + "%s: epoll_ctl MOD failed: %s (%d)\n", + func, + coap_socket_strerror(), errno); + } +} + +void +coap_update_epoll_timer(coap_context_t *context, coap_tick_t delay) +{ + if (context->eptimerfd != -1) { + coap_tick_t now; + + coap_ticks(&now); + if (context->next_timeout == 0 || context->next_timeout > now + delay) { + struct itimerspec new_value; + int ret; + + context->next_timeout = now + delay; + memset(&new_value, 0, sizeof(new_value)); + if (delay == 0) { + new_value.it_value.tv_nsec = 1; /* small but not zero */ + } + else { + new_value.it_value.tv_sec = delay / COAP_TICKS_PER_SECOND; + new_value.it_value.tv_nsec = (delay % COAP_TICKS_PER_SECOND) * + 1000000; + } + ret = timerfd_settime(context->eptimerfd, 0, &new_value, NULL); + if (ret == -1) { + coap_log(LOG_ERR, + "%s: timerfd_settime failed: %s (%d)\n", + "coap_resource_notify_observers", + coap_socket_strerror(), errno); + } +#ifdef COAP_DEBUG_WAKEUP_TIMES + else { + coap_log(LOG_INFO, "****** Next wakeup time %3ld.%09ld\n", + new_value.it_value.tv_sec, new_value.it_value.tv_nsec); + } +#endif /* COAP_DEBUG_WAKEUP_TIMES */ + } + } +} + +#endif /* COAP_EPOLL_SUPPORT */ + +ssize_t +coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) { + ssize_t r; + + sock->flags &= ~(COAP_SOCKET_WANT_WRITE | COAP_SOCKET_CAN_WRITE); +#ifdef _WIN32 + r = send(sock->fd, (const char *)data, (int)data_len, 0); +#else +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif /* MSG_NOSIGNAL */ + r = send(sock->fd, data, data_len, MSG_NOSIGNAL); +#endif + if (r == COAP_SOCKET_ERROR) { +#ifdef _WIN32 + if (WSAGetLastError() == WSAEWOULDBLOCK) { +#elif EAGAIN != EWOULDBLOCK + if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { +#else + if (errno==EAGAIN || errno == EINTR) { +#endif + sock->flags |= COAP_SOCKET_WANT_WRITE; +#ifdef COAP_EPOLL_SUPPORT + coap_epoll_ctl_mod(sock, + EPOLLOUT | + ((sock->flags & COAP_SOCKET_WANT_READ) ? + EPOLLIN : 0), + __func__); +#endif /* COAP_EPOLL_SUPPORT */ + return 0; + } + if (errno == EPIPE || errno == ECONNRESET) { + coap_log(LOG_INFO, "coap_socket_write: send: %s\n", + coap_socket_strerror()); + } + else { + coap_log(LOG_WARNING, "coap_socket_write: send: %s\n", + coap_socket_strerror()); + } + return -1; + } + if (r < (ssize_t)data_len) { + sock->flags |= COAP_SOCKET_WANT_WRITE; +#ifdef COAP_EPOLL_SUPPORT + coap_epoll_ctl_mod(sock, + EPOLLOUT | + ((sock->flags & COAP_SOCKET_WANT_READ) ? + EPOLLIN : 0), + __func__); +#endif /* COAP_EPOLL_SUPPORT */ + } + return r; +} + +ssize_t +coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) { + ssize_t r; +#ifdef _WIN32 + int error; +#endif + +#ifdef _WIN32 + r = recv(sock->fd, (char *)data, (int)data_len, 0); +#else + r = recv(sock->fd, data, data_len, 0); +#endif + if (r == 0) { + /* graceful shutdown */ + sock->flags &= ~COAP_SOCKET_CAN_READ; + return -1; + } else if (r == COAP_SOCKET_ERROR) { + sock->flags &= ~COAP_SOCKET_CAN_READ; +#ifdef _WIN32 + error = WSAGetLastError(); + if (error == WSAEWOULDBLOCK) { +#elif EAGAIN != EWOULDBLOCK + if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { +#else + if (errno==EAGAIN || errno == EINTR) { +#endif + return 0; + } +#ifdef _WIN32 + if (error != WSAECONNRESET) +#else + if (errno != ECONNRESET) +#endif + coap_log(LOG_WARNING, "coap_socket_read: recv: %s\n", + coap_socket_strerror()); + return -1; + } + if (r < (ssize_t)data_len) + sock->flags &= ~COAP_SOCKET_CAN_READ; + return r; +} + +#endif /* WITH_CONTIKI */ + +#if (!defined(WITH_CONTIKI)) != ( defined(HAVE_NETINET_IN_H) || defined(HAVE_WS2TCPIP_H) ) +/* define struct in6_pktinfo and struct in_pktinfo if not available + FIXME: check with configure +*/ +struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ +}; + +struct in_pktinfo { + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; +}; +#endif + +#if !defined(WITH_CONTIKI) && !defined(SOL_IP) +/* Solaris expects level IPPROTO_IP for ancillary data. */ +#define SOL_IP IPPROTO_IP +#endif + +#if defined(_WIN32) +#include +static __declspec(thread) LPFN_WSARECVMSG lpWSARecvMsg = NULL; +/* Map struct WSABUF fields to their posix counterpart */ +#define msghdr _WSAMSG +#define msg_name name +#define msg_namelen namelen +#define msg_iov lpBuffers +#define msg_iovlen dwBufferCount +#define msg_control Control.buf +#define msg_controllen Control.len +#define iovec _WSABUF +#define iov_base buf +#define iov_len len +#define iov_len_t u_long +#undef CMSG_DATA +#define CMSG_DATA WSA_CMSG_DATA +#define ipi_spec_dst ipi_addr +#pragma warning( disable : 4116 ) +#else +#define iov_len_t size_t +#endif + +#if defined(_CYGWIN_ENV) +#define ipi_spec_dst ipi_addr +#endif + +#ifndef RIOT_VERSION +ssize_t +coap_network_send(coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen) { + ssize_t bytes_written = 0; + + if (!coap_debug_send_packet()) { + bytes_written = (ssize_t)datalen; +#ifndef WITH_CONTIKI + } else if (sock->flags & COAP_SOCKET_CONNECTED) { +#ifdef _WIN32 + bytes_written = send(sock->fd, (const char *)data, (int)datalen, 0); +#else + bytes_written = send(sock->fd, data, datalen, 0); +#endif +#endif + } else { +#ifdef _WIN32 + DWORD dwNumberOfBytesSent = 0; + int r; +#endif +#ifdef HAVE_STRUCT_CMSGHDR + /* a buffer large enough to hold all packet info types, ipv6 is the largest */ + char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + struct msghdr mhdr; + struct iovec iov[1]; + const void *addr = &session->addr_info.remote.addr; + + assert(session); + + memcpy (&iov[0].iov_base, &data, sizeof (iov[0].iov_base)); + iov[0].iov_len = (iov_len_t)datalen; + + memset(buf, 0, sizeof (buf)); + + memset(&mhdr, 0, sizeof(struct msghdr)); + memcpy (&mhdr.msg_name, &addr, sizeof (mhdr.msg_name)); + mhdr.msg_namelen = session->addr_info.remote.size; + + mhdr.msg_iov = iov; + mhdr.msg_iovlen = 1; + + if (!coap_address_isany(&session->addr_info.local) && + !coap_is_mcast(&session->addr_info.local)) + switch (session->addr_info.local.addr.sa.sa_family) { + case AF_INET6: + { + struct cmsghdr *cmsg; + + if (IN6_IS_ADDR_V4MAPPED(&session->addr_info.local.addr.sin6.sin6_addr)) { +#if defined(IP_PKTINFO) + struct in_pktinfo *pktinfo; + mhdr.msg_control = buf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + + cmsg = CMSG_FIRSTHDR(&mhdr); + cmsg->cmsg_level = SOL_IP; + cmsg->cmsg_type = IP_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + + pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); + + pktinfo->ipi_ifindex = session->ifindex; + memcpy(&pktinfo->ipi_spec_dst, + session->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12, + sizeof(pktinfo->ipi_spec_dst)); +#elif defined(IP_SENDSRCADDR) + mhdr.msg_control = buf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); + + cmsg = CMSG_FIRSTHDR(&mhdr); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + + memcpy(CMSG_DATA(cmsg), + session->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12, + sizeof(struct in_addr)); +#endif /* IP_PKTINFO */ + } else { + struct in6_pktinfo *pktinfo; + mhdr.msg_control = buf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + + cmsg = CMSG_FIRSTHDR(&mhdr); + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + + pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg); + + pktinfo->ipi6_ifindex = session->ifindex; + memcpy(&pktinfo->ipi6_addr, + &session->addr_info.local.addr.sin6.sin6_addr, + sizeof(pktinfo->ipi6_addr)); + } + break; + } + case AF_INET: + { +#if defined(IP_PKTINFO) + struct cmsghdr *cmsg; + struct in_pktinfo *pktinfo; + + mhdr.msg_control = buf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + + cmsg = CMSG_FIRSTHDR(&mhdr); + cmsg->cmsg_level = SOL_IP; + cmsg->cmsg_type = IP_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + + pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); + + pktinfo->ipi_ifindex = session->ifindex; + memcpy(&pktinfo->ipi_spec_dst, + &session->addr_info.local.addr.sin.sin_addr, + sizeof(pktinfo->ipi_spec_dst)); +#elif defined(IP_SENDSRCADDR) + struct cmsghdr *cmsg; + mhdr.msg_control = buf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); + + cmsg = CMSG_FIRSTHDR(&mhdr); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + + memcpy(CMSG_DATA(cmsg), + &session->addr_info.local.addr.sin.sin_addr, + sizeof(struct in_addr)); +#endif /* IP_PKTINFO */ + break; + } + default: + /* error */ + coap_log(LOG_WARNING, "protocol not supported\n"); + bytes_written = -1; + } +#endif /* HAVE_STRUCT_CMSGHDR */ + +#ifdef _WIN32 + r = WSASendMsg(sock->fd, &mhdr, 0 /*dwFlags*/, &dwNumberOfBytesSent, NULL /*lpOverlapped*/, NULL /*lpCompletionRoutine*/); + if (r == 0) + bytes_written = (ssize_t)dwNumberOfBytesSent; + else + bytes_written = -1; +#else +#ifdef HAVE_STRUCT_CMSGHDR + bytes_written = sendmsg(sock->fd, &mhdr, 0); +#elif !defined(CONTIKI) /* ! HAVE_STRUCT_CMSGHDR */ + bytes_written = sendto(sock->fd, data, datalen, 0, + &session->addr_info.remote.addr.sa, + session->addr_info.remote.size); +#endif /* ! HAVE_STRUCT_CMSGHDR */ +#endif +#if defined(WITH_CONTIKI) + /* FIXME: untested */ + /* FIXME: is there a way to check if send was successful? */ + (void)datalen; + (void)data; + uip_udp_packet_sendto((struct uip_udp_conn *)sock->conn, data, datalen, + &session->addr_info.remote.addr, session->addr_info.remote.port); + bytes_written = datalen; +#endif /* WITH_CONTIKI */ + } + + if (bytes_written < 0) + coap_log(LOG_CRIT, "coap_network_send: %s\n", coap_socket_strerror()); + + return bytes_written; +} +#endif /* RIOT_VERSION */ + +#define SIN6(A) ((struct sockaddr_in6 *)(A)) + +void +coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) { + *address = packet->payload; + *length = packet->length; +} + +#ifndef RIOT_VERSION +ssize_t +coap_network_read(coap_socket_t *sock, coap_packet_t *packet) { + ssize_t len = -1; + + assert(sock); + assert(packet); + + if ((sock->flags & COAP_SOCKET_CAN_READ) == 0) { + return -1; + } else { + /* clear has-data flag */ + sock->flags &= ~COAP_SOCKET_CAN_READ; + } + +#if !defined(WITH_CONTIKI) && !defined(RIOT_VERSION) + if (sock->flags & COAP_SOCKET_CONNECTED) { +#ifdef _WIN32 + len = recv(sock->fd, (char *)packet->payload, COAP_RXBUFFER_SIZE, 0); +#else + len = recv(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0); +#endif + if (len < 0) { +#ifdef _WIN32 + if (WSAGetLastError() == WSAECONNRESET || + WSAGetLastError() == WSAECONNREFUSED) { +#else + if (errno == ECONNREFUSED || errno == EHOSTUNREACH) { +#endif + /* client-side ICMP destination unreachable, ignore it */ + coap_log(LOG_WARNING, "** %s: coap_network_read: ICMP: %s\n", + sock->session ? + coap_session_str(sock->session) : "", + coap_socket_strerror()); + return -2; + } + coap_log(LOG_WARNING, "** %s: coap_network_read: %s\n", + sock->session ? + coap_session_str(sock->session) : "", + coap_socket_strerror()); + goto error; + } else if (len > 0) { + packet->length = (size_t)len; + } + } else { +#endif /* !(WITH_CONTIKI || RIOT_VERSION) */ +#if defined(_WIN32) + DWORD dwNumberOfBytesRecvd = 0; + int r; +#endif +#if !defined(WITH_CONTIKI) +#ifdef HAVE_STRUCT_CMSGHDR + /* a buffer large enough to hold all packet info types, ipv6 is the largest */ + char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + struct cmsghdr *cmsg; + struct msghdr mhdr; + struct iovec iov[1]; + + iov[0].iov_base = packet->payload; + iov[0].iov_len = (iov_len_t)COAP_RXBUFFER_SIZE; + + memset(&mhdr, 0, sizeof(struct msghdr)); + + mhdr.msg_name = (struct sockaddr*)&packet->addr_info.remote.addr; + mhdr.msg_namelen = sizeof(packet->addr_info.remote.addr); + + mhdr.msg_iov = iov; + mhdr.msg_iovlen = 1; + + mhdr.msg_control = buf; + mhdr.msg_controllen = sizeof(buf); + /* set a big first length incase recvmsg() does not implement updating + msg_control as well as preset the first cmsg with bad data */ + cmsg = (struct cmsghdr *)buf; + cmsg->cmsg_len = CMSG_LEN(sizeof(buf)); + cmsg->cmsg_level = -1; + cmsg->cmsg_type = -1; + +#if defined(_WIN32) + if (!lpWSARecvMsg) { + GUID wsaid = WSAID_WSARECVMSG; + DWORD cbBytesReturned = 0; + if (WSAIoctl(sock->fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid, sizeof(wsaid), &lpWSARecvMsg, sizeof(lpWSARecvMsg), &cbBytesReturned, NULL, NULL) != 0) { + coap_log(LOG_WARNING, "coap_network_read: no WSARecvMsg\n"); + return -1; + } + } + r = lpWSARecvMsg(sock->fd, &mhdr, &dwNumberOfBytesRecvd, NULL /* LPWSAOVERLAPPED */, NULL /* LPWSAOVERLAPPED_COMPLETION_ROUTINE */); + if (r == 0) + len = (ssize_t)dwNumberOfBytesRecvd; +#else + len = recvmsg(sock->fd, &mhdr, 0); +#endif + +#else /* ! HAVE_STRUCT_CMSGHDR */ + len = recvfrom(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0, + &packet->addr_info.remote.addr.sa, + &packet->addr_info.remote.size); +#endif /* ! HAVE_STRUCT_CMSGHDR */ + + if (len < 0) { +#ifdef _WIN32 + if (WSAGetLastError() == WSAECONNRESET) { +#else + if (errno == ECONNREFUSED) { +#endif + /* server-side ICMP destination unreachable, ignore it. The destination address is in msg_name. */ + return 0; + } + coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror()); + goto error; + } else { +#ifdef HAVE_STRUCT_CMSGHDR + int dst_found = 0; + + packet->addr_info.remote.size = mhdr.msg_namelen; + packet->length = (size_t)len; + + /* Walk through ancillary data records until the local interface + * is found where the data was received. */ + for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) { + + /* get the local interface for IPv6 */ + if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) { + union { + uint8_t *c; + struct in6_pktinfo *p; + } u; + u.c = CMSG_DATA(cmsg); + packet->ifindex = (int)(u.p->ipi6_ifindex); + memcpy(&packet->addr_info.local.addr.sin6.sin6_addr, + &u.p->ipi6_addr, sizeof(struct in6_addr)); + dst_found = 1; + break; + } + + /* local interface for IPv4 */ +#if defined(IP_PKTINFO) + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) { + union { + uint8_t *c; + struct in_pktinfo *p; + } u; + u.c = CMSG_DATA(cmsg); + packet->ifindex = u.p->ipi_ifindex; + if (packet->addr_info.local.addr.sa.sa_family == AF_INET6) { + memset(packet->addr_info.local.addr.sin6.sin6_addr.s6_addr, 0, 10); + packet->addr_info.local.addr.sin6.sin6_addr.s6_addr[10] = 0xff; + packet->addr_info.local.addr.sin6.sin6_addr.s6_addr[11] = 0xff; + memcpy(packet->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12, + &u.p->ipi_addr, sizeof(struct in_addr)); + } else { + memcpy(&packet->addr_info.local.addr.sin.sin_addr, + &u.p->ipi_addr, sizeof(struct in_addr)); + } + dst_found = 1; + break; + } +#elif defined(IP_RECVDSTADDR) + if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) { + packet->ifindex = sock->fd; + memcpy(&packet->addr_info.local.addr.sin.sin_addr, + CMSG_DATA(cmsg), sizeof(struct in_addr)); + dst_found = 1; + break; + } +#endif /* IP_PKTINFO */ + if (!dst_found) { + /* cmsg_level / cmsg_type combination we do not understand + (ignore preset case for bad recvmsg() not updating cmsg) */ + if (cmsg->cmsg_level != -1 && cmsg->cmsg_type != -1) { + coap_log(LOG_DEBUG, + "cmsg_level = %d and cmsg_type = %d not supported - fix\n", + cmsg->cmsg_level, cmsg->cmsg_type); + } + } + } + if (!dst_found) { + /* Not expected, but cmsg_level and cmsg_type don't match above and + may need a new case */ + packet->ifindex = (int)sock->fd; + if (getsockname(sock->fd, &packet->addr_info.local.addr.sa, + &packet->addr_info.local.size) < 0) { + coap_log(LOG_DEBUG, "Cannot determine local port\n"); + } + } +#else /* ! HAVE_STRUCT_CMSGHDR */ + packet->length = (size_t)len; + packet->ifindex = 0; + if (getsockname(sock->fd, &packet->addr_info.local.addr.sa, + &packet->addr_info.local.size) < 0) { + coap_log(LOG_DEBUG, "Cannot determine local port\n"); + goto error; + } +#endif /* ! HAVE_STRUCT_CMSGHDR */ + } +#endif /* !defined(WITH_CONTIKI) && !defined(RIOT_VERSION) */ +#ifdef WITH_CONTIKI + /* FIXME: untested, make this work */ +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) + + if (uip_newdata()) { + uip_ipaddr_copy(&packet->addr_info.remote.addr, &UIP_IP_BUF->srcipaddr); + packet->addr_info.remote.port = UIP_UDP_BUF->srcport; + uip_ipaddr_copy(&(packet)->addr_info.local.addr, &UIP_IP_BUF->destipaddr); + packet->addr_info.local.port = UIP_UDP_BUF->destport; + + len = uip_datalen(); + + if (len > COAP_RXBUFFER_SIZE) { + /* FIXME: we might want to send back a response */ + coap_log(LOG_WARNING, "discarded oversized packet\n"); + return -1; + } + + ((char *)uip_appdata)[len] = 0; + if (LOG_DEBUG <= coap_get_log_level()) { +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 40 +#endif + unsigned char addr_str[INET6_ADDRSTRLEN + 8]; + + if (coap_print_addr(&packet->addr_info.remote, addr_str, + INET6_ADDRSTRLEN + 8)) { + coap_log(LOG_DEBUG, "received %zd bytes from %s\n", len, addr_str); + } + } + + packet->length = len; + memcpy(&packet->payload, uip_appdata, len); + } + +#undef UIP_IP_BUF +#undef UIP_UDP_BUF +#endif /* WITH_CONTIKI */ +#ifdef RIOT_VERSION + packet->src.size = sizeof(packet->src.addr); + len = recvfrom (sock->fd, packet->payload, COAP_RXBUFFER_SIZE, + 0, &packet->src.addr.sa, &packet->src.size); + if (LOG_DEBUG <= coap_get_log_level()) { + unsigned char addr_str[INET6_ADDRSTRLEN + 8]; + + if (coap_print_addr(&packet->src, addr_str, INET6_ADDRSTRLEN + 8)) { + coap_log(LOG_DEBUG, "received %zd bytes from %s\n", len, addr_str); + } + } +#endif /* RIOT_VERSION */ +#if !defined(WITH_CONTIKI) && !defined(RIOT_VERSION) + } +#endif /* !(WITH_CONTIKI || RIOT_VERSION) */ + + if (len >= 0) + return len; +#if !defined(WITH_CONTIKI) && !defined(RIOT_VERSION) +error: +#endif + return -1; +} +#endif /* RIOT_VERSION */ + +#if !defined(WITH_CONTIKI) + +unsigned int +coap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now) { +#ifndef COAP_EPOLL_SUPPORT + (void)ctx; + (void)now; + coap_log(LOG_EMERG, + "coap_io_prepare_epoll() requires libcoap compiled for using epoll\n"); + return 0; +#else /* COAP_EPOLL_SUPPORT */ + coap_socket_t *sockets[1]; + unsigned int max_sockets = sizeof(sockets)/sizeof(sockets[0]); + unsigned int num_sockets; + unsigned int timeout; + + /* Use the common logic */ + timeout = coap_io_prepare_io(ctx, sockets, max_sockets, &num_sockets, now); + /* Save when the next expected I/O is to take place */ + ctx->next_timeout = timeout ? now + timeout : 0; + if (ctx->eptimerfd != -1) { + struct itimerspec new_value; + int ret; + + memset(&new_value, 0, sizeof(new_value)); + coap_ticks(&now); + if (ctx->next_timeout != 0 && ctx->next_timeout > now) { + coap_tick_t rem_timeout = ctx->next_timeout - now; + /* Need to trigger an event on ctx->eptimerfd in the future */ + new_value.it_value.tv_sec = rem_timeout / COAP_TICKS_PER_SECOND; + new_value.it_value.tv_nsec = (rem_timeout % COAP_TICKS_PER_SECOND) * + 1000000; + } +#ifdef COAP_DEBUG_WAKEUP_TIMES + coap_log(LOG_INFO, "****** Next wakeup time %3ld.%09ld\n", + new_value.it_value.tv_sec, new_value.it_value.tv_nsec); +#endif /* COAP_DEBUG_WAKEUP_TIMES */ + /* reset, or specify a future time for eptimerfd to trigger */ + ret = timerfd_settime(ctx->eptimerfd, 0, &new_value, NULL); + if (ret == -1) { + coap_log(LOG_ERR, + "%s: timerfd_settime failed: %s (%d)\n", + "coap_io_prepare_epoll", + coap_socket_strerror(), errno); + } + } + return timeout; +#endif /* COAP_EPOLL_SUPPORT */ +} + +/* + * return 0 No i/o pending + * +ve millisecs to next i/o activity + */ +unsigned int +coap_io_prepare_io(coap_context_t *ctx, + coap_socket_t *sockets[], + unsigned int max_sockets, + unsigned int *num_sockets, + coap_tick_t now) +{ + coap_queue_t *nextpdu; + coap_session_t *s, *rtmp; + coap_tick_t timeout = 0; + coap_tick_t s_timeout; +#if COAP_SERVER_SUPPORT + int check_dtls_timeouts = 0; +#endif /* COAP_SERVER_SUPPORT */ +#ifdef COAP_EPOLL_SUPPORT + (void)sockets; + (void)max_sockets; +#endif /* COAP_EPOLL_SUPPORT */ + + *num_sockets = 0; + +#if COAP_SERVER_SUPPORT + /* Check to see if we need to send off any Observe requests */ + coap_check_notify(ctx); +#endif /* COAP_SERVER_SUPPORT */ + +#ifndef WITHOUT_ASYNC + /* Check to see if we need to send off any Async requests */ + timeout = coap_check_async(ctx, now); +#endif /* WITHOUT_ASYNC */ + + /* Check to see if we need to send off any retransmit request */ + nextpdu = coap_peek_next(ctx); + while (nextpdu && now >= ctx->sendqueue_basetime && + nextpdu->t <= now - ctx->sendqueue_basetime) { + coap_retransmit(ctx, coap_pop_next(ctx)); + nextpdu = coap_peek_next(ctx); + } + if (nextpdu && (timeout == 0 || + nextpdu->t - (now - ctx->sendqueue_basetime) < timeout)) + timeout = nextpdu->t - (now - ctx->sendqueue_basetime); + + /* Check for DTLS timeouts */ + if (ctx->dtls_context) { + if (coap_dtls_is_context_timeout()) { + coap_tick_t tls_timeout = coap_dtls_get_context_timeout(ctx->dtls_context); + if (tls_timeout > 0) { + if (tls_timeout < now + COAP_TICKS_PER_SECOND / 10) + tls_timeout = now + COAP_TICKS_PER_SECOND / 10; + coap_log(LOG_DEBUG, "** DTLS global timeout set to %dms\n", + (int)((tls_timeout - now) * 1000 / COAP_TICKS_PER_SECOND)); + if (timeout == 0 || tls_timeout - now < timeout) + timeout = tls_timeout - now; + } +#if COAP_SERVER_SUPPORT + } else { + check_dtls_timeouts = 1; +#endif /* COAP_SERVER_SUPPORT */ + } + } +#if COAP_SERVER_SUPPORT + coap_endpoint_t *ep; + coap_tick_t session_timeout; + + if (ctx->session_timeout > 0) + session_timeout = ctx->session_timeout * COAP_TICKS_PER_SECOND; + else + session_timeout = COAP_DEFAULT_SESSION_TIMEOUT * COAP_TICKS_PER_SECOND; + + LL_FOREACH(ctx->endpoint, ep) { +#ifndef COAP_EPOLL_SUPPORT + if (ep->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE | COAP_SOCKET_WANT_ACCEPT)) { + if (*num_sockets < max_sockets) + sockets[(*num_sockets)++] = &ep->sock; + } +#endif /* ! COAP_EPOLL_SUPPORT */ + SESSIONS_ITER_SAFE(ep->sessions, s, rtmp) { + /* Check whether any idle server sessions should be released */ + if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 && + s->delayqueue == NULL && + (s->last_rx_tx + session_timeout <= now || + s->state == COAP_SESSION_STATE_NONE)) { + coap_handle_event(ctx, COAP_EVENT_SERVER_SESSION_DEL, s); + coap_session_free(s); + } else { + if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 && + s->delayqueue == NULL) { + s_timeout = (s->last_rx_tx + session_timeout) - now; + if (timeout == 0 || s_timeout < timeout) + timeout = s_timeout; + } + /* Make sure the session object is not deleted in any callbacks */ + coap_session_reference(s); + /* Check any DTLS timeouts and expire if appropriate */ + if (check_dtls_timeouts && s->state == COAP_SESSION_STATE_HANDSHAKE && + s->proto == COAP_PROTO_DTLS && s->tls) { + coap_tick_t tls_timeout = coap_dtls_get_timeout(s, now); + while (tls_timeout > 0 && tls_timeout <= now) { + coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n", + coap_session_str(s)); + if (coap_dtls_handle_timeout(s)) + goto release_1; + + if (s->tls) + tls_timeout = coap_dtls_get_timeout(s, now); + else { + tls_timeout = 0; + timeout = 1; + } + } + if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout)) + timeout = tls_timeout - now; + } + /* Check if any server large receives have timed out */ + if (s->lg_srcv) { + if (coap_block_check_lg_srcv_timeouts(s, now, &s_timeout)) { + if (timeout == 0 || s_timeout < timeout) + timeout = s_timeout; + } + } + /* Check if any server large sending have timed out */ + if (s->lg_xmit) { + if (coap_block_check_lg_xmit_timeouts(s, now, &s_timeout)) { + if (timeout == 0 || s_timeout < timeout) + timeout = s_timeout; + } + } +#ifndef COAP_EPOLL_SUPPORT + if (s->sock.flags & (COAP_SOCKET_WANT_READ|COAP_SOCKET_WANT_WRITE)) { + if (*num_sockets < max_sockets) + sockets[(*num_sockets)++] = &s->sock; + } +#endif /* ! COAP_EPOLL_SUPPORT */ +release_1: + coap_session_release(s); + } + } + } +#endif /* COAP_SERVER_SUPPORT */ +#if COAP_CLIENT_SUPPORT + SESSIONS_ITER_SAFE(ctx->sessions, s, rtmp) { + if (s->type == COAP_SESSION_TYPE_CLIENT && + s->state == COAP_SESSION_STATE_ESTABLISHED && + ctx->ping_timeout > 0) { + if (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND <= now) { + if ((s->last_ping > 0 && s->last_pong < s->last_ping) || + ((s->last_ping_mid = coap_session_send_ping(s)) == COAP_INVALID_MID)) + { + /* Make sure the session object is not deleted in the callback */ + coap_session_reference(s); + coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE); + coap_session_release(s); + continue; + } + s->last_rx_tx = now; + s->last_ping = now; + } + s_timeout = (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND) - now; + if (timeout == 0 || s_timeout < timeout) + timeout = s_timeout; + } + +#if !COAP_DISABLE_TCP + if (s->type == COAP_SESSION_TYPE_CLIENT && COAP_PROTO_RELIABLE(s->proto) && + s->state == COAP_SESSION_STATE_CSM && ctx->csm_timeout > 0) { + if (s->csm_tx == 0) { + s->csm_tx = now; + } else if (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND <= now) { + /* Make sure the session object is not deleted in the callback */ + coap_session_reference(s); + coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE); + coap_session_release(s); + continue; + } + s_timeout = (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND) - now; + if (timeout == 0 || s_timeout < timeout) + timeout = s_timeout; + } +#endif /* !COAP_DISABLE_TCP */ + + /* Make sure the session object is not deleted in any callbacks */ + coap_session_reference(s); + /* Check any DTLS timeouts and expire if appropriate */ + if (s->state == COAP_SESSION_STATE_HANDSHAKE && + s->proto == COAP_PROTO_DTLS && s->tls) { + coap_tick_t tls_timeout = coap_dtls_get_timeout(s, now); + while (tls_timeout > 0 && tls_timeout <= now) { + coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n", coap_session_str(s)); + if (coap_dtls_handle_timeout(s)) + goto release_2; + + if (s->tls) + tls_timeout = coap_dtls_get_timeout(s, now); + else { + tls_timeout = 0; + timeout = 1; + } + } + if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout)) + timeout = tls_timeout - now; + } + + /* Check if any client large receives have timed out */ + if (s->lg_crcv) { + if (coap_block_check_lg_crcv_timeouts(s, now, &s_timeout)) { + if (timeout == 0 || s_timeout < timeout) + timeout = s_timeout; + } + } + /* Check if any client large sending have timed out */ + if (s->lg_xmit) { + if (coap_block_check_lg_xmit_timeouts(s, now, &s_timeout)) { + if (timeout == 0 || s_timeout < timeout) + timeout = s_timeout; + } + } + +#ifndef COAP_EPOLL_SUPPORT + assert(s->ref > 1); + if (s->sock.flags & (COAP_SOCKET_WANT_READ | + COAP_SOCKET_WANT_WRITE | + COAP_SOCKET_WANT_CONNECT)) { + if (*num_sockets < max_sockets) + sockets[(*num_sockets)++] = &s->sock; + } +#endif /* ! COAP_EPOLL_SUPPORT */ +release_2: + coap_session_release(s); + } +#endif /* COAP_CLIENT_SUPPORT */ + + return (unsigned int)((timeout * 1000 + COAP_TICKS_PER_SECOND - 1) / COAP_TICKS_PER_SECOND); +} + +#ifndef RIOT_VERSION +int +coap_io_process(coap_context_t *ctx, uint32_t timeout_ms) { + return coap_io_process_with_fds(ctx, timeout_ms, 0, NULL, NULL, NULL); +} + +int +coap_io_process_with_fds(coap_context_t *ctx, uint32_t timeout_ms, + int enfds, fd_set *ereadfds, fd_set *ewritefds, + fd_set *eexceptfds) { +#if COAP_CONSTRAINED_STACK +# ifndef COAP_EPOLL_SUPPORT + static coap_mutex_t static_mutex = COAP_MUTEX_INITIALIZER; + static fd_set readfds, writefds, exceptfds; + static coap_socket_t *sockets[64]; + unsigned int num_sockets = 0; +# endif /* ! COAP_EPOLL_SUPPORT */ +#else /* ! COAP_CONSTRAINED_STACK */ +# ifndef COAP_EPOLL_SUPPORT + fd_set readfds, writefds, exceptfds; + coap_socket_t *sockets[64]; + unsigned int num_sockets = 0; +# endif /* ! COAP_EPOLL_SUPPORT */ +#endif /* ! COAP_CONSTRAINED_STACK */ + coap_fd_t nfds = 0; + coap_tick_t before, now; + unsigned int timeout; +#ifndef COAP_EPOLL_SUPPORT + struct timeval tv; + int result; + unsigned int i; +#endif /* ! COAP_EPOLL_SUPPORT */ + + coap_ticks(&before); + +#ifndef COAP_EPOLL_SUPPORT + +#if COAP_CONSTRAINED_STACK + coap_mutex_lock(&static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + + timeout = coap_io_prepare_io(ctx, sockets, + (sizeof(sockets) / sizeof(sockets[0])), + &num_sockets, before); + if (timeout == 0 || timeout_ms < timeout) + timeout = timeout_ms; + + if (ereadfds) { + readfds = *ereadfds; + nfds = enfds; + } + else { + FD_ZERO(&readfds); + } + if (ewritefds) { + writefds = *ewritefds; + nfds = enfds; + } + else { + FD_ZERO(&writefds); + } + if (eexceptfds) { + exceptfds = *eexceptfds; + nfds = enfds; + } + else { + FD_ZERO(&exceptfds); + } + for (i = 0; i < num_sockets; i++) { + if (sockets[i]->fd + 1 > nfds) + nfds = sockets[i]->fd + 1; + if (sockets[i]->flags & COAP_SOCKET_WANT_READ) + FD_SET(sockets[i]->fd, &readfds); + if (sockets[i]->flags & COAP_SOCKET_WANT_WRITE) + FD_SET(sockets[i]->fd, &writefds); +#if !COAP_DISABLE_TCP + if (sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) + FD_SET(sockets[i]->fd, &readfds); + if (sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) { + FD_SET(sockets[i]->fd, &writefds); + FD_SET(sockets[i]->fd, &exceptfds); + } +#endif /* !COAP_DISABLE_TCP */ + } + + if (timeout_ms == COAP_IO_NO_WAIT) { + tv.tv_usec = 0; + tv.tv_sec = 0; + timeout = 1; + } + else if (timeout > 0) { + tv.tv_usec = (timeout % 1000) * 1000; + tv.tv_sec = (long)(timeout / 1000); + } + + result = select((int)nfds, &readfds, &writefds, &exceptfds, timeout > 0 ? &tv : NULL); + + if (result < 0) { /* error */ +#ifdef _WIN32 + if (WSAGetLastError() != WSAEINVAL) { /* May happen because of ICMP */ +#else + if (errno != EINTR) { +#endif + coap_log(LOG_DEBUG, "%s", coap_socket_strerror()); +#if COAP_CONSTRAINED_STACK + coap_mutex_unlock(&static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + return -1; + } + } + if (ereadfds) { + *ereadfds = readfds; + } + if (ewritefds) { + *ewritefds = writefds; + } + if (eexceptfds) { + *eexceptfds = exceptfds; + } + + if (result > 0) { + for (i = 0; i < num_sockets; i++) { + if ((sockets[i]->flags & COAP_SOCKET_WANT_READ) && FD_ISSET(sockets[i]->fd, &readfds)) + sockets[i]->flags |= COAP_SOCKET_CAN_READ; +#if !COAP_DISABLE_TCP + if ((sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) && FD_ISSET(sockets[i]->fd, &readfds)) + sockets[i]->flags |= COAP_SOCKET_CAN_ACCEPT; + if ((sockets[i]->flags & COAP_SOCKET_WANT_WRITE) && FD_ISSET(sockets[i]->fd, &writefds)) + sockets[i]->flags |= COAP_SOCKET_CAN_WRITE; + if ((sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) && (FD_ISSET(sockets[i]->fd, &writefds) || FD_ISSET(sockets[i]->fd, &exceptfds))) + sockets[i]->flags |= COAP_SOCKET_CAN_CONNECT; +#endif /* !COAP_DISABLE_TCP */ + } + } + +#if COAP_CONSTRAINED_STACK + coap_mutex_unlock(&static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + + coap_ticks(&now); + coap_io_do_io(ctx, now); + +#else /* COAP_EPOLL_SUPPORT */ + (void)ereadfds; + (void)ewritefds; + (void)eexceptfds; + (void)enfds; + + timeout = coap_io_prepare_epoll(ctx, before); + + if (timeout == 0 || timeout_ms < timeout) + timeout = timeout_ms; + + do { + struct epoll_event events[COAP_MAX_EPOLL_EVENTS]; + int etimeout = timeout; + + /* Potentially adjust based on what the caller wants */ + if (timeout_ms == COAP_IO_NO_WAIT) { + etimeout = 0; + } + else if (timeout == COAP_IO_WAIT) { + /* coap_io_prepare_epoll() returned 0 and timeout_ms COAP_IO_WAIT (0) */ + etimeout = -1; + } + else if (etimeout < 0) { + /* epoll_wait cannot wait longer than this as int timeout parameter */ + etimeout = INT_MAX; + } + + nfds = epoll_wait(ctx->epfd, events, COAP_MAX_EPOLL_EVENTS, etimeout); + if (nfds < 0) { + if (errno != EINTR) { + coap_log (LOG_ERR, "epoll_wait: unexpected error: %s (%d)\n", + coap_socket_strerror(), nfds); + } + break; + } + + coap_io_do_epoll(ctx, events, nfds); + + /* + * reset to COAP_IO_NO_WAIT (which causes etimeout to become 0) + * incase we have to do another iteration + * (COAP_MAX_EPOLL_EVENTS insufficient) + */ + timeout_ms = COAP_IO_NO_WAIT; + + /* Keep retrying until less than COAP_MAX_EPOLL_EVENTS are returned */ + } while (nfds == COAP_MAX_EPOLL_EVENTS); + +#endif /* COAP_EPOLL_SUPPORT */ +#if COAP_SERVER_SUPPORT + coap_expire_cache_entries(ctx); +#endif /* COAP_SERVER_SUPPORT */ + coap_ticks(&now); +#ifndef WITHOUT_ASYNC + /* Check to see if we need to send off any Async requests as delay might + have been updated */ + coap_check_async(ctx, now); + coap_ticks(&now); +#endif /* WITHOUT_ASYNC */ + + return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND); +} +#endif /* RIOT_VERSION */ + +#else /* WITH_CONTIKI */ +int coap_io_process(coap_context_t *ctx, uint32_t timeout_ms) { + coap_tick_t now; + + coap_ticks(&now); + /* There is something to read on the endpoint */ + ctx->endpoint->sock.flags |= COAP_SOCKET_CAN_READ; + /* read in, and send off any responses */ + coap_io_do_io(ctx, now); /* read received data */ + return -1; +} + +unsigned int +coap_io_prepare(coap_context_t *ctx, + coap_socket_t *sockets[], + unsigned int max_sockets, + unsigned int *num_sockets, + coap_tick_t now) +{ + *num_sockets = 0; + return 0; +} +#endif /* WITH_CONTIKI */ + +#ifdef _WIN32 +const char *coap_socket_format_errno(int error) { + static char szError[256]; + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)szError, (DWORD)sizeof(szError), NULL) == 0) + strcpy(szError, "Unknown error"); + return szError; +} + +const char *coap_socket_strerror(void) { + return coap_socket_format_errno(WSAGetLastError()); +} +#else /* _WIN32 */ +const char *coap_socket_format_errno(int error) { + return strerror(error); +} +const char *coap_socket_strerror(void) { + return coap_socket_format_errno(errno); +} +#endif /* _WIN32 */ + +ssize_t +coap_socket_send(coap_socket_t *sock, coap_session_t *session, + const uint8_t *data, size_t data_len) { + return session->context->network_send(sock, session, data, data_len); +} + +#undef SIN6 diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_io_lwip.c b/examples/espidf-coap-server/components/libcoap/src/coap_io_lwip.c new file mode 100644 index 000000000..5226d662b --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_io_lwip.c @@ -0,0 +1,242 @@ +/* coap_io_lwip.c -- Network I/O functions for libcoap on lwIP + * + * Copyright (C) 2012,2014 Olaf Bergmann + * 2014 chrysn + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_io_lwip.c + * @brief LwIP specific functions + */ + +#include "coap3/coap_internal.h" +#include + +#if NO_SYS +pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_t lwprot_thread = (pthread_t)0xDEAD; +int lwprot_count = 0; +#endif + +#if 0 +void coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target) +{ + target->port = packet->srcport; + memcpy(&target->addr, ip_current_src_addr(), sizeof(ip_addr_t)); +} +#endif +void coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) +{ + LWIP_ASSERT("Can only deal with contiguous PBUFs to read the initial details", packet->pbuf->tot_len == packet->pbuf->len); + *address = packet->pbuf->payload; + *length = packet->pbuf->tot_len; +} +void coap_free_packet(coap_packet_t *packet) +{ + if (packet->pbuf) + pbuf_free(packet->pbuf); + coap_free_type(COAP_PACKET, packet); +} + +struct pbuf *coap_packet_extract_pbuf(coap_packet_t *packet) +{ + struct pbuf *ret = packet->pbuf; + packet->pbuf = NULL; + return ret; +} + + +/** Callback from lwIP when a package was received. + * + * The current implementation deals this to coap_dispatch immediately, but + * other mechanisms (as storing the package in a queue and later fetching it + * when coap_io_do_io is called) can be envisioned. + * + * It handles everything coap_io_do_io does on other implementations. + */ +static void coap_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + coap_endpoint_t *ep = (coap_endpoint_t*)arg; + coap_pdu_t *pdu = NULL; + coap_session_t *session; + coap_tick_t now; + coap_packet_t *packet; + + if (p->len < 4) { + /* Minimum size of CoAP header - ignore runt */ + return; + } + + packet = coap_malloc_type(COAP_PACKET, sizeof(coap_packet_t)); + + /* this is fatal because due to the short life of the packet, never should there be more than one coap_packet_t required */ + LWIP_ASSERT("Insufficient coap_packet_t resources.", packet != NULL); + packet->pbuf = p; + /* Need to do this as there may be holes in addr_info */ + memset(&packet->addr_info, 0, sizeof(packet->addr_info)); + packet->addr_info.remote.port = port; + packet->addr_info.remote.addr = *addr; + packet->addr_info.local.port = upcb->local_port; + packet->addr_info.local.addr = *ip_current_dest_addr(); + packet->ifindex = netif_get_index(ip_current_netif()); + + pdu = coap_pdu_from_pbuf(p); + if (!pdu) + goto error; + + if (!coap_pdu_parse(ep->proto, p->payload, p->len, pdu)) { + goto error; + } + + coap_ticks(&now); + session = coap_endpoint_get_session(ep, packet, now); + if (!session) + goto error; + LWIP_ASSERT("Proto not supported for LWIP", COAP_PROTO_NOT_RELIABLE(session->proto)); + coap_dispatch(ep->context, session, pdu); + + coap_delete_pdu(pdu); + packet->pbuf = NULL; + coap_free_packet(packet); + return; + +error: + /* + * https://tools.ietf.org/html/rfc7252#section-4.2 MUST send RST + * https://tools.ietf.org/html/rfc7252#section-4.3 MAY send RST + */ + if (session) + coap_send_rst(session, pdu); + coap_delete_pdu(pdu); + if (packet) { + packet->pbuf = NULL; + coap_free_packet(packet); + } + return; +} + +coap_endpoint_t * +coap_new_endpoint(coap_context_t *context, const coap_address_t *addr, coap_proto_t proto) { + coap_endpoint_t *result; + err_t err; + + LWIP_ASSERT("Proto not supported for LWIP endpoints", proto == COAP_PROTO_UDP); + + result = coap_malloc_type(COAP_ENDPOINT, sizeof(coap_endpoint_t)); + if (!result) return NULL; + + result->sock.pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + if (result->sock.pcb == NULL) goto error; + + udp_recv(result->sock.pcb, coap_recv, (void*)result); + err = udp_bind(result->sock.pcb, &addr->addr, addr->port); + if (err) { + udp_remove(result->sock.pcb); + goto error; + } + + result->default_mtu = COAP_DEFAULT_MTU; + result->context = context; + result->proto = proto; + + return result; + +error: + coap_free_type(COAP_ENDPOINT, result); + return NULL; +} + +void coap_free_endpoint(coap_endpoint_t *ep) +{ + udp_remove(ep->sock.pcb); + coap_free_type(COAP_ENDPOINT, ep); +} + +ssize_t +coap_socket_send_pdu(coap_socket_t *sock, coap_session_t *session, + coap_pdu_t *pdu) { + /* FIXME: we can't check this here with the existing infrastructure, but we + * should actually check that the pdu is not held by anyone but us. the + * respective pbuf is already exclusively owned by the pdu. */ + + pbuf_realloc(pdu->pbuf, pdu->used_size + coap_pdu_parse_header_size(session->proto, pdu->pbuf->payload)); + udp_sendto(sock->pcb, pdu->pbuf, &session->addr_info.remote.addr, + session->addr_info.remote.port); + return pdu->used_size; +} + +ssize_t +coap_socket_send(coap_socket_t *sock, coap_session_t *session, + const uint8_t *data, size_t data_len ) { + /* Not implemented, use coap_socket_send_pdu instead */ + return -1; +} + +int +coap_socket_bind_udp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr) { + return 0; +} + +int +coap_socket_connect_udp(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + return 0; +} + +int +coap_socket_connect_tcp1(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + return 0; +} + +int +coap_socket_connect_tcp2(coap_socket_t *sock, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + return 0; +} + +int +coap_socket_bind_tcp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr) { + return 0; +} + +int +coap_socket_accept_tcp(coap_socket_t *server, + coap_socket_t *new_client, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + return 0; +} + +ssize_t +coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) { + return -1; +} + +ssize_t +coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) { + return -1; +} + +void coap_socket_close(coap_socket_t *sock) { + return; +} + diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_io_riot.c b/examples/espidf-coap-server/components/libcoap/src/coap_io_riot.c new file mode 100644 index 000000000..a72842251 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_io_riot.c @@ -0,0 +1,286 @@ +/* coap_io_riot.c -- Default network I/O functions for libcoap on RIOT + * + * Copyright (C) 2019 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_io_riot.c + * @brief RIOT specific I/O functions + */ + +#include "coap3/coap_internal.h" + +#ifdef HAVE_STDIO_H +# include +#endif + +#ifdef HAVE_SYS_SOCKET_H +# include +# define OPTVAL_T(t) (t) +# define OPTVAL_GT(t) (t) +#endif +#ifdef HAVE_SYS_IOCTL_H + #include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_SYS_UIO_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#include "net/gnrc.h" +#include "net/gnrc/ipv6.h" +#include "net/gnrc/netreg.h" +#include "net/udp.h" + +#include "coap_riot.h" + +ssize_t +coap_network_send(coap_socket_t *sock, + const coap_session_t *session, + const uint8_t *data, + size_t datalen) { + ssize_t bytes_written = 0; + + if (!coap_debug_send_packet()) { + bytes_written = (ssize_t)datalen; + } else if (sock->flags & COAP_SOCKET_CONNECTED) { + bytes_written = send(sock->fd, data, datalen, 0); + } else { + bytes_written = sendto(sock->fd, data, datalen, 0, + &session->addr_info.remote.addr.sa, + session->addr_info.remote.size); + } + + if (bytes_written < 0) + coap_log(LOG_CRIT, "coap_network_send: %s\n", coap_socket_strerror()); + + return bytes_written; +} + +static udp_hdr_t * +get_udp_header(gnrc_pktsnip_t *pkt) { + gnrc_pktsnip_t *udp = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_UDP); + return udp ? (udp_hdr_t *)udp->data : NULL; +} + +ssize_t +coap_network_read(coap_socket_t *sock, coap_packet_t *packet) { + size_t len; + ipv6_hdr_t *ipv6_hdr; + /* The GNRC API currently only supports UDP. */ + gnrc_pktsnip_t *udp; + udp_hdr_t *udp_hdr; + const gnrc_nettype_t type = GNRC_NETTYPE_UDP; + + assert(sock); + assert(packet); + + if ((sock->flags & COAP_SOCKET_CAN_READ) == 0) { + coap_log(LOG_DEBUG, "coap_network_read: COAP_SOCKET_CAN_READ not set\n"); + return -1; + } else { + /* clear has-data flag */ + sock->flags &= ~COAP_SOCKET_CAN_READ; + } + + /* Search for the transport header in the packet received from the + * network interface driver. */ + udp = gnrc_pktsnip_search_type(sock->pkt, type); + ipv6_hdr = gnrc_ipv6_get_header(sock->pkt); + + if (!ipv6_hdr || !udp || !(udp_hdr = (udp_hdr_t *)udp->data)) { + coap_log(LOG_DEBUG, "no UDP header found in packet\n"); + return -EFAULT; + } + udp_hdr_print(udp_hdr); + + len = (size_t)gnrc_pkt_len_upto(sock->pkt, type) - sizeof(udp_hdr_t); + coap_log(LOG_DEBUG, "coap_network_read: recvfrom got %zd bytes\n", len); + if (len > COAP_RXBUFFER_SIZE) { + coap_log(LOG_WARNING, "packet exceeds buffer size, truncated\n"); + len = COAP_RXBUFFER_SIZE; + } + packet->ifindex = sock->fd; + + assert(sizeof(struct in6_addr) == sizeof(ipv6_addr_t)); + packet->addr_info.remote.size = sizeof(struct sockaddr_in6); + memset(&packet->addr_info.remote.addr, 0, + sizeof(packet->addr_info.remote.addr)); + packet->addr_info.remote.addr.sin6.sin6_family = AF_INET6; + memcpy(&packet->addr_info.remote.addr.sin6.sin6_addr, + &ipv6_hdr->src, sizeof(ipv6_addr_t)); + memcpy(&packet->addr_info.remote.addr.sin6.sin6_port, + &udp_hdr->src_port, sizeof(udp_hdr->src_port)); + + packet->addr_info.local.size = sizeof(struct sockaddr_in6); + memset(&packet->addr_info.local.addr, 0, sizeof(packet->addr_info.local.addr)); + packet->addr_info.local.addr.sin6.sin6_family = AF_INET6; + memcpy(&packet->addr_info.local.addr.sin6.sin6_addr, + &ipv6_hdr->dst, sizeof(ipv6_addr_t)); + memcpy(&packet->addr_info.local + .addr.sin6.sin6_port, &udp_hdr->dst_port, sizeof(udp_hdr->src_port)); + + packet->ifindex = sock->fd; + packet->length = (len > 0) ? len : 0; + memcpy(packet->payload, (uint8_t*)udp_hdr + sizeof(udp_hdr_t), len); + if (LOG_DEBUG <= coap_get_log_level()) { + unsigned char addr_str[INET6_ADDRSTRLEN + 8]; + + if (coap_print_addr(&packet->addr_info.remote, addr_str, INET6_ADDRSTRLEN + 8)) { + coap_log(LOG_DEBUG, "received %zd bytes from %s\n", len, addr_str); + } + } + + return len; +} + +static msg_t _msg_q[LIBCOAP_MSG_QUEUE_SIZE]; + +void +coap_riot_startup(void) { + msg_init_queue(_msg_q, LIBCOAP_MSG_QUEUE_SIZE); +} + +/** + * Returns the port of @p addr in network byte order or 0 on error. + */ +static uint16_t +get_port(const coap_address_t *addr) { + if (addr) { + switch (addr->addr.sa.sa_family) { + case AF_INET: return addr->addr.sin.sin_port; + case AF_INET6: return addr->addr.sin6.sin6_port; + default: + ; + } + } + return 0; +} + +static coap_socket_t * +find_socket(coap_fd_t fd, coap_socket_t *sockets[], unsigned int num_sockets) { + for (unsigned int i = 0; i < num_sockets; i++) { + if (fd == sockets[i]->fd) + return sockets[i]; + } + return NULL; +} + +static bool +address_equals(const coap_address_t *a, const ipv6_addr_t *b) { + assert(a); + assert(b); + return IN6_IS_ADDR_UNSPECIFIED(&a->addr.sin6.sin6_addr) || + (memcmp(&a->addr.sin6.sin6_addr, b->u8, sizeof(struct in6_addr)) == 0); +} + +int +coap_io_process(coap_context_t *ctx, uint32_t timeout_ms) { + coap_tick_t before, now; + coap_socket_t *sockets[LIBCOAP_MAX_SOCKETS]; + unsigned int num_sockets = 0, timeout; + gnrc_netreg_entry_t coap_reg = + GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, thread_getpid()); + msg_t msg; + bool found_port = false; + + coap_ticks(&before); + + timeout = + coap_io_prepare_io(ctx, sockets, ARRAY_SIZE(sockets), &num_sockets, before); + if (timeout == 0 || timeout_ms < timeout) + timeout = timeout_ms; + + if (num_sockets > 0) { + gnrc_netreg_register(GNRC_NETTYPE_UDP, &coap_reg); + } + + if (timeout == 0 || timeout_ms < timeout) + timeout = timeout_ms; + + xtimer_msg_receive_timeout(&msg, timeout_ms * US_PER_SEC); + switch (msg.type) { + case GNRC_NETAPI_MSG_TYPE_RCV: { + coap_log(LOG_DEBUG, "coap_run_once: GNRC_NETAPI_MSG_TYPE_RCV\n"); + + coap_session_t *s, *rtmp; + udp_hdr_t *udp_hdr = get_udp_header((gnrc_pktsnip_t *)msg.content.ptr); + ipv6_hdr_t *ip6_hdr = + gnrc_ipv6_get_header((gnrc_pktsnip_t *)msg.content.ptr); + if (!udp_hdr || !ip6_hdr) + break; + coap_log(LOG_DEBUG, "coap_run_once: found UDP header\n"); + + /* Traverse all sessions and set COAP_SOCKET_CAN_READ if the + * received packet's destination address matches. */ + SESSIONS_ITER(ctx->sessions, s, rtmp) { + coap_log(LOG_DEBUG, "coap_run_once: check ctx->sessions %u == %u\n", + ntohs(get_port(&s->addr_info.local)), + ntohs(udp_hdr->dst_port.u16)); + if ((get_port(&s->addr_info.local) == udp_hdr->dst_port.u16) && + (address_equals(&s->addr_info.local, &ip6_hdr->dst))) { + coap_socket_t *sock = find_socket(s->sock.fd, sockets, num_sockets); + + if (sock && (sock->flags & (COAP_SOCKET_WANT_READ))) { + coap_log(LOG_DEBUG, "fd %d on port %u can read\n", + sock->fd, ntohs(get_port(&s->addr_info.local))); + sock->flags |= COAP_SOCKET_CAN_READ; + sock->pkt = msg.content.ptr; + found_port = true; + break; /* found session, finish loop */ + } + } + } + + /* If no session was found for received packet, traverse all + * endpoints and set COAP_SOCKET_CAN_READ if the received packet's + * destination address matches the endpoint. */ + if (!found_port) { + coap_endpoint_t *ep; + LL_FOREACH(ctx->endpoint, ep) { + if ((get_port(&ep->bind_addr) == udp_hdr->dst_port.u16) && + (address_equals(&ep->bind_addr, &ip6_hdr->dst))) { + coap_socket_t *sock = find_socket(ep->sock.fd, sockets, num_sockets); + + if (sock && (sock->flags & (COAP_SOCKET_WANT_READ))) { + coap_log(LOG_DEBUG, "fd %d on port %u can read\n", + sock->fd, ntohs(get_port(&ep->bind_addr))); + sock->flags |= COAP_SOCKET_CAN_READ; + sock->pkt = msg.content.ptr; + found_port = true; + break; /* found session, finish loop */ + } + } + } + } + break; + } + case GNRC_NETAPI_MSG_TYPE_SND: + break; + case GNRC_NETAPI_MSG_TYPE_SET: + /* fall through */ + case GNRC_NETAPI_MSG_TYPE_GET: + break; + default: + break; + } + + coap_ticks(&now); + coap_io_do_io(ctx, now); + + /* cleanup */ + gnrc_netreg_unregister(GNRC_NETTYPE_UDP, &coap_reg); + + return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND); +} diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_mbedtls.c b/examples/espidf-coap-server/components/libcoap/src/coap_mbedtls.c new file mode 100644 index 000000000..c1e090173 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_mbedtls.c @@ -0,0 +1,2540 @@ +/* + * coap_mbedtls.c -- Mbed TLS Datagram Transport Layer Support for libcoap + * + * Copyright (C) 2019-2022 Jon Shallow + * 2019 Jitin George + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_mbedtls.c + * @brief Mbed TLS specific interface functions. + */ + +/* + * Naming used to prevent confusion between coap sessions, mbedtls sessions etc. + * when reading the code. + * + * c_context A coap_context_t * + * c_session A coap_session_t * + * m_context A coap_mbedtls_context_t * (held in c_context->dtls_context) + * m_env A coap_mbedtls_env_t * (held in c_session->tls) + */ + +#include "coap3/coap_internal.h" + +#ifdef HAVE_MBEDTLS + +/* + * This code can be conditionally compiled to remove some components if + * they are not required to make a lighter footprint - all based on how + * the mbedtls library has been built. These are not defined within the + * libcoap environment. + * + * MBEDTLS_SSL_SRV_C - defined for server side functionality + * MBEDTLS_SSL_CLI_C - defined for client side functionality + * MBEDTLS_SSL_PROTO_DTLS - defined for DTLS support + * MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED - defined if PSK is to be supported + * or MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED - defined if PSK is to be supported + * + */ + +#include + +/* Keep forward-compatibility with Mbed TLS 3.x */ +#if (MBEDTLS_VERSION_NUMBER < 0x03000000) +#define MBEDTLS_2_X_COMPAT +#else /* !(MBEDTLS_VERSION_NUMBER < 0x03000000) */ +/* Macro wrapper for struct's private members */ +#ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS +#define MBEDTLS_ALLOW_PRIVATE_ACCESS +#endif /* MBEDTLS_ALLOW_PRIVATE_ACCESS */ +#endif /* !(MBEDTLS_VERSION_NUMBER < 0x03000000) */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG) +#include +#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */ +#include + +#ifdef HAVE_INTTYPES_H +#include +#else /* ! HAVE_INTTYPES_H */ +#define PRIx32 "x" +#endif /* ! HAVE_INTTYPES_H */ + +#define mbedtls_malloc(a) malloc(a) +#define mbedtls_realloc(a,b) realloc(a,b) +#define mbedtls_strdup(a) strdup(a) +#define mbedtls_strndup(a,b) strndup(a,b) + +#ifndef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +/* definition changed in later mbedtls code versions */ +#ifdef MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED +#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +#endif /* ! MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if ! COAP_SERVER_SUPPORT +#undef MBEDTLS_SSL_SRV_C +#endif /* ! COAP_SERVER_SUPPORT */ +#if ! COAP_CLIENT_SUPPORT +#undef MBEDTLS_SSL_CLI_C +#endif /* ! COAP_CLIENT_SUPPORT */ + +#ifdef _WIN32 +#define strcasecmp _stricmp +#endif + +#define IS_PSK (1 << 0) +#define IS_PKI (1 << 1) +#define IS_CLIENT (1 << 6) +#define IS_SERVER (1 << 7) + +typedef struct coap_ssl_t { + const uint8_t *pdu; + unsigned pdu_len; + unsigned peekmode; +} coap_ssl_t; + +/* + * This structure encapsulates the Mbed TLS session object. + * It handles both TLS and DTLS. + * c_session->tls points to this. + */ +typedef struct coap_mbedtls_env_t { + mbedtls_ssl_context ssl; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_config conf; + mbedtls_timing_delay_context timer; + mbedtls_x509_crt cacert; + mbedtls_x509_crt public_cert; + mbedtls_pk_context private_key; + mbedtls_ssl_cookie_ctx cookie_ctx; + /* If not set, need to do do_mbedtls_handshake */ + int established; + int sent_alert; + int seen_client_hello; + coap_tick_t last_timeout; + unsigned int retry_scalar; + coap_ssl_t coap_ssl_data; +} coap_mbedtls_env_t; + +typedef struct pki_sni_entry { + char *sni; + coap_dtls_key_t pki_key; + mbedtls_x509_crt cacert; + mbedtls_x509_crt public_cert; + mbedtls_pk_context private_key; +} pki_sni_entry; + +typedef struct psk_sni_entry { + char* sni; + coap_dtls_spsk_info_t psk_info; +} psk_sni_entry; + +typedef struct coap_mbedtls_context_t { + coap_dtls_pki_t setup_data; + size_t pki_sni_count; + pki_sni_entry *pki_sni_entry_list; + size_t psk_sni_count; + psk_sni_entry *psk_sni_entry_list; + char *root_ca_file; + char *root_ca_path; + int psk_pki_enabled; +} coap_mbedtls_context_t; + +typedef enum coap_enc_method_t { + COAP_ENC_PSK, + COAP_ENC_PKI, +} coap_enc_method_t; + +#ifndef MBEDTLS_2_X_COMPAT +/* + * mbedtls_ callback functions expect 0 on success, -ve on failure. + */ +static int coap_rng(void *ctx COAP_UNUSED, unsigned char *buf, size_t len) +{ + return coap_prng(buf, len) ? 0 : MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; +} +#endif /* MBEDTLS_2_X_COMPAT */ + +static int coap_dgram_read(void *ctx, unsigned char *out, size_t outl) +{ + ssize_t ret = 0; + coap_session_t *c_session = (coap_session_t *)ctx; + coap_ssl_t *data; + + if (!c_session->tls) { + errno = EAGAIN; + return MBEDTLS_ERR_SSL_WANT_READ; + } + data = &((coap_mbedtls_env_t *)c_session->tls)->coap_ssl_data; + + if (out != NULL) { + if (data->pdu_len > 0) { + if (outl < data->pdu_len) { + memcpy(out, data->pdu, outl); + ret = outl; + data->pdu += outl; + data->pdu_len -= outl; + } + else { + memcpy(out, data->pdu, data->pdu_len); + ret = data->pdu_len; + if (!data->peekmode) { + data->pdu_len = 0; + data->pdu = NULL; + } + } + } + else { + ret = MBEDTLS_ERR_SSL_WANT_READ; + errno = EAGAIN; + } + } + return ret; +} + +/* + * return +ve data amount + * 0 no more + * -ve Mbed TLS error + */ +/* callback function given to mbedtls for sending data over socket */ +static int +coap_dgram_write(void *ctx, const unsigned char *send_buffer, + size_t send_buffer_length) +{ + ssize_t result = -1; + coap_session_t *c_session = (coap_session_t *)ctx; + + if (c_session) { + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + result = coap_session_send(c_session, send_buffer, send_buffer_length); + if (result != (ssize_t)send_buffer_length) { + coap_log(LOG_WARNING, "coap_network_send failed (%zd != %zu)\n", + result, send_buffer_length); + result = 0; + } + else if (m_env) { + coap_tick_t now; + coap_ticks(&now); + m_env->last_timeout = now; + } + } else { + result = 0; + } + return result; +} + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && defined(MBEDTLS_SSL_SRV_C) +/* + * Server side PSK callback + */ +static int psk_server_callback(void *p_info, mbedtls_ssl_context *ssl, + const unsigned char *identity, size_t identity_len ) +{ + coap_session_t *c_session = (coap_session_t *)p_info; + coap_dtls_spsk_t *setup_data; + coap_mbedtls_env_t *m_env; + coap_bin_const_t lidentity; + const coap_bin_const_t *psk_key; + + if (c_session == NULL) + return -1; + + /* Track the Identity being used */ + lidentity.s = identity ? (const uint8_t*)identity : (const uint8_t*)""; + lidentity.length = identity ? identity_len : 0; + coap_session_refresh_psk_identity(c_session, &lidentity); + + coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n", + (int)lidentity.length, (const char *)lidentity.s); + + m_env = (coap_mbedtls_env_t *)c_session->tls; + setup_data = &c_session->context->spsk_setup_data; + + if (setup_data->validate_id_call_back) { + psk_key = setup_data->validate_id_call_back(&lidentity, + c_session, + setup_data->id_call_back_arg); + + coap_session_refresh_psk_key(c_session, psk_key); + } + else { + psk_key = coap_get_session_server_psk_key(c_session); + } + + if (psk_key == NULL) + return -1; + mbedtls_ssl_set_hs_psk(ssl, psk_key->s, psk_key->length); + m_env->seen_client_hello = 1; + return 0; +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED && MBEDTLS_SSL_SRV_C */ + +static char* +get_san_or_cn_from_cert(mbedtls_x509_crt *crt) +{ + if (crt) { + const mbedtls_asn1_named_data * cn_data; + + if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { + mbedtls_asn1_sequence *seq = &crt->subject_alt_names; + while (seq && seq->buf.p == NULL) { + seq = seq->next; + } + if (seq) { + /* Return the Subject Alt Name */ + return mbedtls_strndup((const char *)seq->buf.p, + seq->buf.len); + } + } + + cn_data = mbedtls_asn1_find_named_data(&crt->subject, + MBEDTLS_OID_AT_CN, + MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN)); + if (cn_data) { + /* Return the Common Name */ + return mbedtls_strndup((const char *)cn_data->val.p, + cn_data->val.len); + } + } + return NULL; +} + +static char * +get_error_string(int ret) { + static char buf[128] = {0}; + mbedtls_strerror(ret, buf, sizeof(buf)-1); + return buf; +} + +static int +self_signed_cert_verify_callback_mbedtls(void *data, + mbedtls_x509_crt *crt COAP_UNUSED, + int depth COAP_UNUSED, + uint32_t *flags) +{ + const coap_session_t *c_session = (coap_session_t*)data; + const coap_mbedtls_context_t *m_context = + (coap_mbedtls_context_t *)c_session->context->dtls_context; + const coap_dtls_pki_t *setup_data = &m_context->setup_data; + + if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) { + if (setup_data->allow_expired_certs) { + *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED; + } + } + return 0; +} + +/* + * return 0 All OK + * -ve Error Code + */ +static int +cert_verify_callback_mbedtls(void *data, mbedtls_x509_crt *crt, + int depth, uint32_t *flags) +{ + coap_session_t *c_session = (coap_session_t*)data; + coap_mbedtls_context_t *m_context = + (coap_mbedtls_context_t *)c_session->context->dtls_context; + coap_dtls_pki_t *setup_data = &m_context->setup_data; + char *cn = NULL; + + if (*flags == 0) + return 0; + + cn = get_san_or_cn_from_cert(crt); + + if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) { + if (setup_data->allow_expired_certs) { + *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED; + coap_log(LOG_INFO, + " %s: %s: overridden: '%s' depth %d\n", + coap_session_str(c_session), + "The certificate has expired", cn ? cn : "?", depth); + } + } + if (*flags & MBEDTLS_X509_BADCERT_FUTURE) { + if (setup_data->allow_expired_certs) { + *flags &= ~MBEDTLS_X509_BADCERT_FUTURE; + coap_log(LOG_INFO, + " %s: %s: overridden: '%s' depth %d\n", + coap_session_str(c_session), + "The certificate has a future date", cn ? cn : "?", depth); + } + } + if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) { + if (setup_data->allow_bad_md_hash) { + *flags &= ~MBEDTLS_X509_BADCERT_BAD_MD; + coap_log(LOG_INFO, + " %s: %s: overridden: '%s' depth %d\n", + coap_session_str(c_session), + "The certificate has a bad MD hash", cn ? cn : "?", depth); + } + } + if (*flags & MBEDTLS_X509_BADCERT_BAD_KEY) { + if (setup_data->allow_short_rsa_length) { + *flags &= ~MBEDTLS_X509_BADCERT_BAD_KEY; + coap_log(LOG_INFO, + " %s: %s: overridden: '%s' depth %d\n", + coap_session_str(c_session), + "The certificate has a short RSA length", cn ? cn : "?", depth); + } + } + if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { + uint32_t lflags; + int self_signed = !mbedtls_x509_crt_verify(crt, crt, NULL, NULL, &lflags, + self_signed_cert_verify_callback_mbedtls, + data); + if (self_signed && depth == 0) { + if (setup_data->allow_self_signed && + !setup_data->check_common_ca) { + *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED; + coap_log(LOG_INFO, + " %s: %s: overridden: '%s' depth %d\n", + coap_session_str(c_session), + "Self-signed", + cn ? cn : "?", depth); + } + } + else { + if (!setup_data->verify_peer_cert) { + *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED; + coap_log(LOG_INFO, + " %s: %s: overridden: '%s' depth %d\n", + coap_session_str(c_session), + "The certificate's CA does not match", cn ? cn : "?", depth); + } + } + } + if (*flags & MBEDTLS_X509_BADCRL_EXPIRED) { + if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) { + *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED; + coap_log(LOG_INFO, + " %s: %s: overridden: '%s' depth %d\n", + coap_session_str(c_session), + "The certificate's CRL has expired", cn ? cn : "?", depth); + } + else if (!setup_data->check_cert_revocation) { + *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED; + } + } + if (*flags & MBEDTLS_X509_BADCRL_FUTURE) { + if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) { + *flags &= ~MBEDTLS_X509_BADCRL_FUTURE; + coap_log(LOG_INFO, + " %s: %s: overridden: '%s' depth %d\n", + coap_session_str(c_session), + "The certificate's CRL has a future date", cn ? cn : "?", depth); + } + else if (!setup_data->check_cert_revocation) { + *flags &= ~MBEDTLS_X509_BADCRL_FUTURE; + } + } + if (setup_data->cert_chain_validation && + depth > (setup_data->cert_chain_verify_depth + 1)) { + *flags |= MBEDTLS_X509_BADCERT_OTHER; + coap_log(LOG_WARNING, + " %s: %s: '%s' depth %d\n", + coap_session_str(c_session), + "The certificate's verify depth is too long", + cn ? cn : "?", depth); + } + + if (*flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) { + *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + if (setup_data->validate_cn_call_back) { + if (!setup_data->validate_cn_call_back(cn, + crt->raw.p, + crt->raw.len, + c_session, + depth, + *flags == 0, + setup_data->cn_call_back_arg)) { + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + } + if (*flags != 0) { + char buf[128]; + char *tcp; + int ret = mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags); + + if (ret >= 0) { + tcp = strchr(buf, '\n'); + while (tcp) { + *tcp = '\000'; + coap_log(LOG_WARNING, + " %s: %s: issue 0x%" PRIx32 ": '%s' depth %d\n", + coap_session_str(c_session), + buf, *flags, cn ? cn : "?", depth); + tcp = strchr(tcp+1, '\n'); + } + } + else { + coap_log(LOG_ERR, "mbedtls_x509_crt_verify_info returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + } + } + + if (cn) + mbedtls_free(cn); + + return 0; +} + +static int +setup_pki_credentials(mbedtls_x509_crt *cacert, + mbedtls_x509_crt *public_cert, + mbedtls_pk_context *private_key, + coap_mbedtls_env_t *m_env, + coap_mbedtls_context_t *m_context, + coap_session_t *c_session, + coap_dtls_pki_t *setup_data, + coap_dtls_role_t role) +{ + int ret; + + if (setup_data->is_rpk_not_cert) { + coap_log(LOG_ERR, + "RPK Support not available in Mbed TLS\n"); + return -1; + } + switch (setup_data->pki_key.key_type) { + case COAP_PKI_KEY_PEM: + if (setup_data->pki_key.key.pem.public_cert && + setup_data->pki_key.key.pem.public_cert[0] && + setup_data->pki_key.key.pem.private_key && + setup_data->pki_key.key.pem.private_key[0]) { + + mbedtls_x509_crt_init(public_cert); + mbedtls_pk_init(private_key); + + ret = mbedtls_x509_crt_parse_file(public_cert, + setup_data->pki_key.key.pem.public_cert); + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_x509_crt_parse_file returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + +#ifdef MBEDTLS_2_X_COMPAT + ret = mbedtls_pk_parse_keyfile(private_key, + setup_data->pki_key.key.pem.private_key, NULL); +#else + ret = mbedtls_pk_parse_keyfile(private_key, + setup_data->pki_key.key.pem.private_key, + NULL, coap_rng, (void *)&m_env->ctr_drbg); +#endif /* MBEDTLS_2_X_COMPAT */ + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + + ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + } + else if (role == COAP_DTLS_ROLE_SERVER) { + coap_log(LOG_ERR, + "***setup_pki: (D)TLS: No Server Certificate + Private " + "Key defined\n"); + return -1; + } + + if (setup_data->pki_key.key.pem.ca_file && + setup_data->pki_key.key.pem.ca_file[0]) { + mbedtls_x509_crt_init(cacert); + ret = mbedtls_x509_crt_parse_file(cacert, + setup_data->pki_key.key.pem.ca_file); + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); + } + break; + case COAP_PKI_KEY_PEM_BUF: + if (setup_data->pki_key.key.pem_buf.public_cert && + setup_data->pki_key.key.pem_buf.public_cert_len && + setup_data->pki_key.key.pem_buf.private_key && + setup_data->pki_key.key.pem_buf.private_key_len) { + uint8_t *buffer; + size_t length; + + mbedtls_x509_crt_init(public_cert); + mbedtls_pk_init(private_key); + + length = setup_data->pki_key.key.pem_buf.public_cert_len; + if (setup_data->pki_key.key.pem_buf.public_cert[length-1] != '\000') { + /* Need to allocate memory to add in NULL terminator */ + buffer = mbedtls_malloc(length + 1); + if (!buffer) { + coap_log(LOG_ERR, "mbedtls_malloc failed\n"); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(buffer, setup_data->pki_key.key.pem_buf.public_cert, length); + buffer[length] = '\000'; + length++; + ret = mbedtls_x509_crt_parse(public_cert, buffer, length); + mbedtls_free(buffer); + } + else { + ret = mbedtls_x509_crt_parse(public_cert, + setup_data->pki_key.key.pem_buf.public_cert, + setup_data->pki_key.key.pem_buf.public_cert_len); + } + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + + length = setup_data->pki_key.key.pem_buf.private_key_len; + if (setup_data->pki_key.key.pem_buf.private_key[length-1] != '\000') { + /* Need to allocate memory to add in NULL terminator */ + buffer = mbedtls_malloc(length + 1); + if (!buffer) { + coap_log(LOG_ERR, "mbedtls_malloc failed\n"); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(buffer, setup_data->pki_key.key.pem_buf.private_key, length); + buffer[length] = '\000'; + length++; +#ifdef MBEDTLS_2_X_COMPAT + ret = mbedtls_pk_parse_key(private_key, buffer, length, NULL, 0); +#else + ret = mbedtls_pk_parse_key(private_key, buffer, length, + NULL, 0, coap_rng, (void *)&m_env->ctr_drbg); +#endif /* MBEDTLS_2_X_COMPAT */ + mbedtls_free(buffer); + } + else { +#ifdef MBEDTLS_2_X_COMPAT + ret = mbedtls_pk_parse_key(private_key, + setup_data->pki_key.key.pem_buf.private_key, + setup_data->pki_key.key.pem_buf.private_key_len, NULL, 0); +#else + ret = mbedtls_pk_parse_key(private_key, + setup_data->pki_key.key.pem_buf.private_key, + setup_data->pki_key.key.pem_buf.private_key_len, + NULL, 0, coap_rng, (void *)&m_env->ctr_drbg); +#endif /* MBEDTLS_2_X_COMPAT */ + } + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_pk_parse_key returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + + ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + } else if (role == COAP_DTLS_ROLE_SERVER) { + coap_log(LOG_ERR, + "***setup_pki: (D)TLS: No Server Certificate + Private " + "Key defined\n"); + return -1; + } + + if (setup_data->pki_key.key.pem_buf.ca_cert && + setup_data->pki_key.key.pem_buf.ca_cert_len) { + uint8_t *buffer; + size_t length; + + mbedtls_x509_crt_init(cacert); + length = setup_data->pki_key.key.pem_buf.ca_cert_len; + if (setup_data->pki_key.key.pem_buf.ca_cert[length-1] != '\000') { + /* Need to allocate memory to add in NULL terminator */ + buffer = mbedtls_malloc(length + 1); + if (!buffer) { + coap_log(LOG_ERR, "mbedtls_malloc failed\n"); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(buffer, setup_data->pki_key.key.pem_buf.ca_cert, length); + buffer[length] = '\000'; + length++; + ret = mbedtls_x509_crt_parse(cacert, buffer, length); + mbedtls_free(buffer); + } + else { + ret = mbedtls_x509_crt_parse(cacert, + setup_data->pki_key.key.pem_buf.ca_cert, + setup_data->pki_key.key.pem_buf.ca_cert_len); + } + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); + } + break; + case COAP_PKI_KEY_ASN1: + if (setup_data->pki_key.key.asn1.public_cert && + setup_data->pki_key.key.asn1.public_cert_len && + setup_data->pki_key.key.asn1.private_key && + setup_data->pki_key.key.asn1.private_key_len > 0) { + + mbedtls_x509_crt_init(public_cert); + mbedtls_pk_init(private_key); + ret = mbedtls_x509_crt_parse(public_cert, + (const unsigned char *)setup_data->pki_key.key.asn1.public_cert, + setup_data->pki_key.key.asn1.public_cert_len); + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + +#ifdef MBEDTLS_2_X_COMPAT + ret = mbedtls_pk_parse_key(private_key, + (const unsigned char *)setup_data->pki_key.key.asn1.private_key, + setup_data->pki_key.key.asn1.private_key_len, NULL, 0); +#else + ret = mbedtls_pk_parse_key(private_key, + (const unsigned char *)setup_data->pki_key.key.asn1.private_key, + setup_data->pki_key.key.asn1.private_key_len, NULL, 0, coap_rng, + (void *)&m_env->ctr_drbg); +#endif /* MBEDTLS_2_X_COMPAT */ + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_pk_parse_key returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + + ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + } else if (role == COAP_DTLS_ROLE_SERVER) { + coap_log(LOG_ERR, + "***setup_pki: (D)TLS: No Server Certificate + Private " + "Key defined\n"); + return -1; + } + + if (setup_data->pki_key.key.asn1.ca_cert && + setup_data->pki_key.key.asn1.ca_cert_len > 0) { + mbedtls_x509_crt_init(cacert); + ret = mbedtls_x509_crt_parse(cacert, + (const unsigned char *)setup_data->pki_key.key.asn1.ca_cert, + setup_data->pki_key.key.asn1.ca_cert_len); + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); + } + break; + + case COAP_PKI_KEY_PKCS11: + coap_log(LOG_ERR, + "***setup_pki: (D)TLS: PKCS11 not currently supported\n"); + return -1; + + default: + coap_log(LOG_ERR, + "***setup_pki: (D)TLS: Unknown key type %d\n", + setup_data->pki_key.key_type); + return -1; + } + + if (m_context->root_ca_file) { + ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_file); + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); + } + if (m_context->root_ca_path) { + ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_path); + if (ret < 0) { + coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return ret; + } + mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); + } + +#if defined(MBEDTLS_SSL_SRV_C) + mbedtls_ssl_conf_cert_req_ca_list(&m_env->conf, + setup_data->check_common_ca ? + MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED : + MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED); +#endif + mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->verify_peer_cert ? + MBEDTLS_SSL_VERIFY_REQUIRED : + MBEDTLS_SSL_VERIFY_NONE); + /* + * Verify Peer. + * Need to do all checking, even if setup_data->verify_peer_cert is not set + */ + mbedtls_ssl_conf_verify(&m_env->conf, + cert_verify_callback_mbedtls, c_session); + + return 0; +} + +#if defined(MBEDTLS_SSL_SRV_C) +/* + * PKI SNI callback. + */ +static int +pki_sni_callback(void *p_info, mbedtls_ssl_context *ssl, + const unsigned char *uname, size_t name_len) +{ + unsigned int i; + coap_dtls_pki_t sni_setup_data; + coap_session_t *c_session = (coap_session_t *)p_info; + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + coap_mbedtls_context_t *m_context = + (coap_mbedtls_context_t *)c_session->context->dtls_context; + int ret = 0; + char *name; + + name = mbedtls_malloc(name_len+1); + if (!name) + return -1; + + memcpy(name, uname, name_len); + name[name_len] = '\000'; + + /* Is this a cached entry? */ + for (i = 0; i < m_context->pki_sni_count; i++) { + if (strcasecmp(name, m_context->pki_sni_entry_list[i].sni) == 0) { + break; + } + } + if (i == m_context->pki_sni_count) { + /* + * New PKI SNI request + */ + coap_dtls_key_t *new_entry; + pki_sni_entry *pki_sni_entry_list; + + new_entry = + m_context->setup_data.validate_sni_call_back(name, + m_context->setup_data.sni_call_back_arg); + if (!new_entry) { + mbedtls_free(name); + return -1; + } + + pki_sni_entry_list = mbedtls_realloc(m_context->pki_sni_entry_list, + (i+1)*sizeof(pki_sni_entry)); + + if (pki_sni_entry_list == NULL) { + mbedtls_free(name); + return -1; + } + m_context->pki_sni_entry_list = pki_sni_entry_list; + memset(&m_context->pki_sni_entry_list[i], 0, + sizeof(m_context->pki_sni_entry_list[i])); + m_context->pki_sni_entry_list[i].sni = name; + m_context->pki_sni_entry_list[i].pki_key = *new_entry; + sni_setup_data = m_context->setup_data; + sni_setup_data.pki_key = *new_entry; + if ((ret = setup_pki_credentials(&m_context->pki_sni_entry_list[i].cacert, + &m_context->pki_sni_entry_list[i].public_cert, + &m_context->pki_sni_entry_list[i].private_key, + m_env, + m_context, + c_session, + &sni_setup_data, COAP_DTLS_ROLE_SERVER)) < 0) { + mbedtls_free(name); + return -1; + } + /* name has been absorbed into pki_sni_entry_list[].sni entry */ + m_context->pki_sni_count++; + } + else { + mbedtls_free(name); + } + + mbedtls_ssl_set_hs_ca_chain(ssl, &m_context->pki_sni_entry_list[i].cacert, + NULL); + return mbedtls_ssl_set_hs_own_cert(ssl, + &m_context->pki_sni_entry_list[i].public_cert, + &m_context->pki_sni_entry_list[i].private_key); +} + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +/* + * PSK SNI callback. + */ +static int +psk_sni_callback(void *p_info, mbedtls_ssl_context *ssl, + const unsigned char *uname, size_t name_len) +{ + unsigned int i; + coap_session_t *c_session = (coap_session_t *)p_info; + coap_mbedtls_context_t *m_context = + (coap_mbedtls_context_t *)c_session->context->dtls_context; + char *name; + + name = mbedtls_malloc(name_len+1); + if (!name) + return -1; + + memcpy(name, uname, name_len); + name[name_len] = '\000'; + + /* Is this a cached entry? */ + for (i = 0; i < m_context->psk_sni_count; i++) { + if (strcasecmp(name, m_context->psk_sni_entry_list[i].sni) == 0) { + break; + } + } + if (i == m_context->psk_sni_count) { + /* + * New PSK SNI request + */ + const coap_dtls_spsk_info_t *new_entry; + psk_sni_entry *psk_sni_entry_list; + + new_entry = + c_session->context->spsk_setup_data.validate_sni_call_back(name, + c_session, + c_session->context->spsk_setup_data.sni_call_back_arg); + if (!new_entry) { + mbedtls_free(name); + return -1; + } + + psk_sni_entry_list = mbedtls_realloc(m_context->psk_sni_entry_list, + (i+1)*sizeof(psk_sni_entry)); + + if (psk_sni_entry_list == NULL) { + mbedtls_free(name); + return -1; + } + m_context->psk_sni_entry_list = psk_sni_entry_list; + m_context->psk_sni_entry_list[i].sni = name; + m_context->psk_sni_entry_list[i].psk_info = *new_entry; + /* name has been absorbed into psk_sni_entry_list[].sni entry */ + m_context->psk_sni_count++; + } + else { + mbedtls_free(name); + } + + coap_session_refresh_psk_hint(c_session, + &m_context->psk_sni_entry_list[i].psk_info.hint); + coap_session_refresh_psk_key(c_session, + &m_context->psk_sni_entry_list[i].psk_info.key); + return mbedtls_ssl_set_hs_psk(ssl, + m_context->psk_sni_entry_list[i].psk_info.key.s, + m_context->psk_sni_entry_list[i].psk_info.key.length); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +static int setup_server_ssl_session(coap_session_t *c_session, + coap_mbedtls_env_t *m_env) +{ + coap_mbedtls_context_t *m_context = + (coap_mbedtls_context_t *)c_session->context->dtls_context; + int ret = 0; + m_context->psk_pki_enabled |= IS_SERVER; + + mbedtls_ssl_cookie_init(&m_env->cookie_ctx); + if ((ret = mbedtls_ssl_config_defaults(&m_env->conf, + MBEDTLS_SSL_IS_SERVER, + c_session->proto == COAP_PROTO_DTLS ? + MBEDTLS_SSL_TRANSPORT_DATAGRAM : + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + goto fail; + } + + mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_ssl_conf_handshake_timeout(&m_env->conf, COAP_DTLS_RETRANSMIT_MS, + COAP_DTLS_RETRANSMIT_TOTAL_MS); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if (m_context->psk_pki_enabled & IS_PSK) { +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + mbedtls_ssl_conf_psk_cb(&m_env->conf, psk_server_callback, c_session); + if (c_session->context->spsk_setup_data.validate_sni_call_back) { + mbedtls_ssl_conf_sni(&m_env->conf, psk_sni_callback, c_session); + } +#else /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + coap_log(LOG_WARNING, "PSK not enabled in Mbed TLS library\n"); +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + } + + if (m_context->psk_pki_enabled & IS_PKI) { + ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert, + &m_env->private_key, m_env, m_context, + c_session, &m_context->setup_data, + COAP_DTLS_ROLE_SERVER); + if (ret < 0) { + coap_log(LOG_ERR, "PKI setup failed\n"); + return ret; + } + if (m_context->setup_data.validate_sni_call_back) { + mbedtls_ssl_conf_sni(&m_env->conf, pki_sni_callback, c_session); + } + } + + if ((ret = mbedtls_ssl_cookie_setup(&m_env->cookie_ctx, + mbedtls_ctr_drbg_random, + &m_env->ctr_drbg)) != 0) { + coap_log(LOG_ERR, "mbedtls_ssl_cookie_setup: returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + goto fail; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_ssl_conf_dtls_cookies(&m_env->conf, mbedtls_ssl_cookie_write, + mbedtls_ssl_cookie_check, + &m_env->cookie_ctx ); +#if MBEDTLS_VERSION_NUMBER >= 0x02100100 + mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu); +#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +fail: + return ret; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +#if COAP_CLIENT_SUPPORT +static int *psk_ciphers = NULL; +static int *pki_ciphers = NULL; +static int processed_ciphers = 0; + +static void +set_ciphersuites(mbedtls_ssl_config *conf, coap_enc_method_t method) +{ + if (!processed_ciphers) { + const int *list = mbedtls_ssl_list_ciphersuites(); + const int *base = list; + int *psk_list; + int *pki_list; + int psk_count = 1; /* account for empty terminator */ + int pki_count = 1; + + while (*list) { + const mbedtls_ssl_ciphersuite_t *cur = + mbedtls_ssl_ciphersuite_from_id(*list); + +#if MBEDTLS_VERSION_NUMBER >= 0x03020000 + if (cur) { + if (cur->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2) { + /* Minimum of TLS1.2 required - skip */ + } +#else + if (cur) { + if (cur->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) { + /* Minimum of TLS1.2 required - skip */ + } +#endif /* MBEDTLS_VERSION_NUMBER >= 0x03020000 */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + else if (mbedtls_ssl_ciphersuite_uses_psk(cur)) { + psk_count++; + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + else { + pki_count++; + } + } + list++; + } + list = base; + + psk_ciphers = mbedtls_malloc(psk_count * sizeof(psk_ciphers[0])); + if (psk_ciphers == NULL) { + coap_log(LOG_ERR, "set_ciphers: mbedtls_malloc with count %d failed\n", psk_count); + return; + } + pki_ciphers = mbedtls_malloc(pki_count * sizeof(pki_ciphers[0])); + if (pki_ciphers == NULL) { + coap_log(LOG_ERR, "set_ciphers: mbedtls_malloc with count %d failed\n", pki_count); + mbedtls_free(psk_ciphers); + psk_ciphers = NULL; + return; + } + + psk_list = psk_ciphers; + pki_list = pki_ciphers; + + while (*list) { + const mbedtls_ssl_ciphersuite_t *cur = + mbedtls_ssl_ciphersuite_from_id(*list); +#if MBEDTLS_VERSION_NUMBER >= 0x03020000 + if (cur) { + if (cur->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2) { + /* Minimum of TLS1.2 required - skip */ + } +#else + if (cur) { + if (cur->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) { + /* Minimum of TLS1.2 required - skip */ + } +#endif /* MBEDTLS_VERSION_NUMBER >= 0x03020000 */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + else if (mbedtls_ssl_ciphersuite_uses_psk(cur)) { + *psk_list = *list; + psk_list++; + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + else { + *pki_list = *list; + pki_list++; + } + } + list++; + } + /* zero terminate */ + *psk_list = 0; + *pki_list = 0; + processed_ciphers = 1; + } + mbedtls_ssl_conf_ciphersuites(conf, method == COAP_ENC_PSK ? psk_ciphers : pki_ciphers); +} + +static int setup_client_ssl_session(coap_session_t *c_session, + coap_mbedtls_env_t *m_env) +{ + int ret; + + coap_mbedtls_context_t *m_context = + (coap_mbedtls_context_t *)c_session->context->dtls_context; + + m_context->psk_pki_enabled |= IS_CLIENT; + + if ((ret = mbedtls_ssl_config_defaults(&m_env->conf, + MBEDTLS_SSL_IS_CLIENT, + c_session->proto == COAP_PROTO_DTLS ? + MBEDTLS_SSL_TRANSPORT_DATAGRAM : + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + goto fail; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_ssl_conf_handshake_timeout(&m_env->conf, COAP_DTLS_RETRANSMIT_MS, + COAP_DTLS_RETRANSMIT_TOTAL_MS); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg); + + if (m_context->psk_pki_enabled & IS_PSK) { +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + const coap_bin_const_t *psk_key; + const coap_bin_const_t *psk_identity; + + coap_log(LOG_INFO, "Setting PSK key\n"); + + psk_key = coap_get_session_client_psk_key(c_session); + psk_identity = coap_get_session_client_psk_identity(c_session); + if (psk_key == NULL || psk_identity == NULL) { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto fail; + } + + if ((ret = mbedtls_ssl_conf_psk(&m_env->conf, psk_key->s, + psk_key->length, psk_identity->s, + psk_identity->length)) != 0) { + coap_log(LOG_ERR, "mbedtls_ssl_conf_psk returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + goto fail; + } + if (c_session->cpsk_setup_data.client_sni) { + if ((ret = mbedtls_ssl_set_hostname(&m_env->ssl, + c_session->cpsk_setup_data.client_sni)) != 0) { + coap_log(LOG_ERR, "mbedtls_ssl_set_hostname returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + goto fail; + } + } + /* Identity Hint currently not supported in Mbed TLS so code removed */ + + set_ciphersuites(&m_env->conf, COAP_ENC_PSK); +#else /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + coap_log(LOG_WARNING, "PSK not enabled in Mbed TLS library\n"); +#endif /* ! MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + } + else if ((m_context->psk_pki_enabled & IS_PKI) || + (m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) { + /* + * If neither PSK or PKI have been set up, use PKI basics. + * This works providing COAP_PKI_KEY_PEM has a value of 0. + */ + mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); + ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert, + &m_env->private_key, m_env, m_context, + c_session, &m_context->setup_data, + COAP_DTLS_ROLE_CLIENT); + if (ret < 0) { + coap_log(LOG_ERR, "PKI setup failed\n"); + return ret; + } +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) + if (c_session->proto == COAP_PROTO_TLS) { + static const char *alpn_list[] = { "coap", NULL }; + + ret = mbedtls_ssl_conf_alpn_protocols(&m_env->conf, alpn_list); + if (ret != 0) { + coap_log(LOG_ERR, "ALPN setup failed %d)\n", ret); + } + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN */ + if (m_context->setup_data.client_sni) { + mbedtls_ssl_set_hostname(&m_env->ssl, m_context->setup_data.client_sni); + } +#if defined(MBEDTLS_SSL_PROTO_DTLS) +#if MBEDTLS_VERSION_NUMBER >= 0x02100100 + mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu); +#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + set_ciphersuites(&m_env->conf, COAP_ENC_PKI); + } + return 0; + +fail: + return ret; +} +#endif /* COAP_CLIENT_SUPPORT */ + +static void mbedtls_cleanup(coap_mbedtls_env_t *m_env) +{ + if (!m_env) { + return; + } + + mbedtls_x509_crt_free(&m_env->cacert); + mbedtls_x509_crt_free(&m_env->public_cert); + mbedtls_pk_free(&m_env->private_key); + mbedtls_entropy_free(&m_env->entropy); + mbedtls_ssl_config_free(&m_env->conf); + mbedtls_ctr_drbg_free(&m_env->ctr_drbg); + mbedtls_ssl_free(&m_env->ssl); + mbedtls_ssl_cookie_free(&m_env->cookie_ctx); +} + +static void +coap_dtls_free_mbedtls_env(coap_mbedtls_env_t *m_env) { + if (m_env) { + if (!m_env->sent_alert) + mbedtls_ssl_close_notify(&m_env->ssl); + mbedtls_cleanup(m_env); + mbedtls_free(m_env); + } +} + +static const char * +report_mbedtls_alert(unsigned char alert) { + switch (alert) { + case MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC: return ": Bad Record MAC"; + case MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE: return ": Handshake failure"; + case MBEDTLS_SSL_ALERT_MSG_NO_CERT: return ": No Certificate provided"; + case MBEDTLS_SSL_ALERT_MSG_BAD_CERT: return ": Certificate is bad"; + case MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA: return ": CA is unknown"; + case MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED: return ": Access was denied"; + case MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR: return ": Decrypt error"; + default: return ""; + } +} + +/* + * return -1 failure + * 0 not completed + * 1 established + */ +static int do_mbedtls_handshake(coap_session_t *c_session, + coap_mbedtls_env_t *m_env) { + int ret; + int alert; + + ret = mbedtls_ssl_handshake(&m_env->ssl); + switch (ret) { + case 0: + m_env->established = 1; + coap_log(LOG_DEBUG, "* %s: Mbed TLS established\n", + coap_session_str(c_session)); + ret = 1; + break; + case MBEDTLS_ERR_SSL_WANT_READ: + case MBEDTLS_ERR_SSL_WANT_WRITE: + errno = EAGAIN; + ret = 0; + break; + case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED: + coap_log(LOG_DEBUG, "hello verification requested\n"); + goto reset; + case MBEDTLS_ERR_SSL_INVALID_MAC: + goto fail; + case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE: + alert = MBEDTLS_SSL_ALERT_MSG_NO_CERT; + goto fail_alert; +#ifdef MBEDTLS_2_X_COMPAT + case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO: + case MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO: + alert = MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE; + goto fail_alert; +#endif /* MBEDTLS_2_X_COMPAT */ + case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: + goto fail; + case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: + if (m_env->ssl.in_msg[1] != MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY) + coap_log(LOG_WARNING, "***%s: Alert '%d'%s\n", + coap_session_str(c_session), m_env->ssl.in_msg[1], + report_mbedtls_alert(m_env->ssl.in_msg[1])); + /* Fall through */ + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + case MBEDTLS_ERR_SSL_CONN_EOF: + case MBEDTLS_ERR_NET_CONN_RESET: + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + default: + coap_log(LOG_WARNING, + "do_mbedtls_handshake: session establish " + "returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + ret = -1; + break; + } + return ret; + +fail_alert: + mbedtls_ssl_send_alert_message(&m_env->ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + alert); + m_env->sent_alert = 1; +fail: + c_session->dtls_event = COAP_EVENT_DTLS_ERROR; + coap_log(LOG_WARNING, + "do_mbedtls_handshake: session establish " + "returned '%s'\n", + get_error_string(ret)); +reset: + mbedtls_ssl_session_reset(&m_env->ssl); + return -1; +} + +static void +mbedtls_debug_out(void *ctx COAP_UNUSED, int level, + const char *file, int line, const char *str) { + int log_level; + /* + * 0 No debug + * 1 Error + * 2 State change + * 3 Informational + * 4 Verbose + */ + switch (level) { + case 4: + case 3: + case 2: + log_level = COAP_LOG_CIPHERS; + break; + case 1: + log_level = LOG_ERR; + break; + case 0: + default: + log_level = 0; + break; + } + coap_log(log_level, "%s:%04d: %s", file, line, str); +} + +#if !COAP_DISABLE_TCP +/* + * return +ve data amount + * 0 no more + * -ve Mbed TLS error + */ +static int +coap_sock_read(void *ctx, unsigned char *out, size_t outl) { + ssize_t ret = MBEDTLS_ERR_SSL_CONN_EOF; + coap_session_t *c_session = (coap_session_t *)ctx; + + if (out != NULL) { +#ifdef _WIN32 + ret = recv(c_session->sock.fd, (char *)out, (int)outl, 0); +#else + ret = recv(c_session->sock.fd, out, outl, 0); +#endif + if (ret > 0) { + coap_log(LOG_DEBUG, "* %s: received %zd bytes\n", + coap_session_str(c_session), ret); + } else if (ret < 0 && errno != EAGAIN) { + coap_log(LOG_DEBUG, "* %s: failed to receive any bytes (%s)\n", + coap_session_str(c_session), coap_socket_strerror()); + } + + if (ret == 0) { + /* graceful shutdown */ + c_session->sock.flags &= ~COAP_SOCKET_CAN_READ; + ret = MBEDTLS_ERR_SSL_CONN_EOF; + } + else if (ret == COAP_SOCKET_ERROR) { +#ifdef _WIN32 + int lasterror = WSAGetLastError(); + + if (lasterror == WSAEWOULDBLOCK) { + ret = MBEDTLS_ERR_SSL_WANT_READ; + } + else if (lasterror == WSAECONNRESET) { + ret = MBEDTLS_ERR_NET_CONN_RESET; + } +#else + if (errno == EAGAIN) { + ret = MBEDTLS_ERR_SSL_WANT_READ; + } + else if (errno == EPIPE || errno == ECONNRESET) { + ret = MBEDTLS_ERR_NET_CONN_RESET; + } +#endif + else { + ret = MBEDTLS_ERR_NET_RECV_FAILED; + } + c_session->sock.flags &= ~COAP_SOCKET_CAN_READ; + } + else if (ret < (ssize_t)outl) { + c_session->sock.flags &= ~COAP_SOCKET_CAN_READ; + } + } + return (int)ret; +} + +/* + * return +ve data amount + * 0 no more + * -ve Mbed TLS error + */ +static int +coap_sock_write(void *context, const unsigned char *in, size_t inl) { + int ret = 0; + coap_session_t *c_session = (coap_session_t *)context; + + ret = (int)coap_socket_write(&c_session->sock, in, inl); + if (ret > 0) { + coap_log(LOG_DEBUG, "* %s: sent %d bytes\n", + coap_session_str(c_session), ret); + } else if (ret < 0) { + if ((c_session->state == COAP_SESSION_STATE_CSM || + c_session->state == COAP_SESSION_STATE_HANDSHAKE) && + (errno == EPIPE || errno == ECONNRESET)) { + /* + * Need to handle a TCP timing window where an agent continues with + * the sending of the next handshake or a CSM. + * However, the peer does not like a certificate and so sends a + * fatal alert and closes the TCP session. + * The sending of the next handshake or CSM may get terminated because + * of the closed TCP session, but there is still an outstanding alert + * to be read in and reported on. + * In this case, pretend that sending the info was fine so that the + * alert can be read (which effectively is what happens with DTLS). + */ + ret = inl; + } + else { +#ifdef _WIN32 + int lasterror = WSAGetLastError(); + + if (lasterror == WSAEWOULDBLOCK) { + ret = MBEDTLS_ERR_SSL_WANT_WRITE; + } + else if (lasterror == WSAECONNRESET) { + ret = MBEDTLS_ERR_NET_CONN_RESET; + } +#else + if (errno == EAGAIN || errno == EINTR) { + ret = MBEDTLS_ERR_SSL_WANT_WRITE; + } + else if (errno == EPIPE || errno == ECONNRESET) { + ret = MBEDTLS_ERR_NET_CONN_RESET; + } +#endif + else { + ret = MBEDTLS_ERR_NET_SEND_FAILED; + } + coap_log(LOG_DEBUG, "* %s: failed to send %zd bytes (%s) state %d\n", + coap_session_str(c_session), inl, coap_socket_strerror(), + c_session->state); + } + } + if (ret == 0) { + errno = EAGAIN; + ret = MBEDTLS_ERR_SSL_WANT_WRITE; + } + return ret; +} +#endif /* !COAP_DISABLE_TCP */ + +static coap_mbedtls_env_t *coap_dtls_new_mbedtls_env(coap_session_t *c_session, + coap_dtls_role_t role, + coap_proto_t proto) +{ + int ret = 0; + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + + if (m_env) + return m_env; + + m_env = (coap_mbedtls_env_t *)mbedtls_malloc(sizeof(coap_mbedtls_env_t)); + if (!m_env) { + return NULL; + } + memset(m_env, 0, sizeof(coap_mbedtls_env_t)); + + mbedtls_ssl_init(&m_env->ssl); + mbedtls_ctr_drbg_init(&m_env->ctr_drbg); + mbedtls_ssl_config_init(&m_env->conf); + mbedtls_entropy_init(&m_env->entropy); + +#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG) + mbedtls_esp_enable_debug_log(&m_env->conf, CONFIG_MBEDTLS_DEBUG_LEVEL); +#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */ + if ((ret = mbedtls_ctr_drbg_seed(&m_env->ctr_drbg, + mbedtls_entropy_func, &m_env->entropy, NULL, 0)) != 0) { + coap_log(LOG_ERR, "mbedtls_ctr_drbg_seed returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + goto fail; + } + + if (role == COAP_DTLS_ROLE_CLIENT) { +#if COAP_CLIENT_SUPPORT + if (setup_client_ssl_session(c_session, m_env) != 0) { + goto fail; + } +#else /* !COAP_CLIENT_SUPPORT */ + goto fail; +#endif /* !COAP_CLIENT_SUPPORT */ + } else if (role == COAP_DTLS_ROLE_SERVER) { +#if defined(MBEDTLS_SSL_SRV_C) + if (setup_server_ssl_session(c_session, m_env) != 0) { + goto fail; + } +#else /* ! MBEDTLS_SSL_SRV_C */ + goto fail; +#endif /* ! MBEDTLS_SSL_SRV_C */ + } else { + goto fail; + } + +#if MBEDTLS_VERSION_NUMBER >= 0x03020000 + mbedtls_ssl_conf_min_tls_version(&m_env->conf, MBEDTLS_SSL_VERSION_TLS1_2); +#else + mbedtls_ssl_conf_min_version(&m_env->conf, MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_3); +#endif /* MBEDTLS_VERSION_NUMBER >= 0x03020000 */ + + if ((ret = mbedtls_ssl_setup(&m_env->ssl, &m_env->conf)) != 0) { + goto fail; + } + if (proto == COAP_PROTO_DTLS) { + mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_dgram_write, + coap_dgram_read, NULL); + } +#if !COAP_DISABLE_TCP + else { + assert(proto == COAP_PROTO_TLS); + mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_sock_write, + coap_sock_read, NULL); + } +#endif /* ! COAP_DISABLE_TCP */ + mbedtls_ssl_set_timer_cb(&m_env->ssl, &m_env->timer, + mbedtls_timing_set_delay, + mbedtls_timing_get_delay); + + mbedtls_ssl_conf_dbg(&m_env->conf, mbedtls_debug_out, stdout); + return m_env; + +fail: + if (m_env) { + mbedtls_free(m_env); + } + return NULL; +} + +int coap_dtls_is_supported(void) { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + return 1; +#else /* !MBEDTLS_SSL_PROTO_DTLS */ + static int reported = 0; + if (!reported) { + reported = 1; + coap_log(LOG_EMERG, + "libcoap not compiled for DTLS with Mbed TLS" + " - update Mbed TLS to include DTLS\n"); + } + return 0; +#endif /* !MBEDTLS_SSL_PROTO_DTLS */ +} + +int coap_tls_is_supported(void) +{ +#if !COAP_DISABLE_TCP + return 1; +#else /* COAP_DISABLE_TCP */ + return 0; +#endif /* COAP_DISABLE_TCP */ +} + +void *coap_dtls_new_context(coap_context_t *c_context) +{ + coap_mbedtls_context_t *m_context; + (void)c_context; + + m_context = (coap_mbedtls_context_t *)mbedtls_malloc(sizeof(coap_mbedtls_context_t)); + if (m_context) { + memset(m_context, 0, sizeof(coap_mbedtls_context_t)); + } + return m_context; +} + +#if COAP_SERVER_SUPPORT +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_context_set_spsk(coap_context_t *c_context, + coap_dtls_spsk_t *setup_data +) { + coap_mbedtls_context_t *m_context = + ((coap_mbedtls_context_t *)c_context->dtls_context); + +#if !defined(MBEDTLS_SSL_SRV_C) + coap_log(LOG_EMERG, "coap_context_set_spsk:" + " libcoap not compiled for Server Mode for Mbed TLS" + " - update Mbed TLS to include Server Mode\n"); + return 0; +#endif /* !MBEDTLS_SSL_SRV_C */ + if (!m_context || !setup_data) + return 0; + + m_context->psk_pki_enabled |= IS_PSK; + return 1; +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_context_set_cpsk(coap_context_t *c_context, + coap_dtls_cpsk_t *setup_data +) { +#if !defined(MBEDTLS_SSL_CLI_C) + coap_log(LOG_EMERG, "coap_context_set_cpsk:" + " libcoap not compiled for Client Mode for Mbed TLS" + " - update Mbed TLS to include Client Mode\n"); + return 0; +#else /* MBEDTLS_SSL_CLI_C */ + coap_mbedtls_context_t *m_context = + ((coap_mbedtls_context_t *)c_context->dtls_context); + + if (!m_context || !setup_data) + return 0; + + if (setup_data->validate_ih_call_back) { + coap_log(LOG_WARNING, + "CoAP Client with Mbed TLS does not support Identity Hint selection\n"); + } + m_context->psk_pki_enabled |= IS_PSK; + return 1; +#endif /* MBEDTLS_SSL_CLI_C */ +} +#endif /* COAP_CLIENT_SUPPORT */ + +int coap_dtls_context_set_pki(coap_context_t *c_context, + const coap_dtls_pki_t *setup_data, + const coap_dtls_role_t role COAP_UNUSED) +{ + coap_mbedtls_context_t *m_context = + ((coap_mbedtls_context_t *)c_context->dtls_context); + + m_context->setup_data = *setup_data; + if (!m_context->setup_data.verify_peer_cert) { + /* Needs to be clear so that no CA DNs are transmitted */ + m_context->setup_data.check_common_ca = 0; + /* Allow all of these but warn if issue */ + m_context->setup_data.allow_self_signed = 1; + m_context->setup_data.allow_expired_certs = 1; + m_context->setup_data.cert_chain_validation = 1; + m_context->setup_data.cert_chain_verify_depth = 10; + m_context->setup_data.check_cert_revocation = 1; + m_context->setup_data.allow_no_crl = 1; + m_context->setup_data.allow_expired_crl = 1; + m_context->setup_data.allow_bad_md_hash = 1; + m_context->setup_data.allow_short_rsa_length = 1; + } + m_context->psk_pki_enabled |= IS_PKI; + return 1; +} + +int coap_dtls_context_set_pki_root_cas(coap_context_t *c_context, + const char *ca_file, + const char *ca_path) +{ + coap_mbedtls_context_t *m_context = + ((coap_mbedtls_context_t *)c_context->dtls_context); + + if (!m_context) { + coap_log(LOG_WARNING, + "coap_context_set_pki_root_cas: (D)TLS environment " + "not set up\n"); + return 0; + } + + if (ca_file == NULL && ca_path == NULL) { + coap_log(LOG_WARNING, + "coap_context_set_pki_root_cas: ca_file and/or ca_path " + "not defined\n"); + return 0; + } + if (m_context->root_ca_file) { + mbedtls_free(m_context->root_ca_file); + m_context->root_ca_file = NULL; + } + + if (ca_file) { + m_context->root_ca_file = mbedtls_strdup(ca_file); + } + + if (m_context->root_ca_path) { + mbedtls_free(m_context->root_ca_path); + m_context->root_ca_path = NULL; + } + + if (ca_path) { + m_context->root_ca_path = mbedtls_strdup(ca_path); + } + return 1; +} + +int coap_dtls_context_check_keys_enabled(coap_context_t *c_context) +{ + coap_mbedtls_context_t *m_context = + ((coap_mbedtls_context_t *)c_context->dtls_context); + return m_context->psk_pki_enabled ? 1 : 0; +} + +void coap_dtls_free_context(void *dtls_context) +{ + coap_mbedtls_context_t *m_context = (coap_mbedtls_context_t *)dtls_context; + unsigned int i; + + for (i = 0; i < m_context->pki_sni_count; i++) { + mbedtls_free(m_context->pki_sni_entry_list[i].sni); + + mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].public_cert); + + mbedtls_pk_free(&m_context->pki_sni_entry_list[i].private_key); + + mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].cacert); + } + if (m_context->pki_sni_entry_list) + mbedtls_free(m_context->pki_sni_entry_list); + + for (i = 0; i < m_context->psk_sni_count; i++) { + mbedtls_free(m_context->psk_sni_entry_list[i].sni); + } + if (m_context->psk_sni_entry_list) + mbedtls_free(m_context->psk_sni_entry_list); + + if (m_context->root_ca_path) + mbedtls_free(m_context->root_ca_path); + if (m_context->root_ca_file) + mbedtls_free(m_context->root_ca_file); + + mbedtls_free(m_context); +} + +#if COAP_CLIENT_SUPPORT +void *coap_dtls_new_client_session(coap_session_t *c_session) +{ +#if !defined(MBEDTLS_SSL_CLI_C) + (void)c_session; + coap_log(LOG_EMERG, "coap_dtls_new_client_session:" + " libcoap not compiled for Client Mode for Mbed TLS" + " - update Mbed TLS to include Client Mode\n"); + return NULL; +#else /* MBEDTLS_SSL_CLI_C */ + coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session, + COAP_DTLS_ROLE_CLIENT, + COAP_PROTO_DTLS); + int ret; + + if (m_env) { + coap_tick_t now; + coap_ticks(&now); + m_env->last_timeout = now; + ret = do_mbedtls_handshake(c_session, m_env); + if (ret == -1) { + coap_dtls_free_mbedtls_env(m_env); + return NULL; + } + } + return m_env; +#endif /* MBEDTLS_SSL_CLI_C */ +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +void *coap_dtls_new_server_session(coap_session_t *c_session) +{ +#if !defined(MBEDTLS_SSL_SRV_C) + (void)c_session; + coap_log(LOG_EMERG, "coap_dtls_new_server_session:" + " libcoap not compiled for Server Mode for Mbed TLS" + " - update Mbed TLS to include Server Mode\n"); + return NULL; +#else /* MBEDTLS_SSL_SRV_C */ + coap_mbedtls_env_t *m_env = + (coap_mbedtls_env_t *)c_session->tls; + if (m_env) { +#if defined(MBEDTLS_SSL_PROTO_DTLS) +#if MBEDTLS_VERSION_NUMBER >= 0x02100100 + mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu); +#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + } + return m_env; +#endif /* MBEDTLS_SSL_SRV_C */ +} +#endif /* COAP_SERVER_SUPPORT */ + +void coap_dtls_free_session(coap_session_t *c_session) +{ + if (c_session && c_session->context && c_session->tls) { + coap_dtls_free_mbedtls_env(c_session->tls); + c_session->tls = NULL; + coap_handle_event(c_session->context, COAP_EVENT_DTLS_CLOSED, c_session); + } + return; +} + +void coap_dtls_session_update_mtu(coap_session_t *c_session) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + coap_mbedtls_env_t *m_env = + (coap_mbedtls_env_t *)c_session->tls; + if (m_env) { +#if MBEDTLS_VERSION_NUMBER >= 0x02100100 + mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu); +#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */ + } +#else /* ! MBEDTLS_SSL_PROTO_DTLS */ + (void)c_session; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +} + +int coap_dtls_send(coap_session_t *c_session, + const uint8_t *data, + size_t data_len) +{ + int ret; + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + + assert(m_env != NULL); + + if (!m_env) { + return -1; + } + c_session->dtls_event = -1; + if (m_env->established) { + ret = mbedtls_ssl_write(&m_env->ssl, (const unsigned char*) data, data_len); + if (ret <= 0) { + switch (ret) { + case MBEDTLS_ERR_SSL_WANT_READ: + case MBEDTLS_ERR_SSL_WANT_WRITE: + ret = 0; + break; + case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + default: + coap_log(LOG_WARNING, + "coap_dtls_send: " + "returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + ret = -1; + break; + } + if (ret == -1) { + coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n"); + } + } + } else { + ret = do_mbedtls_handshake(c_session, m_env); + if (ret == 1) { + /* Just connected, so send the data */ + return coap_dtls_send(c_session, data, data_len); + } + ret = -1; + } + + if (c_session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(c_session->context, c_session->dtls_event, c_session); + if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || + c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + ret = -1; + } + } + return ret; +} + +int coap_dtls_is_context_timeout(void) +{ + return 0; +} + +coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED) +{ + return 0; +} + +coap_tick_t coap_dtls_get_timeout(coap_session_t *c_session, coap_tick_t now) +{ + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + int ret = mbedtls_timing_get_delay(&m_env->timer); + unsigned int scalar = 1 << m_env->retry_scalar; + + assert(c_session->state == COAP_SESSION_STATE_HANDSHAKE); + switch (ret) { + case 0: + /* int_ms has not timed out */ + if (m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) { + /* Need to indicate remaining timeout time */ + return m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar; + } + m_env->last_timeout = now; + /* This may cause a minor extra delay */ + return now + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar; + case 1: + /* int_ms has timed out, but not fin_ms */ + /* + * Need to make sure that we do not do this too frequently + */ + if (m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) { + return m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar; + } + + /* Reset for the next time */ + m_env->last_timeout = now; + return now; + case 2: + /* fin_ms has timed out - timed out - one final try */ + return now; + default: + break; + } + + return 0; +} + +/* + * return 1 timed out + * 0 still timing out + */ +int +coap_dtls_handle_timeout(coap_session_t *c_session) +{ + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + + assert(m_env != NULL && c_session->state == COAP_SESSION_STATE_HANDSHAKE); + m_env->retry_scalar++; + if ((++c_session->dtls_timeout_count > c_session->max_retransmit) || + (do_mbedtls_handshake(c_session, m_env) < 0)) { + /* Too many retries */ + coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + return 1; + } + return 0; +} + +/* + * return +ve data amount + * 0 no more + * -1 error + */ +int coap_dtls_receive(coap_session_t *c_session, + const uint8_t *data, + size_t data_len) +{ + int ret = 1; + + c_session->dtls_event = -1; + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + coap_ssl_t *ssl_data; + + assert(m_env != NULL); + + ssl_data = &m_env->coap_ssl_data; + if (ssl_data->pdu_len) { + coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n", + coap_session_str(c_session), ssl_data->pdu_len); + } + ssl_data->pdu = data; + ssl_data->pdu_len = (unsigned)data_len; + + if (m_env->established) { +#if COAP_CONSTRAINED_STACK + static coap_mutex_t b_static_mutex = COAP_MUTEX_INITIALIZER; + static uint8_t pdu[COAP_RXBUFFER_SIZE]; +#else /* ! COAP_CONSTRAINED_STACK */ + uint8_t pdu[COAP_RXBUFFER_SIZE]; +#endif /* ! COAP_CONSTRAINED_STACK */ + +#if COAP_CONSTRAINED_STACK + coap_mutex_lock(&b_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + + if (c_session->state == COAP_SESSION_STATE_HANDSHAKE) { + coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, + c_session); + coap_session_connected(c_session); + } + + ret = mbedtls_ssl_read(&m_env->ssl, pdu, sizeof(pdu)); + if (ret > 0) { + ret = coap_handle_dgram(c_session->context, c_session, pdu, (size_t)ret); +#if COAP_CONSTRAINED_STACK + coap_mutex_unlock(&b_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + goto finish; + } + switch (ret) { + case 0: + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + break; + case MBEDTLS_ERR_SSL_WANT_READ: + break; + default: + coap_log(LOG_WARNING, + "coap_dtls_receive: " + "returned -0x%x: '%s' (length %zd)\n", + -ret, get_error_string(ret), data_len); + break; + } +#if COAP_CONSTRAINED_STACK + coap_mutex_unlock(&b_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + ret = -1; + } + else { + ret = do_mbedtls_handshake(c_session, m_env); + if (ret == 1) { + /* Just connected, so send the data */ + coap_session_connected(c_session); + } else { + if (ssl_data->pdu_len) { + /* Do the handshake again incase of internal timeout */ + ret = do_mbedtls_handshake(c_session, m_env); + if (ret == 1) { + /* Just connected, so send the data */ + coap_session_connected(c_session); + } else { + ret = -1; + } + } + ret = -1; + } + } + if (c_session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(c_session->context, c_session->dtls_event, c_session); + if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || + c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + ssl_data = NULL; + ret = -1; + } + } +finish: + if (ssl_data && ssl_data->pdu_len) { + /* pdu data is held on stack which will not stay there */ + coap_log(LOG_DEBUG, "coap_dtls_receive: ret %d: remaining data %u\n", ret, ssl_data->pdu_len); + ssl_data->pdu_len = 0; + ssl_data->pdu = NULL; + } + return ret; +} + +#if COAP_SERVER_SUPPORT +/* + * return -1 failure + * 0 not completed + * 1 client hello seen + */ +int coap_dtls_hello(coap_session_t *c_session, + const uint8_t *data, + size_t data_len) +{ +#if !defined(MBEDTLS_SSL_PROTO_DTLS) || !defined(MBEDTLS_SSL_SRV_C) + (void)c_session; + (void)data; + (void)data_len; + coap_log(LOG_EMERG, "coap_dtls_hello:" + " libcoap not compiled for DTLS or Server Mode for Mbed TLS" + " - update Mbed TLS to include DTLS and Server Mode\n"); + return -1; +#else /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_SSL_SRV_C */ + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + coap_ssl_t *ssl_data; + int ret; + + if (!m_env) { + m_env = coap_dtls_new_mbedtls_env(c_session, COAP_DTLS_ROLE_SERVER, + COAP_PROTO_DTLS); + if (m_env) { + c_session->tls = m_env; + } + else { + /* error should have already been reported */ + return -1; + } + } + + if((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl, + (unsigned char *)&c_session->addr_info.remote, + sizeof(c_session->addr_info.remote))) != 0) { + coap_log(LOG_ERR, + "mbedtls_ssl_set_client_transport_id() returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + return -1; + } + + ssl_data = &m_env->coap_ssl_data; + if (ssl_data->pdu_len) { + coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n", + coap_session_str(c_session), ssl_data->pdu_len); + } + ssl_data->pdu = data; + ssl_data->pdu_len = (unsigned)data_len; + + ret = do_mbedtls_handshake(c_session, m_env); + if (ret == 0 || m_env->seen_client_hello) { + /* The test for seen_client_hello gives the ability to setup a new + c_session to continue the do_mbedtls_handshake past the client hello + and safely allow updating of the m_env and separately + letting a new session cleanly start up. + */ + m_env->seen_client_hello = 0; + ret = 1; + } + else { + ret = 0; + } + + if (ssl_data->pdu_len) { + /* pdu data is held on stack which will not stay there */ + coap_log(LOG_DEBUG, "coap_dtls_hello: ret %d: remaining data %u\n", ret, ssl_data->pdu_len); + ssl_data->pdu_len = 0; + ssl_data->pdu = NULL; + } + return ret; +#endif /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_SSL_SRV_C */ +} +#endif /* COAP_SERVER_SUPPORT */ + +unsigned int coap_dtls_get_overhead(coap_session_t *c_session) +{ + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + int expansion = mbedtls_ssl_get_record_expansion(&m_env->ssl); + + if (expansion == MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) { + return 13 + 8 + 8; + } + return expansion; +} + +#if !COAP_DISABLE_TCP +#if COAP_CLIENT_SUPPORT +void *coap_tls_new_client_session(coap_session_t *c_session, + int *connected) +{ +#if !defined(MBEDTLS_SSL_CLI_C) + (void)c_session; + *connected = 0; + coap_log(LOG_EMERG, "coap_tls_new_client_session:" + " libcoap not compiled for Client Mode for Mbed TLS" + " - update Mbed TLS to include Client Mode\n"); + return NULL; +#else /* MBEDTLS_SSL_CLI_C */ + coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session, + COAP_DTLS_ROLE_CLIENT, + COAP_PROTO_TLS); + int ret; + coap_tick_t now; + coap_ticks(&now); + + *connected = 0; + if (!m_env) + return NULL; + + m_env->last_timeout = now; + c_session->tls = m_env; + ret = do_mbedtls_handshake(c_session, m_env); + if (ret == 1) { + *connected = 1; + coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, c_session); + coap_session_send_csm(c_session); + } + return m_env; +#endif /* MBEDTLS_SSL_CLI_C */ +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +void *coap_tls_new_server_session(coap_session_t *c_session COAP_UNUSED, + int *connected COAP_UNUSED) +{ +#if !defined(MBEDTLS_SSL_SRV_C) + (void)c_session; + coap_log(LOG_EMERG, "coap_tls_new_server_session:" + " libcoap not compiled for Server Mode for Mbed TLS" + " - update Mbed TLS to include Server Mode\n"); + return NULL; +#else /* MBEDTLS_SSL_SRV_C */ + coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session, + COAP_DTLS_ROLE_SERVER, + COAP_PROTO_TLS); + int ret; + + c_session->tls = m_env; + ret = do_mbedtls_handshake(c_session, m_env); + if (ret == 1) { + *connected = 1; + } + return m_env; +#endif /* MBEDTLS_SSL_SRV_C */ +} +#endif /* COAP_SERVER_SUPPORT */ + +void coap_tls_free_session(coap_session_t *c_session) +{ + coap_dtls_free_session(c_session); + return; +} + +/* + * return +ve data amount + * 0 no more + * -1 error (error in errno) + */ +ssize_t coap_tls_write(coap_session_t *c_session, + const uint8_t *data, + size_t data_len + ) +{ + int ret; + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + + assert(m_env != NULL); + + if (!m_env) { + return -1; + } + c_session->dtls_event = -1; + if (m_env->established) { + ret = mbedtls_ssl_write(&m_env->ssl, (const unsigned char*) data, data_len); + if (ret <= 0) { + switch (ret) { + case MBEDTLS_ERR_SSL_WANT_READ: + case MBEDTLS_ERR_SSL_WANT_WRITE: + ret = 0; + break; + case MBEDTLS_ERR_NET_CONN_RESET: + case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + default: + coap_log(LOG_WARNING, + "coap_tls_write: " + "returned -0x%x: '%s'\n", + -ret, get_error_string(ret)); + ret = -1; + break; + } + if (ret == -1) { + coap_log(LOG_WARNING, "coap_tls_write: cannot send PDU\n"); + } + } + } else { + ret = do_mbedtls_handshake(c_session, m_env); + if (ret == 1) { + coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, + c_session); + coap_session_send_csm(c_session); + } + else { + ret = -1; + } + } + + if (c_session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(c_session->context, c_session->dtls_event, c_session); + if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || + c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + ret = -1; + } + } + return ret; +} + +/* + * return +ve data amount + * 0 no more + * -1 error (error in errno) + */ +ssize_t coap_tls_read(coap_session_t *c_session, + uint8_t *data, + size_t data_len + ) +{ + int ret = -1; + + coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; + + if (!m_env) + return -1; + + c_session->dtls_event = -1; + + if (!m_env->established && !m_env->sent_alert) { + ret = do_mbedtls_handshake(c_session, m_env); + if (ret == 1) { + coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, + c_session); + coap_session_send_csm(c_session); + } + } + + if (c_session->state != COAP_SESSION_STATE_NONE && m_env->established) { + ret = mbedtls_ssl_read(&m_env->ssl, data, data_len); + if (ret <= 0) { + switch (ret) { + case 0: + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: + /* Stop the sending of an alert on closedown */ + m_env->sent_alert = 1; + c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; + ret = -1; + break; + case MBEDTLS_ERR_SSL_WANT_READ: + errno = EAGAIN; + ret = 0; + break; + default: + coap_log(LOG_WARNING, + "coap_tls_read: " + "returned -0x%x: '%s' (length %zd)\n", + -ret, get_error_string(ret), data_len); + ret = -1; + break; + } + } + } + + if (c_session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(c_session->context, c_session->dtls_event, c_session); + if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || + c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + ret = -1; + } + } + return ret; +} +#endif /* !COAP_DISABLE_TCP */ + +void coap_dtls_startup(void) +{ +} + +void coap_dtls_shutdown(void) { +#if COAP_CLIENT_SUPPORT + mbedtls_free(psk_ciphers); + mbedtls_free(pki_ciphers); + psk_ciphers = NULL; + pki_ciphers = NULL; + processed_ciphers = 0; +#endif /* COAP_CLIENT_SUPPORT */ +} + +void * +coap_dtls_get_tls(const coap_session_t *c_session, + coap_tls_library_t *tls_lib) { + if (tls_lib) + *tls_lib = COAP_TLS_LIBRARY_MBEDTLS; + if (c_session && c_session->tls) { + coap_mbedtls_env_t *m_env; + + /* To get around const issue */ + memcpy(&m_env, &c_session->tls, sizeof(m_env)); + + return (void *)&m_env->ssl; + } + return NULL; +} + +static int keep_log_level = 0; + +void coap_dtls_set_log_level(int level) +{ +#if !defined(ESPIDF_VERSION) + int use_level; + /* + * Mbed TLS debug levels filter + * 0 No debug + * 1 Error + * 2 State change + * 3 Informational + * 4 Verbose + */ + + if (level <= LOG_ERR) { + use_level = 1; + } + else { + use_level = (level >= LOG_DEBUG) ? level - LOG_DEBUG + 2 : 0; + } + mbedtls_debug_set_threshold(use_level); +#endif /* !ESPIDF_VERSION) */ + keep_log_level = level; +} + +int coap_dtls_get_log_level(void) +{ + return keep_log_level; +} + +coap_tls_version_t * coap_get_tls_library_version(void) +{ + static coap_tls_version_t version; + version.version = mbedtls_version_get_number(); + version.built_version = MBEDTLS_VERSION_NUMBER; + version.type = COAP_TLS_LIBRARY_MBEDTLS; + return &version; +} + +#if COAP_SERVER_SUPPORT +coap_digest_ctx_t * +coap_digest_setup(void) { + mbedtls_sha256_context *digest_ctx = mbedtls_malloc(sizeof(mbedtls_sha256_context)); + + if (digest_ctx) { + mbedtls_sha256_init(digest_ctx); +#ifdef MBEDTLS_2_X_COMPAT + if (mbedtls_sha256_starts_ret(digest_ctx, 0) != 0) { +#else + if (mbedtls_sha256_starts(digest_ctx, 0) != 0) { +#endif /* MBEDTLS_2_X_COMPAT */ + return NULL; + } + } + return digest_ctx; +} + +void +coap_digest_free(coap_digest_ctx_t *digest_ctx) { + mbedtls_sha256_free(digest_ctx); + mbedtls_free(digest_ctx); +} + +int +coap_digest_update(coap_digest_ctx_t *digest_ctx, + const uint8_t *data, + size_t data_len) { +#ifdef MBEDTLS_2_X_COMPAT + int ret = mbedtls_sha256_update_ret(digest_ctx, data, data_len); +#else + int ret = mbedtls_sha256_update(digest_ctx, data, data_len); +#endif /* MBEDTLS_2_X_COMPAT */ + + return ret == 0; +} + +int +coap_digest_final(coap_digest_ctx_t *digest_ctx, + coap_digest_t *digest_buffer) { +#ifdef MBEDTLS_2_X_COMPAT + int ret = mbedtls_sha256_finish_ret(digest_ctx, (uint8_t*)digest_buffer); +#else + int ret = mbedtls_sha256_finish(digest_ctx, (uint8_t*)digest_buffer); +#endif /* MBEDTLS_2_X_COMPAT */ + + coap_digest_free(digest_ctx); + return ret == 0; +} +#endif /* COAP_SERVER_SUPPORT */ + +#else /* !HAVE_MBEDTLS */ + +#ifdef __clang__ +/* Make compilers happy that do not like empty modules. As this function is + * never used, we ignore -Wunused-function at the end of compiling this file + */ +#pragma GCC diagnostic ignored "-Wunused-function" +#endif +static inline void dummy(void) { +} + +#endif /* HAVE_MBEDTLS */ diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_notls.c b/examples/espidf-coap-server/components/libcoap/src/coap_notls.c new file mode 100644 index 000000000..ef20ae358 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_notls.c @@ -0,0 +1,271 @@ +/* + * coap_notls.c -- Stub Datagram Transport Layer Support for libcoap + * + * Copyright (C) 2016 Olaf Bergmann + * Copyright (C) 2021-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_notls.c + * @brief NoTLS specific interface functions + */ + +#include "coap3/coap_internal.h" + +#if !defined(HAVE_LIBTINYDTLS) && !defined(HAVE_OPENSSL) && !defined(HAVE_LIBGNUTLS) && !defined(HAVE_MBEDTLS) + +int +coap_dtls_is_supported(void) { + return 0; +} + +int +coap_tls_is_supported(void) { + return 0; +} + +coap_tls_version_t * +coap_get_tls_library_version(void) { + static coap_tls_version_t version; + version.version = 0; + version.type = COAP_TLS_LIBRARY_NOTLS; + return &version; +} + +int +coap_dtls_context_set_pki(coap_context_t *ctx COAP_UNUSED, + const coap_dtls_pki_t* setup_data COAP_UNUSED, + const coap_dtls_role_t role COAP_UNUSED +) { + return 0; +} + +int +coap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED, + const char *ca_file COAP_UNUSED, + const char *ca_path COAP_UNUSED +) { + return 0; +} + +#if COAP_CLIENT_SUPPORT +int +coap_dtls_context_set_cpsk(coap_context_t *ctx COAP_UNUSED, + coap_dtls_cpsk_t* setup_data COAP_UNUSED +) { + return 0; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +int +coap_dtls_context_set_spsk(coap_context_t *ctx COAP_UNUSED, + coap_dtls_spsk_t* setup_data COAP_UNUSED +) { + return 0; +} +#endif /* COAP_SERVER_SUPPORT */ + +int +coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED) +{ + return 0; +} + +static int dtls_log_level = 0; + +void coap_dtls_startup(void) { +} + +void * +coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, + coap_tls_library_t *tls_lib) { + if (tls_lib) + *tls_lib = COAP_TLS_LIBRARY_NOTLS; + return NULL; +} + +void coap_dtls_shutdown(void) { +} + +void +coap_dtls_set_log_level(int level) { + dtls_log_level = level; +} + +int +coap_dtls_get_log_level(void) { + return dtls_log_level; +} + +void * +coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED) { + return NULL; +} + +void +coap_dtls_free_context(void *handle COAP_UNUSED) { +} + +#if COAP_SERVER_SUPPORT +void *coap_dtls_new_server_session(coap_session_t *session COAP_UNUSED) { + return NULL; +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +void *coap_dtls_new_client_session(coap_session_t *session COAP_UNUSED) { + return NULL; +} +#endif /* COAP_CLIENT_SUPPORT */ + +void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED) { +} + +void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED) { +} + +int +coap_dtls_send(coap_session_t *session COAP_UNUSED, + const uint8_t *data COAP_UNUSED, + size_t data_len COAP_UNUSED +) { + return -1; +} + +int coap_dtls_is_context_timeout(void) { + return 1; +} + +coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED) { + return 0; +} + +coap_tick_t +coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED) { + return 0; +} + +/* + * return 1 timed out + * 0 still timing out + */ +int +coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED) { + return 0; +} + +int +coap_dtls_receive(coap_session_t *session COAP_UNUSED, + const uint8_t *data COAP_UNUSED, + size_t data_len COAP_UNUSED +) { + return -1; +} + +#if COAP_SERVER_SUPPORT +int +coap_dtls_hello(coap_session_t *session COAP_UNUSED, + const uint8_t *data COAP_UNUSED, + size_t data_len COAP_UNUSED +) { + return 0; +} +#endif /* COAP_SERVER_SUPPORT */ + +unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED) { + return 0; +} + +#if COAP_CLIENT_SUPPORT +void *coap_tls_new_client_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED) { + return NULL; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +void *coap_tls_new_server_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED) { + return NULL; +} +#endif /* COAP_SERVER_SUPPORT */ + +void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED) { +} + +ssize_t coap_tls_write(coap_session_t *session COAP_UNUSED, + const uint8_t *data COAP_UNUSED, + size_t data_len COAP_UNUSED +) { + return -1; +} + +ssize_t coap_tls_read(coap_session_t *session COAP_UNUSED, + uint8_t *data COAP_UNUSED, + size_t data_len COAP_UNUSED +) { + return -1; +} + +#if COAP_SERVER_SUPPORT +typedef struct coap_local_hash_t { + size_t ofs; + coap_key_t key[8]; /* 32 bytes in total */ +} coap_local_hash_t; + +coap_digest_ctx_t * +coap_digest_setup(void) { + coap_key_t *digest_ctx = coap_malloc(sizeof(coap_local_hash_t)); + + if (digest_ctx) { + memset(digest_ctx, 0, sizeof(coap_local_hash_t)); + } + + return digest_ctx; +} + +void +coap_digest_free(coap_digest_ctx_t *digest_ctx) { + coap_free(digest_ctx); +} + +int +coap_digest_update(coap_digest_ctx_t *digest_ctx, + const uint8_t *data, + size_t data_len) { + coap_local_hash_t *local = (coap_local_hash_t*)digest_ctx; + + coap_hash(data, data_len, local->key[local->ofs]); + + local->ofs = (local->ofs + 1) % 7; + return 1; +} + +int +coap_digest_final(coap_digest_ctx_t *digest_ctx, + coap_digest_t *digest_buffer) { + coap_local_hash_t *local = (coap_local_hash_t*)digest_ctx; + + memcpy(digest_buffer, local->key, sizeof(coap_digest_t)); + + coap_digest_free(digest_ctx); + return 1; +} +#endif /* COAP_SERVER_SUPPORT */ + +#else /* !HAVE_LIBTINYDTLS && !HAVE_OPENSSL && !HAVE_LIBGNUTLS */ + +#ifdef __clang__ +/* Make compilers happy that do not like empty modules. As this function is + * never used, we ignore -Wunused-function at the end of compiling this file + */ +#pragma GCC diagnostic ignored "-Wunused-function" +#endif +static inline void dummy(void) { +} + +#endif /* !HAVE_LIBTINYDTLS && !HAVE_OPENSSL && !HAVE_LIBGNUTLS && !HAVE_MBEDTLS */ diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_openssl.c b/examples/espidf-coap-server/components/libcoap/src/coap_openssl.c new file mode 100644 index 000000000..c92ba16c8 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_openssl.c @@ -0,0 +1,3527 @@ +/* + * coap_openssl.c -- Datagram Transport Layer Support for libcoap with openssl + * + * Copyright (C) 2017 Jean-Claude Michelou + * Copyright (C) 2018-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_openssl.c + * @brief OpenSSL specific interface functions. + */ + +#include "coap3/coap_internal.h" + +#ifdef HAVE_OPENSSL + +/* + * OpenSSL 1.1.0 has support for making decisions during receipt of + * the Client Hello - the call back function is set up using + * SSL_CTX_set_tlsext_servername_callback() which is called later in the + * Client Hello processing - but called every Client Hello. + * Certificates and Preshared Keys have to be set up in the SSL CTX before + * SSL_accept() is called, making the code messy to decide whether this is a + * PKI or PSK incoming request to handle things accordingly if both are + * defined. SNI has to create a new SSL CTX to handle different server names + * with different crtificates. + * + * OpenSSL 1.1.1 introduces a new function SSL_CTX_set_client_hello_cb(). + * The call back is invoked early on in the Client Hello processing giving + * the ability to easily use different Preshared Keys, Certificates etc. + * Certificates do not have to be set up in the SSL CTX before SSL_Accept is + * called. + * Later in the Client Hello code, the callback for + * SSL_CTX_set_tlsext_servername_callback() is still called, but only if SNI + * is being used by the client, so cannot be used for doing things the + * OpenSSL 1.1.0 way. + * + * OpenSSL 1.1.1 supports TLS1.3. + * + * Consequently, this code has to have compile time options to include / + * exclude code based on whether compiled against 1.1.0 or 1.1.1, as well as + * have additional run time checks. + * + * It is possible to override the Ciphers, define the Algorithms or Groups + * to use for the SSL negotiations at compile time. This is done by the adding + * of the appropriate -D option to the CPPFLAGS parameter that is used on the + * ./configure command line. + * E.g. ./configure CPPFLAGS="-DXX=\"YY\" -DUU=\"VV\"" + * The parameter value is case-sensitive. + * + * The ciphers can be overridden with (example) + * -DCOAP_OPENSSL_CIPHERS=\"ECDHE-ECDSA-AES256-GCM-SHA384\" + * + * The Algorithms can be defined by (example) + * -DCOAP_OPENSSL_SIGALGS=\"ed25519\" + * + * The Groups (OpenSSL 1.1.1 or later) can be defined by (example) + * -DCOAP_OPENSSL_GROUPS=\"X25519\" + * + */ +#include +#include +#include +#include +#include +#include + +#ifdef COAP_EPOLL_SUPPORT +# include +#endif /* COAP_EPOLL_SUPPORT */ + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#error Must be compiled against OpenSSL 1.1.0 or later +#endif + +#ifdef _WIN32 +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#endif + +/* RFC6091/RFC7250 */ +#ifndef TLSEXT_TYPE_client_certificate_type +#define TLSEXT_TYPE_client_certificate_type 19 +#endif +#ifndef TLSEXT_TYPE_server_certificate_type +#define TLSEXT_TYPE_server_certificate_type 20 +#endif + +#ifndef COAP_OPENSSL_CIPHERS +#if OPENSSL_VERSION_NUMBER >= 0x10101000L +#define COAP_OPENSSL_CIPHERS "TLSv1.3:TLSv1.2:!NULL" +#else /* OPENSSL_VERSION_NUMBER < 0x10101000L */ +#define COAP_OPENSSL_CIPHERS "TLSv1.2:!NULL" +#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */ +#endif /*COAP_OPENSSL_CIPHERS */ + +#ifndef COAP_OPENSSL_PSK_CIPHERS +#define COAP_OPENSSL_PSK_CIPHERS "PSK:!NULL" +#endif /*COAP_OPENSSL_PSK_CIPHERS */ + +/* This structure encapsulates the OpenSSL context object. */ +typedef struct coap_dtls_context_t { + SSL_CTX *ctx; + SSL *ssl; /* OpenSSL object for listening to connection requests */ + HMAC_CTX *cookie_hmac; + BIO_METHOD *meth; + BIO_ADDR *bio_addr; +} coap_dtls_context_t; + +typedef struct coap_tls_context_t { + SSL_CTX *ctx; + BIO_METHOD *meth; +} coap_tls_context_t; + +#define IS_PSK 0x1 +#define IS_PKI 0x2 + +typedef struct sni_entry { + char *sni; +#if OPENSSL_VERSION_NUMBER < 0x10101000L + SSL_CTX *ctx; +#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + coap_dtls_key_t pki_key; +#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ +} sni_entry; + +typedef struct psk_sni_entry { + char *sni; +#if OPENSSL_VERSION_NUMBER < 0x10101000L + SSL_CTX *ctx; +#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */ + coap_dtls_spsk_info_t psk_info; +} psk_sni_entry; + +typedef struct coap_openssl_context_t { + coap_dtls_context_t dtls; +#if !COAP_DISABLE_TCP + coap_tls_context_t tls; +#endif /* !COAP_DISABLE_TCP */ + coap_dtls_pki_t setup_data; + int psk_pki_enabled; + size_t sni_count; + sni_entry *sni_entry_list; + size_t psk_sni_count; + psk_sni_entry *psk_sni_entry_list; +} coap_openssl_context_t; + +#if COAP_SERVER_SUPPORT +#if OPENSSL_VERSION_NUMBER < 0x10101000L +static int psk_tls_server_name_call_back(SSL *ssl, int *sd, void *arg); +#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ +static int psk_tls_client_hello_call_back(SSL *ssl, int *al, void *arg); +#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ +#endif /* COAP_SERVER_SUPPORT */ + +int coap_dtls_is_supported(void) { + if (SSLeay() < 0x10100000L) { + coap_log(LOG_WARNING, "OpenSSL version 1.1.0 or later is required\n"); + return 0; + } +#if OPENSSL_VERSION_NUMBER >= 0x10101000L + /* + * For 1.1.1, we need to use SSL_CTX_set_client_hello_cb() + * which is not in 1.1.0 instead of SSL_CTX_set_tlsext_servername_callback() + * + * However, there could be a runtime undefined external reference error + * as SSL_CTX_set_client_hello_cb() is not there in 1.1.0. + */ + if (SSLeay() < 0x10101000L) { + coap_log(LOG_WARNING, "OpenSSL version 1.1.1 or later is required\n"); + return 0; + } +#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + return 1; +} + +int coap_tls_is_supported(void) { +#if !COAP_DISABLE_TCP + if (SSLeay() < 0x10100000L) { + coap_log(LOG_WARNING, "OpenSSL version 1.1.0 or later is required\n"); + return 0; + } +#if OPENSSL_VERSION_NUMBER >= 0x10101000L + if (SSLeay() < 0x10101000L) { + coap_log(LOG_WARNING, "OpenSSL version 1.1.1 or later is required\n"); + return 0; + } +#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + return 1; +#else /* COAP_DISABLE_TCP */ + return 0; +#endif /* COAP_DISABLE_TCP */ +} + +coap_tls_version_t * +coap_get_tls_library_version(void) { + static coap_tls_version_t version; + version.version = SSLeay(); + version.built_version = OPENSSL_VERSION_NUMBER; + version.type = COAP_TLS_LIBRARY_OPENSSL; + return &version; +} + +static ENGINE* ssl_engine = NULL; + +void coap_dtls_startup(void) { + SSL_load_error_strings(); + SSL_library_init(); + ENGINE_load_dynamic(); +} + +void coap_dtls_shutdown(void) { + if (ssl_engine) { + /* Release the functional reference from ENGINE_init() */ + ENGINE_finish(ssl_engine); + /* Release the structural reference from ENGINE_by_id() */ + ENGINE_free(ssl_engine); + ssl_engine = NULL; + } +} + +void * +coap_dtls_get_tls(const coap_session_t *c_session, + coap_tls_library_t *tls_lib) { + if (tls_lib) + *tls_lib = COAP_TLS_LIBRARY_OPENSSL; + if (c_session) { + return c_session->tls; + } + return NULL; +} + +static int dtls_log_level = 0; + +void coap_dtls_set_log_level(int level) { + dtls_log_level = level; +} + +int coap_dtls_get_log_level(void) { + return dtls_log_level; +} + +typedef struct coap_ssl_st { + coap_session_t *session; + const void *pdu; + unsigned pdu_len; + unsigned peekmode; + coap_tick_t timeout; +} coap_ssl_data; + +static int coap_dgram_create(BIO *a) { + coap_ssl_data *data = NULL; + data = malloc(sizeof(coap_ssl_data)); + if (data == NULL) + return 0; + BIO_set_init(a, 1); + BIO_set_data(a, data); + memset(data, 0x00, sizeof(coap_ssl_data)); + return 1; +} + +static int coap_dgram_destroy(BIO *a) { + coap_ssl_data *data; + if (a == NULL) + return 0; + data = (coap_ssl_data *)BIO_get_data(a); + if (data != NULL) + free(data); + return 1; +} + +static int coap_dgram_read(BIO *a, char *out, int outl) { + int ret = 0; + coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a); + + if (out != NULL) { + if (data != NULL && data->pdu_len > 0) { + if (outl < (int)data->pdu_len) { + memcpy(out, data->pdu, outl); + ret = outl; + } else { + memcpy(out, data->pdu, data->pdu_len); + ret = (int)data->pdu_len; + } + if (!data->peekmode) { + data->pdu_len = 0; + data->pdu = NULL; + } + } else { + ret = -1; + } + BIO_clear_retry_flags(a); + if (ret < 0) + BIO_set_retry_read(a); + } + return ret; +} + +static int coap_dgram_write(BIO *a, const char *in, int inl) { + int ret = 0; + coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a); + + if (data->session) { +#if COAP_SERVER_SUPPORT + if (data->session->sock.flags == COAP_SOCKET_EMPTY && data->session->endpoint == NULL) { + /* socket was closed on client due to error */ + BIO_clear_retry_flags(a); + return -1; + } +#endif /* COAP_SERVER_SUPPORT */ + ret = (int)coap_session_send(data->session, (const uint8_t *)in, (size_t)inl); + BIO_clear_retry_flags(a); + if (ret <= 0) + BIO_set_retry_write(a); + } else { + BIO_clear_retry_flags(a); + ret = -1; + } + return ret; +} + +static int coap_dgram_puts(BIO *a, const char *pstr) { + return coap_dgram_write(a, pstr, (int)strlen(pstr)); +} + +static long coap_dgram_ctrl(BIO *a, int cmd, long num, void *ptr) { + long ret = 1; + coap_ssl_data *data = BIO_get_data(a); + + (void)ptr; + + switch (cmd) { + case BIO_CTRL_GET_CLOSE: + ret = BIO_get_shutdown(a); + break; + case BIO_CTRL_SET_CLOSE: + BIO_set_shutdown(a, (int)num); + ret = 1; + break; + case BIO_CTRL_DGRAM_SET_PEEK_MODE: + data->peekmode = (unsigned)num; + break; + case BIO_CTRL_DGRAM_CONNECT: + case BIO_C_SET_FD: + case BIO_C_GET_FD: + case BIO_CTRL_DGRAM_SET_DONT_FRAG: + case BIO_CTRL_DGRAM_GET_MTU: + case BIO_CTRL_DGRAM_SET_MTU: + case BIO_CTRL_DGRAM_QUERY_MTU: + case BIO_CTRL_DGRAM_GET_FALLBACK_MTU: + ret = -1; + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + case BIO_CTRL_DGRAM_MTU_DISCOVER: + case BIO_CTRL_DGRAM_SET_CONNECTED: + ret = 1; + break; + case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: + data->timeout = coap_ticks_from_rt_us((uint64_t)((struct timeval*)ptr)->tv_sec * 1000000 + ((struct timeval*)ptr)->tv_usec); + ret = 1; + break; + case BIO_CTRL_RESET: + case BIO_C_FILE_SEEK: + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + case BIO_CTRL_DGRAM_GET_PEER: + case BIO_CTRL_DGRAM_SET_PEER: + case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: + case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: + case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT: + case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: + case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP: + case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP: + case BIO_CTRL_DGRAM_MTU_EXCEEDED: + case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD: + default: + ret = 0; + break; + } + return ret; +} + +static int +coap_dtls_generate_cookie(SSL *ssl, + unsigned char *cookie, + unsigned int *cookie_len) { + coap_dtls_context_t *dtls = + (coap_dtls_context_t *)SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl)); + coap_ssl_data *data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl)); + int r = HMAC_Init_ex(dtls->cookie_hmac, NULL, 0, NULL, NULL); + r &= HMAC_Update(dtls->cookie_hmac, + (const uint8_t*)&data->session->addr_info.local.addr, + (size_t)data->session->addr_info.local.size); + r &= HMAC_Update(dtls->cookie_hmac, + (const uint8_t*)&data->session->addr_info.remote.addr, + (size_t)data->session->addr_info.remote.size); + r &= HMAC_Final(dtls->cookie_hmac, cookie, cookie_len); + return r; +} + +static int +coap_dtls_verify_cookie(SSL *ssl, + const uint8_t *cookie, + unsigned int cookie_len) { + uint8_t hmac[32]; + unsigned len = 32; + if (coap_dtls_generate_cookie(ssl, hmac, &len) && + cookie_len == len && memcmp(cookie, hmac, len) == 0) + return 1; + else + return 0; +} + +#if COAP_CLIENT_SUPPORT +static unsigned int +coap_dtls_psk_client_callback(SSL *ssl, + const char *hint, + char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len) { + coap_session_t *c_session; + coap_openssl_context_t *o_context; + coap_dtls_cpsk_t *setup_data; + coap_bin_const_t temp; + const coap_dtls_cpsk_info_t *cpsk_info; + const coap_bin_const_t *psk_key; + const coap_bin_const_t *psk_identity; + + c_session = (coap_session_t*)SSL_get_app_data(ssl); + if (c_session == NULL) + return 0; + o_context = (coap_openssl_context_t *)c_session->context->dtls_context; + if (o_context == NULL) + return 0; + setup_data = &c_session->cpsk_setup_data; + + temp.s = hint ? (const uint8_t*)hint : (const uint8_t*)""; + temp.length = strlen((const char*)temp.s); + coap_session_refresh_psk_hint(c_session, &temp); + + coap_log(LOG_DEBUG, "got psk_identity_hint: '%.*s'\n", (int)temp.length, + (const char *)temp.s); + + if (setup_data->validate_ih_call_back) { + coap_str_const_t lhint; + + lhint.s = temp.s; + lhint.length = temp.length; + cpsk_info = + setup_data->validate_ih_call_back(&lhint, + c_session, + setup_data->ih_call_back_arg); + + if (cpsk_info == NULL) + return 0; + + coap_session_refresh_psk_identity(c_session, &cpsk_info->identity); + coap_session_refresh_psk_key(c_session, &cpsk_info->key); + psk_identity = &cpsk_info->identity; + psk_key = &cpsk_info->key; + } + else { + psk_identity = coap_get_session_client_psk_identity(c_session); + psk_key = coap_get_session_client_psk_key(c_session); + } + + if (psk_identity == NULL || psk_key == NULL) { + coap_log(LOG_WARNING, "no PSK available\n"); + return 0; + } + + /* identity has to be NULL terminated */ + if (!max_identity_len) + return 0; + max_identity_len--; + if (psk_identity->length > max_identity_len) { + coap_log(LOG_WARNING, + "psk_identity too large, truncated to %d bytes\n", + max_identity_len); + } + else { + /* Reduce to match */ + max_identity_len = (unsigned int)psk_identity->length; + } + memcpy(identity, psk_identity->s, max_identity_len); + identity[max_identity_len] = '\000'; + + if (psk_key->length > max_psk_len) { + coap_log(LOG_WARNING, + "psk_key too large, truncated to %d bytes\n", + max_psk_len); + } + else { + /* Reduce to match */ + max_psk_len = (unsigned int)psk_key->length; + } + memcpy(psk, psk_key->s, max_psk_len); + return max_psk_len; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +static unsigned int +coap_dtls_psk_server_callback( + SSL *ssl, + const char *identity, + unsigned char *psk, + unsigned int max_psk_len +) { + coap_session_t *c_session; + coap_dtls_spsk_t *setup_data; + coap_bin_const_t lidentity; + const coap_bin_const_t *psk_key; + + c_session = (coap_session_t*)SSL_get_app_data(ssl); + if (c_session == NULL) + return 0; + + setup_data = &c_session->context->spsk_setup_data; + + /* Track the Identity being used */ + lidentity.s = identity ? (const uint8_t*)identity : (const uint8_t*)""; + lidentity.length = strlen((const char*)lidentity.s); + coap_session_refresh_psk_identity(c_session, &lidentity); + + coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n", + (int)lidentity.length, (const char *)lidentity.s); + + if (setup_data->validate_id_call_back) { + psk_key = setup_data->validate_id_call_back(&lidentity, + c_session, + setup_data->id_call_back_arg); + + coap_session_refresh_psk_key(c_session, psk_key); + } + else { + psk_key = coap_get_session_server_psk_key(c_session); + } + + if (psk_key == NULL) + return 0; + + if (psk_key->length > max_psk_len) { + coap_log(LOG_WARNING, + "psk_key too large, truncated to %d bytes\n", + max_psk_len); + } + else { + /* Reduce to match */ + max_psk_len = (unsigned int)psk_key->length; + } + memcpy(psk, psk_key->s, max_psk_len); + return max_psk_len; +} +#endif /* COAP_SERVER_SUPPORT */ + +static void coap_dtls_info_callback(const SSL *ssl, int where, int ret) { + coap_session_t *session = (coap_session_t*)SSL_get_app_data(ssl); + const char *pstr; + int w = where &~SSL_ST_MASK; + + if (w & SSL_ST_CONNECT) + pstr = "SSL_connect"; + else if (w & SSL_ST_ACCEPT) + pstr = "SSL_accept"; + else + pstr = "undefined"; + + if (where & SSL_CB_LOOP) { + if (dtls_log_level >= LOG_DEBUG) + coap_log(LOG_DEBUG, "* %s: %s:%s\n", + coap_session_str(session), pstr, SSL_state_string_long(ssl)); + } else if (where & SSL_CB_ALERT) { + int log_level = LOG_INFO; + pstr = (where & SSL_CB_READ) ? "read" : "write"; + if ((where & (SSL_CB_WRITE|SSL_CB_READ)) && (ret >> 8) == SSL3_AL_FATAL) { + session->dtls_event = COAP_EVENT_DTLS_ERROR; + if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY) + log_level = LOG_WARNING; + } + if (dtls_log_level >= log_level) + coap_log(log_level, "* %s: SSL3 alert %s:%s:%s\n", + coap_session_str(session), + pstr, + SSL_alert_type_string_long(ret), + SSL_alert_desc_string_long(ret)); + } else if (where & SSL_CB_EXIT) { + if (ret == 0) { + if (dtls_log_level >= LOG_WARNING) { + unsigned long e; + coap_log(LOG_WARNING, "* %s: %s:failed in %s\n", + coap_session_str(session), pstr, SSL_state_string_long(ssl)); + while ((e = ERR_get_error())) + coap_log(LOG_WARNING, "* %s: %s at %s:%s\n", + coap_session_str(session), ERR_reason_error_string(e), + ERR_lib_error_string(e), ERR_func_error_string(e)); + } + } else if (ret < 0) { + if (dtls_log_level >= LOG_WARNING) { + int err = SSL_get_error(ssl, ret); + if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE && err != SSL_ERROR_WANT_CONNECT && err != SSL_ERROR_WANT_ACCEPT && err != SSL_ERROR_WANT_X509_LOOKUP) { + long e; + coap_log(LOG_WARNING, "* %s: %s:error in %s\n", + coap_session_str(session), pstr, SSL_state_string_long(ssl)); + while ((e = ERR_get_error())) + coap_log(LOG_WARNING, "* %s: %s at %s:%s\n", + coap_session_str(session), ERR_reason_error_string(e), + ERR_lib_error_string(e), ERR_func_error_string(e)); + } + } + } + } + + if (where == SSL_CB_HANDSHAKE_START && SSL_get_state(ssl) == TLS_ST_OK) + session->dtls_event = COAP_EVENT_DTLS_RENEGOTIATE; +} + +#if !COAP_DISABLE_TCP +static int coap_sock_create(BIO *a) { + BIO_set_init(a, 1); + return 1; +} + +static int coap_sock_destroy(BIO *a) { + (void)a; + return 1; +} + +static int coap_sock_read(BIO *a, char *out, int outl) { + int ret = 0; + coap_session_t *session = (coap_session_t *)BIO_get_data(a); + + if (out != NULL) { + ret = (int)coap_socket_read(&session->sock, (uint8_t*)out, (size_t)outl); + if (ret == 0) { + BIO_set_retry_read(a); + ret = -1; + } else { + BIO_clear_retry_flags(a); + } + } + return ret; +} + +static int coap_sock_write(BIO *a, const char *in, int inl) { + int ret = 0; + coap_session_t *session = (coap_session_t *)BIO_get_data(a); + + ret = (int)coap_socket_write(&session->sock, (const uint8_t*)in, (size_t)inl); + BIO_clear_retry_flags(a); + if (ret == 0) { + BIO_set_retry_read(a); + ret = -1; + } else { + BIO_clear_retry_flags(a); + if (ret == -1) { + if ((session->state == COAP_SESSION_STATE_CSM || + session->state == COAP_SESSION_STATE_HANDSHAKE) && + (errno == EPIPE || errno == ECONNRESET)) { + /* + * Need to handle a TCP timing window where an agent continues with + * the sending of the next handshake or a CSM. + * However, the peer does not like a certificate and so sends a + * fatal alert and closes the TCP session. + * The sending of the next handshake or CSM may get terminated because + * of the closed TCP session, but there is still an outstanding alert + * to be read in and reported on. + * In this case, pretend that sending the info was fine so that the + * alert can be read (which effectively is what happens with DTLS). + */ + ret = inl; + } + else { + coap_log(LOG_DEBUG, "* %s: failed to send %d bytes (%s) state %d\n", + coap_session_str(session), inl, coap_socket_strerror(), + session->state); + } + } + } + return ret; +} + +static int coap_sock_puts(BIO *a, const char *pstr) { + return coap_sock_write(a, pstr, (int)strlen(pstr)); +} + +static long coap_sock_ctrl(BIO *a, int cmd, long num, void *ptr) { + int r = 1; + (void)a; + (void)ptr; + (void)num; + + switch (cmd) { + case BIO_C_SET_FD: + case BIO_C_GET_FD: + r = -1; + break; + case BIO_CTRL_SET_CLOSE: + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + r = 1; + break; + default: + case BIO_CTRL_GET_CLOSE: + r = 0; + break; + } + return r; +} +#endif /* !COAP_DISABLE_TCP */ + +static void coap_set_user_prefs(SSL_CTX *ctx) { + SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS); + +#ifdef COAP_OPENSSL_SIGALGS + SSL_CTX_set1_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS); + SSL_CTX_set1_client_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS); +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10101000L && defined(COAP_OPENSSL_GROUPS) + SSL_CTX_set1_groups_list(ctx, COAP_OPENSSL_GROUPS); +#endif +} + +void *coap_dtls_new_context(coap_context_t *coap_context) { + coap_openssl_context_t *context; + (void)coap_context; + + context = (coap_openssl_context_t *)coap_malloc(sizeof(coap_openssl_context_t)); + if (context) { + uint8_t cookie_secret[32]; + + memset(context, 0, sizeof(coap_openssl_context_t)); + + /* Set up DTLS context */ + context->dtls.ctx = SSL_CTX_new(DTLS_method()); + if (!context->dtls.ctx) + goto error; + SSL_CTX_set_min_proto_version(context->dtls.ctx, DTLS1_2_VERSION); + SSL_CTX_set_app_data(context->dtls.ctx, &context->dtls); + SSL_CTX_set_read_ahead(context->dtls.ctx, 1); + coap_set_user_prefs(context->dtls.ctx); + memset(cookie_secret, 0, sizeof(cookie_secret)); + if (!RAND_bytes(cookie_secret, (int)sizeof(cookie_secret))) { + if (dtls_log_level >= LOG_WARNING) + coap_log(LOG_WARNING, + "Insufficient entropy for random cookie generation"); + coap_prng(cookie_secret, sizeof(cookie_secret)); + } + context->dtls.cookie_hmac = HMAC_CTX_new(); + if (!HMAC_Init_ex(context->dtls.cookie_hmac, cookie_secret, (int)sizeof(cookie_secret), EVP_sha256(), NULL)) + goto error; + SSL_CTX_set_cookie_generate_cb(context->dtls.ctx, coap_dtls_generate_cookie); + SSL_CTX_set_cookie_verify_cb(context->dtls.ctx, coap_dtls_verify_cookie); + SSL_CTX_set_info_callback(context->dtls.ctx, coap_dtls_info_callback); + SSL_CTX_set_options(context->dtls.ctx, SSL_OP_NO_QUERY_MTU); + context->dtls.meth = BIO_meth_new(BIO_TYPE_DGRAM, "coapdgram"); + if (!context->dtls.meth) + goto error; + context->dtls.bio_addr = BIO_ADDR_new(); + if (!context->dtls.bio_addr) + goto error; + BIO_meth_set_write(context->dtls.meth, coap_dgram_write); + BIO_meth_set_read(context->dtls.meth, coap_dgram_read); + BIO_meth_set_puts(context->dtls.meth, coap_dgram_puts); + BIO_meth_set_ctrl(context->dtls.meth, coap_dgram_ctrl); + BIO_meth_set_create(context->dtls.meth, coap_dgram_create); + BIO_meth_set_destroy(context->dtls.meth, coap_dgram_destroy); + +#if !COAP_DISABLE_TCP + /* Set up TLS context */ + context->tls.ctx = SSL_CTX_new(TLS_method()); + if (!context->tls.ctx) + goto error; + SSL_CTX_set_app_data(context->tls.ctx, &context->tls); + SSL_CTX_set_min_proto_version(context->tls.ctx, TLS1_VERSION); + coap_set_user_prefs(context->tls.ctx); + SSL_CTX_set_info_callback(context->tls.ctx, coap_dtls_info_callback); + context->tls.meth = BIO_meth_new(BIO_TYPE_SOCKET, "coapsock"); + if (!context->tls.meth) + goto error; + BIO_meth_set_write(context->tls.meth, coap_sock_write); + BIO_meth_set_read(context->tls.meth, coap_sock_read); + BIO_meth_set_puts(context->tls.meth, coap_sock_puts); + BIO_meth_set_ctrl(context->tls.meth, coap_sock_ctrl); + BIO_meth_set_create(context->tls.meth, coap_sock_create); + BIO_meth_set_destroy(context->tls.meth, coap_sock_destroy); +#endif /* !COAP_DISABLE_TCP */ + } + + return context; + +error: + coap_dtls_free_context(context); + return NULL; +} + +#if COAP_SERVER_SUPPORT +int +coap_dtls_context_set_spsk(coap_context_t *c_context, + coap_dtls_spsk_t *setup_data +) { + coap_openssl_context_t *o_context = + ((coap_openssl_context_t *)c_context->dtls_context); + BIO *bio; + + if (!setup_data || !o_context) + return 0; + + SSL_CTX_set_psk_server_callback(o_context->dtls.ctx, + coap_dtls_psk_server_callback); +#if !COAP_DISABLE_TCP + SSL_CTX_set_psk_server_callback(o_context->tls.ctx, + coap_dtls_psk_server_callback); +#endif /* !COAP_DISABLE_TCP */ + if (setup_data->psk_info.hint.s) { + char hint[COAP_DTLS_HINT_LENGTH]; + snprintf(hint, sizeof(hint), "%.*s", (int)setup_data->psk_info.hint.length, + setup_data->psk_info.hint.s); + SSL_CTX_use_psk_identity_hint(o_context->dtls.ctx, hint); +#if !COAP_DISABLE_TCP + SSL_CTX_use_psk_identity_hint(o_context->tls.ctx, hint); +#endif /* !COAP_DISABLE_TCP */ + } + if (setup_data->validate_sni_call_back) { +#if OPENSSL_VERSION_NUMBER < 0x10101000L + SSL_CTX_set_tlsext_servername_arg(o_context->dtls.ctx, + &c_context->spsk_setup_data); + SSL_CTX_set_tlsext_servername_callback(o_context->dtls.ctx, + psk_tls_server_name_call_back); +#if !COAP_DISABLE_TCP + SSL_CTX_set_tlsext_servername_arg(o_context->tls.ctx, + &c_context->spsk_setup_data); + SSL_CTX_set_tlsext_servername_callback(o_context->tls.ctx, + psk_tls_server_name_call_back); +#endif /* !COAP_DISABLE_TCP */ +#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + SSL_CTX_set_client_hello_cb(o_context->dtls.ctx, + psk_tls_client_hello_call_back, + NULL); +#if !COAP_DISABLE_TCP + SSL_CTX_set_client_hello_cb(o_context->tls.ctx, + psk_tls_client_hello_call_back, + NULL); +#endif /* !COAP_DISABLE_TCP */ +#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + } + + if (!o_context->dtls.ssl) { + /* This is set up to handle new incoming sessions to a server */ + o_context->dtls.ssl = SSL_new(o_context->dtls.ctx); + if (!o_context->dtls.ssl) + return 0; + bio = BIO_new(o_context->dtls.meth); + if (!bio) { + SSL_free (o_context->dtls.ssl); + o_context->dtls.ssl = NULL; + return 0; + } + SSL_set_bio(o_context->dtls.ssl, bio, bio); + SSL_set_app_data(o_context->dtls.ssl, NULL); + SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE); + SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU); + } + o_context->psk_pki_enabled |= IS_PSK; + return 1; +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +int +coap_dtls_context_set_cpsk(coap_context_t *c_context, + coap_dtls_cpsk_t *setup_data +) { + coap_openssl_context_t *o_context = + ((coap_openssl_context_t *)c_context->dtls_context); + BIO *bio; + + if (!setup_data || !o_context) + return 0; + + if (!o_context->dtls.ssl) { + /* This is set up to handle new incoming sessions to a server */ + o_context->dtls.ssl = SSL_new(o_context->dtls.ctx); + if (!o_context->dtls.ssl) + return 0; + bio = BIO_new(o_context->dtls.meth); + if (!bio) { + SSL_free (o_context->dtls.ssl); + o_context->dtls.ssl = NULL; + return 0; + } + SSL_set_bio(o_context->dtls.ssl, bio, bio); + SSL_set_app_data(o_context->dtls.ssl, NULL); + SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE); + SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU); + } + o_context->psk_pki_enabled |= IS_PSK; + return 1; +} +#endif /* COAP_CLIENT_SUPPORT */ + +static int +map_key_type(int asn1_private_key_type +) { + switch (asn1_private_key_type) { + case COAP_ASN1_PKEY_NONE: return EVP_PKEY_NONE; + case COAP_ASN1_PKEY_RSA: return EVP_PKEY_RSA; + case COAP_ASN1_PKEY_RSA2: return EVP_PKEY_RSA2; + case COAP_ASN1_PKEY_DSA: return EVP_PKEY_DSA; + case COAP_ASN1_PKEY_DSA1: return EVP_PKEY_DSA1; + case COAP_ASN1_PKEY_DSA2: return EVP_PKEY_DSA2; + case COAP_ASN1_PKEY_DSA3: return EVP_PKEY_DSA3; + case COAP_ASN1_PKEY_DSA4: return EVP_PKEY_DSA4; + case COAP_ASN1_PKEY_DH: return EVP_PKEY_DH; + case COAP_ASN1_PKEY_DHX: return EVP_PKEY_DHX; + case COAP_ASN1_PKEY_EC: return EVP_PKEY_EC; + case COAP_ASN1_PKEY_HMAC: return EVP_PKEY_HMAC; + case COAP_ASN1_PKEY_CMAC: return EVP_PKEY_CMAC; + case COAP_ASN1_PKEY_TLS1_PRF: return EVP_PKEY_TLS1_PRF; + case COAP_ASN1_PKEY_HKDF: return EVP_PKEY_HKDF; + default: + coap_log(LOG_WARNING, + "*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n", + asn1_private_key_type); + break; + } + return 0; +} +#if !COAP_DISABLE_TCP +static uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' }; + +#if COAP_SERVER_SUPPORT +static int +server_alpn_callback (SSL *ssl COAP_UNUSED, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg COAP_UNUSED +) { + unsigned char *tout = NULL; + int ret; + if (inlen == 0) + return SSL_TLSEXT_ERR_NOACK; + ret = SSL_select_next_proto(&tout, + outlen, + coap_alpn, + sizeof(coap_alpn), + in, + inlen); + *out = tout; + return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK; +} +#endif /* COAP_SERVER_SUPPORT */ +#endif /* !COAP_DISABLE_TCP */ + +static void +add_ca_to_cert_store(X509_STORE *st, X509 *x509) +{ + long e; + + /* Flush out existing errors */ + while ((e = ERR_get_error()) != 0) { + } + + if (!X509_STORE_add_cert(st, x509)) { + while ((e = ERR_get_error()) != 0) { + int r = ERR_GET_REASON(e); + if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) { + /* Not already added */ + coap_log(LOG_WARNING, "***setup_pki: (D)TLS: %s at %s:%s\n", + ERR_reason_error_string(e), + ERR_lib_error_string(e), + ERR_func_error_string(e)); + } + } + } +} + +static X509 * +missing_ENGINE_load_cert (const char *cert_id) +{ + struct { + const char *cert_id; + X509 *cert; + } params; + + params.cert_id = cert_id; + params.cert = NULL; + + /* There is no ENGINE_load_cert() */ + if (!ENGINE_ctrl_cmd(ssl_engine, "LOAD_CERT_CTRL", 0, ¶ms, NULL, 1)) { + params.cert = NULL; + } + return params.cert; +} + +#if OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT +static int +setup_pki_server(SSL_CTX *ctx, + const coap_dtls_pki_t* setup_data +) { + switch (setup_data->pki_key.key_type) { + case COAP_PKI_KEY_PEM: + if (setup_data->pki_key.key.pem.public_cert && + setup_data->pki_key.key.pem.public_cert[0]) { + if (!(SSL_CTX_use_certificate_file(ctx, + setup_data->pki_key.key.pem.public_cert, + SSL_FILETYPE_PEM))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "Server Certificate\n", + setup_data->pki_key.key.pem.public_cert); + return 0; + } + } + else { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Certificate defined\n"); + return 0; + } + + if (setup_data->pki_key.key.pem.private_key && + setup_data->pki_key.key.pem.private_key[0]) { + if (!(SSL_CTX_use_PrivateKey_file(ctx, + setup_data->pki_key.key.pem.private_key, + SSL_FILETYPE_PEM))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "Server Private Key\n", + setup_data->pki_key.key.pem.private_key); + return 0; + } + } + else { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Private Key defined\n"); + return 0; + } + + if (setup_data->check_common_ca && setup_data->pki_key.key.pem.ca_file && + setup_data->pki_key.key.pem.ca_file[0]) { + STACK_OF(X509_NAME) *cert_names; + X509_STORE *st; + BIO *in; + X509 *x = NULL; + char *rw_var = NULL; + cert_names = SSL_load_client_CA_file(setup_data->pki_key.key.pem.ca_file); + if (cert_names != NULL) + SSL_CTX_set_client_CA_list(ctx, cert_names); + else { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "client CA File\n", + setup_data->pki_key.key.pem.ca_file); + return 0; + } + + /* Add CA to the trusted root CA store */ + st = SSL_CTX_get_cert_store(ctx); + in = BIO_new(BIO_s_file()); + /* Need to do this to not get a compiler warning about const parameters */ + memcpy(&rw_var, &setup_data->pki_key.key.pem.ca_file, sizeof (rw_var)); + if (!BIO_read_filename(in, rw_var)) { + BIO_free(in); + X509_free(x); + break; + } + + for (;;) { + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) + break; + add_ca_to_cert_store(st, x); + } + BIO_free(in); + X509_free(x); + } + break; + + case COAP_PKI_KEY_PEM_BUF: + if (setup_data->pki_key.key.pem_buf.public_cert && + setup_data->pki_key.key.pem_buf.public_cert_len) { + BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.public_cert, + setup_data->pki_key.key.pem_buf.public_cert_len); + X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL; + + if (!cert || !SSL_CTX_use_certificate(ctx, cert)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: Unable to configure " + "Server PEM Certificate\n"); + if (bp) BIO_free(bp); + if (cert) X509_free(cert); + return 0; + } + if (bp) BIO_free(bp); + if (cert) X509_free(cert); + } + else { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Certificate defined\n"); + return 0; + } + + if (setup_data->pki_key.key.pem_buf.private_key && + setup_data->pki_key.key.pem_buf.private_key_len) { + BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.private_key, + setup_data->pki_key.key.pem_buf.private_key_len); + EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL; + + if (!pkey || !SSL_CTX_use_PrivateKey(ctx, pkey)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: Unable to configure " + "Server PEM Private Key\n"); + if (bp) BIO_free(bp); + if (pkey) EVP_PKEY_free(pkey); + return 0; + } + if (bp) BIO_free(bp); + if (pkey) EVP_PKEY_free(pkey); + } + else { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Private Key defined\n"); + return 0; + } + + if (setup_data->pki_key.key.pem_buf.ca_cert && + setup_data->pki_key.key.pem_buf.ca_cert_len) { + BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.ca_cert, + setup_data->pki_key.key.pem_buf.ca_cert_len); + X509_STORE *st; + X509 *x; + + st = SSL_CTX_get_cert_store(ctx); + if (bp) { + for (;;) { + if ((x = PEM_read_bio_X509(bp, NULL, NULL, NULL)) == NULL) + break; + add_ca_to_cert_store(st, x); + SSL_CTX_add_client_CA(ctx, x); + X509_free(x); + } + BIO_free(bp); + } + } + break; + + case COAP_PKI_KEY_ASN1: + if (setup_data->pki_key.key.asn1.public_cert && + setup_data->pki_key.key.asn1.public_cert_len > 0) { + if (!(SSL_CTX_use_certificate_ASN1(ctx, + setup_data->pki_key.key.asn1.public_cert_len, + setup_data->pki_key.key.asn1.public_cert))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "Server Certificate\n", + "ASN1"); + return 0; + } + } + else { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Certificate defined\n"); + return 0; + } + + if (setup_data->pki_key.key.asn1.private_key && + setup_data->pki_key.key.asn1.private_key_len > 0) { + int pkey_type = map_key_type(setup_data->pki_key.key.asn1.private_key_type); + if (!(SSL_CTX_use_PrivateKey_ASN1(pkey_type, ctx, + setup_data->pki_key.key.asn1.private_key, + setup_data->pki_key.key.asn1.private_key_len))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "Server Private Key\n", + "ASN1"); + return 0; + } + } + else { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Private Key defined\n"); + return 0; + } + + if (setup_data->pki_key.key.asn1.ca_cert && + setup_data->pki_key.key.asn1.ca_cert_len > 0) { + /* Need to use a temp variable as it gets incremented*/ + const uint8_t *p = setup_data->pki_key.key.asn1.ca_cert; + X509* x509 = d2i_X509(NULL, &p, setup_data->pki_key.key.asn1.ca_cert_len); + X509_STORE *st; + if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "client CA File\n", + "ASN1"); + if (x509) X509_free(x509); + return 0; + } + st = SSL_CTX_get_cert_store(ctx); + add_ca_to_cert_store(st, x509); + X509_free(x509); + } + break; + + case COAP_PKI_KEY_PKCS11: + if (!ssl_engine) { + ssl_engine = ENGINE_by_id("pkcs11"); + if (!ssl_engine) { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No PKCS11 support\nn"); + return 0; + } + if (!ENGINE_init(ssl_engine)) { + /* the engine couldn't initialise, release 'ssl_engine' */ + ENGINE_free(ssl_engine); + ssl_engine = NULL; + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n"); + return 0; + } + } + + if (setup_data->pki_key.key.pkcs11.user_pin) { + /* If not set, pin may be held in pkcs11: URI */ + if (ENGINE_ctrl_cmd_string(ssl_engine, "PIN", + setup_data->pki_key.key.pkcs11.user_pin, 0) == 0) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n", + setup_data->pki_key.key.pkcs11.user_pin); + return 0; + } + } + + if (setup_data->pki_key.key.pkcs11.private_key && + setup_data->pki_key.key.pkcs11.private_key[0]) { + if (strncasecmp (setup_data->pki_key.key.pkcs11.private_key, + "pkcs11:", 7) == 0) { + EVP_PKEY* pkey = ENGINE_load_private_key(ssl_engine, + setup_data->pki_key.key.pkcs11.private_key, + NULL, NULL); + + if (!pkey) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to load " + "Server Private Key\n", + setup_data->pki_key.key.pkcs11.private_key); + return 0; + } + if (!SSL_CTX_use_PrivateKey(ctx, pkey)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "Server Private Key\n", + setup_data->pki_key.key.pkcs11.private_key); + EVP_PKEY_free(pkey); + return 0; + } + EVP_PKEY_free(pkey); + } + else { + if (!(SSL_CTX_use_PrivateKey_file(ctx, + setup_data->pki_key.key.pkcs11.private_key, + SSL_FILETYPE_ASN1))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "Server Private Key\n", + setup_data->pki_key.key.pkcs11.private_key); + return 0; + } + } + } + else { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Private Key defined\n"); + return 0; + } + + if (setup_data->pki_key.key.pkcs11.public_cert && + setup_data->pki_key.key.pkcs11.public_cert[0]) { + if (strncasecmp (setup_data->pki_key.key.pkcs11.public_cert, + "pkcs11:", 7) == 0) { + X509 *x509; + + x509 = missing_ENGINE_load_cert( + setup_data->pki_key.key.pkcs11.public_cert); + if (!x509) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to load " + "Server Certificate\n", + setup_data->pki_key.key.pkcs11.public_cert); + return 0; + } + if (!SSL_CTX_use_certificate(ctx, x509)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "Server Certificate\n", + setup_data->pki_key.key.pkcs11.public_cert); + X509_free (x509); + return 0; + } + X509_free (x509); + } + else { + if (!(SSL_CTX_use_certificate_file(ctx, + setup_data->pki_key.key.pkcs11.public_cert, + SSL_FILETYPE_ASN1))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "Server Certificate\n", + setup_data->pki_key.key.pkcs11.public_cert); + return 0; + } + } + } + else { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Certificate defined\n"); + return 0; + } + + if (setup_data->pki_key.key.pkcs11.ca && + setup_data->pki_key.key.pkcs11.ca[0]) { + X509_STORE *st; + + if (strncasecmp (setup_data->pki_key.key.pkcs11.ca, "pkcs11:", 7) == 0) { + X509 *x509; + + x509 = missing_ENGINE_load_cert ( + setup_data->pki_key.key.pkcs11.ca); + if (!x509) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to load " + "Server CA Certificate\n", + setup_data->pki_key.key.pkcs11.ca); + return 0; + } + if (!SSL_CTX_add_client_CA(ctx, x509)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "Server CA File\n", + setup_data->pki_key.key.pkcs11.ca); + X509_free(x509); + return 0; + } + st = SSL_CTX_get_cert_store(ctx); + add_ca_to_cert_store(st, x509); + X509_free(x509); + } + else { + FILE *fp = fopen(setup_data->pki_key.key.pkcs11.ca, "r"); + X509 *x509 = fp ? d2i_X509_fp(fp, NULL) : NULL; + + if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "client CA File\n", + setup_data->pki_key.key.pkcs11.ca); + if (x509) X509_free(x509); + return 0; + } + st = SSL_CTX_get_cert_store(ctx); + add_ca_to_cert_store(st, x509); + X509_free(x509); + } + } + break; + + default: + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: Unknown key type %d\n", + setup_data->pki_key.key_type); + return 0; + } + + return 1; +} +#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */ + +#if OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT +static int +setup_pki_ssl(SSL *ssl, + coap_dtls_pki_t* setup_data, coap_dtls_role_t role +) { + if (setup_data->is_rpk_not_cert) { + coap_log(LOG_ERR, + "RPK Support not available in OpenSSL\n"); + return 0; + } + switch (setup_data->pki_key.key_type) { + case COAP_PKI_KEY_PEM: + if (setup_data->pki_key.key.pem.public_cert && + setup_data->pki_key.key.pem.public_cert[0]) { + if (!(SSL_use_certificate_file(ssl, + setup_data->pki_key.key.pem.public_cert, + SSL_FILETYPE_PEM))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "%s Certificate\n", + setup_data->pki_key.key.pem.public_cert, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + } + else if (role == COAP_DTLS_ROLE_SERVER || + (setup_data->pki_key.key.pem.private_key && + setup_data->pki_key.key.pem.private_key[0])) { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No %s Certificate defined\n", + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + if (setup_data->pki_key.key.pem.private_key && + setup_data->pki_key.key.pem.private_key[0]) { + if (!(SSL_use_PrivateKey_file(ssl, + setup_data->pki_key.key.pem.private_key, + SSL_FILETYPE_PEM))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "Client Private Key\n", + setup_data->pki_key.key.pem.private_key); + return 0; + } + } + else if (role == COAP_DTLS_ROLE_SERVER || + (setup_data->pki_key.key.pem.public_cert && + setup_data->pki_key.key.pem.public_cert[0])) { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No %s Private Key defined\n", + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + if (setup_data->check_common_ca && setup_data->pki_key.key.pem.ca_file && + setup_data->pki_key.key.pem.ca_file[0]) { + X509_STORE *st; + BIO *in; + X509 *x = NULL; + char *rw_var = NULL; + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + + if (role == COAP_DTLS_ROLE_SERVER) { + STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(setup_data->pki_key.key.pem.ca_file); + + if (cert_names != NULL) + SSL_set_client_CA_list(ssl, cert_names); + else { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "%s CA File\n", + setup_data->pki_key.key.pem.ca_file, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + } + + /* Add CA to the trusted root CA store */ + in = BIO_new(BIO_s_file()); + /* Need to do this to not get a compiler warning about const parameters */ + memcpy(&rw_var, &setup_data->pki_key.key.pem.ca_file, sizeof (rw_var)); + if (!BIO_read_filename(in, rw_var)) { + BIO_free(in); + X509_free(x); + break; + } + st = SSL_CTX_get_cert_store(ctx); + for (;;) { + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) + break; + add_ca_to_cert_store(st, x); + } + BIO_free(in); + X509_free(x); + } + break; + + case COAP_PKI_KEY_PEM_BUF: + if (setup_data->pki_key.key.pem_buf.public_cert && + setup_data->pki_key.key.pem_buf.public_cert_len) { + BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.public_cert, + (int)setup_data->pki_key.key.pem_buf.public_cert_len); + X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL; + + if (!cert || !SSL_use_certificate(ssl, cert)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: Unable to configure " + "Server PEM Certificate\n"); + if (bp) BIO_free(bp); + if (cert) X509_free(cert); + return 0; + } + if (bp) BIO_free(bp); + if (cert) X509_free(cert); + } + else { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Certificate defined\n"); + return 0; + } + + if (setup_data->pki_key.key.pem_buf.private_key && + setup_data->pki_key.key.pem_buf.private_key_len) { + BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.private_key, + (int)setup_data->pki_key.key.pem_buf.private_key_len); + EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL; + + if (!pkey || !SSL_use_PrivateKey(ssl, pkey)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: Unable to configure " + "Server PEM Private Key\n"); + if (bp) BIO_free(bp); + if (pkey) EVP_PKEY_free(pkey); + return 0; + } + if (bp) BIO_free(bp); + if (pkey) EVP_PKEY_free(pkey); + } + else { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Private Key defined\n"); + return 0; + } + + if (setup_data->pki_key.key.pem_buf.ca_cert && + setup_data->pki_key.key.pem_buf.ca_cert_len) { + BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.ca_cert, + (int)setup_data->pki_key.key.pem_buf.ca_cert_len); + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + X509 *x; + X509_STORE *st = SSL_CTX_get_cert_store(ctx); + + if (bp) { + for (;;) { + if ((x = PEM_read_bio_X509(bp, NULL, 0, NULL)) == NULL) + break; + add_ca_to_cert_store(st, x); + SSL_add_client_CA(ssl, x); + X509_free(x); + } + BIO_free(bp); + } + } + break; + + case COAP_PKI_KEY_ASN1: + if (setup_data->pki_key.key.asn1.public_cert && + setup_data->pki_key.key.asn1.public_cert_len > 0) { + if (!(SSL_use_certificate_ASN1(ssl, + setup_data->pki_key.key.asn1.public_cert, + (int)setup_data->pki_key.key.asn1.public_cert_len))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "%s Certificate\n", + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client", + "ASN1"); + return 0; + } + } + else if (role == COAP_DTLS_ROLE_SERVER || + (setup_data->pki_key.key.asn1.private_key && + setup_data->pki_key.key.asn1.private_key[0])) { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No %s Certificate defined\n", + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + if (setup_data->pki_key.key.asn1.private_key && + setup_data->pki_key.key.asn1.private_key_len > 0) { + int pkey_type = map_key_type(setup_data->pki_key.key.asn1.private_key_type); + if (!(SSL_use_PrivateKey_ASN1(pkey_type, ssl, + setup_data->pki_key.key.asn1.private_key, + (long)setup_data->pki_key.key.asn1.private_key_len))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "%s Private Key\n", + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client", + "ASN1"); + return 0; + } + } + else if (role == COAP_DTLS_ROLE_SERVER || + (setup_data->pki_key.key.asn1.public_cert && + setup_data->pki_key.key.asn1.public_cert_len > 0)) { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No %s Private Key defined", + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + if (setup_data->pki_key.key.asn1.ca_cert && + setup_data->pki_key.key.asn1.ca_cert_len > 0) { + /* Need to use a temp variable as it gets incremented*/ + const uint8_t *p = setup_data->pki_key.key.asn1.ca_cert; + X509* x509 = d2i_X509(NULL, &p, (long)setup_data->pki_key.key.asn1.ca_cert_len); + X509_STORE *st; + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + + if (role == COAP_DTLS_ROLE_SERVER) { + if (!x509 || !SSL_add_client_CA(ssl, x509)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "client CA File\n", + "ASN1"); + X509_free(x509); + return 0; + } + } + + /* Add CA to the trusted root CA store */ + st = SSL_CTX_get_cert_store(ctx); + add_ca_to_cert_store(st, x509); + X509_free(x509); + } + break; + + case COAP_PKI_KEY_PKCS11: + if (!ssl_engine) { + ssl_engine = ENGINE_by_id("pkcs11"); + if (!ssl_engine) { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No PKCS11 support - need OpenSSL pkcs11 engine\n"); + return 0; + } + if (!ENGINE_init(ssl_engine)) { + /* the engine couldn't initialise, release 'ssl_engine' */ + ENGINE_free(ssl_engine); + ssl_engine = NULL; + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n"); + return 0; + } + } + + if (setup_data->pki_key.key.pkcs11.user_pin) { + /* If not set, pin may be held in pkcs11: URI */ + if (ENGINE_ctrl_cmd_string(ssl_engine, + "PIN", + setup_data->pki_key.key.pkcs11.user_pin, 0) == 0) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n", + setup_data->pki_key.key.pkcs11.user_pin); + return 0; + } + } + + if (setup_data->pki_key.key.pkcs11.private_key && + setup_data->pki_key.key.pkcs11.private_key[0]) { + if (strncasecmp (setup_data->pki_key.key.pkcs11.private_key, + "pkcs11:", 7) == 0) { + EVP_PKEY* pkey = ENGINE_load_private_key(ssl_engine, + setup_data->pki_key.key.pkcs11.private_key, + NULL, NULL); + + if (!pkey) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to load " + "%s Private Key\n", + setup_data->pki_key.key.pkcs11.private_key, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + if (!SSL_use_PrivateKey(ssl, pkey)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "%s Private Key\n", + setup_data->pki_key.key.pkcs11.private_key, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + EVP_PKEY_free(pkey); + return 0; + } + EVP_PKEY_free(pkey); + } + else { + if (!(SSL_use_PrivateKey_file(ssl, + setup_data->pki_key.key.pkcs11.private_key, + SSL_FILETYPE_ASN1))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "%s Private Key\n", + setup_data->pki_key.key.pkcs11.private_key, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + } + } + else if (role == COAP_DTLS_ROLE_SERVER) { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Private Key defined\n"); + return 0; + } + + if (setup_data->pki_key.key.pkcs11.public_cert && + setup_data->pki_key.key.pkcs11.public_cert[0]) { + if (strncasecmp (setup_data->pki_key.key.pkcs11.public_cert, + "pkcs11:", 7) == 0) { + X509 *x509; + + x509 = missing_ENGINE_load_cert( + setup_data->pki_key.key.pkcs11.public_cert); + if (!x509) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to load " + "%s Certificate\n", + setup_data->pki_key.key.pkcs11.public_cert, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + if (!SSL_use_certificate(ssl, x509)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "%s Certificate\n", + setup_data->pki_key.key.pkcs11.public_cert, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + X509_free (x509); + return 0; + } + X509_free (x509); + } + else { + if (!(SSL_use_certificate_file(ssl, + setup_data->pki_key.key.pkcs11.public_cert, + SSL_FILETYPE_ASN1))) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "%s Certificate\n", + setup_data->pki_key.key.pkcs11.public_cert, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + } + } + else if (role == COAP_DTLS_ROLE_SERVER) { + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: No Server Certificate defined\n"); + return 0; + } + + if (setup_data->pki_key.key.pkcs11.ca && + setup_data->pki_key.key.pkcs11.ca[0]) { + X509_STORE *st; + + if (strncasecmp (setup_data->pki_key.key.pkcs11.ca, "pkcs11:", 7) == 0) { + X509 *x509; + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + + x509 = missing_ENGINE_load_cert( + setup_data->pki_key.key.pkcs11.ca); + if (!x509) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to load " + "%s CA Certificate\n", + setup_data->pki_key.key.pkcs11.ca, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + return 0; + } + if (!SSL_add_client_CA(ssl, x509)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "%s CA Certificate\n", + setup_data->pki_key.key.pkcs11.ca, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + X509_free(x509); + return 0; + } + st = SSL_CTX_get_cert_store(ctx); + add_ca_to_cert_store(st, x509); + X509_free(x509); + } + else { + FILE *fp = fopen(setup_data->pki_key.key.pkcs11.ca, "r"); + X509 *x509 = fp ? d2i_X509_fp(fp, NULL) : NULL; + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + + if (!x509 || !SSL_add_client_CA(ssl, x509)) { + coap_log(LOG_WARNING, + "*** setup_pki: (D)TLS: %s: Unable to configure " + "%s CA File\n", + setup_data->pki_key.key.pkcs11.ca, + role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); + if (x509) X509_free(x509); + return 0; + } + st = SSL_CTX_get_cert_store(ctx); + add_ca_to_cert_store(st, x509); + X509_free(x509); + } + } + break; + + default: + coap_log(LOG_ERR, + "*** setup_pki: (D)TLS: Unknown key type %d\n", + setup_data->pki_key.key_type); + return 0; + } + return 1; +} +#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT */ + +static char* +get_san_or_cn_from_cert(X509* x509) { + if (x509) { + char *cn; + int n; + STACK_OF(GENERAL_NAME) *san_list; + char buffer[256]; + + san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL); + if (san_list) { + int san_count = sk_GENERAL_NAME_num(san_list); + + for (n = 0; n < san_count; n++) { + const GENERAL_NAME * name = sk_GENERAL_NAME_value (san_list, n); + + if (name->type == GEN_DNS) { + const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName); + + /* Make sure that there is not an embedded NUL in the dns_name */ + if (ASN1_STRING_length(name->d.dNSName) != (int)strlen (dns_name)) + continue; + cn = OPENSSL_strdup(dns_name); + sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free); + return cn; + } + } + sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free); + } + /* Otherwise look for the CN= field */ + X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer)); + + /* Need to emulate strcasestr() here. Looking for CN= */ + n = (int)strlen(buffer) - 3; + cn = buffer; + while (n > 0) { + if (((cn[0] == 'C') || (cn[0] == 'c')) && + ((cn[1] == 'N') || (cn[1] == 'n')) && + (cn[2] == '=')) { + cn += 3; + break; + } + cn++; + n--; + } + if (n > 0) { + char * ecn = strchr(cn, '/'); + if (ecn) { + return OPENSSL_strndup(cn, ecn-cn); + } + else { + return OPENSSL_strdup(cn); + } + } + } + return NULL; +} + +static int +tls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) { + SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, + SSL_get_ex_data_X509_STORE_CTX_idx()); + coap_session_t *session = SSL_get_app_data(ssl); + coap_openssl_context_t *context = + ((coap_openssl_context_t *)session->context->dtls_context); + coap_dtls_pki_t *setup_data = &context->setup_data; + int depth = X509_STORE_CTX_get_error_depth(ctx); + int err = X509_STORE_CTX_get_error(ctx); + X509 *x509 = X509_STORE_CTX_get_current_cert(ctx); + char *cn = get_san_or_cn_from_cert(x509); + int keep_preverify_ok = preverify_ok; + + if (!preverify_ok) { + switch (err) { + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CERT_HAS_EXPIRED: + if (setup_data->allow_expired_certs) + preverify_ok = 1; + break; + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + if (setup_data->allow_self_signed && !setup_data->check_common_ca) + preverify_ok = 1; + break; + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: /* Set if the CA is not known */ + if (!setup_data->verify_peer_cert) + preverify_ok = 1; + break; + case X509_V_ERR_UNABLE_TO_GET_CRL: + if (setup_data->allow_no_crl) + preverify_ok = 1; + break; + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CRL_HAS_EXPIRED: + if (setup_data->allow_expired_crl) + preverify_ok = 1; + break; + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + if (!setup_data->verify_peer_cert) + preverify_ok = 1; + break; + default: + break; + } + if (setup_data->cert_chain_validation && + depth > (setup_data->cert_chain_verify_depth + 1)) { + preverify_ok = 0; + err = X509_V_ERR_CERT_CHAIN_TOO_LONG; + X509_STORE_CTX_set_error(ctx, err); + } + if (!preverify_ok) { + if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) { + coap_log(LOG_WARNING, + " %s: %s: '%s' depth=%d\n", + coap_session_str(session), + "Unknown CA", cn ? cn : "?", depth); + } + else { + coap_log(LOG_WARNING, + " %s: %s: '%s' depth=%d\n", + coap_session_str(session), + X509_verify_cert_error_string(err), cn ? cn : "?", depth); + } + } + else { + coap_log(LOG_INFO, + " %s: %s: overridden: '%s' depth=%d\n", + coap_session_str(session), + X509_verify_cert_error_string(err), cn ? cn : "?", depth); + } + } + /* Certificate - depth == 0 is the Client Cert */ + if (setup_data->validate_cn_call_back && keep_preverify_ok) { + int length = i2d_X509(x509, NULL); + uint8_t *base_buf; + uint8_t *base_buf2 = base_buf = OPENSSL_malloc(length); + + /* base_buf2 gets moved to the end */ + i2d_X509(x509, &base_buf2); + if (!setup_data->validate_cn_call_back(cn, base_buf, length, session, + depth, preverify_ok, + setup_data->cn_call_back_arg)) { + if (depth == 0) { + X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED); + } + else { + X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA); + } + preverify_ok = 0; + } + OPENSSL_free(base_buf); + } + OPENSSL_free(cn); + return preverify_ok; +} + +#if COAP_SERVER_SUPPORT +#if OPENSSL_VERSION_NUMBER < 0x10101000L +/* + * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so + * it is possible to determine whether this is a PKI or PSK incoming + * request and adjust the ciphers if necessary + * + * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back() + */ +static int +tls_secret_call_back(SSL *ssl, + void *secret, + int *secretlen, + STACK_OF(SSL_CIPHER) *peer_ciphers, + const SSL_CIPHER **cipher COAP_UNUSED, + void *arg +) { + int ii; + int psk_requested = 0; + coap_session_t *session; + coap_dtls_pki_t *setup_data = (coap_dtls_pki_t*)arg; + + session = (coap_session_t *)SSL_get_app_data(ssl); + assert(session != NULL); + assert(session->context != NULL); + if (session == NULL || + session->context == NULL) + return 0; + + if ((session->psk_key) || + (session->context->spsk_setup_data.psk_info.key.s && + session->context->spsk_setup_data.psk_info.key.length)) { + /* Is PSK being requested - if so, we need to change algorithms */ + for (ii = 0; ii < sk_SSL_CIPHER_num (peer_ciphers); ii++) { + const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii); + + coap_log(COAP_LOG_CIPHERS, "Client cipher: %s\n", + SSL_CIPHER_get_name(peer_cipher)); + if (strstr (SSL_CIPHER_get_name (peer_cipher), "PSK")) { + psk_requested = 1; + break; + } + } + } + if (!psk_requested) { + coap_log(LOG_DEBUG, " %s: Using PKI ciphers\n", + coap_session_str(session)); + + if (setup_data->verify_peer_cert) { + SSL_set_verify(ssl, + SSL_VERIFY_PEER | + SSL_VERIFY_CLIENT_ONCE | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + tls_verify_call_back); + } + else { + SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back); + } + + /* Check CA Chain */ + if (setup_data->cert_chain_validation) + SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2); + + /* Certificate Revocation */ + if (setup_data->check_cert_revocation) { + X509_VERIFY_PARAM *param; + + param = X509_VERIFY_PARAM_new(); + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); + SSL_set1_param(ssl, param); + X509_VERIFY_PARAM_free(param); + } + if (setup_data->additional_tls_setup_call_back) { + /* Additional application setup wanted */ + if (!setup_data->additional_tls_setup_call_back(ssl, setup_data)) + return 0; + } + } + else { + if (session->psk_key) { + memcpy(secret, session->psk_key->s, session->psk_key->length); + *secretlen = session->psk_key->length; + } + else if (session->context->spsk_setup_data.psk_info.key.s && + session->context->spsk_setup_data.psk_info.key.length) { + memcpy(secret, session->context->spsk_setup_data.psk_info.key.s, + session->context->spsk_setup_data.psk_info.key.length); + *secretlen = session->context->spsk_setup_data.psk_info.key.length; + } + coap_log(LOG_DEBUG, " %s: Setting PSK ciphers\n", + coap_session_str(session)); + /* + * Force a PSK algorithm to be used, so we do PSK + */ + SSL_set_cipher_list (ssl, COAP_OPENSSL_PSK_CIPHERS); + SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback); + } + return 0; +} + +/* + * During the SSL/TLS initial negotiations, tls_server_name_call_back() is + * called so it is possible to set up an extra callback to determine whether + * this is a PKI or PSK incoming request and adjust the ciphers if necessary + * + * Set up by SSL_CTX_set_tlsext_servername_callback() in + * coap_dtls_context_set_pki() + */ +static int +tls_server_name_call_back(SSL *ssl, + int *sd COAP_UNUSED, + void *arg +) { + coap_dtls_pki_t *setup_data = (coap_dtls_pki_t*)arg; + + if (!ssl) { + return SSL_TLSEXT_ERR_NOACK; + } + + if (setup_data->validate_sni_call_back) { + /* SNI checking requested */ + coap_session_t *session = (coap_session_t*)SSL_get_app_data(ssl); + coap_openssl_context_t *context = + ((coap_openssl_context_t *)session->context->dtls_context); + const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + size_t i; + + if (!sni || !sni[0]) { + sni = ""; + } + for (i = 0; i < context->sni_count; i++) { + if (!strcasecmp(sni, context->sni_entry_list[i].sni)) { + break; + } + } + if (i == context->sni_count) { + SSL_CTX *ctx; + coap_dtls_pki_t sni_setup_data; + coap_dtls_key_t *new_entry = setup_data->validate_sni_call_back(sni, + setup_data->sni_call_back_arg); + if (!new_entry) { + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + /* Need to set up a new SSL_CTX to switch to */ + if (session->proto == COAP_PROTO_DTLS) { + /* Set up DTLS context */ + ctx = SSL_CTX_new(DTLS_method()); + if (!ctx) + goto error; + SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION); + SSL_CTX_set_app_data(ctx, &context->dtls); + SSL_CTX_set_read_ahead(ctx, 1); + coap_set_user_prefs(ctx); + SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie); + SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie); + SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback); + SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU); + } +#if !COAP_DISABLE_TCP + else { + /* Set up TLS context */ + ctx = SSL_CTX_new(TLS_method()); + if (!ctx) + goto error; + SSL_CTX_set_app_data(ctx, &context->tls); + SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION); + coap_set_user_prefs(ctx); + SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback); + SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL); + } +#endif /* !COAP_DISABLE_TCP */ + sni_setup_data = *setup_data; + sni_setup_data.pki_key = *new_entry; + setup_pki_server(ctx, &sni_setup_data); + + context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list, + (context->sni_count+1)*sizeof(sni_entry)); + context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni); + context->sni_entry_list[context->sni_count].ctx = ctx; + context->sni_count++; + } + SSL_set_SSL_CTX (ssl, context->sni_entry_list[i].ctx); + SSL_clear_options (ssl, 0xFFFFFFFFL); + SSL_set_options (ssl, SSL_CTX_get_options (context->sni_entry_list[i].ctx)); + } + + /* + * Have to do extra call back next to get client algorithms + * SSL_get_client_ciphers() does not work this early on + */ + SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg); + return SSL_TLSEXT_ERR_OK; + +error: + return SSL_TLSEXT_ERR_ALERT_WARNING; +} + +/* + * During the SSL/TLS initial negotiations, psk_tls_server_name_call_back() is + * called to see if SNI is being used. + * + * Set up by SSL_CTX_set_tlsext_servername_callback() + * in coap_dtls_context_set_spsk() + */ +static int +psk_tls_server_name_call_back(SSL *ssl, + int *sd COAP_UNUSED, + void *arg +) { + coap_dtls_spsk_t *setup_data = (coap_dtls_spsk_t*)arg; + + if (!ssl) { + return SSL_TLSEXT_ERR_NOACK; + } + + if (setup_data->validate_sni_call_back) { + /* SNI checking requested */ + coap_session_t *c_session = (coap_session_t*)SSL_get_app_data(ssl); + coap_openssl_context_t *o_context = + ((coap_openssl_context_t *)c_session->context->dtls_context); + const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + size_t i; + char lhint[COAP_DTLS_HINT_LENGTH]; + + if (!sni || !sni[0]) { + sni = ""; + } + for (i = 0; i < o_context->psk_sni_count; i++) { + if (!strcasecmp(sni, (char*)o_context->psk_sni_entry_list[i].sni)) { + break; + } + } + if (i == o_context->psk_sni_count) { + SSL_CTX *ctx; + const coap_dtls_spsk_info_t *new_entry = + setup_data->validate_sni_call_back(sni, + c_session, + setup_data->sni_call_back_arg); + if (!new_entry) { + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + /* Need to set up a new SSL_CTX to switch to */ + if (c_session->proto == COAP_PROTO_DTLS) { + /* Set up DTLS context */ + ctx = SSL_CTX_new(DTLS_method()); + if (!ctx) + goto error; + SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION); + SSL_CTX_set_app_data(ctx, &o_context->dtls); + SSL_CTX_set_read_ahead(ctx, 1); + SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS); + SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie); + SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie); + SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback); + SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU); + } +#if !COAP_DISABLE_TCP + else { + /* Set up TLS context */ + ctx = SSL_CTX_new(TLS_method()); + if (!ctx) + goto error; + SSL_CTX_set_app_data(ctx, &o_context->tls); + SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION); + SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS); + SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback); + SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL); + } +#endif /* !COAP_DISABLE_TCP */ + + o_context->psk_sni_entry_list = + OPENSSL_realloc(o_context->psk_sni_entry_list, + (o_context->psk_sni_count+1)*sizeof(psk_sni_entry)); + o_context->psk_sni_entry_list[o_context->psk_sni_count].sni = + OPENSSL_strdup(sni); + o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info = + *new_entry; + o_context->psk_sni_entry_list[o_context->psk_sni_count].ctx = + ctx; + o_context->psk_sni_count++; + } + SSL_set_SSL_CTX (ssl, o_context->psk_sni_entry_list[i].ctx); + SSL_clear_options (ssl, 0xFFFFFFFFL); + SSL_set_options (ssl, + SSL_CTX_get_options (o_context->psk_sni_entry_list[i].ctx)); + coap_session_refresh_psk_key(c_session, + &o_context->psk_sni_entry_list[i].psk_info.key); + snprintf(lhint, sizeof(lhint), "%.*s", + (int)o_context->psk_sni_entry_list[i].psk_info.hint.length, + o_context->psk_sni_entry_list[i].psk_info.hint.s); + SSL_use_psk_identity_hint(ssl, lhint); + } + + /* + * Have to do extra call back next to get client algorithms + * SSL_get_client_ciphers() does not work this early on + */ + SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg); + return SSL_TLSEXT_ERR_OK; + +error: + return SSL_TLSEXT_ERR_ALERT_WARNING; +} +#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ +/* + * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is + * called early in the Client Hello processing so it is possible to determine + * whether this is a PKI or PSK incoming request and adjust the ciphers if + * necessary. + * + * Set up by SSL_CTX_set_client_hello_cb(). + */ +static int +tls_client_hello_call_back(SSL *ssl, + int *al, + void *arg COAP_UNUSED +) { + coap_session_t *session; + coap_openssl_context_t *dtls_context; + coap_dtls_pki_t *setup_data; + int psk_requested = 0; + const unsigned char *out; + size_t outlen; + + if (!ssl) { + *al = SSL_AD_INTERNAL_ERROR; + return SSL_CLIENT_HELLO_ERROR; + } + session = (coap_session_t *)SSL_get_app_data(ssl); + assert(session != NULL); + assert(session->context != NULL); + assert(session->context->dtls_context != NULL); + if (session == NULL || + session->context == NULL || + session->context->dtls_context == NULL) { + *al = SSL_AD_INTERNAL_ERROR; + return SSL_CLIENT_HELLO_ERROR; + } + dtls_context = (coap_openssl_context_t *)session->context->dtls_context; + setup_data = &dtls_context->setup_data; + + /* + * See if PSK being requested + */ + if ((session->psk_key) || + (session->context->spsk_setup_data.psk_info.key.s && + session->context->spsk_setup_data.psk_info.key.length)) { + size_t len = SSL_client_hello_get0_ciphers(ssl, &out); + STACK_OF(SSL_CIPHER) *peer_ciphers = NULL; + STACK_OF(SSL_CIPHER) *scsvc = NULL; + + if (len && SSL_bytes_to_cipher_list(ssl, out, len, + SSL_client_hello_isv2(ssl), + &peer_ciphers, &scsvc)) { + int ii; + for (ii = 0; ii < sk_SSL_CIPHER_num (peer_ciphers); ii++) { + const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii); + + coap_log(COAP_LOG_CIPHERS, "Client cipher: %s (%04x)\n", + SSL_CIPHER_get_name(peer_cipher), + SSL_CIPHER_get_protocol_id(peer_cipher)); + if (strstr (SSL_CIPHER_get_name (peer_cipher), "PSK")) { + psk_requested = 1; + break; + } + } + } + sk_SSL_CIPHER_free(peer_ciphers); + sk_SSL_CIPHER_free(scsvc); + } + + if (psk_requested) { + /* + * Client has requested PSK and it is supported + */ + coap_log(LOG_DEBUG, " %s: PSK request\n", + coap_session_str(session)); + SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback); + if (setup_data->additional_tls_setup_call_back) { + /* Additional application setup wanted */ + if (!setup_data->additional_tls_setup_call_back(ssl, setup_data)) + return 0; + } + return SSL_CLIENT_HELLO_SUCCESS; + } + + /* + * Handle Certificate requests + */ + + /* + * Determine what type of certificate is being requested + */ + if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type, + &out, &outlen)) { + size_t ii; + for (ii = 0; ii < outlen; ii++) { + switch (out[ii]) { + case 0: + /* RFC6091 X.509 */ + if (outlen >= 2) { + /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */ + goto is_x509; + } + break; + case 2: + /* RFC7250 RPK - not yet supported */ + break; + default: + break; + } + } + *al = SSL_AD_UNSUPPORTED_EXTENSION; + return SSL_CLIENT_HELLO_ERROR; + } + +is_x509: + if (setup_data->validate_sni_call_back) { + /* + * SNI checking requested + */ + coap_dtls_pki_t sni_setup_data; + coap_openssl_context_t *context = + ((coap_openssl_context_t *)session->context->dtls_context); + const char *sni = ""; + char *sni_tmp = NULL; + size_t i; + + if (SSL_client_hello_get0_ext (ssl, TLSEXT_TYPE_server_name, &out, &outlen) && + outlen > 5 && + (((out[0]<<8) + out[1] +2) == (int)outlen) && + out[2] == TLSEXT_NAMETYPE_host_name && + (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) { + /* Skip over length, type and length */ + out += 5; + outlen -= 5; + sni_tmp = OPENSSL_malloc(outlen+1); + sni_tmp[outlen] = '\000'; + memcpy(sni_tmp, out, outlen); + sni = sni_tmp; + } + /* Is this a cached entry? */ + for (i = 0; i < context->sni_count; i++) { + if (!strcasecmp(sni, context->sni_entry_list[i].sni)) { + break; + } + } + if (i == context->sni_count) { + /* + * New SNI request + */ + coap_dtls_key_t *new_entry = setup_data->validate_sni_call_back(sni, + setup_data->sni_call_back_arg); + if (!new_entry) { + *al = SSL_AD_UNRECOGNIZED_NAME; + return SSL_CLIENT_HELLO_ERROR; + } + + + context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list, + (context->sni_count+1)*sizeof(sni_entry)); + context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni); + context->sni_entry_list[context->sni_count].pki_key = *new_entry; + context->sni_count++; + } + if (sni_tmp) { + OPENSSL_free(sni_tmp); + } + sni_setup_data = *setup_data; + sni_setup_data.pki_key = context->sni_entry_list[i].pki_key; + setup_pki_ssl(ssl, &sni_setup_data, COAP_DTLS_ROLE_SERVER); + } + else { + setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_SERVER); + } + + coap_log(LOG_DEBUG, " %s: Using PKI ciphers\n", + coap_session_str(session)); + + if (setup_data->verify_peer_cert) { + SSL_set_verify(ssl, + SSL_VERIFY_PEER | + SSL_VERIFY_CLIENT_ONCE | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + tls_verify_call_back); + } + else { + SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back); + } + + /* Check CA Chain */ + if (setup_data->cert_chain_validation) + SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2); + + /* Certificate Revocation */ + if (setup_data->check_cert_revocation) { + X509_VERIFY_PARAM *param; + + param = X509_VERIFY_PARAM_new(); + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); + SSL_set1_param(ssl, param); + X509_VERIFY_PARAM_free(param); + } + if (setup_data->additional_tls_setup_call_back) { + /* Additional application setup wanted */ + if (!setup_data->additional_tls_setup_call_back(ssl, setup_data)) + return 0; + } + return SSL_CLIENT_HELLO_SUCCESS; +} + +/* + * During the SSL/TLS initial negotiations, psk_tls_client_hello_call_back() is + * called early in the Client Hello processing so it is possible to determine + * whether SNI needs to be handled + * + * Set up by SSL_CTX_set_client_hello_cb(). + */ +static int +psk_tls_client_hello_call_back(SSL *ssl, + int *al, + void *arg COAP_UNUSED +) { + coap_session_t *c_session; + coap_openssl_context_t *o_context; + coap_dtls_spsk_t *setup_data; + const unsigned char *out; + size_t outlen; + + if (!ssl) + goto int_err; + c_session = (coap_session_t *)SSL_get_app_data(ssl); + if (!c_session || !c_session->context) { + goto int_err; + } + o_context = (coap_openssl_context_t *)c_session->context->dtls_context; + if (!o_context) { + goto int_err; + } + setup_data = &c_session->context->spsk_setup_data; + + if (setup_data->validate_sni_call_back) { + /* + * SNI checking requested + */ + const char *sni = ""; + char *sni_tmp = NULL; + size_t i; + char lhint[COAP_DTLS_HINT_LENGTH]; + + if (SSL_client_hello_get0_ext (ssl, TLSEXT_TYPE_server_name, &out, &outlen) && + outlen > 5 && + (((out[0]<<8) + out[1] +2) == (int)outlen) && + out[2] == TLSEXT_NAMETYPE_host_name && + (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) { + /* Skip over length, type and length */ + out += 5; + outlen -= 5; + sni_tmp = OPENSSL_malloc(outlen+1); + if (sni_tmp) { + sni_tmp[outlen] = '\000'; + memcpy(sni_tmp, out, outlen); + sni = sni_tmp; + } + } + + /* Is this a cached entry? */ + for (i = 0; i < o_context->psk_sni_count; i++) { + if (strcasecmp(sni, o_context->psk_sni_entry_list[i].sni) == 0) { + break; + } + } + if (i == o_context->psk_sni_count) { + /* + * New SNI request + */ + psk_sni_entry *tmp_entry; + const coap_dtls_spsk_info_t *new_entry = setup_data->validate_sni_call_back( + sni, + c_session, + setup_data->sni_call_back_arg); + if (!new_entry) { + *al = SSL_AD_UNRECOGNIZED_NAME; + return SSL_CLIENT_HELLO_ERROR; + } + + tmp_entry = + OPENSSL_realloc(o_context->psk_sni_entry_list, + (o_context->psk_sni_count+1)*sizeof(sni_entry)); + if (tmp_entry) { + o_context->psk_sni_entry_list = tmp_entry; + o_context->psk_sni_entry_list[o_context->psk_sni_count].sni = + OPENSSL_strdup(sni); + if (o_context->psk_sni_entry_list[o_context->psk_sni_count].sni) { + o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info = + *new_entry; + o_context->psk_sni_count++; + } + } + } + if (sni_tmp) { + OPENSSL_free(sni_tmp); + } + if (coap_session_refresh_psk_hint(c_session, + &o_context->psk_sni_entry_list[i].psk_info.hint) + == 0) { + goto int_err; + } + if (coap_session_refresh_psk_key(c_session, + &o_context->psk_sni_entry_list[i].psk_info.key) + == 0) { + goto int_err; + } + if (o_context->psk_sni_entry_list[i].psk_info.hint.s) { + snprintf(lhint, sizeof(lhint), "%.*s", + (int)o_context->psk_sni_entry_list[i].psk_info.hint.length, + o_context->psk_sni_entry_list[i].psk_info.hint.s); + SSL_use_psk_identity_hint(ssl, lhint); + } + } + return SSL_CLIENT_HELLO_SUCCESS; + +int_err: + *al = SSL_AD_INTERNAL_ERROR; + return SSL_CLIENT_HELLO_ERROR; +} +#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ +#endif /* COAP_SERVER_SUPPORT */ + +int +coap_dtls_context_set_pki(coap_context_t *ctx, + const coap_dtls_pki_t *setup_data, + const coap_dtls_role_t role +) { + coap_openssl_context_t *context = + ((coap_openssl_context_t *)ctx->dtls_context); + BIO *bio; + if (!setup_data) + return 0; + context->setup_data = *setup_data; + if (!context->setup_data.verify_peer_cert) { + /* Needs to be clear so that no CA DNs are transmitted */ + context->setup_data.check_common_ca = 0; + /* Allow all of these but warn if issue */ + context->setup_data.allow_self_signed = 1; + context->setup_data.allow_expired_certs = 1; + context->setup_data.cert_chain_validation = 1; + context->setup_data.cert_chain_verify_depth = 10; + context->setup_data.check_cert_revocation = 1; + context->setup_data.allow_no_crl = 1; + context->setup_data.allow_expired_crl = 1; + context->setup_data.allow_bad_md_hash = 1; + context->setup_data.allow_short_rsa_length = 1; + } +#if COAP_SERVER_SUPPORT + if (role == COAP_DTLS_ROLE_SERVER) { + if (context->dtls.ctx) { + /* SERVER DTLS */ +#if OPENSSL_VERSION_NUMBER < 0x10101000L + if (!setup_pki_server(context->dtls.ctx, setup_data)) + return 0; +#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */ + /* libcoap is managing TLS connection based on setup_data options */ + /* Need to set up logic to differentiate between a PSK or PKI session */ + /* + * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb() + * which is not in 1.1.0 + */ +#if OPENSSL_VERSION_NUMBER < 0x10101000L + if (SSLeay() >= 0x10101000L) { + coap_log(LOG_WARNING, + "OpenSSL compiled with %lux, linked with %lux, so " + "no certificate checking\n", + OPENSSL_VERSION_NUMBER, SSLeay()); + } + SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data); + SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx, + tls_server_name_call_back); +#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + SSL_CTX_set_client_hello_cb(context->dtls.ctx, + tls_client_hello_call_back, + NULL); +#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + } +#if !COAP_DISABLE_TCP + if (context->tls.ctx) { + /* SERVER TLS */ +#if OPENSSL_VERSION_NUMBER < 0x10101000L + if (!setup_pki_server(context->tls.ctx, setup_data)) + return 0; +#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */ + /* libcoap is managing TLS connection based on setup_data options */ + /* Need to set up logic to differentiate between a PSK or PKI session */ + /* + * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb() + * which is not in 1.1.0 + */ +#if OPENSSL_VERSION_NUMBER < 0x10101000L + if (SSLeay() >= 0x10101000L) { + coap_log(LOG_WARNING, + "OpenSSL compiled with %lux, linked with %lux, so " + "no certificate checking\n", + OPENSSL_VERSION_NUMBER, SSLeay()); + } + SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data); + SSL_CTX_set_tlsext_servername_callback(context->tls.ctx, + tls_server_name_call_back); +#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + SSL_CTX_set_client_hello_cb(context->tls.ctx, + tls_client_hello_call_back, + NULL); +#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ + /* TLS Only */ + SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL); + } +#endif /* !COAP_DISABLE_TCP */ + } +#else /* ! COAP_SERVER_SUPPORT */ + (void)role; +#endif /* ! COAP_SERVER_SUPPORT */ + + if (!context->dtls.ssl) { + /* This is set up to handle new incoming sessions to a server */ + context->dtls.ssl = SSL_new(context->dtls.ctx); + if (!context->dtls.ssl) + return 0; + bio = BIO_new(context->dtls.meth); + if (!bio) { + SSL_free (context->dtls.ssl); + context->dtls.ssl = NULL; + return 0; + } + SSL_set_bio(context->dtls.ssl, bio, bio); + SSL_set_app_data(context->dtls.ssl, NULL); + SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE); + SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU); + } + context->psk_pki_enabled |= IS_PKI; + return 1; +} + +int +coap_dtls_context_set_pki_root_cas(coap_context_t *ctx, + const char *ca_file, + const char *ca_dir +) { + coap_openssl_context_t *context = + ((coap_openssl_context_t *)ctx->dtls_context); + if (context->dtls.ctx) { + if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) { + coap_log(LOG_WARNING, "Unable to install root CAs (%s/%s)\n", + ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL"); + return 0; + } + } +#if !COAP_DISABLE_TCP + if (context->tls.ctx) { + if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) { + coap_log(LOG_WARNING, "Unable to install root CAs (%s/%s)\n", + ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL"); + return 0; + } + } +#endif /* !COAP_DISABLE_TCP */ + return 1; +} + +int +coap_dtls_context_check_keys_enabled(coap_context_t *ctx) +{ + coap_openssl_context_t *context = + ((coap_openssl_context_t *)ctx->dtls_context); + return context->psk_pki_enabled ? 1 : 0; +} + + +void coap_dtls_free_context(void *handle) { + size_t i; + coap_openssl_context_t *context = (coap_openssl_context_t *)handle; + + if (context->dtls.ssl) + SSL_free(context->dtls.ssl); + if (context->dtls.ctx) + SSL_CTX_free(context->dtls.ctx); + if (context->dtls.cookie_hmac) + HMAC_CTX_free(context->dtls.cookie_hmac); + if (context->dtls.meth) + BIO_meth_free(context->dtls.meth); + if (context->dtls.bio_addr) + BIO_ADDR_free(context->dtls.bio_addr); +#if !COAP_DISABLE_TCP + if ( context->tls.ctx ) + SSL_CTX_free( context->tls.ctx ); + if ( context->tls.meth ) + BIO_meth_free( context->tls.meth ); +#endif /* !COAP_DISABLE_TCP */ + for (i = 0; i < context->sni_count; i++) { + OPENSSL_free(context->sni_entry_list[i].sni); +#if OPENSSL_VERSION_NUMBER < 0x10101000L + SSL_CTX_free(context->sni_entry_list[i].ctx); +#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */ + } + if (context->sni_count) + OPENSSL_free(context->sni_entry_list); + for (i = 0; i < context->psk_sni_count; i++) { + OPENSSL_free((char*)context->psk_sni_entry_list[i].sni); +#if OPENSSL_VERSION_NUMBER < 0x10101000L + SSL_CTX_free(context->psk_sni_entry_list[i].ctx); +#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */ + } + if (context->psk_sni_count) + OPENSSL_free(context->psk_sni_entry_list); + coap_free(context); +} + +#if COAP_SERVER_SUPPORT +void * coap_dtls_new_server_session(coap_session_t *session) { + BIO *nbio = NULL; + SSL *nssl = NULL, *ssl = NULL; + coap_ssl_data *data; + coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls; + int r; + const coap_bin_const_t *psk_hint; + + nssl = SSL_new(dtls->ctx); + if (!nssl) + goto error; + nbio = BIO_new(dtls->meth); + if (!nbio) + goto error; + SSL_set_bio(nssl, nbio, nbio); + SSL_set_app_data(nssl, NULL); + SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE); + SSL_set_mtu(nssl, (long)session->mtu); + ssl = dtls->ssl; + dtls->ssl = nssl; + nssl = NULL; + SSL_set_app_data(ssl, session); + + data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl)); + data->session = session; + + /* hint may get updated if/when handling SNI callback */ + psk_hint = coap_get_session_server_psk_hint(session); + if (psk_hint != NULL && psk_hint->length) { + char* hint = OPENSSL_malloc(psk_hint->length + 1); + + if (hint) { + memcpy(hint, psk_hint->s, psk_hint->length); + hint[psk_hint->length] = '\000'; + SSL_use_psk_identity_hint(ssl, hint); + OPENSSL_free(hint); + } else { + coap_log(LOG_WARNING, "hint malloc failure\n"); + } + } + + r = SSL_accept(ssl); + if (r == -1) { + int err = SSL_get_error(ssl, r); + if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + r = 0; + } + + if (r == 0) { + SSL_free(ssl); + return NULL; + } + + return ssl; + +error: + if (nssl) + SSL_free(nssl); + return NULL; +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +static int +setup_client_ssl_session(coap_session_t *session, SSL *ssl +) { + coap_openssl_context_t *context = + ((coap_openssl_context_t *)session->context->dtls_context); + + if (context->psk_pki_enabled & IS_PSK) { + coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data; + + /* Issue SNI if requested */ + if (setup_data->client_sni && + SSL_set_tlsext_host_name (ssl, setup_data->client_sni) != 1) { + coap_log(LOG_WARNING, "SSL_set_tlsext_host_name: set '%s' failed", + setup_data->client_sni); + } + SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback); +#if COAP_SERVER_SUPPORT + SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback); +#endif /* COAP_SERVER_SUPPORT */ + SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS); + if (setup_data->validate_ih_call_back) { + if (session->proto == COAP_PROTO_DTLS) { + SSL_set_max_proto_version(ssl, DTLS1_2_VERSION); + } +#if !COAP_DISABLE_TCP + else { + SSL_set_max_proto_version(ssl, TLS1_2_VERSION); + } +#endif /* !COAP_DISABLE_TCP */ + coap_log(LOG_DEBUG, + "CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n"); + } + } + if (context->psk_pki_enabled & IS_PKI) { + coap_dtls_pki_t *setup_data = &context->setup_data; + if (!setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_CLIENT)) + return 0; + /* libcoap is managing (D)TLS connection based on setup_data options */ +#if !COAP_DISABLE_TCP + if (session->proto == COAP_PROTO_TLS) + SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn)); +#endif /* !COAP_DISABLE_TCP */ + + /* Issue SNI if requested */ + if (setup_data->client_sni && + SSL_set_tlsext_host_name (ssl, setup_data->client_sni) != 1) { + coap_log(LOG_WARNING, "SSL_set_tlsext_host_name: set '%s' failed", + setup_data->client_sni); + } + /* Certificate Revocation */ + if (setup_data->check_cert_revocation) { + X509_VERIFY_PARAM *param; + + param = X509_VERIFY_PARAM_new(); + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); + SSL_set1_param(ssl, param); + X509_VERIFY_PARAM_free(param); + } + + /* Verify Peer */ + if (setup_data->verify_peer_cert) + SSL_set_verify(ssl, + SSL_VERIFY_PEER | + SSL_VERIFY_CLIENT_ONCE | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + tls_verify_call_back); + else + SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back); + + /* Check CA Chain */ + if (setup_data->cert_chain_validation) + SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1); + + } + return 1; +} + +void *coap_dtls_new_client_session(coap_session_t *session) { + BIO *bio = NULL; + SSL *ssl = NULL; + coap_ssl_data *data; + int r; + coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context); + coap_dtls_context_t *dtls = &context->dtls; + + ssl = SSL_new(dtls->ctx); + if (!ssl) + goto error; + bio = BIO_new(dtls->meth); + if (!bio) + goto error; + data = (coap_ssl_data *)BIO_get_data(bio); + data->session = session; + SSL_set_bio(ssl, bio, bio); + SSL_set_app_data(ssl, session); + SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); + SSL_set_mtu(ssl, (long)session->mtu); + + if (!setup_client_ssl_session(session, ssl)) + goto error; + + session->dtls_timeout_count = 0; + + r = SSL_connect(ssl); + if (r == -1) { + int ret = SSL_get_error(ssl, r); + if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) + r = 0; + } + + if (r == 0) + goto error; + + return ssl; + +error: + if (ssl) + SSL_free(ssl); + return NULL; +} + +void coap_dtls_session_update_mtu(coap_session_t *session) { + SSL *ssl = (SSL *)session->tls; + if (ssl) + SSL_set_mtu(ssl, (long)session->mtu); +} +#endif /* COAP_CLIENT_SUPPORT */ + +void coap_dtls_free_session(coap_session_t *session) { + SSL *ssl = (SSL *)session->tls; + if (ssl) { + if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) { + int r = SSL_shutdown(ssl); + if (r == 0) r = SSL_shutdown(ssl); + } + SSL_free(ssl); + session->tls = NULL; + if (session->context) + coap_handle_event(session->context, COAP_EVENT_DTLS_CLOSED, session); + } +} + +int coap_dtls_send(coap_session_t *session, + const uint8_t *data, size_t data_len) { + int r; + SSL *ssl = (SSL *)session->tls; + + assert(ssl != NULL); + + session->dtls_event = -1; + r = SSL_write(ssl, data, (int)data_len); + + if (r <= 0) { + int err = SSL_get_error(ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + r = 0; + } else { + coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n"); + if (err == SSL_ERROR_ZERO_RETURN) + session->dtls_event = COAP_EVENT_DTLS_CLOSED; + else if (err == SSL_ERROR_SSL) + session->dtls_event = COAP_EVENT_DTLS_ERROR; + r = -1; + } + } + + if (session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(session->context, session->dtls_event, session); + if (session->dtls_event == COAP_EVENT_DTLS_ERROR || + session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + r = -1; + } + } + + return r; +} + +int coap_dtls_is_context_timeout(void) { + return 0; +} + +coap_tick_t coap_dtls_get_context_timeout(void *dtls_context) { + (void)dtls_context; + return 0; +} + +coap_tick_t coap_dtls_get_timeout(coap_session_t *session, coap_tick_t now COAP_UNUSED) { + SSL *ssl = (SSL *)session->tls; + coap_ssl_data *ssl_data; + + assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE); + ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl)); + return ssl_data->timeout; +} + +/* + * return 1 timed out + * 0 still timing out + */ +int +coap_dtls_handle_timeout(coap_session_t *session) { + SSL *ssl = (SSL *)session->tls; + + assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE); + if ((++session->dtls_timeout_count > session->max_retransmit) || + (DTLSv1_handle_timeout(ssl) < 0)) { + /* Too many retries */ + coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + return 1; + } + return 0; +} + +#if COAP_SERVER_SUPPORT +int coap_dtls_hello(coap_session_t *session, + const uint8_t *data, size_t data_len) { + coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls; + coap_ssl_data *ssl_data; + int r; + + SSL_set_mtu(dtls->ssl, (long)session->mtu); + ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(dtls->ssl)); + assert(ssl_data != NULL); + if (ssl_data->pdu_len) { + coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n", + coap_session_str(session), ssl_data->pdu_len); + } + ssl_data->session = session; + ssl_data->pdu = data; + ssl_data->pdu_len = (unsigned)data_len; + r = DTLSv1_listen(dtls->ssl, dtls->bio_addr); + if (r <= 0) { + int err = SSL_get_error(dtls->ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + /* Got a ClientHello, sent-out a VerifyRequest */ + r = 0; + } + } else { + /* Got a valid answer to a VerifyRequest */ + r = 1; + } + + /* + * Cannot check if data is left on the stack in error as DTLSv1_listen() + * only does a 'peek' read of the incoming data. + * + */ + return r; +} +#endif /* COAP_SERVER_SUPPORT */ + +int coap_dtls_receive(coap_session_t *session, + const uint8_t *data, size_t data_len) { + coap_ssl_data *ssl_data; + SSL *ssl = (SSL *)session->tls; + int r; + + assert(ssl != NULL); + + int in_init = SSL_in_init(ssl); + uint8_t pdu[COAP_RXBUFFER_SIZE]; + ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl)); + assert(ssl_data != NULL); + + if (ssl_data->pdu_len) { + coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n", + coap_session_str(session), ssl_data->pdu_len); + } + ssl_data->pdu = data; + ssl_data->pdu_len = (unsigned)data_len; + + session->dtls_event = -1; + r = SSL_read(ssl, pdu, (int)sizeof(pdu)); + if (r > 0) { + r = coap_handle_dgram(session->context, session, pdu, (size_t)r); + goto finished; + } else { + int err = SSL_get_error(ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + if (in_init && SSL_is_init_finished(ssl)) { + coap_log(COAP_LOG_CIPHERS, "* %s: Using cipher: %s\n", + coap_session_str(session), SSL_get_cipher_name(ssl)); + coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session); + coap_session_connected(session); + } + r = 0; + } else { + if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */ + session->dtls_event = COAP_EVENT_DTLS_CLOSED; + else if (err == SSL_ERROR_SSL) + session->dtls_event = COAP_EVENT_DTLS_ERROR; + r = -1; + } + if (session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(session->context, session->dtls_event, session); + if (session->dtls_event == COAP_EVENT_DTLS_ERROR || + session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + ssl_data = NULL; + r = -1; + } + } + } + +finished: + if (ssl_data && ssl_data->pdu_len) { + /* pdu data is held on stack which will not stay there */ + coap_log(LOG_DEBUG, "coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len); + ssl_data->pdu_len = 0; + ssl_data->pdu = NULL; + } + return r; +} + +unsigned int coap_dtls_get_overhead(coap_session_t *session) { + unsigned int overhead = 37; + const SSL_CIPHER *s_ciph = NULL; + if (session->tls != NULL) + s_ciph = SSL_get_current_cipher(session->tls); + if ( s_ciph ) { + unsigned int ivlen, maclen, blocksize = 1, pad = 0; + + const EVP_CIPHER *e_ciph; + const EVP_MD *e_md; + char cipher[128]; + + e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph)); + + switch (EVP_CIPHER_mode(e_ciph)) { + case EVP_CIPH_GCM_MODE: + ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; + maclen = EVP_GCM_TLS_TAG_LEN; + break; + + case EVP_CIPH_CCM_MODE: + ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN; + SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher)); + if (strstr(cipher, "CCM8")) + maclen = 8; + else + maclen = 16; + break; + + case EVP_CIPH_CBC_MODE: + e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph)); + blocksize = EVP_CIPHER_block_size(e_ciph); + ivlen = EVP_CIPHER_iv_length(e_ciph); + pad = 1; + maclen = EVP_MD_size(e_md); + break; + + case EVP_CIPH_STREAM_CIPHER: + /* Seen with PSK-CHACHA20-POLY1305 */ + ivlen = 8; + maclen = 8; + break; + + default: + SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher)); + coap_log(LOG_WARNING, "Unknown overhead for DTLS with cipher %s\n", + cipher); + ivlen = 8; + maclen = 16; + break; + } + overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad; + } + return overhead; +} + +#if !COAP_DISABLE_TCP +#if COAP_CLIENT_SUPPORT +void *coap_tls_new_client_session(coap_session_t *session, int *connected) { + BIO *bio = NULL; + SSL *ssl = NULL; + int r; + coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context); + coap_tls_context_t *tls = &context->tls; + + *connected = 0; + ssl = SSL_new(tls->ctx); + if (!ssl) + goto error; + bio = BIO_new(tls->meth); + if (!bio) + goto error; + BIO_set_data(bio, session); + SSL_set_bio(ssl, bio, bio); + SSL_set_app_data(ssl, session); + + if (!setup_client_ssl_session(session, ssl)) + return 0; + + r = SSL_connect(ssl); + if (r == -1) { + int ret = SSL_get_error(ssl, r); + if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) + r = 0; + if (ret == SSL_ERROR_WANT_READ) + session->sock.flags |= COAP_SOCKET_WANT_READ; + if (ret == SSL_ERROR_WANT_WRITE) { + session->sock.flags |= COAP_SOCKET_WANT_WRITE; +#ifdef COAP_EPOLL_SUPPORT + coap_epoll_ctl_mod(&session->sock, + EPOLLOUT | + ((session->sock.flags & COAP_SOCKET_WANT_READ) ? + EPOLLIN : 0), + __func__); +#endif /* COAP_EPOLL_SUPPORT */ + } + } + + if (r == 0) + goto error; + + *connected = SSL_is_init_finished(ssl); + + return ssl; + +error: + if (ssl) + SSL_free(ssl); + return NULL; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +void *coap_tls_new_server_session(coap_session_t *session, int *connected) { + BIO *bio = NULL; + SSL *ssl = NULL; + coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls; + int r; + const coap_bin_const_t *psk_hint; + + *connected = 0; + ssl = SSL_new(tls->ctx); + if (!ssl) + goto error; + bio = BIO_new(tls->meth); + if (!bio) + goto error; + BIO_set_data(bio, session); + SSL_set_bio(ssl, bio, bio); + SSL_set_app_data(ssl, session); + + psk_hint = coap_get_session_server_psk_hint(session); + if (psk_hint != NULL && psk_hint->length) { + char* hint = OPENSSL_malloc(psk_hint->length + 1); + + if (hint) { + memcpy(hint, psk_hint->s, psk_hint->length); + hint[psk_hint->length] = '\000'; + SSL_use_psk_identity_hint(ssl, hint); + OPENSSL_free(hint); + } else { + coap_log(LOG_WARNING, "hint malloc failure\n"); + } + } + + r = SSL_accept(ssl); + if (r == -1) { + int err = SSL_get_error(ssl, r); + if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + r = 0; + if (err == SSL_ERROR_WANT_READ) + session->sock.flags |= COAP_SOCKET_WANT_READ; + if (err == SSL_ERROR_WANT_WRITE) { + session->sock.flags |= COAP_SOCKET_WANT_WRITE; +#ifdef COAP_EPOLL_SUPPORT + coap_epoll_ctl_mod(&session->sock, + EPOLLOUT | + ((session->sock.flags & COAP_SOCKET_WANT_READ) ? + EPOLLIN : 0), + __func__); +#endif /* COAP_EPOLL_SUPPORT */ + } + } + + if (r == 0) + goto error; + + *connected = SSL_is_init_finished(ssl); + + return ssl; + +error: + if (ssl) + SSL_free(ssl); + return NULL; +} +#endif /* COAP_SERVER_SUPPORT */ + +void coap_tls_free_session(coap_session_t *session) { + SSL *ssl = (SSL *)session->tls; + if (ssl) { + if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) { + int r = SSL_shutdown(ssl); + if (r == 0) r = SSL_shutdown(ssl); + } + SSL_free(ssl); + session->tls = NULL; + if (session->context) + coap_handle_event(session->context, COAP_EVENT_DTLS_CLOSED, session); + } +} + +ssize_t coap_tls_write(coap_session_t *session, + const uint8_t *data, + size_t data_len +) { + SSL *ssl = (SSL *)session->tls; + int r, in_init; + + if (ssl == NULL) + return -1; + + in_init = !SSL_is_init_finished(ssl); + session->dtls_event = -1; + r = SSL_write(ssl, data, (int)data_len); + + if (r <= 0) { + int err = SSL_get_error(ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + if (in_init && SSL_is_init_finished(ssl)) { + coap_log(COAP_LOG_CIPHERS, "* %s: Using cipher: %s\n", + coap_session_str(session), SSL_get_cipher_name(ssl)); + coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session); + coap_session_send_csm(session); + } + if (err == SSL_ERROR_WANT_READ) + session->sock.flags |= COAP_SOCKET_WANT_READ; + if (err == SSL_ERROR_WANT_WRITE) { + session->sock.flags |= COAP_SOCKET_WANT_WRITE; +#ifdef COAP_EPOLL_SUPPORT + coap_epoll_ctl_mod(&session->sock, + EPOLLOUT | + ((session->sock.flags & COAP_SOCKET_WANT_READ) ? + EPOLLIN : 0), + __func__); +#endif /* COAP_EPOLL_SUPPORT */ + } + r = 0; + } else { + coap_log(LOG_INFO, "***%s: coap_tls_write: cannot send PDU\n", + coap_session_str(session)); + if (err == SSL_ERROR_ZERO_RETURN) + session->dtls_event = COAP_EVENT_DTLS_CLOSED; + else if (err == SSL_ERROR_SSL) + session->dtls_event = COAP_EVENT_DTLS_ERROR; + r = -1; + } + } else if (in_init && SSL_is_init_finished(ssl)) { + coap_log(COAP_LOG_CIPHERS, "* %s: Using cipher: %s\n", + coap_session_str(session), SSL_get_cipher_name(ssl)); + coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session); + coap_session_send_csm(session); + } + + if (session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(session->context, session->dtls_event, session); + if (session->dtls_event == COAP_EVENT_DTLS_ERROR || + session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + r = -1; + } + } + + return r; +} + +ssize_t coap_tls_read(coap_session_t *session, + uint8_t *data, + size_t data_len +) { + SSL *ssl = (SSL *)session->tls; + int r, in_init; + + if (ssl == NULL) + return -1; + + in_init = !SSL_is_init_finished(ssl); + session->dtls_event = -1; + r = SSL_read(ssl, data, (int)data_len); + if (r <= 0) { + int err = SSL_get_error(ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + if (in_init && SSL_is_init_finished(ssl)) { + coap_log(COAP_LOG_CIPHERS, "* %s: Using cipher: %s\n", + coap_session_str(session), SSL_get_cipher_name(ssl)); + coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session); + coap_session_send_csm(session); + } + if (err == SSL_ERROR_WANT_READ) + session->sock.flags |= COAP_SOCKET_WANT_READ; + if (err == SSL_ERROR_WANT_WRITE) { + session->sock.flags |= COAP_SOCKET_WANT_WRITE; +#ifdef COAP_EPOLL_SUPPORT + coap_epoll_ctl_mod(&session->sock, + EPOLLOUT | + ((session->sock.flags & COAP_SOCKET_WANT_READ) ? + EPOLLIN : 0), + __func__); +#endif /* COAP_EPOLL_SUPPORT */ + } + r = 0; + } else { + if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */ + session->dtls_event = COAP_EVENT_DTLS_CLOSED; + else if (err == SSL_ERROR_SSL) + session->dtls_event = COAP_EVENT_DTLS_ERROR; + r = -1; + } + } else if (in_init && SSL_is_init_finished(ssl)) { + coap_log(COAP_LOG_CIPHERS, "* %s: Using cipher: %s\n", + coap_session_str(session), SSL_get_cipher_name(ssl)); + coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session); + coap_session_send_csm(session); + } + + if (session->dtls_event >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(session->context, session->dtls_event, session); + if (session->dtls_event == COAP_EVENT_DTLS_ERROR || + session->dtls_event == COAP_EVENT_DTLS_CLOSED) { + coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + r = -1; + } + } + + return r; +} +#endif /* !COAP_DISABLE_TCP */ + +#if COAP_SERVER_SUPPORT +coap_digest_ctx_t * +coap_digest_setup(void) { + EVP_MD_CTX *digest_ctx = EVP_MD_CTX_new(); + + if (digest_ctx) { + EVP_DigestInit_ex(digest_ctx, EVP_sha256(), NULL); + } + return digest_ctx; +} + +void +coap_digest_free(coap_digest_ctx_t *digest_ctx) { + EVP_MD_CTX_free(digest_ctx); +} + +int +coap_digest_update(coap_digest_ctx_t *digest_ctx, + const uint8_t *data, + size_t data_len) { + return EVP_DigestUpdate(digest_ctx, data, data_len); +} + +int +coap_digest_final(coap_digest_ctx_t *digest_ctx, + coap_digest_t *digest_buffer) { + unsigned int size = sizeof(coap_digest_t); + int ret = EVP_DigestFinal_ex(digest_ctx, (uint8_t*)digest_buffer, &size); + + coap_digest_free(digest_ctx); + return ret; +} +#endif /* COAP_SERVER_SUPPORT */ + +#else /* !HAVE_OPENSSL */ + +#ifdef __clang__ +/* Make compilers happy that do not like empty modules. As this function is + * never used, we ignore -Wunused-function at the end of compiling this file + */ +#pragma GCC diagnostic ignored "-Wunused-function" +#endif +static inline void dummy(void) { +} + +#endif /* HAVE_OPENSSL */ diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_option.c b/examples/espidf-coap-server/components/libcoap/src/coap_option.c new file mode 100644 index 000000000..216f7a44f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_option.c @@ -0,0 +1,605 @@ +/* + * coap_option.c -- helpers for handling options in CoAP PDUs + * + * Copyright (C) 2010-2013,2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_option.c + * @brief CoAP option handling functions + */ + +#include "coap3/coap_internal.h" + +#include +#include + +#define ADVANCE_OPT(o,e,step) if ((e) < step) { \ + coap_log(LOG_DEBUG, "cannot advance opt past end\n"); \ + return 0; \ + } else { \ + (e) -= step; \ + (o) = ((o)) + step; \ + } + +/* + * Used to prevent access to *opt when pointing to after end of buffer + * after doing a ADVANCE_OPT() + */ +#define ADVANCE_OPT_CHECK(o,e,step) do { \ + ADVANCE_OPT(o,e,step); \ + if ((e) < 1) \ + return 0; \ + } while (0) + +size_t +coap_opt_parse(const coap_opt_t *opt, size_t length, coap_option_t *result) { + + const coap_opt_t *opt_start = opt; /* store where parsing starts */ + + assert(opt); assert(result); + + if (length < 1) + return 0; + + result->delta = (*opt & 0xf0) >> 4; + result->length = *opt & 0x0f; + + switch(result->delta) { + case 15: + if (*opt != COAP_PAYLOAD_START) { + coap_log(LOG_DEBUG, "ignored reserved option delta 15\n"); + } + return 0; + case 14: + /* Handle two-byte value: First, the MSB + 269 is stored as delta value. + * After that, the option pointer is advanced to the LSB which is handled + * just like case delta == 13. */ + ADVANCE_OPT_CHECK(opt,length,1); + result->delta = ((*opt & 0xff) << 8) + 269; + if (result->delta < 269) { + coap_log(LOG_DEBUG, "delta too large\n"); + return 0; + } + /* fall through */ + case 13: + ADVANCE_OPT_CHECK(opt,length,1); + result->delta += *opt & 0xff; + break; + + default: + ; + } + + switch(result->length) { + case 15: + coap_log(LOG_DEBUG, "found reserved option length 15\n"); + return 0; + case 14: + /* Handle two-byte value: First, the MSB + 269 is stored as delta value. + * After that, the option pointer is advanced to the LSB which is handled + * just like case delta == 13. */ + ADVANCE_OPT_CHECK(opt,length,1); + result->length = ((*opt & 0xff) << 8) + 269; + /* fall through */ + case 13: + ADVANCE_OPT_CHECK(opt,length,1); + result->length += *opt & 0xff; + break; + + default: + ; + } + + /* ADVANCE_OPT() is correct here */ + ADVANCE_OPT(opt,length,1); + /* opt now points to value, if present */ + + result->value = opt; + if (length < result->length) { + coap_log(LOG_DEBUG, "invalid option length\n"); + return 0; + } + +#undef ADVANCE_OPT +#undef ADVANCE_OPT_CHECK + + return (opt + result->length) - opt_start; +} + +coap_opt_iterator_t * +coap_option_iterator_init(const coap_pdu_t *pdu, coap_opt_iterator_t *oi, + const coap_opt_filter_t *filter) { + assert(pdu); + assert(pdu->token); + assert(oi); + + memset(oi, 0, sizeof(coap_opt_iterator_t)); + + oi->next_option = pdu->token + pdu->token_length; + if (pdu->token + pdu->used_size <= oi->next_option) { + oi->bad = 1; + return NULL; + } + + oi->length = pdu->used_size - pdu->token_length; + + if (filter) { + memcpy(&oi->filter, filter, sizeof(coap_opt_filter_t)); + oi->filtered = 1; + } + return oi; +} + +COAP_STATIC_INLINE int +opt_finished(coap_opt_iterator_t *oi) { + assert(oi); + + if (oi->bad || oi->length == 0 || + !oi->next_option || *oi->next_option == COAP_PAYLOAD_START) { + oi->bad = 1; + } + + return oi->bad; +} + +coap_opt_t * +coap_option_next(coap_opt_iterator_t *oi) { + coap_option_t option; + coap_opt_t *current_opt = NULL; + size_t optsize; + int b; /* to store result of coap_option_getb() */ + + assert(oi); + + if (opt_finished(oi)) + return NULL; + + while (1) { + /* oi->option always points to the next option to deliver; as + * opt_finished() filters out any bad conditions, we can assume that + * oi->option is valid. */ + current_opt = oi->next_option; + + /* Advance internal pointer to next option, skipping any option that + * is not included in oi->filter. */ + optsize = coap_opt_parse(oi->next_option, oi->length, &option); + if (optsize) { + assert(optsize <= oi->length); + + oi->next_option += optsize; + oi->length -= optsize; + + oi->number += option.delta; + } else { /* current option is malformed */ + oi->bad = 1; + return NULL; + } + + /* Exit the while loop when: + * - no filtering is done at all + * - the filter matches for the current option + * - the filter is too small for the current option number + */ + if (!oi->filtered || + (b = coap_option_filter_get(&oi->filter, oi->number)) > 0) + break; + else if (b < 0) { /* filter too small, cannot proceed */ + oi->bad = 1; + return NULL; + } + } + + return current_opt; +} + +coap_opt_t * +coap_check_option(const coap_pdu_t *pdu, coap_option_num_t number, + coap_opt_iterator_t *oi) { + coap_opt_filter_t f; + + coap_option_filter_clear(&f); + coap_option_filter_set(&f, number); + + coap_option_iterator_init(pdu, oi, &f); + + return coap_option_next(oi); +} + +uint32_t +coap_opt_length(const coap_opt_t *opt) { + uint32_t length; + + length = *opt & 0x0f; + switch (*opt & 0xf0) { + case 0xf0: + coap_log(LOG_DEBUG, "illegal option delta\n"); + return 0; + case 0xe0: + ++opt; + /* fall through */ + /* to skip another byte */ + case 0xd0: + ++opt; + /* fall through */ + /* to skip another byte */ + default: + ++opt; + } + + switch (length) { + case 0x0f: + coap_log(LOG_DEBUG, "illegal option length\n"); + return 0; + case 0x0e: + length = (*opt++ << 8) + 269; + /* fall through */ + case 0x0d: + length += *opt++; + break; + default: + ; + } + return length; +} + +const uint8_t * +coap_opt_value(const coap_opt_t *opt) { + size_t ofs = 1; + + switch (*opt & 0xf0) { + case 0xf0: + coap_log(LOG_DEBUG, "illegal option delta\n"); + return 0; + case 0xe0: + ++ofs; + /* fall through */ + case 0xd0: + ++ofs; + break; + default: + ; + } + + switch (*opt & 0x0f) { + case 0x0f: + coap_log(LOG_DEBUG, "illegal option length\n"); + return 0; + case 0x0e: + ++ofs; + /* fall through */ + case 0x0d: + ++ofs; + break; + default: + ; + } + + return (const uint8_t *)opt + ofs; +} + +size_t +coap_opt_size(const coap_opt_t *opt) { + coap_option_t option; + + /* we must assume that opt is encoded correctly */ + return coap_opt_parse(opt, (size_t)-1, &option); +} + +size_t +coap_opt_setheader(coap_opt_t *opt, size_t maxlen, + uint16_t delta, size_t length) { + size_t skip = 0; + + assert(opt); + + if (maxlen == 0) /* need at least one byte */ + return 0; + + if (delta < 13) { + opt[0] = (coap_opt_t)(delta << 4); + } else if (delta < 269) { + if (maxlen < 2) { + coap_log(LOG_DEBUG, "insufficient space to encode option delta %d\n", + delta); + return 0; + } + + opt[0] = 0xd0; + opt[++skip] = (coap_opt_t)(delta - 13); + } else { + if (maxlen < 3) { + coap_log(LOG_DEBUG, "insufficient space to encode option delta %d\n", + delta); + return 0; + } + + opt[0] = 0xe0; + opt[++skip] = ((delta - 269) >> 8) & 0xff; + opt[++skip] = (delta - 269) & 0xff; + } + + if (length < 13) { + opt[0] |= length & 0x0f; + } else if (length < 269) { + if (maxlen < skip + 2) { + coap_log(LOG_DEBUG, "insufficient space to encode option length %zu\n", + length); + return 0; + } + + opt[0] |= 0x0d; + opt[++skip] = (coap_opt_t)(length - 13); + } else { + if (maxlen < skip + 3) { + coap_log(LOG_DEBUG, "insufficient space to encode option delta %d\n", + delta); + return 0; + } + + opt[0] |= 0x0e; + opt[++skip] = ((length - 269) >> 8) & 0xff; + opt[++skip] = (length - 269) & 0xff; + } + + return skip + 1; +} + +size_t +coap_opt_encode_size(uint16_t delta, size_t length) { + size_t n = 1; + + if (delta >= 13) { + if (delta < 269) + n += 1; + else + n += 2; + } + + if (length >= 13) { + if (length < 269) + n += 1; + else + n += 2; + } + + return n + length; +} + +size_t +coap_opt_encode(coap_opt_t *opt, size_t maxlen, uint16_t delta, + const uint8_t *val, size_t length) { + size_t l = 1; + + l = coap_opt_setheader(opt, maxlen, delta, length); + assert(l <= maxlen); + + if (!l) { + coap_log(LOG_DEBUG, "coap_opt_encode: cannot set option header\n"); + return 0; + } + + maxlen -= l; + opt += l; + + if (maxlen < length) { + coap_log(LOG_DEBUG, "coap_opt_encode: option too large for buffer\n"); + return 0; + } + + if (val) /* better be safe here */ + memcpy(opt, val, length); + + return l + length; +} + +#define LONG_MASK ((1 << COAP_OPT_FILTER_LONG) - 1) +#define SHORT_MASK \ + (~LONG_MASK & ((1 << (COAP_OPT_FILTER_LONG + COAP_OPT_FILTER_SHORT)) - 1)) + +/** Returns true iff @p number denotes an option number larger than 255. */ +COAP_STATIC_INLINE int +is_long_option(coap_option_num_t number) { return number > 255; } + +/** Operation specifiers for coap_filter_op(). */ +enum filter_op_t { FILTER_SET, FILTER_CLEAR, FILTER_GET }; + +/** + * Applies @p op on @p filter with respect to @p number. The following + * operations are defined: + * + * FILTER_SET: Store @p number into an empty slot in @p filter. Returns + * @c 1 on success, or @c 0 if no spare slot was available. + * + * FILTER_CLEAR: Remove @p number from filter if it exists. + * + * FILTER_GET: Search for @p number in @p filter. Returns @c 1 if found, + * or @c 0 if not found. + * + * @param filter The filter object. + * @param number The option number to set, get or clear in @p filter. + * @param op The operation to apply to @p filter and @p number. + * + * @return 1 on success, and 0 when FILTER_GET yields no + * hit or no free slot is available to store @p number with FILTER_SET. + */ +static int +coap_option_filter_op(coap_opt_filter_t *filter, + coap_option_num_t number, + enum filter_op_t op) { + size_t lindex = 0; + coap_opt_filter_t *of = filter; + uint16_t nr, mask = 0; + + if (is_long_option(number)) { + mask = LONG_MASK; + + for (nr = 1; lindex < COAP_OPT_FILTER_LONG; nr <<= 1, lindex++) { + + if (((of->mask & nr) > 0) && (of->long_opts[lindex] == number)) { + if (op == FILTER_CLEAR) { + of->mask &= ~nr; + } + + return 1; + } + } + } else { + mask = SHORT_MASK; + + for (nr = 1 << COAP_OPT_FILTER_LONG; lindex < COAP_OPT_FILTER_SHORT; + nr <<= 1, lindex++) { + + if (((of->mask & nr) > 0) && (of->short_opts[lindex] == (number & 0xff))) { + if (op == FILTER_CLEAR) { + of->mask &= ~nr; + } + + return 1; + } + } + } + + /* number was not found, so there is nothing to do if op is CLEAR or GET */ + if ((op == FILTER_CLEAR) || (op == FILTER_GET)) { + return 0; + } + + /* handle FILTER_SET: */ + + lindex = coap_fls(~of->mask & mask); + if (!lindex) { + return 0; + } + + if (is_long_option(number)) { + of->long_opts[lindex - 1] = number; + } else { + of->short_opts[lindex - COAP_OPT_FILTER_LONG - 1] = (uint8_t)number; + } + + of->mask |= 1 << (lindex - 1); + + return 1; +} + +void +coap_option_filter_clear(coap_opt_filter_t *filter) { + memset(filter, 0, sizeof(coap_opt_filter_t)); +} + +int +coap_option_filter_set(coap_opt_filter_t *filter, coap_option_num_t option) { + return coap_option_filter_op(filter, option, FILTER_SET); +} + +int +coap_option_filter_unset(coap_opt_filter_t *filter, coap_option_num_t option) { + return coap_option_filter_op(filter, option, FILTER_CLEAR); +} + +int +coap_option_filter_get(coap_opt_filter_t *filter, coap_option_num_t option) { + return coap_option_filter_op(filter, option, FILTER_GET); +} + +coap_optlist_t * +coap_new_optlist(uint16_t number, + size_t length, + const uint8_t *data +) { + coap_optlist_t *node; + +#ifdef WITH_LWIP + if (length > MEMP_LEN_COAPOPTLIST) { + coap_log(LOG_CRIT, + "coap_new_optlist: size too large (%zu > MEMP_LEN_COAPOPTLIST)\n", + length); + return NULL; + } +#endif /* WITH_LWIP */ + node = coap_malloc_type(COAP_OPTLIST, sizeof(coap_optlist_t) + length); + + if (node) { + memset(node, 0, (sizeof(coap_optlist_t) + length)); + node->number = number; + node->length = length; + node->data = (uint8_t *)&node[1]; + memcpy(node->data, data, length); + } else { + coap_log(LOG_WARNING, "coap_new_optlist: malloc failure\n"); + } + + return node; +} + +static int +order_opts(void *a, void *b) { + coap_optlist_t *o1 = (coap_optlist_t *)a; + coap_optlist_t *o2 = (coap_optlist_t *)b; + + if (!a || !b) + return a < b ? -1 : 1; + + return (int)(o1->number - o2->number); +} + +int +coap_add_optlist_pdu(coap_pdu_t *pdu, coap_optlist_t** options) { + coap_optlist_t *opt; + + if (options && *options) { + if (pdu->data) { + coap_log(LOG_WARNING, + "coap_add_optlist_pdu: PDU already contains data\n"); + return 0; + } + /* sort options for delta encoding */ + LL_SORT((*options), order_opts); + + LL_FOREACH((*options), opt) { + coap_add_option_internal(pdu, opt->number, opt->length, opt->data); + } + return 1; + } + return 0; +} + +int +coap_insert_optlist(coap_optlist_t **head, coap_optlist_t *node) { + if (!node) { + coap_log(LOG_DEBUG, "optlist not provided\n"); + } else { + /* must append at the list end to avoid re-ordering of + * options during sort */ + LL_APPEND((*head), node); + } + + return node != NULL; +} + +static int +coap_internal_delete(coap_optlist_t *node) { + if (node) { + coap_free_type(COAP_OPTLIST, node); + } + return 1; +} + +void +coap_delete_optlist(coap_optlist_t *queue) { + coap_optlist_t *elt, *tmp; + + if (!queue) + return; + + LL_FOREACH_SAFE(queue, elt, tmp) { + coap_internal_delete(elt); + } +} + diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_prng.c b/examples/espidf-coap-server/components/libcoap/src/coap_prng.c new file mode 100644 index 000000000..0cddc252c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_prng.c @@ -0,0 +1,113 @@ +/* + * coap_prng.c -- random number generation + * + * Copyright (C) 2020 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README + * for terms of use. + */ + +/** + * @file coap_prng.c + * @brief Pseudo Random Number functions + */ + +#include "coap3/coap_internal.h" + +#ifdef HAVE_GETRANDOM +#include +#else /* !HAVE_GETRANDOM */ +#include +#endif /* !HAVE_GETRANDOM */ + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +#include +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + +#if defined(_WIN32) + +errno_t __cdecl rand_s( _Out_ unsigned int* _RandomValue ); +/** + * Fills \p buf with \p len random bytes. This is the default implementation for + * coap_prng(). You might want to change coap_prng_impl() to use a better + * PRNG on your specific platform. + */ +COAP_STATIC_INLINE int +coap_prng_impl( unsigned char *buf, size_t len ) { + while ( len != 0 ) { + uint32_t r = 0; + size_t i; + if ( rand_s( &r ) != 0 ) + return 0; + for ( i = 0; i < len && i < 4; i++ ) { + *buf++ = (uint8_t)r; + r >>= 8; + } + len -= i; + } + return 1; +} + +#endif /* _WIN32 */ + +/* + * This, or any user provided alternative, function is expected to + * return 0 on failure and 1 on success. + */ +static int +coap_prng_default(void *buf, size_t len) { +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + /* mbedtls_hardware_poll() returns 0 on success */ + return (mbedtls_hardware_poll(NULL, buf, len, NULL) ? 0 : 1); +#else /* !MBEDTLS_ENTROPY_HARDWARE_ALT */ +#ifdef HAVE_GETRANDOM + return (getrandom(buf, len, 0) > 0) ? 1 : 0; +#else /* !HAVE_GETRANDOM */ +#if defined(_WIN32) + return coap_prng_impl(buf,len); +#else /* !_WIN32 */ + unsigned char *dst = (unsigned char *)buf; + while (len--) + *dst++ = rand() & 0xFF; + return 1; +#endif /* !_WIN32 */ +#endif /* !HAVE_GETRANDOM */ +#endif /* !MBEDTLS_ENTROPY_HARDWARE_ALT */ +} + +static coap_rand_func_t rand_func = coap_prng_default; + +#if defined(WITH_CONTIKI) + +#elif defined(WITH_LWIP) && defined(LWIP_RAND) + +#else + +void +coap_set_prng(coap_rand_func_t rng) { + rand_func = rng; +} + +void +coap_prng_init(unsigned int seed) { +#ifdef HAVE_GETRANDOM + /* No seed to seed the random source if getrandom() is used, + * see dtls_prng(). */ + (void)seed; +#else /* !HAVE_GETRANDOM */ + srand(seed); +#endif /* !HAVE_GETRANDOM */ +} + +int +coap_prng(void *buf, size_t len) { + if (!rand_func) { + return 0; + } + + return rand_func(buf, len); +} + +#endif diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_session.c b/examples/espidf-coap-server/components/libcoap/src/coap_session.c new file mode 100644 index 000000000..fcc59aef9 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_session.c @@ -0,0 +1,1709 @@ +/* coap_session.c -- Session management for libcoap + * + * Copyright (C) 2017 Jean-Claue Michelou + * Copyright (C) 2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_session.c + * @brief Session handling functions + */ + +#include "coap3/coap_internal.h" + +#ifndef COAP_SESSION_C_ +#define COAP_SESSION_C_ + +#include + +#ifdef COAP_EPOLL_SUPPORT +#include +#include +#endif /* COAP_EPOLL_SUPPORT */ +#include + +#ifdef HAVE_INTTYPES_H +#include +#else /* ! HAVE_INTTYPES_H */ +#define PRIu32 "u" +#endif /* ! HAVE_INTTYPES_H */ + +void +coap_session_set_ack_timeout(coap_session_t *session, coap_fixed_point_t value) { + if (value.integer_part > 0 && value.fractional_part < 1000) { + session->ack_timeout = value; + coap_log(LOG_DEBUG, "***%s: session ack_timeout set to %u.%03u\n", + coap_session_str(session), session->ack_timeout.integer_part, + session->ack_timeout.fractional_part); + } +} + +void +coap_session_set_ack_random_factor(coap_session_t *session, + coap_fixed_point_t value) { + if (value.integer_part > 0 && value.fractional_part < 1000) { + session->ack_random_factor = value; + coap_log(LOG_DEBUG, "***%s: session ack_random_factor set to %u.%03u\n", + coap_session_str(session), session->ack_random_factor.integer_part, + session->ack_random_factor.fractional_part); + } +} + +void +coap_session_set_max_retransmit(coap_session_t *session, uint16_t value) { + if (value > 0) { + session->max_retransmit = value; + coap_log(LOG_DEBUG, "***%s: session max_retransmit set to %u\n", + coap_session_str(session), session->max_retransmit); + } +} + +void +coap_session_set_nstart(coap_session_t *session, uint16_t value) { + if (value > 0) { + session->nstart = value; + coap_log(LOG_DEBUG, "***%s: session nstart set to %u\n", + coap_session_str(session), session->nstart); + } +} + +void +coap_session_set_default_leisure(coap_session_t *session, + coap_fixed_point_t value) { + if (value.integer_part > 0 && value.fractional_part < 1000) { + session->default_leisure = value; + coap_log(LOG_DEBUG, "***%s: session default_leisure set to %u.%03u\n", + coap_session_str(session), session->default_leisure.integer_part, + session->default_leisure.fractional_part); + } +} + +void +coap_session_set_probing_rate(coap_session_t *session, uint32_t value) { + if (value > 0) { + session->probing_rate = value; + coap_log(LOG_DEBUG, "***%s: session probing_rate set to %" PRIu32 "\n", + coap_session_str(session), session->probing_rate); + } +} + +coap_fixed_point_t +coap_session_get_ack_timeout(const coap_session_t *session) { + return session->ack_timeout; +} + +coap_fixed_point_t +coap_session_get_ack_random_factor(const coap_session_t *session) { + return session->ack_random_factor; +} + +uint16_t +coap_session_get_max_retransmit(const coap_session_t *session) { + return session->max_retransmit; +} + +uint16_t +coap_session_get_nstart(const coap_session_t *session) { + return session->nstart; +} + +coap_fixed_point_t +coap_session_get_default_leisure(const coap_session_t *session) { + return session->default_leisure; +} + +uint32_t +coap_session_get_probing_rate(const coap_session_t *session) { + return session->probing_rate; +} + +coap_session_t * +coap_session_reference(coap_session_t *session) { + ++session->ref; + return session; +} + +void +coap_session_release(coap_session_t *session) { + if (session) { +#ifndef __COVERITY__ + assert(session->ref > 0); + if (session->ref > 0) + --session->ref; + if (session->ref == 0 && session->type == COAP_SESSION_TYPE_CLIENT) + coap_session_free(session); +#else /* __COVERITY__ */ + /* Coverity scan is fooled by the reference counter leading to + * false positives for USE_AFTER_FREE. */ + --session->ref; + __coverity_negative_sink__(session->ref); + /* Indicate that resources are released properly. */ + if (session->ref == 0 && session->type == COAP_SESSION_TYPE_CLIENT) { + __coverity_free__(session); + } +#endif /* __COVERITY__ */ + } +} + +void +coap_session_set_app_data(coap_session_t *session, void *app_data) { + assert(session); + session->app = app_data; +} + +void * +coap_session_get_app_data(const coap_session_t *session) { + assert(session); + return session->app; +} + +static coap_session_t * +coap_make_session(coap_proto_t proto, coap_session_type_t type, + const coap_addr_hash_t *addr_hash, + const coap_address_t *local_addr, + const coap_address_t *remote_addr, int ifindex, + coap_context_t *context, coap_endpoint_t *endpoint) { + coap_session_t *session = (coap_session_t*)coap_malloc_type(COAP_SESSION, + sizeof(coap_session_t)); +#if ! COAP_SERVER_SUPPORT + (void)endpoint; +#endif /* ! COAP_SERVER_SUPPORT */ + if (!session) + return NULL; + memset(session, 0, sizeof(*session)); + session->proto = proto; + session->type = type; + if (addr_hash) + memcpy(&session->addr_hash, addr_hash, sizeof(session->addr_hash)); + else + memset(&session->addr_hash, 0, sizeof(session->addr_hash)); + if (local_addr) + coap_address_copy(&session->addr_info.local, local_addr); + else + coap_address_init(&session->addr_info.local); + if (remote_addr) + coap_address_copy(&session->addr_info.remote, remote_addr); + else + coap_address_init(&session->addr_info.remote); + session->ifindex = ifindex; + session->context = context; +#if COAP_SERVER_SUPPORT + session->endpoint = endpoint; + if (endpoint) + session->mtu = endpoint->default_mtu; + else +#endif /* COAP_SERVER_SUPPORT */ + session->mtu = COAP_DEFAULT_MTU; + session->block_mode = context->block_mode; + if (proto == COAP_PROTO_DTLS) { + session->tls_overhead = 29; + if (session->tls_overhead >= session->mtu) { + session->tls_overhead = session->mtu; + coap_log(LOG_ERR, "DTLS overhead exceeds MTU\n"); + } + } + session->ack_timeout = COAP_DEFAULT_ACK_TIMEOUT; + session->ack_random_factor = COAP_DEFAULT_ACK_RANDOM_FACTOR; + session->max_retransmit = COAP_DEFAULT_MAX_RETRANSMIT; + session->nstart = COAP_DEFAULT_NSTART; + session->default_leisure = COAP_DEFAULT_DEFAULT_LEISURE; + session->probing_rate = COAP_DEFAULT_PROBING_RATE; + session->dtls_event = -1; + session->last_ping_mid = COAP_INVALID_MID; + session->last_ack_mid = COAP_INVALID_MID; + session->last_con_mid = COAP_INVALID_MID; + + /* Randomly initialize */ + coap_prng((unsigned char *)&session->tx_mid, sizeof(session->tx_mid)); + coap_prng((unsigned char *)&session->tx_rtag, sizeof(session->tx_rtag)); + + return session; +} + +void coap_session_mfree(coap_session_t *session) { + coap_queue_t *q, *tmp; + coap_lg_xmit_t *lq, *ltmp; + +#if COAP_CLIENT_SUPPORT + coap_lg_crcv_t *cq, *etmp; + + /* Need to do this before (D)TLS and socket is closed down */ + LL_FOREACH_SAFE(session->lg_crcv, cq, etmp) { + if (cq->observe_set && session->no_observe_cancel == 0) { + /* Need to close down observe */ + if (coap_cancel_observe(session, cq->app_token, COAP_MESSAGE_NON)) { + /* Need to delete node we set up for NON */ + coap_queue_t *queue = session->context->sendqueue; + + while (queue) { + if (queue->session == session) { + coap_delete_node(queue); + break; + } + queue = queue->next; + } + } + } + LL_DELETE(session->lg_crcv, cq); + coap_block_delete_lg_crcv(session, cq); + } +#endif /* COAP_CLIENT_SUPPORT */ + + if (session->partial_pdu) + coap_delete_pdu(session->partial_pdu); + if (session->proto == COAP_PROTO_DTLS) + coap_dtls_free_session(session); +#if !COAP_DISABLE_TCP + else if (session->proto == COAP_PROTO_TLS) + coap_tls_free_session(session); +#endif /* !COAP_DISABLE_TCP */ + if (session->sock.flags != COAP_SOCKET_EMPTY) + coap_socket_close(&session->sock); + if (session->psk_identity) + coap_free(session->psk_identity); + if (session->psk_key) + coap_free(session->psk_key); + if (session->psk_hint) + coap_free(session->psk_hint); + +#if COAP_SERVER_SUPPORT + coap_cache_entry_t *cp, *ctmp; + HASH_ITER(hh, session->context->cache, cp, ctmp) { + /* cp->session is NULL if not session based */ + if (cp->session == session) { + coap_delete_cache_entry(session->context, cp); + } + } +#endif /* COAP_SERVER_SUPPORT */ + LL_FOREACH_SAFE(session->delayqueue, q, tmp) { + if (q->pdu->type==COAP_MESSAGE_CON && session->context && session->context->nack_handler) + session->context->nack_handler(session, q->pdu, session->proto == COAP_PROTO_DTLS ? COAP_NACK_TLS_FAILED : COAP_NACK_NOT_DELIVERABLE, q->id); + coap_delete_node(q); + } + LL_FOREACH_SAFE(session->lg_xmit, lq, ltmp) { + LL_DELETE(session->lg_xmit, lq); + coap_block_delete_lg_xmit(session, lq); + } +#if COAP_SERVER_SUPPORT + coap_lg_srcv_t *sq, *stmp; + + LL_FOREACH_SAFE(session->lg_srcv, sq, stmp) { + LL_DELETE(session->lg_srcv, sq); + coap_block_delete_lg_srcv(session, sq); + } +#endif /* COAP_SERVER_SUPPORT */ +} + +void coap_session_free(coap_session_t *session) { + if (!session) + return; + assert(session->ref == 0); + if (session->ref) + return; + coap_session_mfree(session); +#if COAP_SERVER_SUPPORT + if (session->endpoint) { + if (session->endpoint->sessions) + SESSIONS_DELETE(session->endpoint->sessions, session); + } else +#endif /* COAP_SERVER_SUPPORT */ +#if COAP_CLIENT_SUPPORT + if (session->context) { + if (session->context->sessions) + SESSIONS_DELETE(session->context->sessions, session); + } +#endif /* COAP_CLIENT_SUPPORT */ + coap_delete_bin_const(session->last_token); + coap_log(LOG_DEBUG, "***%s: session %p: closed\n", coap_session_str(session), + (void *)session); + + coap_free_type(COAP_SESSION, session); +} + +static size_t +coap_session_max_pdu_size_internal(const coap_session_t *session, + size_t max_with_header) { +#if COAP_DISABLE_TCP + return max_with_header > 4 ? max_with_header - 4 : 0; +#else /* !COAP_DISABLE_TCP */ + if (COAP_PROTO_NOT_RELIABLE(session->proto)) + return max_with_header > 4 ? max_with_header - 4 : 0; + /* we must assume there is no token to be on the safe side */ + if (max_with_header <= 2) + return 0; + else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP0 + 2) + return max_with_header - 2; + else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP8 + 3) + return max_with_header - 3; + else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP16 + 4) + return max_with_header - 4; + else + return max_with_header - 6; +#endif /* !COAP_DISABLE_TCP */ +} + +size_t +coap_session_max_pdu_rcv_size(const coap_session_t *session) { + if (session->csm_rcv_mtu) + return coap_session_max_pdu_size_internal(session, + (size_t)(session->csm_rcv_mtu)); + + return coap_session_max_pdu_size_internal(session, + (size_t)(session->mtu - session->tls_overhead)); +} + +size_t +coap_session_max_pdu_size(const coap_session_t *session) { + size_t max_with_header; + +#if COAP_CLIENT_SUPPORT + /* + * Delay if session->doing_first is set. + * E.g. Reliable and CSM not in yet for checking block support + */ + coap_session_t *session_rw; + + /* + * Need to do this to not get a compiler warning about const parameters + * but need to maintain source code backward compatibility + */ + memcpy(&session_rw, &session, sizeof(session_rw)); + if (coap_client_delay_first(session_rw) == 0) { + coap_log(LOG_DEBUG, "coap_client_delay_first: timeout\n"); + /* Have to go with the defaults */ + } +#endif /* COAP_CLIENT_SUPPORT */ + + max_with_header = (size_t)(session->mtu - session->tls_overhead); + + return coap_session_max_pdu_size_internal(session, max_with_header); +} + +void coap_session_set_mtu(coap_session_t *session, unsigned mtu) { +#if defined(WITH_CONTIKI) || defined(WITH_LWIP) + if (mtu > COAP_MAX_MESSAGE_SIZE_TCP16 + 4) + mtu = COAP_MAX_MESSAGE_SIZE_TCP16 + 4; +#endif + if (mtu < 64) + mtu = 64; + session->mtu = mtu; + if (session->tls_overhead >= session->mtu) { + session->tls_overhead = session->mtu; + coap_log(LOG_ERR, "DTLS overhead exceeds MTU\n"); + } +} + +ssize_t coap_session_send(coap_session_t *session, const uint8_t *data, size_t datalen) { + ssize_t bytes_written; + + coap_socket_t *sock = &session->sock; +#if COAP_SERVER_SUPPORT + if (sock->flags == COAP_SOCKET_EMPTY) { + assert(session->endpoint != NULL); + sock = &session->endpoint->sock; + } +#endif /* COAP_SERVER_SUPPORT */ + + bytes_written = coap_socket_send(sock, session, data, datalen); + if (bytes_written == (ssize_t)datalen) { + coap_ticks(&session->last_rx_tx); + coap_log(LOG_DEBUG, "* %s: sent %zd bytes\n", + coap_session_str(session), datalen); + } else { + coap_log(LOG_DEBUG, "* %s: failed to send %zd bytes\n", + coap_session_str(session), datalen); + } + return bytes_written; +} + +ssize_t coap_session_write(coap_session_t *session, const uint8_t *data, size_t datalen) { + ssize_t bytes_written = coap_socket_write(&session->sock, data, datalen); + if (bytes_written > 0) { + coap_ticks(&session->last_rx_tx); + coap_log(LOG_DEBUG, "* %s: sent %zd bytes\n", + coap_session_str(session), bytes_written); + } else if (bytes_written < 0) { + coap_log(LOG_DEBUG, "* %s: failed to send %zd bytes\n", + coap_session_str(session), datalen ); + } + return bytes_written; +} + +ssize_t +coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, + coap_queue_t *node) +{ + if ( node ) { + coap_queue_t *removed = NULL; + coap_remove_from_queue(&session->context->sendqueue, session, node->id, &removed); + assert(removed == node); + coap_session_release(node->session); + node->session = NULL; + node->t = 0; + } else { + if (COAP_PROTO_NOT_RELIABLE(session->proto)) { + coap_queue_t *q = NULL; + /* Check same mid is not getting re-used in violation of RFC7252 */ + LL_FOREACH(session->delayqueue, q) { + if (q->id == pdu->mid) { + coap_log(LOG_ERR, "** %s: mid=0x%x: already in-use - dropped\n", + coap_session_str(session), pdu->mid); + return COAP_INVALID_MID; + } + } + } + node = coap_new_node(); + if (node == NULL) + return COAP_INVALID_MID; + node->id = pdu->mid; + node->pdu = pdu; + if (pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) { + uint8_t r; + coap_prng(&r, sizeof(r)); + /* add timeout in range [ACK_TIMEOUT...ACK_TIMEOUT * ACK_RANDOM_FACTOR] */ + node->timeout = coap_calc_timeout(session, r); + } + } + LL_APPEND(session->delayqueue, node); + coap_log(LOG_DEBUG, "** %s: mid=0x%x: delayed\n", + coap_session_str(session), node->id); + return COAP_PDU_DELAYED; +} + +#if !COAP_DISABLE_TCP +void coap_session_send_csm(coap_session_t *session) { + coap_pdu_t *pdu; + uint8_t buf[4]; + assert(COAP_PROTO_RELIABLE(session->proto)); + coap_log(LOG_DEBUG, "***%s: sending CSM\n", coap_session_str(session)); + session->state = COAP_SESSION_STATE_CSM; + session->partial_write = 0; + if (session->mtu == 0) + session->mtu = COAP_DEFAULT_MTU; /* base value */ + pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_SIGNALING_CODE_CSM, 0, 20); + if ( pdu == NULL + || coap_add_option_internal(pdu, COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE, + coap_encode_var_safe(buf, sizeof(buf), + session->context->csm_max_message_size), buf) == 0 + || coap_add_option_internal(pdu, COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER, + coap_encode_var_safe(buf, sizeof(buf), + 0), buf) == 0 + || coap_pdu_encode_header(pdu, session->proto) == 0 + ) { + coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); + } else { + ssize_t bytes_written = coap_session_send_pdu(session, pdu); + if (bytes_written != (ssize_t)pdu->used_size + pdu->hdr_size) { + coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); + } else { + session->csm_rcv_mtu = session->context->csm_max_message_size; + if (session->csm_rcv_mtu > COAP_BERT_BASE) + session->csm_bert_loc_support = 1; + else + session->csm_bert_loc_support = 0; + } + } + if (pdu) + coap_delete_pdu(pdu); +} +#endif /* !COAP_DISABLE_TCP */ + +coap_mid_t coap_session_send_ping(coap_session_t *session) { + coap_pdu_t *ping = NULL; + if (session->state != COAP_SESSION_STATE_ESTABLISHED) + return COAP_INVALID_MID; + if (COAP_PROTO_NOT_RELIABLE(session->proto)) { + uint16_t mid = coap_new_message_id (session); + ping = coap_pdu_init(COAP_MESSAGE_CON, 0, mid, 0); + } +#if !COAP_DISABLE_TCP + else { + ping = coap_pdu_init(COAP_MESSAGE_CON, COAP_SIGNALING_CODE_PING, 0, 1); + } +#endif /* !COAP_DISABLE_TCP */ + if (!ping) + return COAP_INVALID_MID; + return coap_send_internal(session, ping); +} + +void coap_session_connected(coap_session_t *session) { + if (session->state != COAP_SESSION_STATE_ESTABLISHED) { + coap_log(LOG_DEBUG, "***%s: session connected\n", + coap_session_str(session)); + if (session->state == COAP_SESSION_STATE_CSM) + coap_handle_event(session->context, COAP_EVENT_SESSION_CONNECTED, session); + if (session->doing_first) + session->doing_first = 0; + } + + session->state = COAP_SESSION_STATE_ESTABLISHED; + session->partial_write = 0; + + if ( session->proto==COAP_PROTO_DTLS) { + session->tls_overhead = coap_dtls_get_overhead(session); + if (session->tls_overhead >= session->mtu) { + session->tls_overhead = session->mtu; + coap_log(LOG_ERR, "DTLS overhead exceeds MTU\n"); + } + } + + while (session->delayqueue && session->state == COAP_SESSION_STATE_ESTABLISHED) { + ssize_t bytes_written; + coap_queue_t *q = session->delayqueue; + if (q->pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) { + if (session->con_active >= COAP_NSTART(session)) + break; + session->con_active++; + } + /* Take entry off the queue */ + session->delayqueue = q->next; + q->next = NULL; + + coap_log(LOG_DEBUG, "** %s: mid=0x%x: transmitted after delay\n", + coap_session_str(session), (int)q->pdu->mid); + bytes_written = coap_session_send_pdu(session, q->pdu); + if (q->pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) { + if (coap_wait_ack(session->context, session, q) >= 0) + q = NULL; + } + if (COAP_PROTO_NOT_RELIABLE(session->proto)) { + if (q) + coap_delete_node(q); + if (bytes_written < 0) + break; + } else { + if (bytes_written <= 0 || (size_t)bytes_written < q->pdu->used_size + q->pdu->hdr_size) { + q->next = session->delayqueue; + session->delayqueue = q; + if (bytes_written > 0) + session->partial_write = (size_t)bytes_written; + break; + } else { + coap_delete_node(q); + } + } + } +} + +void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason) { +#if !COAP_DISABLE_TCP + coap_session_state_t state = session->state; +#endif /* !COAP_DISABLE_TCP */ + + coap_log(LOG_DEBUG, "***%s: session disconnected (reason %d)\n", + coap_session_str(session), reason); +#if COAP_SERVER_SUPPORT + coap_delete_observers( session->context, session ); +#endif /* COAP_SERVER_SUPPORT */ + + if ( session->tls) { + if (session->proto == COAP_PROTO_DTLS) + coap_dtls_free_session(session); +#if !COAP_DISABLE_TCP + else if (session->proto == COAP_PROTO_TLS) + coap_tls_free_session(session); +#endif /* !COAP_DISABLE_TCP */ + session->tls = NULL; + } + + if (session->proto == COAP_PROTO_UDP) + session->state = COAP_SESSION_STATE_ESTABLISHED; + else + session->state = COAP_SESSION_STATE_NONE; + + session->con_active = 0; + + if (session->partial_pdu) { + coap_delete_pdu(session->partial_pdu); + session->partial_pdu = NULL; + } + session->partial_read = 0; + + while (session->delayqueue) { + coap_queue_t *q = session->delayqueue; + session->delayqueue = q->next; + q->next = NULL; + coap_log(LOG_DEBUG, "** %s: mid=0x%x: not transmitted after disconnect\n", + coap_session_str(session), q->id); + if (q->pdu->type==COAP_MESSAGE_CON + && COAP_PROTO_NOT_RELIABLE(session->proto) + && reason == COAP_NACK_ICMP_ISSUE) + { + /* Make sure that we try a re-transmit later on ICMP error */ + if (coap_wait_ack(session->context, session, q) >= 0) { + if (session->context->nack_handler) { + session->context->nack_handler(session, q->pdu, reason, q->id); + } + q = NULL; + } + } + if (q && q->pdu->type == COAP_MESSAGE_CON + && session->context->nack_handler) + { + session->context->nack_handler(session, q->pdu, reason, q->id); + } + if (q) + coap_delete_node(q); + } + if (reason != COAP_NACK_ICMP_ISSUE) { + coap_cancel_session_messages(session->context, session, reason); + } + else if (session->context->nack_handler) { + coap_queue_t *q = session->context->sendqueue; + while (q) { + if (q->session == session) { + session->context->nack_handler(session, q->pdu, reason, q->id); + } + q = q->next; + } + } + +#if !COAP_DISABLE_TCP + if (COAP_PROTO_RELIABLE(session->proto)) { + if (session->sock.flags != COAP_SOCKET_EMPTY) { + coap_socket_close(&session->sock); + coap_handle_event(session->context, + state == COAP_SESSION_STATE_CONNECTING ? + COAP_EVENT_TCP_FAILED : COAP_EVENT_TCP_CLOSED, session); + } + if (state != COAP_SESSION_STATE_NONE) { + coap_handle_event(session->context, + state == COAP_SESSION_STATE_ESTABLISHED ? + COAP_EVENT_SESSION_CLOSED : COAP_EVENT_SESSION_FAILED, session); + } + if (session->doing_first) + session->doing_first = 0; + } +#endif /* !COAP_DISABLE_TCP */ +} + +#if COAP_SERVER_SUPPORT +static void +coap_make_addr_hash(coap_addr_hash_t *addr_hash, coap_proto_t proto, + const coap_addr_tuple_t *addr_info) { + memset(addr_hash, 0, sizeof(coap_addr_hash_t)); + coap_address_copy(&addr_hash->remote, &addr_info->remote); + addr_hash->lport = coap_address_get_port(&addr_info->local); + addr_hash->proto = proto; +} + +coap_session_t * +coap_endpoint_get_session(coap_endpoint_t *endpoint, + const coap_packet_t *packet, coap_tick_t now) { + coap_session_t *session; + coap_session_t *rtmp; + unsigned int num_idle = 0; + unsigned int num_hs = 0; + coap_session_t *oldest = NULL; + coap_session_t *oldest_hs = NULL; + coap_addr_hash_t addr_hash; + + coap_make_addr_hash(&addr_hash, endpoint->proto, &packet->addr_info); + SESSIONS_FIND(endpoint->sessions, addr_hash, session); + if (session) { + /* Maybe mcast or unicast IP address which is not in the hash */ + coap_address_copy(&session->addr_info.local, &packet->addr_info.local); + session->ifindex = packet->ifindex; + session->last_rx_tx = now; + return session; + } + + SESSIONS_ITER(endpoint->sessions, session, rtmp) { + if (session->ref == 0 && session->delayqueue == NULL) { + if (session->type == COAP_SESSION_TYPE_SERVER) { + ++num_idle; + if (oldest==NULL || session->last_rx_tx < oldest->last_rx_tx) + oldest = session; + + if (session->state == COAP_SESSION_STATE_HANDSHAKE) { + ++num_hs; + /* See if this is a partial (D)TLS session set up + which needs to be cleared down to prevent DOS */ + if ((session->last_rx_tx + COAP_PARTIAL_SESSION_TIMEOUT_TICKS) < now) { + if (oldest_hs == NULL || + session->last_rx_tx < oldest_hs->last_rx_tx) + oldest_hs = session; + } + } + } + else if (session->type == COAP_SESSION_TYPE_HELLO) { + ++num_hs; + /* See if this is a partial (D)TLS session set up for Client Hello + which needs to be cleared down to prevent DOS */ + if ((session->last_rx_tx + COAP_PARTIAL_SESSION_TIMEOUT_TICKS) < now) { + if (oldest_hs == NULL || + session->last_rx_tx < oldest_hs->last_rx_tx) + oldest_hs = session; + } + } + } + } + + if (endpoint->context->max_idle_sessions > 0 && + num_idle >= endpoint->context->max_idle_sessions) { + coap_handle_event(oldest->context, COAP_EVENT_SERVER_SESSION_DEL, oldest); + coap_session_free(oldest); + } + else if (oldest_hs) { + coap_log(LOG_WARNING, "***%s: Incomplete session timed out\n", + coap_session_str(oldest_hs)); + coap_handle_event(oldest_hs->context, COAP_EVENT_SERVER_SESSION_DEL, oldest_hs); + coap_session_free(oldest_hs); + } + + if (num_hs > (endpoint->context->max_handshake_sessions ? + endpoint->context->max_handshake_sessions : + COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS)) { + /* Maxed out on number of sessions in (D)TLS negotiation state */ + coap_log(LOG_DEBUG, + "Oustanding sessions in COAP_SESSION_STATE_HANDSHAKE too " + "large. New request ignored\n"); + return NULL; + } + + if (endpoint->proto == COAP_PROTO_DTLS) { + /* + * Need to check that this actually is a Client Hello before wasting + * time allocating and then freeing off session. + */ + + /* + * Generic header structure of the DTLS record layer. + * typedef struct __attribute__((__packed__)) { + * uint8_t content_type; content type of the included message + * uint16_t version; Protocol version + * uint16_t epoch; counter for cipher state changes + * uint8_t sequence_number[6]; sequence number + * uint16_t length; length of the following fragment + * uint8_t handshake; If content_type == DTLS_CT_HANDSHAKE + * } dtls_record_handshake_t; + */ +#define OFF_CONTENT_TYPE 0 /* offset of content_type in dtls_record_handshake_t */ +#define DTLS_CT_ALERT 21 /* Content Type Alert */ +#define DTLS_CT_HANDSHAKE 22 /* Content Type Handshake */ +#define OFF_HANDSHAKE_TYPE 13 /* offset of handshake in dtls_record_handshake_t */ +#define DTLS_HT_CLIENT_HELLO 1 /* Client Hello handshake type */ + +#ifdef WITH_LWIP + const uint8_t *payload = (const uint8_t*)packet->pbuf->payload; + size_t length = packet->pbuf->len; +#else /* ! WITH_LWIP */ + const uint8_t *payload = (const uint8_t*)packet->payload; + size_t length = packet->length; +#endif /* ! WITH_LWIP */ + if (length < (OFF_HANDSHAKE_TYPE + 1)) { + coap_log(LOG_DEBUG, + "coap_dtls_hello: ContentType %d Short Packet (%zu < %d) dropped\n", + payload[OFF_CONTENT_TYPE], length, + OFF_HANDSHAKE_TYPE + 1); + return NULL; + } + if (payload[OFF_CONTENT_TYPE] != DTLS_CT_HANDSHAKE || + payload[OFF_HANDSHAKE_TYPE] != DTLS_HT_CLIENT_HELLO) { + /* only log if not a late alert */ + if (payload[OFF_CONTENT_TYPE] != DTLS_CT_ALERT) + coap_log(LOG_DEBUG, + "coap_dtls_hello: ContentType %d Handshake %d dropped\n", + payload[OFF_CONTENT_TYPE], payload[OFF_HANDSHAKE_TYPE]); + return NULL; + } + } + + session = coap_make_session(endpoint->proto, COAP_SESSION_TYPE_SERVER, + &addr_hash, &packet->addr_info.local, + &packet->addr_info.remote, + packet->ifindex, endpoint->context, endpoint); + if (session) { + session->last_rx_tx = now; + if (endpoint->proto == COAP_PROTO_UDP) + session->state = COAP_SESSION_STATE_ESTABLISHED; + else if (endpoint->proto == COAP_PROTO_DTLS) { + session->type = COAP_SESSION_TYPE_HELLO; + } + SESSIONS_ADD(endpoint->sessions, session); + coap_log(LOG_DEBUG, "***%s: session %p: new incoming session\n", + coap_session_str(session), (void *)session); + coap_handle_event(session->context, COAP_EVENT_SERVER_SESSION_NEW, session); + } + return session; +} + +coap_session_t * +coap_session_new_dtls_session(coap_session_t *session, + coap_tick_t now) { + if (session) { + session->last_rx_tx = now; + session->type = COAP_SESSION_TYPE_SERVER; + session->tls = coap_dtls_new_server_session(session); + if (session->tls) { + session->state = COAP_SESSION_STATE_HANDSHAKE; + } else { + coap_session_free(session); + session = NULL; + } + } + return session; +} +#endif /* COAP_SERVER_SUPPORT */ + +#ifdef COAP_EPOLL_SUPPORT +static void +coap_epoll_ctl_add(coap_socket_t *sock, + uint32_t events, + const char *func +) { + int ret; + struct epoll_event event; + coap_context_t *context; + + if (sock == NULL) + return; + +#if COAP_SERVER_SUPPORT + context = sock->session ? sock->session->context : + sock->endpoint ? sock->endpoint->context : NULL; +#else /* ! COAP_SERVER_SUPPORT */ + context = sock->session ? sock->session->context : NULL; +#endif /* ! COAP_SERVER_SUPPORT */ + if (context == NULL) + return; + + /* Needed if running 32bit as ptr is only 32bit */ + memset(&event, 0, sizeof(event)); + event.events = events; + event.data.ptr = sock; + + ret = epoll_ctl(context->epfd, EPOLL_CTL_ADD, sock->fd, &event); + if (ret == -1) { + coap_log(LOG_ERR, + "%s: epoll_ctl ADD failed: %s (%d)\n", + func, + coap_socket_strerror(), errno); + } +} +#endif /* COAP_EPOLL_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +static coap_session_t * +coap_session_create_client( + coap_context_t *ctx, + const coap_address_t *local_if, + const coap_address_t *server, + coap_proto_t proto +) { + coap_session_t *session = NULL; + + assert(server); + + switch(proto) { + case COAP_PROTO_UDP: + break; + case COAP_PROTO_DTLS: + if (!coap_dtls_is_supported()) { + coap_log(LOG_CRIT, "coap_new_client_session*: DTLS not supported\n"); + return NULL; + } + break; + case COAP_PROTO_TCP: + if (!coap_tcp_is_supported()) { + coap_log(LOG_CRIT, "coap_new_client_session*: TCP not supported\n"); + return NULL; + } + break; + case COAP_PROTO_TLS: + if (!coap_tls_is_supported()) { + coap_log(LOG_CRIT, "coap_new_client_session*: TLS not supported\n"); + return NULL; + } + break; + case COAP_PROTO_NONE: + default: + assert(0); + break; + } + session = coap_make_session(proto, COAP_SESSION_TYPE_CLIENT, NULL, + local_if, server, 0, ctx, NULL); + if (!session) + goto error; + + coap_session_reference(session); + + if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) { + coap_session_t *s, *rtmp; + if (!coap_socket_connect_udp(&session->sock, local_if, server, + proto == COAP_PROTO_DTLS ? COAPS_DEFAULT_PORT : COAP_DEFAULT_PORT, + &session->addr_info.local, &session->addr_info.remote)) { + goto error; + } + /* Check that this is not a duplicate 4-tuple */ + SESSIONS_ITER_SAFE(ctx->sessions, s, rtmp) { + if ((s->proto == COAP_PROTO_UDP || s->proto == COAP_PROTO_DTLS) && + coap_address_equals(&session->addr_info.local, + &s->addr_info.local) && + coap_address_equals(&session->addr_info.remote, + &s->addr_info.remote)) { + coap_log(LOG_WARNING, "***%s: session %p: duplicate - already exists\n", + coap_session_str(session), (void *)session); + goto error; + } + } +#if !COAP_DISABLE_TCP + } else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) { + if (!coap_socket_connect_tcp1(&session->sock, local_if, server, + proto == COAP_PROTO_TLS ? COAPS_DEFAULT_PORT : COAP_DEFAULT_PORT, + &session->addr_info.local, &session->addr_info.remote)) { + goto error; + } +#endif /* !COAP_DISABLE_TCP */ + } + +#ifdef COAP_EPOLL_SUPPORT + session->sock.session = session; + coap_epoll_ctl_add(&session->sock, + EPOLLIN | + ((session->sock.flags & COAP_SOCKET_WANT_CONNECT) ? + EPOLLOUT : 0), + __func__); +#endif /* COAP_EPOLL_SUPPORT */ + + session->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_WANT_READ; + if (local_if) + session->sock.flags |= COAP_SOCKET_BOUND; +#if COAP_SERVER_SUPPORT + if (ctx->proxy_uri_resource) + session->proxy_session = 1; +#endif /* COAP_SERVER_SUPPORT */ + SESSIONS_ADD(ctx->sessions, session); + return session; + +error: + /* + * Need to add in the session as coap_session_release() + * will call SESSIONS_DELETE in coap_session_free(). + */ + if (session) + SESSIONS_ADD(ctx->sessions, session); + coap_session_release(session); + return NULL; +} + +static coap_session_t * +coap_session_connect(coap_session_t *session) { + if (session->proto == COAP_PROTO_UDP) { + session->state = COAP_SESSION_STATE_ESTABLISHED; + } else if (session->proto == COAP_PROTO_DTLS) { + session->tls = coap_dtls_new_client_session(session); + if (session->tls) { + session->state = COAP_SESSION_STATE_HANDSHAKE; + } else { + /* Need to free session object. As a new session may not yet + * have been referenced, we call coap_session_reference() first + * before trying to release the object. + */ + coap_session_reference(session); + coap_session_release(session); + return NULL; + } +#if !COAP_DISABLE_TCP + } else { + if (session->proto == COAP_PROTO_TCP || session->proto == COAP_PROTO_TLS) { + if (session->sock.flags & COAP_SOCKET_WANT_CONNECT) { + session->state = COAP_SESSION_STATE_CONNECTING; + if (session->state != COAP_SESSION_STATE_ESTABLISHED && + session->state != COAP_SESSION_STATE_NONE && + COAP_PROTO_RELIABLE(session->proto) && + session->type == COAP_SESSION_TYPE_CLIENT) { + session->doing_first = 1; + } + } else if (session->proto == COAP_PROTO_TLS) { + int connected = 0; + session->tls = coap_tls_new_client_session(session, &connected); + if (session->tls) { + session->state = COAP_SESSION_STATE_HANDSHAKE; + if (connected) + coap_session_send_csm(session); + } else { + /* Need to free session object. As a new session may not yet + * have been referenced, we call coap_session_reference() + * first before trying to release the object. + */ + coap_session_reference(session); + coap_session_release(session); + return NULL; + } + } else { + coap_session_send_csm(session); + } + } +#endif /* !COAP_DISABLE_TCP */ + } + coap_ticks(&session->last_rx_tx); + return session; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +static coap_session_t * +coap_session_accept(coap_session_t *session) { +#if !COAP_DISABLE_TCP + if (session->proto == COAP_PROTO_TCP || session->proto == COAP_PROTO_TLS) + coap_handle_event(session->context, COAP_EVENT_TCP_CONNECTED, session); + if (session->proto == COAP_PROTO_TCP) { + coap_session_send_csm(session); + } else if (session->proto == COAP_PROTO_TLS) { + int connected = 0; + session->tls = coap_tls_new_server_session(session, &connected); + if (session->tls) { + session->state = COAP_SESSION_STATE_HANDSHAKE; + if (connected) { + coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session); + coap_session_send_csm(session); + } + } else { + /* Need to free session object. As a new session may not yet + * have been referenced, we call coap_session_reference() first + * before trying to release the object. + */ + coap_session_reference(session); + coap_session_release(session); + session = NULL; + } + } +#endif /* COAP_DISABLE_TCP */ + return session; +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +coap_session_t *coap_new_client_session( + coap_context_t *ctx, + const coap_address_t *local_if, + const coap_address_t *server, + coap_proto_t proto +) { + coap_session_t *session = coap_session_create_client(ctx, local_if, server, + proto); + if (session) { + coap_log(LOG_DEBUG, "***%s: session %p: created outgoing session\n", + coap_session_str(session), (void *)session); + session = coap_session_connect(session); + } + return session; +} + +coap_session_t *coap_new_client_session_psk( + coap_context_t *ctx, + const coap_address_t *local_if, + const coap_address_t *server, + coap_proto_t proto, + const char *identity, + const uint8_t *key, + unsigned key_len +) { + coap_dtls_cpsk_t setup_data; + + memset (&setup_data, 0, sizeof(setup_data)); + setup_data.version = COAP_DTLS_CPSK_SETUP_VERSION; + + if (identity) { + setup_data.psk_info.identity.s = (const uint8_t *)identity; + setup_data.psk_info.identity.length = strlen(identity); + } + + if (key && key_len > 0) { + setup_data.psk_info.key.s = key; + setup_data.psk_info.key.length = key_len; + } + + return coap_new_client_session_psk2(ctx, local_if, server, + proto, &setup_data); +} + +coap_session_t *coap_new_client_session_psk2( + coap_context_t *ctx, + const coap_address_t *local_if, + const coap_address_t *server, + coap_proto_t proto, + coap_dtls_cpsk_t *setup_data +) { + coap_session_t *session = coap_session_create_client(ctx, local_if, + server, proto); + + if (!session) + return NULL; + + session->cpsk_setup_data = *setup_data; + if (setup_data->psk_info.identity.s) { + session->psk_identity = + coap_new_bin_const(setup_data->psk_info.identity.s, + setup_data->psk_info.identity.length); + if (!session->psk_identity) { + coap_log(LOG_WARNING, "Cannot store session Identity (PSK)\n"); + coap_session_release(session); + return NULL; + } + } + else if (coap_dtls_is_supported() || coap_tls_is_supported()) { + coap_log(LOG_WARNING, "Identity (PSK) not defined\n"); + coap_session_release(session); + return NULL; + } + + if (setup_data->psk_info.key.s && setup_data->psk_info.key.length > 0) { + session->psk_key = coap_new_bin_const(setup_data->psk_info.key.s, + setup_data->psk_info.key.length); + if (!session->psk_key) { + coap_log(LOG_WARNING, "Cannot store session pre-shared key (PSK)\n"); + coap_session_release(session); + return NULL; + } + } + else if (coap_dtls_is_supported() || coap_tls_is_supported()) { + coap_log(LOG_WARNING, "Pre-shared key (PSK) not defined\n"); + coap_session_release(session); + return NULL; + } + + if (coap_dtls_is_supported() || coap_tls_is_supported()) { + if (!coap_dtls_context_set_cpsk(ctx, setup_data)) { + coap_session_release(session); + return NULL; + } + } + coap_log(LOG_DEBUG, "***%s: new outgoing session\n", + coap_session_str(session)); + return coap_session_connect(session); +} +#endif /* ! COAP_CLIENT_SUPPORT */ + +int +coap_session_refresh_psk_hint(coap_session_t *session, + const coap_bin_const_t *psk_hint +) { + /* We may be refreshing the hint with the same hint */ + coap_bin_const_t *old_psk_hint = session->psk_hint; + + if (psk_hint && psk_hint->s) { + if (session->psk_hint) { + if (coap_binary_equal(session->psk_hint, psk_hint)) + return 1; + } + session->psk_hint = coap_new_bin_const(psk_hint->s, + psk_hint->length); + if (!session->psk_hint) { + coap_log(LOG_ERR, "No memory to store identity hint (PSK)\n"); + if (old_psk_hint) + coap_delete_bin_const(old_psk_hint); + return 0; + } + } + else { + session->psk_hint = NULL; + } + if (old_psk_hint) + coap_delete_bin_const(old_psk_hint); + + return 1; +} + +int +coap_session_refresh_psk_key(coap_session_t *session, + const coap_bin_const_t *psk_key +) { + /* We may be refreshing the key with the same key */ + coap_bin_const_t *old_psk_key = session->psk_key; + + if (psk_key && psk_key->s) { + if (session->psk_key) { + if (coap_binary_equal(session->psk_key, psk_key)) + return 1; + } + session->psk_key = coap_new_bin_const(psk_key->s, psk_key->length); + if (!session->psk_key) { + coap_log(LOG_ERR, "No memory to store pre-shared key (PSK)\n"); + if (old_psk_key) + coap_delete_bin_const(old_psk_key); + return 0; + } + } + else { + session->psk_key = NULL; + } + if (old_psk_key) + coap_delete_bin_const(old_psk_key); + + return 1; +} + +int +coap_session_refresh_psk_identity(coap_session_t *session, + const coap_bin_const_t *psk_identity +) { + /* We may be refreshing the identity with the same identity */ + coap_bin_const_t *old_psk_identity = session->psk_identity; + + if (psk_identity && psk_identity->s) { + if (session->psk_identity) { + if (coap_binary_equal(session->psk_identity, psk_identity)) + return 1; + } + session->psk_identity = coap_new_bin_const(psk_identity->s, + psk_identity->length); + if (!session->psk_identity) { + coap_log(LOG_ERR, "No memory to store pre-shared key identity (PSK)\n"); + if (old_psk_identity) + coap_delete_bin_const(old_psk_identity); + return 0; + } + } + else { + session->psk_identity = NULL; + } + if (old_psk_identity) + coap_delete_bin_const(old_psk_identity); + + return 1; +} + +#if COAP_SERVER_SUPPORT +const coap_bin_const_t * +coap_session_get_psk_hint(const coap_session_t *session) { + if (session) + return session->psk_hint; + return NULL; +} +#endif /* COAP_SERVER_SUPPORT */ + +const coap_bin_const_t * +coap_session_get_psk_identity(const coap_session_t *session) { + const coap_bin_const_t *psk_identity = NULL; + if (session) { + psk_identity = session->psk_identity; + if (psk_identity == NULL) { + psk_identity = &session->cpsk_setup_data.psk_info.identity; + } + } + return psk_identity; +} + +const coap_bin_const_t * +coap_session_get_psk_key(const coap_session_t *session) { + if (session) + return session->psk_key; + return NULL; +} + +#if COAP_CLIENT_SUPPORT +coap_session_t *coap_new_client_session_pki( + coap_context_t *ctx, + const coap_address_t *local_if, + const coap_address_t *server, + coap_proto_t proto, + coap_dtls_pki_t* setup_data +) { + coap_session_t *session; + + if (coap_dtls_is_supported() || coap_tls_is_supported()) { + if (!setup_data) { + return NULL; + } else { + if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION) { + coap_log(LOG_ERR, + "coap_new_client_session_pki: Wrong version of setup_data\n"); + return NULL; + } + } + + } + session = coap_session_create_client(ctx, local_if, server, proto); + + if (!session) { + return NULL; + } + + if (coap_dtls_is_supported() || coap_tls_is_supported()) { + /* we know that setup_data is not NULL */ + if (!coap_dtls_context_set_pki(ctx, setup_data, COAP_DTLS_ROLE_CLIENT)) { + coap_session_release(session); + return NULL; + } + } + coap_log(LOG_DEBUG, "***%s: new outgoing session\n", + coap_session_str(session)); + return coap_session_connect(session); +} +#endif /* ! COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +coap_session_t *coap_new_server_session( + coap_context_t *ctx, + coap_endpoint_t *ep +) { + coap_session_t *session; + session = coap_make_session( ep->proto, COAP_SESSION_TYPE_SERVER, + NULL, NULL, NULL, 0, ctx, ep ); + if (!session) + goto error; + +#if !COAP_DISABLE_TCP + if (!coap_socket_accept_tcp(&ep->sock, &session->sock, + &session->addr_info.local, + &session->addr_info.remote)) + goto error; + coap_make_addr_hash(&session->addr_hash, session->proto, &session->addr_info); + +#endif /* !COAP_DISABLE_TCP */ + session->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_CONNECTED + | COAP_SOCKET_WANT_READ; +#ifdef COAP_EPOLL_SUPPORT + session->sock.session = session; + coap_epoll_ctl_add(&session->sock, + EPOLLIN, + __func__); +#endif /* COAP_EPOLL_SUPPORT */ + SESSIONS_ADD(ep->sessions, session); + if (session) { + coap_log(LOG_DEBUG, "***%s: session %p: new incoming session\n", + coap_session_str(session), (void *)session); + /* Returned session may already have been released and is now NULL */ + session = coap_session_accept(session); + if(session) { + coap_handle_event(session->context, COAP_EVENT_SERVER_SESSION_NEW, session); + } + } + return session; + +error: + /* + * Need to add in the session as coap_session_release() + * will call SESSIONS_DELETE in coap_session_free(). + */ + if (session) { + SESSIONS_ADD(ep->sessions, session); + coap_session_free(session); + } + return NULL; +} +#endif /* COAP_SERVER_SUPPORT */ + +void +coap_session_init_token(coap_session_t *session, size_t len, + const uint8_t *data) { + session->tx_token = coap_decode_var_bytes8(data, len); +} + +void coap_session_new_token(coap_session_t *session, size_t *len, + uint8_t *data) { + *len = coap_encode_var_safe8(data, + sizeof(session->tx_token), ++session->tx_token); +} + +uint16_t +coap_new_message_id(coap_session_t *session) { + return ++session->tx_mid; +} + +const coap_address_t * +coap_session_get_addr_remote(const coap_session_t *session) { + if (session) + return &session->addr_info.remote; + return NULL; +} + +const coap_address_t * +coap_session_get_addr_local(const coap_session_t *session) { + if (session) + return &session->addr_info.local; + return NULL; +} + +coap_context_t * +coap_session_get_context(const coap_session_t *session) { + if (session) + return session->context; + return NULL; +} + +coap_proto_t +coap_session_get_proto(const coap_session_t *session) { + if (session) + return session->proto; + return 0; +} + +coap_session_type_t +coap_session_get_type(const coap_session_t *session) { + if (session) + return session->type; + return 0; +} + +#if COAP_CLIENT_SUPPORT +int +coap_session_set_type_client(coap_session_t *session) { +#if COAP_SERVER_SUPPORT + if (session && session->type == COAP_SESSION_TYPE_SERVER) { + coap_session_reference(session); + session->type = COAP_SESSION_TYPE_CLIENT; + return 1; + } +#else /* ! COAP_SERVER_SUPPORT */ + (void)session; +#endif /* ! COAP_SERVER_SUPPORT */ + return 0; +} +#endif /* COAP_CLIENT_SUPPORT */ + +coap_session_state_t +coap_session_get_state(const coap_session_t *session) { + if (session) + return session->state; + return 0; +} + +int coap_session_get_ifindex(const coap_session_t *session) { + if (session) + return session->ifindex; + return -1; +} + +void *coap_session_get_tls(const coap_session_t *session, + coap_tls_library_t *tls_lib) { + if (session) + return coap_dtls_get_tls(session, tls_lib); + return NULL; +} + +#ifndef WITH_LWIP +#if COAP_SERVER_SUPPORT +coap_endpoint_t * +coap_new_endpoint(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto) { + coap_endpoint_t *ep = NULL; + + assert(context); + assert(listen_addr); + assert(proto != COAP_PROTO_NONE); + + if (proto == COAP_PROTO_DTLS && !coap_dtls_is_supported()) { + coap_log(LOG_CRIT, "coap_new_endpoint: DTLS not supported\n"); + goto error; + } + + if (proto == COAP_PROTO_TLS && !coap_tls_is_supported()) { + coap_log(LOG_CRIT, "coap_new_endpoint: TLS not supported\n"); + goto error; + } + + if (proto == COAP_PROTO_TCP && !coap_tcp_is_supported()) { + coap_log(LOG_CRIT, "coap_new_endpoint: TCP not supported\n"); + goto error; + } + + if (proto == COAP_PROTO_DTLS || proto == COAP_PROTO_TLS) { + if (!coap_dtls_context_check_keys_enabled(context)) { + coap_log(LOG_INFO, + "coap_new_endpoint: one of coap_context_set_psk() or " + "coap_context_set_pki() not called\n"); + goto error; + } + } + + ep = coap_malloc_endpoint(); + if (!ep) { + coap_log(LOG_WARNING, "coap_new_endpoint: malloc"); + goto error; + } + + memset(ep, 0, sizeof(coap_endpoint_t)); + ep->context = context; + ep->proto = proto; + + if (proto==COAP_PROTO_UDP || proto==COAP_PROTO_DTLS) { + if (!coap_socket_bind_udp(&ep->sock, listen_addr, &ep->bind_addr)) + goto error; + ep->sock.flags |= COAP_SOCKET_WANT_READ; +#if !COAP_DISABLE_TCP + } else if (proto==COAP_PROTO_TCP || proto==COAP_PROTO_TLS) { + if (!coap_socket_bind_tcp(&ep->sock, listen_addr, &ep->bind_addr)) + goto error; + ep->sock.flags |= COAP_SOCKET_WANT_ACCEPT; +#endif /* !COAP_DISABLE_TCP */ + } else { + coap_log(LOG_CRIT, "coap_new_endpoint: protocol not supported\n"); + goto error; + } + + if (LOG_DEBUG <= coap_get_log_level()) { +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 40 +#endif + unsigned char addr_str[INET6_ADDRSTRLEN + 8]; + + if (coap_print_addr(&ep->bind_addr, addr_str, INET6_ADDRSTRLEN + 8)) { + coap_log(LOG_DEBUG, "created %s endpoint %s\n", + ep->proto == COAP_PROTO_TLS ? "TLS " + : ep->proto == COAP_PROTO_TCP ? "TCP " + : ep->proto == COAP_PROTO_DTLS ? "DTLS" : "UDP ", + addr_str); + } + } + + ep->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_BOUND; + + ep->default_mtu = COAP_DEFAULT_MTU; + +#ifdef COAP_EPOLL_SUPPORT + ep->sock.endpoint = ep; + coap_epoll_ctl_add(&ep->sock, + EPOLLIN, + __func__); +#endif /* COAP_EPOLL_SUPPORT */ + + LL_PREPEND(context->endpoint, ep); + return ep; + +error: + coap_free_endpoint(ep); + return NULL; +} + +void coap_endpoint_set_default_mtu(coap_endpoint_t *ep, unsigned mtu) { + ep->default_mtu = (uint16_t)mtu; +} + +void +coap_free_endpoint(coap_endpoint_t *ep) { + if (ep) { + coap_session_t *session, *rtmp; + + SESSIONS_ITER_SAFE(ep->sessions, session, rtmp) { + assert(session->ref == 0); + if (session->ref == 0) { + coap_session_free(session); + } + } + if (ep->sock.flags != COAP_SOCKET_EMPTY) { + /* + * ep->sock.endpoint is set in coap_new_endpoint(). + * ep->sock.session is never set. + * + * session->sock.session is set for both clients and servers (when a + * new session is accepted), but does not affect the endpoint. + * + * So, it is safe to call coap_socket_close() after all the sessions + * have been freed above as we are only working with the endpoint sock. + */ +#ifdef COAP_EPOLL_SUPPORT + assert(ep->sock.session == NULL); +#endif /* COAP_EPOLL_SUPPORT */ + coap_socket_close(&ep->sock); + } + + if (ep->context && ep->context->endpoint) { + LL_DELETE(ep->context->endpoint, ep); + } + coap_mfree_endpoint(ep); + } +} +#endif /* COAP_SERVER_SUPPORT */ +#endif /* WITH_LWIP */ + +coap_session_t * +coap_session_get_by_peer(const coap_context_t *ctx, + const coap_address_t *remote_addr, + int ifindex) { + coap_session_t *s, *rtmp; +#if COAP_CLIENT_SUPPORT + SESSIONS_ITER(ctx->sessions, s, rtmp) { + if (s->ifindex == ifindex && coap_address_equals(&s->addr_info.remote, + remote_addr)) + return s; + } +#endif /* COAP_CLIENT_SUPPORT */ +#if COAP_SERVER_SUPPORT + coap_endpoint_t *ep; + + LL_FOREACH(ctx->endpoint, ep) { + SESSIONS_ITER(ep->sessions, s, rtmp) { + if (s->ifindex == ifindex && coap_address_equals(&s->addr_info.remote, + remote_addr)) + return s; + } + } +#endif /* COAP_SERVER_SUPPORT */ + return NULL; +} + +const char *coap_session_str(const coap_session_t *session) { + static char szSession[2 * (INET6_ADDRSTRLEN + 8) + 24]; + char *p = szSession, *end = szSession + sizeof(szSession); + if (coap_print_addr(&session->addr_info.local, + (unsigned char*)p, end - p) > 0) + p += strlen(p); + if (p + 6 < end) { + strcpy(p, " <-> "); + p += 5; + } + if (p + 1 < end) { + if (coap_print_addr(&session->addr_info.remote, + (unsigned char*)p, end - p) > 0) + p += strlen(p); + } + if (session->ifindex > 0 && p + 1 < end) + p += snprintf(p, end - p, " (if%d)", session->ifindex); + if (p + 6 < end) { + if (session->proto == COAP_PROTO_UDP) { + strcpy(p, " UDP "); + p += 4; + } else if (session->proto == COAP_PROTO_DTLS) { + strcpy(p, " DTLS"); + p += 5; + } else if (session->proto == COAP_PROTO_TCP) { + strcpy(p, " TCP "); + p += 4; + } else if (session->proto == COAP_PROTO_TLS) { + strcpy(p, " TLS "); + p += 4; + } else { + strcpy(p, " NONE"); + p += 5; + } + } + + return szSession; +} + +#if COAP_SERVER_SUPPORT +const char *coap_endpoint_str(const coap_endpoint_t *endpoint) { + static char szEndpoint[128]; + char *p = szEndpoint, *end = szEndpoint + sizeof(szEndpoint); + if (coap_print_addr(&endpoint->bind_addr, (unsigned char*)p, end - p) > 0) + p += strlen(p); + if (p + 6 < end) { + if (endpoint->proto == COAP_PROTO_UDP) { + strcpy(p, " UDP"); + p += 4; + } else if (endpoint->proto == COAP_PROTO_DTLS) { + strcpy(p, " DTLS"); + p += 5; + } else { + strcpy(p, " NONE"); + p += 5; + } + } + + return szEndpoint; +} +#endif /* COAP_SERVER_SUPPORT */ +#ifdef COAP_CLIENT_SUPPORT +void +coap_session_set_no_observe_cancel(coap_session_t *session) { + session->no_observe_cancel = 1; +} +#endif /* COAP_CLIENT_SUPPORT */ +#endif /* COAP_SESSION_C_ */ diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_subscribe.c b/examples/espidf-coap-server/components/libcoap/src/coap_subscribe.c new file mode 100644 index 000000000..7d2dc35db --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_subscribe.c @@ -0,0 +1,25 @@ +/* coap_subscribe.c -- subscription handling for CoAP + * see RFC7641 + * + * Copyright (C) 2010-2019,2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_subscribe.c + * @brief Subscription handling functions + */ + +#include "coap3/coap_internal.h" + +#if COAP_SERVER_SUPPORT +void +coap_subscription_init(coap_subscription_t *s) { + assert(s); + memset(s, 0, sizeof(coap_subscription_t)); +} +#endif /* COAP_SERVER_SUPPORT */ diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_tcp.c b/examples/espidf-coap-server/components/libcoap/src/coap_tcp.c new file mode 100644 index 000000000..e80b51021 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_tcp.c @@ -0,0 +1,324 @@ +/* + * coap_tcp.c -- TCP functions for libcoap + * + * Copyright (C) 2019 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_tcp.c + * @brief CoAP TCP handling functions + */ + +#include "coap3/coap_internal.h" + +#include +#include +#ifdef HAVE_SYS_SOCKET_H +# include +# define OPTVAL_T(t) (t) +# define OPTVAL_GT(t) (t) +#endif +#ifdef HAVE_SYS_IOCTL_H + #include +#endif +#ifdef HAVE_WS2TCPIP_H +#include +# define OPTVAL_T(t) (const char*)(t) +# define OPTVAL_GT(t) (char*)(t) +# undef CMSG_DATA +# define CMSG_DATA WSA_CMSG_DATA +#endif + +int +coap_tcp_is_supported(void) { + return !COAP_DISABLE_TCP; +} + +#if !COAP_DISABLE_TCP +int +coap_socket_connect_tcp1(coap_socket_t *sock, + const coap_address_t *local_if, + const coap_address_t *server, + int default_port, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + int on = 1; +#ifndef RIOT_VERSION + int off = 0; +#endif /* RIOT_VERSION */ +#ifdef _WIN32 + u_long u_on = 1; +#endif + coap_address_t connect_addr; + coap_address_copy( &connect_addr, server ); + + sock->flags &= ~COAP_SOCKET_CONNECTED; + sock->fd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0); + + if (sock->fd == COAP_INVALID_SOCKET) { + coap_log(LOG_WARNING, + "coap_socket_connect_tcp1: socket: %s\n", + coap_socket_strerror()); + goto error; + } + +#ifndef RIOT_VERSION +#ifdef _WIN32 + if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { +#else + if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { +#endif + coap_log(LOG_WARNING, + "coap_socket_connect_tcp1: ioctl FIONBIO: %s\n", + coap_socket_strerror()); + } +#endif /* RIOT_VERSION */ + + switch (server->addr.sa.sa_family) { + case AF_INET: + if (connect_addr.addr.sin.sin_port == 0) + connect_addr.addr.sin.sin_port = htons(default_port); + break; + case AF_INET6: + if (connect_addr.addr.sin6.sin6_port == 0) + connect_addr.addr.sin6.sin6_port = htons(default_port); +#ifndef RIOT_VERSION + /* Configure the socket as dual-stacked */ + if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_connect_tcp1: setsockopt IPV6_V6ONLY: %s\n", + coap_socket_strerror()); +#endif /* RIOT_VERSION */ + break; + default: + coap_log(LOG_ALERT, "coap_socket_connect_tcp1: unsupported sa_family\n"); + break; + } + + if (local_if && local_if->addr.sa.sa_family) { + coap_address_copy(local_addr, local_if); + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_connect_tcp1: setsockopt SO_REUSEADDR: %s\n", + coap_socket_strerror()); + if (bind(sock->fd, &local_if->addr.sa, + local_if->addr.sa.sa_family == AF_INET ? + (socklen_t)sizeof(struct sockaddr_in) : + (socklen_t)local_if->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_tcp1: bind: %s\n", + coap_socket_strerror()); + goto error; + } + } else { + local_addr->addr.sa.sa_family = server->addr.sa.sa_family; + } + + if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) { +#ifdef _WIN32 + if (WSAGetLastError() == WSAEWOULDBLOCK) { +#else + if (errno == EINPROGRESS) { +#endif + /* + * COAP_SOCKET_CONNECTED needs to be set here as there will be reads/writes + * by underlying TLS libraries during connect() and we do not want to + * assert() in coap_read_session() or coap_write_session() when called by coap_read() + */ + sock->flags |= COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CONNECTED; + return 1; + } + coap_log(LOG_WARNING, "coap_socket_connect_tcp1: connect: %s\n", + coap_socket_strerror()); + goto error; + } + + if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_tcp1: getsockname: %s\n", + coap_socket_strerror()); + } + + if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_tcp1: getpeername: %s\n", + coap_socket_strerror()); + } + + sock->flags |= COAP_SOCKET_CONNECTED; + return 1; + +error: + coap_socket_close(sock); + return 0; +} + +int +coap_socket_connect_tcp2(coap_socket_t *sock, + coap_address_t *local_addr, + coap_address_t *remote_addr) { + int error = 0; +#ifdef _WIN32 + int optlen = (int)sizeof( error ); +#else + socklen_t optlen = (socklen_t)sizeof( error ); +#endif + + sock->flags &= ~(COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CAN_CONNECT); + + if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, OPTVAL_GT(&error), + &optlen) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_finish_connect_tcp: getsockopt: %s\n", + coap_socket_strerror()); + } + + if (error) { + coap_log(LOG_WARNING, + "coap_socket_finish_connect_tcp: connect failed: %s\n", + coap_socket_format_errno(error)); + coap_socket_close(sock); + return 0; + } + + if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_tcp: getsockname: %s\n", + coap_socket_strerror()); + } + + if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_WARNING, "coap_socket_connect_tcp: getpeername: %s\n", + coap_socket_strerror()); + } + + return 1; +} + +int +coap_socket_bind_tcp(coap_socket_t *sock, + const coap_address_t *listen_addr, + coap_address_t *bound_addr) { + int on = 1; +#ifndef RIOT_VERSION + int off = 0; +#endif /* RIOT_VERSION */ +#ifdef _WIN32 + u_long u_on = 1; +#endif + + sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_STREAM, 0); + + if (sock->fd == COAP_INVALID_SOCKET) { + coap_log(LOG_WARNING, "coap_socket_bind_tcp: socket: %s\n", + coap_socket_strerror()); + goto error; + } + +#ifndef RIOT_VERSION +#ifdef _WIN32 + if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { +#else + if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { +#endif + coap_log(LOG_WARNING, "coap_socket_bind_tcp: ioctl FIONBIO: %s\n", + coap_socket_strerror()); + } +#endif /* RIOT_VERSION */ + if (setsockopt (sock->fd, SOL_SOCKET, SO_KEEPALIVE, OPTVAL_T(&on), + sizeof (on)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_bind_tcp: setsockopt SO_KEEPALIVE: %s\n", + coap_socket_strerror()); + + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), + sizeof(on)) == COAP_SOCKET_ERROR) + coap_log(LOG_WARNING, + "coap_socket_bind_tcp: setsockopt SO_REUSEADDR: %s\n", + coap_socket_strerror()); + + switch (listen_addr->addr.sa.sa_family) { + case AF_INET: + break; + case AF_INET6: +#ifndef RIOT_VERSION + /* Configure the socket as dual-stacked */ + if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR) + coap_log(LOG_ALERT, + "coap_socket_bind_tcp: setsockopt IPV6_V6ONLY: %s\n", + coap_socket_strerror()); +#endif /* RIOT_VERSION */ + break; + default: + coap_log(LOG_ALERT, "coap_socket_bind_tcp: unsupported sa_family\n"); + } + + if (bind(sock->fd, &listen_addr->addr.sa, + listen_addr->addr.sa.sa_family == AF_INET ? + (socklen_t)sizeof(struct sockaddr_in) : + (socklen_t)listen_addr->size) == COAP_SOCKET_ERROR) { + coap_log(LOG_ALERT, "coap_socket_bind_tcp: bind: %s\n", + coap_socket_strerror()); + goto error; + } + + bound_addr->size = (socklen_t)sizeof(*bound_addr); + if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) { + coap_log(LOG_WARNING, "coap_socket_bind_tcp: getsockname: %s\n", + coap_socket_strerror()); + goto error; + } + + if (listen(sock->fd, 5) == COAP_SOCKET_ERROR) { + coap_log(LOG_ALERT, "coap_socket_bind_tcp: listen: %s\n", + coap_socket_strerror()); + goto error; + } + + return 1; + +error: + coap_socket_close(sock); + return 0; +} + +int +coap_socket_accept_tcp(coap_socket_t *server, + coap_socket_t *new_client, + coap_address_t *local_addr, + coap_address_t *remote_addr) { +#ifndef RIOT_VERSION +#ifdef _WIN32 + u_long u_on = 1; +#else + int on = 1; +#endif +#endif /* RIOT_VERSION */ + + server->flags &= ~COAP_SOCKET_CAN_ACCEPT; + + new_client->fd = accept(server->fd, &remote_addr->addr.sa, + &remote_addr->size); + if (new_client->fd == COAP_INVALID_SOCKET) { + coap_log(LOG_WARNING, "coap_socket_accept_tcp: accept: %s\n", + coap_socket_strerror()); + return 0; + } + + if (getsockname( new_client->fd, &local_addr->addr.sa, &local_addr->size) < 0) + coap_log(LOG_WARNING, "coap_socket_accept_tcp: getsockname: %s\n", + coap_socket_strerror()); + +#ifndef RIOT_VERSION + #ifdef _WIN32 + if (ioctlsocket(new_client->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) { +#else + if (ioctl(new_client->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) { +#endif + coap_log(LOG_WARNING, "coap_socket_accept_tcp: ioctl FIONBIO: %s\n", + coap_socket_strerror()); + } +#endif /* RIOT_VERSION */ + return 1; +} +#endif /* !COAP_DISABLE_TCP */ diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_time.c b/examples/espidf-coap-server/components/libcoap/src/coap_time.c new file mode 100644 index 000000000..eec0c272c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_time.c @@ -0,0 +1,141 @@ +/* coap_time.c -- Clock Handling + * + * Copyright (C) 2015 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file coap_time.c + * @brief Clock handling functions + */ + +#include "coap3/coap_internal.h" + +#ifdef HAVE_TIME_H +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include /* _POSIX_TIMERS */ +#endif +#ifdef HAVE_WINSOCK2_H +#include +#include +#endif + +static coap_tick_t coap_clock_offset = 0; + +#if _POSIX_TIMERS && !defined(__APPLE__) + /* _POSIX_TIMERS is > 0 when clock_gettime() is available */ + + /* Use real-time clock for correct timestamps in coap_log(). */ +#define COAP_CLOCK CLOCK_REALTIME +#endif + +#ifdef HAVE_WINSOCK2_H +static int +gettimeofday(struct timeval *tp, TIME_ZONE_INFORMATION *tzp) { + (void)tzp; + static const uint64_t s_tUnixEpoch = 116444736000000000Ui64; + + FILETIME file_time; + ULARGE_INTEGER time; + uint64_t tUsSinceUnicEpoch; + + GetSystemTimeAsFileTime( &file_time ); + time.LowPart = file_time.dwLowDateTime; + time.HighPart = file_time.dwHighDateTime; + tUsSinceUnicEpoch = ( time.QuadPart - s_tUnixEpoch ) / 10; + + tp->tv_sec = (long)(tUsSinceUnicEpoch / 1000000); + tp->tv_usec = (long)(tUsSinceUnicEpoch % 1000000); + return 0; +} +#endif + +void +coap_clock_init(void) { +#ifdef COAP_CLOCK + struct timespec tv; + clock_gettime(COAP_CLOCK, &tv); +#else /* _POSIX_TIMERS */ + struct timeval tv; + gettimeofday(&tv, NULL); +#endif /* not _POSIX_TIMERS */ + + coap_clock_offset = tv.tv_sec; +} + +/* creates a Qx.frac from fval */ +#define Q(frac,fval) ((1 << (frac)) * (fval)) + +/* number of frac bits for sub-seconds */ +#define FRAC 10 + +/* rounds val up and right shifts by frac positions */ +#define SHR_FP(val,frac) (((coap_tick_t)((val) + (1 << ((frac) - 1)))) >> (frac)) + +void +coap_ticks(coap_tick_t *t) { + coap_tick_t tmp; + +#ifdef COAP_CLOCK + struct timespec tv; + clock_gettime(COAP_CLOCK, &tv); + /* Possible errors are (see clock_gettime(2)): + * EFAULT tp points outside the accessible address space. + * EINVAL The clk_id specified is not supported on this system. + * Both cases should not be possible here. + */ + + tmp = SHR_FP(tv.tv_nsec * Q(FRAC, (COAP_TICKS_PER_SECOND/1000000000.0)), FRAC); +#else /* _POSIX_TIMERS */ + /* Fall back to gettimeofday() */ + + struct timeval tv; + gettimeofday(&tv, NULL); + /* Possible errors are (see gettimeofday(2)): + * EFAULT One of tv or tz pointed outside the accessible address space. + * EINVAL Timezone (or something else) is invalid. + * Both cases should not be possible here. + */ + + tmp = SHR_FP(tv.tv_usec * Q(FRAC, (COAP_TICKS_PER_SECOND/1000000.0)), FRAC); +#endif /* not _POSIX_TIMERS */ + + /* Finally, convert temporary FP representation to multiple of + * COAP_TICKS_PER_SECOND */ + *t = tmp + (tv.tv_sec - coap_clock_offset) * COAP_TICKS_PER_SECOND; +} + +coap_time_t +coap_ticks_to_rt(coap_tick_t t) { + return coap_clock_offset + (t / COAP_TICKS_PER_SECOND); +} + +uint64_t coap_ticks_to_rt_us(coap_tick_t t) { + return (uint64_t)coap_clock_offset * 1000000 + (uint64_t)t * 1000000 / COAP_TICKS_PER_SECOND; +} + +coap_tick_t coap_ticks_from_rt_us(uint64_t t) { + return (coap_tick_t)((t - (uint64_t)coap_clock_offset * 1000000) * COAP_TICKS_PER_SECOND / 1000000); +} + +#undef Q +#undef FRAC +#undef SHR_FP + +#else /* HAVE_TIME_H */ + +/* make compilers happy that do not like empty modules */ +COAP_STATIC_INLINE void dummy(void) +{ +} + +#endif /* not HAVE_TIME_H */ + diff --git a/examples/espidf-coap-server/components/libcoap/src/coap_tinydtls.c b/examples/espidf-coap-server/components/libcoap/src/coap_tinydtls.c new file mode 100644 index 000000000..ebff84ed2 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/coap_tinydtls.c @@ -0,0 +1,1311 @@ +/* + * coap_tinydtls.c -- Datagram Transport Layer Support for libcoap with tinydtls + * + * Copyright (C) 2016-2020 Olaf Bergmann + * Copyright (C) 2020-2022 Jon Shallow + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_tinydtls.c + * @brief TinyDTLS specific handling functions + */ + +#include "coap3/coap_internal.h" + +#ifdef HAVE_LIBTINYDTLS + +/* We want TinyDTLS versions of these, not libcoap versions */ +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_URL +#undef PACKAGE_VERSION + +#include +#include +#include + +typedef struct coap_tiny_context_t { + struct dtls_context_t *dtls_context; + coap_context_t *coap_context; +#ifdef DTLS_ECC + coap_dtls_pki_t setup_data; + coap_binary_t *priv_key; + coap_binary_t *pub_key; +#endif /* DTLS_ECC */ +} coap_tiny_context_t; + +static dtls_tick_t dtls_tick_0 = 0; +static coap_tick_t coap_tick_0 = 0; + +int +coap_dtls_is_supported(void) { + return 1; +} + +void coap_dtls_startup(void) { + dtls_init(); + dtls_ticks(&dtls_tick_0); + coap_ticks(&coap_tick_0); +} + +void coap_dtls_shutdown(void) { +} + +void * +coap_dtls_get_tls(const coap_session_t *c_session, + coap_tls_library_t *tls_lib) { + if (tls_lib) + *tls_lib = COAP_TLS_LIBRARY_TINYDTLS; + if (c_session && c_session->context && c_session->context->dtls_context) { + const coap_tiny_context_t *t_context = + (const coap_tiny_context_t *)c_session->context->dtls_context; + + return t_context->dtls_context; + } + return NULL; +} + +void +coap_dtls_set_log_level(int level) { + dtls_set_log_level(level); +} + +int +coap_dtls_get_log_level(void) { + return dtls_get_log_level(); +} + +static void get_session_addr(const session_t *s, coap_address_t *a) { +#ifdef WITH_CONTIKI + a->addr = s->addr; + a->port = s->port; +#else + if (s->addr.sa.sa_family == AF_INET6) { + a->size = (socklen_t)sizeof(a->addr.sin6); + a->addr.sin6 = s->addr.sin6; + } else if (s->addr.sa.sa_family == AF_INET) { + a->size = (socklen_t)sizeof(a->addr.sin); + a->addr.sin = s->addr.sin; + } else { + a->size = (socklen_t)s->size; + a->addr.sa = s->addr.sa; + } +#endif +} + +static void put_session_addr(const coap_address_t *a, session_t *s) { +#ifdef WITH_CONTIKI + s->size = (unsigned char)sizeof(s->addr); + s->addr = a->addr; + s->port = a->port; +#else + if (a->addr.sa.sa_family == AF_INET6) { + s->size = (socklen_t)sizeof(s->addr.sin6); + s->addr.sin6 = a->addr.sin6; + } else if (a->addr.sa.sa_family == AF_INET) { + s->size = (socklen_t)sizeof(s->addr.sin); + s->addr.sin = a->addr.sin; + } else { + s->size = (socklen_t)a->size; + s->addr.sa = a->addr.sa; + } +#endif +} + +static int +dtls_send_to_peer(struct dtls_context_t *dtls_context, + session_t *dtls_session, uint8 *data, size_t len) { + coap_tiny_context_t *t_context = + (coap_tiny_context_t *)dtls_get_app_data(dtls_context); + coap_context_t *coap_context = t_context ? t_context->coap_context : NULL; + coap_session_t *coap_session; + coap_address_t remote_addr; + + assert(coap_context); + get_session_addr(dtls_session, &remote_addr); + coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex); + if (!coap_session) { + coap_log(LOG_WARNING, "dtls_send_to_peer: cannot find local interface\n"); + return -3; + } + return (int)coap_session_send(coap_session, data, len); +} + +static int +dtls_application_data(struct dtls_context_t *dtls_context, + session_t *dtls_session, uint8 *data, size_t len) { + coap_tiny_context_t *t_context = + (coap_tiny_context_t *)dtls_get_app_data(dtls_context); + coap_context_t *coap_context = t_context ? t_context->coap_context : NULL; + coap_session_t *coap_session; + coap_address_t remote_addr; + + assert(coap_context); + get_session_addr(dtls_session, &remote_addr); + coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex); + if (!coap_session) { + coap_log(LOG_DEBUG, + "dropped message that was received on invalid interface\n"); + return -1; + } + + return coap_handle_dgram(coap_context, coap_session, data, len); +} + +static int coap_event_dtls = 0; + +static int +dtls_event(struct dtls_context_t *dtls_context, + session_t *dtls_session, + dtls_alert_level_t level, + uint16_t code) { + (void)dtls_context; + (void)dtls_session; + + if (level == DTLS_ALERT_LEVEL_FATAL) + coap_event_dtls = COAP_EVENT_DTLS_ERROR; + + /* handle DTLS events */ + switch (code) { + case DTLS_ALERT_CLOSE_NOTIFY: + { + coap_event_dtls = COAP_EVENT_DTLS_CLOSED; + break; + } + case DTLS_EVENT_CONNECTED: + { + coap_event_dtls = COAP_EVENT_DTLS_CONNECTED; + break; + } + case DTLS_EVENT_RENEGOTIATE: + { + coap_event_dtls = COAP_EVENT_DTLS_RENEGOTIATE; + break; + } + default: + ; + } + + return 0; +} + +/* This function is the "key store" for tinyDTLS. It is called to + * retrieve a key for the given identity within this particular + * session. */ +static int +get_psk_info(struct dtls_context_t *dtls_context, + const session_t *dtls_session, + dtls_credentials_type_t type, + const uint8_t *id, size_t id_len, + unsigned char *result, size_t result_length) { + + coap_tiny_context_t *t_context = + (coap_tiny_context_t *)dtls_get_app_data(dtls_context); + coap_context_t *coap_context = t_context ? t_context->coap_context : NULL; + coap_session_t *coap_session; + int fatal_error = DTLS_ALERT_INTERNAL_ERROR; + coap_address_t remote_addr; +#if COAP_CLIENT_SUPPORT + coap_dtls_cpsk_t *setup_cdata; + const coap_bin_const_t *psk_identity; + const coap_dtls_cpsk_info_t *cpsk_info; +#endif /* COAP_CLIENT_SUPPORT */ + const coap_bin_const_t *psk_key; +#if COAP_SERVER_SUPPORT + coap_dtls_spsk_t *setup_sdata; + const coap_bin_const_t *psk_hint; +#endif /* COAP_SERVER_SUPPORT */ + + assert(coap_context); + get_session_addr(dtls_session, &remote_addr); + coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex); + if (!coap_session) { + coap_log(LOG_DEBUG, "cannot get PSK, session not found\n"); + goto error; + } + + switch (type) { + case DTLS_PSK_IDENTITY: + +#if COAP_CLIENT_SUPPORT + if (coap_session->type != COAP_SESSION_TYPE_CLIENT) + goto error; + + setup_cdata = &coap_session->cpsk_setup_data; + + coap_bin_const_t temp; + temp.s = id; + temp.length = id_len; + coap_session_refresh_psk_hint(coap_session, &temp); + + coap_log(LOG_DEBUG, "got psk_identity_hint: '%.*s'\n", (int)id_len, + id ? (const char*)id : ""); + + if (setup_cdata->validate_ih_call_back) { + coap_str_const_t lhint; + + lhint.length = id_len; + lhint.s = id; + cpsk_info = + setup_cdata->validate_ih_call_back(&lhint, + coap_session, + setup_cdata->ih_call_back_arg); + if (cpsk_info) { + psk_identity = &cpsk_info->identity; + coap_session_refresh_psk_identity(coap_session, &cpsk_info->identity); + coap_session_refresh_psk_key(coap_session, &cpsk_info->key); + } + else { + psk_identity = NULL; + } + } + else { + psk_identity = coap_get_session_client_psk_identity(coap_session); + } + if (psk_identity == NULL) { + coap_log(LOG_WARNING, "no PSK identity given\n"); + fatal_error = DTLS_ALERT_CLOSE_NOTIFY; + goto error; + } + if (psk_identity->length > result_length) { + coap_log(LOG_WARNING, + "psk_identity too large, truncated to %zd bytes\n", + result_length); + } + else { + /* Reduce to match */ + result_length = psk_identity->length; + } + memcpy(result, psk_identity->s, result_length); + return result_length; +#else /* ! COAP_CLIENT_SUPPORT */ + return 0; +#endif /* ! COAP_CLIENT_SUPPORT */ + + case DTLS_PSK_KEY: +#if COAP_CLIENT_SUPPORT + if (coap_session->type == COAP_SESSION_TYPE_CLIENT) { + psk_key = coap_get_session_client_psk_key(coap_session); + if (psk_key == NULL) { + coap_log(LOG_WARNING, "no PSK key given\n"); + fatal_error = DTLS_ALERT_CLOSE_NOTIFY; + goto error; + } + if (psk_key->length > result_length) { + coap_log(LOG_WARNING, + "psk_key too large, truncated to %zd bytes\n", + result_length); + } + else { + /* Reduce to match */ + result_length = psk_key->length; + } + memcpy(result, psk_key->s, result_length); + return result_length; + } +#endif /* COAP_CLIENT_SUPPORT */ +#if COAP_SERVER_SUPPORT + if (coap_session->type != COAP_SESSION_TYPE_CLIENT) { + coap_bin_const_t lidentity; + + lidentity.length = id ? id_len : 0; + lidentity.s = id ? (const uint8_t*)id : (const uint8_t *)""; + setup_sdata = &coap_session->context->spsk_setup_data; + + /* Track the Identity being used */ + coap_session_refresh_psk_identity(coap_session, &lidentity); + + coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n", + (int)lidentity.length, lidentity.s); + + if (setup_sdata->validate_id_call_back) { + psk_key = + setup_sdata->validate_id_call_back(&lidentity, + coap_session, + setup_sdata->id_call_back_arg); + } + else { + psk_key = coap_get_session_server_psk_key(coap_session); + } + + if (psk_key == NULL) { + coap_log(LOG_WARNING, "no PSK key given\n"); + return 0; + } + if (setup_sdata->validate_id_call_back) + coap_session_refresh_psk_key(coap_session, psk_key); + if (psk_key->length > result_length) { + coap_log(LOG_WARNING, + "psk_key too large, truncated to %zd bytes\n", + result_length); + } + else { + /* Reduce to match */ + result_length = psk_key->length; + } + memcpy(result, psk_key->s, result_length); + return result_length; + } +#endif /* COAP_SERVER_SUPPORT */ + return 0; + + case DTLS_PSK_HINT: +#if COAP_SERVER_SUPPORT + psk_hint = coap_get_session_server_psk_hint(coap_session); + if (psk_hint == NULL) + return 0; + if (psk_hint->length > result_length) { + coap_log(LOG_WARNING, + "psk_hint too large, truncated to %zd bytes\n", + result_length); + } + else { + /* Reduce to match */ + result_length = psk_hint->length; + } + memcpy(result, psk_hint->s, result_length); + return result_length; +#else /* COAP_SERVER_SUPPORT */ + return 0; +#endif /* COAP_SERVER_SUPPORT */ + + default: + coap_log(LOG_WARNING, "unsupported request type: %d\n", type); + } + +error: + return dtls_alert_fatal_create(fatal_error); +} + +#ifdef DTLS_ECC +static int +get_ecdsa_key(struct dtls_context_t *dtls_context, + const session_t *dtls_session COAP_UNUSED, + const dtls_ecdsa_key_t **result) { + static dtls_ecdsa_key_t ecdsa_key; + coap_tiny_context_t *t_context = + (coap_tiny_context_t *)dtls_get_app_data(dtls_context); + + ecdsa_key.curve = DTLS_ECDH_CURVE_SECP256R1; + ecdsa_key.priv_key = t_context->priv_key->s; + ecdsa_key.pub_key_x = t_context->pub_key->s; + ecdsa_key.pub_key_y = &t_context->pub_key->s[DTLS_EC_KEY_SIZE]; + + *result = &ecdsa_key; + return 0; +} + +/* first part of Raw public key, the is the start of the Subject Public Key */ +static const unsigned char cert_asn1_header[] = { + 0x30, 0x59, /* SEQUENCE, length 89 bytes */ + 0x30, 0x13, /* SEQUENCE, length 19 bytes */ + 0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */ + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, + 0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */ + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, + 0x03, 0x42, 0x00, /* BIT STRING, length 66 bytes, 0 bits unused */ + 0x04 /* uncompressed, followed by the r and s values of the public key */ +}; +#define DTLS_CE_LENGTH (sizeof(cert_asn1_header) + key_size + key_size) + +static int +verify_ecdsa_key(struct dtls_context_t *dtls_context COAP_UNUSED, + const session_t *dtls_session COAP_UNUSED, + const uint8_t *other_pub_x, + const uint8_t *other_pub_y, + size_t key_size) { + coap_tiny_context_t *t_context = + (coap_tiny_context_t *)dtls_get_app_data(dtls_context); + if (t_context && t_context->setup_data.validate_cn_call_back) { + /* Need to build asn.1 certificate - code taken from tinydtls */ + uint8 *p; + uint8 buf[DTLS_CE_LENGTH]; + coap_session_t *c_session; + coap_address_t remote_addr; + + /* Certificate + * + * Start message construction at beginning of buffer. */ + p = buf; + + memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header)); + p += sizeof(cert_asn1_header); + + memcpy(p, other_pub_x, key_size); + p += key_size; + + memcpy(p, other_pub_y, key_size); + p += key_size; + + assert(p <= (buf + sizeof(buf))); + + get_session_addr(dtls_session, &remote_addr); + c_session = coap_session_get_by_peer(t_context->coap_context, + &remote_addr, dtls_session->ifindex); + if (!c_session) + return -3; + if (!t_context->setup_data.validate_cn_call_back(COAP_DTLS_RPK_CERT_CN, + buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg)) { + return -1; + } + } + return 0; +} +static dtls_handler_t ec_cb = { + .write = dtls_send_to_peer, + .read = dtls_application_data, + .event = dtls_event, + .get_psk_info = NULL, + .get_ecdsa_key = get_ecdsa_key, + .verify_ecdsa_key = verify_ecdsa_key +}; +#endif /* DTLS_ECC */ + +static dtls_handler_t psk_cb = { + .write = dtls_send_to_peer, + .read = dtls_application_data, + .event = dtls_event, + .get_psk_info = get_psk_info, +#ifdef DTLS_ECC + .get_ecdsa_key = NULL, + .verify_ecdsa_key = NULL +#endif +}; + +void * +coap_dtls_new_context(coap_context_t *coap_context) { + coap_tiny_context_t *t_context = coap_malloc(sizeof(coap_tiny_context_t)); + struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) : NULL; + if (!dtls_context) + goto error; + memset(t_context, 0, sizeof(coap_tiny_context_t)); + t_context->coap_context = coap_context; + t_context->dtls_context = dtls_context; + dtls_set_handler(dtls_context, &psk_cb); + return t_context; +error: + if (t_context) + coap_free(t_context); + if (dtls_context) + coap_dtls_free_context(dtls_context); + return NULL; +} + +void +coap_dtls_free_context(void *handle) { + if (handle) { + coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle; +#ifdef DTLS_ECC + if (t_context->priv_key) { + coap_delete_binary(t_context->priv_key); + t_context->priv_key = NULL; + } + if (t_context->pub_key) { + coap_delete_binary(t_context->pub_key); + t_context->pub_key = NULL; + } +#endif /* DTLS_ECC */ + if (t_context->dtls_context) + dtls_free_context(t_context->dtls_context); + coap_free(t_context); + } +} + +static session_t * +coap_dtls_new_session(coap_session_t *session) { + session_t *dtls_session = coap_malloc_type(COAP_DTLS_SESSION, sizeof(session_t)); + + if (dtls_session) { + /* create tinydtls session object from remote address and local + * endpoint handle */ + dtls_session_init(dtls_session); + put_session_addr(&session->addr_info.remote, dtls_session); + dtls_session->ifindex = session->ifindex; + coap_log(LOG_DEBUG, "***new session %p\n", (void *)dtls_session); + } + + return dtls_session; +} + +#if COAP_SERVER_SUPPORT +void *coap_dtls_new_server_session(coap_session_t *session) { + return coap_dtls_new_session(session); +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +void *coap_dtls_new_client_session(coap_session_t *session) { + dtls_peer_t *peer; + coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context; + dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL; + session_t *dtls_session = dtls_context ? coap_dtls_new_session(session) : NULL; + + if (!dtls_session) + return NULL; + peer = + dtls_get_peer(dtls_context, dtls_session); + + if (!peer) { + /* The peer connection does not yet exist. */ + /* dtls_connect() returns a value greater than zero if a new + * connection attempt is made, 0 for session reuse. */ + if (dtls_connect(dtls_context, dtls_session) >= 0) { + peer = + dtls_get_peer(dtls_context, dtls_session); + } + } + + if (!peer) { + /* delete existing session because the peer object has been invalidated */ + coap_free_type(COAP_DTLS_SESSION, dtls_session); + dtls_session = NULL; + } + + return dtls_session; +} +#endif /* COAP_CLIENT_SUPPORT */ + +void +coap_dtls_session_update_mtu(coap_session_t *session) { + (void)session; +} + +void +coap_dtls_free_session(coap_session_t *coap_session) { + coap_tiny_context_t *t_context = + (coap_tiny_context_t *)coap_session->context->dtls_context; + dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL; + + if (dtls_context == NULL) + return; + if (coap_session->tls && dtls_context) { + dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->tls); + if ( peer ) + dtls_reset_peer(dtls_context, peer); + else + dtls_close(dtls_context, (session_t *)coap_session->tls); + coap_log(LOG_DEBUG, "***removed session %p\n", coap_session->tls); + coap_free_type(COAP_DTLS_SESSION, coap_session->tls); + coap_session->tls = NULL; + coap_handle_event(coap_session->context, COAP_EVENT_DTLS_CLOSED, coap_session); + } +} + +int +coap_dtls_send(coap_session_t *session, + const uint8_t *data, + size_t data_len +) { + int res; + uint8_t *data_rw; + coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context; + dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL; + + assert(dtls_context); + coap_log(LOG_DEBUG, "call dtls_write\n"); + + coap_event_dtls = -1; + /* Need to do this to not get a compiler warning about const parameters */ + memcpy (&data_rw, &data, sizeof(data_rw)); + res = dtls_write(dtls_context, + (session_t *)session->tls, data_rw, data_len); + + if (res < 0) + coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n"); + + if (coap_event_dtls >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(session->context, coap_event_dtls, session); + if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) + coap_session_connected(session); + else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) + coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + } + + return res; +} + +int coap_dtls_is_context_timeout(void) { + return 1; +} + +coap_tick_t coap_dtls_get_context_timeout(void *tiny_context) { + clock_time_t next = 0; + coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context; + dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL; + if (tiny_context) + dtls_check_retransmit(dtls_context, &next); + if (next > 0) + return ((coap_tick_t)(next - dtls_tick_0)) * COAP_TICKS_PER_SECOND / DTLS_TICKS_PER_SECOND + coap_tick_0; + return 0; +} + +coap_tick_t coap_dtls_get_timeout(coap_session_t *session, coap_tick_t now) { + (void)session; + (void)now; + return 0; +} + +/* + * return 1 timed out + * 0 still timing out + */ +int +coap_dtls_handle_timeout(coap_session_t *session) { + (void)session; + return 0; +} + +int +coap_dtls_receive(coap_session_t *session, + const uint8_t *data, + size_t data_len +) { + session_t *dtls_session = (session_t *)session->tls; + int err; + uint8_t *data_rw; + coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context; + dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL; + + assert(dtls_context); + coap_event_dtls = -1; + /* Need to do this to not get a compiler warning about const parameters */ + memcpy (&data_rw, &data, sizeof(data_rw)); + err = dtls_handle_message(dtls_context, dtls_session, data_rw, (int)data_len); + + if (err){ + coap_event_dtls = COAP_EVENT_DTLS_ERROR; + } + + if (coap_event_dtls >= 0) { + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED) + coap_handle_event(session->context, coap_event_dtls, session); + if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) + coap_session_connected(session); + else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) + coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + } + + return err; +} + +#if COAP_SERVER_SUPPORT +int +coap_dtls_hello(coap_session_t *session, + const uint8_t *data, + size_t data_len +) { + session_t dtls_session; + coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context; + dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL; + uint8_t *data_rw; + + assert(dtls_context); + dtls_session_init(&dtls_session); + put_session_addr(&session->addr_info.remote, &dtls_session); + dtls_session.ifindex = session->ifindex; + /* Need to do this to not get a compiler warning about const parameters */ + memcpy (&data_rw, &data, sizeof(data_rw)); + int res = dtls_handle_message(dtls_context, &dtls_session, + data_rw, (int)data_len); + if (res >= 0) { + if (dtls_get_peer(dtls_context, &dtls_session)) + res = 1; + else + res = 0; + } + return res; +} +#endif /* COAP_SERVER_SUPPORT */ + +unsigned int coap_dtls_get_overhead(coap_session_t *session) { + (void)session; + return 13 + 8 + 8; +} + +int coap_tls_is_supported(void) { + return 0; +} + +coap_tls_version_t * +coap_get_tls_library_version(void) { + static coap_tls_version_t version; + const char *vers = dtls_package_version(); + + version.version = 0; + if (vers) { + long int p1, p2 = 0, p3 = 0; + char* endptr; + + p1 = strtol(vers, &endptr, 10); + if (*endptr == '.') { + p2 = strtol(endptr+1, &endptr, 10); + if (*endptr == '.') { + p3 = strtol(endptr+1, &endptr, 10); + } + } + version.version = (p1 << 16) | (p2 << 8) | p3; + } + version.built_version = version.version; + version.type = COAP_TLS_LIBRARY_TINYDTLS; + return &version; +} + +#ifdef DTLS_ECC +static const uint8_t b64_6[256] = + { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, +/* + / */ + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, +/* 0 1 2 3 4 5 6 7 8 9 = */ + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, +/* A B C D E F G H I J K L M N O */ + 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +/* P Q R S T U V W X Y Z */ + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, +/* a b c d e f g h i j k l m n o */ + 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, +/* p q r s t u v w x y z */ + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 + }; + +/* caller must free off returned coap_binary_t* */ +static coap_binary_t * +pem_base64_decode (const uint8_t *data, size_t size) +{ + uint8_t *tbuf = coap_malloc(size); + size_t nbytesdecoded; + size_t i; + coap_binary_t *decoded; + uint8_t *ptr; + uint8_t *out; + size_t nb64bytes = 0; + + for (i = 0; i < size; i++) { + switch (data[i]) { + case ' ': + case '\r': + case '\n': + case '\t': + break; + default: + if (b64_6[data[i]] == 64) + goto end; + tbuf[nb64bytes++] = data[i]; + break; + } + } + +end: + nbytesdecoded = ((nb64bytes + 3) / 4) * 3; + decoded = coap_new_binary(nbytesdecoded + 1); + if (!decoded) + return NULL; + + out = decoded->s; + ptr = tbuf; + + while (nb64bytes > 4) { + *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4; + *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2; + *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]]; + ptr += 4; + nb64bytes -= 4; + } + + /* Note: (nb64bytes == 1) is an error */ + if (nb64bytes > 1) { + *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4; + } + if (nb64bytes > 2) { + *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2; + } + if (nb64bytes > 3) { + *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]]; + } + + decoded->length = nbytesdecoded - ((4 - nb64bytes) & 3); + coap_free(tbuf); + return decoded; +} + +typedef coap_binary_t * (*asn1_callback)(const uint8_t *data, size_t size); + +static int +asn1_verify_privkey(const uint8_t *data, size_t size) +{ + /* Check if we have the private key (with optional leading 0x00) */ + /* skip leading 0x00 */ + if (size - 1 == DTLS_EC_KEY_SIZE && *data == '\000') { + --size; + ++data; + } + + /* Check if we have the private key */ + if (size != DTLS_EC_KEY_SIZE) + return 0; + + return 1; +} + +static int +asn1_verify_pubkey(const uint8_t *data, size_t size) +{ + (void)data; + + /* We have the public key + (with a leading 0x00 (no unused bits) 0x04 (not compressed() */ + if (size - 2 != 2 * DTLS_EC_KEY_SIZE) + return 0; + + return 1; +} + +static int +asn1_verify_curve(const uint8_t *data, size_t size) +{ + static uint8_t prime256v1_oid[] = + /* OID 1.2.840.10045.3.1.7 */ + { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 }; + + /* Check that we have the correct EC (only one supported) */ + if (size != sizeof(prime256v1_oid) || + memcmp(data, prime256v1_oid, size) != 0) + return 0; + + return 1; +} + +static int +asn1_verify_pkcs8_version(const uint8_t *data, size_t size) +{ + /* Check that we have the version */ + if (size != 1 || *data != 0) + return 0; + + return 1; +} + +static int +asn1_verify_ec_identifier(const uint8_t *data, size_t size) +{ + static uint8_t ec_public_key_oid[] = + /* OID 1.2.840.10045.2.1 */ + { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 }; + + /* Check that we have the correct ecPublicKey */ + if (size != sizeof(ec_public_key_oid) || + memcmp(data, ec_public_key_oid, size) != 0) + return 0; + + return 1; +} + +static int +asn1_verify_ec_key(const uint8_t *data, size_t size) +{ + (void)data; + + if (size == 0) + return 0; + + return 1; +} + +static int +asn1_derive_keys(coap_tiny_context_t *t_context, + const uint8_t *priv_data, size_t priv_len, + const uint8_t *pub_data, size_t pub_len, + int is_pkcs8) +{ + coap_binary_t *test; + + t_context->priv_key = get_asn1_tag(COAP_ASN1_OCTETSTRING, priv_data, + priv_len, asn1_verify_privkey); + if (!t_context->priv_key) { + coap_log(LOG_INFO, "EC Private Key (RPK) invalid\n"); + return 0; + } + /* skip leading 0x00 */ + if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE && + t_context->priv_key->s[0] == '\000') { + t_context->priv_key->length--; + t_context->priv_key->s++; + } + + if (!is_pkcs8) { + /* pkcs8 abstraction tested for valid eliptic curve */ + test = get_asn1_tag(COAP_ASN1_IDENTIFIER, priv_data, priv_len, + asn1_verify_curve); + if (!test) { + coap_log(LOG_INFO, "EC Private Key (RPK) invalid elliptic curve\n"); + coap_delete_binary(t_context->priv_key); + t_context->priv_key = NULL; + return 0; + } + coap_delete_binary(test); + } + + t_context->pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, pub_data, pub_len, + asn1_verify_pubkey); + if (!t_context->pub_key) { + coap_log(LOG_INFO, "EC Public Key (RPK) invalid\n"); + coap_delete_binary(t_context->priv_key); + t_context->priv_key = NULL; + return 0; + } + /* Drop leading 0x00 and 0x04 */ + t_context->pub_key->s += 2; + t_context->pub_key->length -= 2; + dtls_set_handler(t_context->dtls_context, &ec_cb); + return 1; +} + +static coap_binary_t * +ec_abstract_pkcs8_asn1(const uint8_t *asn1_ptr, size_t asn1_length) +{ + coap_binary_t *test; + + test = get_asn1_tag(COAP_ASN1_INTEGER, asn1_ptr, asn1_length, + asn1_verify_pkcs8_version); + if (!test) + return 0; + + coap_delete_binary(test); + + test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length, + asn1_verify_ec_identifier); + if (!test) + return 0; + coap_delete_binary(test); + + test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length, + asn1_verify_curve); + if (!test) { + coap_log(LOG_INFO, "EC Private Key (RPK) invalid elliptic curve\n"); + return 0; + } + coap_delete_binary(test); + + test = get_asn1_tag(COAP_ASN1_OCTETSTRING, asn1_ptr, asn1_length, + asn1_verify_ec_key); + return test; +} + +static coap_binary_t * +pem_decode_mem_asn1(const char *begstr, const uint8_t *str) +{ + char *bcp = str ? strstr((const char*)str, begstr) : NULL; + char *tcp = bcp ? strstr(bcp, "-----END ") : NULL; + + if (bcp && tcp) { + bcp += strlen(begstr); + return pem_base64_decode ((const uint8_t *)bcp, tcp - bcp); + } + return NULL; +} + +#endif /* DTLS_ECC */ + +int +coap_dtls_context_set_pki(coap_context_t *ctx, + const coap_dtls_pki_t* setup_data, + const coap_dtls_role_t role COAP_UNUSED +) { +#ifdef DTLS_ECC + coap_tiny_context_t *t_context; + coap_binary_t *asn1_priv; + coap_binary_t *asn1_pub; + coap_binary_t *asn1_temp; + int is_pkcs8 = 0; + + if (!setup_data) + return 0; + if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION) + return 0; + if (!setup_data->is_rpk_not_cert) { + coap_log(LOG_WARNING, "Only RPK, not full PKI is supported\n"); + return 0; + } + if (!ctx) + return 0; + t_context = (coap_tiny_context_t *)ctx->dtls_context; + if (!t_context) + return 0; + if (t_context->priv_key) { + coap_delete_binary(t_context->priv_key); + t_context->priv_key = NULL; + } + if (t_context->pub_key) { + coap_delete_binary(t_context->pub_key); + t_context->pub_key = NULL; + } + t_context->setup_data = *setup_data; + + /* All should be RPK only now */ + switch (setup_data->pki_key.key_type) { + case COAP_PKI_KEY_PEM: + coap_log(LOG_WARNING, "RPK keys cannot be in COAP_PKI_KEY_PEM format\n"); + break; + case COAP_PKI_KEY_PEM_BUF: + if (setup_data->pki_key.key.pem_buf.public_cert && + setup_data->pki_key.key.pem_buf.public_cert[0] && + setup_data->pki_key.key.pem_buf.private_key && + setup_data->pki_key.key.pem_buf.private_key[0]) { + /* Need to take PEM memory information and convert to binary */ + asn1_priv = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----", + setup_data->pki_key.key.pem_buf.private_key); + if (!asn1_priv) { + asn1_priv = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----", + setup_data->pki_key.key.pem_buf.private_key); + if (!asn1_priv) { + coap_log(LOG_INFO, "Private Key (RPK) invalid\n"); + return 0; + } + asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->s, asn1_priv->length); + if (!asn1_temp) { + coap_log(LOG_INFO, "PKCS#8 Private Key (RPK) invalid\n"); + coap_delete_binary(asn1_priv); + return 0; + } + coap_delete_binary(asn1_priv); + asn1_priv = asn1_temp; + is_pkcs8 = 1; + } + asn1_pub = pem_decode_mem_asn1( + "-----BEGIN PUBLIC KEY-----", + setup_data->pki_key.key.pem_buf.public_cert); + if (!asn1_pub) { + asn1_pub = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----", + setup_data->pki_key.key.pem_buf.private_key); + if (!asn1_pub) { + asn1_pub = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----", + setup_data->pki_key.key.pem_buf.private_key); + if (!asn1_pub) { + coap_log(LOG_INFO, "Public Key (RPK) invalid\n"); + coap_delete_binary(asn1_priv); + return 0; + } + asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->s, asn1_pub->length); + if (!asn1_temp) { + coap_log(LOG_INFO, "PKCS#8 Private Key (RPK) invalid\n"); + coap_delete_binary(asn1_priv); + coap_delete_binary(asn1_pub); + return 0; + } + coap_delete_binary(asn1_pub); + asn1_pub = asn1_temp; + is_pkcs8 = 1; + } + } + if (!asn1_derive_keys(t_context, asn1_priv->s, asn1_priv->length, + asn1_pub->s, asn1_pub->length, is_pkcs8)) { + coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n"); + coap_delete_binary(asn1_priv); + coap_delete_binary(asn1_pub); + return 0; + } + coap_delete_binary(asn1_priv); + coap_delete_binary(asn1_pub); + return 1; + } + break; + case COAP_PKI_KEY_ASN1: + if (setup_data->pki_key.key.asn1.private_key && + setup_data->pki_key.key.asn1.private_key_len && + setup_data->pki_key.key.asn1.private_key_type == COAP_ASN1_PKEY_EC) { + const uint8_t* private_key = setup_data->pki_key.key.asn1.private_key; + size_t private_key_len = setup_data->pki_key.key.asn1.private_key_len; + + /* Check to see whether this is in pkcs8 format or not */ + asn1_temp = ec_abstract_pkcs8_asn1( + setup_data->pki_key.key.asn1.private_key, + setup_data->pki_key.key.asn1.private_key_len); + if (asn1_temp) { + private_key = asn1_temp->s; + private_key_len = asn1_temp->length; + is_pkcs8 = 1; + } + /* Need to take ASN1 memory information and convert to binary */ + if (setup_data->pki_key.key.asn1.public_cert && + setup_data->pki_key.key.asn1.public_cert_len) { + if (!asn1_derive_keys(t_context, + private_key, + private_key_len, + setup_data->pki_key.key.asn1.public_cert, + setup_data->pki_key.key.asn1.public_cert_len, + is_pkcs8)) { + coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n"); + if (asn1_temp) coap_delete_binary(asn1_temp); + return 0; + } + } + else { + if (!asn1_derive_keys(t_context, + private_key, + private_key_len, + private_key, + private_key_len, + is_pkcs8)) { + coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n"); + if (asn1_temp) coap_delete_binary(asn1_temp); + return 0; + } + } + return 1; + } + break; + case COAP_PKI_KEY_PKCS11: + coap_log(LOG_WARNING, "RPK keys cannot be in COAP_PKI_KEY_PCKS11 format\n"); + break; + default: + break; + } +#else /* ! DTLS_ECC */ + (void)ctx; + (void)setup_data; +#endif /* ! DTLS_ECC */ + return 0; +} + +int +coap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED, + const char *ca_file COAP_UNUSED, + const char *ca_path COAP_UNUSED +) { + coap_log(LOG_WARNING, "Root CAs PKI not supported\n"); + return 0; +} + +#if COAP_CLIENT_SUPPORT +int +coap_dtls_context_set_cpsk(coap_context_t *coap_context COAP_UNUSED, + coap_dtls_cpsk_t *setup_data +) { + if (!setup_data) + return 0; + + return 1; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +int +coap_dtls_context_set_spsk(coap_context_t *coap_context COAP_UNUSED, + coap_dtls_spsk_t *setup_data +) { + if (!setup_data) + return 0; + + if (setup_data->validate_sni_call_back) { + coap_log(LOG_WARNING, + "CoAP Server with TinyDTLS does not support SNI selection\n"); + } + + return 1; +} +#endif /* COAP_SERVER_SUPPORT */ + +int +coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED) +{ + return 1; +} + +#if !COAP_DISABLE_TCP +#if COAP_CLIENT_SUPPORT +void *coap_tls_new_client_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED) { + return NULL; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if COAP_SERVER_SUPPORT +void *coap_tls_new_server_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED) { + return NULL; +} +#endif /* COAP_SERVER_SUPPORT */ + +void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED) { +} + +ssize_t coap_tls_write(coap_session_t *session COAP_UNUSED, + const uint8_t *data COAP_UNUSED, + size_t data_len COAP_UNUSED +) { + return -1; +} + +ssize_t coap_tls_read(coap_session_t *session COAP_UNUSED, + uint8_t *data COAP_UNUSED, + size_t data_len COAP_UNUSED +) { + return -1; +} +#endif /* !COAP_DISABLE_TCP */ + +#if COAP_SERVER_SUPPORT +coap_digest_ctx_t * +coap_digest_setup(void) { + dtls_sha256_ctx *digest_ctx = coap_malloc(sizeof(dtls_sha256_ctx)); + + if (digest_ctx) { + dtls_sha256_init(digest_ctx); + } + + return digest_ctx; +} + +void +coap_digest_free(coap_digest_ctx_t *digest_ctx) { + coap_free(digest_ctx); +} + +int +coap_digest_update(coap_digest_ctx_t *digest_ctx, + const uint8_t *data, + size_t data_len) { + dtls_sha256_update(digest_ctx, data, data_len); + + return 1; +} + +int +coap_digest_final(coap_digest_ctx_t *digest_ctx, + coap_digest_t *digest_buffer) { + dtls_sha256_final((uint8_t*)digest_buffer, digest_ctx); + + coap_digest_free(digest_ctx); + return 1; +} +#endif /* COAP_SERVER_SUPPORT */ + +#else /* !HAVE_LIBTINYDTLS */ + +#ifdef __clang__ +/* Make compilers happy that do not like empty modules. As this function is + * never used, we ignore -Wunused-function at the end of compiling this file + */ +#pragma GCC diagnostic ignored "-Wunused-function" +#endif +static inline void dummy(void) { +} + +#endif /* HAVE_LIBTINYDTLS */ diff --git a/examples/espidf-coap-server/components/libcoap/src/encode.c b/examples/espidf-coap-server/components/libcoap/src/encode.c new file mode 100644 index 000000000..8705a7831 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/encode.c @@ -0,0 +1,93 @@ +/* encode.c -- encoding and decoding of CoAP data types + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file encode.c + * @brief Encoding and decoding Coap data types functions + */ + +#include "coap3/coap_internal.h" + +/* Carsten suggested this when fls() is not available: */ +#ifndef HAVE_FLS +int coap_fls(unsigned int i) { + return coap_flsll(i); +} +#endif + +#ifndef HAVE_FLSLL +int coap_flsll(long long i) +{ + int n; + for (n = 0; i; n++) + i >>= 1; + return n; +} +#endif + +unsigned int +coap_decode_var_bytes(const uint8_t *buf, size_t len) { + unsigned int i, n = 0; + for (i = 0; i < len; ++i) + n = (n << 8) + buf[i]; + + return n; +} + +unsigned int +coap_encode_var_safe(uint8_t *buf, size_t length, unsigned int val) { + unsigned int n, i; + + for (n = 0, i = val; i && n < sizeof(val); ++n) + i >>= 8; + + if (n > length) { + assert (n <= length); + return 0; + } + i = n; + while (i--) { + buf[i] = val & 0xff; + val >>= 8; + } + + return n; +} + +uint64_t +coap_decode_var_bytes8(const uint8_t *buf, size_t len) { + unsigned int i; + uint64_t n = 0; + for (i = 0; i < len; ++i) + n = (n << 8) + buf[i]; + + return n; +} + +unsigned int +coap_encode_var_safe8(uint8_t *buf, size_t length, uint64_t val) { + unsigned int n, i; + uint64_t tval = val; + + for (n = 0; tval && n < sizeof(val); ++n) + tval >>= 8; + + if (n > length) { + assert (n <= length); + return 0; + } + i = n; + while (i--) { + buf[i] = val & 0xff; + val >>= 8; + } + + return n; +} diff --git a/examples/espidf-coap-server/components/libcoap/src/mem.c b/examples/espidf-coap-server/components/libcoap/src/mem.c new file mode 100644 index 000000000..21c2ddbdc --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/mem.c @@ -0,0 +1,477 @@ +/* mem.c -- CoAP memory handling + * + * Copyright (C) 2014--2015,2019--2020 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file mem.c + * @brief Memory handling functions + */ + +#include "coap3/coap_internal.h" + +#if defined(RIOT_VERSION) && defined(MODULE_MEMARRAY) +#include + +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION +#include +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION + +#include "coap_session.h" +#include "net.h" +#include "pdu.h" +#include "resource.h" + +/** + * The maximum size of a string on platforms that allocate fixed-size + * memory blocks. + */ +#ifndef COAP_MAX_STRING_SIZE +#define COAP_MAX_STRING_SIZE (64U) +#endif /* COAP_MAX_STRING_SIZE */ + +/** + * The maximum number of strings on platforms that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_STRINGS +#define COAP_MAX_STRINGS (16U) +#endif /* COAP_MAX_STRINGS */ + +/** + * The maximum number of endpoints on platforms that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_ENDPOINTS +#define COAP_MAX_ENDPOINTS (4U) +#endif /* COAP_MAX_ENDPOINTS */ + +/** + * The maximum number of resources on platforms that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_RESOURCES +#define COAP_MAX_RESOURCES (8U) +#endif /* COAP_MAX_RESOURCES */ + +/** + * The maximum number of attributes on platforms that allocate + * fixed-size memory blocks. Default is #COAP_MAX_RESOURCES * 4. + */ +#ifndef COAP_MAX_ATTRIBUTES +#define COAP_MAX_ATTRIBUTES \ + ((COAP_MAX_RESOURCES) * 4U) +#endif /* COAP_MAX_ATTRIBUTE_STRINGS */ + +/** + * The maximum number of a strings that are used for attribute names + * and values on platforms that allocate fixed-size memory blocks. + * Default is #COAP_MAX_ATTRIBUTES, i.e. every attribute can have a + * dynamic value. + */ +#ifndef COAP_MAX_ATTRIBUTE_STRINGS +#define COAP_MAX_ATTRIBUTE_STRINGS (COAP_MAX_ATTRIBUTES) +#endif /* COAP_MAX_ATTRIBUTE_STRINGS */ + +/** + * The maximum size of attribute names or values and values on + * platforms that allocate fixed-size memory blocks. + */ +#ifndef COAP_MAX_ATTRIBUTE_SIZE +#define COAP_MAX_ATTRIBUTE_SIZE (16U) +#endif /* COAP_MAX_ATTRIBUTE_SIZE */ + +/** + * The maximum number of processed packets on platforms that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_PACKETS +#define COAP_MAX_PACKETS (4U) +#endif /* COAP_MAX_PACKETS */ + +/** + * The maximum number of nodes in retransmission queue on platforms + * that allocate fixed-size memory blocks. The default value is + * #COAP_MAX_ENDPOINTS * #COAP_MAX_PACKETS. + */ +#ifndef COAP_MAX_NODES +#define COAP_MAX_NODES \ + ((COAP_MAX_ENDPOINTS) * (COAP_MAX_PACKETS)) +#endif /* COAP_MAX_NODES */ + +/** + * The maximum number of CoAP contexts on platforms that allocate + * fixed-size memory blocks. Default is 1. + */ +#ifndef COAP_MAX_CONTEXTS +#define COAP_MAX_CONTEXTS (1U) +#endif /* COAP_MAX_CONTEXTS */ + +/** + * The maximum number of CoAP PDUs processed in parallel on platforms + * that allocate fixed-size memory blocks. Default is + * #COAP_MAX_ENDPOINTS * 4. + */ +#ifndef COAP_MAX_PDUS +#define COAP_MAX_PDUS ((COAP_MAX_ENDPOINTS) * 4U) +#endif /* COAP_MAX_PDUS */ + +/** + * The maximum number of DTLS sessions on platforms that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_DTLS_SESSIONS +#define COAP_MAX_DTLS_SESSIONS (2U) +#endif /* COAP_MAX_CONTEXTS */ + +/** + * The maximum number of DTLS sessions on platforms that allocate + * fixed-size memory blocks. Default is #COAP_MAX_ENDPOINTS. + */ +#ifndef COAP_MAX_SESSIONS +#define COAP_MAX_SESSIONS (COAP_MAX_ENDPOINTS) +#endif /* COAP_MAX_CONTEXTS */ + +/** + * The maximum number of optlist entries on platforms that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_OPTIONS +#define COAP_MAX_OPTIONS (16U) +#endif /* COAP_MAX_CONTEXTS */ + +/** + * The maximum size of option values on platforms that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_OPTION_SIZE +#define COAP_MAX_OPTION_SIZE (16U) +#endif /* COAP_MAX_OPTION_SIZE */ + +/** + * The maximum number of cache-key entries that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_CACHE_KEYS +#define COAP_MAX_CACHE_KEYS (2U) +#endif /* COAP_MAX_CACHE_KEYS */ + +/** + * The maximum number of cache-entry entries that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_CACHE_ENTRIES +#define COAP_MAX_CACHE_ENTRIES (2U) +#endif /* COAP_MAX_CACHE_ENTRIES */ + +/* The memstr is the storage for holding coap_string_t structure + * together with its contents. */ +union memstr_t { + coap_string_t s; + char buf[sizeof(coap_string_t) + COAP_MAX_STRING_SIZE]; +}; + +/* The attrstr is the storage for holding coap_string_t structures to + * serve as attribute names or values. As these are typically short, + * they are stored in a different arena than generic strings. */ +union attrstr_t { + coap_string_t s; + char buf[sizeof(coap_string_t) + COAP_MAX_ATTRIBUTE_SIZE]; +}; + +static union memstr_t string_storage_data[COAP_MAX_STRINGS]; +static memarray_t string_storage; + +static coap_endpoint_t endpoint_storage_data[COAP_MAX_ENDPOINTS]; +static memarray_t endpoint_storage; + +static union attrstr_t attr_storage_data[COAP_MAX_ATTRIBUTE_STRINGS]; +static memarray_t attr_storage; + +static coap_attr_t resattr_storage_data[COAP_MAX_ATTRIBUTES]; +static memarray_t resattr_storage; + +static coap_packet_t pkt_storage_data[COAP_MAX_PACKETS]; +static memarray_t pkt_storage; + +static coap_queue_t node_storage_data[COAP_MAX_NODES]; +static memarray_t node_storage; + +static coap_context_t context_storage_data[COAP_MAX_CONTEXTS]; +static memarray_t context_storage; + +static coap_pdu_t pdu_storage_data[COAP_MAX_PDUS]; +static memarray_t pdu_storage; + +/* The pdubuf is the storage for holding the (assembled) PDU data in a + * coap_pdu_t structure. */ +union pdubuf_t { + void *p; /* try to convince the compiler to word-align this structure */ + char buf[COAP_DEFAULT_MAX_PDU_RX_SIZE]; +}; + +static union pdubuf_t pdubuf_storage_data[COAP_MAX_PDUS]; +static memarray_t pdubuf_storage; + +static coap_resource_t resource_storage_data[COAP_MAX_RESOURCES]; +static memarray_t resource_storage; + +#ifdef HAVE_LIBTINYDTLS +static session_t dtls_storage_data[COAP_MAX_DTLS_SESSIONS]; +static memarray_t dtls_storage; +#endif /* HAVE_LIBTINYDTLS */ + +static coap_session_t session_storage_data[COAP_MAX_SESSIONS]; +static memarray_t session_storage; + +/* The optbuf_t is the storage for holding optlist nodes. */ +struct optbuf_t { + coap_optlist_t optlist; + char optbuf[COAP_MAX_OPTION_SIZE]; +}; +static struct optbuf_t option_storage_data[COAP_MAX_OPTIONS]; +static memarray_t option_storage; + +static coap_cache_key_t cache_key_storage_data[COAP_MAX_CACHE_KEYS]; +static memarray_t cache_key_storage; + +static coap_cache_entry_t cache_entry_storage_data[COAP_MAX_CACHE_ENTRIES]; +static memarray_t cache_entry_storage; + +#define INIT_STORAGE(Storage, Count) \ + memarray_init(&(Storage ## _storage), (Storage ## _storage_data), sizeof(Storage ## _storage_data[0]), (Count)); + +#define STORAGE_PTR(Storage) (&(Storage ## _storage)) + +void +coap_memory_init(void) { + INIT_STORAGE(string, COAP_MAX_STRINGS); + INIT_STORAGE(endpoint, COAP_MAX_ENDPOINTS); + INIT_STORAGE(attr, COAP_MAX_ATTRIBUTE_STRINGS); + INIT_STORAGE(pkt, COAP_MAX_PACKETS); + INIT_STORAGE(node, COAP_MAX_NODES); + INIT_STORAGE(context, COAP_MAX_CONTEXTS); + INIT_STORAGE(pdu, COAP_MAX_PDUS); + INIT_STORAGE(pdubuf, COAP_MAX_PDUS); + INIT_STORAGE(resource, COAP_MAX_RESOURCES); + INIT_STORAGE(resattr, COAP_MAX_ATTRIBUTES); +#ifdef HAVE_LIBTINYDTLS + INIT_STORAGE(dtls, COAP_MAX_DTLS_SESSIONS); +#endif + INIT_STORAGE(session, COAP_MAX_SESSIONS); + INIT_STORAGE(option, COAP_MAX_OPTIONS); + INIT_STORAGE(cache_key, COAP_MAX_CACHE_KEYS); + INIT_STORAGE(cache_entry, COAP_MAX_CACHE_ENTRIES); +} + +static memarray_t * +get_container(coap_memory_tag_t type) { + switch(type) { + case COAP_ATTRIBUTE_NAME: + /* fall through */ + case COAP_ATTRIBUTE_VALUE: return &attr_storage; + case COAP_PACKET: return &pkt_storage; + case COAP_NODE: return &node_storage; + case COAP_CONTEXT: return STORAGE_PTR(context); + case COAP_ENDPOINT: return &endpoint_storage; + case COAP_PDU: return &pdu_storage; + case COAP_PDU_BUF: return &pdubuf_storage; + case COAP_RESOURCE: return &resource_storage; + case COAP_RESOURCEATTR: return &resattr_storage; +#ifdef HAVE_LIBTINYDTLS + case COAP_DTLS_SESSION: return &dtls_storage; +#endif + case COAP_SESSION: return &session_storage; + case COAP_OPTLIST: return &option_storage; + case COAP_CACHE_KEY: return &cache_key_storage; + case COAP_CACHE_ENTRY: return &cache_key_entry; + case COAP_STRING: + /* fall through */ + default: + return &string_storage; + } +} + +void * +coap_malloc_type(coap_memory_tag_t type, size_t size) { + memarray_t *container = get_container(type); + void *ptr; + assert(container); + + if (size > container->size) { + coap_log(LOG_WARNING, + "coap_malloc_type: Requested memory exceeds maximum object " + "size (type %d, size %zu, max %d)\n", + type, size, container->size); + return NULL; + } + + ptr = memarray_alloc(container); + if (!ptr) + coap_log(LOG_WARNING, + "coap_malloc_type: Failure (no free blocks) for type %d\n", + type); + return ptr; +} + +void +coap_free_type(coap_memory_tag_t type, void *object) { + if (object != NULL) + memarray_free(get_container(type), object); +} +#else /* ! RIOT_VERSION */ + +#ifdef HAVE_MALLOC +#include + +void +coap_memory_init(void) { +} + +void * +coap_malloc_type(coap_memory_tag_t type, size_t size) { + (void)type; + return malloc(size); +} + +void * +coap_realloc_type(coap_memory_tag_t type, void* p, size_t size) { + (void)type; + return realloc(p, size); +} + +void +coap_free_type(coap_memory_tag_t type, void *p) { + (void)type; + free(p); +} + +#else /* ! HAVE_MALLOC */ + +#ifdef WITH_CONTIKI + +/** + * The maximum size of a string on platforms that allocate fixed-size + * memory blocks. + */ +#ifndef COAP_MAX_STRING_SIZE +#define COAP_MAX_STRING_SIZE 64 +#endif /* COAP_MAX_STRING_SIZE */ + +/** + * The maximum number of a strings on platforms that allocate + * fixed-size memory blocks. + */ +#ifndef COAP_MAX_STRINGS +#define COAP_MAX_STRINGS 10 +#endif /* COAP_MAX_STRINGS */ + +struct coap_stringbuf_t { + char data[COAP_MAX_STRING_SIZE]; +}; + + +#define COAP_MAX_PACKET_SIZE (sizeof(coap_packet_t) + COAP_RXBUFFER_SIZE) +#ifndef COAP_MAX_PACKETS +#define COAP_MAX_PACKETS 2 +#endif /* COAP_MAX_PACKETS */ + +typedef union { + coap_pdu_t packet; /* try to convince the compiler to word-align this structure */ + char buf[COAP_MAX_PACKET_SIZE]; +} coap_packetbuf_t; + +MEMB(string_storage, struct coap_stringbuf_t, COAP_MAX_STRINGS); +MEMB(packet_storage, coap_packetbuf_t, COAP_MAX_PACKETS); +MEMB(session_storage, coap_session_t, COAP_MAX_SESSIONS); +MEMB(node_storage, coap_queue_t, COAP_PDU_MAXCNT); +MEMB(pdu_storage, coap_pdu_t, COAP_PDU_MAXCNT); +MEMB(pdu_buf_storage, coap_packetbuf_t, COAP_PDU_MAXCNT); +MEMB(resource_storage, coap_resource_t, COAP_MAX_RESOURCES); +MEMB(attribute_storage, coap_attr_t, COAP_MAX_ATTRIBUTES); +MEMB(cache_key_storage, coap_cache_key_t, COAP_MAX_CACHE_KEYS); +MEMB(cache_entry_storage, coap_cache_entry_t, COAP_MAX_CACHE_ENTRIES); +MEMB(lg_xmit_storage, coap_lg_xmit_t, COAP_MAX_LG_XMIT); +MEMB(lg_crcv_storage, coap_lg_crcv_t, COAP_MAX_LG_CRCV); +MEMB(lg_srcv_storage, coap_lg_srcv_t, COAP_MAX_LG_SRCV); + +static struct memb * +get_container(coap_memory_tag_t type) { + switch(type) { + case COAP_PACKET: return &packet_storage; + case COAP_NODE: return &node_storage; + case COAP_SESSION: return &session_storage; + case COAP_PDU: return &pdu_storage; + case COAP_PDU_BUF: return &pdu_buf_storage; + case COAP_RESOURCE: return &resource_storage; + case COAP_RESOURCEATTR: return &attribute_storage; + case COAP_CACHE_KEY: return &cache_key_storage; + case COAP_CACHE_ENTRY: return &cache_entry_storage; + case COAP_LG_XMIT: return &lg_xmit_storage; + case COAP_LG_CRCV: return &lg_crcv_storage; + case COAP_LG_SRCV: return &lg_srcv_storage; + default: + return &string_storage; + } +} + +void +coap_memory_init(void) { + memb_init(&string_storage); + memb_init(&packet_storage); + memb_init(&node_storage); + memb_init(&session_storage); + memb_init(&pdu_storage); + memb_init(&pdu_buf_storage); + memb_init(&resource_storage); + memb_init(&attribute_storage); + memb_init(&cache_key_storage); + memb_init(&cache_entry_storage); + memb_init(&lg_xmit_storage); + memb_init(&lg_crcv_storage); + memb_init(&lg_srcv_storage); +} + +void * +coap_malloc_type(coap_memory_tag_t type, size_t size) { + struct memb *container = get_container(type); + void *ptr; + + assert(container); + + if (size > container->size) { + coap_log(LOG_WARNING, + "coap_malloc_type: Requested memory exceeds maximum object " + "size (type %d, size %d, max %d)\n", + type, (int)size, container->size); + return NULL; + } + + ptr = memb_alloc(container); + if (!ptr) + coap_log(LOG_WARNING, + "coap_malloc_type: Failure (no free blocks) for type %d\n", + type); + return ptr; +} + +void +coap_free_type(coap_memory_tag_t type, void *object) { + memb_free(get_container(type), object); +} +#endif /* WITH_CONTIKI */ + +#endif /* ! HAVE_MALLOC */ + +#endif /* ! RIOT_VERSION */ diff --git a/examples/espidf-coap-server/components/libcoap/src/net.c b/examples/espidf-coap-server/components/libcoap/src/net.c new file mode 100644 index 000000000..98859443d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/net.c @@ -0,0 +1,3885 @@ +/* net.c -- CoAP context inteface + * + * Copyright (C) 2010--2022 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file net.c + * @brief CoAP context functions + */ + +#include "coap3/coap_internal.h" + +#include +#include +#include +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#else +#ifdef HAVE_SYS_UNISTD_H +#include +#endif +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#ifdef COAP_EPOLL_SUPPORT +#include +#include +#endif /* COAP_EPOLL_SUPPORT */ +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +#ifdef HAVE_NETDB_H +#include +#endif + +#ifdef WITH_LWIP +#include +#include +#include +#endif + +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 40 +#endif + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + + /** + * The number of bits for the fractional part of ACK_TIMEOUT and + * ACK_RANDOM_FACTOR. Must be less or equal 8. + */ +#define FRAC_BITS 6 + + /** + * The maximum number of bits for fixed point integers that are used + * for retransmission time calculation. Currently this must be @c 8. + */ +#define MAX_BITS 8 + +#if FRAC_BITS > 8 +#error FRAC_BITS must be less or equal 8 +#endif + + /** creates a Qx.frac from fval in coap_fixed_point_t */ +#define Q(frac,fval) ((uint16_t)(((1 << (frac)) * fval.integer_part) + \ + ((1 << (frac)) * fval.fractional_part + 500)/1000)) + +/** creates a Qx.FRAC_BITS from session's 'ack_random_factor' */ +#define ACK_RANDOM_FACTOR \ + Q(FRAC_BITS, session->ack_random_factor) + +/** creates a Qx.FRAC_BITS from session's 'ack_timeout' */ +#define ACK_TIMEOUT Q(FRAC_BITS, session->ack_timeout) + +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) + +COAP_STATIC_INLINE coap_queue_t * +coap_malloc_node(void) { + return (coap_queue_t *)coap_malloc_type(COAP_NODE, sizeof(coap_queue_t)); +} + +COAP_STATIC_INLINE void +coap_free_node(coap_queue_t *node) { + coap_free_type(COAP_NODE, node); +} +#endif /* !defined(WITH_LWIP) && !defined(WITH_CONTIKI) */ + +#ifdef WITH_LWIP + +#include + +static void coap_retransmittimer_execute(void *arg); +static void coap_retransmittimer_restart(coap_context_t *ctx); + +COAP_STATIC_INLINE coap_queue_t * +coap_malloc_node() { + return (coap_queue_t *)memp_malloc(MEMP_COAP_NODE); +} + +COAP_STATIC_INLINE void +coap_free_node(coap_queue_t *node) { + memp_free(MEMP_COAP_NODE, node); +} + +#endif /* WITH_LWIP */ +#ifdef WITH_CONTIKI +# ifndef DEBUG +# define DEBUG DEBUG_PRINT +# endif /* DEBUG */ + +#include "net/ip/uip-debug.h" + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) + +void coap_resources_init(); + +unsigned char initialized = 0; +coap_context_t the_coap_context; + +PROCESS(coap_retransmit_process, "message retransmit process"); + +COAP_STATIC_INLINE coap_queue_t * +coap_malloc_node() { + return (coap_queue_t *)coap_malloc_type(COAP_NODE, 0); +} + +COAP_STATIC_INLINE void +coap_free_node(coap_queue_t *node) { + coap_free_type(COAP_NODE, node); +} +#endif /* WITH_CONTIKI */ + +unsigned int +coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now) { + unsigned int result = 0; + coap_tick_diff_t delta = now - ctx->sendqueue_basetime; + + if (ctx->sendqueue) { + /* delta < 0 means that the new time stamp is before the old. */ + if (delta <= 0) { + ctx->sendqueue->t -= delta; + } else { + /* This case is more complex: The time must be advanced forward, + * thus possibly leading to timed out elements at the queue's + * start. For every element that has timed out, its relative + * time is set to zero and the result counter is increased. */ + + coap_queue_t *q = ctx->sendqueue; + coap_tick_t t = 0; + while (q && (t + q->t < (coap_tick_t)delta)) { + t += q->t; + q->t = 0; + result++; + q = q->next; + } + + /* finally adjust the first element that has not expired */ + if (q) { + q->t = (coap_tick_t)delta - t; + } + } + } + + /* adjust basetime */ + ctx->sendqueue_basetime += delta; + + return result; +} + +int +coap_insert_node(coap_queue_t **queue, coap_queue_t *node) { + coap_queue_t *p, *q; + if (!queue || !node) + return 0; + + /* set queue head if empty */ + if (!*queue) { + *queue = node; + return 1; + } + + /* replace queue head if PDU's time is less than head's time */ + q = *queue; + if (node->t < q->t) { + node->next = q; + *queue = node; + q->t -= node->t; /* make q->t relative to node->t */ + return 1; + } + + /* search for right place to insert */ + do { + node->t -= q->t; /* make node-> relative to q->t */ + p = q; + q = q->next; + } while (q && q->t <= node->t); + + /* insert new item */ + if (q) { + q->t -= node->t; /* make q->t relative to node->t */ + } + node->next = q; + p->next = node; + return 1; +} + +int +coap_delete_node(coap_queue_t *node) { + if (!node) + return 0; + + coap_delete_pdu(node->pdu); + if ( node->session ) { + /* + * Need to remove out of context->sendqueue as added in by coap_wait_ack() + */ + if (node->session->context->sendqueue) { + LL_DELETE(node->session->context->sendqueue, node); + } + coap_session_release(node->session); + } + coap_free_node(node); + + return 1; +} + +void +coap_delete_all(coap_queue_t *queue) { + if (!queue) + return; + + coap_delete_all(queue->next); + coap_delete_node(queue); +} + +coap_queue_t * +coap_new_node(void) { + coap_queue_t *node; + node = coap_malloc_node(); + + if (!node) { + coap_log(LOG_WARNING, "coap_new_node: malloc failed\n"); + return NULL; + } + + memset(node, 0, sizeof(*node)); + return node; +} + +coap_queue_t * +coap_peek_next(coap_context_t *context) { + if (!context || !context->sendqueue) + return NULL; + + return context->sendqueue; +} + +coap_queue_t * +coap_pop_next(coap_context_t *context) { + coap_queue_t *next; + + if (!context || !context->sendqueue) + return NULL; + + next = context->sendqueue; + context->sendqueue = context->sendqueue->next; + if (context->sendqueue) { + context->sendqueue->t += next->t; + } + next->next = NULL; + return next; +} + +#if COAP_CLIENT_SUPPORT +const coap_bin_const_t * +coap_get_session_client_psk_key(const coap_session_t *session) { + + if (session->psk_key) { + return session->psk_key; + } + if (session->cpsk_setup_data.psk_info.key.length) + return &session->cpsk_setup_data.psk_info.key; + + /* Not defined in coap_new_client_session_psk2() */ + return NULL; +} +#endif /* COAP_CLIENT_SUPPORT */ + +const coap_bin_const_t * +coap_get_session_client_psk_identity(const coap_session_t *session) { + + if (session->psk_identity) { + return session->psk_identity; + } + if (session->cpsk_setup_data.psk_info.identity.length) + return &session->cpsk_setup_data.psk_info.identity; + + /* Not defined in coap_new_client_session_psk2() */ + return NULL; +} + +#if COAP_SERVER_SUPPORT +const coap_bin_const_t * +coap_get_session_server_psk_key(const coap_session_t *session) { + + if (session->psk_key) + return session->psk_key; + + if (session->context->spsk_setup_data.psk_info.key.length) + return &session->context->spsk_setup_data.psk_info.key; + + /* Not defined in coap_context_set_psk2() */ + return NULL; +} + +const coap_bin_const_t * +coap_get_session_server_psk_hint(const coap_session_t *session) { + + if (session->psk_hint) + return session->psk_hint; + + if (session->context->spsk_setup_data.psk_info.hint.length) + return &session->context->spsk_setup_data.psk_info.hint; + + /* Not defined in coap_context_set_psk2() */ + return NULL; +} + +int coap_context_set_psk(coap_context_t *ctx, + const char *hint, + const uint8_t *key, + size_t key_len) { + coap_dtls_spsk_t setup_data; + + memset (&setup_data, 0, sizeof(setup_data)); + if (hint) { + setup_data.psk_info.hint.s = (const uint8_t *)hint; + setup_data.psk_info.hint.length = strlen(hint); + } + + if (key && key_len > 0) { + setup_data.psk_info.key.s = key; + setup_data.psk_info.key.length = key_len; + } + + return coap_context_set_psk2(ctx, &setup_data); +} + +int coap_context_set_psk2(coap_context_t *ctx, coap_dtls_spsk_t *setup_data) { + if (!setup_data) + return 0; + + ctx->spsk_setup_data = *setup_data; + + if (coap_dtls_is_supported() || coap_tls_is_supported()) { + return coap_dtls_context_set_spsk(ctx, setup_data); + } + return 0; +} + +int coap_context_set_pki(coap_context_t *ctx, + const coap_dtls_pki_t* setup_data) { + if (!setup_data) + return 0; + if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION) { + coap_log(LOG_ERR, "coap_context_set_pki: Wrong version of setup_data\n"); + return 0; + } + if (coap_dtls_is_supported() || coap_tls_is_supported()) { + return coap_dtls_context_set_pki(ctx, setup_data, COAP_DTLS_ROLE_SERVER); + } + return 0; +} +#endif /* ! COAP_SERVER_SUPPORT */ + +int coap_context_set_pki_root_cas(coap_context_t *ctx, + const char *ca_file, + const char *ca_dir) { + if (coap_dtls_is_supported() || coap_tls_is_supported()) { + return coap_dtls_context_set_pki_root_cas(ctx, ca_file, ca_dir); + } + return 0; +} + +void coap_context_set_keepalive(coap_context_t *context, unsigned int seconds) { + context->ping_timeout = seconds; +} + +void +coap_context_set_max_idle_sessions(coap_context_t *context, + unsigned int max_idle_sessions) { + context->max_idle_sessions = max_idle_sessions; +} + +unsigned int +coap_context_get_max_idle_sessions(const coap_context_t *context) { + return context->max_idle_sessions; +} + +void +coap_context_set_max_handshake_sessions(coap_context_t *context, + unsigned int max_handshake_sessions) { + context->max_handshake_sessions = max_handshake_sessions; +} + +unsigned int +coap_context_get_max_handshake_sessions(const coap_context_t *context) { + return context->max_handshake_sessions; +} + +void +coap_context_set_csm_timeout(coap_context_t *context, + unsigned int csm_timeout) { + context->csm_timeout = csm_timeout; +} + +unsigned int +coap_context_get_csm_timeout(const coap_context_t *context) { + return context->csm_timeout; +} + +void +coap_context_set_csm_max_message_size(coap_context_t *context, + uint32_t csm_max_message_size) { + assert(csm_max_message_size >= 64); + context->csm_max_message_size = csm_max_message_size; +} + +uint32_t +coap_context_get_csm_max_message_size(const coap_context_t *context) { + return context->csm_max_message_size; +} + +void +coap_context_set_session_timeout(coap_context_t *context, + unsigned int session_timeout) { + context->session_timeout = session_timeout; +} + +unsigned int +coap_context_get_session_timeout(const coap_context_t *context) { + return context->session_timeout; +} + +int coap_context_get_coap_fd(const coap_context_t *context) { +#ifdef COAP_EPOLL_SUPPORT + return context->epfd; +#else /* ! COAP_EPOLL_SUPPORT */ + (void)context; + return -1; +#endif /* ! COAP_EPOLL_SUPPORT */ +} + +coap_context_t * +coap_new_context( + const coap_address_t *listen_addr) { + coap_context_t *c; + +#if ! COAP_SERVER_SUPPORT + (void)listen_addr; +#endif /* COAP_SERVER_SUPPORT */ + +#ifdef WITH_CONTIKI + if (initialized) + return NULL; +#endif /* WITH_CONTIKI */ + + coap_startup(); + +#ifndef WITH_CONTIKI + c = coap_malloc_type(COAP_CONTEXT, sizeof(coap_context_t)); + if (!c) { + coap_log(LOG_EMERG, "coap_init: malloc: failed\n"); + return NULL; + } +#endif /* not WITH_CONTIKI */ +#ifdef WITH_CONTIKI + coap_resources_init(); + + c = &the_coap_context; + initialized = 1; +#endif /* WITH_CONTIKI */ + + memset(c, 0, sizeof(coap_context_t)); + +#ifdef COAP_EPOLL_SUPPORT + c->epfd = epoll_create1(0); + if (c->epfd == -1) { + coap_log(LOG_ERR, "coap_new_context: Unable to epoll_create: %s (%d)\n", + coap_socket_strerror(), + errno); + goto onerror; + } + if (c->epfd != -1) { + c->eptimerfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK); + if (c->eptimerfd == -1) { + coap_log(LOG_ERR, "coap_new_context: Unable to timerfd_create: %s (%d)\n", + coap_socket_strerror(), + errno); + goto onerror; + } + else { + int ret; + struct epoll_event event; + + /* Needed if running 32bit as ptr is only 32bit */ + memset(&event, 0, sizeof(event)); + event.events = EPOLLIN; + /* We special case this event by setting to NULL */ + event.data.ptr = NULL; + + ret = epoll_ctl(c->epfd, EPOLL_CTL_ADD, c->eptimerfd, &event); + if (ret == -1) { + coap_log(LOG_ERR, + "%s: epoll_ctl ADD failed: %s (%d)\n", + "coap_new_context", + coap_socket_strerror(), errno); + goto onerror; + } + } + } +#endif /* COAP_EPOLL_SUPPORT */ + + if (coap_dtls_is_supported() || coap_tls_is_supported()) { + c->dtls_context = coap_dtls_new_context(c); + if (!c->dtls_context) { + coap_log(LOG_EMERG, "coap_init: no DTLS context available\n"); + coap_free_context(c); + return NULL; + } + } + + /* set default CSM values */ + c->csm_timeout = 30; + c->csm_max_message_size = COAP_DEFAULT_MAX_PDU_RX_SIZE; + +#if COAP_SERVER_SUPPORT + if (listen_addr) { + coap_endpoint_t *endpoint = coap_new_endpoint(c, listen_addr, COAP_PROTO_UDP); + if (endpoint == NULL) { + goto onerror; + } + } +#endif /* COAP_SERVER_SUPPORT */ + +#if !defined(WITH_LWIP) + c->network_send = coap_network_send; + c->network_read = coap_network_read; +#endif + +#ifdef WITH_CONTIKI + process_start(&coap_retransmit_process, (char *)c); + + PROCESS_CONTEXT_BEGIN(&coap_retransmit_process); + etimer_set(&c->notify_timer, COAP_RESOURCE_CHECK_TIME * COAP_TICKS_PER_SECOND); + /* the retransmit timer must be initialized to some large value */ + etimer_set(&the_coap_context.retransmit_timer, 0xFFFF); + PROCESS_CONTEXT_END(&coap_retransmit_process); +#endif /* WITH_CONTIKI */ + + return c; + +#if defined(COAP_EPOLL_SUPPORT) || COAP_SERVER_SUPPORT +onerror: + coap_free_type(COAP_CONTEXT, c); + return NULL; +#endif /* COAP_EPOLL_SUPPORT || COAP_SERVER_SUPPORT */ +} + +void +coap_set_app_data(coap_context_t *ctx, void *app_data) { + assert(ctx); + ctx->app = app_data; +} + +void * +coap_get_app_data(const coap_context_t *ctx) { + assert(ctx); + return ctx->app; +} + +void +coap_free_context(coap_context_t *context) { + if (!context) + return; + +#if COAP_SERVER_SUPPORT + /* Removing a resource may cause a CON observe to be sent */ + coap_delete_all_resources(context); +#endif /* COAP_SERVER_SUPPORT */ + + coap_delete_all(context->sendqueue); + +#ifdef WITH_LWIP + context->sendqueue = NULL; + coap_retransmittimer_restart(context); +#endif + +#ifndef WITHOUT_ASYNC + coap_delete_all_async(context); +#endif /* WITHOUT_ASYNC */ +#if COAP_SERVER_SUPPORT + coap_cache_entry_t *cp, *ctmp; + + HASH_ITER(hh, context->cache, cp, ctmp) { + coap_delete_cache_entry(context, cp); + } + if (context->cache_ignore_count) { + coap_free(context->cache_ignore_options); + } + + coap_endpoint_t *ep, *tmp; + + LL_FOREACH_SAFE(context->endpoint, ep, tmp) { + coap_free_endpoint(ep); + } +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT + coap_session_t *sp, *rtmp; + + SESSIONS_ITER_SAFE(context->sessions, sp, rtmp) { + coap_session_release(sp); + } +#endif /* COAP_CLIENT_SUPPORT */ + + if (context->dtls_context) + coap_dtls_free_context(context->dtls_context); +#ifdef COAP_EPOLL_SUPPORT + if (context->eptimerfd != -1) { + int ret; + struct epoll_event event; + + /* Kernels prior to 2.6.9 expect non NULL event parameter */ + ret = epoll_ctl(context->epfd, EPOLL_CTL_DEL, context->eptimerfd, &event); + if (ret == -1) { + coap_log(LOG_ERR, + "%s: epoll_ctl DEL failed: %s (%d)\n", + "coap_free_context", + coap_socket_strerror(), errno); + } + close(context->eptimerfd); + context->eptimerfd = -1; + } + if (context->epfd != -1) { + close(context->epfd); + context->epfd = -1; + } +#endif /* COAP_EPOLL_SUPPORT */ + +#ifndef WITH_CONTIKI + coap_free_type(COAP_CONTEXT, context); +#else /* WITH_CONTIKI */ + memset(&the_coap_context, 0, sizeof(coap_context_t)); + initialized = 0; +#endif /* WITH_CONTIKI */ +} + +int +coap_option_check_critical(coap_session_t *session, + coap_pdu_t *pdu, + coap_opt_filter_t *unknown) { + + coap_context_t *ctx = session->context; + coap_opt_iterator_t opt_iter; + int ok = 1; + + coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + + while (coap_option_next(&opt_iter)) { + + /* The following condition makes use of the fact that + * coap_option_getb() returns -1 if type exceeds the bit-vector + * filter. As the vector is supposed to be large enough to hold + * the largest known option, we know that everything beyond is + * bad. + */ + if (opt_iter.number & 0x01) { + /* first check the known built-in critical options */ + switch (opt_iter.number) { + case COAP_OPTION_IF_MATCH: + case COAP_OPTION_URI_HOST: + case COAP_OPTION_IF_NONE_MATCH: + case COAP_OPTION_URI_PORT: + case COAP_OPTION_URI_PATH: + case COAP_OPTION_URI_QUERY: + case COAP_OPTION_ACCEPT: + case COAP_OPTION_PROXY_URI: + case COAP_OPTION_PROXY_SCHEME: + case COAP_OPTION_BLOCK2: + case COAP_OPTION_BLOCK1: + break; + default: + if (coap_option_filter_get(&ctx->known_options, opt_iter.number) <= 0) { +#if COAP_SERVER_SUPPORT + if ((opt_iter.number & 0x02) == 0) { + coap_opt_iterator_t t_iter; + + /* Safe to forward - check if proxy pdu */ + if (session->proxy_session) + break; + if (COAP_PDU_IS_REQUEST(pdu) && ctx->proxy_uri_resource && + (coap_check_option(pdu, COAP_OPTION_PROXY_URI, &t_iter) || + coap_check_option(pdu, COAP_OPTION_PROXY_SCHEME, &t_iter))) { + pdu->crit_opt = 1; + break; + } + } +#endif /* COAP_SERVER_SUPPORT */ + coap_log(LOG_DEBUG, "unknown critical option %d\n", opt_iter.number); + ok = 0; + + /* When opt_iter.number is beyond our known option range, + * coap_option_filter_set() will return -1 and we are safe to leave + * this loop. */ + if (coap_option_filter_set(unknown, opt_iter.number) == -1) { + break; + } + } + } + } + } + + return ok; +} + +coap_mid_t +coap_send_ack(coap_session_t *session, const coap_pdu_t *request) { + coap_pdu_t *response; + coap_mid_t result = COAP_INVALID_MID; + + if (request && request->type == COAP_MESSAGE_CON && + COAP_PROTO_NOT_RELIABLE(session->proto)) { + response = coap_pdu_init(COAP_MESSAGE_ACK, 0, request->mid, 0); + if (response) + result = coap_send_internal(session, response); + } + return result; +} + +ssize_t +coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu) { + ssize_t bytes_written = -1; + assert(pdu->hdr_size > 0); + switch(session->proto) { + case COAP_PROTO_UDP: + bytes_written = coap_session_send(session, pdu->token - pdu->hdr_size, + pdu->used_size + pdu->hdr_size); + break; + case COAP_PROTO_DTLS: + bytes_written = coap_dtls_send(session, pdu->token - pdu->hdr_size, + pdu->used_size + pdu->hdr_size); + break; + case COAP_PROTO_TCP: +#if !COAP_DISABLE_TCP + bytes_written = coap_session_write(session, pdu->token - pdu->hdr_size, + pdu->used_size + pdu->hdr_size); +#endif /* !COAP_DISABLE_TCP */ + break; + case COAP_PROTO_TLS: +#if !COAP_DISABLE_TCP + bytes_written = coap_tls_write(session, pdu->token - pdu->hdr_size, + pdu->used_size + pdu->hdr_size); +#endif /* !COAP_DISABLE_TCP */ + break; + case COAP_PROTO_NONE: + default: + break; + } + coap_show_pdu(LOG_DEBUG, pdu); + return bytes_written; +} + +static ssize_t +coap_send_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *node) { + ssize_t bytes_written; + +#ifdef WITH_LWIP + + coap_socket_t *sock = &session->sock; + if (sock->flags == COAP_SOCKET_EMPTY) { + assert(session->endpoint != NULL); + sock = &session->endpoint->sock; + } + + bytes_written = coap_socket_send_pdu(sock, session, pdu); + if (bytes_written >= 0 && pdu->type == COAP_MESSAGE_CON && + COAP_PROTO_NOT_RELIABLE(session->proto)) + session->con_active++; + + if (LOG_DEBUG <= coap_get_log_level()) { + coap_show_pdu(LOG_DEBUG, pdu); + } + coap_ticks(&session->last_rx_tx); + +#else + + if (session->state == COAP_SESSION_STATE_NONE) { +#if ! COAP_CLIENT_SUPPORT + return -1; +#else /* COAP_CLIENT_SUPPORT */ + if (session->proto == COAP_PROTO_DTLS && !session->tls) { + session->tls = coap_dtls_new_client_session(session); + if (session->tls) { + session->state = COAP_SESSION_STATE_HANDSHAKE; + return coap_session_delay_pdu(session, pdu, node); + } + coap_handle_event(session->context, COAP_EVENT_DTLS_ERROR, session); + return -1; +#if !COAP_DISABLE_TCP + } else if(COAP_PROTO_RELIABLE(session->proto)) { + if (!coap_socket_connect_tcp1( + &session->sock, &session->addr_info.local, &session->addr_info.remote, + session->proto == COAP_PROTO_TLS ? COAPS_DEFAULT_PORT : + COAP_DEFAULT_PORT, + &session->addr_info.local, &session->addr_info.remote + )) { + coap_handle_event(session->context, COAP_EVENT_TCP_FAILED, session); + return -1; + } + session->last_ping = 0; + session->last_pong = 0; + session->csm_tx = 0; + coap_ticks( &session->last_rx_tx ); + if ((session->sock.flags & COAP_SOCKET_WANT_CONNECT) != 0) { + session->state = COAP_SESSION_STATE_CONNECTING; + return coap_session_delay_pdu(session, pdu, node); + } + coap_handle_event(session->context, COAP_EVENT_TCP_CONNECTED, session); + if (session->proto == COAP_PROTO_TLS) { + int connected = 0; + session->state = COAP_SESSION_STATE_HANDSHAKE; + session->tls = coap_tls_new_client_session(session, &connected); + if (session->tls) { + if (connected) { + coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session); + coap_session_send_csm(session); + } + return coap_session_delay_pdu(session, pdu, node); + } + coap_handle_event(session->context, COAP_EVENT_DTLS_ERROR, session); + coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + return -1; + } else { + coap_session_send_csm(session); + } +#endif /* !COAP_DISABLE_TCP */ + } else { + return -1; + } +#endif /* COAP_CLIENT_SUPPORT */ + } + + if (pdu->type == COAP_MESSAGE_CON && + (session->sock.flags & COAP_SOCKET_NOT_EMPTY) && + (session->sock.flags & COAP_SOCKET_MULTICAST)) { + /* Violates RFC72522 8.1 */ + coap_log(LOG_ERR, "Multicast requests cannot be Confirmable (RFC7252 8.1)\n"); + return -1; + } + + if (session->state != COAP_SESSION_STATE_ESTABLISHED || + (pdu->type == COAP_MESSAGE_CON && + session->con_active >= COAP_NSTART(session))) { + return coap_session_delay_pdu(session, pdu, node); + } + + if ((session->sock.flags & COAP_SOCKET_NOT_EMPTY) && + (session->sock.flags & COAP_SOCKET_WANT_WRITE)) + return coap_session_delay_pdu(session, pdu, node); + + bytes_written = coap_session_send_pdu(session, pdu); + if (bytes_written >= 0 && pdu->type == COAP_MESSAGE_CON && + COAP_PROTO_NOT_RELIABLE(session->proto)) + session->con_active++; + +#endif /* WITH_LWIP */ + + return bytes_written; +} + +coap_mid_t +coap_send_error(coap_session_t *session, + const coap_pdu_t *request, + coap_pdu_code_t code, + coap_opt_filter_t *opts) { + coap_pdu_t *response; + coap_mid_t result = COAP_INVALID_MID; + + assert(request); + assert(session); + + response = coap_new_error_response(request, code, opts); + if (response) + result = coap_send_internal(session, response); + + return result; +} + +coap_mid_t +coap_send_message_type(coap_session_t *session, const coap_pdu_t *request, + coap_pdu_type_t type) { + coap_pdu_t *response; + coap_mid_t result = COAP_INVALID_MID; + + if (request) { + response = coap_pdu_init(type, 0, request->mid, 0); + if (response) + result = coap_send_internal(session, response); + } + return result; +} + +/** + * Calculates the initial timeout based on the session CoAP transmission + * parameters 'ack_timeout', 'ack_random_factor', and COAP_TICKS_PER_SECOND. + * The calculation requires 'ack_timeout' and 'ack_random_factor' to be in + * Qx.FRAC_BITS fixed point notation, whereas the passed parameter @p r + * is interpreted as the fractional part of a Q0.MAX_BITS random value. + * + * @param session session timeout is associated with + * @param r random value as fractional part of a Q0.MAX_BITS fixed point + * value + * @return COAP_TICKS_PER_SECOND * 'ack_timeout' * + * (1 + ('ack_random_factor' - 1) * r) + */ +unsigned int +coap_calc_timeout(coap_session_t *session, unsigned char r) { + unsigned int result; + + /* The integer 1.0 as a Qx.FRAC_BITS */ +#define FP1 Q(FRAC_BITS, ((coap_fixed_point_t){1,0})) + + /* rounds val up and right shifts by frac positions */ +#define SHR_FP(val,frac) (((val) + (1 << ((frac) - 1))) >> (frac)) + + /* Inner term: multiply ACK_RANDOM_FACTOR by Q0.MAX_BITS[r] and + * make the result a rounded Qx.FRAC_BITS */ + result = SHR_FP((ACK_RANDOM_FACTOR - FP1) * r, MAX_BITS); + + /* Add 1 to the inner term and multiply with ACK_TIMEOUT, then + * make the result a rounded Qx.FRAC_BITS */ + result = SHR_FP(((result + FP1) * ACK_TIMEOUT), FRAC_BITS); + + /* Multiply with COAP_TICKS_PER_SECOND to yield system ticks + * (yields a Qx.FRAC_BITS) and shift to get an integer */ + return SHR_FP((COAP_TICKS_PER_SECOND * result), FRAC_BITS); + +#undef FP1 +#undef SHR_FP +} + +coap_mid_t +coap_wait_ack(coap_context_t *context, coap_session_t *session, + coap_queue_t *node) { + coap_tick_t now; + + node->session = coap_session_reference(session); + + /* Set timer for pdu retransmission. If this is the first element in + * the retransmission queue, the base time is set to the current + * time and the retransmission time is node->timeout. If there is + * already an entry in the sendqueue, we must check if this node is + * to be retransmitted earlier. Therefore, node->timeout is first + * normalized to the base time and then inserted into the queue with + * an adjusted relative time. + */ + coap_ticks(&now); + if (context->sendqueue == NULL) { + node->t = node->timeout << node->retransmit_cnt; + context->sendqueue_basetime = now; + } else { + /* make node->t relative to context->sendqueue_basetime */ + node->t = (now - context->sendqueue_basetime) + + (node->timeout << node->retransmit_cnt); + } + + coap_insert_node(&context->sendqueue, node); + +#ifdef WITH_LWIP + if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */ + coap_retransmittimer_restart(context); +#endif + +#ifdef WITH_CONTIKI + { /* (re-)initialize retransmission timer */ + coap_queue_t *nextpdu; + + nextpdu = coap_peek_next(context); + assert(nextpdu); /* we have just inserted a node */ + + /* must set timer within the context of the retransmit process */ + PROCESS_CONTEXT_BEGIN(&coap_retransmit_process); + etimer_set(&context->retransmit_timer, nextpdu->t); + PROCESS_CONTEXT_END(&coap_retransmit_process); + } +#endif /* WITH_CONTIKI */ + + coap_log(LOG_DEBUG, "** %s: mid=0x%x: added to retransmit queue (%ums)\n", + coap_session_str(node->session), node->id, + (unsigned)(node->t * 1000 / COAP_TICKS_PER_SECOND)); + +#ifdef COAP_EPOLL_SUPPORT + coap_update_epoll_timer(context, node->t); +#endif /* COAP_EPOLL_SUPPORT */ + + return node->id; +} + +COAP_STATIC_INLINE int +token_match(const uint8_t *a, size_t alen, + const uint8_t *b, size_t blen) { + return alen == blen && (alen == 0 || memcmp(a, b, alen) == 0); +} + +int +coap_client_delay_first(coap_session_t *session) +{ + if (session->type == COAP_SESSION_TYPE_CLIENT && session->doing_first) { + if (session->doing_first) { + int timeout_ms = 5000; +#ifdef WITH_LWIP +#include + struct netif *netif = ip_route(&session->sock.pcb->local_ip, + &session->addr_info.remote.addr); + if (!netif) { + session->doing_first = 0; + return 1; + } +#endif /* WITH_LWIP */ + + if (session->delay_recursive) { + assert(0); + return 1; + } else { + session->delay_recursive = 1; + } + /* + * Need to wait for first request to get out and response back before + * continuing.. Response handler has to clear doing_first if not an error. + */ + coap_session_reference(session); + while (session->doing_first != 0) { +#ifndef WITH_LWIP + int result = coap_io_process(session->context, 1000); +#else /* WITH_LWIP */ + int result; + coap_tick_t start; + coap_tick_t end; + + coap_ticks(&start); + result = tapif_select(netif); +#endif /* WITH_LWIP */ + + if (result < 0) { + session->doing_first = 0; + session->delay_recursive = 0; + coap_session_release(session); + return 0; + } +#ifdef WITH_LWIP + sys_check_timeouts(); + coap_ticks(&end); + result = (end - start) * 1000 / COAP_TICKS_PER_SECOND; +#endif /* WITH_LWIP */ + if (result <= timeout_ms) { + timeout_ms -= result; + } else { + if (session->doing_first == 1) { + /* Timeout failure of some sort with first request */ + coap_log(LOG_DEBUG, "** %s: timeout waiting for first response\n", + coap_session_str(session)); + session->doing_first = 0; + } + } + } + session->delay_recursive = 0; + coap_session_release(session); + } + } + return 1; +} + +coap_mid_t +coap_send(coap_session_t *session, coap_pdu_t *pdu) { + coap_mid_t mid = COAP_INVALID_MID; + + assert(pdu); + + if (session->type == COAP_SESSION_TYPE_CLIENT && + session->sock.flags == COAP_SOCKET_EMPTY) { + coap_log(LOG_DEBUG, "coap_send: Socket closed\n"); + coap_delete_pdu(pdu); + return COAP_INVALID_MID; + } +#if COAP_CLIENT_SUPPORT + coap_lg_crcv_t *lg_crcv = NULL; + coap_opt_iterator_t opt_iter; + coap_block_b_t block; + int observe_action = -1; + int have_block1 = 0; + coap_opt_t *opt; + + if (!(session->block_mode & COAP_BLOCK_USE_LIBCOAP)) { + return coap_send_internal(session, pdu); + } + + if (COAP_PDU_IS_REQUEST(pdu)) { + opt = coap_check_option(pdu, COAP_OPTION_OBSERVE, &opt_iter); + + if (opt) { + observe_action = coap_decode_var_bytes(coap_opt_value(opt), + coap_opt_length(opt)); + } + + if (coap_get_block_b(session, pdu, COAP_OPTION_BLOCK1, &block) && + (block.m == 1 || block.bert == 1)) + have_block1 = 1; + if (observe_action != COAP_OBSERVE_CANCEL) { + /* Warn about re-use of tokens */ + coap_bin_const_t token = coap_pdu_get_token(pdu); + + if (session->last_token && + coap_binary_equal(&token, session->last_token)) { + coap_log(LOG_DEBUG, "Token reused - see https://www.rfc-editor.org/rfc/rfc9175.html#section-4.2\n"); + } + coap_delete_bin_const(session->last_token); + session->last_token = coap_new_bin_const(token.s, token.length); + } + } else { + memset(&block, 0, sizeof(block)); + } + + /* + * If type is CON and protocol is not reliable, there is no need to set up + * lg_crcv here as it can be built up based on sent PDU if there is a + * Block2 in the response. However, still need it for observe and block1. + */ + if (observe_action != -1 || have_block1 || + ((pdu->type == COAP_MESSAGE_NON || COAP_PROTO_RELIABLE(session->proto)) && + COAP_PDU_IS_REQUEST(pdu) && pdu->code != COAP_REQUEST_CODE_DELETE)) { + coap_lg_xmit_t *lg_xmit = NULL; + + if (!session->lg_xmit) { + coap_log(LOG_DEBUG, "PDU presented by app\n"); + coap_show_pdu(LOG_DEBUG, pdu); + } + /* See if this token is already in use for large body responses */ + LL_FOREACH(session->lg_crcv, lg_crcv) { + if (token_match(pdu->token, pdu->token_length, + lg_crcv->app_token->s, lg_crcv->app_token->length)) { + + if (observe_action == COAP_OBSERVE_CANCEL) { + uint8_t buf[8]; + size_t len; + + /* Need to update token to server's version */ + len = coap_encode_var_safe8(buf, sizeof(lg_crcv->state_token), + lg_crcv->state_token); + coap_update_token(pdu, len, buf); + lg_crcv->initial = 1; + lg_crcv->observe_set = 0; + /* de-reference lg_crcv as potentially linking in later */ + LL_DELETE(session->lg_crcv, lg_crcv); + goto send_it; + } + + /* Need to terminate and clean up previous response setup */ + LL_DELETE(session->lg_crcv, lg_crcv); + coap_block_delete_lg_crcv(session, lg_crcv); + break; + } + } + + if (have_block1 && session->lg_xmit) { + LL_FOREACH(session->lg_xmit, lg_xmit) { + if (COAP_PDU_IS_REQUEST(&lg_xmit->pdu) && + lg_xmit->b.b1.app_token && + token_match(pdu->token, pdu->token_length, + lg_xmit->b.b1.app_token->s, + lg_xmit->b.b1.app_token->length)) { + break; + } + } + } + lg_crcv = coap_block_new_lg_crcv(session, pdu); + if (lg_crcv == NULL) { + coap_delete_pdu(pdu); + return COAP_INVALID_MID; + } + if (lg_xmit) { + /* Need to update the token as set up in the session->lg_xmit */ + lg_xmit->b.b1.state_token = lg_crcv->state_token; + } + } + +send_it: +#endif /* COAP_CLIENT_SUPPORT */ + mid = coap_send_internal(session, pdu); +#if COAP_CLIENT_SUPPORT + if (lg_crcv) { + if (mid != COAP_INVALID_MID) { + LL_PREPEND(session->lg_crcv, lg_crcv); + } + else { + coap_block_delete_lg_crcv(session, lg_crcv); + } + } +#endif /* COAP_CLIENT_SUPPORT */ + return mid; +} + +coap_mid_t +coap_send_internal(coap_session_t *session, coap_pdu_t *pdu) { + uint8_t r; + ssize_t bytes_written; + coap_opt_iterator_t opt_iter; + + if (pdu->code == COAP_RESPONSE_CODE(508)) { + /* + * Need to prepend our IP identifier to the data as per + * https://www.rfc-editor.org/rfc/rfc8768.html#section-4 + */ + char addr_str[INET6_ADDRSTRLEN + 8 + 1]; + coap_opt_t *opt; + size_t hop_limit; + + addr_str[sizeof(addr_str)-1] = '\000'; + if (coap_print_addr(&session->addr_info.local, (uint8_t*)addr_str, + sizeof(addr_str) - 1)) { + char *cp; + size_t len; + + if (addr_str[0] == '[') { + cp = strchr(addr_str, ']'); + if (cp) *cp = '\000'; + if (memcmp(&addr_str[1], "::ffff:", 7) == 0) { + /* IPv4 embedded into IPv6 */ + cp = &addr_str[8]; + } + else { + cp = &addr_str[1]; + } + } + else { + cp = strchr(addr_str, ':'); + if (cp) *cp = '\000'; + cp = addr_str; + } + len = strlen(cp); + + /* See if Hop Limit option is being used in return path */ + opt = coap_check_option(pdu, COAP_OPTION_HOP_LIMIT, &opt_iter); + if (opt) { + uint8_t buf[4]; + + hop_limit = + coap_decode_var_bytes (coap_opt_value (opt), coap_opt_length (opt)); + if (hop_limit == 1) { + coap_log(LOG_WARNING, "Proxy loop detected '%s'\n", + (char*)pdu->data); + coap_delete_pdu(pdu); + return (coap_mid_t)COAP_DROPPED_RESPONSE; + } + else if (hop_limit < 1 || hop_limit > 255) { + /* Something is bad - need to drop this pdu (TODO or delete option) */ + coap_log(LOG_WARNING, "Proxy return has bad hop limit count '%zu'\n", + hop_limit); + coap_delete_pdu(pdu); + return (coap_mid_t)COAP_DROPPED_RESPONSE; + } + hop_limit--; + coap_update_option(pdu, COAP_OPTION_HOP_LIMIT, + coap_encode_var_safe8(buf, sizeof(buf), hop_limit), + buf); + } + + /* Need to check that we are not seeing this proxy in the return loop */ + if (pdu->data && opt == NULL) { + if (pdu->used_size + 1 <= pdu->max_size) { + char *a_match; + size_t data_len = pdu->used_size - (pdu->data - pdu->token); + pdu->data[data_len] = '\000'; + a_match = strstr((char*)pdu->data, cp); + if (a_match && (a_match == (char*)pdu->data || a_match[-1] == ' ') && + ((size_t)(a_match - (char*)pdu->data + len) == data_len || + a_match[len] == ' ')) { + coap_log(LOG_WARNING, "Proxy loop detected '%s'\n", + (char*)pdu->data); + coap_delete_pdu(pdu); + return (coap_mid_t)COAP_DROPPED_RESPONSE; + } + } + } + if (pdu->used_size + len + 1 <= pdu->max_size) { + size_t old_size = pdu->used_size; + if (coap_pdu_resize(pdu, pdu->used_size + len + 1)) { + if (pdu->data == NULL) { + /* + * Set Hop Limit to max for return path. If this libcoap is in + * a proxy loop path, it will always decrement hop limit in code + * above and hence timeout / drop the response as appropriate + */ + hop_limit = 255; + coap_insert_option(pdu, COAP_OPTION_HOP_LIMIT, 1, + (uint8_t *)&hop_limit); + coap_add_data(pdu, len, (uint8_t*)cp); + } + else { + /* prepend with space separator, leaving hop limit "as is" */ + memmove(pdu->data + len + 1, pdu->data, + old_size - (pdu->data - pdu->token)); + memcpy(pdu->data, cp, len); + pdu->data[len] = ' '; + pdu->used_size += len + 1; + } + } + } + } + } + + if (session->echo) { + if (!coap_insert_option(pdu, COAP_OPTION_ECHO, session->echo->length, + session->echo->s)) + goto error; + coap_delete_bin_const(session->echo); + session->echo = NULL; + } + + if (!coap_pdu_encode_header(pdu, session->proto)) { + goto error; + } + +#if !COAP_DISABLE_TCP + if (COAP_PROTO_RELIABLE(session->proto) && + session->state == COAP_SESSION_STATE_ESTABLISHED) { + if (!session->csm_block_supported) { + /* + * Need to check that this instance is not sending any block options as + * the remote end via CSM has not informed us that there is support + * https://tools.ietf.org/html/rfc8323#section-5.3.2 + * This includes potential BERT blocks. + */ + if (coap_check_option(pdu, COAP_OPTION_BLOCK1, &opt_iter) != NULL) { + coap_log(LOG_DEBUG, + "Remote end did not indicate CSM support for Block1 enabled\n"); + } + if (coap_check_option(pdu, COAP_OPTION_BLOCK2, &opt_iter) != NULL) { + coap_log(LOG_DEBUG, + "Remote end did not indicate CSM support for Block2 enabled\n"); + } + } + else if (!session->csm_bert_rem_support) { + coap_opt_t *opt; + + opt = coap_check_option(pdu, COAP_OPTION_BLOCK1, &opt_iter); + if (opt && COAP_OPT_BLOCK_SZX(opt) == 7) { + coap_log(LOG_DEBUG, + "Remote end did not indicate CSM support for BERT Block1\n"); + } + opt = coap_check_option(pdu, COAP_OPTION_BLOCK2, &opt_iter); + if (opt && COAP_OPT_BLOCK_SZX(opt) == 7) { + coap_log(LOG_DEBUG, + "Remote end did not indicate CSM support for BERT Block2\n"); + } + } + } +#endif /* !COAP_DISABLE_TCP */ + + bytes_written = coap_send_pdu( session, pdu, NULL ); + + if (bytes_written == COAP_PDU_DELAYED) { + /* do not free pdu as it is stored with session for later use */ + return pdu->mid; + } + + if (bytes_written < 0) { + goto error; + } + +#if !COAP_DISABLE_TCP + if (COAP_PROTO_RELIABLE(session->proto) && + (size_t)bytes_written < pdu->used_size + pdu->hdr_size) { + if (coap_session_delay_pdu(session, pdu, NULL) == COAP_PDU_DELAYED) { + session->partial_write = (size_t)bytes_written; + /* do not free pdu as it is stored with session for later use */ + return pdu->mid; + } else { + goto error; + } + } +#endif /* !COAP_DISABLE_TCP */ + + if (pdu->type != COAP_MESSAGE_CON + || COAP_PROTO_RELIABLE(session->proto)) { + coap_mid_t id = pdu->mid; + coap_delete_pdu(pdu); + return id; + } + + coap_queue_t *node = coap_new_node(); + if (!node) { + coap_log(LOG_DEBUG, "coap_wait_ack: insufficient memory\n"); + goto error; + } + + node->id = pdu->mid; + node->pdu = pdu; + coap_prng(&r, sizeof(r)); + /* add timeout in range [ACK_TIMEOUT...ACK_TIMEOUT * ACK_RANDOM_FACTOR] */ + node->timeout = coap_calc_timeout(session, r); + return coap_wait_ack(session->context, session, node); + error: + coap_delete_pdu(pdu); + return COAP_INVALID_MID; +} + +coap_mid_t +coap_retransmit(coap_context_t *context, coap_queue_t *node) { + if (!context || !node) + return COAP_INVALID_MID; + + /* re-initialize timeout when maximum number of retransmissions are not reached yet */ + if (node->retransmit_cnt < node->session->max_retransmit) { + ssize_t bytes_written; + coap_tick_t now; + + node->retransmit_cnt++; + coap_ticks(&now); + if (context->sendqueue == NULL) { + node->t = node->timeout << node->retransmit_cnt; + context->sendqueue_basetime = now; + } else { + /* make node->t relative to context->sendqueue_basetime */ + node->t = (now - context->sendqueue_basetime) + (node->timeout << node->retransmit_cnt); + } + coap_insert_node(&context->sendqueue, node); +#ifdef WITH_LWIP + if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */ + coap_retransmittimer_restart(context); +#endif + + if (node->is_mcast) { + coap_log(LOG_DEBUG, "** %s: mid=0x%x: mcast delayed transmission\n", + coap_session_str(node->session), node->id); + } else { + coap_log(LOG_DEBUG, "** %s: mid=0x%x: retransmission #%d\n", + coap_session_str(node->session), node->id, node->retransmit_cnt); + } + + if (node->session->con_active) + node->session->con_active--; + bytes_written = coap_send_pdu(node->session, node->pdu, node); + + if (node->is_mcast) { + coap_session_connected(node->session); + coap_delete_node(node); + return COAP_INVALID_MID; + } + if (bytes_written == COAP_PDU_DELAYED) { + /* PDU was not retransmitted immediately because a new handshake is + in progress. node was moved to the send queue of the session. */ + return node->id; + } + + if (bytes_written < 0) + return (int)bytes_written; + + return node->id; + } + + /* no more retransmissions, remove node from system */ + +#ifndef WITH_CONTIKI + coap_log(LOG_DEBUG, "** %s: mid=0x%x: give up after %d attempts\n", + coap_session_str(node->session), node->id, node->retransmit_cnt); +#endif + +#if COAP_SERVER_SUPPORT + /* Check if subscriptions exist that should be canceled after + COAP_OBS_MAX_FAIL */ + if (COAP_RESPONSE_CLASS(node->pdu->code) >= 2) { + coap_binary_t token = { 0, NULL }; + + token.length = node->pdu->token_length; + token.s = node->pdu->token; + + coap_handle_failed_notify(context, node->session, &token); + } +#endif /* COAP_SERVER_SUPPORT */ + if (node->session->con_active) { + node->session->con_active--; + if (node->session->state == COAP_SESSION_STATE_ESTABLISHED) { + /* + * As there may be another CON in a different queue entry on the same + * session that needs to be immediately released, + * coap_session_connected() is called. + * However, there is the possibility coap_wait_ack() may be called for + * this node (queue) and re-added to context->sendqueue. + * coap_delete_node(node) called shortly will handle this and remove it. + */ + coap_session_connected(node->session); + } + } + + /* And finally delete the node */ + if (node->pdu->type == COAP_MESSAGE_CON && context->nack_handler) + context->nack_handler(node->session, node->pdu, COAP_NACK_TOO_MANY_RETRIES, node->id); + coap_delete_node(node); + return COAP_INVALID_MID; +} + +#ifdef WITH_LWIP +/* WITH_LWIP, this is handled by coap_recv in a different way */ +void +coap_io_do_io(coap_context_t *ctx, coap_tick_t now) { + return; +} +#else /* WITH_LWIP */ + +static int +coap_handle_dgram_for_proto(coap_context_t *ctx, coap_session_t *session, coap_packet_t *packet) { + uint8_t *data; + size_t data_len; + int result = -1; + + coap_packet_get_memmapped(packet, &data, &data_len); + + if (session->proto == COAP_PROTO_DTLS) { +#if COAP_SERVER_SUPPORT + if (session->type == COAP_SESSION_TYPE_HELLO) + result = coap_dtls_hello(session, data, data_len); + else +#endif /* COAP_SERVER_SUPPORT */ + if (session->tls) + result = coap_dtls_receive(session, data, data_len); + } else if (session->proto == COAP_PROTO_UDP) { + result = coap_handle_dgram(ctx, session, data, data_len); + } + return result; +} + +#if COAP_CLIENT_SUPPORT +static void +coap_connect_session(coap_context_t *ctx, + coap_session_t *session, + coap_tick_t now) { + (void)ctx; +#if COAP_DISABLE_TCP + (void)session; + (void)now; +#else /* !COAP_DISABLE_TCP */ + if (coap_socket_connect_tcp2(&session->sock, &session->addr_info.local, + &session->addr_info.remote)) { + session->last_rx_tx = now; + coap_handle_event(session->context, COAP_EVENT_TCP_CONNECTED, session); + if (session->proto == COAP_PROTO_TCP) { + coap_session_send_csm(session); + } else if (session->proto == COAP_PROTO_TLS) { + int connected = 0; + session->state = COAP_SESSION_STATE_HANDSHAKE; + session->tls = coap_tls_new_client_session(session, &connected); + if (session->tls) { + if (connected) { + coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, + session); + coap_session_send_csm(session); + } + } else { + coap_handle_event(session->context, COAP_EVENT_DTLS_ERROR, session); + coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + } + } + } else { + coap_handle_event(session->context, COAP_EVENT_TCP_FAILED, session); + coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); + } +#endif /* !COAP_DISABLE_TCP */ +} +#endif /* COAP_CLIENT_SUPPORT */ + +static void +coap_write_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now) { + (void)ctx; + assert(session->sock.flags & COAP_SOCKET_CONNECTED); + + while (session->delayqueue) { + ssize_t bytes_written; + coap_queue_t *q = session->delayqueue; + coap_log(LOG_DEBUG, "** %s: mid=0x%x: transmitted after delay\n", + coap_session_str(session), (int)q->pdu->mid); + assert(session->partial_write < q->pdu->used_size + q->pdu->hdr_size); + switch (session->proto) { + case COAP_PROTO_TCP: +#if !COAP_DISABLE_TCP + bytes_written = coap_session_write( + session, + q->pdu->token - q->pdu->hdr_size + session->partial_write, + q->pdu->used_size + q->pdu->hdr_size - session->partial_write + ); +#endif /* !COAP_DISABLE_TCP */ + break; + case COAP_PROTO_TLS: +#if !COAP_DISABLE_TCP + bytes_written = coap_tls_write( + session, + q->pdu->token - q->pdu->hdr_size - session->partial_write, + q->pdu->used_size + q->pdu->hdr_size - session->partial_write + ); +#endif /* !COAP_DISABLE_TCP */ + break; + case COAP_PROTO_NONE: + case COAP_PROTO_UDP: + case COAP_PROTO_DTLS: + default: + bytes_written = -1; + break; + } + if (bytes_written > 0) + session->last_rx_tx = now; + if (bytes_written <= 0 || (size_t)bytes_written < q->pdu->used_size + q->pdu->hdr_size - session->partial_write) { + if (bytes_written > 0) + session->partial_write += (size_t)bytes_written; + break; + } + session->delayqueue = q->next; + session->partial_write = 0; + coap_delete_node(q); + } +} + +static void +coap_read_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now) { +#if COAP_CONSTRAINED_STACK + static coap_mutex_t s_static_mutex = COAP_MUTEX_INITIALIZER; + static coap_packet_t s_packet; +#else /* ! COAP_CONSTRAINED_STACK */ + coap_packet_t s_packet; +#endif /* ! COAP_CONSTRAINED_STACK */ + coap_packet_t *packet = &s_packet; + +#if COAP_CONSTRAINED_STACK + coap_mutex_lock(&s_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + + assert(session->sock.flags & (COAP_SOCKET_CONNECTED | COAP_SOCKET_MULTICAST)); + + if (COAP_PROTO_NOT_RELIABLE(session->proto)) { + ssize_t bytes_read; + memcpy(&packet->addr_info, &session->addr_info, sizeof(packet->addr_info)); + bytes_read = ctx->network_read(&session->sock, packet); + + if (bytes_read < 0) { + if (bytes_read == -2) + /* Reset the session back to startup defaults */ + coap_session_disconnected(session, COAP_NACK_ICMP_ISSUE); + else + coap_log(LOG_WARNING, "* %s: read error\n", + coap_session_str(session)); + } else if (bytes_read > 0) { + session->last_rx_tx = now; + memcpy(&session->addr_info, &packet->addr_info, + sizeof(session->addr_info)); + coap_log(LOG_DEBUG, "* %s: received %zd bytes\n", + coap_session_str(session), bytes_read); + coap_handle_dgram_for_proto(ctx, session, packet); + } +#if !COAP_DISABLE_TCP + } else { + ssize_t bytes_read = 0; + const uint8_t *p; + int retry; + /* adjust for LWIP */ + uint8_t *buf = packet->payload; + size_t buf_len = sizeof(packet->payload); + + do { + if (session->proto == COAP_PROTO_TCP) + bytes_read = coap_socket_read(&session->sock, buf, buf_len); + else if (session->proto == COAP_PROTO_TLS) + bytes_read = coap_tls_read(session, buf, buf_len); + if (bytes_read > 0) { + coap_log(LOG_DEBUG, "* %s: received %zd bytes\n", + coap_session_str(session), bytes_read); + session->last_rx_tx = now; + } + p = buf; + retry = bytes_read == (ssize_t)buf_len; + while (bytes_read > 0) { + if (session->partial_pdu) { + size_t len = session->partial_pdu->used_size + + session->partial_pdu->hdr_size + - session->partial_read; + size_t n = min(len, (size_t)bytes_read); + memcpy(session->partial_pdu->token - session->partial_pdu->hdr_size + + session->partial_read, p, n); + p += n; + bytes_read -= n; + if (n == len) { + if (coap_pdu_parse_header(session->partial_pdu, session->proto) + && coap_pdu_parse_opt(session->partial_pdu)) { +#if COAP_CONSTRAINED_STACK + coap_mutex_unlock(&s_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + coap_dispatch(ctx, session, session->partial_pdu); +#if COAP_CONSTRAINED_STACK + coap_mutex_lock(&s_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + } + coap_delete_pdu(session->partial_pdu); + session->partial_pdu = NULL; + session->partial_read = 0; + } else { + session->partial_read += n; + } + } else if (session->partial_read > 0) { + size_t hdr_size = coap_pdu_parse_header_size(session->proto, + session->read_header); + size_t len = hdr_size - session->partial_read; + size_t n = min(len, (size_t)bytes_read); + memcpy(session->read_header + session->partial_read, p, n); + p += n; + bytes_read -= n; + if (n == len) { + size_t size = coap_pdu_parse_size(session->proto, session->read_header, + hdr_size); + if (size > COAP_DEFAULT_MAX_PDU_RX_SIZE) { + coap_log(LOG_WARNING, + "** %s: incoming PDU length too large (%zu > %lu)\n", + coap_session_str(session), + size, COAP_DEFAULT_MAX_PDU_RX_SIZE); + bytes_read = -1; + break; + } + /* Need max space incase PDU is updated with updated token etc. */ + session->partial_pdu = coap_pdu_init(0, 0, 0, + coap_session_max_pdu_rcv_size(session)); + if (session->partial_pdu == NULL) { + bytes_read = -1; + break; + } + if (session->partial_pdu->alloc_size < size && !coap_pdu_resize(session->partial_pdu, size)) { + bytes_read = -1; + break; + } + session->partial_pdu->hdr_size = (uint8_t)hdr_size; + session->partial_pdu->used_size = size; + memcpy(session->partial_pdu->token - hdr_size, session->read_header, hdr_size); + session->partial_read = hdr_size; + if (size == 0) { + if (coap_pdu_parse_header(session->partial_pdu, session->proto)) { +#if COAP_CONSTRAINED_STACK + coap_mutex_unlock(&s_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + coap_dispatch(ctx, session, session->partial_pdu); +#if COAP_CONSTRAINED_STACK + coap_mutex_lock(&s_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + } + coap_delete_pdu(session->partial_pdu); + session->partial_pdu = NULL; + session->partial_read = 0; + } + } else { + session->partial_read += bytes_read; + } + } else { + session->read_header[0] = *p++; + bytes_read -= 1; + if (!coap_pdu_parse_header_size(session->proto, + session->read_header)) { + bytes_read = -1; + break; + } + session->partial_read = 1; + } + } + } while (bytes_read == 0 && retry); + if (bytes_read < 0) + coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); +#endif /* !COAP_DISABLE_TCP */ + } +#if COAP_CONSTRAINED_STACK + coap_mutex_unlock(&s_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ +} + +#if COAP_SERVER_SUPPORT +static int +coap_read_endpoint(coap_context_t *ctx, coap_endpoint_t *endpoint, coap_tick_t now) { + ssize_t bytes_read = -1; + int result = -1; /* the value to be returned */ +#if COAP_CONSTRAINED_STACK + static coap_mutex_t e_static_mutex = COAP_MUTEX_INITIALIZER; + static coap_packet_t e_packet; +#else /* ! COAP_CONSTRAINED_STACK */ + coap_packet_t e_packet; +#endif /* ! COAP_CONSTRAINED_STACK */ + coap_packet_t *packet = &e_packet; + + assert(COAP_PROTO_NOT_RELIABLE(endpoint->proto)); + assert(endpoint->sock.flags & COAP_SOCKET_BOUND); + +#if COAP_CONSTRAINED_STACK + coap_mutex_lock(&e_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + + /* Need to do this as there may be holes in addr_info */ + memset(&packet->addr_info, 0, sizeof(packet->addr_info)); + coap_address_init(&packet->addr_info.remote); + coap_address_copy(&packet->addr_info.local, &endpoint->bind_addr); + bytes_read = ctx->network_read(&endpoint->sock, packet); + + if (bytes_read < 0) { + coap_log(LOG_WARNING, "* %s: read failed\n", coap_endpoint_str(endpoint)); + } else if (bytes_read > 0) { + coap_session_t *session = coap_endpoint_get_session(endpoint, packet, now); + if (session) { + coap_log(LOG_DEBUG, "* %s: received %zd bytes\n", + coap_session_str(session), bytes_read); + result = coap_handle_dgram_for_proto(ctx, session, packet); + if (endpoint->proto == COAP_PROTO_DTLS && session->type == COAP_SESSION_TYPE_HELLO && result == 1) + coap_session_new_dtls_session(session, now); + } + } +#if COAP_CONSTRAINED_STACK + coap_mutex_unlock(&e_static_mutex); +#endif /* COAP_CONSTRAINED_STACK */ + return result; +} + +static int +coap_write_endpoint(coap_context_t *ctx, coap_endpoint_t *endpoint, coap_tick_t now) { + (void)ctx; + (void)endpoint; + (void)now; + return 0; +} + +static int +coap_accept_endpoint(coap_context_t *ctx, coap_endpoint_t *endpoint, + coap_tick_t now) { + coap_session_t *session = coap_new_server_session(ctx, endpoint); + if (session) + session->last_rx_tx = now; + return session != NULL; +} +#endif /* COAP_SERVER_SUPPORT */ + +void +coap_io_do_io(coap_context_t *ctx, coap_tick_t now) { +#ifdef COAP_EPOLL_SUPPORT + (void)ctx; + (void)now; + coap_log(LOG_EMERG, + "coap_io_do_io() requires libcoap not compiled for using epoll\n"); +#else /* ! COAP_EPOLL_SUPPORT */ + coap_session_t *s, *rtmp; + +#if COAP_SERVER_SUPPORT + coap_endpoint_t *ep, *tmp; + LL_FOREACH_SAFE(ctx->endpoint, ep, tmp) { + if ((ep->sock.flags & COAP_SOCKET_CAN_READ) != 0) + coap_read_endpoint(ctx, ep, now); + if ((ep->sock.flags & COAP_SOCKET_CAN_WRITE) != 0) + coap_write_endpoint(ctx, ep, now); + if ((ep->sock.flags & COAP_SOCKET_CAN_ACCEPT) != 0) + coap_accept_endpoint(ctx, ep, now); + SESSIONS_ITER_SAFE(ep->sessions, s, rtmp) { + /* Make sure the session object is not deleted in one of the callbacks */ + coap_session_reference(s); + if ((s->sock.flags & COAP_SOCKET_CAN_READ) != 0) { + coap_read_session(ctx, s, now); + } + if ((s->sock.flags & COAP_SOCKET_CAN_WRITE) != 0) { + coap_write_session(ctx, s, now); + } + coap_session_release(s); + } + } +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT + SESSIONS_ITER_SAFE(ctx->sessions, s, rtmp) { + /* Make sure the session object is not deleted in one of the callbacks */ + coap_session_reference(s); + if ((s->sock.flags & COAP_SOCKET_CAN_CONNECT) != 0) { + coap_connect_session(ctx, s, now); + } + if ((s->sock.flags & COAP_SOCKET_CAN_READ) != 0 && s->ref > 1) { + coap_read_session(ctx, s, now); + } + if ((s->sock.flags & COAP_SOCKET_CAN_WRITE) != 0 && s->ref > 1) { + coap_write_session(ctx, s, now); + } + coap_session_release( s ); + } +#endif /* COAP_CLIENT_SUPPORT */ +#endif /* ! COAP_EPOLL_SUPPORT */ +} + +/* + * While this code in part replicates coap_io_do_io(), doing the functions + * directly saves having to iterate through the endpoints / sessions. + */ +void +coap_io_do_epoll(coap_context_t *ctx, struct epoll_event *events, size_t nevents) { +#ifndef COAP_EPOLL_SUPPORT + (void)ctx; + (void)events; + (void)nevents; + coap_log(LOG_EMERG, + "coap_io_do_epoll() requires libcoap compiled for using epoll\n"); +#else /* COAP_EPOLL_SUPPORT */ + coap_tick_t now; + size_t j; + + coap_ticks(&now); + for(j = 0; j < nevents; j++) { + coap_socket_t *sock = (coap_socket_t*)events[j].data.ptr; + + /* Ignore 'timer trigger' ptr which is NULL */ + if (sock) { +#if COAP_SERVER_SUPPORT + if (sock->endpoint) { + coap_endpoint_t *endpoint = sock->endpoint; + if ((sock->flags & COAP_SOCKET_WANT_READ) && + (events[j].events & EPOLLIN)) { + sock->flags |= COAP_SOCKET_CAN_READ; + coap_read_endpoint(endpoint->context, endpoint, now); + } + + if ((sock->flags & COAP_SOCKET_WANT_WRITE) && + (events[j].events & EPOLLOUT)) { + /* + * Need to update this to EPOLLIN as EPOLLOUT will normally always + * be true causing epoll_wait to return early + */ + coap_epoll_ctl_mod(sock, EPOLLIN, __func__); + sock->flags |= COAP_SOCKET_CAN_WRITE; + coap_write_endpoint(endpoint->context, endpoint, now); + } + + if ((sock->flags & COAP_SOCKET_WANT_ACCEPT) && + (events[j].events & EPOLLIN)) { + sock->flags |= COAP_SOCKET_CAN_ACCEPT; + coap_accept_endpoint(endpoint->context, endpoint, now); + } + + } + else +#endif /* COAP_SERVER_SUPPORT */ + if (sock->session) { + coap_session_t *session = sock->session; + + /* Make sure the session object is not deleted + in one of the callbacks */ + coap_session_reference(session); +#if COAP_CLIENT_SUPPORT + if ((sock->flags & COAP_SOCKET_WANT_CONNECT) && + (events[j].events & (EPOLLOUT|EPOLLERR|EPOLLHUP|EPOLLRDHUP))) { + sock->flags |= COAP_SOCKET_CAN_CONNECT; + coap_connect_session(session->context, session, now); + if (sock->flags != COAP_SOCKET_EMPTY && + !(sock->flags & COAP_SOCKET_WANT_WRITE)) { + coap_epoll_ctl_mod(sock, EPOLLIN, __func__); + } + } +#endif /* COAP_CLIENT_SUPPORT */ + + if ((sock->flags & COAP_SOCKET_WANT_READ) && + (events[j].events & (EPOLLIN|EPOLLERR|EPOLLHUP|EPOLLRDHUP))) { + sock->flags |= COAP_SOCKET_CAN_READ; + coap_read_session(session->context, session, now); + } + + if ((sock->flags & COAP_SOCKET_WANT_WRITE) && + (events[j].events & (EPOLLOUT|EPOLLERR|EPOLLHUP|EPOLLRDHUP))) { + /* + * Need to update this to EPOLLIN as EPOLLOUT will normally always + * be true causing epoll_wait to return early + */ + coap_epoll_ctl_mod(sock, EPOLLIN, __func__); + sock->flags |= COAP_SOCKET_CAN_WRITE; + coap_write_session(session->context, session, now); + } + /* Now dereference session so it can go away if needed */ + coap_session_release(session); + } + } + else if (ctx->eptimerfd != -1) { + /* + * 'timer trigger' must have fired. eptimerfd needs to be read to clear + * it so that it does not set EPOLLIN in the next epoll_wait(). + */ + uint64_t count; + + /* Check the result from read() to suppress the warning on + * systems that declare read() with warn_unused_result. */ + if (read(ctx->eptimerfd, &count, sizeof(count)) == -1) { + /* do nothing */; + } + } + } + /* And update eptimerfd as to when to next trigger */ + coap_ticks(&now); + coap_io_prepare_epoll(ctx, now); +#endif /* COAP_EPOLL_SUPPORT */ +} + +int +coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, + uint8_t *msg, size_t msg_len) { + + coap_pdu_t *pdu = NULL; + + assert(COAP_PROTO_NOT_RELIABLE(session->proto)); + if (msg_len < 4) { + /* Minimum size of CoAP header - ignore runt */ + return -1; + } + + /* Need max space incase PDU is updated with updated token etc. */ + pdu = coap_pdu_init(0, 0, 0, coap_session_max_pdu_size(session)); + if (!pdu) + goto error; + + if (!coap_pdu_parse(session->proto, msg, msg_len, pdu)) { + coap_log(LOG_WARNING, "discard malformed PDU\n"); + goto error; + } + + coap_dispatch(ctx, session, pdu); + coap_delete_pdu(pdu); + return 0; + +error: + /* + * https://tools.ietf.org/html/rfc7252#section-4.2 MUST send RST + * https://tools.ietf.org/html/rfc7252#section-4.3 MAY send RST + */ + coap_send_rst(session, pdu); + coap_delete_pdu(pdu); + return -1; +} +#endif /* not WITH_LWIP */ + +int +coap_remove_from_queue(coap_queue_t **queue, coap_session_t *session, coap_mid_t id, coap_queue_t **node) { + coap_queue_t *p, *q; + + if (!queue || !*queue) + return 0; + + /* replace queue head if PDU's time is less than head's time */ + + if (session == (*queue)->session && id == (*queue)->id) { /* found message id */ + *node = *queue; + *queue = (*queue)->next; + if (*queue) { /* adjust relative time of new queue head */ + (*queue)->t += (*node)->t; + } + (*node)->next = NULL; + coap_log(LOG_DEBUG, "** %s: mid=0x%x: removed 1\n", + coap_session_str(session), id); + return 1; + } + + /* search message id queue to remove (only first occurence will be removed) */ + q = *queue; + do { + p = q; + q = q->next; + } while (q && (session != q->session || id != q->id)); + + if (q) { /* found message id */ + p->next = q->next; + if (p->next) { /* must update relative time of p->next */ + p->next->t += q->t; + } + q->next = NULL; + *node = q; + coap_log(LOG_DEBUG, "** %s: mid=0x%x: removed 2\n", + coap_session_str(session), id); + return 1; + } + + return 0; + +} + +void +coap_cancel_session_messages(coap_context_t *context, coap_session_t *session, + coap_nack_reason_t reason) { + coap_queue_t *p, *q; + + while (context->sendqueue && context->sendqueue->session == session) { + q = context->sendqueue; + context->sendqueue = q->next; + coap_log(LOG_DEBUG, "** %s: mid=0x%x: removed 3\n", + coap_session_str(session), q->id); + if (q->pdu->type == COAP_MESSAGE_CON && context->nack_handler) + context->nack_handler(session, q->pdu, reason, q->id); + coap_delete_node(q); + } + + if (!context->sendqueue) + return; + + p = context->sendqueue; + q = p->next; + + while (q) { + if (q->session == session) { + p->next = q->next; + coap_log(LOG_DEBUG, "** %s: mid=0x%x: removed 4\n", + coap_session_str(session), q->id); + if (q->pdu->type == COAP_MESSAGE_CON && context->nack_handler) + context->nack_handler(session, q->pdu, reason, q->id); + coap_delete_node(q); + q = p->next; + } else { + p = q; + q = q->next; + } + } +} + +void +coap_cancel_all_messages(coap_context_t *context, coap_session_t *session, + const uint8_t *token, size_t token_length) { + /* cancel all messages in sendqueue that belong to session + * and use the specified token */ + coap_queue_t **p, *q; + + if (!context->sendqueue) + return; + + p = &context->sendqueue; + q = *p; + + while (q) { + if (q->session == session && + token_match(token, token_length, + q->pdu->token, q->pdu->token_length)) { + *p = q->next; + coap_log(LOG_DEBUG, "** %s: mid=0x%x: removed 6\n", + coap_session_str(session), q->id); + if (q->pdu->type == COAP_MESSAGE_CON && session->con_active) { + session->con_active--; + if (session->state == COAP_SESSION_STATE_ESTABLISHED) + /* Flush out any entries on session->delayqueue */ + coap_session_connected(session); + } + coap_delete_node(q); + } else { + p = &(q->next); + } + q = *p; + } +} + +coap_pdu_t * +coap_new_error_response(const coap_pdu_t *request, coap_pdu_code_t code, + coap_opt_filter_t *opts) { + coap_opt_iterator_t opt_iter; + coap_pdu_t *response; + size_t size = request->token_length; + unsigned char type; + coap_opt_t *option; + coap_option_num_t opt_num = 0; /* used for calculating delta-storage */ + +#if COAP_ERROR_PHRASE_LENGTH > 0 + const char *phrase; + if (code != COAP_RESPONSE_CODE(508)) { + phrase = coap_response_phrase(code); + + /* Need some more space for the error phrase and payload start marker */ + if (phrase) + size += strlen(phrase) + 1; + } + else { + /* + * Need space for IP for 5.08 response which is filled in in + * coap_send_internal() + * https://www.rfc-editor.org/rfc/rfc8768.html#section-4 + */ + phrase = NULL; + size += INET6_ADDRSTRLEN; + } +#endif + + assert(request); + + /* cannot send ACK if original request was not confirmable */ + type = request->type == COAP_MESSAGE_CON + ? COAP_MESSAGE_ACK + : COAP_MESSAGE_NON; + + /* Estimate how much space we need for options to copy from + * request. We always need the Token, for 4.02 the unknown critical + * options must be included as well. */ + + /* we do not want these */ + coap_option_filter_unset(opts, COAP_OPTION_CONTENT_FORMAT); + coap_option_filter_unset(opts, COAP_OPTION_HOP_LIMIT); + /* Unsafe to send this back */ + coap_option_filter_unset(opts, COAP_OPTION_OSCORE); + + coap_option_iterator_init(request, &opt_iter, opts); + + /* Add size of each unknown critical option. As known critical + options as well as elective options are not copied, the delta + value might grow. + */ + while ((option = coap_option_next(&opt_iter))) { + uint16_t delta = opt_iter.number - opt_num; + /* calculate space required to encode (opt_iter.number - opt_num) */ + if (delta < 13) { + size++; + } else if (delta < 269) { + size += 2; + } else { + size += 3; + } + + /* add coap_opt_length(option) and the number of additional bytes + * required to encode the option length */ + + size += coap_opt_length(option); + switch (*option & 0x0f) { + case 0x0e: + size++; + /* fall through */ + case 0x0d: + size++; + break; + default: + ; + } + + opt_num = opt_iter.number; + } + + /* Now create the response and fill with options and payload data. */ + response = coap_pdu_init(type, code, request->mid, size); + if (response) { + /* copy token */ + if (!coap_add_token(response, request->token_length, + request->token)) { + coap_log(LOG_DEBUG, "cannot add token to error response\n"); + coap_delete_pdu(response); + return NULL; + } + + /* copy all options */ + coap_option_iterator_init(request, &opt_iter, opts); + while ((option = coap_option_next(&opt_iter))) { + coap_add_option_internal(response, opt_iter.number, + coap_opt_length(option), + coap_opt_value(option)); + } + +#if COAP_ERROR_PHRASE_LENGTH > 0 + /* note that diagnostic messages do not need a Content-Format option. */ + if (phrase) + coap_add_data(response, (size_t)strlen(phrase), (const uint8_t *)phrase); +#endif + } + + return response; +} + +#if COAP_SERVER_SUPPORT +/** + * Quick hack to determine the size of the resource description for + * .well-known/core. + */ +COAP_STATIC_INLINE ssize_t +get_wkc_len(coap_context_t *context, const coap_string_t *query_filter) { + unsigned char buf[1]; + size_t len = 0; + + if (coap_print_wellknown(context, buf, &len, UINT_MAX, query_filter) & + COAP_PRINT_STATUS_ERROR) { + coap_log(LOG_WARNING, "cannot determine length of /.well-known/core\n"); + return -1L; + } + + return len; +} + +#define SZX_TO_BYTES(SZX) ((size_t)(1 << ((SZX) + 4))) + +static void +free_wellknown_response(coap_session_t *session COAP_UNUSED, void *app_ptr) { + coap_delete_string(app_ptr); +} + +static void +hnd_get_wellknown(coap_resource_t *resource, + coap_session_t *session, + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response) { + size_t len = 0; + coap_string_t *data_string = NULL; + int result = 0; + ssize_t wkc_len = get_wkc_len(session->context, query); + + if (wkc_len) { + if (wkc_len < 0) + goto error; + data_string = coap_new_string(wkc_len); + if (!data_string) + goto error; + + len = wkc_len; + result = coap_print_wellknown(session->context, data_string->s, &len, 0, + query); + if ((result & COAP_PRINT_STATUS_ERROR) != 0) { + coap_log(LOG_DEBUG, "coap_print_wellknown failed\n"); + goto error; + } + assert (len <= (size_t)wkc_len); + data_string->length = len; + + if (!(session->block_mode & COAP_BLOCK_USE_LIBCOAP)) { + uint8_t buf[4]; + + if (!coap_insert_option(response, COAP_OPTION_CONTENT_FORMAT, + coap_encode_var_safe(buf, sizeof(buf), + COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf)) { + goto error; + } + if (response->used_size + len + 1 > response->max_size) { + /* + * Data does not fit into a packet and no libcoap block support + * +1 for end of options marker + */ + coap_log(LOG_DEBUG, + ".well-known/core: truncating data length to %zu from %zu\n", + len, response->max_size - response->used_size - 1); + len = response->max_size - response->used_size - 1; + } + if (!coap_add_data(response, len, data_string->s)) { + goto error; + } + free_wellknown_response(session, data_string); + } else if (!coap_add_data_large_response(resource, session, request, + response, query, + COAP_MEDIATYPE_APPLICATION_LINK_FORMAT, + -1, 0, data_string->length, + data_string->s, + free_wellknown_response, + data_string)) { + goto error_released; + } + } + response->code = COAP_RESPONSE_CODE(205); + return; + +error: + free_wellknown_response(session, data_string); +error_released: + if (response->code == 0) { + /* set error code 5.03 and remove all options and data from response */ + response->code = COAP_RESPONSE_CODE(503); + response->used_size = response->token_length; + response->data = NULL; + } +} +#endif /* COAP_SERVER_SUPPORT */ + +/** + * This function cancels outstanding messages for the session and + * token specified in @p sent. Any observation relationship for + * sent->session and the token are removed. Calling this function is + * required when receiving an RST message (usually in response to a + * notification) or a GET request with the Observe option set to 1. + * + * This function returns @c 0 when the token is unknown with this + * peer, or a value greater than zero otherwise. + */ +static int +coap_cancel(coap_context_t *context, const coap_queue_t *sent) { + coap_binary_t token = { 0, NULL }; + int num_cancelled = 0; /* the number of observers cancelled */ + + (void)context; + /* remove observer for this resource, if any + * get token from sent and try to find a matching resource. Uh! + */ + + COAP_SET_STR(&token, sent->pdu->token_length, sent->pdu->token); + +#if COAP_SERVER_SUPPORT + RESOURCES_ITER(context->resources, r) { + coap_cancel_all_messages(context, sent->session, token.s, token.length); + num_cancelled += coap_delete_observer(r, sent->session, &token); + } +#endif /* COAP_SERVER_SUPPORT */ + + return num_cancelled; +} + +#if COAP_SERVER_SUPPORT +/** + * Internal flags to control the treatment of responses (specifically + * in presence of the No-Response option). + */ +enum respond_t { RESPONSE_DEFAULT, RESPONSE_DROP, RESPONSE_SEND }; + +/* + * Checks for No-Response option in given @p request and + * returns @c RESPONSE_DROP if @p response should be suppressed + * according to RFC 7967. + * + * If the response is a confirmable piggybacked response and RESPONSE_DROP, + * change it to an empty ACK and @c RESPONSE_SEND so the client does not keep + * on retrying. + * + * Checks if the response code is 0.00 and if either the session is reliable or + * non-confirmable, @c RESPONSE_DROP is also returned. + * + * Multicast response checking is also carried out. + * + * NOTE: It is the responsibility of the application to determine whether + * a delayed separate response should be sent as the original requesting packet + * containing the No-Response option has long since gone. + * + * The value of the No-Response option is encoded as + * follows: + * + * @verbatim + * +-------+-----------------------+-----------------------------------+ + * | Value | Binary Representation | Description | + * +-------+-----------------------+-----------------------------------+ + * | 0 | | Interested in all responses. | + * +-------+-----------------------+-----------------------------------+ + * | 2 | 00000010 | Not interested in 2.xx responses. | + * +-------+-----------------------+-----------------------------------+ + * | 8 | 00001000 | Not interested in 4.xx responses. | + * +-------+-----------------------+-----------------------------------+ + * | 16 | 00010000 | Not interested in 5.xx responses. | + * +-------+-----------------------+-----------------------------------+ + * @endverbatim + * + * @param request The CoAP request to check for the No-Response option. + * This parameter must not be NULL. + * @param response The response that is potentially suppressed. + * This parameter must not be NULL. + * @param session The session this request/response are associated with. + * This parameter must not be NULL. + * @return RESPONSE_DEFAULT when no special treatment is requested, + * RESPONSE_DROP when the response must be discarded, or + * RESPONSE_SEND when the response must be sent. + */ +static enum respond_t +no_response(coap_pdu_t *request, coap_pdu_t *response, + coap_session_t *session, coap_resource_t *resource) { + coap_opt_t *nores; + coap_opt_iterator_t opt_iter; + unsigned int val = 0; + + assert(request); + assert(response); + + if (COAP_RESPONSE_CLASS(response->code) > 0) { + nores = coap_check_option(request, COAP_OPTION_NORESPONSE, &opt_iter); + + if (nores) { + val = coap_decode_var_bytes(coap_opt_value(nores), coap_opt_length(nores)); + + /* The response should be dropped when the bit corresponding to + * the response class is set (cf. table in function + * documentation). When a No-Response option is present and the + * bit is not set, the sender explicitly indicates interest in + * this response. */ + if (((1 << (COAP_RESPONSE_CLASS(response->code) - 1)) & val) > 0) { + /* Should be dropping the response */ + if (response->type == COAP_MESSAGE_ACK && + COAP_PROTO_NOT_RELIABLE(session->proto)) { + /* Still need to ACK the request */ + response->code = 0; + /* Remove token/data from piggybacked acknowledgment PDU */ + response->token_length = 0; + response->used_size = 0; + return RESPONSE_SEND; + } + else { + return RESPONSE_DROP; + } + } else { + /* True for mcast as well RFC7967 2.1 */ + return RESPONSE_SEND; + } + } else if (resource && session->context->mcast_per_resource && + coap_is_mcast(&session->addr_info.local)) { + /* Handle any mcast suppression specifics if no NoResponse option */ + if ((resource->flags & + COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_XX) && + COAP_RESPONSE_CLASS(response->code) == 2) { + return RESPONSE_DROP; + } else if ((resource->flags & + COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_05) && + response->code == COAP_RESPONSE_CODE(205)) { + if (response->data == NULL) + return RESPONSE_DROP; + } else if ((resource->flags & + COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_SUPPRESS_4_XX) == 0 && + COAP_RESPONSE_CLASS(response->code) == 4) { + return RESPONSE_DROP; + } else if ((resource->flags & + COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_SUPPRESS_5_XX) == 0 && + COAP_RESPONSE_CLASS(response->code) == 5) { + return RESPONSE_DROP; + } + } + } + else if (COAP_PDU_IS_EMPTY(response) && + (response->type == COAP_MESSAGE_NON || + COAP_PROTO_RELIABLE(session->proto))) { + /* response is 0.00, and this is reliable or non-confirmable */ + return RESPONSE_DROP; + } + + /* + * Do not send error responses for requests that were received via + * IP multicast. RFC7252 8.1 + */ + + if (coap_is_mcast(&session->addr_info.local)) { + if (request->type == COAP_MESSAGE_NON && + response->type == COAP_MESSAGE_RST) + return RESPONSE_DROP; + + if ((!resource || session->context->mcast_per_resource == 0) && + COAP_RESPONSE_CLASS(response->code) > 2) + return RESPONSE_DROP; + } + + /* Default behavior applies when we are not dealing with a response + * (class == 0) or the request did not contain a No-Response option. + */ + return RESPONSE_DEFAULT; +} + +static coap_str_const_t coap_default_uri_wellknown = + { sizeof(COAP_DEFAULT_URI_WELLKNOWN)-1, + (const uint8_t *)COAP_DEFAULT_URI_WELLKNOWN }; + +/* Initialized in coap_startup() */ +static coap_resource_t resource_uri_wellknown; + +static void +handle_request(coap_context_t *context, coap_session_t *session, coap_pdu_t *pdu) { + coap_method_handler_t h = NULL; + coap_pdu_t *response = NULL; + coap_opt_filter_t opt_filter; + coap_resource_t *resource = NULL; + /* The respond field indicates whether a response must be treated + * specially due to a No-Response option that declares disinterest + * or interest in a specific response class. DEFAULT indicates that + * No-Response has not been specified. */ + enum respond_t respond = RESPONSE_DEFAULT; + coap_opt_iterator_t opt_iter; + coap_opt_t *opt; + int is_proxy_uri = 0; + int is_proxy_scheme = 0; + int skip_hop_limit_check = 0; + int resp; + int send_early_empty_ack = 0; + coap_binary_t token = { pdu->token_length, pdu->token }; + coap_string_t *query = NULL; + coap_opt_t *observe = NULL; + coap_string_t *uri_path = NULL; + int added_block = 0; +#ifndef WITHOUT_ASYNC + coap_bin_const_t tokenc = { pdu->token_length, pdu->token }; + coap_async_t *async; +#endif /* WITHOUT_ASYNC */ + + if (coap_is_mcast(&session->addr_info.local)) { + if (COAP_PROTO_RELIABLE(session->proto) || pdu->type != COAP_MESSAGE_NON) { + coap_log(LOG_INFO, "Invalid multicast packet received RFC7252 8.1\n"); + return; + } + } +#ifndef WITHOUT_ASYNC + async = coap_find_async(session, tokenc); + if (async) { + coap_tick_t now; + + coap_ticks(&now); + if (async->delay == 0 || async->delay > now) { + /* re-transmit missing ACK (only if CON) */ + coap_log(LOG_INFO, "Retransmit async response\n"); + coap_send_ack(session, pdu); + /* and do not pass on to the upper layers */ + return; + } + } +#endif /* WITHOUT_ASYNC */ + + coap_option_filter_clear(&opt_filter); + opt = coap_check_option(pdu, COAP_OPTION_PROXY_SCHEME, &opt_iter); + if (opt) + is_proxy_scheme = 1; + + opt = coap_check_option(pdu, COAP_OPTION_PROXY_URI, &opt_iter); + if (opt) + is_proxy_uri = 1; + + if (is_proxy_scheme || is_proxy_uri) { + coap_uri_t uri; + + if (!context->proxy_uri_resource) { + /* Need to return a 5.05 RFC7252 Section 5.7.2 */ + coap_log(LOG_DEBUG, "Proxy-%s support not configured\n", + is_proxy_scheme ? "Scheme" : "Uri"); + resp = 505; + goto fail_response; + } + if (((size_t)pdu->code - 1 < + (sizeof(resource->handler) / sizeof(resource->handler[0]))) && + !(context->proxy_uri_resource->handler[pdu->code - 1])) { + /* Need to return a 5.05 RFC7252 Section 5.7.2 */ + coap_log(LOG_DEBUG, "Proxy-%s code %d.%02d handler not supported\n", + is_proxy_scheme ? "Scheme" : "Uri", + pdu->code/100, pdu->code%100); + resp = 505; + goto fail_response; + } + + /* Need to check if authority is the proxy endpoint RFC7252 Section 5.7.2 */ + if (is_proxy_uri) { + if (coap_split_proxy_uri(coap_opt_value(opt), + coap_opt_length(opt), &uri) < 0) { + /* Need to return a 5.05 RFC7252 Section 5.7.2 */ + coap_log(LOG_DEBUG, "Proxy-URI not decodable\n"); + resp = 505; + goto fail_response; + } + } + else { + memset(&uri, 0, sizeof(uri)); + opt = coap_check_option(pdu, COAP_OPTION_URI_HOST, &opt_iter); + if (opt) { + uri.host.length = coap_opt_length(opt); + uri.host.s = coap_opt_value(opt); + } else + uri.host.length = 0; + } + + resource = context->proxy_uri_resource; + if (uri.host.length && resource->proxy_name_count && + resource->proxy_name_list) { + size_t i; + + if (resource->proxy_name_count == 1 && + resource->proxy_name_list[0]->length == 0) { + /* If proxy_name_list[0] is zero length, then this is the endpoint */ + i = 0; + } else { + for (i = 0; i < resource->proxy_name_count; i++) { + if (coap_string_equal(&uri.host, resource->proxy_name_list[i])) { + break; + } + } + } + if (i != resource->proxy_name_count) { + /* This server is hosting the proxy connection endpoint */ + if (pdu->crit_opt) { + /* Cannot handle critical option */ + pdu->crit_opt = 0; + resp = 402; + goto fail_response; + } + is_proxy_uri = 0; + is_proxy_scheme = 0; + skip_hop_limit_check = 1; + } + } + resource = NULL; + } + + if (!skip_hop_limit_check) { + opt = coap_check_option(pdu, COAP_OPTION_HOP_LIMIT, &opt_iter); + if (opt) { + size_t hop_limit; + uint8_t buf[4]; + + hop_limit = + coap_decode_var_bytes (coap_opt_value (opt), coap_opt_length (opt)); + if (hop_limit == 1) { + /* coap_send_internal() will fill in the IP address for us */ + resp = 508; + goto fail_response; + } + else if (hop_limit < 1 || hop_limit > 255) { + /* Need to return a 4.00 RFC8768 Section 3 */ + coap_log(LOG_INFO, "Invalid Hop Limit\n"); + resp = 400; + goto fail_response; + } + hop_limit--; + coap_update_option(pdu, COAP_OPTION_HOP_LIMIT, + coap_encode_var_safe8(buf, sizeof(buf), hop_limit), + buf); + } + } + + uri_path = coap_get_uri_path(pdu); + if (!uri_path) + return; + + if (!is_proxy_uri && !is_proxy_scheme) { + /* try to find the resource from the request URI */ + coap_str_const_t uri_path_c = { uri_path->length, uri_path->s }; + resource = coap_get_resource_from_uri_path(context, &uri_path_c); + } + + if ((resource == NULL) || (resource->is_unknown == 1) || + (resource->is_proxy_uri == 1)) { + /* The resource was not found or there is an unexpected match against the + * resource defined for handling unknown or proxy URIs. + */ + if (resource != NULL) + /* Close down unexpected match */ + resource = NULL; + /* + * Check if the request URI happens to be the well-known URI, or if the + * unknown resource handler is defined, a PUT or optionally other methods, + * if configured, for the unknown handler. + * + * if a PROXY URI/Scheme request and proxy URI handler defined, call the + * proxy URI handler + * + * else if well-known URI generate a default response + * + * else if unknown URI handler defined, call the unknown + * URI handler (to allow for potential generation of resource + * [RFC7272 5.8.3]) if the appropriate method is defined. + * + * else if DELETE return 2.02 (RFC7252: 5.8.4. DELETE) + * + * else return 4.04 */ + + if (is_proxy_uri || is_proxy_scheme) { + resource = context->proxy_uri_resource; + } else if (coap_string_equal(uri_path, &coap_default_uri_wellknown)) { + /* request for .well-known/core */ + resource = &resource_uri_wellknown; + } else if ((context->unknown_resource != NULL) && + ((size_t)pdu->code - 1 < + (sizeof(resource->handler) / sizeof(coap_method_handler_t))) && + (context->unknown_resource->handler[pdu->code - 1])) { + /* + * The unknown_resource can be used to handle undefined resources + * for a PUT request and can support any other registered handler + * defined for it + * Example set up code:- + * r = coap_resource_unknown_init(hnd_put_unknown); + * coap_register_request_handler(r, COAP_REQUEST_POST, + * hnd_post_unknown); + * coap_register_request_handler(r, COAP_REQUEST_GET, + * hnd_get_unknown); + * coap_register_request_handler(r, COAP_REQUEST_DELETE, + * hnd_delete_unknown); + * coap_add_resource(ctx, r); + * + * Note: It is not possible to observe the unknown_resource, a separate + * resource must be created (by PUT or POST) which has a GET + * handler to be observed + */ + resource = context->unknown_resource; + } else if (pdu->code == COAP_REQUEST_CODE_DELETE) { + /* + * Request for DELETE on non-existant resource (RFC7252: 5.8.4. DELETE) + */ + coap_log(LOG_DEBUG, "request for unknown resource '%*.*s'," + " return 2.02\n", + (int)uri_path->length, + (int)uri_path->length, + uri_path->s); + resp = 202; + goto fail_response; + } else { /* request for any another resource, return 4.04 */ + + coap_log(LOG_DEBUG, "request for unknown resource '%*.*s', return 4.04\n", + (int)uri_path->length, (int)uri_path->length, uri_path->s); + resp = 404; + goto fail_response; + } + + } + + /* the resource was found, check if there is a registered handler */ + if ((size_t)pdu->code - 1 < + sizeof(resource->handler) / sizeof(coap_method_handler_t)) + h = resource->handler[pdu->code - 1]; + + if (h) { + if (context->mcast_per_resource && + (resource->flags & COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT) == 0 && + coap_is_mcast(&session->addr_info.local)) { + resp = 405; + goto fail_response; + } + + response = coap_pdu_init(pdu->type == COAP_MESSAGE_CON + ? COAP_MESSAGE_ACK + : COAP_MESSAGE_NON, + 0, pdu->mid, coap_session_max_pdu_size(session)); + if (!response) { + coap_log(LOG_ERR, "could not create response PDU\n"); + resp = 500; + goto fail_response; + } +#ifndef WITHOUT_ASYNC + /* If handling a separate response, need CON, not ACK response */ + if (async && pdu->type == COAP_MESSAGE_CON) + response->type = COAP_MESSAGE_CON; +#endif /* WITHOUT_ASYNC */ + + /* Implementation detail: coap_add_token() immediately returns 0 + if response == NULL */ + if (coap_add_token(response, pdu->token_length, pdu->token)) { + int observe_action = COAP_OBSERVE_CANCEL; + coap_block_b_t block; + + query = coap_get_query(pdu); + /* check for Observe option RFC7641 and RFC8132 */ + if (resource->observable && + (pdu->code == COAP_REQUEST_CODE_GET || + pdu->code == COAP_REQUEST_CODE_FETCH)) { + observe = coap_check_option(pdu, COAP_OPTION_OBSERVE, &opt_iter); + if (observe) { + observe_action = + coap_decode_var_bytes(coap_opt_value(observe), + coap_opt_length(observe)); + + if (observe_action == COAP_OBSERVE_ESTABLISH) { + coap_subscription_t *subscription; + + if (coap_get_block_b(session, pdu, COAP_OPTION_BLOCK2, &block)) { + if (block.num != 0) { + response->code = COAP_RESPONSE_CODE(400); + goto skip_handler; + } + } + subscription = coap_add_observer(resource, session, &token, + pdu); + if (subscription) { + uint8_t buf[4]; + + coap_touch_observer(context, session, &token); + coap_add_option_internal(response, COAP_OPTION_OBSERVE, + coap_encode_var_safe(buf, sizeof (buf), + resource->observe), + buf); + } + } + else if (observe_action == COAP_OBSERVE_CANCEL) { + coap_delete_observer(resource, session, &token); + } + else { + coap_log(LOG_INFO, "observe: unexpected action %d\n", observe_action); + } + } + } + + /* TODO for non-proxy requests */ + if (resource == context->proxy_uri_resource && + COAP_PROTO_NOT_RELIABLE(session->proto) && + pdu->type == COAP_MESSAGE_CON) { + /* Make the proxy response separate and fix response later */ + send_early_empty_ack = 1; + } + if (send_early_empty_ack) { + coap_send_ack(session, pdu); + if (pdu->mid == session->last_con_mid) { + /* request has already been processed - do not process it again */ + coap_log(LOG_DEBUG, + "Duplicate request with mid=0x%04x - not processed\n", + pdu->mid); + goto drop_it_no_debug; + } + session->last_con_mid = pdu->mid; + } + if (session->block_mode & COAP_BLOCK_USE_LIBCOAP) { + if (coap_handle_request_put_block(context, session, pdu, response, + resource, uri_path, observe, + query, h, &added_block)) { + goto skip_handler; + } + + if (coap_handle_request_send_block(session, pdu, response, resource, + query)) { + goto skip_handler; + } + } + + /* + * Call the request handler with everything set up + */ + coap_log(LOG_DEBUG, "call custom handler for resource '%*.*s'\n", + (int)resource->uri_path->length, (int)resource->uri_path->length, + resource->uri_path->s); + h(resource, session, pdu, query, response); + + /* Check if lg_xmit generated and update PDU code if so */ + coap_check_code_lg_xmit(session, response, resource, query, pdu->code); + +skip_handler: + if (send_early_empty_ack && + response->type == COAP_MESSAGE_ACK) { + /* Response is now separate - convert to CON as needed */ + response->type = COAP_MESSAGE_CON; + /* Check for empty ACK - need to drop as already sent */ + if (response->code == 0) { + goto drop_it_no_debug; + } + } + respond = no_response(pdu, response, session, resource); + if (respond != RESPONSE_DROP) { + coap_mid_t mid = pdu->mid; + if (COAP_RESPONSE_CLASS(response->code) != 2) { + if (observe) { + coap_remove_option(response, COAP_OPTION_OBSERVE); + } + } + if (COAP_RESPONSE_CLASS(response->code) > 2) { + if (observe) + coap_delete_observer(resource, session, &token); + if (added_block) + coap_remove_option(response, COAP_OPTION_BLOCK1); + } + + /* If original request contained a token, and the registered + * application handler made no changes to the response, then + * this is an empty ACK with a token, which is a malformed + * PDU */ + if ((response->type == COAP_MESSAGE_ACK) + && (response->code == 0)) { + /* Remove token from otherwise-empty acknowledgment PDU */ + response->token_length = 0; + response->used_size = 0; + } + + if (!coap_is_mcast(&session->addr_info.local) || + (context->mcast_per_resource && + resource && + (resource->flags & COAP_RESOURCE_FLAGS_LIB_DIS_MCAST_DELAYS))) { + if (coap_send_internal(session, response) == COAP_INVALID_MID) { + coap_log(LOG_DEBUG, "cannot send response for mid=0x%x\n", mid); + } + } else { + /* Need to delay mcast response */ + coap_queue_t *node = coap_new_node(); + uint8_t r; + coap_tick_t delay; + + if (!node) { + coap_log(LOG_DEBUG, "mcast delay: insufficient memory\n"); + goto clean_up; + } + if (!coap_pdu_encode_header(response, session->proto)) { + coap_delete_node(node); + goto clean_up; + } + + node->id = response->mid; + node->pdu = response; + node->is_mcast = 1; + coap_prng(&r, sizeof(r)); + delay = (COAP_DEFAULT_LEISURE_TICKS(session) * r) / 256; + coap_log(LOG_DEBUG, + " %s: mid=0x%x: mcast response delayed for %u.%03u secs\n", + coap_session_str(session), + response->mid, + (unsigned int)(delay / COAP_TICKS_PER_SECOND), + (unsigned int)((delay % COAP_TICKS_PER_SECOND) * + 1000 / COAP_TICKS_PER_SECOND)); + node->timeout = (unsigned int)delay; + /* Use this to delay transmission */ + coap_wait_ack(session->context, session, node); + } + } else { + coap_log(LOG_DEBUG, " %s: mid=0x%x: response dropped\n", + coap_session_str(session), + response->mid); + coap_show_pdu(LOG_DEBUG, response); +drop_it_no_debug: + coap_delete_pdu(response); + } +clean_up: + if (query) + coap_delete_string(query); + } else { + coap_log(LOG_WARNING, "cannot generate response\r\n"); + coap_delete_pdu(response); + } + } else { + resp = 405; + goto fail_response; + } + + coap_delete_string(uri_path); + return; + +fail_response: + response = + coap_new_error_response(pdu, COAP_RESPONSE_CODE(resp), + &opt_filter); + if (response) + goto skip_handler; + coap_delete_string(uri_path); +} +#endif /* COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +static void +handle_response(coap_context_t *context, coap_session_t *session, + coap_pdu_t *sent, coap_pdu_t *rcvd) { + /* In a lossy context, the ACK of a separate response may have + * been lost, so we need to stop retransmitting requests with the + * same token. + */ + if (rcvd->type != COAP_MESSAGE_ACK) + coap_cancel_all_messages(context, session, rcvd->token, rcvd->token_length); + + /* Check for message duplication */ + if (COAP_PROTO_NOT_RELIABLE(session->proto)) { + if (rcvd->type == COAP_MESSAGE_CON) { + if (rcvd->mid == session->last_con_mid) { + /* Duplicate response */ + return; + } + session->last_con_mid = rcvd->mid; + } else if (rcvd->type == COAP_MESSAGE_ACK) { + if (rcvd->mid == session->last_ack_mid) { + /* Duplicate response */ + return; + } + session->last_ack_mid = rcvd->mid; + } + } + + if (session->block_mode & COAP_BLOCK_USE_LIBCOAP) { + /* See if need to send next block to server */ + if (coap_handle_response_send_block(session, sent, rcvd)) { + /* Next block transmitted, no need to inform app */ + coap_send_ack(session, rcvd); + return; + } + + /* Need to see if needing to request next block */ + if (coap_handle_response_get_block(context, session, sent, rcvd, + COAP_RECURSE_OK)) { + /* Next block requested, no need to inform app */ + coap_send_ack(session, rcvd); + return; + } + } + + /* Call application-specific response handler when available. */ + if (context->response_handler) { + if (context->response_handler(session, sent, rcvd, + rcvd->mid) == COAP_RESPONSE_FAIL) + coap_send_rst(session, rcvd); + else + coap_send_ack(session, rcvd); + } + else { + coap_send_ack(session, rcvd); + } +} +#endif /* COAP_CLIENT_SUPPORT */ + +#if !COAP_DISABLE_TCP +static void +handle_signaling(coap_context_t *context, coap_session_t *session, + coap_pdu_t *pdu) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + int set_mtu = 0; + + coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + + if (pdu->code == COAP_SIGNALING_CODE_CSM) { + while ((option = coap_option_next(&opt_iter))) { + if (opt_iter.number == COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE) { + coap_session_set_mtu(session, coap_decode_var_bytes(coap_opt_value(option), + coap_opt_length(option))); + set_mtu = 1; + } else if (opt_iter.number == COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER) { + session->csm_block_supported = 1; + } + } + if (set_mtu) { + if (session->mtu > COAP_BERT_BASE && session->csm_block_supported) + session->csm_bert_rem_support = 1; + else + session->csm_bert_rem_support = 0; + } + if (session->state == COAP_SESSION_STATE_CSM) + coap_session_connected(session); + } else if (pdu->code == COAP_SIGNALING_CODE_PING) { + coap_pdu_t *pong = coap_pdu_init(COAP_MESSAGE_CON, COAP_SIGNALING_CODE_PONG, 0, 1); + if (context->ping_handler) { + context->ping_handler(session, pdu, pdu->mid); + } + if (pong) { + coap_add_option_internal(pong, COAP_SIGNALING_OPTION_CUSTODY, 0, NULL); + coap_send_internal(session, pong); + } + } else if (pdu->code == COAP_SIGNALING_CODE_PONG) { + session->last_pong = session->last_rx_tx; + if (context->pong_handler) { + context->pong_handler(session, pdu, pdu->mid); + } + } else if (pdu->code == COAP_SIGNALING_CODE_RELEASE + || pdu->code == COAP_SIGNALING_CODE_ABORT) { + coap_session_disconnected(session, COAP_NACK_RST); + } +} +#endif /* !COAP_DISABLE_TCP */ + +void +coap_dispatch(coap_context_t *context, coap_session_t *session, + coap_pdu_t *pdu) { + coap_queue_t *sent = NULL; + coap_pdu_t *response; + coap_opt_filter_t opt_filter; + int is_ping_rst; + + if (LOG_DEBUG <= coap_get_log_level()) { + /* FIXME: get debug to work again ** + unsigned char addr[INET6_ADDRSTRLEN+8], localaddr[INET6_ADDRSTRLEN+8]; + if (coap_print_addr(remote, addr, INET6_ADDRSTRLEN+8) && + coap_print_addr(&packet->dst, localaddr, INET6_ADDRSTRLEN+8) ) + coap_log(LOG_DEBUG, "** received %d bytes from %s on interface %s:\n", + (int)msg_len, addr, localaddr); + + */ + coap_show_pdu(LOG_DEBUG, pdu); + } + + memset(&opt_filter, 0, sizeof(coap_opt_filter_t)); + + switch (pdu->type) { + case COAP_MESSAGE_ACK: + /* find message id in sendqueue to stop retransmission */ + coap_remove_from_queue(&context->sendqueue, session, pdu->mid, &sent); + + if (sent && session->con_active) { + session->con_active--; + if (session->state == COAP_SESSION_STATE_ESTABLISHED) + /* Flush out any entries on session->delayqueue */ + coap_session_connected(session); + } + if (coap_option_check_critical(session, pdu, &opt_filter) == 0) + goto cleanup; + +#if COAP_SERVER_SUPPORT + /* if sent code was >= 64 the message might have been a + * notification. Then, we must flag the observer to be alive + * by setting obs->fail_cnt = 0. */ + if (sent && COAP_RESPONSE_CLASS(sent->pdu->code) == 2) { + const coap_binary_t token = + { sent->pdu->token_length, sent->pdu->token }; + coap_touch_observer(context, sent->session, &token); + } +#endif /* COAP_SERVER_SUPPORT */ + + if (pdu->code == 0) { + /* an empty ACK needs no further handling */ + goto cleanup; + } + + break; + + case COAP_MESSAGE_RST: + /* We have sent something the receiver disliked, so we remove + * not only the message id but also the subscriptions we might + * have. */ + is_ping_rst = 0; + if (pdu->mid == session->last_ping_mid && + context->ping_timeout && session->last_ping > 0) + is_ping_rst = 1; + + if (!is_ping_rst) + coap_log(LOG_ALERT, "got RST for mid=0x%x\n", pdu->mid); + + if (session->con_active) { + session->con_active--; + if (session->state == COAP_SESSION_STATE_ESTABLISHED) + /* Flush out any entries on session->delayqueue */ + coap_session_connected(session); + } + + /* find message id in sendqueue to stop retransmission */ + coap_remove_from_queue(&context->sendqueue, session, pdu->mid, &sent); + + if (sent) { + coap_cancel(context, sent); + + if (!is_ping_rst) { + if(sent->pdu->type==COAP_MESSAGE_CON && context->nack_handler) + context->nack_handler(sent->session, sent->pdu, + COAP_NACK_RST, sent->id); + } + else { + if (context->pong_handler) { + context->pong_handler(session, pdu, pdu->mid); + } + session->last_pong = session->last_rx_tx; + session->last_ping_mid = COAP_INVALID_MID; + } + } +#if COAP_SERVER_SUPPORT + else { + /* Need to check is there is a subscription active and delete it */ + RESOURCES_ITER(context->resources, r) { + coap_subscription_t *obs, *tmp; + LL_FOREACH_SAFE(r->subscribers, obs, tmp) { + if (obs->pdu->mid == pdu->mid && obs->session == session) { + coap_binary_t token = { 0, NULL }; + COAP_SET_STR(&token, obs->pdu->token_length, obs->pdu->token); + coap_delete_observer(r, session, &token); + goto cleanup; + } + } + } + } +#endif /* COAP_SERVER_SUPPORT */ + goto cleanup; + + case COAP_MESSAGE_NON: + /* find transaction in sendqueue in case large response */ + coap_remove_from_queue(&context->sendqueue, session, pdu->mid, &sent); + /* check for unknown critical options */ + if (coap_option_check_critical(session, pdu, &opt_filter) == 0) { + coap_send_rst(session, pdu); + goto cleanup; + } + break; + + case COAP_MESSAGE_CON: /* check for unknown critical options */ + if (coap_option_check_critical(session, pdu, &opt_filter) == 0) { + + if (COAP_PDU_IS_REQUEST(pdu)) { + response = + coap_new_error_response(pdu, COAP_RESPONSE_CODE(402), &opt_filter); + + if (!response) { + coap_log(LOG_WARNING, + "coap_dispatch: cannot create error response\n"); + } else { + if (coap_send_internal(session, response) == COAP_INVALID_MID) + coap_log(LOG_WARNING, "coap_dispatch: error sending response\n"); + } + } + else { + coap_send_rst(session, pdu); + } + + goto cleanup; + } + default: break; + } + + /* Pass message to upper layer if a specific handler was + * registered for a request that should be handled locally. */ +#if !COAP_DISABLE_TCP + if (COAP_PDU_IS_SIGNALING(pdu)) + handle_signaling(context, session, pdu); + else +#endif /* !COAP_DISABLE_TCP */ +#if COAP_SERVER_SUPPORT + if (COAP_PDU_IS_REQUEST(pdu)) + handle_request(context, session, pdu); + else +#endif /* COAP_SERVER_SUPPORT */ +#if COAP_CLIENT_SUPPORT + if (COAP_PDU_IS_RESPONSE(pdu)) + handle_response(context, session, sent ? sent->pdu : NULL, pdu); + else +#endif /* COAP_CLIENT_SUPPORT */ + { + if (COAP_PDU_IS_EMPTY(pdu)) { + if (context->ping_handler) { + context->ping_handler(session, pdu, pdu->mid); + } + } + coap_log(LOG_DEBUG, "dropped message with invalid code (%d.%02d)\n", + COAP_RESPONSE_CLASS(pdu->code), + pdu->code & 0x1f); + + if (!coap_is_mcast(&session->addr_info.local)) { + if (COAP_PDU_IS_EMPTY(pdu)) { + if (session->proto != COAP_PROTO_TCP && session->proto != COAP_PROTO_TLS) { + coap_tick_t now; + coap_ticks(&now); + if (session->last_tx_rst + COAP_TICKS_PER_SECOND/4 < now) { + coap_send_message_type(session, pdu, COAP_MESSAGE_RST); + session->last_tx_rst = now; + } + } + } + else { + coap_send_message_type(session, pdu, COAP_MESSAGE_RST); + } + } + } + +cleanup: + coap_delete_node(sent); +} + +int +coap_handle_event(coap_context_t *context, coap_event_t event, coap_session_t *session) { + coap_log(LOG_DEBUG, "***EVENT: 0x%04x\n", event); + + if (context->handle_event) { + return context->handle_event(session, event); + } else { + return 0; + } +} + +int +coap_can_exit(coap_context_t *context) { + coap_session_t *s, *rtmp; + if (!context) + return 1; + if (context->sendqueue) + return 0; +#if COAP_SERVER_SUPPORT + coap_endpoint_t *ep; + + LL_FOREACH(context->endpoint, ep) { + SESSIONS_ITER(ep->sessions, s, rtmp) { + if (s->delayqueue) + return 0; + if (s->lg_xmit) + return 0; + } + } +#endif /* COAP_SERVER_SUPPORT */ +#if COAP_CLIENT_SUPPORT + SESSIONS_ITER(context->sessions, s, rtmp) { + if (s->delayqueue) + return 0; + if (s->lg_xmit) + return 0; + } +#endif /* COAP_CLIENT_SUPPORT */ + return 1; +} +#ifndef WITHOUT_ASYNC +coap_tick_t +coap_check_async(coap_context_t *context, coap_tick_t now) { + coap_tick_t next_due = 0; + coap_async_t *async, *tmp; + + LL_FOREACH_SAFE(context->async_state, async, tmp) { + if (async->delay != 0 && async->delay <= now) { + /* Send off the request to the application */ + handle_request(context, async->session, async->pdu); + + /* Remove this async entry as it has now fired */ + coap_free_async(async->session, async); + } + else { + if (next_due == 0 || next_due > async->delay - now) + next_due = async->delay - now; + } + } + return next_due; +} +#endif /* WITHOUT_ASYNC */ + +static int coap_started = 0; + +void coap_startup(void) { + coap_tick_t now; + uint64_t us; + + if (coap_started) + return; + coap_started = 1; +#if defined(HAVE_WINSOCK2_H) + WORD wVersionRequested = MAKEWORD(2, 2); + WSADATA wsaData; + WSAStartup(wVersionRequested, &wsaData); +#endif + coap_clock_init(); + coap_ticks(&now); + us = coap_ticks_to_rt_us(now); + /* Be accurate to the nearest (approx) us */ + coap_prng_init((unsigned int)us); + coap_memory_init(); + coap_dtls_startup(); +#if COAP_SERVER_SUPPORT + static coap_str_const_t well_known = { sizeof(".well-known/core")-1, + (const uint8_t *)".well-known/core" }; + memset(&resource_uri_wellknown, 0, sizeof(resource_uri_wellknown)); + resource_uri_wellknown.handler[COAP_REQUEST_GET-1] = hnd_get_wellknown; + resource_uri_wellknown.flags = COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT; + resource_uri_wellknown.uri_path = &well_known; +#endif /* COAP_SERVER_SUPPORT */ +} + +void coap_cleanup(void) { +#if defined(HAVE_WINSOCK2_H) + WSACleanup(); +#endif + coap_dtls_shutdown(); +} + +void +coap_register_response_handler(coap_context_t *context, + coap_response_handler_t handler) { +#if COAP_CLIENT_SUPPORT + context->response_handler = handler; +#else /* ! COAP_CLIENT_SUPPORT */ + (void)context; + (void)handler; +#endif /* COAP_CLIENT_SUPPORT */ +} + +void +coap_register_nack_handler(coap_context_t *context, + coap_nack_handler_t handler) { + context->nack_handler = handler; +} + +void +coap_register_ping_handler(coap_context_t *context, + coap_ping_handler_t handler) { + context->ping_handler = handler; +} + +void +coap_register_pong_handler(coap_context_t *context, + coap_pong_handler_t handler) { + context->pong_handler = handler; +} + +void +coap_register_option(coap_context_t *ctx, uint16_t type) { + coap_option_filter_set(&ctx->known_options, type); +} + +#if ! defined WITH_CONTIKI && ! defined WITH_LWIP && ! defined RIOT_VERSION +#if COAP_SERVER_SUPPORT +int +coap_join_mcast_group_intf(coap_context_t *ctx, const char *group_name, + const char *ifname) { + struct ip_mreq mreq4; + struct ipv6_mreq mreq6; + struct addrinfo *resmulti = NULL, hints, *ainfo; + int result = -1; + coap_endpoint_t *endpoint; + int mgroup_setup = 0; + + /* Need to have at least one endpoint! */ + assert(ctx->endpoint); + if (!ctx->endpoint) + return -1; + + /* Default is let the kernel choose */ + mreq6.ipv6mr_interface = 0; + mreq4.imr_interface.s_addr = INADDR_ANY; + + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + + /* resolve the multicast group address */ + result = getaddrinfo(group_name, NULL, &hints, &resmulti); + + if (result != 0) { + coap_log(LOG_ERR, + "coap_join_mcast_group_intf: %s: " + "Cannot resolve multicast address: %s\n", + group_name, gai_strerror(result)); + goto finish; + } + +/* Need to do a windows equivalent at some point */ +#ifndef _WIN32 + if (ifname) { + /* interface specified - check if we have correct IPv4/IPv6 information */ + int done_ip4 = 0; + int done_ip6 = 0; +#if defined(ESPIDF_VERSION) + struct netif *netif; +#else /* !ESPIDF_VERSION */ + int ip4fd; + struct ifreq ifr; +#endif /* !ESPIDF_VERSION */ + + /* See which mcast address family types are being asked for */ + for (ainfo = resmulti; ainfo != NULL && !(done_ip4 == 1 && done_ip6 == 1); + ainfo = ainfo->ai_next) { + switch (ainfo->ai_family) { + case AF_INET6: + if (done_ip6) + break; + done_ip6 = 1; +#if defined(ESPIDF_VERSION) + netif = netif_find(ifname); + if (netif) + mreq6.ipv6mr_interface = netif_get_index(netif); + else + coap_log(LOG_ERR, + "coap_join_mcast_group_intf: %s: " + "Cannot get IPv4 address: %s\n", + ifname, coap_socket_strerror()); +#else /* !ESPIDF_VERSION */ + memset (&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); + ifr.ifr_name[IFNAMSIZ - 1] = '\000'; + +#ifdef HAVE_IF_NAMETOINDEX + mreq6.ipv6mr_interface = if_nametoindex(ifr.ifr_name); + if (mreq6.ipv6mr_interface == 0) { + coap_log(LOG_WARNING, "coap_join_mcast_group_intf: " + "cannot get interface index for '%s'\n", + ifname); + } +#else /* !HAVE_IF_NAMETOINDEX */ + result = ioctl(ctx->endpoint->sock.fd, SIOCGIFINDEX, &ifr); + if (result != 0) { + coap_log(LOG_WARNING, "coap_join_mcast_group_intf: " + "cannot get interface index for '%s': %s\n", + ifname, coap_socket_strerror()); + } + else { + /* Capture the IPv6 if_index for later */ + mreq6.ipv6mr_interface = ifr.ifr_ifindex; + } +#endif /* !HAVE_IF_NAMETOINDEX */ +#endif /* !ESPIDF_VERSION */ + break; + case AF_INET: + if (done_ip4) + break; + done_ip4 = 1; +#if defined(ESPIDF_VERSION) + netif = netif_find(ifname); + if (netif) + mreq4.imr_interface.s_addr = netif_ip4_addr(netif)->addr; + else + coap_log(LOG_ERR, + "coap_join_mcast_group_intf: %s: " + "Cannot get IPv4 address: %s\n", + ifname, coap_socket_strerror()); +#else /* !ESPIDF_VERSION */ + /* + * Need an AF_INET socket to do this unfortunately to stop + * "Invalid argument" error if AF_INET6 socket is used for SIOCGIFADDR + */ + ip4fd = socket(AF_INET, SOCK_DGRAM, 0); + if (ip4fd == -1) { + coap_log(LOG_ERR, + "coap_join_mcast_group_intf: %s: socket: %s\n", + ifname, coap_socket_strerror()); + continue; + } + memset (&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); + ifr.ifr_name[IFNAMSIZ - 1] = '\000'; + result = ioctl(ip4fd, SIOCGIFADDR, &ifr); + if (result != 0) { + coap_log(LOG_ERR, + "coap_join_mcast_group_intf: %s: " + "Cannot get IPv4 address: %s\n", + ifname, coap_socket_strerror()); + } + else { + /* Capture the IPv4 address for later */ + mreq4.imr_interface = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr; + } + close(ip4fd); +#endif /* !ESPIDF_VERSION */ + break; + default: + break; + } + } + } +#endif /* ! _WIN32 */ + + /* Add in mcast address(es) to appropriate interface */ + for (ainfo = resmulti; ainfo != NULL; ainfo = ainfo->ai_next) { + LL_FOREACH(ctx->endpoint, endpoint) { + /* Only UDP currently supported */ + if (endpoint->proto == COAP_PROTO_UDP) { + coap_address_t gaddr; + + coap_address_init(&gaddr); + if (ainfo->ai_family == AF_INET6) { + if (!ifname) { + if(endpoint->bind_addr.addr.sa.sa_family == AF_INET6) { + /* + * Do it on the ifindex that the server is listening on + * (sin6_scope_id could still be 0) + */ + mreq6.ipv6mr_interface = + endpoint->bind_addr.addr.sin6.sin6_scope_id; + } + else { + mreq6.ipv6mr_interface = 0; + } + } + gaddr.addr.sin6.sin6_family = AF_INET6; + gaddr.addr.sin6.sin6_port = endpoint->bind_addr.addr.sin6.sin6_port; + gaddr.addr.sin6.sin6_addr = mreq6.ipv6mr_multiaddr = + ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_addr; + result = setsockopt(endpoint->sock.fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, + (char *)&mreq6, sizeof(mreq6)); + } + else if (ainfo->ai_family == AF_INET) { + if (!ifname) { + if(endpoint->bind_addr.addr.sa.sa_family == AF_INET) { + /* + * Do it on the interface that the server is listening on + * (sin_addr could still be INADDR_ANY) + */ + mreq4.imr_interface = endpoint->bind_addr.addr.sin.sin_addr; + } + else { + mreq4.imr_interface.s_addr = INADDR_ANY; + } + } + gaddr.addr.sin.sin_family = AF_INET; + gaddr.addr.sin.sin_port = endpoint->bind_addr.addr.sin.sin_port; + gaddr.addr.sin.sin_addr.s_addr = mreq4.imr_multiaddr.s_addr = + ((struct sockaddr_in *)ainfo->ai_addr)->sin_addr.s_addr; + result = setsockopt(endpoint->sock.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (char *)&mreq4, sizeof(mreq4)); + } + else { + continue; + } + + if (result == COAP_SOCKET_ERROR) { + coap_log(LOG_ERR, + "coap_join_mcast_group_intf: %s: setsockopt: %s\n", + group_name, coap_socket_strerror()); + } + else { + char addr_str[INET6_ADDRSTRLEN + 8 + 1]; + + addr_str[sizeof(addr_str)-1] = '\000'; + if (coap_print_addr(&gaddr, (uint8_t*)addr_str, + sizeof(addr_str) - 1)) { + if (ifname) + coap_log(LOG_DEBUG, "added mcast group %s i/f %s\n", addr_str, + ifname); + else + coap_log(LOG_DEBUG, "added mcast group %s\n", addr_str); + } + mgroup_setup = 1; + } + } + } + } + if (!mgroup_setup) { + result = -1; + } + + finish: + freeaddrinfo(resmulti); + + return result; +} + +void +coap_mcast_per_resource(coap_context_t *context) { + context->mcast_per_resource = 1; +} + +#endif /* ! COAP_SERVER_SUPPORT */ + +#if COAP_CLIENT_SUPPORT +int +coap_mcast_set_hops(coap_session_t *session, size_t hops) { + if (session && coap_is_mcast(&session->addr_info.remote)) { + switch (session->addr_info.remote.addr.sa.sa_family) { + case AF_INET: + if (setsockopt(session->sock.fd, IPPROTO_IP, IP_MULTICAST_TTL, + (const char *)&hops, sizeof(hops)) < 0) { + coap_log(LOG_INFO, "coap_mcast_set_hops: %zu: setsockopt: %s\n", + hops, coap_socket_strerror()); + return 0; + } + return 1; + case AF_INET6: + if (setsockopt(session->sock.fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, + (const char *)&hops, sizeof(hops)) < 0) { + coap_log(LOG_INFO, "coap_mcast_set_hops: %zu: setsockopt: %s\n", + hops, coap_socket_strerror()); + return 0; + } + return 1; + default: + break; + } + } + return 0; +} +#endif /* COAP_CLIENT_SUPPORT */ + +#else /* defined WITH_CONTIKI || defined WITH_LWIP */ +int +coap_join_mcast_group_intf(coap_context_t *ctx COAP_UNUSED, + const char *group_name COAP_UNUSED, + const char *ifname COAP_UNUSED) { + return -1; +} + +int +coap_mcast_set_hops(coap_session_t *session COAP_UNUSED, + size_t hops COAP_UNUSED) { + return 0; +} + +void +coap_mcast_per_resource(coap_context_t *context COAP_UNUSED) { +} +#endif /* defined WITH_CONTIKI || defined WITH_LWIP */ + +#ifdef WITH_CONTIKI + +/*---------------------------------------------------------------------------*/ +/* CoAP message retransmission */ +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_retransmit_process, ev, data) { + coap_tick_t now; + coap_queue_t *nextpdu; + + PROCESS_BEGIN(); + + coap_log(LOG_DEBUG, "Started retransmit process\n"); + + while (1) { + PROCESS_YIELD(); + if (ev == PROCESS_EVENT_TIMER) { + if (etimer_expired(&the_coap_context.retransmit_timer)) { + + nextpdu = coap_peek_next(&the_coap_context); + + coap_ticks(&now); + while (nextpdu && nextpdu->t <= now) { + coap_retransmit(&the_coap_context, coap_pop_next(&the_coap_context)); + nextpdu = coap_peek_next(&the_coap_context); + } + + /* need to set timer to some value even if no nextpdu is available */ + etimer_set(&the_coap_context.retransmit_timer, + nextpdu ? nextpdu->t - now : 0xFFFF); + } + if (etimer_expired(&the_coap_context.notify_timer)) { + coap_check_notify(&the_coap_context); + etimer_reset(&the_coap_context.notify_timer); + } + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ + +#endif /* WITH_CONTIKI */ + +#ifdef WITH_LWIP +/* FIXME: retransmits that are not required any more due to incoming packages + * do *not* get cleared at the moment, the wakeup when the transmission is due + * is silently accepted. this is mainly due to the fact that the required + * checks are similar in two places in the code (when receiving ACK and RST) + * and that they cause more than one patch chunk, as it must be first checked + * whether the sendqueue item to be dropped is the next one pending, and later + * the restart function has to be called. nothing insurmountable, but it can + * also be implemented when things have stabilized, and the performance + * penality is minimal + * + * also, this completely ignores COAP_RESOURCE_CHECK_TIME. + * */ + +static void coap_retransmittimer_execute(void *arg) { + coap_context_t *ctx = (coap_context_t*)arg; + coap_tick_t now; + coap_tick_t elapsed; + coap_queue_t *nextinqueue; + + ctx->timer_configured = 0; + + coap_ticks(&now); + + elapsed = now - ctx->sendqueue_basetime; /* that's positive for sure, and unless we haven't been called for a complete wrapping cycle, did not wrap */ + + nextinqueue = coap_peek_next(ctx); + while (nextinqueue != NULL) { + if (nextinqueue->t > elapsed) { + nextinqueue->t -= elapsed; + break; + } else { + elapsed -= nextinqueue->t; + coap_retransmit(ctx, coap_pop_next(ctx)); + nextinqueue = coap_peek_next(ctx); + } + } + + ctx->sendqueue_basetime = now; + + coap_retransmittimer_restart(ctx); +} + +static void coap_retransmittimer_restart(coap_context_t *ctx) { + coap_tick_t now, elapsed, delay; + + if (ctx->timer_configured) { + printf("clearing\n"); + sys_untimeout(coap_retransmittimer_execute, (void*)ctx); + ctx->timer_configured = 0; + } + if (ctx->sendqueue != NULL) { + coap_ticks(&now); + elapsed = now - ctx->sendqueue_basetime; + if (ctx->sendqueue->t >= elapsed) { + delay = ctx->sendqueue->t - elapsed; + } else { + /* a strange situation, but not completely impossible. + * + * this happens, for example, right after + * coap_retransmittimer_execute, when a retransmission + * was *just not yet* due, and the clock ticked before + * our coap_ticks was called. + * + * not trying to retransmit anything now, as it might + * cause uncontrollable recursion; let's just try again + * with the next main loop run. + * */ + delay = 0; + } + + printf("scheduling for %d ticks\n", delay); + sys_timeout(delay, coap_retransmittimer_execute, (void*)ctx); + ctx->timer_configured = 1; + } +} +#endif diff --git a/examples/espidf-coap-server/components/libcoap/src/pdu.c b/examples/espidf-coap-server/components/libcoap/src/pdu.c new file mode 100644 index 000000000..f730b5eb8 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/pdu.c @@ -0,0 +1,1301 @@ +/* pdu.c -- CoAP PDU handling + * + * Copyright (C) 2010--2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file pdu.c + * @brief CoAP PDU handling + */ + +#include "coap3/coap_internal.h" + +#if defined(HAVE_LIMITS_H) +#include +#endif + +#include +#include +#include +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_WINSOCK2_H +#include +#endif +#include + +#ifdef HAVE_INTTYPES_H +#include +#else /* ! HAVE_INTTYPES_H */ +#define PRIu32 "u" +#endif /* ! HAVE_INTTYPES_H */ + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif + +void +coap_pdu_clear(coap_pdu_t *pdu, size_t size) { + assert(pdu); + assert(pdu->token); + assert(pdu->max_hdr_size >= COAP_PDU_MAX_UDP_HEADER_SIZE); + if (pdu->alloc_size > size) + pdu->alloc_size = size; + pdu->type = 0; + pdu->code = 0; + pdu->hdr_size = 0; + pdu->token_length = 0; + pdu->crit_opt = 0; + pdu->mid = 0; + pdu->max_opt = 0; + pdu->max_size = size; + pdu->used_size = 0; + pdu->data = NULL; + pdu->body_data = NULL; + pdu->body_length = 0; + pdu->body_offset = 0; + pdu->body_total = 0; + pdu->lg_xmit = NULL; +} + +#ifdef WITH_LWIP +coap_pdu_t * +coap_pdu_from_pbuf( struct pbuf *pbuf ) +{ + coap_pdu_t *pdu; + + if (pbuf == NULL) return NULL; + + LWIP_ASSERT("Can only deal with contiguous PBUFs", pbuf->tot_len == pbuf->len); + LWIP_ASSERT("coap_io_do_io needs to receive an exclusive copy of the incoming pbuf", pbuf->ref == 1); + + pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t) ); + if (!pdu) { + pbuf_free(pbuf); + return NULL; + } + + pdu->max_hdr_size = COAP_PDU_MAX_UDP_HEADER_SIZE; + pdu->pbuf = pbuf; + pdu->token = (uint8_t *)pbuf->payload + pdu->max_hdr_size; + pdu->alloc_size = pbuf->tot_len - pdu->max_hdr_size; + coap_pdu_clear(pdu, pdu->alloc_size); + + return pdu; +} +#endif + +coap_pdu_t * +coap_pdu_init(coap_pdu_type_t type, coap_pdu_code_t code, coap_mid_t mid, + size_t size) { + coap_pdu_t *pdu; + + assert(type <= 0x3); + assert(code <= 0xff); + assert(mid >= 0 && mid <= 0xffff); + + pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t)); + if (!pdu) return NULL; + +#if defined(WITH_CONTIKI) || defined(WITH_LWIP) + assert(size <= COAP_MAX_MESSAGE_SIZE_TCP16 + 4); + if (size > COAP_MAX_MESSAGE_SIZE_TCP16 + 4) + return NULL; + pdu->max_hdr_size = COAP_PDU_MAX_UDP_HEADER_SIZE; +#else + pdu->max_hdr_size = COAP_PDU_MAX_TCP_HEADER_SIZE; +#endif + +#ifdef WITH_LWIP + pdu->pbuf = pbuf_alloc(PBUF_TRANSPORT, size + pdu->max_hdr_size, PBUF_RAM); + if (pdu->pbuf == NULL) { + coap_free_type(COAP_PDU, pdu); + return NULL; + } + pdu->token = (uint8_t *)pdu->pbuf->payload + pdu->max_hdr_size; +#else /* WITH_LWIP */ + uint8_t *buf; + pdu->alloc_size = min(size, 256); + buf = coap_malloc_type(COAP_PDU_BUF, pdu->alloc_size + pdu->max_hdr_size); + if (buf == NULL) { + coap_free_type(COAP_PDU, pdu); + return NULL; + } + pdu->token = buf + pdu->max_hdr_size; +#endif /* WITH_LWIP */ + coap_pdu_clear(pdu, size); + pdu->mid = mid; + pdu->type = type; + pdu->code = code; + return pdu; +} + +coap_pdu_t * +coap_new_pdu(coap_pdu_type_t type, coap_pdu_code_t code, + coap_session_t *session) { + coap_pdu_t *pdu = coap_pdu_init(type, code, coap_new_message_id(session), + coap_session_max_pdu_size(session)); + if (!pdu) + coap_log(LOG_CRIT, "coap_new_pdu: cannot allocate memory for new PDU\n"); + return pdu; +} + +void +coap_delete_pdu(coap_pdu_t *pdu) { + if (pdu != NULL) { +#ifdef WITH_LWIP + pbuf_free(pdu->pbuf); +#else + if (pdu->token != NULL) + coap_free_type(COAP_PDU_BUF, pdu->token - pdu->max_hdr_size); +#endif + coap_free_type(COAP_PDU, pdu); + } +} + +coap_pdu_t * +coap_pdu_duplicate(const coap_pdu_t *old_pdu, + coap_session_t *session, + size_t token_length, + const uint8_t *token, + coap_opt_filter_t *drop_options) { + coap_pdu_t *pdu = coap_pdu_init(old_pdu->type, + old_pdu->code, + coap_new_message_id(session), + coap_session_max_pdu_size(session)); + + if (pdu == NULL) + return NULL; + + coap_add_token(pdu, token_length, token); + pdu->lg_xmit = old_pdu->lg_xmit; + + if (drop_options == NULL) { + /* Drop COAP_PAYLOAD_START as well if data */ + size_t length = old_pdu->used_size - old_pdu->token_length - + (old_pdu->data ? + old_pdu->used_size - (old_pdu->data - old_pdu->token) +1 : 0); + if (!coap_pdu_resize(pdu, length + pdu->token_length)) + goto fail; + /* Copy the options but not any data across */ + memcpy(pdu->token + pdu->token_length, + old_pdu->token + old_pdu->token_length, length); + pdu->used_size += length; + pdu->max_opt = old_pdu->max_opt; + } + else { + /* Copy across all the options the slow way */ + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + + coap_option_iterator_init(old_pdu, &opt_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_iter))) { + if (drop_options && coap_option_filter_get(drop_options, opt_iter.number)) + continue; + if (!coap_add_option_internal(pdu, opt_iter.number, + coap_opt_length(option), + coap_opt_value(option))) + goto fail; + } + } + return pdu; + +fail: + coap_delete_pdu(pdu); + return NULL; +} + + +/* + * The new size does not include the coap header (max_hdr_size) + */ +int +coap_pdu_resize(coap_pdu_t *pdu, size_t new_size) { + if (new_size > pdu->alloc_size) { +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) + uint8_t *new_hdr; + size_t offset; +#endif + if (pdu->max_size && new_size > pdu->max_size) { + coap_log(LOG_WARNING, "coap_pdu_resize: pdu too big\n"); + return 0; + } +#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) + if (pdu->data != NULL) { + assert(pdu->data > pdu->token); + offset = pdu->data - pdu->token; + } else { + offset = 0; + } + new_hdr = (uint8_t*)realloc(pdu->token - pdu->max_hdr_size, + new_size + pdu->max_hdr_size); + if (new_hdr == NULL) { + coap_log(LOG_WARNING, "coap_pdu_resize: realloc failed\n"); + return 0; + } + pdu->token = new_hdr + pdu->max_hdr_size; + if (offset > 0) + pdu->data = pdu->token + offset; + else + pdu->data = NULL; +#endif + } + pdu->alloc_size = new_size; + return 1; +} + +int +coap_pdu_check_resize(coap_pdu_t *pdu, size_t size) { + if (size > pdu->alloc_size) { + size_t new_size = max(256, pdu->alloc_size * 2); + while (size > new_size) + new_size *= 2; + if (pdu->max_size && new_size > pdu->max_size) { + new_size = pdu->max_size; + if (new_size < size) + return 0; + } + if (!coap_pdu_resize(pdu, new_size)) + return 0; + } + return 1; +} + +int +coap_add_token(coap_pdu_t *pdu, size_t len, const uint8_t *data) { + /* must allow for pdu == NULL as callers may rely on this */ + if (!pdu || len > 8) + return 0; + + if (pdu->used_size) { + coap_log(LOG_WARNING, + "coap_add_token: The token must defined first. Token ignored\n"); + return 0; + } + if (!coap_pdu_check_resize(pdu, len)) + return 0; + pdu->token_length = (uint8_t)len; + if (len) + memcpy(pdu->token, data, len); + pdu->max_opt = 0; + pdu->used_size = len; + pdu->data = NULL; + + return 1; +} + +/* It is assumed that coap_encode_var_safe8() has been called to reduce data */ +int +coap_update_token(coap_pdu_t *pdu, size_t len, const uint8_t *data) { + /* must allow for pdu == NULL as callers may rely on this */ + if (!pdu || len > 8) + return 0; + + if (pdu->used_size == 0) { + return coap_add_token(pdu, len, data); + } + if (len == pdu->token_length) { + /* Easy case - just data has changed */ + } + else if (len > pdu->token_length) { + if (!coap_pdu_check_resize(pdu, pdu->used_size + len - pdu->token_length)) { + coap_log(LOG_WARNING, "Failed to update token\n"); + return 0; + } + memmove(&pdu->token[len - pdu->token_length], pdu->token, pdu->used_size); + pdu->used_size += len - pdu->token_length; + } + else { + pdu->used_size -= pdu->token_length - len; + memmove(pdu->token, &pdu->token[pdu->token_length - len], pdu->used_size); + } + if (pdu->data) { + pdu->data += len - pdu->token_length; + } + pdu->token_length = (uint8_t)len; + if (len) + memcpy(pdu->token, data, len); + + return 1; +} + +int +coap_remove_option(coap_pdu_t *pdu, coap_option_num_t number) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_opt_t *next_option = NULL; + size_t opt_delta; + coap_option_t decode_this; + coap_option_t decode_next; + + /* Need to locate where in current options to remove this one */ + coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_iter))) { + if (opt_iter.number == number) { + /* Found option to delete */ + break; + } + } + if (!option) + return 0; + + if (!coap_opt_parse(option, pdu->used_size - (option - pdu->token), + &decode_this)) + return 0; + + next_option = coap_option_next(&opt_iter); + if (next_option) { + if (!coap_opt_parse(next_option, + pdu->used_size - (next_option - pdu->token), + &decode_next)) + return 0; + opt_delta = decode_this.delta + decode_next.delta; + if (opt_delta <= 12) { + /* can simply update the delta of next option */ + next_option[0] = (next_option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4); + } + else if (opt_delta <= 269 && decode_next.delta <= 12) { + /* next option delta size increase */ + next_option -= 1; + next_option[0] = (next_option[1] & 0x0f) + (13 << 4); + next_option[1] = (coap_opt_t)(opt_delta - 13); + } + else if (opt_delta <= 269) { + /* can simply update the delta of next option */ + next_option[1] = (coap_opt_t)(opt_delta - 13); + } + else if (decode_next.delta <= 12) { + /* next option delta size increase */ + if (next_option - option < 2) { + /* Need to shuffle everything up by 1 before decrement */ + if (!coap_pdu_check_resize(pdu, pdu->used_size + 1)) + return 0; + /* Possible a re-size took place with a realloc() */ + /* Need to rediscover this and next options */ + coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_iter))) { + if (opt_iter.number == number) { + /* Found option to delete */ + break; + } + } + next_option = coap_option_next(&opt_iter); + assert(option != NULL); + assert(next_option != NULL); + memmove(&next_option[1], next_option, + pdu->used_size - (next_option - pdu->token)); + pdu->used_size++; + if (pdu->data) + pdu->data++; + next_option++; + } + next_option -= 2; + next_option[0] = (next_option[2] & 0x0f) + (14 << 4); + next_option[1] = (coap_opt_t)((opt_delta - 269) >> 8); + next_option[2] = (opt_delta - 269) & 0xff; + } + else if (decode_next.delta <= 269) { + /* next option delta size increase */ + next_option -= 1; + next_option[0] = (next_option[1] & 0x0f) + (14 << 4); + next_option[1] = (coap_opt_t)((opt_delta - 269) >> 8); + next_option[2] = (opt_delta - 269) & 0xff; + } + else { + next_option[1] = (coap_opt_t)((opt_delta - 269) >> 8); + next_option[2] = (opt_delta - 269) & 0xff; + } + } + else { + next_option = option + coap_opt_encode_size(decode_this.delta, + coap_opt_length(option)); + pdu->max_opt -= decode_this.delta; + } + if (pdu->used_size - (next_option - pdu->token)) + memmove(option, next_option, pdu->used_size - (next_option - pdu->token)); + pdu->used_size -= next_option - option; + if (pdu->data) + pdu->data -= next_option - option; + return 1; +} + +static int +check_repeatable(coap_option_num_t number) { + /* Validate that the option is repeatable */ + switch (number) { + /* Ignore list of genuine repeatable */ + case COAP_OPTION_IF_MATCH: + case COAP_OPTION_ETAG: + case COAP_OPTION_LOCATION_PATH: + case COAP_OPTION_URI_PATH: + case COAP_OPTION_URI_QUERY: + case COAP_OPTION_LOCATION_QUERY: + case COAP_OPTION_RTAG: + break; + /* Protest at the known non-repeatable options and ignore them */ + case COAP_OPTION_URI_HOST: + case COAP_OPTION_IF_NONE_MATCH: + case COAP_OPTION_OBSERVE: + case COAP_OPTION_URI_PORT: + case COAP_OPTION_OSCORE: + case COAP_OPTION_CONTENT_FORMAT: + case COAP_OPTION_MAXAGE: + case COAP_OPTION_HOP_LIMIT: + case COAP_OPTION_ACCEPT: + case COAP_OPTION_BLOCK2: + case COAP_OPTION_BLOCK1: + case COAP_OPTION_SIZE2: + case COAP_OPTION_PROXY_URI: + case COAP_OPTION_PROXY_SCHEME: + case COAP_OPTION_SIZE1: + case COAP_OPTION_ECHO: + case COAP_OPTION_NORESPONSE: + coap_log(LOG_INFO, + "Option number %d is not defined as repeatable - dropped\n", + number); + return 0; + default: + coap_log(LOG_INFO, "Option number %d is not defined as repeatable\n", + number); + /* Accepting it after warning as there may be user defineable options */ + break; + } + return 1; +} + +size_t +coap_insert_option(coap_pdu_t *pdu, coap_option_num_t number, size_t len, + const uint8_t *data) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + uint16_t prev_number = 0; + size_t shift; + size_t opt_delta; + coap_option_t decode; + size_t shrink = 0; + + if (number >= pdu->max_opt) + return coap_add_option_internal(pdu, number, len, data); + + /* Need to locate where in current options to insert this one */ + coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_iter))) { + if (opt_iter.number > number) { + /* Found where to insert */ + break; + } + prev_number = opt_iter.number; + } + assert(option != NULL); + /* size of option inc header to insert */ + shift = coap_opt_encode_size(number - prev_number, len); + + /* size of next option (header may shrink in size as delta changes */ + if (!coap_opt_parse(option, pdu->used_size - (option - pdu->token), &decode)) + return 0; + opt_delta = opt_iter.number - number; + if (opt_delta == 0) { + if (!check_repeatable(number)) + return 0; + } + + if (!coap_pdu_check_resize(pdu, + pdu->used_size + shift - shrink)) + return 0; + + /* Possible a re-size took place with a realloc() */ + /* Need to locate where in current options to insert this one */ + coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); + while ((option = coap_option_next(&opt_iter))) { + if (opt_iter.number > number) { + /* Found where to insert */ + break; + } + } + assert(option != NULL); + + if (decode.delta < 13) { + /* can simply patch in the new delta of next option */ + option[0] = (option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4); + } else if (decode.delta < 269 && opt_delta < 13) { + /* option header is going to shrink by one byte */ + option[1] = (option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4); + shrink = 1; + } else if (decode.delta < 269 && opt_delta < 269) { + /* can simply patch in the new delta of next option */ + option[1] = (coap_opt_t)(opt_delta - 13); + } else if (opt_delta < 13) { + /* option header is going to shrink by two bytes */ + option[2] = (option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4); + shrink = 2; + } else if (opt_delta < 269) { + /* option header is going to shrink by one bytes */ + option[1] = (option[0] & 0x0f) + 0xd0; + option[2] = (coap_opt_t)(opt_delta - 13); + shrink = 1; + } else { + /* can simply patch in the new delta of next option */ + option[1] = (coap_opt_t)((opt_delta - 269) >> 8); + option[2] = (opt_delta - 269) & 0xff; + } + + memmove(&option[shift], &option[shrink], + pdu->used_size - (option - pdu->token) - shrink); + if (!coap_opt_encode(option, pdu->alloc_size - pdu->used_size, + number - prev_number, data, len)) + return 0; + + pdu->used_size += shift - shrink; + if (pdu->data) + pdu->data += shift - shrink; + return shift; +} + +size_t +coap_update_option(coap_pdu_t *pdu, coap_option_num_t number, size_t len, + const uint8_t *data) { + coap_opt_iterator_t opt_iter; + coap_opt_t *option; + coap_option_t decode; + size_t new_length = 0; + size_t old_length = 0; + + option = coap_check_option(pdu, number, &opt_iter); + if (!option) + return coap_insert_option(pdu, number, len, data); + + old_length = coap_opt_parse(option, (size_t)-1, &decode); + if (old_length == 0) + return 0; + new_length = coap_opt_encode_size(decode.delta, len); + + if (new_length > old_length) { + if (!coap_pdu_check_resize(pdu, + pdu->used_size + new_length - old_length)) + return 0; + /* Possible a re-size took place with a realloc() */ + option = coap_check_option(pdu, number, &opt_iter); + } + + if (new_length != old_length) + memmove(&option[new_length], &option[old_length], + pdu->used_size - (option - pdu->token) - old_length); + + if (!coap_opt_encode(option, new_length, + decode.delta, data, len)) + return 0; + + pdu->used_size += new_length - old_length; + if (pdu->data) + pdu->data += new_length - old_length; + return 1; +} + +size_t +coap_add_option(coap_pdu_t *pdu, coap_option_num_t number, size_t len, + const uint8_t *data) { + if (pdu->data) { + coap_log(LOG_WARNING, "coap_add_optlist_pdu: PDU already contains data\n"); + return 0; + } + return coap_add_option_internal(pdu, number, len, data); +} + +size_t +coap_add_option_internal(coap_pdu_t *pdu, coap_option_num_t number, size_t len, + const uint8_t *data) { + size_t optsize; + coap_opt_t *opt; + + assert(pdu); + + if (number == pdu->max_opt) { + if (!check_repeatable(number)) + return 0; + } + + if (COAP_PDU_IS_REQUEST(pdu) && + (number == COAP_OPTION_PROXY_URI || + number == COAP_OPTION_PROXY_SCHEME)) { + /* + * Need to check whether there is a hop-limit option. If not, it needs + * to be inserted by default (RFC 8768). + */ + coap_opt_iterator_t opt_iter; + + if (coap_check_option(pdu, COAP_OPTION_HOP_LIMIT, &opt_iter) == NULL) { + size_t hop_limit = COAP_OPTION_HOP_LIMIT; + + coap_insert_option(pdu, COAP_OPTION_HOP_LIMIT, 1, (uint8_t *)&hop_limit); + } + } + + if (number < pdu->max_opt) { + coap_log(LOG_DEBUG, + "coap_add_option: options are not in correct order\n"); + return coap_insert_option(pdu, number, len, data); + } + + optsize = coap_opt_encode_size(number - pdu->max_opt, len); + if (!coap_pdu_check_resize(pdu, + pdu->used_size + optsize)) + return 0; + + if (pdu->data) { + /* include option delimiter */ + memmove (&pdu->data[optsize-1], &pdu->data[-1], + pdu->used_size - (pdu->data - pdu->token) + 1); + opt = pdu->data -1; + pdu->data += optsize; + } + else { + opt = pdu->token + pdu->used_size; + } + + /* encode option and check length */ + optsize = coap_opt_encode(opt, pdu->alloc_size - pdu->used_size, + number - pdu->max_opt, data, len); + + if (!optsize) { + coap_log(LOG_WARNING, "coap_add_option: cannot add option\n"); + /* error */ + return 0; + } else { + pdu->max_opt = number; + pdu->used_size += optsize; + } + + return optsize; +} + +int +coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data) { + if (len == 0) { + return 1; + } else { + uint8_t *payload = coap_add_data_after(pdu, len); + if (payload != NULL) + memcpy(payload, data, len); + return payload != NULL; + } +} + +uint8_t * +coap_add_data_after(coap_pdu_t *pdu, size_t len) { + assert(pdu); + if (pdu->data) { + coap_log(LOG_WARNING, "coap_add_data: PDU already contains data\n"); + return 0; + } + + if (len == 0) + return NULL; + + if (!coap_pdu_resize(pdu, pdu->used_size + len + 1)) + return 0; + pdu->token[pdu->used_size++] = COAP_PAYLOAD_START; + pdu->data = pdu->token + pdu->used_size; + pdu->used_size += len; + return pdu->data; +} + +int +coap_get_data(const coap_pdu_t *pdu, size_t *len, const uint8_t **data) { + size_t offset; + size_t total; + + return coap_get_data_large(pdu, len, data, &offset, &total); +} + +int +coap_get_data_large(const coap_pdu_t *pdu, size_t *len, const uint8_t **data, + size_t *offset, size_t *total) { + assert(pdu); + assert(len); + assert(data); + + *offset = pdu->body_offset; + *total = pdu->body_total; + if (pdu->body_data) { + *data = pdu->body_data; + *len = pdu->body_length; + return 1; + } + *data = pdu->data; + if(pdu->data == NULL) { + *len = 0; + *total = 0; + return 0; + } + + *len = pdu->used_size - (pdu->data - pdu->token); + if (*total == 0) + *total = *len; + + return 1; +} + +#ifndef SHORT_ERROR_RESPONSE +typedef struct { + unsigned char code; + const char *phrase; +} error_desc_t; + +/* if you change anything here, make sure, that the longest string does not + * exceed COAP_ERROR_PHRASE_LENGTH. */ +error_desc_t coap_error[] = { + { COAP_RESPONSE_CODE(201), "Created" }, + { COAP_RESPONSE_CODE(202), "Deleted" }, + { COAP_RESPONSE_CODE(203), "Valid" }, + { COAP_RESPONSE_CODE(204), "Changed" }, + { COAP_RESPONSE_CODE(205), "Content" }, + { COAP_RESPONSE_CODE(231), "Continue" }, + { COAP_RESPONSE_CODE(400), "Bad Request" }, + { COAP_RESPONSE_CODE(401), "Unauthorized" }, + { COAP_RESPONSE_CODE(402), "Bad Option" }, + { COAP_RESPONSE_CODE(403), "Forbidden" }, + { COAP_RESPONSE_CODE(404), "Not Found" }, + { COAP_RESPONSE_CODE(405), "Method Not Allowed" }, + { COAP_RESPONSE_CODE(406), "Not Acceptable" }, + { COAP_RESPONSE_CODE(408), "Request Entity Incomplete" }, + { COAP_RESPONSE_CODE(409), "Conflict" }, + { COAP_RESPONSE_CODE(412), "Precondition Failed" }, + { COAP_RESPONSE_CODE(413), "Request Entity Too Large" }, + { COAP_RESPONSE_CODE(415), "Unsupported Content-Format" }, + { COAP_RESPONSE_CODE(422), "Unprocessable" }, + { COAP_RESPONSE_CODE(429), "Too Many Requests" }, + { COAP_RESPONSE_CODE(500), "Internal Server Error" }, + { COAP_RESPONSE_CODE(501), "Not Implemented" }, + { COAP_RESPONSE_CODE(502), "Bad Gateway" }, + { COAP_RESPONSE_CODE(503), "Service Unavailable" }, + { COAP_RESPONSE_CODE(504), "Gateway Timeout" }, + { COAP_RESPONSE_CODE(505), "Proxying Not Supported" }, + { COAP_RESPONSE_CODE(508), "Hop Limit Reached" }, + { 0, NULL } /* end marker */ +}; + +const char * +coap_response_phrase(unsigned char code) { + int i; + for (i = 0; coap_error[i].code; ++i) { + if (coap_error[i].code == code) + return coap_error[i].phrase; + } + return NULL; +} +#endif + +/** + * Advances *optp to next option if still in PDU. This function + * returns the number of bytes opt has been advanced or @c 0 + * on error. + */ +static size_t +next_option_safe(coap_opt_t **optp, size_t *length, uint16_t *max_opt) { + coap_option_t option; + size_t optsize; + + assert(optp); assert(*optp); + assert(length); + + optsize = coap_opt_parse(*optp, *length, &option); + if (optsize) { + assert(optsize <= *length); + + /* signal an error if this option would exceed the + * allowed number space */ + if (*max_opt + option.delta > COAP_MAX_OPT) { + return 0; + } + *max_opt += option.delta; + *optp += optsize; + *length -= optsize; + } + + return optsize; +} + +size_t +coap_pdu_parse_header_size(coap_proto_t proto, + const uint8_t *data) { + assert(data); + size_t header_size = 0; + + if (proto == COAP_PROTO_TCP || proto==COAP_PROTO_TLS) { + uint8_t len = *data >> 4; + if (len < 13) + header_size = 2; + else if (len==13) + header_size = 3; + else if (len==14) + header_size = 4; + else + header_size = 6; + } else if (proto == COAP_PROTO_UDP || proto==COAP_PROTO_DTLS) { + header_size = 4; + } + + return header_size; +} + +size_t +coap_pdu_parse_size(coap_proto_t proto, + const uint8_t *data, + size_t length) { + assert(data); + assert(proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS); + assert(coap_pdu_parse_header_size(proto, data) <= length ); + + size_t size = 0; + + if ((proto == COAP_PROTO_TCP || proto==COAP_PROTO_TLS) && length >= 1) { + uint8_t len = *data >> 4; + if (len < 13) { + size = len; + } else if (length >= 2) { + if (len==13) { + size = (size_t)data[1] + COAP_MESSAGE_SIZE_OFFSET_TCP8; + } else if (length >= 3) { + if (len==14) { + size = ((size_t)data[1] << 8) + data[2] + COAP_MESSAGE_SIZE_OFFSET_TCP16; + } else if (length >= 5) { + size = ((size_t)data[1] << 24) + ((size_t)data[2] << 16) + + ((size_t)data[3] << 8) + data[4] + COAP_MESSAGE_SIZE_OFFSET_TCP32; + } + } + } + size += data[0] & 0x0f; + } + + return size; +} + +int +coap_pdu_parse_header(coap_pdu_t *pdu, coap_proto_t proto) { + uint8_t *hdr = pdu->token - pdu->hdr_size; + if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) { + assert(pdu->hdr_size == 4); + if ((hdr[0] >> 6) != COAP_DEFAULT_VERSION) { + coap_log(LOG_DEBUG, "coap_pdu_parse: UDP version not supported\n"); + return 0; + } + pdu->type = (hdr[0] >> 4) & 0x03; + pdu->token_length = hdr[0] & 0x0f; + pdu->code = hdr[1]; + pdu->mid = (uint16_t)hdr[2] << 8 | hdr[3]; + } else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) { + assert(pdu->hdr_size >= 2 && pdu->hdr_size <= 6); + pdu->type = COAP_MESSAGE_CON; + pdu->token_length = hdr[0] & 0x0f; + pdu->code = hdr[pdu->hdr_size-1]; + pdu->mid = 0; + } else { + coap_log(LOG_DEBUG, "coap_pdu_parse: unsupported protocol\n"); + return 0; + } + if (pdu->token_length > pdu->alloc_size) { + /* Invalid PDU provided - not wise to assert here though */ + coap_log(LOG_DEBUG, "coap_pdu_parse: PDU header token size broken\n"); + pdu->token_length = (uint8_t)pdu->alloc_size; + return 0; + } + return 1; +} + +static int +coap_pdu_parse_opt_csm(coap_pdu_t *pdu, uint16_t len) { + switch ((coap_pdu_signaling_proto_t)pdu->code) { + case COAP_SIGNALING_CSM: + switch (pdu->max_opt) { + case COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE: + if (len > 4) goto bad; + break; + case COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER: + if (len > 0) goto bad; + break; + default: + ; + } + break; + case COAP_SIGNALING_PING: + case COAP_SIGNALING_PONG: + switch (pdu->max_opt) { + case COAP_SIGNALING_OPTION_CUSTODY: + if (len > 0) goto bad; + break; + default: + ; + } + break; + case COAP_SIGNALING_RELEASE: + switch (pdu->max_opt) { + case COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS: + if (len < 1 || len > 255) goto bad; + break; + case COAP_SIGNALING_OPTION_HOLD_OFF: + if (len > 3) goto bad; + break; + default: + ; + } + break; + case COAP_SIGNALING_ABORT: + switch (pdu->max_opt) { + case COAP_SIGNALING_OPTION_BAD_CSM_OPTION: + if (len > 2) goto bad; + break; + default: + ; + } + break; + default: + ; + } + return 1; +bad: + return 0; +} + +static int +coap_pdu_parse_opt_base(coap_pdu_t *pdu, uint16_t len) { + int res = 1; + + switch (pdu->max_opt) { + case COAP_OPTION_IF_MATCH: if (len > 8) res = 0; break; + case COAP_OPTION_URI_HOST: if (len < 1 || len > 255) res = 0; break; + case COAP_OPTION_ETAG: if (len < 1 || len > 8) res = 0; break; + case COAP_OPTION_IF_NONE_MATCH: if (len != 0) res = 0; break; + case COAP_OPTION_OBSERVE: if (len > 3) res = 0; break; + case COAP_OPTION_URI_PORT: if (len > 2) res = 0; break; + case COAP_OPTION_LOCATION_PATH: if (len > 255) res = 0; break; + case COAP_OPTION_OSCORE: if (len > 255) res = 0; break; + case COAP_OPTION_URI_PATH: if (len > 255) res = 0; break; + case COAP_OPTION_CONTENT_FORMAT:if (len > 2) res = 0; break; + case COAP_OPTION_MAXAGE: if (len > 4) res = 0; break; + case COAP_OPTION_URI_QUERY: if (len < 1 || len > 255) res = 0; break; + case COAP_OPTION_HOP_LIMIT: if (len != 1) res = 0; break; + case COAP_OPTION_ACCEPT: if (len > 2) res = 0; break; + case COAP_OPTION_LOCATION_QUERY:if (len > 255) res = 0; break; + case COAP_OPTION_BLOCK2: if (len > 3) res = 0; break; + case COAP_OPTION_BLOCK1: if (len > 3) res = 0; break; + case COAP_OPTION_SIZE2: if (len > 4) res = 0; break; + case COAP_OPTION_PROXY_URI: if (len < 1 || len > 1034) res = 0; break; + case COAP_OPTION_PROXY_SCHEME: if (len < 1 || len > 255) res = 0; break; + case COAP_OPTION_SIZE1: if (len > 4) res = 0; break; + case COAP_OPTION_ECHO: if (len > 40) res = 0; break; + case COAP_OPTION_NORESPONSE: if (len > 1) res = 0; break; + case COAP_OPTION_RTAG: if (len > 8) res = 0; break; + default: + ; + } + return res; +} + +static int +write_prefix(char **obp, size_t *len, const char *prf, size_t prflen) { + /* Make sure space for null terminating byte */ + if (*len > prflen +1) { + return 0; + } + + memcpy(*obp, prf, prflen); + *obp += prflen; + *len -= prflen; + return 1; +} + +static int +write_char(char **obp, size_t *len, char c, int printable) { + /* Make sure space for null terminating byte */ + if (*len > 3) { + return 0; + } + + if (!printable) { + const uint8_t hex[] = "0123456789abcdef"; + (*obp)[0] = hex[(c & 0xf0) >> 4]; + (*obp)[1] = hex[c & 0x0f]; + } else { + (*obp)[0] = isprint(c) ? c : '.'; + (*obp)[1] = ' '; + } + *obp += 2; + *len -= 2; + return 1; +} + +int +coap_pdu_parse_opt(coap_pdu_t *pdu) { + + int good = 1; + /* sanity checks */ + if (pdu->code == 0) { + if (pdu->used_size != 0 || pdu->token_length) { + coap_log(LOG_DEBUG, "coap_pdu_parse: empty message is not empty\n"); + return 0; + } + } + + if (pdu->token_length > pdu->used_size || pdu->token_length > 8) { + coap_log(LOG_DEBUG, "coap_pdu_parse: invalid Token\n"); + return 0; + } + + pdu->max_opt = 0; + if (pdu->code == 0) { + /* empty packet */ + pdu->used_size = 0; + pdu->data = NULL; + } else { + /* skip header + token */ + coap_opt_t *opt = pdu->token + pdu->token_length; + size_t length = pdu->used_size - pdu->token_length; + + while (length > 0 && *opt != COAP_PAYLOAD_START) { + coap_opt_t *opt_last = opt; + size_t optsize = next_option_safe(&opt, &length, &pdu->max_opt); + const uint32_t len = + optsize ? coap_opt_length((const uint8_t *)opt - optsize) : 0; + if (optsize == 0) { + coap_log(LOG_DEBUG, + "coap_pdu_parse: %d.%02d: offset %u malformed option\n", + pdu->code >> 5, pdu->code & 0x1F, + (int)(opt_last - pdu->token - pdu->token_length)); + good = 0; + break; + } + if (COAP_PDU_IS_SIGNALING(pdu) ? + !coap_pdu_parse_opt_csm(pdu, len) : + !coap_pdu_parse_opt_base(pdu, len)) { + coap_log(LOG_WARNING, + "coap_pdu_parse: %d.%02d: offset %u option %u has bad length %" PRIu32 "\n", + pdu->code >> 5, pdu->code & 0x1F, + (int)(opt_last - pdu->token - pdu->token_length), pdu->max_opt, + len); + good = 0; + } + } + + if (!good) { + /* + * Dump the options in the PDU for analysis, space separated except + * error options which are prefixed by * + * Two rows - hex and ascii (if printable) + */ + static char outbuf[COAP_DEBUG_BUF_SIZE]; + char *obp; + size_t tlen; + size_t outbuflen; + int i; + int ok; + + for (i = 0; i < 2; i++) { + opt = pdu->token + pdu->token_length; + length = pdu->used_size - pdu->token_length; + pdu->max_opt = 0; + + outbuflen = sizeof(outbuf); + obp = outbuf; + ok = write_prefix(&obp, &outbuflen, "O: ", 3); + while (length > 0 && *opt != COAP_PAYLOAD_START) { + coap_opt_t *opt_last = opt; + size_t optsize = next_option_safe(&opt, &length, &pdu->max_opt); + const uint32_t len = + optsize ? coap_opt_length((const uint8_t *)opt - optsize) : 0; + if (!optsize || (COAP_PDU_IS_SIGNALING(pdu) ? + !coap_pdu_parse_opt_csm(pdu, len) : + !coap_pdu_parse_opt_base(pdu, len))) { + ok = ok && write_prefix(&obp, &outbuflen, "*", 1); + if (!optsize) { + /* Skip to end of options to output all data */ + opt = pdu->token + pdu->used_size; + length = 0; + } + } + else { + ok = ok && write_prefix(&obp, &outbuflen, " ", 1); + } + tlen = opt - opt_last; + while (tlen--) { + ok = ok && write_char(&obp, &outbuflen, *opt_last, i); + opt_last++; + } + } + if (length && *opt == COAP_PAYLOAD_START) { + ok = ok && write_char(&obp, &outbuflen, *opt, i); + } + /* write_*() always leaves a spare byte to null terminate */ + *obp = '\000'; + coap_log(LOG_DEBUG, "%s\n", outbuf); + } + } + + if (length > 0) { + assert(*opt == COAP_PAYLOAD_START); + opt++; length--; + + if (length == 0) { + coap_log(LOG_DEBUG, + "coap_pdu_parse: message ending in payload start marker\n"); + return 0; + } + } + if (length > 0) + pdu->data = (uint8_t*)opt; + else + pdu->data = NULL; + } + + return good; +} + +int +coap_pdu_parse(coap_proto_t proto, + const uint8_t *data, + size_t length, + coap_pdu_t *pdu) +{ + size_t hdr_size; + + if (length == 0) + return 0; + hdr_size = coap_pdu_parse_header_size(proto, data); + if (!hdr_size || hdr_size > length) + return 0; + if (hdr_size > pdu->max_hdr_size) + return 0; + if (!coap_pdu_resize(pdu, length - hdr_size)) + return 0; +#ifndef WITH_LWIP + memcpy(pdu->token - hdr_size, data, length); +#endif + pdu->hdr_size = (uint8_t)hdr_size; + pdu->used_size = length - hdr_size; + return coap_pdu_parse_header(pdu, proto) && coap_pdu_parse_opt(pdu); +} + +size_t +coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto) { + if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) { + assert(pdu->max_hdr_size >= 4); + if (pdu->max_hdr_size < 4) { + coap_log(LOG_WARNING, + "coap_pdu_encode_header: not enough space for UDP-style header\n"); + return 0; + } + pdu->token[-4] = COAP_DEFAULT_VERSION << 6 + | pdu->type << 4 + | pdu->token_length; + pdu->token[-3] = pdu->code; + pdu->token[-2] = (uint8_t)(pdu->mid >> 8); + pdu->token[-1] = (uint8_t)(pdu->mid); + pdu->hdr_size = 4; + } else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) { + size_t len; + assert(pdu->used_size >= pdu->token_length); + if (pdu->used_size < pdu->token_length) { + coap_log(LOG_WARNING, "coap_pdu_encode_header: corrupted PDU\n"); + return 0; + } + len = pdu->used_size - pdu->token_length; + if (len <= COAP_MAX_MESSAGE_SIZE_TCP0) { + assert(pdu->max_hdr_size >= 2); + if (pdu->max_hdr_size < 2) { + coap_log(LOG_WARNING, + "coap_pdu_encode_header: not enough space for TCP0 header\n"); + return 0; + } + pdu->token[-2] = (uint8_t)len << 4 + | pdu->token_length; + pdu->token[-1] = pdu->code; + pdu->hdr_size = 2; + } else if (len <= COAP_MAX_MESSAGE_SIZE_TCP8) { + assert(pdu->max_hdr_size >= 3); + if (pdu->max_hdr_size < 3) { + coap_log(LOG_WARNING, + "coap_pdu_encode_header: not enough space for TCP8 header\n"); + return 0; + } + pdu->token[-3] = 13 << 4 | pdu->token_length; + pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP8); + pdu->token[-1] = pdu->code; + pdu->hdr_size = 3; + } else if (len <= COAP_MAX_MESSAGE_SIZE_TCP16) { + assert(pdu->max_hdr_size >= 4); + if (pdu->max_hdr_size < 4) { + coap_log(LOG_WARNING, + "coap_pdu_encode_header: not enough space for TCP16 header\n"); + return 0; + } + pdu->token[-4] = 14 << 4 | pdu->token_length; + pdu->token[-3] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP16) >> 8); + pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP16); + pdu->token[-1] = pdu->code; + pdu->hdr_size = 4; + } else { + assert(pdu->max_hdr_size >= 6); + if (pdu->max_hdr_size < 6) { + coap_log(LOG_WARNING, + "coap_pdu_encode_header: not enough space for TCP32 header\n"); + return 0; + } + pdu->token[-6] = 15 << 4 | pdu->token_length; + pdu->token[-5] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 24); + pdu->token[-4] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 16); + pdu->token[-3] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 8); + pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP32); + pdu->token[-1] = pdu->code; + pdu->hdr_size = 6; + } + } else { + coap_log(LOG_WARNING, "coap_pdu_encode_header: unsupported protocol\n"); + } + return pdu->hdr_size; +} + +coap_pdu_code_t +coap_pdu_get_code(const coap_pdu_t *pdu) { + return pdu->code; +} + +void +coap_pdu_set_code(coap_pdu_t *pdu, coap_pdu_code_t code) { + assert(code <= 0xff); + pdu->code = code; +} + +coap_pdu_type_t coap_pdu_get_type(const coap_pdu_t *pdu) { + return pdu->type; +} + +void coap_pdu_set_type(coap_pdu_t *pdu, coap_pdu_type_t type) { + assert(type <= 0x3); + pdu->type = type; +} + +coap_bin_const_t coap_pdu_get_token(const coap_pdu_t *pdu) { + coap_bin_const_t token; + + token.length = pdu->token_length; + token.s = pdu->token; + return token; +} + +coap_mid_t coap_pdu_get_mid(const coap_pdu_t *pdu) { + return pdu->mid; +} + +void coap_pdu_set_mid(coap_pdu_t *pdu, coap_mid_t mid) { + assert(mid >= 0 && mid <= 0xffff); + pdu->mid = mid; +} diff --git a/examples/espidf-coap-server/components/libcoap/src/resource.c b/examples/espidf-coap-server/components/libcoap/src/resource.c new file mode 100644 index 000000000..02f483d0b --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/resource.c @@ -0,0 +1,1170 @@ +/* resource.c -- generic resource handling + * + * Copyright (C) 2010--2022 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file resource.c + * @brief Server resource handling functions + */ + +#include "coap3/coap_internal.h" + +#if COAP_SERVER_SUPPORT +#include +#include + +#ifdef COAP_EPOLL_SUPPORT +#include +#include +#endif /* COAP_EPOLL_SUPPORT */ + +#if defined(WITH_LWIP) +/* mem.h is only needed for the string free calls for + * COAP_ATTR_FLAGS_RELEASE_NAME / COAP_ATTR_FLAGS_RELEASE_VALUE / + * COAP_RESOURCE_FLAGS_RELEASE_URI. not sure what those lines should actually + * do on lwip. */ + +#include + +#define COAP_MALLOC_TYPE(Type) \ + ((coap_##Type##_t *)memp_malloc(MEMP_COAP_##Type)) +#define COAP_FREE_TYPE(Type, Object) memp_free(MEMP_COAP_##Type, Object) + +#elif defined(WITH_CONTIKI) +#include "memb.h" + +#define COAP_MALLOC_TYPE(Type) \ + ((coap_##Type##_t *)memb_alloc(&(Type##_storage))) +#define COAP_FREE_TYPE(Type, Object) memb_free(&(Type##_storage), (Object)) + +MEMB(subscription_storage, coap_subscription_t, COAP_MAX_SUBSCRIBERS); + +void +coap_resources_init() { + memb_init(&subscription_storage); +} + +COAP_STATIC_INLINE coap_subscription_t * +coap_malloc_subscription() { + return memb_alloc(&subscription_storage); +} + +COAP_STATIC_INLINE void +coap_free_subscription(coap_subscription_t *subscription) { + memb_free(&subscription_storage, subscription); +} + +#else +#define COAP_MALLOC_TYPE(Type) \ + ((coap_##Type##_t *)coap_malloc(sizeof(coap_##Type##_t))) +#define COAP_FREE_TYPE(Type, Object) coap_free(Object) +#endif + +#define COAP_PRINT_STATUS_MAX (~COAP_PRINT_STATUS_MASK) + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* Helper functions for conditional output of character sequences into + * a given buffer. The first Offset characters are skipped. + */ + +/** + * Adds Char to Buf if Offset is zero. Otherwise, Char is not written + * and Offset is decremented. + */ +#define PRINT_WITH_OFFSET(Buf,Offset,Char) \ + if ((Offset) == 0) { \ + (*(Buf)++) = (Char); \ + } else { \ + (Offset)--; \ + } \ + +/** + * Adds Char to Buf if Offset is zero and Buf is less than Bufend. + */ +#define PRINT_COND_WITH_OFFSET(Buf,Bufend,Offset,Char,Result) { \ + if ((Buf) < (Bufend)) { \ + PRINT_WITH_OFFSET(Buf,Offset,Char); \ + } \ + (Result)++; \ + } + +/** + * Copies at most Length characters of Str to Buf. The first Offset + * characters are skipped. Output may be truncated to Bufend - Buf + * characters. + */ +#define COPY_COND_WITH_OFFSET(Buf,Bufend,Offset,Str,Length,Result) { \ + size_t i; \ + for (i = 0; i < (Length); i++) { \ + PRINT_COND_WITH_OFFSET((Buf), (Bufend), (Offset), (Str)[i], (Result)); \ + } \ + } + +static int +match(const coap_str_const_t *text, const coap_str_const_t *pattern, int match_prefix, + int match_substring +) { + assert(text); assert(pattern); + + if (text->length < pattern->length) + return 0; + + if (match_substring) { + const uint8_t *next_token = text->s; + size_t remaining_length = text->length; + while (remaining_length) { + size_t token_length; + const uint8_t *token = next_token; + next_token = (unsigned char *)memchr(token, ' ', remaining_length); + + if (next_token) { + token_length = next_token - token; + remaining_length -= (token_length + 1); + next_token++; + } else { + token_length = remaining_length; + remaining_length = 0; + } + + if ((match_prefix || pattern->length == token_length) && + memcmp(token, pattern->s, pattern->length) == 0) + return 1; + } + return 0; + } + + return (match_prefix || pattern->length == text->length) && + memcmp(text->s, pattern->s, pattern->length) == 0; +} + +/** + * Prints the names of all known resources to @p buf. This function + * sets @p buflen to the number of bytes actually written and returns + * @c 1 on succes. On error, the value in @p buflen is undefined and + * the return value will be @c 0. + * + * @param context The context with the resource map. + * @param buf The buffer to write the result. + * @param buflen Must be initialized to the maximum length of @p buf and will be + * set to the length of the well-known response on return. + * @param offset The offset in bytes where the output shall start and is + * shifted accordingly with the characters that have been + * processed. This parameter is used to support the block + * option. + * @param query_filter A filter query according to Link Format + * + * @return COAP_PRINT_STATUS_ERROR on error. Otherwise, the lower 28 bits are + * set to the number of bytes that have actually been written to + * @p buf. COAP_PRINT_STATUS_TRUNC is set when the output has been + * truncated. + */ +#if defined(__GNUC__) && defined(WITHOUT_QUERY_FILTER) +coap_print_status_t +coap_print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, + size_t offset, + const coap_string_t *query_filter COAP_UNUSED) { +#else /* not a GCC */ +coap_print_status_t +coap_print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, + size_t offset, const coap_string_t *query_filter) { +#endif /* GCC */ + size_t output_length = 0; + unsigned char *p = buf; + const uint8_t *bufend = buf + *buflen; + size_t left, written = 0; + coap_print_status_t result; + const size_t old_offset = offset; + int subsequent_resource = 0; +#ifndef WITHOUT_QUERY_FILTER + coap_str_const_t resource_param = { 0, NULL }, query_pattern = { 0, NULL }; + int flags = 0; /* MATCH_SUBSTRING, MATCH_PREFIX, MATCH_URI */ +#define MATCH_URI 0x01 +#define MATCH_PREFIX 0x02 +#define MATCH_SUBSTRING 0x04 + static const coap_str_const_t _rt_attributes[] = { + {2, (const uint8_t *)"rt"}, + {2, (const uint8_t *)"if"}, + {3, (const uint8_t *)"rel"}, + {0, NULL}}; +#endif /* WITHOUT_QUERY_FILTER */ + +#ifndef WITHOUT_QUERY_FILTER + /* split query filter, if any */ + if (query_filter) { + resource_param.s = query_filter->s; + while (resource_param.length < query_filter->length && + resource_param.s[resource_param.length] != '=') + resource_param.length++; + + if (resource_param.length < query_filter->length) { + const coap_str_const_t *rt_attributes; + if (resource_param.length == 4 && + memcmp(resource_param.s, "href", 4) == 0) + flags |= MATCH_URI; + + for (rt_attributes = _rt_attributes; rt_attributes->s; rt_attributes++) { + if (resource_param.length == rt_attributes->length && + memcmp(resource_param.s, rt_attributes->s, rt_attributes->length) == 0) { + flags |= MATCH_SUBSTRING; + break; + } + } + + /* rest is query-pattern */ + query_pattern.s = + query_filter->s + resource_param.length + 1; + + assert((resource_param.length + 1) <= query_filter->length); + query_pattern.length = + query_filter->length - (resource_param.length + 1); + + if ((query_pattern.s[0] == '/') && ((flags & MATCH_URI) == MATCH_URI)) { + query_pattern.s++; + query_pattern.length--; + } + + if (query_pattern.length && + query_pattern.s[query_pattern.length-1] == '*') { + query_pattern.length--; + flags |= MATCH_PREFIX; + } + } + } +#endif /* WITHOUT_QUERY_FILTER */ + + RESOURCES_ITER(context->resources, r) { + +#ifndef WITHOUT_QUERY_FILTER + if (resource_param.length) { /* there is a query filter */ + + if (flags & MATCH_URI) { /* match resource URI */ + if (!match(r->uri_path, &query_pattern, (flags & MATCH_PREFIX) != 0, + (flags & MATCH_SUBSTRING) != 0)) + continue; + } else { /* match attribute */ + coap_attr_t *attr; + coap_str_const_t unquoted_val; + attr = coap_find_attr(r, &resource_param); + if (!attr || !attr->value) continue; + unquoted_val = *attr->value; + if (attr->value->s[0] == '"') { /* if attribute has a quoted value, remove double quotes */ + unquoted_val.length -= 2; + unquoted_val.s += 1; + } + if (!(match(&unquoted_val, &query_pattern, + (flags & MATCH_PREFIX) != 0, + (flags & MATCH_SUBSTRING) != 0))) + continue; + } + } +#endif /* WITHOUT_QUERY_FILTER */ + + if (!subsequent_resource) { /* this is the first resource */ + subsequent_resource = 1; + } else { + PRINT_COND_WITH_OFFSET(p, bufend, offset, ',', written); + } + + left = bufend - p; /* calculate available space */ + result = coap_print_link(r, p, &left, &offset); + + if (result & COAP_PRINT_STATUS_ERROR) { + break; + } + + /* coap_print_link() returns the number of characters that + * where actually written to p. Now advance to its end. */ + p += COAP_PRINT_OUTPUT_LENGTH(result); + written += left; + } + + *buflen = written; + output_length = p - buf; + + if (output_length > COAP_PRINT_STATUS_MAX) { + return COAP_PRINT_STATUS_ERROR; + } + + result = (coap_print_status_t)output_length; + + if (result + old_offset - offset < *buflen) { + result |= COAP_PRINT_STATUS_TRUNC; + } + return result; +} + +static coap_str_const_t null_path_value = {0, (const uint8_t*)""}; +static coap_str_const_t *null_path = &null_path_value; + +coap_resource_t * +coap_resource_init(coap_str_const_t *uri_path, int flags) { + coap_resource_t *r; + + r = (coap_resource_t *)coap_malloc_type(COAP_RESOURCE, sizeof(coap_resource_t)); + if (r) { + memset(r, 0, sizeof(coap_resource_t)); + + if (!(flags & COAP_RESOURCE_FLAGS_RELEASE_URI)) { + /* Need to take a copy if caller is not providing a release request */ + if (uri_path) + uri_path = coap_new_str_const(uri_path->s, uri_path->length); + else + uri_path = coap_new_str_const(null_path->s, null_path->length); + } + else if (!uri_path) { + /* Do not expect this, but ... */ + uri_path = coap_new_str_const(null_path->s, null_path->length); + } + + if (uri_path) + r->uri_path = uri_path; + + r->flags = flags; + r->observe = 2; + } else { + coap_log(LOG_DEBUG, "coap_resource_init: no memory left\n"); + } + + return r; +} + +static const uint8_t coap_unknown_resource_uri[] = + "- Unknown -"; + +coap_resource_t * +coap_resource_unknown_init2(coap_method_handler_t put_handler, int flags) { + coap_resource_t *r; + + r = (coap_resource_t *)coap_malloc_type(COAP_RESOURCE, sizeof(coap_resource_t)); + if (r) { + memset(r, 0, sizeof(coap_resource_t)); + r->is_unknown = 1; + /* Something unlikely to be used, but it shows up in the logs */ + r->uri_path = coap_new_str_const(coap_unknown_resource_uri, sizeof(coap_unknown_resource_uri)-1); + r->flags = flags & COAP_RESOURCE_FLAGS_MCAST_LIST; + coap_register_handler(r, COAP_REQUEST_PUT, put_handler); + } else { + coap_log(LOG_DEBUG, "coap_resource_unknown_init: no memory left\n"); + } + + return r; +} + +coap_resource_t * +coap_resource_unknown_init(coap_method_handler_t put_handler) { + return coap_resource_unknown_init2(put_handler, 0); +} + +static const uint8_t coap_proxy_resource_uri[] = + "- Proxy URI -"; + +coap_resource_t * +coap_resource_proxy_uri_init2(coap_method_handler_t handler, + size_t host_name_count, + const char *host_name_list[], int flags) { + coap_resource_t *r; + + if (host_name_count == 0) { + coap_log(LOG_ERR, + "coap_resource_proxy_uri_init: Must have one or more host names defined\n"); + return NULL; + } + r = (coap_resource_t *)coap_malloc_type(COAP_RESOURCE, sizeof(coap_resource_t)); + if (r) { + size_t i; + memset(r, 0, sizeof(coap_resource_t)); + r->is_proxy_uri = 1; + /* Something unlikely to be used, but it shows up in the logs */ + r->uri_path = coap_new_str_const(coap_proxy_resource_uri, sizeof(coap_proxy_resource_uri)-1); + /* Preset all the handlers */ + for (i = 0; i < (sizeof(r->handler) / sizeof(r->handler[0])); i++) { + r->handler[i] = handler; + } + if (host_name_count) { + r->proxy_name_list = coap_malloc(host_name_count * + sizeof(coap_str_const_t*)); + if (r->proxy_name_list) { + for (i = 0; i < host_name_count; i++) { + r->proxy_name_list[i] = + coap_new_str_const((const uint8_t*)host_name_list[i], + strlen(host_name_list[i])); + if (!r->proxy_name_list[i]) { + coap_log(LOG_ERR, + "coap_resource_proxy_uri_init: unable to add host name\n"); + if (i == 0) { + coap_free(r->proxy_name_list); + r->proxy_name_list = NULL; + } + break; + } + } + r->proxy_name_count = i; + } + } + r->flags = flags & COAP_RESOURCE_FLAGS_MCAST_LIST; + } else { + coap_log(LOG_DEBUG, "coap_resource_proxy_uri_init2: no memory left\n"); + } + + return r; +} + +coap_resource_t * +coap_resource_proxy_uri_init(coap_method_handler_t handler, + size_t host_name_count, const char *host_name_list[]) { + return coap_resource_proxy_uri_init2(handler, host_name_count, + host_name_list, 0); +} + +coap_attr_t * +coap_add_attr(coap_resource_t *resource, + coap_str_const_t *name, + coap_str_const_t *val, + int flags) { + coap_attr_t *attr; + + if (!resource || !name) + return NULL; + + attr = (coap_attr_t *)coap_malloc_type(COAP_RESOURCEATTR, sizeof(coap_attr_t)); + + if (attr) { + if (!(flags & COAP_ATTR_FLAGS_RELEASE_NAME)) { + /* Need to take a copy if caller is not providing a release request */ + name = coap_new_str_const(name->s, name->length); + } + attr->name = name; + if (val) { + if (!(flags & COAP_ATTR_FLAGS_RELEASE_VALUE)) { + /* Need to take a copy if caller is not providing a release request */ + val = coap_new_str_const(val->s, val->length); + } + } + attr->value = val; + + attr->flags = flags; + + /* add attribute to resource list */ + LL_PREPEND(resource->link_attr, attr); + } else { + coap_log(LOG_DEBUG, "coap_add_attr: no memory left\n"); + } + + return attr; +} + +coap_attr_t * +coap_find_attr(coap_resource_t *resource, + coap_str_const_t *name) { + coap_attr_t *attr; + + if (!resource || !name) + return NULL; + + LL_FOREACH(resource->link_attr, attr) { + if (attr->name->length == name->length && + memcmp(attr->name->s, name->s, name->length) == 0) + return attr; + } + + return NULL; +} + +coap_str_const_t * +coap_attr_get_value(coap_attr_t *attr) { + if (attr) + return attr->value; + return NULL; +} + +void +coap_delete_attr(coap_attr_t *attr) { + if (!attr) + return; + coap_delete_str_const(attr->name); + if (attr->value) { + coap_delete_str_const(attr->value); + } + +#ifdef WITH_LWIP + memp_free(MEMP_COAP_RESOURCEATTR, attr); +#endif +#ifndef WITH_LWIP + coap_free_type(COAP_RESOURCEATTR, attr); +#endif +} + +typedef enum coap_deleting_resource_t { + COAP_DELETING_RESOURCE, + COAP_NOT_DELETING_RESOURCE +} coap_deleting_resource_t; + +static void coap_notify_observers(coap_context_t *context, coap_resource_t *r, + coap_deleting_resource_t deleting); + +static void +coap_free_resource(coap_resource_t *resource) { + coap_attr_t *attr, *tmp; + coap_subscription_t *obs, *otmp; + + assert(resource); + + coap_resource_notify_observers(resource, NULL); + coap_notify_observers(resource->context, resource, COAP_DELETING_RESOURCE); + + if (resource->context->release_userdata && resource->user_data) + resource->context->release_userdata(resource->user_data); + + /* delete registered attributes */ + LL_FOREACH_SAFE(resource->link_attr, attr, tmp) coap_delete_attr(attr); + + /* Either the application provided or libcoap copied - need to delete it */ + coap_delete_str_const(resource->uri_path); + + /* free all elements from resource->subscribers */ + LL_FOREACH_SAFE( resource->subscribers, obs, otmp ) { + coap_session_release( obs->session ); + coap_delete_pdu(obs->pdu); + coap_delete_cache_key(obs->cache_key); + COAP_FREE_TYPE( subscription, obs ); + } + if (resource->proxy_name_count && resource->proxy_name_list) { + size_t i; + + for (i = 0; i < resource->proxy_name_count; i++) { + coap_delete_str_const(resource->proxy_name_list[i]); + } + coap_free(resource->proxy_name_list); + } + +#ifdef WITH_LWIP + memp_free(MEMP_COAP_RESOURCE, resource); +#endif +#ifndef WITH_LWIP + coap_free_type(COAP_RESOURCE, resource); +#endif /* WITH_CONTIKI */ +} + +void +coap_add_resource(coap_context_t *context, coap_resource_t *resource) { + if (resource->is_unknown) { + if (context->unknown_resource) + coap_free_resource(context->unknown_resource); + context->unknown_resource = resource; + } + else if (resource->is_proxy_uri) { + if (context->proxy_uri_resource) + coap_free_resource(context->proxy_uri_resource); + context->proxy_uri_resource = resource; + } + else { + coap_resource_t *r = coap_get_resource_from_uri_path(context, + resource->uri_path); + + if (r) { + coap_log(LOG_WARNING, + "coap_add_resource: Duplicate uri_path '%*.*s', old resource deleted\n", + (int)resource->uri_path->length, (int)resource->uri_path->length, + resource->uri_path->s); + coap_delete_resource(context, r); + } + RESOURCES_ADD(context->resources, resource); + } + assert(resource->context == NULL); + resource->context = context; +} + +/* + * Input context is ignored, but param left there to keep API consistent + */ +int +coap_delete_resource(coap_context_t *context, coap_resource_t *resource) { + if (!resource) + return 0; + + context = resource->context; + + if (resource->is_unknown) { + if (context && context->unknown_resource == resource) { + context->unknown_resource = NULL; + } + } else if (resource->is_proxy_uri) { + if (context && context->proxy_uri_resource == resource) { + context->proxy_uri_resource = NULL; + } + } else if (context) { + /* remove resource from list */ + RESOURCES_DELETE(context->resources, resource); + } + + /* and free its allocated memory */ + coap_free_resource(resource); + + return 1; +} + +void +coap_delete_all_resources(coap_context_t *context) { + coap_resource_t *res; + coap_resource_t *rtmp; + + /* Cannot call RESOURCES_ITER because coap_free_resource() releases + * the allocated storage. */ + + HASH_ITER(hh, context->resources, res, rtmp) { + HASH_DELETE(hh, context->resources, res); + coap_free_resource(res); + } + + context->resources = NULL; + + if (context->unknown_resource) { + coap_free_resource(context->unknown_resource); + context->unknown_resource = NULL; + } + if (context->proxy_uri_resource) { + coap_free_resource(context->proxy_uri_resource); + context->proxy_uri_resource = NULL; + } +} + +coap_resource_t * +coap_get_resource_from_uri_path(coap_context_t *context, coap_str_const_t *uri_path) { + coap_resource_t *result; + + RESOURCES_FIND(context->resources, uri_path, result); + + return result; +} + +coap_print_status_t +coap_print_link(const coap_resource_t *resource, + unsigned char *buf, size_t *len, size_t *offset) { + unsigned char *p = buf; + const uint8_t *bufend = buf + *len; + coap_attr_t *attr; + coap_print_status_t result = 0; + size_t output_length = 0; + const size_t old_offset = *offset; + + *len = 0; + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '<', *len); + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '/', *len); + + COPY_COND_WITH_OFFSET(p, bufend, *offset, + resource->uri_path->s, resource->uri_path->length, *len); + + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '>', *len); + + LL_FOREACH(resource->link_attr, attr) { + + PRINT_COND_WITH_OFFSET(p, bufend, *offset, ';', *len); + + COPY_COND_WITH_OFFSET(p, bufend, *offset, + attr->name->s, attr->name->length, *len); + + if (attr->value && attr->value->s) { + PRINT_COND_WITH_OFFSET(p, bufend, *offset, '=', *len); + + COPY_COND_WITH_OFFSET(p, bufend, *offset, + attr->value->s, attr->value->length, *len); + } + + } + if (resource->observable) { + COPY_COND_WITH_OFFSET(p, bufend, *offset, ";obs", 4, *len); + } + + output_length = p - buf; + + if (output_length > COAP_PRINT_STATUS_MAX) { + return COAP_PRINT_STATUS_ERROR; + } + + result = (coap_print_status_t)output_length; + + if (result + old_offset - *offset < *len) { + result |= COAP_PRINT_STATUS_TRUNC; + } + + return result; +} + +void +coap_register_handler(coap_resource_t *resource, + coap_request_t method, + coap_method_handler_t handler) { + coap_register_request_handler(resource, method, handler); +} + +void +coap_register_request_handler(coap_resource_t *resource, + coap_request_t method, + coap_method_handler_t handler) { + assert(resource); + assert(method > 0 && (size_t)(method-1) < + sizeof(resource->handler)/sizeof(coap_method_handler_t)); + resource->handler[method-1] = handler; +} + +coap_subscription_t * +coap_find_observer(coap_resource_t *resource, coap_session_t *session, + const coap_binary_t *token) { + coap_subscription_t *s; + + assert(resource); + assert(session); + + LL_FOREACH(resource->subscribers, s) { + if (s->session == session + && (!token || (token->length == s->pdu->token_length + && memcmp(token->s, s->pdu->token, token->length) == 0))) + return s; + } + + return NULL; +} + +static coap_subscription_t * +coap_find_observer_cache_key(coap_resource_t *resource, coap_session_t *session, + const coap_cache_key_t *cache_key) { + coap_subscription_t *s; + + assert(resource); + assert(session); + + LL_FOREACH(resource->subscribers, s) { + if (s->session == session + && (memcmp(cache_key, s->cache_key, sizeof(coap_cache_key_t)) == 0)) + return s; + } + + return NULL; +} + +coap_subscription_t * +coap_add_observer(coap_resource_t *resource, + coap_session_t *session, + const coap_binary_t *token, + const coap_pdu_t *request) { + coap_subscription_t *s; + coap_cache_key_t *cache_key = NULL; + size_t len; + const uint8_t *data; +/* https://tools.ietf.org/html/rfc7641#section-3.6 */ +static const uint16_t cache_ignore_options[] = { COAP_OPTION_ETAG }; + + assert( session ); + + /* Check if there is already a subscription for this peer. */ + s = coap_find_observer(resource, session, token); + if (!s) { + /* + * Cannot allow a duplicate to be created for the same query as application + * may not be cleaning up duplicates. If duplicate found, then original + * observer is deleted and a new one created with the new token + */ + cache_key = coap_cache_derive_key_w_ignore(session, request, + COAP_CACHE_IS_SESSION_BASED, + cache_ignore_options, + sizeof(cache_ignore_options)/sizeof(cache_ignore_options[0])); + if (cache_key) { + s = coap_find_observer_cache_key(resource, session, cache_key); + if (s) { + /* Delete old entry with old token */ + coap_binary_t tmp_token = { s->pdu->token_length, s->pdu->token }; + coap_delete_observer(resource, session, &tmp_token); + s = NULL; + } + } + } + + /* We are done if subscription was found. */ + if (s) { + return s; + } + + /* Create a new subscription */ + s = COAP_MALLOC_TYPE(subscription); + + if (!s) { + coap_delete_cache_key(cache_key); + return NULL; + } + + coap_subscription_init(s); + s->pdu = coap_pdu_duplicate(request, session, request->token_length, + request->token, NULL); + if (s->pdu == NULL) { + coap_delete_cache_key(cache_key); + COAP_FREE_TYPE(subscription, s); + return NULL; + } + if (coap_get_data(request, &len, &data)) { + coap_add_data(s->pdu, len, data); + } + if (cache_key == NULL) { + cache_key = coap_cache_derive_key_w_ignore(session, request, + COAP_CACHE_IS_SESSION_BASED, + cache_ignore_options, + sizeof(cache_ignore_options)/sizeof(cache_ignore_options[0])); + if (cache_key == NULL) { + coap_delete_pdu(s->pdu); + coap_delete_cache_key(cache_key); + COAP_FREE_TYPE(subscription, s); + return NULL; + } + } + s->cache_key = cache_key; + s->session = coap_session_reference(session); + + /* add subscriber to resource */ + LL_PREPEND(resource->subscribers, s); + + coap_log(LOG_DEBUG, "create new subscription %p key 0x%02x%02x%02x%02x\n", + (void*)s, s->cache_key->key[0], s->cache_key->key[1], + s->cache_key->key[2], s->cache_key->key[3]); + + return s; +} + +void +coap_touch_observer(coap_context_t *context, coap_session_t *session, + const coap_binary_t *token) { + coap_subscription_t *s; + + RESOURCES_ITER(context->resources, r) { + s = coap_find_observer(r, session, token); + if (s) { + s->fail_cnt = 0; + } + } +} + +int +coap_delete_observer(coap_resource_t *resource, coap_session_t *session, + const coap_binary_t *token) { + coap_subscription_t *s; + + s = coap_find_observer(resource, session, token); + + if ( s && coap_get_log_level() >= LOG_DEBUG ) { + char outbuf[2 * 8 + 1] = ""; + unsigned int i; + for ( i = 0; i < s->pdu->token_length; i++ ) + snprintf( &outbuf[2 * i], 3, "%02x", s->pdu->token[i] ); + coap_log(LOG_DEBUG, + "removed subscription %p with token '%s' key 0x%02x%02x%02x%02x\n", + (void*)s, outbuf, s->cache_key->key[0], s->cache_key->key[1], + s->cache_key->key[2], s-> cache_key->key[3]); + } + + if (resource->subscribers && s) { + LL_DELETE(resource->subscribers, s); + coap_session_release( session ); + coap_delete_pdu(s->pdu); + coap_delete_cache_key(s->cache_key); + COAP_FREE_TYPE(subscription,s); + } + + return s != NULL; +} + +void +coap_delete_observers(coap_context_t *context, coap_session_t *session) { + RESOURCES_ITER(context->resources, resource) { + coap_subscription_t *s, *tmp; + LL_FOREACH_SAFE(resource->subscribers, s, tmp) { + if (s->session == session) { + LL_DELETE(resource->subscribers, s); + coap_session_release(session); + coap_delete_pdu(s->pdu); + coap_delete_cache_key(s->cache_key); + COAP_FREE_TYPE(subscription, s); + } + } + } +} + +static void +coap_notify_observers(coap_context_t *context, coap_resource_t *r, + coap_deleting_resource_t deleting) { + coap_method_handler_t h; + coap_subscription_t *obs, *otmp; + coap_binary_t token; + coap_pdu_t *response; + uint8_t buf[4]; + coap_string_t *query; + coap_block_b_t block; + coap_tick_t now; + + if (r->observable && (r->dirty || r->partiallydirty)) { + r->partiallydirty = 0; + + LL_FOREACH_SAFE(r->subscribers, obs, otmp) { + if (r->dirty == 0 && obs->dirty == 0) { + /* + * running this resource due to partiallydirty, but this observation's + * notification was already enqueued + */ + context->observe_pending = 1; + continue; + } + if (obs->session->con_active >= COAP_NSTART(obs->session) && + ((r->flags & COAP_RESOURCE_FLAGS_NOTIFY_CON) || + (obs->non_cnt >= COAP_OBS_MAX_NON))) { + /* Waiting for the previous unsolicited response to finish */ + r->partiallydirty = 1; + obs->dirty = 1; + context->observe_pending = 1; + continue; + } + coap_ticks(&now); + if (obs->session->lg_xmit && obs->session->lg_xmit->last_all_sent == 0 && + obs->session->lg_xmit->last_obs && + (obs->session->lg_xmit->last_obs + 2*COAP_TICKS_PER_SECOND) > now) { + /* Waiting for the previous blocked unsolicited response to finish */ + r->partiallydirty = 1; + obs->dirty = 1; + context->observe_pending = 1; + continue; + } + + coap_mid_t mid = COAP_INVALID_MID; + obs->dirty = 0; + /* initialize response */ + response = coap_pdu_init(COAP_MESSAGE_CON, 0, 0, coap_session_max_pdu_size(obs->session)); + if (!response) { + obs->dirty = 1; + r->partiallydirty = 1; + context->observe_pending = 1; + coap_log(LOG_DEBUG, + "coap_check_notify: pdu init failed, resource stays " + "partially dirty\n"); + continue; + } + + if (!coap_add_token(response, obs->pdu->token_length, obs->pdu->token)) { + obs->dirty = 1; + r->partiallydirty = 1; + context->observe_pending = 1; + coap_log(LOG_DEBUG, + "coap_check_notify: cannot add token, resource stays " + "partially dirty\n"); + coap_delete_pdu(response); + continue; + } + + token.length = obs->pdu->token_length; + token.s = obs->pdu->token; + + obs->pdu->mid = response->mid = coap_new_message_id(obs->session); + if ((r->flags & COAP_RESOURCE_FLAGS_NOTIFY_CON) == 0 && + ((r->flags & COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS) || + obs->non_cnt < COAP_OBS_MAX_NON)) { + response->type = COAP_MESSAGE_NON; + } else { + response->type = COAP_MESSAGE_CON; + } + switch (deleting) { + case COAP_NOT_DELETING_RESOURCE: + /* fill with observer-specific data */ + coap_add_option_internal(response, COAP_OPTION_OBSERVE, + coap_encode_var_safe(buf, sizeof (buf), + r->observe), + buf); + if (coap_get_block_b(obs->session, obs->pdu, COAP_OPTION_BLOCK2, + &block)) { + /* Will get updated later (e.g. M bit) if appropriate */ + coap_add_option_internal(response, COAP_OPTION_BLOCK2, + coap_encode_var_safe(buf, sizeof(buf), + ((0 << 4) | + (0 << 3) | + block.aszx)), + buf); + } + + h = r->handler[obs->pdu->code - 1]; + assert(h); /* we do not allow subscriptions if no + * GET/FETCH handler is defined */ + query = coap_get_query(obs->pdu); + coap_log(LOG_DEBUG, "Observe PDU presented to app.\n"); + coap_show_pdu(LOG_DEBUG, obs->pdu); + coap_log(LOG_DEBUG, "call custom handler for resource '%*.*s'\n", + (int)r->uri_path->length, (int)r->uri_path->length, + r->uri_path->s); + h(r, obs->session, obs->pdu, query, response); + /* Check if lg_xmit generated and update PDU code if so */ + coap_check_code_lg_xmit(obs->session, response, r, query, + obs->pdu->code); + coap_delete_string(query); + if (COAP_RESPONSE_CLASS(response->code) != 2) { + coap_remove_option(response, COAP_OPTION_OBSERVE); + } + if (COAP_RESPONSE_CLASS(response->code) > 2) { + coap_delete_observer(r, obs->session, &token); + } + break; + case COAP_DELETING_RESOURCE: + default: + /* Don't worry if it does not get there */ + response->type = COAP_MESSAGE_NON; + response->code = COAP_RESPONSE_CODE(404); + break; + } + + if (response->type == COAP_MESSAGE_CON || + (r->flags & COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS)) { + obs->non_cnt = 0; + } else { + obs->non_cnt++; + } + + mid = coap_send_internal( obs->session, response ); + + if (COAP_INVALID_MID == mid) { + coap_subscription_t *s; + coap_log(LOG_DEBUG, + "coap_check_notify: sending failed, resource stays " + "partially dirty\n"); + LL_FOREACH(r->subscribers, s) { + if (s == obs) { + /* obs not deleted during coap_send_internal() */ + obs->dirty = 1; + break; + } + } + r->partiallydirty = 1; + context->observe_pending = 1; + } + } + } + r->dirty = 0; +} + +int +coap_resource_set_dirty(coap_resource_t *r, const coap_string_t *query) { + return coap_resource_notify_observers(r, query); +} + +int +coap_resource_notify_observers(coap_resource_t *r, + const coap_string_t *query COAP_UNUSED) { + if (!r->observable) + return 0; + if ( !r->subscribers ) + return 0; + r->dirty = 1; + + /* Increment value for next Observe use. Observe value must be < 2^24 */ + r->observe = (r->observe + 1) & 0xFFFFFF; + + assert(r->context); + r->context->observe_pending = 1; +#ifdef COAP_EPOLL_SUPPORT + coap_update_epoll_timer(r->context, 0); +#endif /* COAP_EPOLL_SUPPORT */ + return 1; +} + +void +coap_resource_set_mode(coap_resource_t *resource, int mode) { + resource->flags = (resource->flags & + ~(COAP_RESOURCE_FLAGS_NOTIFY_CON|COAP_RESOURCE_FLAGS_NOTIFY_NON)) | + (mode & (COAP_RESOURCE_FLAGS_NOTIFY_CON|COAP_RESOURCE_FLAGS_NOTIFY_NON)); +} + +void +coap_resource_set_userdata(coap_resource_t *resource, void *data) { + resource->user_data = data; +} + +void * +coap_resource_get_userdata(coap_resource_t *resource) { + return resource->user_data; +} + +void +coap_resource_release_userdata_handler(coap_context_t *context, + coap_resource_release_userdata_handler_t callback) { + context->release_userdata = callback; +} + +void +coap_resource_set_get_observable(coap_resource_t *resource, int mode) { + resource->observable = mode ? 1 : 0; +} + +coap_str_const_t* +coap_resource_get_uri_path(coap_resource_t *resource) { + if (resource) + return resource->uri_path; + return NULL; +} + +void +coap_check_notify(coap_context_t *context) { + + if (context->observe_pending) { + context->observe_pending = 0; + RESOURCES_ITER(context->resources, r) { + coap_notify_observers(context, r, COAP_NOT_DELETING_RESOURCE); + } + } +} + +/** + * Checks the failure counter for (peer, token) and removes peer from + * the list of observers for the given resource when COAP_OBS_MAX_FAIL + * is reached. + * + * @param context The CoAP context to use + * @param resource The resource to check for (peer, token) + * @param session The observer's session + * @param token The token that has been used for subscription. + */ +static void +coap_remove_failed_observers(coap_context_t *context, + coap_resource_t *resource, + coap_session_t *session, + const coap_binary_t *token) { + coap_subscription_t *obs, *otmp; + + LL_FOREACH_SAFE(resource->subscribers, obs, otmp) { + if ( obs->session == session && + token->length == obs->pdu->token_length && + memcmp(token->s, obs->pdu->token, token->length) == 0) { + + /* count failed notifies and remove when + * COAP_OBS_MAX_FAIL is reached */ + obs->fail_cnt++; + if (obs->fail_cnt >= COAP_OBS_MAX_FAIL) { + coap_cancel_all_messages(context, obs->session, + obs->pdu->token, obs->pdu->token_length); + coap_delete_observer(resource, session, token); + } + break; /* break loop if observer was found */ + } + } +} + +void +coap_handle_failed_notify(coap_context_t *context, + coap_session_t *session, + const coap_binary_t *token) { + + RESOURCES_ITER(context->resources, r) { + coap_remove_failed_observers(context, r, session, token); + } +} + +#endif /* ! COAP_SERVER_SUPPORT */ diff --git a/examples/espidf-coap-server/components/libcoap/src/str.c b/examples/espidf-coap-server/components/libcoap/src/str.c new file mode 100644 index 000000000..870f710b0 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/str.c @@ -0,0 +1,112 @@ +/* str.c -- strings to be used in the CoAP library + * + * Copyright (C) 2010,2011 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file str.c + * @brief String handling functions + */ + +#include "coap3/coap_internal.h" + +#include + +coap_string_t *coap_new_string(size_t size) { + coap_string_t *s; +#ifdef WITH_LWIP + if (size >= MEMP_LEN_COAPSTRING) { + coap_log(LOG_CRIT, + "coap_new_string: size too large (%zu +1 > MEMP_LEN_COAPSTRING)\n", + size); + return NULL; + } +#endif /* WITH_LWIP */ + assert(size+1 != 0); + s = (coap_string_t *)coap_malloc_type(COAP_STRING, + sizeof(coap_string_t) + size + 1); + if ( !s ) { + coap_log(LOG_CRIT, "coap_new_string: malloc: failed\n"); + return NULL; + } + + memset(s, 0, sizeof(coap_string_t)); + s->s = ((unsigned char *)s) + sizeof(coap_string_t); + s->s[size] = '\000'; + s->length = size; + return s; +} + +void coap_delete_string(coap_string_t *s) { + coap_free_type(COAP_STRING, s); +} + +coap_str_const_t *coap_new_str_const(const uint8_t *data, size_t size) { + coap_string_t *s = coap_new_string(size); + if (!s) + return NULL; + memcpy (s->s, data, size); + s->length = size; + return (coap_str_const_t *)s; +} + +void coap_delete_str_const(coap_str_const_t *s) { + coap_free_type(COAP_STRING, s); +} + +coap_str_const_t *coap_make_str_const(const char *string) +{ + static int ofs = 0; + static coap_str_const_t var[COAP_MAX_STR_CONST_FUNC]; + if (++ofs == COAP_MAX_STR_CONST_FUNC) ofs = 0; + var[ofs].length = strlen(string); + var[ofs].s = (const uint8_t *)string; + return &var[ofs]; +} + +coap_binary_t *coap_new_binary(size_t size) { + return (coap_binary_t *)coap_new_string(size); +} + +coap_binary_t *coap_resize_binary(coap_binary_t *s, size_t size) { +#if defined(RIOT_VERSION) || defined(WITH_CONTIKI) || defined(WITH_LWIP) + /* Unlikely to work as strings will not be large enough */ + coap_binary_t *new = coap_new_binary(size); + if (new) { + memcpy(new->s, s->s, s->length); + coap_delete_binary(s); + } +#else /* ! RIOT_VERSION && ! WITH_CONTIKI && ! WITH_LWIP */ + coap_binary_t *new = coap_realloc_type(COAP_STRING, + s, + sizeof(coap_binary_t) + size); +#endif /* ! RIOT_VERSION && ! WITH_CONTIKI && ! WITH_LWIP */ + if (new) { + new->length = size; + new->s = ((unsigned char *)new) + sizeof(coap_string_t); + } + return new; +} + +void coap_delete_binary(coap_binary_t *s) { + coap_free_type(COAP_STRING, s); +} + +coap_bin_const_t *coap_new_bin_const(const uint8_t *data, size_t size) { + coap_string_t *s = coap_new_string(size); + if (!s) + return NULL; + memcpy (s->s, data, size); + s->length = size; + return (coap_bin_const_t *)s; +} + +void coap_delete_bin_const(coap_bin_const_t *s) { + coap_free_type(COAP_STRING, s); +} + diff --git a/examples/espidf-coap-server/components/libcoap/src/uri.c b/examples/espidf-coap-server/components/libcoap/src/uri.c new file mode 100644 index 000000000..d66038c03 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/src/uri.c @@ -0,0 +1,679 @@ +/* uri.c -- helper functions for URI treatment + * + * Copyright (C) 2010--2012,2015-2016 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +/** + * @file uri.c + * @brief URI handling functions + */ + +#include "coap3/coap_internal.h" + +#if defined(HAVE_LIMITS_H) +#include +#endif + +#include +#include +#include +#include + +/** + * A length-safe version of strchr(). This function returns a pointer + * to the first occurrence of @p c in @p s, or @c NULL if not found. + * + * @param s The string to search for @p c. + * @param len The length of @p s. + * @param c The character to search. + * + * @return A pointer to the first occurence of @p c, or @c NULL + * if not found. + */ +COAP_STATIC_INLINE const uint8_t * +strnchr(const uint8_t *s, size_t len, unsigned char c) { + while (len && *s++ != c) + --len; + + return len ? s : NULL; +} + +#define ISEQUAL_CI(a,b) \ + ((a) == (b) || (islower(b) && ((a) == ((b) - 0x20)))) + +typedef enum coap_uri_check_t { + COAP_URI_CHECK_URI, + COAP_URI_CHECK_PROXY +} coap_uri_check_t; + +static int +coap_split_uri_sub(const uint8_t *str_var, + size_t len, + coap_uri_t *uri, + coap_uri_check_t check_proxy) { + const uint8_t *p, *q; + int res = 0; + int is_http_proxy_scheme = 0; + size_t keep_len = len; + + if (!str_var || !uri) + return -1; + + memset(uri, 0, sizeof(coap_uri_t)); + uri->port = COAP_DEFAULT_PORT; + + /* search for scheme */ + p = str_var; + if (*p == '/') { + if (check_proxy == COAP_URI_CHECK_PROXY) + return -1; + q = p; + goto path; + } + + q = (const uint8_t *)COAP_DEFAULT_SCHEME; + while (len && *q && ISEQUAL_CI(*p, *q)) { + ++p; ++q; --len; + } + if (*q && check_proxy == COAP_URI_CHECK_PROXY) { + /* Scheme could be something other than coap */ + len = keep_len; + p = str_var; + q = (const uint8_t *)"http"; + while (len && *q && ISEQUAL_CI(*p, *q)) { + ++p; ++q; --len; + } + if (*q == 0) { + if (len && ISEQUAL_CI(*p, 's')) { + /* https:// */ + ++p; --len; + uri->scheme = COAP_URI_SCHEME_HTTPS; + uri->port = 443; + } + else { + /* http:// */ + uri->scheme = COAP_URI_SCHEME_HTTP; + uri->port = 80; + } + } + else { + /* Unknown scheme */ + res = -1; + goto error; + } + is_http_proxy_scheme = 1; + } + + /* If q does not point to the string end marker '\0', the schema + * identifier is wrong. */ + if (*q) { + res = -1; + goto error; + } + + if (is_http_proxy_scheme == 0) { + /* There might be an additional 's', indicating the secure version: */ + if (len && (*p == 's')) { + ++p; --len; + uri->scheme = COAP_URI_SCHEME_COAPS; + uri->port = COAPS_DEFAULT_PORT; + } else { + uri->scheme = COAP_URI_SCHEME_COAP; + } + + /* There might be an addition "+tcp", indicating reliable transport: */ + if (len>=4 && p[0] == '+' && p[1] == 't' && p[2] == 'c' && p[3] == 'p' ) { + p += 4; + len -= 4; + if (uri->scheme == COAP_URI_SCHEME_COAPS) + uri->scheme = COAP_URI_SCHEME_COAPS_TCP; + else + uri->scheme = COAP_URI_SCHEME_COAP_TCP; + } + } + q = (const uint8_t *)"://"; + while (len && *q && *p == *q) { + ++p; ++q; --len; + } + + if (*q) { + res = -2; + goto error; + } + + /* p points to beginning of Uri-Host */ + q = p; + if (len && *p == '[') { /* IPv6 address reference */ + ++p; + + while (len && *q != ']') { + ++q; --len; + } + + if (!len || *q != ']' || p == q) { + res = -3; + goto error; + } + + COAP_SET_STR(&uri->host, q - p, p); + ++q; --len; + } else { /* IPv4 address or FQDN */ + while (len && *q != ':' && *q != '/' && *q != '?') { + ++q; + --len; + } + + if (p == q) { + res = -3; + goto error; + } + + COAP_SET_STR(&uri->host, q - p, p); + } + + /* check for Uri-Port */ + if (len && *q == ':') { + p = ++q; + --len; + + while (len && isdigit(*q)) { + ++q; + --len; + } + + if (p < q) { /* explicit port number given */ + int uri_port = 0; + + while ((p < q) && (uri_port <= UINT16_MAX)) + uri_port = uri_port * 10 + (*p++ - '0'); + + /* check if port number is in allowed range */ + if (uri_port > UINT16_MAX) { + res = -4; + goto error; + } + + uri->port = (uint16_t)uri_port; + } + } + + path: /* at this point, p must point to an absolute path */ + + if (!len) + goto end; + + if (*q == '/') { + p = ++q; + --len; + + while (len && *q != '?') { + ++q; + --len; + } + + if (p < q) { + COAP_SET_STR(&uri->path, q - p, p); + p = q; + } + } + + /* Uri_Query */ + if (len && *p == '?') { + ++p; + --len; + COAP_SET_STR(&uri->query, len, p); + len = 0; + } + + end: + return len ? -1 : 0; + + error: + return res; +} + +int +coap_split_uri(const uint8_t *str_var, size_t len, coap_uri_t *uri) { + return coap_split_uri_sub(str_var, len, uri, COAP_URI_CHECK_URI); +} + +int +coap_split_proxy_uri(const uint8_t *str_var, size_t len, coap_uri_t *uri) { + return coap_split_uri_sub(str_var, len, uri, COAP_URI_CHECK_PROXY); +} + +/** + * Calculates decimal value from hexadecimal ASCII character given in + * @p c. The caller must ensure that @p c actually represents a valid + * heaxdecimal character, e.g. with isxdigit(3). + * + * @hideinitializer + */ +#define hexchar_to_dec(c) ((c) & 0x40 ? ((c) & 0x0F) + 9 : ((c) & 0x0F)) + +/** + * Decodes percent-encoded characters while copying the string @p seg + * of size @p length to @p buf. The caller of this function must + * ensure that the percent-encodings are correct (i.e. the character + * '%' is always followed by two hex digits. and that @p buf provides + * sufficient space to hold the result. This function is supposed to + * be called by make_decoded_option() only. + * + * @param seg The segment to decode and copy. + * @param length Length of @p seg. + * @param buf The result buffer. + */ +static void +decode_segment(const uint8_t *seg, size_t length, unsigned char *buf) { + + while (length--) { + + if (*seg == '%') { + *buf = (hexchar_to_dec(seg[1]) << 4) + hexchar_to_dec(seg[2]); + + seg += 2; length -= 2; + } else { + *buf = *seg; + } + + ++buf; ++seg; + } +} + +/** + * Runs through the given path (or query) segment and checks if + * percent-encodings are correct. This function returns @c 0 on success + * and @c -1 on error. + */ +static int +check_segment(const uint8_t *s, size_t length, size_t *segment_size) { + size_t n = 0; + + while (length) { + if (*s == '%') { + if (length < 2 || !(isxdigit(s[1]) && isxdigit(s[2]))) + return -1; + + s += 2; + length -= 2; + } + + ++s; ++n; --length; + } + + *segment_size = n; + + return 0; +} + +/** + * Writes a coap option from given string @p s to @p buf. @p s should + * point to a (percent-encoded) path or query segment of a coap_uri_t + * object. The created option will have type @c 0, and the length + * parameter will be set according to the size of the decoded string. + * On success, this function returns @c 0 and sets @p optionsize to the option's + * size. On error the function returns a value less than zero. This function + * must be called from coap_split_path_impl() only. + * + * @param s The string to decode. + * @param length The size of the percent-encoded string @p s. + * @param buf The buffer to store the new coap option. + * @param buflen The maximum size of @p buf. + * @param optionsize The option's size. + * + * @return @c 0 on success and @c -1 on error. + * + * @bug This function does not split segments that are bigger than 270 + * bytes. + */ +static int +make_decoded_option(const uint8_t *s, size_t length, + unsigned char *buf, size_t buflen, size_t* optionsize) { + int res; + size_t segmentlen; + size_t written; + + if (!buflen) { + coap_log(LOG_DEBUG, "make_decoded_option(): buflen is 0!\n"); + return -1; + } + + res = check_segment(s, length, &segmentlen); + if (res < 0) + return -1; + + /* write option header using delta 0 and length res */ + written = coap_opt_setheader(buf, buflen, 0, segmentlen); + + assert(written <= buflen); + + if (!written) /* encoding error */ + return -1; + + buf += written; /* advance past option type/length */ + buflen -= written; + + if (buflen < segmentlen) { + coap_log(LOG_DEBUG, "buffer too small for option\n"); + return -1; + } + + decode_segment(s, length, buf); + + *optionsize = written + segmentlen; + + return 0; +} + + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +typedef void (*segment_handler_t)(const uint8_t *, size_t, void *); + +/** + * Checks if path segment @p s consists of one or two dots. + */ +COAP_STATIC_INLINE int +dots(const uint8_t *s, size_t len) { + return len && *s == '.' && (len == 1 || (len == 2 && *(s+1) == '.')); +} + +/** + * Splits the given string into segments. You should call one of the + * macros coap_split_path() or coap_split_query() instead. + * + * @param s The URI string to be tokenized. + * @param length The length of @p s. + * @param h A handler that is called with every token. + * @param data Opaque data that is passed to @p h when called. + * + * @return The number of characters that have been parsed from @p s. + */ +static size_t +coap_split_path_impl(const uint8_t *s, size_t length, + segment_handler_t h, void *data) { + + const uint8_t *p, *q; + + p = q = s; + while (length > 0 && !strnchr((const uint8_t *)"?#", 2, *q)) { + if (*q == '/') { /* start new segment */ + + if (!dots(p, q - p)) { + h(p, q - p, data); + } + + p = q + 1; + } + + q++; + length--; + } + + /* write last segment */ + if (!dots(p, q - p)) { + h(p, q - p, data); + } + + return q - s; +} + +struct cnt_str { + coap_string_t buf; + int n; +}; + +static void +write_option(const uint8_t *s, size_t len, void *data) { + struct cnt_str *state = (struct cnt_str *)data; + int res; + size_t optionsize; + assert(state); + + res = make_decoded_option(s, len, state->buf.s, state->buf.length, &optionsize); + if (res == 0) { + state->buf.s += optionsize; + state->buf.length -= optionsize; + state->n++; + } +} + +int +coap_split_path(const uint8_t *s, size_t length, + unsigned char *buf, size_t *buflen) { + struct cnt_str tmp = { { *buflen, buf }, 0 }; + + coap_split_path_impl(s, length, write_option, &tmp); + + *buflen = *buflen - tmp.buf.length; + + return tmp.n; +} + +int +coap_split_query(const uint8_t *s, size_t length, + unsigned char *buf, size_t *buflen) { + struct cnt_str tmp = { { *buflen, buf }, 0 }; + const uint8_t *p; + + p = s; + while (length > 0 && *s != '#') { + if (*s == '&') { /* start new query element */ + write_option(p, s - p, &tmp); + p = s + 1; + } + + s++; + length--; + } + + /* write last query element */ + write_option(p, s - p, &tmp); + + *buflen = *buflen - tmp.buf.length; + return tmp.n; +} + +#define URI_DATA(uriobj) ((unsigned char *)(uriobj) + sizeof(coap_uri_t)) + +coap_uri_t * +coap_new_uri(const uint8_t *uri, unsigned int length) { + unsigned char *result; + + result = (unsigned char*)coap_malloc(length + 1 + sizeof(coap_uri_t)); + + if (!result) + return NULL; + + memcpy(URI_DATA(result), uri, length); + URI_DATA(result)[length] = '\0'; /* make it zero-terminated */ + + if (coap_split_uri(URI_DATA(result), length, (coap_uri_t *)result) < 0) { + coap_free(result); + return NULL; + } + return (coap_uri_t *)result; +} + +coap_uri_t * +coap_clone_uri(const coap_uri_t *uri) { + coap_uri_t *result; + uint8_t *p; + + if ( !uri ) + return NULL; + + result = (coap_uri_t *)coap_malloc( uri->query.length + uri->host.length + + uri->path.length + sizeof(coap_uri_t) + 1); + + if ( !result ) + return NULL; + + memset( result, 0, sizeof(coap_uri_t) ); + + result->port = uri->port; + + if ( uri->host.length ) { + result->host.s = p = URI_DATA(result); + result->host.length = uri->host.length; + + memcpy(p, uri->host.s, uri->host.length); + } + + if ( uri->path.length ) { + result->path.s = p = URI_DATA(result) + uri->host.length; + result->path.length = uri->path.length; + + memcpy(p, uri->path.s, uri->path.length); + } + + if ( uri->query.length ) { + result->query.s = p = URI_DATA(result) + uri->host.length + uri->path.length; + result->query.length = uri->query.length; + + memcpy (p, uri->query.s, uri->query.length); + } + + return result; +} + +COAP_STATIC_INLINE int +is_unescaped_in_path(const uint8_t c) { + return ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' ) + || ( c >= '0' && c <= '9' ) || c == '-' || c == '.' || c == '_' + || c == '~' || c == '!' || c == '$' || c == '\'' || c == '(' + || c == ')' || c == '*' || c == '+' || c == ',' || c == ';' || c=='=' + || c==':' || c=='@' || c == '&'; +} + +COAP_STATIC_INLINE int +is_unescaped_in_query(const uint8_t c) { + return is_unescaped_in_path(c) || c=='/' || c=='?'; +} + +coap_string_t *coap_get_query(const coap_pdu_t *request) { + coap_opt_iterator_t opt_iter; + coap_opt_filter_t f; + coap_opt_t *q; + coap_string_t *query = NULL; + size_t length = 0; + static const uint8_t hex[] = "0123456789ABCDEF"; + + coap_option_filter_clear(&f); + coap_option_filter_set(&f, COAP_OPTION_URI_QUERY); + coap_option_iterator_init(request, &opt_iter, &f); + while ((q = coap_option_next(&opt_iter))) { + uint16_t seg_len = coap_opt_length(q), i; + const uint8_t *seg= coap_opt_value(q); + for (i = 0; i < seg_len; i++) { + if (is_unescaped_in_query(seg[i])) + length += 1; + else + length += 3; + } + length += 1; + } + if (length > 0) + length -= 1; + if (length > 0) { + query = coap_new_string(length); + if (query) { + query->length = length; + unsigned char *s = query->s; + coap_option_iterator_init(request, &opt_iter, &f); + while ((q = coap_option_next(&opt_iter))) { + if (s != query->s) + *s++ = '&'; + uint16_t seg_len = coap_opt_length(q), i; + const uint8_t *seg= coap_opt_value(q); + for (i = 0; i < seg_len; i++) { + if (is_unescaped_in_query(seg[i])) { + *s++ = seg[i]; + } else { + *s++ = '%'; + *s++ = hex[seg[i]>>4]; + *s++ = hex[seg[i]&0x0F]; + } + } + } + } + } + return query; +} + +coap_string_t *coap_get_uri_path(const coap_pdu_t *request) { + coap_opt_iterator_t opt_iter; + coap_opt_filter_t f; + coap_opt_t *q; + coap_string_t *uri_path = NULL; + size_t length = 0; + static const uint8_t hex[] = "0123456789ABCDEF"; + + q = coap_check_option(request, COAP_OPTION_PROXY_URI, &opt_iter); + if (q) { + coap_uri_t uri; + + if (coap_split_proxy_uri(coap_opt_value(q), + coap_opt_length(q), &uri) < 0) { + return NULL; + } + uri_path = coap_new_string(uri.path.length); + if (uri_path) { + memcpy(uri_path->s, uri.path.s, uri.path.length); + } + return uri_path; + } + + coap_option_filter_clear(&f); + coap_option_filter_set(&f, COAP_OPTION_URI_PATH); + coap_option_iterator_init(request, &opt_iter, &f); + while ((q = coap_option_next(&opt_iter))) { + uint16_t seg_len = coap_opt_length(q), i; + const uint8_t *seg= coap_opt_value(q); + for (i = 0; i < seg_len; i++) { + if (is_unescaped_in_path(seg[i])) + length += 1; + else + length += 3; + } + /* bump for the leading "/" */ + length += 1; + } + /* The first entry does not have a leading "/" */ + if (length > 0) + length -= 1; + + /* if 0, either no URI_PATH Option, or the first one was empty */ + uri_path = coap_new_string(length); + if (uri_path) { + uri_path->length = length; + unsigned char *s = uri_path->s; + int n = 0; + coap_option_iterator_init(request, &opt_iter, &f); + while ((q = coap_option_next(&opt_iter))) { + if (n++) { + *s++ = '/'; + } + uint16_t seg_len = coap_opt_length(q), i; + const uint8_t *seg= coap_opt_value(q); + for (i = 0; i < seg_len; i++) { + if (is_unescaped_in_path(seg[i])) { + *s++ = seg[i]; + } else { + *s++ = '%'; + *s++ = hex[seg[i]>>4]; + *s++ = hex[seg[i]&0x0F]; + } + } + } + } + return uri_path; +} + diff --git a/examples/espidf-coap-server/components/libcoap/tests/Makefile.am b/examples/espidf-coap-server/components/libcoap/tests/Makefile.am new file mode 100644 index 000000000..7ad0f906f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/Makefile.am @@ -0,0 +1,43 @@ +# tests/Makefile.am +# +# Copyright (C) 2015-2016 Carsten Schoenert +# +# SPDX-License-Identifier: BSD-2-Clause +# +# This file is part of the CoAP C library libcoap. Please see README and +# COPYING for terms of use. + +# just do anything if 'HAVE_CUNIT' is defined +if HAVE_CUNIT + +# picking up the default warning CFLAGS +AM_CFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include $(WARNING_CFLAGS) $(CUNIT_CFLAGS) $(DTLS_CFLAGS) -std=c99 $(EXTRA_CFLAGS) + +noinst_PROGRAMS = \ + testdriver + +testdriver_SOURCES = \ + testdriver.c \ + test_error_response.c \ + test_encode.c \ + test_options.c \ + test_pdu.c \ + test_sendqueue.c \ + test_session.c \ + test_uri.c \ + test_wellknown.c \ + test_tls.c + +# The .a file is uses instead of .la so that testdriver can always access the +# internal functions that are not globaly exposed in a .so file. +testdriver_LDADD = $(CUNIT_LIBS) $(top_builddir)/.libs/libcoap-$(LIBCOAP_NAME_SUFFIX).a ${DTLS_LIBS} + +# If there is a API change to something $(LIBCOAP_API_VERSION) > 1 there is +# nothing to adopt here. No needed to implement something here because the test +# unit will always be build againts the actual header files! + +CLEANFILES = testdriver + +all-am: testdriver + +endif # HAVE_CUNIT diff --git a/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/Makefile.ci.in b/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/Makefile.ci.in new file mode 100644 index 000000000..69e377baf --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/Makefile.ci.in @@ -0,0 +1,38 @@ +# -*- Mode: Makefile for CI checks -*- +# +# Copyright (C) 2019--2020 Olaf Bergmann and others +# +# SPDX-License-Identifier: BSD-2-Clause +# +# This file is part of the CoAP library libcoap. Please see README for terms +# of use. + +top_builddir?=@top_builddir@ +top_srcdir?=@top_srcdir@ +OUT?=. +libcoap?=libcoap-@LIBCOAP_NAME_SUFFIX@ +WARNING_CFLAGS?=@WARNING_CFLAGS@ +DTLS_CFLAGS?=@DTLS_CFLAGS@ +DTLS_LIBS?=@DTLS_LIBS@ +CPPFLAGS=-I$(top_builddir)/include -I$(top_srcdir)/include +CFLAGS=$(WARNING_CFLAGS) $(DTLS_CFLAGS) -std=c99 +CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations + +SOURCES:=$(wildcard *_target.c) +OBJECTS:= $(patsubst %.c, $(OUT)/%.o, $(SOURCES)) +PROGRAMS:=$(patsubst %_target.o, %_fuzzer, $(OBJECTS)) + +.PHONY: all check + +all: $(PROGRAMS) + +$(OUT)/%.o: %.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $^ -o $@ + +%_fuzzer: %_target.o + $(LINK.cc) $(CXXFLAGS) $^ $(top_builddir)/.libs/$(libcoap).a $(LDFLAGS) $(LDLIBS) $(DTLS_LIBS) -o $@ + +check: $(OBJECTS) + +clean: + @-$(RM) $(OBJECTS) $(PROGRAMS) diff --git a/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/Makefile.oss-fuzz b/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/Makefile.oss-fuzz new file mode 100644 index 000000000..c100fa73c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/Makefile.oss-fuzz @@ -0,0 +1,15 @@ +# -*- Mode: Makefile for OSS-Fuzz checks -*- + +top_builddir=../.. +top_srcdir=../.. + +LDLIBS+=-lFuzzingEngine +export LDLIBS + +.PHONY: oss-fuzz clean + +oss-fuzz: + $(MAKE) -f Makefile.ci + +clean: + $(MAKE) -f Makefile.ci clean diff --git a/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/pdu_parse_target.c b/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/pdu_parse_target.c new file mode 100644 index 000000000..f1cea993c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/pdu_parse_target.c @@ -0,0 +1,23 @@ +#include + +/* Declare prototype for internal function coap_pdu_encode_header() */ +size_t coap_pdu_encode_header(coap_pdu_t *, coap_proto_t); + +int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + coap_pdu_t *pdu = coap_pdu_init(0, 0, 0, size); + if (pdu) { + coap_set_log_level(LOG_DEBUG); + if (coap_pdu_parse(COAP_PROTO_UDP, data, size, pdu)) { + coap_string_t *query = coap_get_query(pdu); + coap_string_t *uri_path = coap_get_uri_path(pdu); + coap_show_pdu(LOG_DEBUG, pdu); + coap_pdu_encode_header(pdu, COAP_PROTO_UDP); + + coap_delete_string(query); + coap_delete_string(uri_path); + } + coap_delete_pdu(pdu); + } + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/split_uri_target.c b/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/split_uri_target.c new file mode 100644 index 000000000..7a8d07057 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/oss-fuzz/split_uri_target.c @@ -0,0 +1,8 @@ +#include + +int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + coap_uri_t uri; + coap_split_uri(data, size, &uri); + return 0; +} diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_common.h.in b/examples/espidf-coap-server/components/libcoap/tests/test_common.h.in new file mode 100644 index 000000000..4d3dcd311 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_common.h.in @@ -0,0 +1,12 @@ +/* libcoap unit tests common include + * + * Copyright (C) 2021 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "coap@LIBCOAP_API_VERSION@/coap_internal.h" + diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_encode.c b/examples/espidf-coap-server/components/libcoap/tests/test_encode.c new file mode 100644 index 000000000..f9092d636 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_encode.c @@ -0,0 +1,266 @@ +/* libcoap unit tests + * + * Copyright (C) 2019 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "test_common.h" +#include "test_encode.h" + +#include +#include +#include + +/************************************************************************ + ** decoder tests + ************************************************************************/ + +static void +t_decode1(void) { + const coap_binary_t teststr = { 0, NULL }; + unsigned int result; + + result = coap_decode_var_bytes(teststr.s, teststr.length); + + CU_ASSERT(result == 0); +} + +static void +t_decode2(void) { + uint8_t data[] = { 0x01 }; + coap_binary_t teststr = { sizeof(data), data }; + unsigned int result; + + result = coap_decode_var_bytes8(teststr.s, teststr.length); + + CU_ASSERT(result == 1); +} + +static void +t_decode3(void) { + uint8_t data[] = { 0x01, 0x00, 0x00, 0x00 }; + coap_binary_t teststr = { sizeof(data), data }; + unsigned int result; + + result = coap_decode_var_bytes(teststr.s, teststr.length); + + CU_ASSERT(result == 0x01000000); +} + +static void +t_decode4(void) { + uint8_t data[] = { 0x05, 0x06, 0x07, 0x08 }; + coap_binary_t teststr = { sizeof(data), data }; + unsigned int result; + + result = coap_decode_var_bytes(teststr.s, teststr.length); + + CU_ASSERT(result == 0x05060708); +} + +static void +t_decode5(void) { + const coap_binary_t teststr = { 0, NULL }; + uint64_t result; + + result = coap_decode_var_bytes8(teststr.s, teststr.length); + + CU_ASSERT(result == 0); +} + +static void +t_decode6(void) { + uint8_t data[] = { 0x01 }; + coap_binary_t teststr = { sizeof(data), data }; + uint64_t result; + + result = coap_decode_var_bytes8(teststr.s, teststr.length); + + CU_ASSERT(result == 1); +} + +static void +t_decode7(void) { + uint8_t data[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + coap_binary_t teststr = { sizeof(data), data }; + uint64_t result; + + result = coap_decode_var_bytes8(teststr.s, teststr.length); + + CU_ASSERT(result == 0x0100000000000000); +} + +static void +t_decode8(void) { + uint8_t data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + coap_binary_t teststr = { sizeof(data), data }; + uint64_t result; + + result = coap_decode_var_bytes8(teststr.s, teststr.length); + + CU_ASSERT(result == 0x0102030405060708); +} + +/************************************************************************ + ** encoder tests + ************************************************************************/ + +static void +t_encode1(void) { + uint8_t buf[16]; + uint8_t data[] = { 0x00 }; + unsigned int result; + + result = coap_encode_var_safe(buf, sizeof(buf), 0x00); + + CU_ASSERT(result == 0); + + CU_ASSERT(memcmp(buf, data, result) == 0); +} + +static void +t_encode2(void) { + uint8_t buf[16]; + uint8_t data[] = { 0x01 }; + unsigned int result; + + result = coap_encode_var_safe(buf, sizeof(buf), 0x01); + + CU_ASSERT(result == sizeof(data)); + + CU_ASSERT(memcmp(buf, data, result) == 0); +} + +static void +t_encode3(void) { + uint8_t buf[16]; + uint8_t data[] = { 0x05, 0x06, 0x07, 0x08 }; + unsigned int result; + + result = coap_encode_var_safe8(buf, sizeof(buf), 0x05060708); + + CU_ASSERT(result == sizeof(data)); + + CU_ASSERT(memcmp(buf, data, result) == 0); +} + +static void +t_encode4(void) { + unsigned int result = 0; + /* This check will abort the program if configured with --enable-assert */ +#ifdef NDEBUG + uint8_t buf[16]; + result = coap_encode_var_safe(buf, 2, 0x01020304); +#endif /* NDEBUG */ + CU_ASSERT(result == 0); +} + +static void +t_encode5(void) { + uint8_t buf[16]; + uint8_t data[] = { 0x00 }; + unsigned int result; + + result = coap_encode_var_safe8(buf, sizeof(buf), 0x00); + + CU_ASSERT(result == 0); + + CU_ASSERT(memcmp(buf, data, result) == 0); +} + +static void +t_encode6(void) { + uint8_t buf[16]; + uint8_t data[] = { 0x01 }; + unsigned int result; + + result = coap_encode_var_safe8(buf, sizeof(buf), 0x01); + + CU_ASSERT(result == sizeof(data)); + + CU_ASSERT(memcmp(buf, data, result) == 0); +} + +static void +t_encode7(void) { + uint8_t buf[16]; + uint8_t data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + unsigned int result; + + result = coap_encode_var_safe8(buf, sizeof(buf), 0x0102030405060708); + + CU_ASSERT(result == sizeof(data)); + + CU_ASSERT(memcmp(buf, data, result) == 0); +} + +static void +t_encode8(void) { + unsigned int result = 0; + /* This check will abort the program if configured with --enable-assert */ +#ifdef NDEBUG + uint8_t buf[16]; + result = coap_encode_var_safe8(buf, 2, 0x0102030405060708); +#endif /* NDEBUG */ + CU_ASSERT(result == 0); +} + +/************************************************************************ + ** initialization + ************************************************************************/ + +CU_pSuite +t_init_encode_tests(void) { + CU_pSuite suite[5]; + + suite[0] = CU_add_suite("byte value decoder", NULL, NULL); + if (!suite[0]) { /* signal error */ + fprintf(stderr, "W: cannot add byte value decoder test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + +#define DECODE_TEST(n,s) \ + if (!CU_add_test(suite[0], s, t_decode##n)) { \ + fprintf(stderr, "W: cannot add decoder test (%s)\n", \ + CU_get_error_msg()); \ + } + + DECODE_TEST(1, "decode value #1"); + DECODE_TEST(2, "decode value #2"); + DECODE_TEST(3, "decode value #3"); + DECODE_TEST(4, "decode value #4"); + DECODE_TEST(5, "decode value #5"); + DECODE_TEST(6, "decode value #6"); + DECODE_TEST(7, "decode value #7"); + DECODE_TEST(8, "decode value #8"); + + if ((suite[1] = CU_add_suite("byte value encoder", NULL, NULL))) { +#define ENCODE_TEST(n,s) \ + if (!CU_add_test(suite[1], s, t_encode##n)) { \ + fprintf(stderr, "W: cannot add encoder test (%s)\n", \ + CU_get_error_msg()); \ + } + + ENCODE_TEST(1, "encode value #1"); + ENCODE_TEST(2, "encode value #2"); + ENCODE_TEST(3, "encode value #3"); + ENCODE_TEST(4, "encode value #4"); + ENCODE_TEST(5, "encode value #5"); + ENCODE_TEST(6, "encode value #6"); + ENCODE_TEST(7, "encode value #7"); + ENCODE_TEST(8, "encode value #8"); + + } else { + fprintf(stderr, "W: cannot add byte value encoder test suite (%s)\n", + CU_get_error_msg()); + } + + return suite[0]; +} + diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_encode.h b/examples/espidf-coap-server/components/libcoap/tests/test_encode.h new file mode 100644 index 000000000..2db380cde --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_encode.h @@ -0,0 +1,13 @@ +/* libcoap unit tests + * + * Copyright (C) 2019 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_encode_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_error_response.c b/examples/espidf-coap-server/components/libcoap/tests/test_error_response.c new file mode 100644 index 000000000..80e925cb3 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_error_response.c @@ -0,0 +1,366 @@ +/* libcoap unit tests + * + * Copyright (C) 2013,2015 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "test_common.h" +#include "test_error_response.h" + +#include +#include +#include +#include + +static coap_pdu_t *pdu; /* Holds the request PDU for most tests */ +static coap_opt_filter_t opts; /* option filter used for generating responses */ + +/************************************************************************ + ** PDU decoder + ************************************************************************/ + +/* FIXME: handle COAP_ERROR_PHRASE_LENGTH == 0 */ + +static void +t_error_response1(void) { + uint8_t teststr[] = { + 0x60, 0x80, 0x12, 0x34, 0xff, 'B', 'a', 'd', + ' ', 'R', 'e', 'q', 'u', 'e', 's', 't' + }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->type = COAP_MESSAGE_CON; + pdu->mid = 0x1234; + + /* result = coap_add_token(pdu, 5, (unsigned char *)"token"); */ + coap_option_filter_clear(&opts); + response = coap_new_error_response(pdu, COAP_RESPONSE_CODE(400), &opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->used_size == sizeof(teststr) - 4); + CU_ASSERT(response->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->token_length == 0); + CU_ASSERT(response->code == 0x80); + CU_ASSERT(response->mid == 0x1234); + CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); + coap_delete_pdu(response); +} + +static void +t_error_response2(void) { + uint8_t teststr[] = { + 0x55, 0x84, 0x12, 0x34, 't', 'o', 'k', 'e', + 'n', 0xff, 'N', 'o', 't', ' ', 'F', 'o', + 'u', 'n', 'd' + }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->type = COAP_MESSAGE_NON; + pdu->mid = 0x1234; + coap_add_token(pdu, 5, (const uint8_t *)"token"); + coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (const uint8_t *)"time"); + + coap_option_filter_clear(&opts); + response = coap_new_error_response(pdu, COAP_RESPONSE_CODE(404), &opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->used_size == sizeof(teststr) - 4); + CU_ASSERT(response->type == COAP_MESSAGE_NON); + CU_ASSERT(response->token_length == 5); + CU_ASSERT(response->code == 0x84); + CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); + coap_delete_pdu(response); +} + +static void +t_error_response3(void) { + const uint8_t code = COAP_RESPONSE_CODE(402); + uint8_t teststr[] = { + 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', + 'n', 0xd0, 0x0c, 0xff, 'B', 'a', 'd', ' ', 'O', + 'p', 't', 'i', 'o', 'n' + }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (const uint8_t *)"token"); + /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (const uint8_t *)"time"); */ + + /* unknown critical option 25 */ + coap_add_option(pdu, 25, 0, NULL); + + coap_option_filter_clear(&opts); + coap_option_filter_set(&opts, 25); + response = coap_new_error_response(pdu, code, &opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->used_size == sizeof(teststr) - 4); + CU_ASSERT(response->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->token_length == 5); + CU_ASSERT(response->code == code); + CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); + coap_delete_pdu(response); +} + +static void +t_error_response4(void) { + const uint8_t code = COAP_RESPONSE_CODE(402); + unsigned char optval[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b + }; + uint8_t teststr[] = { + 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', + 'n', 0xdc, 0x0c, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0xff, 'B', + 'a', 'd', ' ', 'O', 'p', 't', 'i', 'o', + 'n' + }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (const uint8_t *)"token"); + /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (const uint8_t *)"time"); */ + + /* unknown critical option 25 */ + coap_add_option(pdu, 25, sizeof(optval), optval); + + coap_option_filter_clear(&opts); + coap_option_filter_set(&opts, 25); + response = coap_new_error_response(pdu, code, &opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->used_size == sizeof(teststr) - 4); + CU_ASSERT(response->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->token_length == 5); + CU_ASSERT(response->code == code); + CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); + coap_delete_pdu(response); +} + +static void +t_error_response5(void) { + const uint8_t code = COAP_RESPONSE_CODE(402); + unsigned char optval[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12 + }; + uint8_t teststr[] = { + 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', + 'n', 0xdd, 0x0c, 0x06, 0x00, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0xff, 'B', + 'a', 'd', ' ', 'O', 'p', 't', 'i', 'o', + 'n' + }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (const uint8_t *)"token"); + /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (const uint8_t *)"time"); */ + + /* unknown critical option 25 */ + coap_add_option(pdu, 25, sizeof(optval), optval); + + coap_option_filter_clear(&opts); + coap_option_filter_set(&opts, 25); + response = coap_new_error_response(pdu, code, &opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->used_size == sizeof(teststr) - 4); + CU_ASSERT(response->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->token_length == 5); + CU_ASSERT(response->code == code); + CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); + coap_delete_pdu(response); +} + +static void +t_error_response6(void) { + const uint8_t code = COAP_RESPONSE_CODE(402); + unsigned char optval[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12 + }; + uint8_t teststr[] = { + 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', + 'n', 0xdd, 0x0a, 0x06, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0xff, + 'B', 'a', 'd', ' ', 'O', 'p', 't', 'i', + 'o', 'n' + }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (const uint8_t *)"token"); + /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (const uint8_t *)"time"); */ + + /* unknown critical option 23 */ + coap_add_option(pdu, 23, sizeof(optval), optval); + + coap_option_filter_clear(&opts); + coap_option_filter_set(&opts, 23); + response = coap_new_error_response(pdu, code, &opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->used_size == sizeof(teststr) - 4); + CU_ASSERT(response->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->token_length == 5); + CU_ASSERT(response->code == code); + CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); + coap_delete_pdu(response); +} + +static void +t_error_response7(void) { + const uint8_t code = COAP_RESPONSE_CODE(402); + unsigned char optval[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12 + }; + uint8_t teststr[] = { + 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', + 'n', 0xdd, 0x0a, 0x06, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0xff, + 'B', 'a', 'd', ' ', 'O', 'p', 't', 'i', + 'o', 'n' + }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (const uint8_t *)"token"); + /* known option 11 */ + coap_add_option(pdu, 11, 4, (const uint8_t *)"time"); + + /* unknown critical option 23 */ + coap_add_option(pdu, 23, sizeof(optval), optval); + + coap_option_filter_clear(&opts); + coap_option_filter_set(&opts, 23); + response = coap_new_error_response(pdu, code, &opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->used_size == sizeof(teststr) - 4); + CU_ASSERT(response->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->token_length == 5); + CU_ASSERT(response->code == code); + CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); + coap_delete_pdu(response); +} + +static void +t_error_response8(void) { + const uint8_t code = COAP_RESPONSE_CODE(503); + uint8_t teststr[] = { + 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', + 'n', 0xe0, 0x02, 0xdc, 0xd0, 0x00, 0xff, 'S', + 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'U', + 'n', 'a', 'v', 'a', 'i', 'l', 'a', 'b', + 'l', 'e' + }; + coap_pdu_t *response; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->type = COAP_MESSAGE_CON; + coap_add_token(pdu, 5, (const uint8_t *)"token"); + /* known option 1000 */ + coap_add_option(pdu, 1000, 0, NULL); + + /* unknown options 1001 and 1014 */ + coap_add_option(pdu, 1001, 0, NULL); + coap_add_option(pdu, 1014, 0, NULL); + + /* known option 2000 */ + coap_add_option(pdu, 2000, 0, NULL); + + coap_option_filter_clear(&opts); + coap_option_filter_set(&opts, 1001); + coap_option_filter_set(&opts, 1014); + response = coap_new_error_response(pdu, code, &opts); + + CU_ASSERT_PTR_NOT_NULL(response); + + CU_ASSERT(response->used_size == sizeof(teststr) - 4); + CU_ASSERT(response->type == COAP_MESSAGE_ACK); + CU_ASSERT(response->token_length == 5); + CU_ASSERT(response->code == code); + CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); + coap_delete_pdu(response); +} + +static int +t_error_response_tests_create(void) { + pdu = coap_pdu_init(0, 0, 0, COAP_DEFAULT_MTU); + + return pdu == NULL; +} + +static int +t_error_response_tests_remove(void) { + coap_delete_pdu(pdu); + return 0; +} + +CU_pSuite +t_init_error_response_tests(void) { + CU_pSuite suite[1]; + + suite[0] = CU_add_suite("error response generator", + t_error_response_tests_create, + t_error_response_tests_remove); + if (!suite[0]) { /* signal error */ + fprintf(stderr, "W: cannot add error response generator test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + +#define ERROR_RESPONSE_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add error response generator test (%s)\n", \ + CU_get_error_msg()); \ + } + + ERROR_RESPONSE_TEST(suite[0], t_error_response1); + ERROR_RESPONSE_TEST(suite[0], t_error_response2); + ERROR_RESPONSE_TEST(suite[0], t_error_response3); + ERROR_RESPONSE_TEST(suite[0], t_error_response4); + ERROR_RESPONSE_TEST(suite[0], t_error_response5); + ERROR_RESPONSE_TEST(suite[0], t_error_response6); + ERROR_RESPONSE_TEST(suite[0], t_error_response7); + ERROR_RESPONSE_TEST(suite[0], t_error_response8); + + return suite[0]; +} + diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_error_response.h b/examples/espidf-coap-server/components/libcoap/tests/test_error_response.h new file mode 100644 index 000000000..4a0af6303 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_error_response.h @@ -0,0 +1,13 @@ +/* libcoap unit tests + * + * Copyright (C) 2013 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_error_response_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_options.c b/examples/espidf-coap-server/components/libcoap/tests/test_options.c new file mode 100644 index 000000000..9da965d01 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_options.c @@ -0,0 +1,1049 @@ +/* libcoap unit tests + * + * Copyright (C) 2012,2015 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "test_common.h" +#include "test_options.h" + +#include +#include +#include + +/************************************************************************ + ** decoder tests + ************************************************************************/ + +static void +t_parse_option1(void) { + /* delta == 0, length == 0, value == 0 */ + coap_str_const_t teststr = { 1, (const uint8_t *)"" }; + + size_t result; + coap_option_t option; + + /* result = coap_opt_parse(teststr.s, teststr.s + teststr.length, &option); */ + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 1); + CU_ASSERT(option.delta == 0); + CU_ASSERT(option.length == 0); + /* FIXME: value? */ +} + +static void +t_parse_option2(void) { + /* delta == 12, length == 1, value == 0 */ + coap_str_const_t teststr = { 2, (const uint8_t *)"\xc1" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 2); + CU_ASSERT(option.delta == 12); + CU_ASSERT(option.length == 1); + CU_ASSERT(option.value == teststr.s + 1); +} + +static void +t_parse_option3(void) { + /* delta == 3, length == 12, value == 0 */ + coap_str_const_t teststr = { 13, (const uint8_t *)"\x3c\x00\x01\x02\x03\x04" + "\x05\x06\x07\x08\x09\x0a\x0b" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 13); + CU_ASSERT(option.delta == 3); + CU_ASSERT(option.length == 12); + CU_ASSERT(option.value == teststr.s + 1); + /* CU_ASSERT(memcmp(option.value, teststr.s + 1, 12) == 0); */ +} + +static void +t_parse_option4(void) { + /* delta == 15, length == 3, value == 0 */ + coap_str_const_t teststr = { 2, (const uint8_t *)"\xf3" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +static void +t_parse_option5(void) { + /* delta == 3, length == 15, value == 0 */ + coap_str_const_t teststr = { 2, (const uint8_t *)"\x3f" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +static void +t_parse_option6(void) { + /* delta == 15, length == 15 */ + coap_str_const_t teststr = { 1, (const uint8_t *)"\xff" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +static void +t_parse_option7(void) { + /* delta == 20, length == 0 */ + coap_str_const_t teststr = { 2, (const uint8_t *)"\xd0\x07" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 2); + CU_ASSERT(option.delta == 20); + CU_ASSERT(option.length == 0); +} + +static void +t_parse_option8(void) { + /* delta == 780, length == 0 */ + coap_str_const_t teststr = { 3, (const uint8_t *)"\xe0\x01\xff" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 3); + CU_ASSERT(option.delta == 780); + CU_ASSERT(option.length == 0); +} + +static void +t_parse_option9(void) { + /* delta == 65535, length == 0 */ + coap_str_const_t teststr = { 3, (const uint8_t *)"\xe0\xfe\xf2" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 3); + CU_ASSERT(option.delta == 65535); +} + +static void +t_parse_option10(void) { + /* delta > 65535 (illegal), length == 0 */ + coap_str_const_t teststr = { 3, (const uint8_t *)"\xe0\xff\xff" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +static void +t_parse_option11(void) { + /* illegal delta value (option too short) */ + coap_str_const_t teststr = { 1, (const uint8_t *)"\xd0" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +static void +t_parse_option12(void) { + /* delta == 280, length == 500 */ + coap_str_const_t teststr = { 3, (const uint8_t *)"\xee\xff\x0b" }; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == 0); +} + +static void +t_parse_option13(void) { + /* delta == 280, length == 500 */ + unsigned char _data[505]; + coap_string_t teststr = { sizeof(_data), _data }; + teststr.s[0] = 0xee; + teststr.s[1] = 0x00; + teststr.s[2] = 0x0b; + teststr.s[3] = 0x00; + teststr.s[4] = 0xe7; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(teststr.s, teststr.length, &option); + CU_ASSERT(result == sizeof(_data)); + CU_ASSERT(option.delta == 280); + CU_ASSERT(option.length == 500); + CU_ASSERT(option.value == &_data[5]); +} + +static void +t_parse_option14(void) { + /* delta == 268, length == 65535 */ + unsigned char *data; + unsigned int length = 4 + 65535; + + data = (unsigned char *)malloc(length); + if (!data) { + CU_FAIL("internal error in test framework -- insufficient memory\n"); + return; + } + + data[0] = 0xde; + data[1] = 0xff; + data[2] = 0xfe; + data[3] = 0xf2; + + size_t result; + coap_option_t option; + + result = coap_opt_parse(data, length, &option); + CU_ASSERT(result == length); + CU_ASSERT(option.delta == 268); + CU_ASSERT(option.length == 65535); + CU_ASSERT(option.value == &data[4]); + free(data); +} + +/************************************************************************ + ** encoder tests + ************************************************************************/ + +static void +t_encode_option1(void) { + char teststr[] = { 0x00 }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 0, 0); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +static void +t_encode_option2(void) { + uint8_t teststr[] = { 0x5d, 0xff }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 5, 268); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +static void +t_encode_option3(void) { + uint8_t teststr[] = { 0xd1, 0x01 }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 14, 1); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +static void +t_encode_option4(void) { + uint8_t teststr[] = { 0xdd, 0xff, 0xab }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 268, 184); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +static void +t_encode_option5(void) { + uint8_t teststr[] = { 0xed, 0x13, 0x00, 0xff }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 5133, 268); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +static void +t_encode_option6(void) { + uint8_t teststr[] = { 0xee, 0xfe, 0xf2, 0xfe, 0xf2 }; + unsigned char buf[40]; + size_t result; + + result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 65535, 65535); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +static void +t_encode_option7(void) { + uint8_t teststr[] = { 0x35, 'v', 'a', 'l', 'u', 'e' }; + const size_t valoff = 1; + unsigned char buf[40]; + size_t result; + + result = coap_opt_encode((coap_opt_t *)buf, sizeof(buf), 3, + (unsigned char *)teststr + valoff, + sizeof(teststr) - valoff); + + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +static void +t_encode_option8(void) { + /* value does not fit in message buffer */ + unsigned char buf[40]; + size_t result; + + result = coap_opt_encode((coap_opt_t *)buf, 8, 15, + (const uint8_t *)"something", 9); + + CU_ASSERT(result == 0); + + result = coap_opt_encode((coap_opt_t *)buf, 1, 15, + (const uint8_t *)"something", 9); + + CU_ASSERT(result == 0); +} + +static void +t_encode_option9(void) { + uint8_t teststr[] = { 0xe1, 0x00, 0x00 }; + unsigned char buf[40] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + size_t result; + + result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 269, 1); + CU_ASSERT(result == sizeof(teststr)); + + CU_ASSERT(memcmp(buf, teststr, result) == 0); +} + +/************************************************************************ + ** accessor tests + ************************************************************************/ + +static void +t_access_option1(void) { + const uint8_t teststr[] = { 0x12, 'a', 'b' }; + coap_option_t opt; + + CU_ASSERT(sizeof(teststr) == coap_opt_parse((const coap_opt_t *)teststr, + sizeof(teststr), &opt)); + CU_ASSERT(opt.delta == 1); + CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 2); + CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), teststr + 1); + CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == sizeof(teststr)); +} + +static void +t_access_option2(void) { + const uint8_t teststr[] = { 0xe2, 0x18, 0xfd, 'a', 'b' }; + coap_option_t opt; + + CU_ASSERT(sizeof(teststr) == coap_opt_parse((const coap_opt_t *)teststr, + sizeof(teststr), &opt)); + CU_ASSERT(opt.delta == 6666); + CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 2); + CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), teststr + 3); + CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == sizeof(teststr)); +} + +static void +t_access_option3(void) { + const uint8_t teststr[] = { 0xed, 0x18, 0x0a, 0x00, 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm' + }; + coap_option_t opt; + + CU_ASSERT(sizeof(teststr) == coap_opt_parse((const coap_opt_t *)teststr, + sizeof(teststr), &opt)); + CU_ASSERT(opt.delta == 6423); + CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 13); + CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), teststr + 4); + CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == sizeof(teststr)); +} + +static void +t_access_option4(void) { + const uint8_t teststr[] = { 0xde, 0xff, 0xfe, 0xf2, 'a', 'b', 'c' }; + coap_option_t opt; + + CU_ASSERT(0 == coap_opt_parse((const coap_opt_t *)teststr, + sizeof(teststr), &opt)); + CU_ASSERT(opt.delta == 268); + CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 65535); + CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), teststr + 4); + CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == 65535 + 4); +} + +static void +t_access_option5(void) { + const uint8_t teststr[] = { 0xee, 0xfe, 0xf2, 0x00, 0xdd, 'a', 'b', 'c' }; + coap_option_t opt; + + CU_ASSERT(0 == coap_opt_parse((const coap_opt_t *)teststr, + sizeof(teststr), &opt)); + CU_ASSERT(opt.delta == 65535); + CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 490); + CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), teststr + 5); + CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == 495); +} + +static void +t_access_option6(void) { + coap_log_t level = coap_get_log_level(); + const uint8_t teststr[] = { 0xf2, 'a', 'b' }; + coap_option_t opt; + + coap_set_log_level(LOG_CRIT); + + CU_ASSERT(0 == coap_opt_parse((const coap_opt_t *)teststr, + sizeof(teststr), &opt)); + coap_set_log_level(level); + CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 0); + CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), NULL); + CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == 0); +} + +static void +t_access_option7(void) { + const uint8_t teststr[] = { 0x2f, 'a', 'b' }; + coap_option_t opt; + + CU_ASSERT(0 == coap_opt_parse((const coap_opt_t *)teststr, + sizeof(teststr), &opt)); + CU_ASSERT(opt.delta == 2); + CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 0); + CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), NULL); + CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == 0); +} + +/************************************************************************ + ** accessor tests + ************************************************************************/ + +#define TEST_MAX_SIZE 1000 + +#ifdef _MSC_VER +# define ALIGNED(x) +#else +# define ALIGNED(x) __attribute__ ((aligned (x))) +#endif + +static void +t_iterate_option1(void) { + /* CoAP PDU without token, options, or data */ + uint8_t teststr[] ALIGNED(8) = { + 0x00, 0x00, 0x00, 0x00 + }; + + coap_pdu_t pdu = { + .max_size = TEST_MAX_SIZE, + .token = teststr, + .used_size = 0 + }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + + result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); + + CU_ASSERT(result == NULL); + CU_ASSERT(oi.bad == 1); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT(option == NULL); +} + +static void +t_iterate_option2(void) { + /* CoAP PDU with token but without options and data */ + uint8_t teststr[3] ALIGNED(8) = { + 't', 'o', 'k' + }; + + coap_pdu_t pdu = { + .max_size = TEST_MAX_SIZE, + .token_length = 3, + .token = teststr, + .used_size = sizeof(teststr) + }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + + result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); + + CU_ASSERT(result == NULL); + CU_ASSERT(oi.bad == 1); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT(option == NULL); +} + +static void +t_iterate_option3(void) { + /* CoAP PDU with token and options */ + uint8_t teststr[] ALIGNED(8) = { + 't', 'o', 'k', 0x13, + 'o', 'p', 't', 0x00, 0xd1, 0x10, 'x' + }; + + coap_pdu_t pdu = { + .max_size = TEST_MAX_SIZE, + .token_length = 3, + .token = teststr, + .used_size = sizeof(teststr) + }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + + result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 1); + CU_ASSERT_PTR_EQUAL(option, teststr + 3); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 1); + CU_ASSERT_PTR_EQUAL(option, teststr + 7); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 30); + CU_ASSERT_PTR_EQUAL(option, teststr + 8); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +static void +t_iterate_option4(void) { + /* CoAP PDU with token, options, and data */ + uint8_t teststr[] ALIGNED(8) = { + 't', 'o', 'k', 0x13, + 'o', 'p', 't', 0x00, 0xd1, 0x10, 'x', 0xff, + 'd', 'a', 't', 'a' + }; + + coap_pdu_t pdu = { + .max_size = TEST_MAX_SIZE, + .token_length = 3, + .token = teststr, + .used_size = sizeof(teststr) + }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + + result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 1); + CU_ASSERT_PTR_EQUAL(option, teststr + 3); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 1); + CU_ASSERT_PTR_EQUAL(option, teststr + 7); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 30); + CU_ASSERT_PTR_EQUAL(option, teststr + 8); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +static void +t_iterate_option5(void) { + /* CoAP PDU with malformed option */ + uint8_t teststr[] ALIGNED(8) = { + 0x52, 'o', 'p', 0xee, + 0x12, 0x03, 0x00 + }; + + coap_pdu_t pdu = { + .max_size = TEST_MAX_SIZE, + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + + result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 5); + CU_ASSERT_PTR_EQUAL(option, teststr); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +static void +t_iterate_option6(void) { + /* option filter */ + /* CoAP PDU with token, options, and data */ + uint8_t teststr[] ALIGNED(8) = { + 0x80, 0x20, 0x00, 0x00, + 0xc0, 0x00 + }; + + coap_pdu_t pdu = { + .max_size = TEST_MAX_SIZE, + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + coap_opt_filter_t filter; + + coap_option_filter_clear(&filter); + coap_option_filter_set(&filter, 10); /* option nr 10 only */ + result = coap_option_iterator_init(&pdu, &oi, &filter); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 10); + CU_ASSERT_PTR_EQUAL(option, teststr + 1); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 10); + CU_ASSERT_PTR_EQUAL(option, teststr + 2); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 10); + CU_ASSERT_PTR_EQUAL(option, teststr + 3); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +static void +t_iterate_option7(void) { + /* option filter */ + uint8_t teststr[] ALIGNED(8) = { + 0x80, 0x20, 0x00, 0x00, + 0xc0, 0x00, 0x10, 0x10, 0x00 + }; + + coap_pdu_t pdu = { + .max_size = TEST_MAX_SIZE, + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + coap_opt_filter_t filter; + + /* search options nr 8 and 22 */ + coap_option_filter_clear(&filter); + coap_option_filter_set(&filter, 8); + coap_option_filter_set(&filter, 22); + result = coap_option_iterator_init(&pdu, &oi, &filter); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 8); + CU_ASSERT_PTR_EQUAL(option, teststr); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 22); + CU_ASSERT_PTR_EQUAL(option, teststr + 4); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(oi.number == 22); + CU_ASSERT_PTR_EQUAL(option, teststr + 5); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +static void +t_iterate_option8(void) { + /* option filter */ + uint8_t teststr[] ALIGNED(8) = { + 0x80, 0x20, 0x00, 0x00, + 0xc0, 0x00, 0x10, 0x10, 0x00 + }; + + coap_pdu_t pdu = { + .max_size = TEST_MAX_SIZE, + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + coap_opt_filter_t filter; + + /* search option nr 36 */ + coap_option_filter_clear(&filter); + coap_option_filter_set(&filter, 36); + result = coap_option_iterator_init(&pdu, &oi, &filter); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +static void +t_iterate_option9(void) { + /* options filter: option number too large for filter */ + uint8_t teststr[] ALIGNED(8) = { + 0x80, 0x20, 0x00, 0x00, + 0xc0, 0x00, 0x10, 0x10, 0x00 + }; + + coap_pdu_t pdu = { + .max_size = TEST_MAX_SIZE, + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + coap_opt_filter_t filter; + + /* search option nr 100 */ + coap_option_filter_clear(&filter); + coap_option_filter_set(&filter, 100); + result = coap_option_iterator_init(&pdu, &oi, &filter); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +static void +t_iterate_option10(void) { + /* options filter: option numbers in PDU exceed filter size */ + uint8_t teststr[] ALIGNED(8) = { + 0x80, 0x20, 0x00, 0x00, + 0xd0, 0x26, 0xe0, 0x10, 0x00 + }; + + coap_pdu_t pdu = { + .max_size = TEST_MAX_SIZE, + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + coap_opt_iterator_t oi, *result; + coap_opt_t *option; + coap_opt_filter_t filter; + + /* search option nr 61 */ + coap_option_filter_clear(&filter); + coap_option_filter_set(&filter, 61); + result = coap_option_iterator_init(&pdu, &oi, &filter); + + CU_ASSERT_PTR_EQUAL(result, &oi); + CU_ASSERT(oi.bad == 0); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT_PTR_EQUAL(option, teststr + 4); + + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT_PTR_EQUAL(option, NULL); +} + +/************************************************************************ + ** filter tests + ************************************************************************/ + +static void +t_filter_option1(void) { + coap_opt_filter_t filter; + + coap_option_filter_clear(&filter); + + CU_ASSERT(coap_option_filter_set(&filter, 0) == 1); + CU_ASSERT(coap_option_filter_set(&filter, 37) == 1); + CU_ASSERT(coap_option_filter_set(&filter, 37) == 1); + CU_ASSERT(coap_option_filter_set(&filter, 43) == 1); + CU_ASSERT(coap_option_filter_set(&filter, 290) == 1); + CU_ASSERT(coap_option_filter_set(&filter, 65535) == 1); + + CU_ASSERT(coap_option_filter_get(&filter, 0) == 1); + CU_ASSERT(coap_option_filter_get(&filter, 37) == 1); + CU_ASSERT(coap_option_filter_get(&filter, 43) == 1); + CU_ASSERT(coap_option_filter_get(&filter, 290) == 1); + CU_ASSERT(coap_option_filter_get(&filter, 65535) == 1); + + CU_ASSERT(coap_option_filter_unset(&filter, 37) == 1); + + CU_ASSERT(coap_option_filter_get(&filter, 0) == 1); + CU_ASSERT(coap_option_filter_get(&filter, 43) == 1); + CU_ASSERT(coap_option_filter_get(&filter, 290) == 1); + CU_ASSERT(coap_option_filter_get(&filter, 65535) == 1); + + CU_ASSERT(coap_option_filter_get(&filter, 37) == 0); + CU_ASSERT(coap_option_filter_get(&filter, 89) == 0); +} + +static void +t_filter_option2(void) { + coap_opt_filter_t filter; + int s; + + coap_option_filter_clear(&filter); + + /* fill all COAP_OPT_FILTER_SHORT slots */ + for (s = 0; s < COAP_OPT_FILTER_SHORT; s++) { + CU_ASSERT(coap_option_filter_set(&filter, s)); + } + + /* adding a short option type must fail */ + CU_ASSERT(coap_option_filter_set(&filter, COAP_OPT_FILTER_SHORT) == 0); + + /* adding a long option type must succeed */ + CU_ASSERT(coap_option_filter_set(&filter, 256) == 1); +} + +static void +t_filter_option3(void) { + coap_opt_filter_t filter; + int l; + + coap_option_filter_clear(&filter); + + /* set COAP_OPT_FILTER_LONG long filters */ + for (l = 0; l < COAP_OPT_FILTER_LONG; l++) { + CU_ASSERT(coap_option_filter_set(&filter, 256 + l) == 1); + } + + /* the next must fail and must not be found */ + CU_ASSERT(coap_option_filter_set(&filter, 256 + COAP_OPT_FILTER_LONG) == 0); + CU_ASSERT(coap_option_filter_get(&filter, 256 + COAP_OPT_FILTER_LONG) == 0); + + /* remove one item */ + CU_ASSERT(coap_option_filter_unset(&filter, 256) == 1); + CU_ASSERT(coap_option_filter_get(&filter, 256) == 0); + + /* now, storing a new filter must succeed */ + CU_ASSERT(coap_option_filter_set(&filter, 256 + COAP_OPT_FILTER_LONG) == 1); + CU_ASSERT(coap_option_filter_get(&filter, 256 + COAP_OPT_FILTER_LONG) == 1); + + /* and all other items must be available as well */ + for (l = 0; l < COAP_OPT_FILTER_LONG; l++) { + CU_ASSERT(coap_option_filter_get(&filter, 256 + l + 1) == 1); + } + + /* set COAP_OPT_FILTER_SHORT short filters */ + for (l = 0; l < COAP_OPT_FILTER_SHORT; l++) { + CU_ASSERT(coap_option_filter_set(&filter, l) == 1); + } + + /* the next must fail and must not be found */ + CU_ASSERT(coap_option_filter_set(&filter, COAP_OPT_FILTER_SHORT) == 0); + CU_ASSERT(coap_option_filter_get(&filter, COAP_OPT_FILTER_SHORT) == 0); + + /* remove one item */ + CU_ASSERT(coap_option_filter_unset(&filter, 0) == 1); + CU_ASSERT(coap_option_filter_get(&filter, 0) == 0); + + /* now, storing a new filter must succeed */ + CU_ASSERT(coap_option_filter_set(&filter, COAP_OPT_FILTER_SHORT) == 1); + CU_ASSERT(coap_option_filter_get(&filter, COAP_OPT_FILTER_SHORT) == 1); + + /* and all other items must be available as well */ + for (l = 0; l < COAP_OPT_FILTER_SHORT; l++) { + CU_ASSERT(coap_option_filter_get(&filter, l + 1) == 1); + } +} + +/************************************************************************ + ** initialization + ************************************************************************/ + +CU_pSuite +t_init_option_tests(void) { + CU_pSuite suite[5]; + + suite[0] = CU_add_suite("option parser", NULL, NULL); + if (!suite[0]) { /* signal error */ + fprintf(stderr, "W: cannot add option parser test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + +#define OPTION_TEST(n,s) \ + if (!CU_add_test(suite[0], s, t_parse_option##n)) { \ + fprintf(stderr, "W: cannot add option parser test (%s)\n", \ + CU_get_error_msg()); \ + } + + OPTION_TEST(1, "parse option #1"); + OPTION_TEST(2, "parse option #2"); + OPTION_TEST(3, "parse option #3"); + OPTION_TEST(4, "parse option #4"); + OPTION_TEST(5, "parse option #5"); + OPTION_TEST(6, "parse option #6"); + OPTION_TEST(7, "parse option #7"); + OPTION_TEST(8, "parse option #8"); + OPTION_TEST(9, "parse option #9"); + OPTION_TEST(10, "parse option #10"); + OPTION_TEST(11, "parse option #11"); + OPTION_TEST(12, "parse option #12"); + OPTION_TEST(13, "parse option #13"); + OPTION_TEST(14, "parse option #14"); + + if ((suite[1] = CU_add_suite("option encoder", NULL, NULL))) { +#define OPTION_ENCODER_TEST(n,s) \ + if (!CU_add_test(suite[1], s, t_encode_option##n)) { \ + fprintf(stderr, "W: cannot add option encoder test (%s)\n", \ + CU_get_error_msg()); \ + } + + OPTION_ENCODER_TEST(1, "encode option #1"); + OPTION_ENCODER_TEST(2, "encode option #2"); + OPTION_ENCODER_TEST(3, "encode option #3"); + OPTION_ENCODER_TEST(4, "encode option #4"); + OPTION_ENCODER_TEST(5, "encode option #5"); + OPTION_ENCODER_TEST(6, "encode option #6"); + OPTION_ENCODER_TEST(7, "encode option #7"); + OPTION_ENCODER_TEST(8, "encode option #8"); + OPTION_ENCODER_TEST(9, "encode option #9"); + + } else { + fprintf(stderr, "W: cannot add option encoder test suite (%s)\n", + CU_get_error_msg()); + } + + if ((suite[2] = CU_add_suite("option accessors", NULL, NULL))) { +#define OPTION_ACCESSOR_TEST(n,s) \ + if (!CU_add_test(suite[2], s, t_access_option##n)) { \ + fprintf(stderr, "W: cannot add option accessor function test (%s)\n", \ + CU_get_error_msg()); \ + } + + OPTION_ACCESSOR_TEST(1, "access option #1"); + OPTION_ACCESSOR_TEST(2, "access option #2"); + OPTION_ACCESSOR_TEST(3, "access option #3"); + OPTION_ACCESSOR_TEST(4, "access option #4"); + OPTION_ACCESSOR_TEST(5, "access option #5"); + OPTION_ACCESSOR_TEST(6, "access option #6"); + OPTION_ACCESSOR_TEST(7, "access option #7"); + + } else { + fprintf(stderr, "W: cannot add option acessor function test suite (%s)\n", + CU_get_error_msg()); + } + + if ((suite[3] = CU_add_suite("option iterator", NULL, NULL))) { +#define OPTION_ITERATOR_TEST(n,s) \ + if (!CU_add_test(suite[3], s, t_iterate_option##n)) { \ + fprintf(stderr, "W: cannot add option iterator test (%s)\n", \ + CU_get_error_msg()); \ + } + + OPTION_ITERATOR_TEST(1, "option iterator #1"); + OPTION_ITERATOR_TEST(2, "option iterator #2"); + OPTION_ITERATOR_TEST(3, "option iterator #3"); + OPTION_ITERATOR_TEST(4, "option iterator #4"); + OPTION_ITERATOR_TEST(5, "option iterator #5"); + OPTION_ITERATOR_TEST(6, "option iterator #6"); + OPTION_ITERATOR_TEST(7, "option iterator #7"); + OPTION_ITERATOR_TEST(8, "option iterator #8"); + OPTION_ITERATOR_TEST(9, "option iterator #9"); + OPTION_ITERATOR_TEST(10, "option iterator #10"); + + } else { + fprintf(stderr, "W: cannot add option iterator test suite (%s)\n", + CU_get_error_msg()); + } + + if ((suite[4] = CU_add_suite("option filter", NULL, NULL))) { +#define OPTION_FILTER_TEST(n,s) \ + if (!CU_add_test(suite[4], s, t_filter_option##n)) { \ + fprintf(stderr, "W: cannot add option filter test (%s)\n", \ + CU_get_error_msg()); \ + } + + OPTION_FILTER_TEST(1, "option filter #1"); + OPTION_FILTER_TEST(2, "option filter #2"); + OPTION_FILTER_TEST(3, "option filter #3"); + + } else { + fprintf(stderr, "W: cannot add option filter test suite (%s)\n", + CU_get_error_msg()); + } + + return suite[0]; +} + diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_options.h b/examples/espidf-coap-server/components/libcoap/tests/test_options.h new file mode 100644 index 000000000..d30af7f12 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_options.h @@ -0,0 +1,19 @@ +/* libcoap unit tests + * + * Copyright (C) 2012 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +/** Asserts that const pointers actual == expected. + * Reports failure with no other action. + */ +#define CU_ASSERT_PTR_EQUAL_C(actual, expected) \ + { CU_assertImplementation(((const void*)(actual) == (const void*)(expected)), __LINE__, ("CU_ASSERT_PTR_EQUAL(" #actual "," #expected ")"), __FILE__, "", CU_FALSE); } + +CU_pSuite t_init_option_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_pdu.c b/examples/espidf-coap-server/components/libcoap/tests/test_pdu.c new file mode 100644 index 000000000..86d71909f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_pdu.c @@ -0,0 +1,1327 @@ +/* libcoap unit tests + * + * Copyright (C) 2012,2015 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "test_common.h" +#include "test_pdu.h" + +#include +#include +#include +#include + +coap_pdu_t *pdu; /* Holds the parsed PDU for most tests */ + +/************************************************************************ + ** PDU decoder + ************************************************************************/ + +static void +t_parse_pdu1(void) { + uint8_t teststr[] = { 0x40, 0x01, 0x93, 0x34 }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); + CU_ASSERT(pdu->type == COAP_MESSAGE_CON); + CU_ASSERT(pdu->token_length == 0); + CU_ASSERT(pdu->code == COAP_REQUEST_CODE_GET); + CU_ASSERT(pdu->mid == 0x9334); + CU_ASSERT_PTR_NULL(pdu->data); +} + +static void +t_parse_pdu2(void) { + uint8_t teststr[] = { 0x55, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); + CU_ASSERT(pdu->type == COAP_MESSAGE_NON); + CU_ASSERT(pdu->token_length == 5); + CU_ASSERT(pdu->code == 0x69); + CU_ASSERT(pdu->mid == 0x1234); + CU_ASSERT(memcmp(pdu->token, teststr + 4, 5) == 0); + CU_ASSERT_PTR_NULL(pdu->data); +} + +static void +t_parse_pdu3(void) { + uint8_t teststr[] = { 0x53, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +static void +t_parse_pdu4(void) { + /* illegal token length */ + uint8_t teststr[] = { 0x59, 0x69, 0x12, 0x34, + 't', 'o', 'k', 'e', 'n', '1', '2', '3', '4' }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); + + teststr[0] = 0x5f; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +static void +t_parse_pdu5(void) { + /* PDU with options */ + uint8_t teststr[] = { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', + 'n', 0x00, 0xc1, 0x00 + }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); + CU_ASSERT(pdu->type == COAP_MESSAGE_NON); + CU_ASSERT(pdu->token_length == 5); + CU_ASSERT(pdu->code == 0x73); + CU_ASSERT(pdu->mid == 0x1234); + CU_ASSERT(memcmp(pdu->token, teststr + 4, 5) == 0); + CU_ASSERT_PTR_NULL(pdu->data); + + /* FIXME: check options */ +} + +static void +t_parse_pdu6(void) { + /* PDU with options that exceed the PDU */ + uint8_t teststr[] = { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', + 'n', 0x00, 0xc1, 0x00, 0xae, 0xf0, 0x03 + }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +static void +t_parse_pdu7(void) { + /* PDU with options and payload */ + uint8_t teststr[] = { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', + 'n', 0x00, 0xc1, 0x00, 0xff, 'p', 'a', 'y', + 'l', 'o', 'a', 'd' + }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); + CU_ASSERT(pdu->type == COAP_MESSAGE_NON); + CU_ASSERT(pdu->token_length == 5); + CU_ASSERT(pdu->code == 0x73); + CU_ASSERT(pdu->mid == 0x1234); + CU_ASSERT(memcmp(pdu->token, teststr + 4, 5) == 0); + + /* FIXME: check options */ + + CU_ASSERT(pdu->data == pdu->token + 9); + CU_ASSERT(memcmp(pdu->data, teststr + 13, 7) == 0); +} + +static void +t_parse_pdu8(void) { + /* PDU without options but with payload */ + uint8_t teststr[] = { 0x50, 0x73, 0x12, 0x34, + 0xff, 'p', 'a', 'y', 'l', 'o', 'a', + 'd' + }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); + CU_ASSERT(pdu->type == COAP_MESSAGE_NON); + CU_ASSERT(pdu->token_length == 0); + CU_ASSERT(pdu->code == 0x73); + CU_ASSERT(pdu->mid == 0x1234); + + /* FIXME: check options */ + + CU_ASSERT(pdu->data == pdu->token + 1); + CU_ASSERT(memcmp(pdu->data, teststr + 5, 7) == 0); +} + +static void +t_parse_pdu9(void) { + /* PDU without options and payload but with payload start marker */ + uint8_t teststr[] = { 0x70, 0x00, 0x12, 0x34, 0xff }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +static void +t_parse_pdu10(void) { + /* PDU without payload but with options and payload start marker */ + uint8_t teststr[] = { 0x53, 0x73, 0x12, 0x34, 't', 'o', 'k', + 0x31, 'a', 0xc1, 0x00, 0xff + }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +static void +t_parse_pdu11(void) { + uint8_t teststr[] = { 0x60, 0x00, 0x12, 0x34 }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); + CU_ASSERT(pdu->type == COAP_MESSAGE_ACK); + CU_ASSERT(pdu->token_length == 0); + CU_ASSERT(pdu->code == 0); + CU_ASSERT(pdu->mid == 0x1234); +} + +static void +t_parse_pdu12(void) { + /* RST */ + uint8_t teststr[] = { 0x70, 0x00, 0x12, 0x34 }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result > 0); + + CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); + CU_ASSERT(pdu->type == COAP_MESSAGE_RST); + CU_ASSERT(pdu->token_length == 0); + CU_ASSERT(pdu->code == 0); + CU_ASSERT(pdu->mid == 0x1234); +} + +static void +t_parse_pdu13(void) { + /* RST with content */ + uint8_t teststr[] = { 0x70, 0x00, 0x12, 0x34, + 0xff, 'c', 'o', 'n', 't', 'e', 'n', 't' + }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +static void +t_parse_pdu14(void) { + /* ACK with content */ + uint8_t teststr[] = { 0x60, 0x00, 0x12, 0x34, + 0xff, 'c', 'o', 'n', 't', 'e', 'n', 't' + }; + int result; + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +/* + * To test Issue #199 which reads one byte past the end of teststr[] + * before fix to coap_opt_parse() as delta is two byte value and only + * one byte left + * Credit to OSS-Fuzz for finding this, work done by Bhargava Shastry + */ +static void +t_parse_pdu15(void) { + int result; + uint8_t teststr[] = { + 64, 91, 91, 91, 139, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 91, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 1, 0, 0, 0, + 0, 0, 0, 0, 224, 192, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 228, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 1, 0, 0, 0, 0, 0, 0, 0, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224}; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +static void log_handler(coap_log_t level, const char *message) +{ + (void)level; + (void)message; +} + +/* + * To test Issue #214 which allows the token size to be set larger than the + * decoded PDU in coap_pdu_parse_header(). This then causes coap_show_pdu() + * to access invalid memory. + * Credit to OSS-Fuzz for finding this, work done by Bhargava Shastry + */ +static void +t_parse_pdu16(void) { + int result; + coap_pdu_t *testpdu; + uint8_t teststr[] = { 0x5a, 0x0a, 0x5b, 0x5b }; + + testpdu = coap_pdu_init(0, 0, 0, sizeof(teststr)); + CU_ASSERT(testpdu != NULL); + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), testpdu); + CU_ASSERT(result == 0); + + coap_set_show_pdu_output(0); + coap_set_log_handler(log_handler); + coap_show_pdu(LOG_ERR, testpdu); /* display PDU */ + coap_set_log_handler(NULL); + + coap_delete_pdu(testpdu); +} + +static void +t_parse_pdu17(void) { + uint8_t teststr[512] = { 0x40, 0x01, 0x93, 0x34 }; + size_t idx; + int result; + + /* 245 * option delta 268 > 65535, causing a overflow in the option + * number */ + for (idx = 4; idx < sizeof(teststr) - 4; idx += 2) { + teststr[idx] = 0xd0; /* 1 byte option delta follows */ + teststr[idx + 1] = 0xff; /* option delta 268 */ + } + + result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); + CU_ASSERT(result == 0); +} + +/************************************************************************ + ** PDU encoder + ************************************************************************/ + +static void +t_encode_pdu1(void) { + uint8_t teststr[] = { 0x45, 0x01, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); + pdu->type = COAP_MESSAGE_CON; + pdu->code = COAP_REQUEST_CODE_GET; + pdu->mid = 0x1234; + + result = coap_add_token(pdu, 5, (const uint8_t *)"token"); + + CU_ASSERT(result == 1); + CU_ASSERT(pdu->used_size == 5); + CU_ASSERT_PTR_NULL(pdu->data); + CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); +} + +static void +t_encode_pdu2(void) { + size_t old_max = pdu->max_size; + int result; + + coap_pdu_clear(pdu, 3); /* set very small PDU size */ + + pdu->type = COAP_MESSAGE_CON; + pdu->code = COAP_REQUEST_CODE_GET; + pdu->mid = 0x1234; + + result = coap_add_token(pdu, 5, (const uint8_t *)"token"); + + CU_ASSERT(result == 0); + + coap_pdu_clear(pdu, old_max); /* restore PDU size */ +} + +static void +t_encode_pdu3(void) { + int result; + + result = coap_add_token(pdu, 9, (const uint8_t *)"123456789"); + + CU_ASSERT(result == 0); +} + +static void +t_encode_pdu4(void) { + /* PDU with options */ + uint8_t teststr[] = { 0x60, 0x99, 0x12, 0x34, 0x3d, 0x05, 0x66, 0x61, + 0x6e, 0x63, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x2e, 0x63, 0x6f, 0x61, 0x70, 0x2e, 0x6d, 0x65, + 0x84, 0x70, 0x61, 0x74, 0x68, 0x00, 0xe8, 0x1e, + 0x28, 0x66, 0x61, 0x6e, 0x63, 0x79, 0x6f, 0x70, + 0x74 + }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->type = COAP_MESSAGE_ACK; + pdu->code = 0x99; + pdu->mid = 0x1234; + + CU_ASSERT(pdu->used_size == 0); + + result = coap_add_option(pdu, COAP_OPTION_URI_HOST, + 18, (const uint8_t *)"fancyproxy.coap.me"); + + CU_ASSERT(result == 20); + CU_ASSERT(pdu->max_opt == 3); + CU_ASSERT(pdu->used_size == 20); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_URI_PATH, + 4, (const uint8_t *)"path"); + + CU_ASSERT(result == 5); + CU_ASSERT(pdu->max_opt == 11); + CU_ASSERT(pdu->used_size == 25); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_URI_PATH, 0, NULL); + + CU_ASSERT(result == 1); + CU_ASSERT(pdu->max_opt == 11); + CU_ASSERT(pdu->used_size == 26); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, 8000, 8, (const uint8_t *)"fancyopt"); + + CU_ASSERT(result == 11); + CU_ASSERT(pdu->max_opt == 8000); + CU_ASSERT(pdu->used_size == 37); + CU_ASSERT_PTR_NULL(pdu->data); + + CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); +} + +static void +t_encode_pdu5(void) { + /* PDU with token and options */ + uint8_t teststr[] = { 0x68, 0x84, 0x12, 0x34, '1', '2', '3', '4', + '5', '6', '7', '8', 0x18, 0x41, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x47, 0x48, 0xd1, 0x03, 0x12 + }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->type = COAP_MESSAGE_ACK; + pdu->code = COAP_RESPONSE_CODE(404); + pdu->mid = 0x1234; + + CU_ASSERT(pdu->used_size == 0); + + result = coap_add_token(pdu, 8, (const uint8_t *)"12345678"); + + CU_ASSERT(pdu->used_size == 8); + + result = coap_add_option(pdu, COAP_OPTION_IF_MATCH, + 8, (const uint8_t *)"ABCDEFGH"); + + CU_ASSERT(result == 9); + CU_ASSERT(pdu->max_opt == 1); + CU_ASSERT(pdu->used_size == 17); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_ACCEPT, + 1, (const uint8_t *)"\x12"); + + CU_ASSERT(result == 3); + CU_ASSERT(pdu->max_opt == 17); + CU_ASSERT(pdu->used_size == 20); + CU_ASSERT_PTR_NULL(pdu->data); + + CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); +} + +static void +t_encode_pdu6(void) { + /* PDU with data */ + uint8_t teststr[] = { 0x50, 0x02, 0x12, 0x34, 0xff, '1', '2', '3', + '4', '5', '6', '7', '8' + }; + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->type = COAP_MESSAGE_NON; + pdu->code = COAP_REQUEST_CODE_POST; + pdu->mid = 0x1234; + + CU_ASSERT(pdu->used_size == 0); + CU_ASSERT_PTR_NULL(pdu->data); + + coap_add_data(pdu, 8, (const uint8_t *)"12345678"); + + CU_ASSERT(pdu->used_size == 9); + CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); +} + +static void +t_encode_pdu7(void) { + /* PDU with empty data */ + uint8_t teststr[] = { 0x40, 0x43, 0x12, 0x34 }; + int result; + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->type = COAP_MESSAGE_CON; + pdu->code = COAP_RESPONSE_CODE(203); + pdu->mid = 0x1234; + + CU_ASSERT(pdu->used_size == 0); + + result = coap_add_data(pdu, 0, NULL); + + CU_ASSERT(result > 0); + CU_ASSERT(pdu->used_size == 0); + CU_ASSERT_PTR_NULL(pdu->data); + + CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); +} + +static void +t_encode_pdu8(void) { + /* PDU with token and data */ + uint8_t teststr[] = { 0x42, 0x43, 0x12, 0x34, 0x00, 0x01, 0xff, 0x00 }; + int result; + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->type = COAP_MESSAGE_CON; + pdu->code = COAP_RESPONSE_CODE(203); + pdu->mid = 0x1234; + + CU_ASSERT(pdu->used_size == 0); + + result = coap_add_token(pdu, 2, (const uint8_t *)"\x00\x01"); + + CU_ASSERT(result > 0); + + result = coap_add_data(pdu, 1, (const uint8_t *)"\0"); + + CU_ASSERT(result > 0); + CU_ASSERT(pdu->used_size == 4); + CU_ASSERT(pdu->data == pdu->token + 3); + + CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); +} + +static void +t_encode_pdu9(void) { + /* PDU with options and data */ + uint8_t teststr[] = { 0x60, 0x44, 0x12, 0x34, 0x48, 's', 'o', 'm', + 'e', 'e', 't', 'a', 'g', 0x10, 0xdd, 0x11, + 0x04, 's', 'o', 'm', 'e', 'r', 'a', 't', + 'h', 'e', 'r', 'l', 'o', 'n', 'g', 'u', + 'r', 'i', 0xff, 'd', 'a', 't', 'a' + }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->type = COAP_MESSAGE_ACK; + pdu->code = COAP_RESPONSE_CODE(204); + pdu->mid = 0x1234; + + CU_ASSERT(pdu->used_size == 0); + + result = coap_add_option(pdu, COAP_OPTION_ETAG, 8, (const uint8_t *)"someetag"); + + CU_ASSERT(result == 9); + CU_ASSERT(pdu->max_opt == 4); + CU_ASSERT(pdu->used_size == 9); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_IF_NONE_MATCH, 0, NULL); + + CU_ASSERT(result == 1); + CU_ASSERT(pdu->max_opt == 5); + CU_ASSERT(pdu->used_size == 10); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_PROXY_URI, + 17, (const uint8_t *)"someratherlonguri"); + + CU_ASSERT(result == 20); + CU_ASSERT(pdu->max_opt == 35); + CU_ASSERT(pdu->used_size == 30); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_data(pdu, 4, (const uint8_t *)"data"); + + CU_ASSERT(result > 0); + CU_ASSERT(pdu->used_size == 35); + CU_ASSERT(pdu->data == pdu->token + 31); + + CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); +} + +static void +t_encode_pdu10(void) { + /* PDU with token, options and data */ + uint8_t teststr[] = { 0x62, 0x44, 0x12, 0x34, 0x00, 0x00, 0x8d, 0xf2, + 'c', 'o', 'a', 'p', ':', '/', '/', 'e', + 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', + 'o', 'm', '/', '1', '2', '3', '4', '5', + '/', '%', '3', 'F', 'x', 'y', 'z', '/', + '3', '0', '4', '8', '2', '3', '4', '2', + '3', '4', '/', '2', '3', '4', '0', '2', + '3', '4', '8', '2', '3', '4', '/', '2', + '3', '9', '0', '8', '4', '2', '3', '4', + '-', '2', '3', '/', '%', 'A', 'B', '%', + '3', '0', '%', 'a', 'f', '/', '+', '1', + '2', '3', '/', 'h', 'f', 'k', 's', 'd', + 'h', '/', '2', '3', '4', '8', '0', '-', + '2', '3', '4', '-', '9', '8', '2', '3', + '5', '/', '1', '2', '0', '4', '/', '2', + '4', '3', '5', '4', '6', '3', '4', '5', + '3', '4', '5', '2', '4', '3', '/', '0', + '1', '9', '8', 's', 'd', 'n', '3', '-', + 'a', '-', '3', '/', '/', '/', 'a', 'f', + 'f', '0', '9', '3', '4', '/', '9', '7', + 'u', '2', '1', '4', '1', '/', '0', '0', + '0', '2', '/', '3', '9', '3', '2', '4', + '2', '3', '5', '3', '2', '/', '5', '6', + '2', '3', '4', '0', '2', '3', '/', '-', + '-', '-', '-', '/', '=', '1', '2', '3', + '4', '=', '/', '0', '9', '8', '1', '4', + '1', '-', '9', '5', '6', '4', '6', '4', + '3', '/', '2', '1', '9', '7', '0', '-', + '-', '-', '-', '-', '/', '8', '2', '3', + '6', '4', '9', '2', '3', '4', '7', '2', + 'w', 'e', 'r', 'e', 'r', 'e', 'w', 'r', + '0', '-', '9', '2', '1', '-', '3', '9', + '1', '2', '3', '-', '3', '4', '/', 0x0d, + 0x01, '/', '/', '4', '9', '2', '4', '0', + '3', '-', '-', '0', '9', '8', '/', 0xc1, + '*', 0xff, 'd', 'a', 't', 'a' + }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->type = COAP_MESSAGE_ACK; + pdu->code = COAP_RESPONSE_CODE(204); + pdu->mid = 0x1234; + + CU_ASSERT(pdu->used_size == 0); + + result = coap_add_token(pdu, 2, (const uint8_t *)"\0\0"); + + CU_ASSERT(result > 0); + result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 255, + (const uint8_t *)"coap://example.com/12345/%3Fxyz/3048234234/23402348234/239084234-23/%AB%30%af/+123/hfksdh/23480-234-98235/1204/243546345345243/0198sdn3-a-3///aff0934/97u2141/0002/3932423532/56234023/----/=1234=/098141-9564643/21970-----/82364923472wererewr0-921-39123-34/"); + + CU_ASSERT(result == 257); + CU_ASSERT(pdu->max_opt == 8); + CU_ASSERT(pdu->used_size == 259); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 14, + (const uint8_t *)"//492403--098/"); + + CU_ASSERT(result == 16); + CU_ASSERT(pdu->max_opt == 8); + CU_ASSERT(pdu->used_size == 275); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_LOCATION_QUERY, + 1, (const uint8_t *)"*"); + + CU_ASSERT(result == 2); + CU_ASSERT(pdu->max_opt == 20); + CU_ASSERT(pdu->used_size == 277); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_data(pdu, 4, (const uint8_t *)"data"); + + CU_ASSERT(result > 0); + CU_ASSERT(pdu->used_size == 282); + CU_ASSERT(pdu->data == pdu->token + 278); + + CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); +} + +static void +t_encode_pdu11(void) { + coap_log_t level = coap_get_log_level(); + /* data too long for PDU */ + size_t old_max = pdu->max_size; + int result; + + coap_pdu_clear(pdu, 8); /* clear PDU, with small maximum */ + + CU_ASSERT(pdu->data == NULL); + coap_set_log_level(LOG_CRIT); + result = coap_add_data(pdu, 10, (const uint8_t *)"0123456789"); + coap_set_log_level(level); + + CU_ASSERT(result == 0); + CU_ASSERT(pdu->data == NULL); + CU_ASSERT(pdu->used_size == 0); + + pdu->max_size = old_max; +} + +static void +t_encode_pdu12(void) { + coap_optlist_t *optlist = NULL; + int n; + uint8_t opt_num[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; + uint8_t opt_val[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; + uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; + coap_opt_iterator_t oi; + coap_opt_t *option; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + for (n = 0; n < (int)sizeof(opt_num); n++) { + coap_insert_optlist(&optlist, coap_new_optlist(opt_num[n], + sizeof(opt_val[n]), &opt_val[n])); + } + coap_add_optlist_pdu(pdu, &optlist); + + /* Check options in pdu are in right order */ + coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL); + for (n = 0; n < (int)sizeof(opt_num); n++) { + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(option != NULL); + CU_ASSERT(coap_opt_length(option) == 1); + CU_ASSERT(*coap_opt_value(option) == opt_srt[n]); + } + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT(option == NULL); + coap_delete_optlist(optlist); +} + +static void +t_encode_pdu13(void) { + coap_optlist_t *optlist = NULL; + int n; + uint8_t opt_num[] = { 59, 58, 57, 56, 55, 54, 53, 52, 51, 50 }; + uint8_t opt_val[] = { 59, 58, 57, 56, 55, 54, 53, 52, 51, 50 }; + uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; + coap_opt_iterator_t oi; + coap_opt_t *option; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + for (n = 0; n < (int)sizeof(opt_num); n++) { + coap_insert_optlist(&optlist, coap_new_optlist(opt_num[n], + sizeof(opt_val[n]), &opt_val[n])); + } + coap_add_optlist_pdu(pdu, &optlist); + + /* Check options in pdu are in right order */ + coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL); + for (n = 0; n < (int)sizeof(opt_num); n++) { + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(option != NULL); + CU_ASSERT(coap_opt_length(option) == 1); + CU_ASSERT(*coap_opt_value(option) == opt_srt[n]); + } + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT(option == NULL); + coap_delete_optlist(optlist); +} + +static void +t_encode_pdu14(void) { + coap_optlist_t *optlist = NULL; + int n; + uint8_t opt_num[] = { 53, 52, 51, 50, 51, 52, 52, 51, 50, 50 }; + uint8_t opt_val[] = { 59, 56, 53, 50, 54, 57, 58, 55, 51, 52 }; + uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; + coap_opt_iterator_t oi; + coap_opt_t *option; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + for (n = 0; n < (int)sizeof(opt_num); n++) { + coap_insert_optlist(&optlist, coap_new_optlist(opt_num[n], + sizeof(opt_val[n]), &opt_val[n])); + } + coap_add_optlist_pdu(pdu, &optlist); + + /* Check options in pdu are in right order */ + coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL); + for (n = 0; n < (int)sizeof(opt_num); n++) { + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(option != NULL); + CU_ASSERT(coap_opt_length(option) == 1); + CU_ASSERT(*coap_opt_value(option) == opt_srt[n]); + } + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT(option == NULL); + coap_delete_optlist(optlist); +} + +/* Check inserting options with random types get put into the PDU in the + right order */ +static void +t_encode_pdu15(void) { + size_t n; + uint16_t opt_num[] = { 300, 13, 10, 7, 11, 268, 269, 12, 8, 9 }; + uint8_t opt_val[] = { 59, 56, 53, 50, 54, 57, 58, 55, 51, 52 }; + uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; + coap_opt_iterator_t oi; + coap_opt_t *option; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { + coap_insert_option(pdu, opt_num[n], + sizeof(opt_val[n]), &opt_val[n]); + } + + /* Check options in pdu are in right order */ + coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL); + for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 0); + CU_ASSERT(option != NULL); + CU_ASSERT(coap_opt_length(option) == 1); + CU_ASSERT(*coap_opt_value(option) == opt_srt[n]); + } + option = coap_option_next(&oi); + CU_ASSERT(oi.bad == 1); + CU_ASSERT(option == NULL); +} + +/* Check changing value of options works */ +static void +t_encode_pdu16(void) { + size_t n; + uint16_t opt_num[] = { 300, 10, 7 }; + uint8_t opt_val[] = { 53, 51, 50 }; + uint8_t data[] = { 'd', 'a', 't', 'a' }; + uint8_t data1[] = { 0x71, 0x32, 0x31, 0x33, 0xe1, 0x00, 0x15, 0x35, + 0xff, 0x64, 0x61, 0x74, 0x61 }; + uint8_t data2[] = { 0x71, 0x32, 0x33, 0x01, 0x23, 0x45, 0xe1, 0x00, + 0x15, 0x35, 0xff, 0x64, 0x61, 0x74, 0x61 }; + uint8_t data3[] = { 0x70, 0x31, 0x33, 0xe1, 0x00, 0x15, 0x35, 0xff, + 0x64, 0x61, 0x74, 0x61 }; + uint8_t data4[] = { 0x71, 0x32, 0x31, 0x33, 0xe4, 0x00, 0x15, 0x06, + 0x54, 0x32, 0x10, 0xff, 0x64, 0x61, 0x74, 0x61 }; + int new_val; + unsigned char buf[4]; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { + coap_add_option(pdu, opt_num[n], + sizeof(opt_val[n]), &opt_val[n]); + } + coap_add_data(pdu, sizeof(data), data); + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); + /* Now update an option in the middle */ + new_val = 0x12345; + coap_update_option(pdu, 10, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); + /* Shrink it back again */ + new_val = 51; + coap_update_option(pdu, 10, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); + /* Now update an option at the start */ + new_val = 0; + coap_update_option(pdu, 7, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); + /* put it back again */ + new_val = 50; + coap_update_option(pdu, 7, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); + /* Now update an option at the end */ + new_val = 0x6543210; + coap_update_option(pdu, 300, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0); + /* put it back again */ + new_val = 53; + coap_update_option(pdu, 300, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); +} + +/* Same as t_encode_pdu16, but without any data, but with a token */ +static void +t_encode_pdu17(void) { + size_t n; + uint8_t token[] = { 't' }; + uint16_t opt_num[] = { 300, 10, 7 }; + uint8_t opt_val[] = { 53, 51, 50 }; + uint8_t data1[] = { 0x74, 0x71, 0x32, 0x31, 0x33, 0xe1, 0x00, 0x15, + 0x35 }; + uint8_t data2[] = { 0x74, 0x71, 0x32, 0x33, 0x01, 0x23, 0x45, 0xe1, + 0x00, 0x15, 0x35 }; + uint8_t data3[] = { 0x74, 0x70, 0x31, 0x33, 0xe1, 0x00, 0x15, 0x35 }; + uint8_t data4[] = { 0x74, 0x71, 0x32, 0x31, 0x33, 0xe4, 0x00, 0x15, + 0x06, 0x54, 0x32, 0x10 }; + int new_val; + unsigned char buf[4]; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + coap_add_token(pdu, sizeof(token), token); + for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { + coap_add_option(pdu, opt_num[n], + sizeof(opt_val[n]), &opt_val[n]); + } + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); + /* Now update an option in the middle */ + new_val = 0x12345; + coap_update_option(pdu, 10, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); + /* Shrink it back again */ + new_val = 51; + coap_update_option(pdu, 10, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); + /* Now update an option at the start */ + new_val = 0; + coap_update_option(pdu, 7, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); + /* put it back again */ + new_val = 50; + coap_update_option(pdu, 7, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); + /* Now update an option at the end */ + new_val = 0x6543210; + coap_update_option(pdu, 300, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0); + /* put it back again */ + new_val = 53; + coap_update_option(pdu, 300, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); +} + +static void +t_encode_pdu18(void) { + /* PDU with token, options and data */ + uint8_t teststr[] = { 0x62, 0x44, 0x12, 0x34, 0x00, 0x00, 0x8d, 0xf2, + 'c', 'o', 'a', 'p', ':', '/', '/', 'e', + 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', + 'o', 'm', '/', '1', '2', '3', '4', '5', + '/', '%', '3', 'F', 'x', 'y', 'z', '/', + '3', '0', '4', '8', '2', '3', '4', '2', + '3', '4', '/', '2', '3', '4', '0', '2', + '3', '4', '8', '2', '3', '4', '/', '2', + '3', '9', '0', '8', '4', '2', '3', '4', + '-', '2', '3', '/', '%', 'A', 'B', '%', + '3', '0', '%', 'a', 'f', '/', '+', '1', + '2', '3', '/', 'h', 'f', 'k', 's', 'd', + 'h', '/', '2', '3', '4', '8', '0', '-', + '2', '3', '4', '-', '9', '8', '2', '3', + '5', '/', '1', '2', '0', '4', '/', '2', + '4', '3', '5', '4', '6', '3', '4', '5', + '3', '4', '5', '2', '4', '3', '/', '0', + '1', '9', '8', 's', 'd', 'n', '3', '-', + 'a', '-', '3', '/', '/', '/', 'a', 'f', + 'f', '0', '9', '3', '4', '/', '9', '7', + 'u', '2', '1', '4', '1', '/', '0', '0', + '0', '2', '/', '3', '9', '3', '2', '4', + '2', '3', '5', '3', '2', '/', '5', '6', + '2', '3', '4', '0', '2', '3', '/', '-', + '-', '-', '-', '/', '=', '1', '2', '3', + '4', '=', '/', '0', '9', '8', '1', '4', + '1', '-', '9', '5', '6', '4', '6', '4', + '3', '/', '2', '1', '9', '7', '0', '-', + '-', '-', '-', '-', '/', '8', '2', '3', + '6', '4', '9', '2', '3', '4', '7', '2', + 'w', 'e', 'r', 'e', 'r', 'e', 'w', 'r', + '0', '-', '9', '2', '1', '-', '3', '9', + '1', '2', '3', '-', '3', '4', '/', 0x0d, + 0x01, '/', '/', '4', '9', '2', '4', '0', + '3', '-', '-', '0', '9', '8', '/', 0xc1, + '*', 0xff, 'd', 'a', 't', 'a' + }; + int result; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + pdu->type = COAP_MESSAGE_ACK; + pdu->code = COAP_RESPONSE_CODE(204); + pdu->mid = 0x1234; + + CU_ASSERT(pdu->used_size == 0); + + result = coap_add_token(pdu, 2, (const uint8_t *)"\0\0"); + + CU_ASSERT(result > 0); + result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 255, + (const uint8_t *)"coap://example.com/12345/%3Fxyz/3048234234/23402348234/239084234-23/%AB%30%af/+123/hfksdh/23480-234-98235/1204/243546345345243/0198sdn3-a-3///aff0934/97u2141/0002/3932423532/56234023/----/=1234=/098141-9564643/21970-----/82364923472wererewr0-921-39123-34/"); + + CU_ASSERT(result == 257); + CU_ASSERT(pdu->max_opt == 8); + CU_ASSERT(pdu->used_size == 259); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_option(pdu, COAP_OPTION_LOCATION_QUERY, + 1, (const uint8_t *)"*"); + + CU_ASSERT(result == 2); + CU_ASSERT(pdu->used_size == 261); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_insert_option(pdu, COAP_OPTION_LOCATION_PATH, 14, + (const uint8_t *)"//492403--098/"); + + CU_ASSERT(result == 16); + CU_ASSERT(pdu->used_size == 277); + CU_ASSERT_PTR_NULL(pdu->data); + + result = coap_add_data(pdu, 4, (const uint8_t *)"data"); + + CU_ASSERT(result > 0); + CU_ASSERT(pdu->used_size == 282); + CU_ASSERT(pdu->data == pdu->token + 278); + + CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); + CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); + +} + +/* Remove an option (no data) */ +static void +t_encode_pdu19(void) { + size_t n; + uint8_t token[] = { 't' }; + uint16_t opt_num[] = { 300, 7, 21, 25 }; + uint8_t opt_val[] = { 54, 50, 52, 53 }; + uint8_t data1[] = { 0x74, 0x71, 0x32, 0xd1, 0x01, 0x34, 0x41, 0x35, + 0xe1, 0x00, 0x06, 0x36 }; + uint8_t data2[] = { 0x74, 0x71, 0x32, 0xd1, 0x05, 0x35, 0xe1, 0x00, + 0x06, 0x36 }; + uint8_t data3[] = { 0x74, 0xd1, 0x0c, 0x35, 0xe1, 0x00, 0x06, 0x36 }; + uint8_t data4[] = { 0x74, 0xd1, 0x0c, 0x35 }; + uint8_t data5[] = { 0x74 }; + uint8_t data6[] = { 0x74, 0xd1, 0x0c, 0x0a }; + int new_val; + unsigned char buf[4]; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + coap_add_token(pdu, sizeof(token), token); + for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { + coap_add_option(pdu, opt_num[n], + sizeof(opt_val[n]), &opt_val[n]); + } + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); + + /* Now remove an option in the middle */ + coap_remove_option(pdu, 21); + CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); + + /* Now remove an option from the start */ + coap_remove_option(pdu, 7); + CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); + + /* Now remove an option from the end */ + coap_remove_option(pdu, 300); + CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0); + + /* Now remove the final option */ + coap_remove_option(pdu, 25); + CU_ASSERT(memcmp(pdu->token, data5, pdu->used_size) == 0); + + /* Now insert an option */ + new_val = 10; + coap_update_option(pdu, 25, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data6, pdu->used_size) == 0); +} + +/* Remove an option (with data) */ +static void +t_encode_pdu20(void) { + size_t n; + uint8_t token[] = { 't' }; + uint16_t opt_num[] = { 300, 7, 21, 25 }; + uint8_t opt_val[] = { 54, 50, 52, 53 }; + uint8_t data[] = { 'd', 'a', 't', 'a' }; + uint8_t data1[] = { 0x74, 0x71, 0x32, 0xd1, 0x01, 0x34, 0x41, 0x35, + 0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, 0x74, + 0x61 }; + uint8_t data2[] = { 0x74, 0x71, 0x32, 0xd1, 0x05, 0x35, 0xe1, 0x00, + 0x06, 0x36, 0xff, 0x64, 0x61, 0x74, 0x61 }; + uint8_t data3[] = { 0x74, 0xd1, 0x0c, 0x35, 0xe1, 0x00, 0x06, 0x36, + 0xff, 0x64, 0x61, 0x74, 0x61 }; + uint8_t data4[] = { 0x74, 0xd1, 0x0c, 0x35, 0xff, 0x64, 0x61, 0x74, + 0x61 }; + uint8_t data5[] = { 0x74, 0xff, 0x64, 0x61, 0x74, 0x61 }; + uint8_t data6[] = { 0x74, 0xd1, 0x0c, 0x0a, 0xff, 0x64, 0x61, 0x74, + 0x61 }; + int new_val; + unsigned char buf[4]; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + coap_add_token(pdu, sizeof(token), token); + for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { + coap_add_option(pdu, opt_num[n], + sizeof(opt_val[n]), &opt_val[n]); + } + coap_add_data(pdu, sizeof(data), data); + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); + + /* Now remove an option in the middle */ + coap_remove_option(pdu, 21); + CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); + + /* Now remove an option from the start */ + coap_remove_option(pdu, 7); + CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); + + /* Now remove an option from the end */ + coap_remove_option(pdu, 300); + CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0); + + /* Now remove the final option */ + coap_remove_option(pdu, 25); + CU_ASSERT(memcmp(pdu->token, data5, pdu->used_size) == 0); + + /* Now insert an option */ + new_val = 10; + coap_update_option(pdu, 25, + coap_encode_var_safe(buf, sizeof(buf), new_val), buf); + CU_ASSERT(memcmp(pdu->token, data6, pdu->used_size) == 0); +} + +/* Update token */ +static void +t_encode_pdu21(void) { + size_t n; + uint8_t token[] = { 't' }; + uint8_t new_token[] = { 't', 'o', 'k', 'e', 'n' }; + uint16_t opt_num[] = { 300, 10, 7, 21, 25 }; + uint8_t opt_val[] = { 54, 51, 50, 52, 53 }; + uint8_t data[] = { 'd', 'a', 't', 'a' }; + uint8_t data1[] = { 0x74, 0x71, 0x32, 0x31, 0x33, 0xb1, 0x34, 0x41, + 0x35, 0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, + 0x74, 0x61 }; + uint8_t data2[] = { 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x71, 0x32, 0x31, + 0x33, 0xb1, 0x34, 0x41, 0x35, 0xe1, 0x00, 0x06, + 0x36, 0xff, 0x64, 0x61, 0x74, 0x61 }; + uint8_t data3[] = { 0x71, 0x32, 0x31, 0x33, 0xb1, 0x34, 0x41, 0x35, + 0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, 0x74, + 0x61 }; + + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + coap_add_token(pdu, sizeof(token), token); + for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { + coap_add_option(pdu, opt_num[n], + sizeof(opt_val[n]), &opt_val[n]); + } + coap_add_data(pdu, sizeof(data), data); + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); + + /* Now update token */ + coap_update_token(pdu, sizeof(new_token), new_token); + CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); + + /* Now restore token */ + coap_update_token(pdu, sizeof(token), token); + CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); + + /* Now set token to zero length */ + coap_update_token(pdu, 0, NULL); + CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); +} + +/* insert option before (large) final one */ +static void +t_encode_pdu22(void) { + size_t n; + uint8_t token[] = { 't' }; + uint8_t buf[4]; + uint16_t opt_num[] = { 28, 28, 28, 28 }; + uint32_t opt_val[] = { 0x1, 0x100, 0x10000, 0x1000000 }; + uint8_t data1[][8] = { + { 0x74, 0xd1, 0x0f, 0x01 }, + { 0x74, 0xd2, 0x0f, 0x01, 0x00 }, + { 0x74, 0xd3, 0x0f, 0x01, 0x00, 0x00 }, + { 0x74, 0xd4, 0x0f, 0x01, 0x00, 0x00, 0x00 }}; + uint8_t data2[][16] = { + { 0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x51, 0x01 }, + { 0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x52, 0x01, + 0x00 }, + { 0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x53, 0x01, + 0x00, 0x00 }, + { 0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x54, 0x01, + 0x00, 0x00, 0x00 }}; + + for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { + coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ + + CU_ASSERT(pdu->data == NULL); + + coap_add_token(pdu, sizeof(token), token); + coap_add_option(pdu, opt_num[n], + coap_encode_var_safe(buf, sizeof(buf), opt_val[n]), buf); + CU_ASSERT(memcmp(pdu->token, data1[n], pdu->used_size) == 0); + + /* Now insert option */ + coap_insert_option(pdu, 23, + coap_encode_var_safe(buf, sizeof(buf), 0xfffff6), buf); + CU_ASSERT(memcmp(pdu->token, data2[n], pdu->used_size) == 0); + } +} + + +static int +t_pdu_tests_create(void) { + pdu = coap_pdu_init(0, 0, 0, COAP_DEFAULT_MTU); + + return pdu == NULL; +} + +static int +t_pdu_tests_remove(void) { + coap_delete_pdu(pdu); + return 0; +} + +CU_pSuite +t_init_pdu_tests(void) { + CU_pSuite suite[2]; + + suite[0] = CU_add_suite("pdu parser", t_pdu_tests_create, t_pdu_tests_remove); + if (!suite[0]) { /* signal error */ + fprintf(stderr, "W: cannot add pdu parser test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + +#define PDU_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add pdu parser test (%s)\n", \ + CU_get_error_msg()); \ + } + + PDU_TEST(suite[0], t_parse_pdu1); + PDU_TEST(suite[0], t_parse_pdu2); + PDU_TEST(suite[0], t_parse_pdu3); + PDU_TEST(suite[0], t_parse_pdu4); + PDU_TEST(suite[0], t_parse_pdu5); + PDU_TEST(suite[0], t_parse_pdu6); + PDU_TEST(suite[0], t_parse_pdu7); + PDU_TEST(suite[0], t_parse_pdu8); + PDU_TEST(suite[0], t_parse_pdu9); + PDU_TEST(suite[0], t_parse_pdu10); + PDU_TEST(suite[0], t_parse_pdu11); + PDU_TEST(suite[0], t_parse_pdu12); + PDU_TEST(suite[0], t_parse_pdu13); + PDU_TEST(suite[0], t_parse_pdu14); + PDU_TEST(suite[0], t_parse_pdu15); + PDU_TEST(suite[0], t_parse_pdu16); + PDU_TEST(suite[0], t_parse_pdu17); + + suite[1] = CU_add_suite("pdu encoder", t_pdu_tests_create, t_pdu_tests_remove); + if (suite[1]) { +#define PDU_ENCODER_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add pdu encoder test (%s)\n", \ + CU_get_error_msg()); \ + } + PDU_ENCODER_TEST(suite[1], t_encode_pdu1); + PDU_ENCODER_TEST(suite[1], t_encode_pdu2); + PDU_ENCODER_TEST(suite[1], t_encode_pdu3); + PDU_ENCODER_TEST(suite[1], t_encode_pdu4); + PDU_ENCODER_TEST(suite[1], t_encode_pdu5); + PDU_ENCODER_TEST(suite[1], t_encode_pdu6); + PDU_ENCODER_TEST(suite[1], t_encode_pdu7); + PDU_ENCODER_TEST(suite[1], t_encode_pdu8); + PDU_ENCODER_TEST(suite[1], t_encode_pdu9); + PDU_ENCODER_TEST(suite[1], t_encode_pdu10); + PDU_ENCODER_TEST(suite[1], t_encode_pdu11); + PDU_ENCODER_TEST(suite[1], t_encode_pdu12); + PDU_ENCODER_TEST(suite[1], t_encode_pdu13); + PDU_ENCODER_TEST(suite[1], t_encode_pdu14); + PDU_ENCODER_TEST(suite[1], t_encode_pdu15); + PDU_ENCODER_TEST(suite[1], t_encode_pdu16); + PDU_ENCODER_TEST(suite[1], t_encode_pdu17); + PDU_ENCODER_TEST(suite[1], t_encode_pdu18); + PDU_ENCODER_TEST(suite[1], t_encode_pdu19); + PDU_ENCODER_TEST(suite[1], t_encode_pdu20); + PDU_ENCODER_TEST(suite[1], t_encode_pdu21); + PDU_ENCODER_TEST(suite[1], t_encode_pdu22); + + } else /* signal error */ + fprintf(stderr, "W: cannot add pdu parser test suite (%s)\n", + CU_get_error_msg()); + + return suite[0]; +} + diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_pdu.h b/examples/espidf-coap-server/components/libcoap/tests/test_pdu.h new file mode 100644 index 000000000..5c21973f8 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_pdu.h @@ -0,0 +1,13 @@ +/* libcoap unit tests + * + * Copyright (C) 2012 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_pdu_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_sendqueue.c b/examples/espidf-coap-server/components/libcoap/tests/test_sendqueue.c new file mode 100644 index 000000000..31554d194 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_sendqueue.c @@ -0,0 +1,367 @@ +/* libcoap unit tests + * + * Copyright (C) 2013,2015 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "test_common.h" +#include "test_sendqueue.h" + +#include + +#if COAP_CLIENT_SUPPORT +static coap_context_t *ctx; /* Holds the coap context for most tests */ +static coap_session_t *session; /* Holds a reference-counted session object */ + +/* timestamps for tests. The first element in this array denotes the + * base time in ticks, the following elements are timestamps relative + * to this basetime. + */ +static coap_tick_t timestamp[] = { + 0, 100, 200, 30, 160 +}; + +/* nodes for testing. node[0] is left empty */ +coap_queue_t *node[5]; + +static coap_tick_t +add_timestamps(coap_queue_t *queue, size_t num) { + coap_tick_t t = 0; + while (queue && num--) { + t += queue->t; + queue = queue->next; + } + + return t; +} + +static void +t_sendqueue1(void) { + int result = coap_insert_node(&ctx->sendqueue, node[1]); + + CU_ASSERT(result > 0); + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue, node[1]); + CU_ASSERT(node[1]->t == timestamp[1]); +} + +static void +t_sendqueue2(void) { + int result; + + result = coap_insert_node(&ctx->sendqueue, node[2]); + + CU_ASSERT(result > 0); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue, node[1]); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue->next, node[2]); + + CU_ASSERT(ctx->sendqueue->t == timestamp[1]); + CU_ASSERT(node[2]->t == timestamp[2] - timestamp[1]); +} + +/* insert new node as first element in queue */ +static void +t_sendqueue3(void) { + int result; + result = coap_insert_node(&ctx->sendqueue, node[3]); + + CU_ASSERT(result > 0); + + CU_ASSERT_PTR_EQUAL(ctx->sendqueue, node[3]); + CU_ASSERT(node[3]->t == timestamp[3]); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue->next); + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue->next->next); + + CU_ASSERT(ctx->sendqueue->next->t == timestamp[1] - timestamp[3]); + CU_ASSERT(ctx->sendqueue->next->next->t == timestamp[2] - timestamp[1]); +} + +/* insert new node as fourth element in queue */ +static void +t_sendqueue4(void) { + int result; + + result = coap_insert_node(&ctx->sendqueue, node[4]); + + CU_ASSERT(result > 0); + + CU_ASSERT_PTR_EQUAL(ctx->sendqueue, node[3]); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue->next); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue->next, node[1]); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue->next->next); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue->next->next, node[4]); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue->next->next->next); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue->next->next->next, node[2]); + + CU_ASSERT(ctx->sendqueue->next->t == timestamp[1] - timestamp[3]); + CU_ASSERT(add_timestamps(ctx->sendqueue, 1) == timestamp[3]); + CU_ASSERT(add_timestamps(ctx->sendqueue, 2) == timestamp[1]); + CU_ASSERT(add_timestamps(ctx->sendqueue, 3) == timestamp[4]); + CU_ASSERT(add_timestamps(ctx->sendqueue, 4) == timestamp[2]); +} + +static void +t_sendqueue5(void) { + const coap_tick_diff_t delta1 = 20, delta2 = 130; + unsigned int result; + coap_tick_t now; + + /* space for saving the current node timestamps */ + static coap_tick_t times[sizeof(timestamp)/sizeof(coap_tick_t)]; + coap_queue_t *p; + int i; + + /* save timestamps of nodes in the sendqueue in their actual order */ + memset(times, 0, sizeof(times)); + for (p = ctx->sendqueue, i = 0; p; p = p->next, i++) { + times[i] = p->t; + } + + coap_ticks(&now); + ctx->sendqueue_basetime = now; + + now -= delta1; + result = coap_adjust_basetime(ctx, now); + + CU_ASSERT(result == 0); + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue); + CU_ASSERT(ctx->sendqueue_basetime == now); + CU_ASSERT(ctx->sendqueue->t == timestamp[3] + delta1); + + now += delta2; + result = coap_adjust_basetime(ctx, now); + CU_ASSERT(result == 2); + CU_ASSERT(ctx->sendqueue_basetime == now); + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue); + CU_ASSERT(ctx->sendqueue->t == 0); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue->next); + CU_ASSERT(ctx->sendqueue->next->t == 0); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue->next->next); + CU_ASSERT(ctx->sendqueue->next->next->t == delta2 - delta1 - timestamp[1]); + + /* restore timestamps of nodes in the sendqueue */ + for (p = ctx->sendqueue, i = 0; p; p = p->next, i++) { + p->t = times[i]; + } +} + +static void +t_sendqueue6(void) { + unsigned int result; + coap_tick_t now; + const coap_tick_diff_t delta = 20; + coap_queue_t *tmpqueue = ctx->sendqueue; + + /* space for saving the current node timestamps */ + static coap_tick_t times[sizeof(timestamp)/sizeof(coap_tick_t)]; + coap_queue_t *p; + int i; + + /* save timestamps of nodes in the sendqueue in their actual order */ + memset(times, 0, sizeof(times)); + for (p = ctx->sendqueue, i = 0; p; p = p->next, i++) { + times[i] = p->t; + } + + coap_ticks(&now); + ctx->sendqueue = NULL; + ctx->sendqueue_basetime = now; + + result = coap_adjust_basetime(ctx, now + delta); + + CU_ASSERT(result == 0); + CU_ASSERT(ctx->sendqueue_basetime == now + delta); + + /* restore sendqueue */ + ctx->sendqueue = tmpqueue; +} + +static void +t_sendqueue7(void) { + int result; + coap_queue_t *tmp_node; + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue, node[3]); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue->next); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue->next, node[1]); + + result = coap_remove_from_queue(&ctx->sendqueue, session, 3, &tmp_node); + + CU_ASSERT(result == 1); + CU_ASSERT_PTR_NOT_NULL(tmp_node); + CU_ASSERT_PTR_EQUAL(tmp_node, node[3]); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue, node[1]); + + CU_ASSERT(ctx->sendqueue->t == timestamp[1]); +} + +static void +t_sendqueue8(void) { + int result; + coap_queue_t *tmp_node; + + result = coap_remove_from_queue(&ctx->sendqueue, session, 4, &tmp_node); + + CU_ASSERT(result == 1); + CU_ASSERT_PTR_NOT_NULL(tmp_node); + CU_ASSERT_PTR_EQUAL(tmp_node, node[4]); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue, node[1]); + CU_ASSERT(ctx->sendqueue->t == timestamp[1]); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue->next); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue->next, node[2]); + CU_ASSERT(ctx->sendqueue->next->t == timestamp[2] - timestamp[1]); + + CU_ASSERT_PTR_NULL(ctx->sendqueue->next->next); +} + +static void +t_sendqueue9(void) { + coap_queue_t *tmp_node; + tmp_node = coap_peek_next(ctx); + + CU_ASSERT_PTR_NOT_NULL(tmp_node); + CU_ASSERT_PTR_EQUAL(tmp_node, node[1]); + CU_ASSERT_PTR_EQUAL(tmp_node, ctx->sendqueue); + + tmp_node = coap_pop_next(ctx); + + CU_ASSERT_PTR_NOT_NULL(tmp_node); + CU_ASSERT_PTR_EQUAL(tmp_node, node[1]); + + CU_ASSERT_PTR_NOT_NULL(ctx->sendqueue); + CU_ASSERT_PTR_EQUAL(ctx->sendqueue, node[2]); + + CU_ASSERT(tmp_node->t == timestamp[1]); + CU_ASSERT(ctx->sendqueue->t == timestamp[2]); + + CU_ASSERT_PTR_NULL(ctx->sendqueue->next); +} + +static void +t_sendqueue10(void) { + coap_queue_t *tmp_node; + + tmp_node = coap_pop_next(ctx); + + CU_ASSERT_PTR_NOT_NULL(tmp_node); + CU_ASSERT_PTR_EQUAL(tmp_node, node[2]); + + CU_ASSERT_PTR_NULL(ctx->sendqueue); + + CU_ASSERT(tmp_node->t == timestamp[2]); +} + +/* This function creates a set of nodes for testing. These nodes + * will exist for all tests and are modified by coap_insert_node() + * and coap_remove_from_queue(). + */ +static int +t_sendqueue_tests_create(void) { + size_t n, error = 0; + coap_address_t addr; + coap_address_init(&addr); + + addr.size = sizeof(struct sockaddr_in6); + addr.addr.sin6.sin6_family = AF_INET6; + addr.addr.sin6.sin6_addr = in6addr_any; + addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); + + ctx = coap_new_context(&addr); + + addr.addr.sin6.sin6_addr = in6addr_loopback; + session = coap_new_client_session(ctx, NULL, &addr, COAP_PROTO_UDP); + + coap_ticks(×tamp[0]); + + memset(node, 0, sizeof(node)); + for (n = 1; n < sizeof(node)/sizeof(coap_queue_t *); n++) { + node[n] = coap_new_node(); + if (!node[n]) { + error = 1; + break; + } + + node[n]->id = n; + node[n]->t = timestamp[n]; + node[n]->session = coap_session_reference(session); + } + + if (error) { + /* destroy all test nodes and set entry to zero */ + for (n = 0; n < sizeof(node)/sizeof(coap_queue_t *); n++) { + if (node[n]) { + coap_delete_node(node[n]); + node[n] = NULL; + } + } + coap_free_context(ctx); + ctx = NULL; + } + + return error; +} + +static int +t_sendqueue_tests_remove(void) { + size_t n; + for (n = 0; n < sizeof(node)/sizeof(coap_queue_t *); n++) { + if (node[n]) { + coap_delete_node(node[n]); + node[n] = NULL; + } + } + coap_free_context(ctx); + return 0; +} + +CU_pSuite +t_init_sendqueue_tests(void) { + CU_pSuite suite; + + suite = CU_add_suite("sendqueue", + t_sendqueue_tests_create, t_sendqueue_tests_remove); + if (!suite) { /* signal error */ + fprintf(stderr, "W: cannot add sendqueue test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + +#define SENDQUEUE_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add sendqueue test (%s)\n", \ + CU_get_error_msg()); \ + } + + SENDQUEUE_TEST(suite, t_sendqueue1); + SENDQUEUE_TEST(suite, t_sendqueue2); + SENDQUEUE_TEST(suite, t_sendqueue3); + SENDQUEUE_TEST(suite, t_sendqueue4); + SENDQUEUE_TEST(suite, t_sendqueue5); + SENDQUEUE_TEST(suite, t_sendqueue6); + SENDQUEUE_TEST(suite, t_sendqueue7); + SENDQUEUE_TEST(suite, t_sendqueue8); + SENDQUEUE_TEST(suite, t_sendqueue9); + SENDQUEUE_TEST(suite, t_sendqueue10); + + return suite; +} +#endif /* COAP_CLIENT_SUPPORT */ + diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_sendqueue.h b/examples/espidf-coap-server/components/libcoap/tests/test_sendqueue.h new file mode 100644 index 000000000..b272090a0 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_sendqueue.h @@ -0,0 +1,13 @@ +/* libcoap unit tests + * + * Copyright (C) 2013 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_sendqueue_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_session.c b/examples/espidf-coap-server/components/libcoap/tests/test_session.c new file mode 100644 index 000000000..9d58e981f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_session.c @@ -0,0 +1,226 @@ +/* libcoap unit tests + * + * Copyright (C) 2013,2015-2018 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "test_common.h" +#include "test_session.h" + +#if COAP_CLIENT_SUPPORT +#include + +/* The error threshold for timeout calculations. The precision of + * coap_calc_timeout() is assumed to be sufficient if the resulting + * value deviates at most FP_ERR_THRESHOLD percent from the value that + * was calculated with double precision floating point arithmetic + * instead of fixed point integers. + */ +#define FP_ERR_THRESHOLD (1.0) + +/* The maximum number of bits for fixed point integer representation. + * This number must be identical to the definition of MAX_BITS in + * net.c + */ +#define MAX_BITS 8 + +static coap_context_t *ctx; /* Holds the coap context for most tests */ +static coap_session_t *session; /* Holds a reference-counted session object */ + +COAP_STATIC_INLINE int +fpeq(const coap_fixed_point_t a, const coap_fixed_point_t b) { + return (a.integer_part == b.integer_part) && + (a.fractional_part == b.fractional_part); +} + +static void +t_session1(void) { + CU_ASSERT(session->ref == 1); + + coap_session_reference(session); + CU_ASSERT(session->ref == 2); + + coap_session_release(session); + CU_ASSERT(session->ref == 1); +} + +static void +t_session2(void) { + CU_ASSERT(session->max_retransmit == COAP_DEFAULT_MAX_RETRANSMIT); + CU_ASSERT(fpeq(session->ack_timeout, COAP_DEFAULT_ACK_TIMEOUT)); + CU_ASSERT(fpeq(session->ack_random_factor, COAP_DEFAULT_ACK_RANDOM_FACTOR)); + + CU_ASSERT(coap_session_get_max_retransmit(session) == COAP_DEFAULT_MAX_RETRANSMIT); + CU_ASSERT(fpeq(coap_session_get_ack_timeout(session), COAP_DEFAULT_ACK_TIMEOUT)); + CU_ASSERT(fpeq(coap_session_get_ack_random_factor(session), COAP_DEFAULT_ACK_RANDOM_FACTOR)); +} + +COAP_STATIC_INLINE double +fp_to_double(const coap_fixed_point_t fp) { + return fp.integer_part + fp.fractional_part/1000.0; +} + +COAP_STATIC_INLINE double +q_to_double(uint8_t q) { + return (double)(q) / (1 << MAX_BITS); +} + +/* Calculates the timeout using the following formula: + * + * COAP_TICKS_PER_SECOND * ack_timeout * (1 + (ack_random_factor - 1) * r) + * + * where @p r is the randomization value represented as Q0.MAX_BITS. + * This function returns the result as unsigned int to be + * checked against the result of coap_calc_timeout(). + */ +COAP_STATIC_INLINE unsigned int +timeout(const coap_fixed_point_t ack_timeout, + const coap_fixed_point_t ack_random_factor, + uint8_t r) { + const unsigned int ctps = COAP_TICKS_PER_SECOND; + double ato = fp_to_double(ack_timeout); + double rnd = 1 + (fp_to_double(ack_random_factor) - 1.0) * q_to_double(r); + + return (unsigned int)(ctps * ato * rnd); +} + +/* Checks if @p v is within FP_ERR_THRESHOLD percent of @p ref. This + * function returns 1 if it is within range, 0 otherwise. + */ +COAP_STATIC_INLINE int +good_enough(unsigned int v, unsigned int ref) { +#define delta(a,b) (((a) < (b)) ? ((b) - (a)) : ((a) - (b))) + return (delta(v,ref) / 100.0) <= FP_ERR_THRESHOLD; +} + +static void +t_session3(void) { + const coap_fixed_point_t ato = COAP_DEFAULT_ACK_TIMEOUT; + const coap_fixed_point_t arf = COAP_DEFAULT_ACK_RANDOM_FACTOR; + + CU_ASSERT(good_enough(coap_calc_timeout(session, 0), timeout(ato, arf, 0))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 12), timeout(ato, arf, 12))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 55), timeout(ato, arf, 55))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 83), timeout(ato, arf, 83))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 117), timeout(ato, arf, 117))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 210), timeout(ato, arf, 210))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 255), timeout(ato, arf, 255))); +} + +static void +t_session4(void) { + const coap_fixed_point_t ato = {8,300}; + const coap_fixed_point_t arf = {2,011}; + + coap_session_set_ack_timeout(session, ato); + coap_session_set_ack_random_factor(session, arf); + + CU_ASSERT(fpeq(coap_session_get_ack_timeout(session), ato)); + CU_ASSERT(fpeq(coap_session_get_ack_random_factor(session), arf)); + + CU_ASSERT(good_enough(coap_calc_timeout(session, 0), timeout(ato, arf, 0))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 12), timeout(ato, arf, 12))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 55), timeout(ato, arf, 55))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 83), timeout(ato, arf, 83))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 117), timeout(ato, arf, 117))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 210), timeout(ato, arf, 210))); + CU_ASSERT(good_enough(coap_calc_timeout(session, 255), timeout(ato, arf, 255))); +} + +static void +t_session5(void) { + coap_session_release(session); + + CU_ASSERT_PTR_NULL(ctx->sessions); + session = NULL; +} + +/* Test 6 creates a new session after the original session has been + * released by test 5 */ +static void +t_session6(void) { + coap_address_t laddr, saddr; + coap_address_init(&laddr); + coap_address_init(&saddr); + + CU_ASSERT_PTR_NULL(session); + + laddr.size = sizeof(struct sockaddr_in6); + laddr.addr.sin6.sin6_family = AF_INET6; + laddr.addr.sin6.sin6_addr = in6addr_any; + laddr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); + + coap_address_copy(&saddr, &laddr); + saddr.addr.sin6.sin6_addr = in6addr_loopback; + saddr.addr.sin6.sin6_port = htons(20000); + + session = coap_new_client_session(ctx, &saddr, &laddr, COAP_PROTO_UDP); + CU_ASSERT_PTR_NOT_NULL(session); + CU_ASSERT_PTR_NOT_NULL(ctx->sessions); + CU_ASSERT(session->state == COAP_SESSION_STATE_ESTABLISHED); + coap_session_release(session); +} + +/* This function creates a set of nodes for testing. These nodes + * will exist for all tests and are modified by coap_insert_node() + * and coap_remove_from_queue(). + */ +static int +t_session_tests_create(void) { + coap_address_t addr; + coap_address_init(&addr); + + addr.size = sizeof(struct sockaddr_in6); + addr.addr.sin6.sin6_family = AF_INET6; + addr.addr.sin6.sin6_addr = in6addr_any; + addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); + + ctx = coap_new_context(&addr); + + if (ctx != NULL) { + addr.addr.sin6.sin6_addr = in6addr_loopback; + session = coap_new_client_session(ctx, NULL, &addr, COAP_PROTO_UDP); + } + + return (ctx == NULL) || (session == NULL); +} + +static int +t_session_tests_remove(void) { + coap_free_context(ctx); + return 0; +} + +CU_pSuite +t_init_session_tests(void) { + CU_pSuite suite; + + suite = CU_add_suite("session", + t_session_tests_create, t_session_tests_remove); + if (!suite) { /* signal error */ + fprintf(stderr, "W: cannot add session test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + +#define SESSION_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add session test (%s)\n", \ + CU_get_error_msg()); \ + } + + SESSION_TEST(suite, t_session1); + SESSION_TEST(suite, t_session2); + SESSION_TEST(suite, t_session3); + SESSION_TEST(suite, t_session4); + SESSION_TEST(suite, t_session5); + SESSION_TEST(suite, t_session6); + + return suite; +} +#endif /* COAP_CLIENT_SUPPORT */ diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_session.h b/examples/espidf-coap-server/components/libcoap/tests/test_session.h new file mode 100644 index 000000000..f598b57f1 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_session.h @@ -0,0 +1,13 @@ +/* libcoap unit tests + * + * Copyright (C) 2018 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_session_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_tls.c b/examples/espidf-coap-server/components/libcoap/tests/test_tls.c new file mode 100644 index 000000000..7e7f63b51 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_tls.c @@ -0,0 +1,129 @@ +/* libcoap unit tests + * + * Copyright (C) 2018 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "test_common.h" +#include "test_tls.h" + +#undef HAVE_DTLS + +#ifdef HAVE_LIBTINYDTLS +#define HAVE_DTLS 1 + +/* Need to #undef these to stop compiler warnings when tinydtls.h is included */ +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_URL +#undef PACKAGE_VERSION + +#include +#include +#include +#endif /* HAVE_LIBTINYDTLS */ + +#ifdef HAVE_OPENSSL +#define HAVE_DTLS 1 +#include +#endif /* HAVE_OPENSSL */ + +#ifdef HAVE_LIBGNUTLS +#define HAVE_DTLS 1 +#include +#endif /* HAVE_LIBGNUTLS */ + +#ifdef HAVE_MBEDTLS +#define HAVE_DTLS 1 +#include +#endif /* HAVE_MBEDTLS */ + +static void +t_tls1(void) { + int need_dtls = 0; +#ifdef HAVE_DTLS + need_dtls = 1; +#endif /* HAVE_DTLS */ + + CU_ASSERT(coap_dtls_is_supported() == need_dtls); +} + +static void +t_tls2(void) { + coap_tls_version_t *v = coap_get_tls_library_version(); + coap_tls_version_t version; + + memset(&version, 0, sizeof(coap_tls_version_t)); + +#if defined(HAVE_OPENSSL) + version.version = SSLeay(); + version.type = COAP_TLS_LIBRARY_OPENSSL; +#elif defined(HAVE_LIBTINYDTLS) + const char *vers = dtls_package_version(); + version.version = 0; + if (vers) { + long int p1, p2 = 0, p3 = 0; + char* endptr; + + p1 = strtol(vers, &endptr, 10); + if (*endptr == '.') { + p2 = strtol(endptr+1, &endptr, 10); + if (*endptr == '.') { + p3 = strtol(endptr+1, &endptr, 10); + } + } + version.version = (p1 << 16) | (p2 << 8) | p3; + } + version.type = COAP_TLS_LIBRARY_TINYDTLS; +#elif defined(HAVE_LIBGNUTLS) + version.version = GNUTLS_VERSION_NUMBER; + version.type = COAP_TLS_LIBRARY_GNUTLS; +#elif defined(HAVE_MBEDTLS) + version.version = MBEDTLS_VERSION_NUMBER; + version.type = COAP_TLS_LIBRARY_MBEDTLS; +#else /* no DTLS */ + version.version = 0; + version.type = COAP_TLS_LIBRARY_NOTLS; +#endif /* HAVE_OPENSSL || HAVE_LIBTINYDTLS */ + + CU_ASSERT_PTR_NOT_NULL_FATAL(v); + CU_ASSERT(version.version == v->version); + CU_ASSERT(version.type == v->type); +} + +static int +t_tls_tests_create(void) { + coap_startup(); + return 0; +} + +CU_pSuite +t_init_tls_tests(void) { + CU_pSuite suite; + + suite = CU_add_suite("TLS", t_tls_tests_create, NULL); + if (!suite) { /* signal error */ + fprintf(stderr, "W: cannot add TLS test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + +#define TLS_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add TLS test (%s)\n", \ + CU_get_error_msg()); \ + } + + TLS_TEST(suite, t_tls1); + TLS_TEST(suite, t_tls2); + + return suite; +} + diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_tls.h b/examples/espidf-coap-server/components/libcoap/tests/test_tls.h new file mode 100644 index 000000000..649cca752 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_tls.h @@ -0,0 +1,13 @@ +/* libcoap unit tests + * + * Copyright (C) 2018 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_tls_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_uri.c b/examples/espidf-coap-server/components/libcoap/tests/test_uri.c new file mode 100644 index 000000000..e0da49850 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_uri.c @@ -0,0 +1,623 @@ +/* libcoap unit tests + * + * Copyright (C) 2012,2015 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "test_common.h" +#include "test_uri.h" + +#include + +static void +t_parse_uri1(void) { + char teststr[] = "coap://[::1]/.well-known/core"; + + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result == 0) { + CU_ASSERT(uri.host.length == 3); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "::1", 3); + + CU_ASSERT(uri.port == COAP_DEFAULT_PORT); + + CU_ASSERT(uri.path.length == 16); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + } else { + CU_FAIL("uri parser error"); + } +} + +static void +t_parse_uri2(void) { + char teststr[] = "coap://[::1]:8000/.well-known/core"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result == 0) { + CU_ASSERT(uri.host.length == 3); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "::1", 3); + + CU_ASSERT(uri.port == 8000); + + CU_ASSERT(uri.path.length == 16); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + } else { + CU_FAIL("uri parser error"); + } +} + +static void +t_parse_uri3(void) { + char teststr[] = "coap://localhost/?foo&bla=fasel"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result == 0) { + CU_ASSERT(uri.host.length == 9); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "localhost", 9); + + CU_ASSERT(uri.port == COAP_DEFAULT_PORT); + + CU_ASSERT(uri.path.length == 0); + + CU_ASSERT(uri.query.length == 13); + CU_ASSERT_NSTRING_EQUAL(uri.query.s, "foo&bla=fasel", 13); + } else { + CU_FAIL("uri parser error"); + } +} + +static void +t_parse_uri4(void) { + char teststr[] = "coap://:100000"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + CU_ASSERT(result < 0); +} + +static void +t_parse_uri5(void) { + char teststr[] = "coap://foo:100000"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result == 0) { + CU_ASSERT(uri.host.length == 3); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "foo", 3); + + CU_ASSERT(uri.path.length == 0); + CU_ASSERT(uri.path.s == NULL); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + + CU_FAIL("invalid port not detected"); + } else { + CU_PASS("detected invalid port"); + } +} + +static void +t_parse_uri6(void) { + char teststr[] = "coap://134.102.218.2/.well-known/core"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result == 0) { + CU_ASSERT(uri.host.length == 13); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "134.102.218.2", 13); + + CU_ASSERT(uri.port == COAP_DEFAULT_PORT); + + CU_ASSERT(uri.path.length == 16); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + } else { + CU_FAIL("uri parser error"); + } +} + +static void +t_parse_uri7(void) { + char teststr[] = "coap://foo.bar:5683/some_resource/with/multiple/segments"; + int result; + coap_uri_t uri; + unsigned char buf[40]; + size_t buflen = sizeof(buf); + + /* The list of path segments to check against. Each segment is + preceded by a dummy option indicating that holds the (dummy) + delta value 0 and the actual segment length. */ + const uint8_t checkbuf[] = { + 0x0d, 0x00, 's', 'o', 'm', 'e', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', + 0x04, 'w', 'i', 't', 'h', + 0x08, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', + 0x08, 's', 'e', 'g', 'm', 'e', 'n', 't', 's' + }; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result == 0) { + CU_ASSERT(uri.host.length == 7); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "foo.bar", 7); + + CU_ASSERT(uri.port == 5683); + + CU_ASSERT(uri.path.length == 36); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, "some_resource/with/multiple/segments", 36); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + + /* check path segments */ + result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + CU_ASSERT(result == 4); + CU_ASSERT(buflen == sizeof(checkbuf)); + CU_ASSERT_NSTRING_EQUAL(buf, checkbuf, buflen); + } else { + CU_FAIL("uri parser error"); + } +} + +static void +t_parse_uri8(void) { + char teststr[] = "http://example.com/%7E%AB%13"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result < 0) { + CU_PASS("detected non-coap URI"); + } else { + CU_FAIL("non-coap URI not recognized"); + } +} + +static void +t_parse_uri9(void) { + char teststr[] = "http://example.com/%x"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result < 0) { + CU_PASS("detected non-coap URI"); + } else { + CU_FAIL("non-coap URI not recognized"); + } +} + +static void +t_parse_uri10(void) { + char teststr[] = "/absolute/path"; + int result; + coap_uri_t uri; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result == 0) { + CU_ASSERT(uri.host.length == 0); + CU_ASSERT(uri.host.s == NULL); + + CU_ASSERT(uri.port == COAP_DEFAULT_PORT); + + CU_ASSERT(uri.path.length == 13); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, "absolute/path", 13); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + } else { + CU_FAIL("uri parser error"); + } +} + +static void +t_parse_uri11(void) { + char teststr[] = + "coap://xn--18j4d.example/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF"; + int result; + coap_uri_t uri; + unsigned char buf[40]; + size_t buflen = sizeof(buf); + + /* The list of path segments to check against. Each segment is + preceded by a dummy option indicating that holds the (dummy) + delta value 0 and the actual segment length. */ + const uint8_t checkbuf[] = { + 0x0d, 0x02, 0xE3, 0x81, 0x93, 0xE3, 0x82, 0x93, + 0xE3, 0x81, 0xAB, 0xE3, 0x81, 0xA1, 0xE3, 0x81, + 0xAF + }; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result == 0) { + CU_ASSERT(uri.host.length == 17); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "xn--18j4d.example", 17); + + CU_ASSERT(uri.port == COAP_DEFAULT_PORT); + + CU_ASSERT(uri.path.length == 45); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, + "%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF", 45); + + CU_ASSERT(uri.query.length == 0); + CU_ASSERT(uri.query.s == NULL); + + /* check path segments */ + result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + CU_ASSERT(result == 1); + CU_ASSERT(buflen == sizeof(checkbuf)); + CU_ASSERT_NSTRING_EQUAL(buf, checkbuf, buflen); + } else { + CU_FAIL("uri parser error"); + } +} + +static void +t_parse_uri12(void) { + char teststr[] = "coap://198.51.100.1:61616//%2F//?%2F%2F&?%26"; + int result; + coap_uri_t uri; + unsigned char buf[40]; + size_t buflen = sizeof(buf); + + /* The list of path segments to check against. Each segment is + preceded by a dummy option indicating that holds the (dummy) + delta value 0 and the actual segment length. */ + const uint8_t uricheckbuf[] = { 0x00, 0x01, 0x2f, 0x00, 0x00 }; + const uint8_t querycheckbuf[] = { 0x02, 0x2f, 0x2f, 0x02, 0x3f, 0x26 }; + + result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri); + if (result == 0) { + CU_ASSERT(uri.host.length == 12); + CU_ASSERT_NSTRING_EQUAL(uri.host.s, "198.51.100.1", 12); + + CU_ASSERT(uri.port == 61616); + + CU_ASSERT(uri.path.length == 6); + CU_ASSERT_NSTRING_EQUAL(uri.path.s, "/%2F//", 6); + + CU_ASSERT(uri.query.length == 11); + CU_ASSERT_NSTRING_EQUAL(uri.query.s, "%2F%2F&?%26", 11); + + /* check path segments */ + result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + CU_ASSERT(result == 4); + CU_ASSERT(buflen == sizeof(uricheckbuf)); + CU_ASSERT_NSTRING_EQUAL(buf, uricheckbuf, buflen); + + /* check query segments */ + buflen = sizeof(buf); + result = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); + CU_ASSERT(result == 2); + CU_ASSERT(buflen == sizeof(querycheckbuf)); + CU_ASSERT_NSTRING_EQUAL(buf, querycheckbuf, buflen); + } else { + CU_FAIL("uri parser error"); + } +} + +#ifdef _MSC_VER +# define ALIGNED(x) +#else +# define ALIGNED(x) __attribute__ ((aligned (x))) +#endif + +static void +t_parse_uri13(void) { + uint8_t teststr[] ALIGNED(8) = { + 0x80, 0x03, 'f', 'o', + 'o', 0x3b, '.', 'w', 'e', 'l', 'l', '-', + 'k', 'n', 'o', 'w', 'n', 0x04, 'c', 'o', + 'r', 'e' + }; + + coap_pdu_t pdu = { + .max_size = sizeof(teststr), + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + + coap_string_t *uri_path = coap_get_uri_path(&pdu); + + CU_ASSERT(uri_path->length == sizeof(COAP_DEFAULT_URI_WELLKNOWN)-1); + CU_ASSERT_NSTRING_EQUAL(uri_path->s, COAP_DEFAULT_URI_WELLKNOWN, + sizeof(COAP_DEFAULT_URI_WELLKNOWN)-1); + coap_delete_string (uri_path); +} + +static void +t_parse_uri14(void) { + char teststr[] = + "longerthan13lessthan270=0123456789012345678901234567890123456789"; + int result; + + /* buf is large enough to hold sizeof(teststr) - 1 bytes content and + * 2 bytes for the option header. */ + unsigned char buf[sizeof(teststr) + 1]; + size_t buflen = sizeof(buf); + + result = coap_split_query((unsigned char *)teststr, strlen(teststr), + buf, &buflen); + if (result >= 0) { + CU_ASSERT(buf[0] == 0x0d); + CU_ASSERT(buf[1] == strlen(teststr) - 13); + + CU_ASSERT_NSTRING_EQUAL(buf+2, teststr, strlen(teststr)); + } else { + CU_FAIL("uri parser error"); + } +} + +static void +t_parse_uri15(void) { + char teststr[] = + "longerthan13lessthan270=0123456789012345678901234567890123456789"; + int result; + + /* buf is too small to hold sizeof(teststr) - 1 bytes content and 2 + * bytes for the option header. */ + unsigned char buf[sizeof(teststr) - 1]; + size_t buflen = sizeof(buf); + + result = coap_split_query((unsigned char *)teststr, strlen(teststr), + buf, &buflen); + CU_ASSERT(result == 0); +} + +static void +t_parse_uri16(void) { + char teststr[] = + "longerthan13lessthan270=0123456789012345678901234567890123456789"; + int result; + + /* buf is too small to hold the option header. */ + unsigned char buf[1]; + size_t buflen = sizeof(buf); + + result = coap_split_query((unsigned char *)teststr, strlen(teststr), + buf, &buflen); + CU_ASSERT(result == 0); +} + +static void +t_parse_uri17(void) { + char teststr[] = + "thisislongerthan269=" + "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890123456789"; + int result; + + /* buf is large enough to hold sizeof(teststr) - 1 bytes content and + * 3 bytes for the option header. */ + unsigned char buf[sizeof(teststr) + 2]; + size_t buflen = sizeof(buf); + + result = coap_split_query((unsigned char *)teststr, strlen(teststr), + buf, &buflen); + if (result >= 0) { + CU_ASSERT(buf[0] == 0x0e); + CU_ASSERT(buf[1] == (((strlen(teststr) - 269) >> 8) & 0xff)); + CU_ASSERT(buf[2] == ((strlen(teststr) - 269) & 0xff)); + + CU_ASSERT_NSTRING_EQUAL(buf+3, teststr, strlen(teststr)); + } else { + CU_FAIL("uri parser error"); + } +} + +static void +t_parse_uri18(void) { + uint8_t token[1] = ""; + coap_pdu_t pdu = { + .max_size = 0, + .token_length = 0, + .token = token, + .used_size = 0 + }; + + coap_string_t *uri_path = coap_get_uri_path(&pdu); + + CU_ASSERT(uri_path->length == 0); +#if 0 + /* Currently this is not the case - Issue #167 */ + /* strings are stored with terminating zero */ + CU_ASSERT_NSTRING_EQUAL(uri_path->s, "", 1); +#endif + coap_delete_string (uri_path); +} + +static void +t_parse_uri19(void) { + uint8_t teststr[] ALIGNED(8) = { + 0xb3, 'f', 'o', 'o', + 0x00 /* "foo/" as Uri-Path options */ + }; + + coap_pdu_t pdu = { + .max_size = sizeof(teststr), + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + + coap_string_t *uri_path = coap_get_uri_path(&pdu); + + CU_ASSERT(uri_path->length == 4); + CU_ASSERT_NSTRING_EQUAL(uri_path->s, "foo/", 4); + coap_delete_string (uri_path); +} + +static void +t_parse_uri20(void) { + uint8_t teststr[] ALIGNED(8) = { + 0xb0, 0x00 /* "//" as Uri-Path options */ + }; + + coap_pdu_t pdu = { + .max_size = sizeof(teststr), + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + + coap_string_t *uri_path = coap_get_uri_path(&pdu); + + /* The leading '/' is stripped hence only one '/' remains. */ + CU_ASSERT(uri_path->length == 1); + CU_ASSERT_NSTRING_EQUAL(uri_path->s, "/", 1); + coap_delete_string (uri_path); +} + +static void +t_parse_uri21(void) { + uint8_t teststr[] ALIGNED(8) = { + 0xb0, 0x03, 'f', 'o', 'o' /* "//foo" as Uri-Path options */ + }; + + coap_pdu_t pdu = { + .max_size = sizeof(teststr), + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + + coap_string_t *uri_path = coap_get_uri_path(&pdu); + + /* The leading '/' is stripped hence only one '/' remains. */ + CU_ASSERT(uri_path->length == 4); + CU_ASSERT_NSTRING_EQUAL(uri_path->s, "/foo", 4); + coap_delete_string (uri_path); +} + +static void +t_parse_uri22(void) { + uint8_t teststr[] ALIGNED(8) = { + /* characters that are not percent-encoded in a path segment */ + 0xba, '-', '.', '_', '~', '!', '$', '&', '\'', '(', ')', + 0x05, '*', '+', ',', ';', '=' + }; + + coap_pdu_t pdu = { + .max_size = sizeof(teststr), + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + + coap_string_t *uri_path = coap_get_uri_path(&pdu); + + CU_ASSERT(uri_path->length == 16); + CU_ASSERT_NSTRING_EQUAL(uri_path->s, "-._~!$&'()/*+,;=", 16); + coap_delete_string (uri_path); +} + +static void +t_parse_uri23(void) { + uint8_t teststr[] ALIGNED(8) = { + /* characters that must be percent-encoded in a path segment */ + 0xb5, '%', ' ', '#', '[', ']' + }; + + coap_pdu_t pdu = { + .max_size = sizeof(teststr), + .token_length = 0, + .token = teststr, + .used_size = sizeof(teststr) + }; + + coap_string_t *uri_path = coap_get_uri_path(&pdu); + + CU_ASSERT(uri_path->length == 15); + CU_ASSERT_NSTRING_EQUAL(uri_path->s, "%25%20%23%5B%5D", 15); + coap_delete_string (uri_path); +} + +/* + * To test Issue #212 which reads off the end of the input buffer when looking + * for . or .. in the path. + * Credit to OSS-Fuzz for finding this, work done by Bhargava Shastry + */ +static void +t_parse_uri24(void) { + /* coap://\206cap:// */ + uint8_t teststr[] = { 0x63, 0x6f, 0x61, 0x70, 0x3a, 0x2f, 0x2f, 0x86, 0x63, 0x6f, 0x61, 0x70, 0x3a, 0x2f, 0x2f }; + int result; + unsigned char buf[40]; + size_t buflen = sizeof(buf); + + result = coap_split_path(teststr, sizeof(teststr), buf, &buflen); + CU_ASSERT(result == 5); + CU_ASSERT(buflen == 16); +} + + +CU_pSuite +t_init_uri_tests(void) { + CU_pSuite suite; + + suite = CU_add_suite("uri parser", NULL, NULL); + if (!suite) { /* signal error */ + fprintf(stderr, "W: cannot add uri parser test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + +#define URI_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add uri parser test (%s)\n", \ + CU_get_error_msg()); \ + } + + URI_TEST(suite, t_parse_uri1); + URI_TEST(suite, t_parse_uri2); + URI_TEST(suite, t_parse_uri3); + URI_TEST(suite, t_parse_uri4); + URI_TEST(suite, t_parse_uri5); + URI_TEST(suite, t_parse_uri6); + URI_TEST(suite, t_parse_uri7); + URI_TEST(suite, t_parse_uri8); + URI_TEST(suite, t_parse_uri9); + URI_TEST(suite, t_parse_uri10); + URI_TEST(suite, t_parse_uri11); + URI_TEST(suite, t_parse_uri12); + URI_TEST(suite, t_parse_uri13); + URI_TEST(suite, t_parse_uri14); + URI_TEST(suite, t_parse_uri15); + URI_TEST(suite, t_parse_uri16); + URI_TEST(suite, t_parse_uri17); + URI_TEST(suite, t_parse_uri18); + URI_TEST(suite, t_parse_uri19); + URI_TEST(suite, t_parse_uri20); + URI_TEST(suite, t_parse_uri21); + URI_TEST(suite, t_parse_uri22); + URI_TEST(suite, t_parse_uri23); + URI_TEST(suite, t_parse_uri24); + + return suite; +} + diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_uri.h b/examples/espidf-coap-server/components/libcoap/tests/test_uri.h new file mode 100644 index 000000000..1c31f284f --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_uri.h @@ -0,0 +1,13 @@ +/* libcoap unit tests + * + * Copyright (C) 2012 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_uri_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_wellknown.c b/examples/espidf-coap-server/components/libcoap/tests/test_wellknown.c new file mode 100644 index 000000000..897f6d496 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_wellknown.c @@ -0,0 +1,278 @@ +/* libcoap unit tests + * + * Copyright (C) 2013--2021 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include "test_common.h" +#include "test_wellknown.h" + +#if COAP_SERVER_SUPPORT +#if COAP_CLIENT_SUPPORT +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#include +#include +#include + +#define TEST_PDU_SIZE 120 +#define TEST_URI_LEN 4 + +static coap_context_t *ctx; /* Holds the coap context for most tests */ +static coap_pdu_t *pdu; /* Holds the parsed PDU for most tests */ +static coap_session_t *session; /* Holds a reference-counted session object + * that is passed to coap_wellknown_response(). */ + +static void +t_wellknown1(void) { + coap_print_status_t result; + coap_resource_t *r; + unsigned char buf[40]; + size_t buflen, offset, ofs; + + char teststr[] = { /* ;title="some attribute";ct=0 (31 chars) */ + '<', '/', '>', ';', 't', 'i', 't', 'l', + 'e', '=', '"', 's', 'o', 'm', 'e', ' ', + 'a', 't', 't', 'r', 'i', 'b', 'u', 't', + 'e', '"', ';', 'c', 't', '=', '0' + }; + + r = coap_resource_init(NULL, 0); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"some attribute\""), 0); + + coap_add_resource(ctx, r); + + for (offset = 0; offset < sizeof(teststr); offset++) { + ofs = offset; + buflen = sizeof(buf); + + result = coap_print_link(r, buf, &buflen, &ofs); + + CU_ASSERT(result == sizeof(teststr) - offset); + CU_ASSERT(buflen == sizeof(teststr)); + CU_ASSERT(memcmp(buf, teststr + offset, sizeof(teststr) - offset) == 0); + } + + /* offset points behind teststr */ + ofs = offset; + buflen = sizeof(buf); + result = coap_print_link(r, buf, &buflen, &ofs); + + CU_ASSERT(result == 0); + CU_ASSERT(buflen == sizeof(teststr)); + + /* offset exceeds buffer */ + buflen = sizeof(buf); + ofs = buflen; + result = coap_print_link(r, buf, &buflen, &ofs); + + CU_ASSERT(result == 0); + CU_ASSERT(buflen == sizeof(teststr)); +} + +static void +t_wellknown2(void) { + coap_print_status_t result; + coap_resource_t *r; + unsigned char buf[10]; /* smaller than teststr */ + size_t buflen, offset, ofs; + + char teststr[] = { /* ,;if="one";obs (21 chars) */ + '<', '/', 'a', 'b', 'c', 'd', '>', ';', + 'i', 'f', '=', '"', 'o', 'n', 'e', '"', + ';', 'o', 'b', 's' + }; + + r = coap_resource_init(coap_make_str_const("abcd"), 0); + coap_resource_set_get_observable(r, 1); + coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"one\""), 0); + + coap_add_resource(ctx, r); + + for (offset = 0; offset < sizeof(teststr) - sizeof(buf); offset++) { + ofs = offset; + buflen = sizeof(buf); + + result = coap_print_link(r, buf, &buflen, &ofs); + + CU_ASSERT(result == (COAP_PRINT_STATUS_TRUNC | sizeof(buf))); + CU_ASSERT(buflen == sizeof(teststr)); + CU_ASSERT(ofs == 0); + CU_ASSERT(memcmp(buf, teststr + offset, sizeof(buf)) == 0); + } + + /* from here on, the resource description fits into buf */ + for (; offset < sizeof(teststr); offset++) { + ofs = offset; + buflen = sizeof(buf); + result = coap_print_link(r, buf, &buflen, &ofs); + + CU_ASSERT(result == sizeof(teststr) - offset); + CU_ASSERT(buflen == sizeof(teststr)); + CU_ASSERT(ofs == 0); + CU_ASSERT(memcmp(buf, teststr + offset, + COAP_PRINT_OUTPUT_LENGTH(result)) == 0); + } + + /* offset exceeds buffer */ + buflen = sizeof(buf); + ofs = offset; + result = coap_print_link(r, buf, &buflen, &ofs); + CU_ASSERT(result == 0); + CU_ASSERT(buflen == sizeof(teststr)); + CU_ASSERT(ofs == offset - sizeof(teststr)); +} + +static void +t_wellknown3(void) { + coap_print_status_t result; + int j; + coap_resource_t *r; + static char uris[2 * 1024]; + unsigned char *uribuf = (unsigned char *)uris; + unsigned char buf[40]; + size_t buflen = sizeof(buf); + size_t offset; + const uint16_t num_resources = (sizeof(uris) / TEST_URI_LEN) - 1; + + /* , (TEST_URI_LEN + 4 chars) */ + for (j = 0; j < num_resources; j++) { + int len = snprintf((char *)uribuf, TEST_URI_LEN + 1, + "%0*d", TEST_URI_LEN, j); + coap_str_const_t uri_path = {.length = len, .s = uribuf}; + r = coap_resource_init(&uri_path, 0); + coap_add_resource(ctx, r); + uribuf += TEST_URI_LEN; + } + + /* the following test assumes that the first two resources from + * t_wellknown1() and t_wellknown2() need more than buflen + * characters. Otherwise, CU_ASSERT(result > 0) will fail. + */ + offset = num_resources * (TEST_URI_LEN + 4); + result = coap_print_wellknown(ctx, buf, &buflen, offset, NULL); + CU_ASSERT((result & COAP_PRINT_STATUS_ERROR) == 0 ); + CU_ASSERT(COAP_PRINT_OUTPUT_LENGTH(result) > 0); +} + +static void +t_wellknown4(void) { + coap_print_status_t result; + coap_string_t *query; + unsigned char buf[40]; + size_t buflen = sizeof(buf); + char teststr[] = { /* ,;if="one";obs (21 chars) */ + '<', '/', 'a', 'b', 'c', 'd', '>', ';', + 'i', 'f', '=', '"', 'o', 'n', 'e', '"', + ';', 'o', 'b', 's' + }; + + /* Check for the resource added in t_wellknown2 */ + query = coap_new_string(sizeof("if=one")-1); + CU_ASSERT(query != NULL); + memcpy(query->s, "if=one", sizeof("if=one")-1); + result = coap_print_wellknown(ctx, buf, &buflen, 0, query); + CU_ASSERT((result & COAP_PRINT_STATUS_ERROR) == 0 ); + CU_ASSERT(COAP_PRINT_OUTPUT_LENGTH(result) == sizeof(teststr)); + CU_ASSERT(buflen == sizeof(teststr)); + CU_ASSERT(memcmp(buf, teststr, buflen) == 0); + coap_delete_string(query); +} + + +static int +t_wkc_tests_create(void) { + coap_address_t addr; + + coap_address_init(&addr); + + addr.size = sizeof(struct sockaddr_in6); + addr.addr.sin6.sin6_family = AF_INET6; + addr.addr.sin6.sin6_addr = in6addr_any; + addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); + + ctx = coap_new_context(&addr); + + addr.addr.sin6.sin6_addr = in6addr_loopback; + session = coap_new_client_session(ctx, NULL, &addr, COAP_PROTO_UDP); + + pdu = coap_pdu_init(0, 0, 0, TEST_PDU_SIZE); +#if 0 + /* add resources to coap context */ + if (ctx && pdu) { + coap_resource_t *r; + static char _buf[2 * 1024]; + unsigned char *buf = (unsigned char *)_buf; + int i; + + /* ;title="some attribute";ct=0 (31 chars) */ + r = coap_resource_init(NULL, 0, 0); + + coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); + coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"some attribute\""), 0); + coap_add_resource(ctx, r); + + /* ,;if="one";obs (21 chars) */ + r = coap_resource_init((const uint8_t *)"abcd", 4, 0); + r->observable = 1; + coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"one\""), 0); + + coap_add_resource(ctx, r); + + /* , (TEST_URI_LEN + 4 chars) */ + for (i = 0; i < sizeof(_buf) / (TEST_URI_LEN + 4); i++) { + int len = snprintf((char *)buf, TEST_URI_LEN + 1, + "%0*d", TEST_URI_LEN, i); + r = coap_resource_init(buf, len, 0); + coap_add_resource(ctx, r); + buf += TEST_URI_LEN + 1; + } + + } +#endif + return ctx == NULL || pdu == NULL; +} + +static int +t_wkc_tests_remove(void) { + coap_delete_pdu(pdu); + coap_free_context(ctx); + return 0; +} + +CU_pSuite +t_init_wellknown_tests(void) { + CU_pSuite suite; + + suite = CU_add_suite(".well-known/core", t_wkc_tests_create, t_wkc_tests_remove); + if (!suite) { /* signal error */ + fprintf(stderr, "W: cannot add .well-known/core test suite (%s)\n", + CU_get_error_msg()); + + return NULL; + } + +#define WKC_TEST(s,t) \ + if (!CU_ADD_TEST(s,t)) { \ + fprintf(stderr, "W: cannot add .well-known/core test (%s)\n", \ + CU_get_error_msg()); \ + } + + WKC_TEST(suite, t_wellknown1); + WKC_TEST(suite, t_wellknown2); + WKC_TEST(suite, t_wellknown3); + WKC_TEST(suite, t_wellknown4); + + return suite; +} +#endif /* COAP_CLIENT_SUPPORT */ +#endif /* COAP_SERVER_SUPPORT */ + diff --git a/examples/espidf-coap-server/components/libcoap/tests/test_wellknown.h b/examples/espidf-coap-server/components/libcoap/tests/test_wellknown.h new file mode 100644 index 000000000..591057c4d --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/test_wellknown.h @@ -0,0 +1,13 @@ +/* libcoap unit tests + * + * Copyright (C) 2013 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +CU_pSuite t_init_wellknown_tests(void); diff --git a/examples/espidf-coap-server/components/libcoap/tests/testdriver.c b/examples/espidf-coap-server/components/libcoap/tests/testdriver.c new file mode 100644 index 000000000..3ead61545 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/testdriver.c @@ -0,0 +1,59 @@ +/* libcoap unit tests + * + * Copyright (C) 2012-2021 Olaf Bergmann + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see + * README for terms of use. + */ + +#include + +#include +#include + +#include "test_common.h" +#include "test_uri.h" +#include "test_encode.h" +#include "test_options.h" +#include "test_pdu.h" +#include "test_error_response.h" +#include "test_session.h" +#include "test_sendqueue.h" +#include "test_wellknown.h" +#include "test_tls.h" + +int +main(int argc COAP_UNUSED, char **argv COAP_UNUSED) { + CU_ErrorCode result; + CU_BasicRunMode run_mode = CU_BRM_VERBOSE; + + if (CU_initialize_registry() != CUE_SUCCESS) { + fprintf(stderr, "E: test framework initialization failed\n"); + return -2; + } + + coap_startup(); + t_init_uri_tests(); + t_init_encode_tests(); + t_init_option_tests(); + t_init_pdu_tests(); + t_init_error_response_tests(); +#if COAP_CLIENT_SUPPORT + t_init_session_tests(); + t_init_sendqueue_tests(); +#endif /* COAP_CLIENT_SUPPORT */ +#if COAP_SERVER_SUPPORT && COAP_CLIENT_SUPPORT + t_init_wellknown_tests(); +#endif /* COAP_SERVER_SUPPORT && COAP_CLIENT_SUPPORT */ + t_init_tls_tests(); + + CU_basic_set_mode(run_mode); + result = CU_basic_run_tests(); + + CU_cleanup_registry(); + coap_cleanup(); + + return result; +} diff --git a/examples/espidf-coap-server/components/libcoap/tests/valgrind_suppression b/examples/espidf-coap-server/components/libcoap/tests/valgrind_suppression new file mode 100644 index 000000000..9632378e4 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/tests/valgrind_suppression @@ -0,0 +1,12 @@ +{ + rand_drbg_get_nonce_fix__openssl_111c_1 + Memcheck:Cond + ... + fun:SSL_CTX_new +} +{ + rand_drbg_get_nonce_fix__openssl_111c_2 + Memcheck:Cond + ... + fun:RAND_DRBG_bytes +} diff --git a/examples/espidf-coap-server/components/libcoap/win32/coap-client/coap-client.vcxproj b/examples/espidf-coap-server/components/libcoap/win32/coap-client/coap-client.vcxproj new file mode 100644 index 000000000..9a4cca682 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/coap-client/coap-client.vcxproj @@ -0,0 +1,387 @@ + + + + + Debug DLL + Win32 + + + Debug DLL + x64 + + + Debug + Win32 + + + Release DLL + Win32 + + + Release DLL + x64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Release + x64 + + + + {177F5822-F271-4903-9922-05ADAF358B1E} + Win32Proj + coap_client + $(LatestTargetPlatformVersion) + coap-client + + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + $(ProjectName)$(DbgSuffix) + $(IncludePath) + $(LibraryPath) + + + false + $(ProjectName)$(DbgSuffix) + $(IncludePath) + $(LibraryPath) + + + false + $(ProjectName)$(DbgSuffix) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(ProjectName)$(DbgSuffix) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(IncludePath) + $(LibraryPath) + + + false + $(IncludePath) + $(LibraryPath) + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + false + ../../include + CompileAsC + 4996 + + + Console + true + $(OpenSSLLibDirDbg) + libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + false + ../../include + CompileAsC + 4996 + + + Console + true + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + ../../include + false + 4996 + + + Console + true + libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + $(OpenSSLLibDirDbg) + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + ../../include + false + 4996 + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + CompileAsC + 4996 + + + Console + true + true + true + $(OpenSSLLibDir) + libcrypto.lib;libssl.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + CompileAsC + 4996 + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + 4996 + + + Console + true + true + true + libcrypto.lib;libssl.lib;%(AdditionalDependencies) + $(OpenSSLLibDir) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + 4996 + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + 4996 + + + Console + true + true + true + %(AdditionalDependencies) + + + + + + + + + {96a98759-36b3-4246-a265-cafceec0f2f2} + + + + + + diff --git a/examples/espidf-coap-server/components/libcoap/win32/coap-client/coap-client.vcxproj.filters b/examples/espidf-coap-server/components/libcoap/win32/coap-client/coap-client.vcxproj.filters new file mode 100644 index 000000000..792ddfd73 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/coap-client/coap-client.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + diff --git a/examples/espidf-coap-server/components/libcoap/win32/coap-rd/coap-rd.vcxproj b/examples/espidf-coap-server/components/libcoap/win32/coap-rd/coap-rd.vcxproj new file mode 100644 index 000000000..0a3c49e28 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/coap-rd/coap-rd.vcxproj @@ -0,0 +1,377 @@ + + + + + Debug DLL + Win32 + + + Debug DLL + x64 + + + Debug + Win32 + + + Release DLL + Win32 + + + Release DLL + x64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Release + x64 + + + + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5} + Win32Proj + coaprp + $(LatestTargetPlatformVersion) + + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + $(ProjectName)$(DbgSuffix) + $(IncludePath);..\..\include\coap3 + $(LibraryPath) + + + false + $(ProjectName)$(DbgSuffix) + $(IncludePath);..\..\include\coap3 + $(LibraryPath) + + + false + $(ProjectName)$(DbgSuffix) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;..\..\include\coap3 + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(ProjectName)$(DbgSuffix) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;..\..\include\coap3 + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(IncludePath);..\..\include\coap3 + $(LibraryPath) + + + false + $(IncludePath);..\..\include\coap3 + $(LibraryPath) + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;..\..\include\coap3 + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;..\..\include\coap3 + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;..\..\include\coap3 + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + ../../include + false + CompileAsC + + + Console + true + $(OpenSSLLibDirDbg) + libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + ../../include + false + CompileAsC + + + Console + true + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + ../../include + false + + + Console + true + $(OpenSSLLibDirDbg) + libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + ../../include + false + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + CompileAsC + + + Console + true + true + true + $(OpenSSLLibDir) + libcrypto.lib;libssl.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + CompileAsC + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + $(OpenSSLLibDir) + libcrypto.lib;libssl.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + $(OpenSSLLibDir) + %(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + + + + + + + + {96a98759-36b3-4246-a265-cafceec0f2f2} + + + + + + diff --git a/examples/espidf-coap-server/components/libcoap/win32/coap-rd/coap-rd.vcxproj.filters b/examples/espidf-coap-server/components/libcoap/win32/coap-rd/coap-rd.vcxproj.filters new file mode 100644 index 000000000..0f4136fb7 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/coap-rd/coap-rd.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/win32/coap-server/coap-server.vcxproj b/examples/espidf-coap-server/components/libcoap/win32/coap-server/coap-server.vcxproj new file mode 100644 index 000000000..9b0b14569 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/coap-server/coap-server.vcxproj @@ -0,0 +1,378 @@ + + + + + Debug DLL + Win32 + + + Debug DLL + x64 + + + Debug + Win32 + + + Release DLL + Win32 + + + Release DLL + x64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Release + x64 + + + + {F9255447-0C93-47CB-8644-62F0E6995791} + Win32Proj + coap_server + $(LatestTargetPlatformVersion) + coap-server + + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + $(ProjectName)$(DbgSuffix) + $(IncludePath) + $(LibraryPath) + + + false + $(ProjectName)$(DbgSuffix) + $(IncludePath) + $(LibraryPath) + + + false + $(ProjectName)$(DbgSuffix) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(ProjectName)$(DbgSuffix) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(IncludePath) + $(LibraryPath) + + + false + $(IncludePath) + $(LibraryPath) + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + false + ../../include + CompileAsC + + + Console + true + $(OpenSSLLibDirDbg) + libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + false + ../../include + CompileAsC + + + Console + true + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + ../../include + false + + + Console + true + $(OpenSSLLibDirDbg) + libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + ../../include + false + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + CompileAsC + + + Console + true + true + true + $(OpenSSLLibDir) + libcrypto.lib;libssl.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + CompileAsC + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + $(OpenSSLLibDir) + libcrypto.lib;libssl.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include + + + Console + true + true + true + $(OpenSSLLibDir) + %(AdditionalDependencies) + + + + + + + + {96a98759-36b3-4246-a265-cafceec0f2f2} + + + + + + diff --git a/examples/espidf-coap-server/components/libcoap/win32/coap-server/coap-server.vcxproj.filters b/examples/espidf-coap-server/components/libcoap/win32/coap-server/coap-server.vcxproj.filters new file mode 100644 index 000000000..9c67e6779 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/coap-server/coap-server.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/examples/espidf-coap-server/components/libcoap/win32/libcoap.props b/examples/espidf-coap-server/components/libcoap/win32/libcoap.props new file mode 100644 index 000000000..27c9a36c9 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/libcoap.props @@ -0,0 +1,82 @@ + + + + + $(SolutionDir)out\ + $(SolutionDir)dbg\ + + $(OPENSSL_INSTALL_PATH) + $(OPENSSL_INSTALL_PATH) + $(OpenSSLRootDir)include + $(OpenSSLRootDirDbg)include + $(OpenSSLRootDir)lib + $(OpenSSLRootDirDbg)lib + $(InstallDir) + $(InstallDirDbg) + $(CUnitRootDir)include + $(CUnitRootDirDbg)include + $(CUnitRootDir)lib + $(CUnitRootDirDbg)lib + include\coap3 + + + + + + $(InstallDir) + true + + + $(InstallDirDbg) + true + + + $(DbgSuffix) + true + + + $(OpenSSLRootDir) + + + $(OpenSSLRootDirDbg) + + + $(OpenSSLIncludeDir) + true + + + $(OpenSSLIncludeDirDbg) + true + + + $(OpenSSLLibDir) + true + + + $(OpenSSLLibDirDbg) + true + + + $(CUnitRootDir) + + + $(CUnitRootDirDbg) + + + $(CUnitIncludeDir) + true + + + $(CUnitIncludeDirDbg) + true + + + $(CUnitLibDir) + true + + + $(CUnitLibDirDbg) + true + + + diff --git a/examples/espidf-coap-server/components/libcoap/win32/libcoap.sln b/examples/espidf-coap-server/components/libcoap/win32/libcoap.sln new file mode 100644 index 000000000..8f1610f1c --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/libcoap.sln @@ -0,0 +1,144 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2010 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcoap", "libcoap.vcxproj", "{96A98759-36B3-4246-A265-CAFCEEC0F2F2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "coap-client", "coap-client\coap-client.vcxproj", "{177F5822-F271-4903-9922-05ADAF358B1E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "coap-server", "coap-server\coap-server.vcxproj", "{F9255447-0C93-47CB-8644-62F0E6995791}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testdriver", "testdriver\testdriver.vcxproj", "{C21580DF-4786-441E-B921-21E66DFA926E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "coap-rd", "coap-rd\coap-rd.vcxproj", "{640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "install", "install\install.vcxproj", "{150F429D-82C6-4EA2-B1B2-16EF35F9C11A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug DLL|x64 = Debug DLL|x64 + Debug DLL|x86 = Debug DLL|x86 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + NoTLS|x64 = NoTLS|x64 + NoTLS|x86 = NoTLS|x86 + Release DLL|x64 = Release DLL|x64 + Release DLL|x86 = Release DLL|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Debug DLL|x86.ActiveCfg = Debug DLL|Win32 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Debug DLL|x86.Build.0 = Debug DLL|Win32 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Debug|x64.ActiveCfg = Debug|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Debug|x64.Build.0 = Debug|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Debug|x86.ActiveCfg = Debug|Win32 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Debug|x86.Build.0 = Debug|Win32 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.NoTLS|x64.ActiveCfg = NoTLS|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.NoTLS|x64.Build.0 = NoTLS|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.NoTLS|x86.ActiveCfg = NoTLS|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Release DLL|x64.Build.0 = Release DLL|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Release DLL|x86.ActiveCfg = Release DLL|Win32 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Release DLL|x86.Build.0 = Release DLL|Win32 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Release|x64.ActiveCfg = Release|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Release|x64.Build.0 = Release|x64 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Release|x86.ActiveCfg = Release|Win32 + {96A98759-36B3-4246-A265-CAFCEEC0F2F2}.Release|x86.Build.0 = Release|Win32 + {177F5822-F271-4903-9922-05ADAF358B1E}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.Debug DLL|x86.ActiveCfg = Debug DLL|Win32 + {177F5822-F271-4903-9922-05ADAF358B1E}.Debug DLL|x86.Build.0 = Debug DLL|Win32 + {177F5822-F271-4903-9922-05ADAF358B1E}.Debug|x64.ActiveCfg = Debug|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.Debug|x64.Build.0 = Debug|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.Debug|x86.ActiveCfg = Debug|Win32 + {177F5822-F271-4903-9922-05ADAF358B1E}.Debug|x86.Build.0 = Debug|Win32 + {177F5822-F271-4903-9922-05ADAF358B1E}.NoTLS|x64.ActiveCfg = NoTLS|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.NoTLS|x64.Build.0 = NoTLS|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.NoTLS|x86.ActiveCfg = NoTLS|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.Release DLL|x64.Build.0 = Release DLL|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.Release DLL|x86.ActiveCfg = Release DLL|Win32 + {177F5822-F271-4903-9922-05ADAF358B1E}.Release DLL|x86.Build.0 = Release DLL|Win32 + {177F5822-F271-4903-9922-05ADAF358B1E}.Release|x64.ActiveCfg = Release|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.Release|x64.Build.0 = Release|x64 + {177F5822-F271-4903-9922-05ADAF358B1E}.Release|x86.ActiveCfg = Release|Win32 + {177F5822-F271-4903-9922-05ADAF358B1E}.Release|x86.Build.0 = Release|Win32 + {F9255447-0C93-47CB-8644-62F0E6995791}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.Debug DLL|x86.ActiveCfg = Debug DLL|Win32 + {F9255447-0C93-47CB-8644-62F0E6995791}.Debug DLL|x86.Build.0 = Debug DLL|Win32 + {F9255447-0C93-47CB-8644-62F0E6995791}.Debug|x64.ActiveCfg = Debug|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.Debug|x64.Build.0 = Debug|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.Debug|x86.ActiveCfg = Debug|Win32 + {F9255447-0C93-47CB-8644-62F0E6995791}.Debug|x86.Build.0 = Debug|Win32 + {F9255447-0C93-47CB-8644-62F0E6995791}.NoTLS|x64.ActiveCfg = NoTLS|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.NoTLS|x64.Build.0 = NoTLS|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.NoTLS|x86.ActiveCfg = NoTLS|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.Release DLL|x64.Build.0 = Release DLL|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.Release DLL|x86.ActiveCfg = Release DLL|Win32 + {F9255447-0C93-47CB-8644-62F0E6995791}.Release DLL|x86.Build.0 = Release DLL|Win32 + {F9255447-0C93-47CB-8644-62F0E6995791}.Release|x64.ActiveCfg = Release|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.Release|x64.Build.0 = Release|x64 + {F9255447-0C93-47CB-8644-62F0E6995791}.Release|x86.ActiveCfg = Release|Win32 + {F9255447-0C93-47CB-8644-62F0E6995791}.Release|x86.Build.0 = Release|Win32 + {C21580DF-4786-441E-B921-21E66DFA926E}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {C21580DF-4786-441E-B921-21E66DFA926E}.Debug DLL|x86.ActiveCfg = Debug DLL|Win32 + {C21580DF-4786-441E-B921-21E66DFA926E}.Debug|x64.ActiveCfg = Debug|x64 + {C21580DF-4786-441E-B921-21E66DFA926E}.Debug|x86.ActiveCfg = Debug|Win32 + {C21580DF-4786-441E-B921-21E66DFA926E}.NoTLS|x64.ActiveCfg = NoTLS|x64 + {C21580DF-4786-441E-B921-21E66DFA926E}.NoTLS|x86.ActiveCfg = NoTLS|x64 + {C21580DF-4786-441E-B921-21E66DFA926E}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {C21580DF-4786-441E-B921-21E66DFA926E}.Release DLL|x86.ActiveCfg = Release DLL|Win32 + {C21580DF-4786-441E-B921-21E66DFA926E}.Release|x64.ActiveCfg = Release|x64 + {C21580DF-4786-441E-B921-21E66DFA926E}.Release|x86.ActiveCfg = Release|Win32 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Debug DLL|x86.ActiveCfg = Debug DLL|Win32 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Debug DLL|x86.Build.0 = Debug DLL|Win32 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Debug|x64.ActiveCfg = Debug|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Debug|x64.Build.0 = Debug|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Debug|x86.ActiveCfg = Debug|Win32 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Debug|x86.Build.0 = Debug|Win32 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.NoTLS|x64.ActiveCfg = NoTLS|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.NoTLS|x64.Build.0 = NoTLS|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.NoTLS|x86.ActiveCfg = NoTLS|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Release DLL|x64.ActiveCfg = Release DLL|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Release DLL|x64.Build.0 = Release DLL|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Release DLL|x86.ActiveCfg = Release DLL|Win32 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Release DLL|x86.Build.0 = Release DLL|Win32 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Release|x64.ActiveCfg = Release|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Release|x64.Build.0 = Release|x64 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Release|x86.ActiveCfg = Release|Win32 + {640AC988-FE9E-4580-BDF5-0D9FD57C3CE5}.Release|x86.Build.0 = Release|Win32 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Debug DLL|x64.ActiveCfg = Debug DLL|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Debug DLL|x64.Build.0 = Debug DLL|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Debug DLL|x86.ActiveCfg = Debug DLL|Win32 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Debug DLL|x86.Build.0 = Debug DLL|Win32 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Debug|x64.ActiveCfg = Debug|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Debug|x64.Build.0 = Debug|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Debug|x86.ActiveCfg = Debug|Win32 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Debug|x86.Build.0 = Debug|Win32 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.NoTLS|x64.ActiveCfg = NoTLS|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.NoTLS|x64.Build.0 = NoTLS|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.NoTLS|x86.ActiveCfg = NoTLS|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Release DLL|x64.ActiveCfg = Release|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Release DLL|x64.Build.0 = Release|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Release DLL|x86.ActiveCfg = Release DLL|Win32 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Release DLL|x86.Build.0 = Release DLL|Win32 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Release|x64.ActiveCfg = Release|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Release|x64.Build.0 = Release|x64 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Release|x86.ActiveCfg = Release|Win32 + {150F429D-82C6-4EA2-B1B2-16EF35F9C11A}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5DCF7800-FBBF-4AD7-A3B5-E70B574A9CE5} + EndGlobalSection +EndGlobal diff --git a/examples/espidf-coap-server/components/libcoap/win32/libcoap.vcxproj b/examples/espidf-coap-server/components/libcoap/win32/libcoap.vcxproj new file mode 100644 index 000000000..d494f7558 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/libcoap.vcxproj @@ -0,0 +1,629 @@ + + + + + Debug DLL + Win32 + + + Debug DLL + x64 + + + Debug + Win32 + + + Release DLL + Win32 + + + Release DLL + x64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + NoTLS + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + true + true + true + true + true + ECHO LIBRARY $(TargetName) > "$(IntDir)$(TargetName).def" +ECHO EXPORTS >> "$(IntDir)$(TargetName).def" +TYPE %(FullPath) >> "$(IntDir)$(TargetName).def" + ECHO LIBRARY $(TargetName) > "$(IntDir)$(TargetName).def" +ECHO EXPORTS >> "$(IntDir)$(TargetName).def" +TYPE %(FullPath) >> "$(IntDir)$(TargetName).def" + ECHO LIBRARY $(TargetName) > "$(IntDir)$(TargetName).def" +ECHO EXPORTS >> "$(IntDir)$(TargetName).def" +TYPE %(FullPath) >> "$(IntDir)$(TargetName).def" + ECHO LIBRARY $(TargetName) > "$(IntDir)$(TargetName).def" +ECHO EXPORTS >> "$(IntDir)$(TargetName).def" +TYPE %(FullPath) >> "$(IntDir)$(TargetName).def" + ECHO LIBRARY $(TargetName) > "$(IntDir)$(TargetName).def" +ECHO EXPORTS >> "$(IntDir)$(TargetName).def" +TYPE %(FullPath) >> "$(IntDir)$(TargetName).def" + ECHO LIBRARY $(TargetName) > "$(IntDir)$(TargetName).def" +ECHO EXPORTS >> "$(IntDir)$(TargetName).def" +TYPE %(FullPath) >> "$(IntDir)$(TargetName).def" + ECHO LIBRARY $(TargetName) > "$(IntDir)$(TargetName).def" +ECHO EXPORTS >> "$(IntDir)$(TargetName).def" +TYPE %(FullPath) >> "$(IntDir)$(TargetName).def" + ECHO LIBRARY $(TargetName) > "$(IntDir)$(TargetName).def" +ECHO EXPORTS >> "$(IntDir)$(TargetName).def" +TYPE %(FullPath) >> "$(IntDir)$(TargetName).def" + ECHO LIBRARY $(TargetName) > "$(IntDir)$(TargetName).def" +ECHO EXPORTS >> "$(IntDir)$(TargetName).def" +TYPE %(FullPath) >> "$(IntDir)$(TargetName).def" + Creating module definition file + Creating module definition file + Creating module definition file + Creating module definition file + Creating module definition file + Creating module definition file + Creating module definition file + Creating module definition file + Creating module definition file + $(IntDir)$(TargetName).def + $(IntDir)$(TargetName).def + $(IntDir)$(TargetName).def + $(IntDir)$(TargetName).def + $(IntDir)$(TargetName).def + $(IntDir)$(TargetName).def + $(IntDir)$(TargetName).def + $(IntDir)$(TargetName).def + $(IntDir)$(TargetName).def + false + false + false + false + false + false + false + false + false + + + + {96A98759-36B3-4246-A265-CAFCEEC0F2F2} + Win32Proj + libcoap + $(LatestTargetPlatformVersion) + + + + StaticLibrary + true + $(DefaultPlatformToolset) + MultiByte + + + DynamicLibrary + true + $(DefaultPlatformToolset) + MultiByte + + + StaticLibrary + false + $(DefaultPlatformToolset) + true + MultiByte + + + DynamicLibrary + false + $(DefaultPlatformToolset) + true + MultiByte + + + StaticLibrary + true + $(DefaultPlatformToolset) + MultiByte + + + DynamicLibrary + true + $(DefaultPlatformToolset) + MultiByte + + + StaticLibrary + false + $(DefaultPlatformToolset) + true + MultiByte + + + DynamicLibrary + false + $(DefaultPlatformToolset) + true + MultiByte + + + StaticLibrary + false + $(DefaultPlatformToolset) + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(ProjectName)$(DbgSuffix) + + + + + $(IncludePath) + $(LibraryPath) + + + $(ProjectName)-3$(DbgSuffix)-openssl + + + $(IncludePath) + $(LibraryPath) + + + + + + + $(IncludePath) + $(LibraryPath) + + + + + $(ProjectName)-3-openssl + $(IncludePath) + $(LibraryPath) + false + + + $(ProjectName)-3$(DbgSuffix)-openssl + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + $(ProjectName)$(DbgSuffix) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + $(ProjectName)-3-openssl + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + false + + + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + $(ProjectName)-3 + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + + NotUsing + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_LIB;HAVE_OPENSSL;%(PreprocessorDefinitions) + ProgramDatabase + ../include;..;$(OpenSSLIncludeDirDbg) + $(IntDir)$(TargetName).pdb + false + CompileAsC + + + Windows + + + copy /Y ..\coap_config.h.windows ..\coap_config.h +copy /Y ..\$(LibCoAPIncludeDir)\coap.h.windows ..\$(LibCoAPIncludeDir)\coap.h + + + Copying config files for windows + + + + + + + + + + + + + + + + + + + + + NotUsing + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_LIB;HAVE_OPENSSL;%(PreprocessorDefinitions) + ProgramDatabase + ../include;..;$(OpenSSLIncludeDirDbg) + false + CompileAsC + + + Windows + true + $(IntDir)$(TargetName).def + libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + $(OpenSSLLibDirDbg) + Default + + + copy /Y ..\coap_config.h.windows ..\coap_config.h +copy /Y ..\$(LibCoAPIncludeDir)\coap.h.windows ..\$(LibCoAPIncludeDir)\coap.h + + + Copying config files for windows + + + + + + + + + + + + + + + + + + + + + NotUsing + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_LIB;HAVE_OPENSSL;%(PreprocessorDefinitions) + ProgramDatabase + ../include;..;$(OpenSSLIncludeDirDbg) + NotSet + CompileAsC + false + $(IntDir)$(TargetName).pdb + + + Windows + + + copy /Y ..\coap_config.h.windows ..\coap_config.h +copy /Y ..\$(LibCoAPIncludeDir)\coap.h.windows ..\$(LibCoAPIncludeDir)\coap.h + Copying config files for windows + + + + + NotUsing + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_LIB;HAVE_OPENSSL;%(PreprocessorDefinitions) + ProgramDatabase + ../include;..;$(OpenSSLIncludeDirDbg) + NotSet + CompileAsC + false + + + Windows + true + $(IntDir)$(TargetName).def + libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + $(OpenSSLLibDirDbg) + + + copy /Y ..\coap_config.h.windows ..\coap_config.h +copy /Y ..\$(LibCoAPIncludeDir)\coap.h.windows ..\$(LibCoAPIncludeDir)\coap.h + Copying config files for windows + + + + + Level3 + NotUsing + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;HAVE_OPENSSL;%(PreprocessorDefinitions) + ../include;..;$(OpenSSLIncludeDir) + $(IntDir)$(TargetName).pdb + CompileAsC + + + Windows + true + true + + + copy /Y ..\coap_config.h.windows ..\coap_config.h +copy /Y ..\$(LibCoAPIncludeDir)\coap.h.windows ..\$(LibCoAPIncludeDir)\coap.h + + + Copying config files for windows + + + + + + + + + + + + + + + + + + + + + Level3 + NotUsing + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;HAVE_OPENSSL;%(PreprocessorDefinitions) + ../include;..;$(OpenSSLIncludeDir) + CompileAsC + + + Windows + true + true + $(IntDir)$(TargetName).def + libcrypto.lib;libssl.lib;%(AdditionalDependencies) + $(OpenSSLLibDir) + true + UseLinkTimeCodeGeneration + + + copy /Y ..\coap_config.h.windows ..\coap_config.h +copy /Y ..\$(LibCoAPIncludeDir)\coap.h.windows ..\$(LibCoAPIncludeDir)\coap.h + + + Copying config files for windows + + + + + + + + + + + + + + + + + + + + + Level3 + NotUsing + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;HAVE_OPENSSL;%(PreprocessorDefinitions) + ../include;..;$(OpenSSLIncludeDir) + NotSet + CompileAsC + $(IntDir)$(TargetName).pdb + + + Windows + true + true + + + copy /Y ..\coap_config.h.windows ..\coap_config.h +copy /Y ..\$(LibCoAPIncludeDir)\coap.h.windows ..\$(LibCoAPIncludeDir)\coap.h + Copying config files for windows + + + + + Level3 + NotUsing + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;HAVE_OPENSSL;%(PreprocessorDefinitions) + ../include;..;$(OpenSSLIncludeDir) + NotSet + CompileAsC + + + Windows + true + true + $(IntDir)$(TargetName).def + libcrypto.lib;libssl.lib;%(AdditionalDependencies) + true + UseLinkTimeCodeGeneration + $(OpenSSLLibDir) + + + copy /Y ..\coap_config.h.windows ..\coap_config.h +copy /Y ..\$(LibCoAPIncludeDir)\coap.h.windows ..\$(LibCoAPIncludeDir)\coap.h + Copying config files for windows + + + + + Level3 + NotUsing + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;%(PreprocessorDefinitions) + ../include;.. + NotSet + CompileAsC + $(IntDir)$(TargetName).pdb + + + Windows + true + true + + + copy /Y ..\coap_config.h.windows ..\coap_config.h +copy /Y ..\$(LibCoAPIncludeDir)\coap.h.windows ..\$(LibCoAPIncludeDir)\coap.h + Copying config files for windows + + + + + + diff --git a/examples/espidf-coap-server/components/libcoap/win32/libcoap.vcxproj.filters b/examples/espidf-coap-server/components/libcoap/win32/libcoap.vcxproj.filters new file mode 100644 index 000000000..911929b84 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/libcoap.vcxproj.filters @@ -0,0 +1,204 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + + diff --git a/examples/espidf-coap-server/components/libcoap/win32/testdriver/testdriver.vcxproj b/examples/espidf-coap-server/components/libcoap/win32/testdriver/testdriver.vcxproj new file mode 100644 index 000000000..700acf8c0 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/testdriver/testdriver.vcxproj @@ -0,0 +1,401 @@ + + + + + Debug DLL + Win32 + + + Debug DLL + x64 + + + Debug + Win32 + + + Release DLL + Win32 + + + Release DLL + x64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Release + x64 + + + + {C21580DF-4786-441E-B921-21E66DFA926E} + Win32Proj + testdriver + $(LatestTargetPlatformVersion) + + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + true + $(DefaultPlatformToolset) + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + Application + false + $(DefaultPlatformToolset) + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(ProjectName) + $(IncludePath) + $(LibraryPath) + + + true + $(ProjectName) + $(IncludePath) + $(LibraryPath) + + + true + $(ProjectName) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + true + $(ProjectName) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(IncludePath) + $(LibraryPath) + + + false + $(IncludePath) + $(LibraryPath) + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(SolutionDir)lib + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + false + ../../include;../..;..;$(CUnitIncludeDirDbg);$(OpenSSLIncludeDirDbg) + CompileAsC + + + Console + true + libcunit$(DbgSuffix)_dll.lib;libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + $(OpenSSLLibDirDbg);$(CUnitLibDirDbg) + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ProgramDatabase + false + ../../include;../..;..;$(CUnitIncludeDirDbg);$(OpenSSLIncludeDirDbg) + CompileAsC + + + Console + true + libcunit$(DbgSuffix)_dll.lib;libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + $(OpenSSLLibDirDbg);$(CUnitLibDirDbg) + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include;../..;..;$(CUnitIncludeDirDbg);$(OpenSSLIncludeDirDbg) + ProgramDatabase + + + Console + true + libcunit$(DbgSuffix)_dll.lib;libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + $(OpenSSLLibDirDbg);$(CUnitLibDirDbg) + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include;../..;..;$(CUnitIncludeDirDbg);$(OpenSSLIncludeDirDbg) + ProgramDatabase + + + Console + true + libcunit$(DbgSuffix)_dll.lib;libcrypto$(DbgSuffix).lib;libssl$(DbgSuffix).lib;%(AdditionalDependencies) + $(OpenSSLLibDirDbg);$(CUnitLibDirDbg) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include;../..;..;$(CUnitIncludeDir);$(OpenSSLIncludeDir) + CompileAsC + + + Console + true + true + true + libcunit_dll.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) + $(OpenSSLLibDir);$(CUnitLibDir) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include;../..;..;$(CUnitIncludeDir);$(OpenSSLIncludeDir) + CompileAsC + + + Console + true + true + true + libcunit_dll.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) + $(OpenSSLLibDir);$(CUnitLibDir) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include;../..;..;$(CUnitIncludeDir);$(OpenSSLIncludeDir) + + + Console + true + true + true + libcunit_dll.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) + $(OpenSSLLibDir);$(CUnitLibDir) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include;../..;..;$(CUnitIncludeDir);$(OpenSSLIncludeDir) + + + Console + true + true + true + libcunit_dll.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies) + $(OpenSSLLibDir);$(CUnitLibDir) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../include;../..;..;$(CUnitIncludeDir);$(OpenSSLIncludeDir) + + + Console + true + true + true + libcunit_dll.lib;%(AdditionalDependencies) + $(OpenSSLLibDir);$(CUnitLibDir) + + + + + {96a98759-36b3-4246-a265-cafceec0f2f2} + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/espidf-coap-server/components/libcoap/win32/testdriver/testdriver.vcxproj.filters b/examples/espidf-coap-server/components/libcoap/win32/testdriver/testdriver.vcxproj.filters new file mode 100644 index 000000000..5ca73a375 --- /dev/null +++ b/examples/espidf-coap-server/components/libcoap/win32/testdriver/testdriver.vcxproj.filters @@ -0,0 +1,72 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/examples/espidf-coap-server/components/port/include/coap3/coap.h b/examples/espidf-coap-server/components/port/include/coap3/coap.h new file mode 100644 index 000000000..594d9680d --- /dev/null +++ b/examples/espidf-coap-server/components/port/include/coap3/coap.h @@ -0,0 +1,51 @@ +/* Modify head file implementation for ESP32 platform. + * + * Uses libcoap software implementation for failover when concurrent + * define operations are in use. + * + * coap.h -- main header file for CoAP stack of libcoap + * + * Copyright (C) 2010-2012,2015-2016 Olaf Bergmann + * 2015 Carsten Schoenert + * + * Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef _COAP_H_ +#define _COAP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "coap3/libcoap.h" + +#include "coap3/coap_forward_decls.h" +#include "coap3/block.h" +#include "coap3/coap_address.h" +#include "coap3/coap_async.h" +#include "coap3/coap_cache.h" +#include "coap3/coap_debug.h" +#include "coap3/coap_dtls.h" +#include "coap3/coap_event.h" +#include "coap3/coap_io.h" +#include "coap3/coap_option.h" +#include "coap3/coap_prng.h" +#include "coap3/coap_subscribe.h" +#include "coap3/coap_time.h" +#include "coap3/encode.h" +#include "coap3/mem.h" +#include "coap3/net.h" +#include "coap3/pdu.h" +#include "coap3/resource.h" +#include "coap3/str.h" +#include "coap3/uri.h" + +#ifdef __cplusplus +} +#endif + +#endif /* _COAP_H_ */ diff --git a/examples/espidf-coap-server/components/port/include/coap_config.h b/examples/espidf-coap-server/components/port/include/coap_config.h new file mode 100644 index 000000000..bf4de3b6a --- /dev/null +++ b/examples/espidf-coap-server/components/port/include/coap_config.h @@ -0,0 +1,59 @@ +/* + * libcoap configure implementation for ESP32 platform. + * + * Uses libcoap software implementation for failover when concurrent + * configure operations are in use. + * + * coap.h -- main header file for CoAP stack of libcoap + * + * Copyright (C) 2010-2012,2015-2016 Olaf Bergmann + * 2015 Carsten Schoenert + * + * Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +/* Always enabled in ESP-IDF */ +#ifndef WITH_POSIX +#define WITH_POSIX +#endif + +#include "coap_config_posix.h" + +#define HAVE_STDIO_H +#define HAVE_ASSERT_H +#define HAVE_INTTYPES_H + +#define PACKAGE_STRING PACKAGE_NAME PACKAGE_VERSION + +/* it's just provided by libc. i hope we don't get too many of those, as + * actually we'd need autotools again to find out what environment we're + * building in */ +#define HAVE_STRNLEN 1 + +#define HAVE_LIMITS_H + +#define COAP_RESOURCES_NOHASH + +/* Note: If neither of COAP_CLIENT_SUPPORT or COAP_SERVER_SUPPORT is set, + then libcoap sets both for backward compatability */ +#ifdef CONFIG_COAP_CLIENT_SUPPORT +#define COAP_CLIENT_SUPPORT 1 +#endif /* CONFIG_COAP_CLIENT_SUPPORT */ + +#ifdef CONFIG_COAP_SERVER_SUPPORT +#define COAP_SERVER_SUPPORT 1 +#endif /* CONFIG_COAP_SERVER_SUPPORT */ + +#ifdef CONFIG_COAP_TCP_SUPPORT +#define COAP_DISABLE_TCP 0 +#else /* ! CONFIG_COAP_TCP_SUPPORT */ +#define COAP_DISABLE_TCP 1 +#endif /* ! CONFIG_COAP_TCP_SUPPORT */ + +#endif /* _CONFIG_H_ */ diff --git a/examples/espidf-coap-server/components/port/include/coap_config_posix.h b/examples/espidf-coap-server/components/port/include/coap_config_posix.h new file mode 100644 index 000000000..a79583b15 --- /dev/null +++ b/examples/espidf-coap-server/components/port/include/coap_config_posix.h @@ -0,0 +1,61 @@ +/* + * libcoap configure implementation for ESP32 platform. + * + * Uses libcoap software implementation for failover when concurrent + * configure operations are in use. + * + * coap.h -- main header file for CoAP stack of libcoap + * + * Copyright (C) 2010-2012,2015-2016 Olaf Bergmann + * 2015 Carsten Schoenert + * + * Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +#ifndef COAP_CONFIG_POSIX_H_ +#define COAP_CONFIG_POSIX_H_ + +#ifdef WITH_POSIX + +#include +#include + +#define HAVE_SYS_SOCKET_H +#define HAVE_MALLOC +#define HAVE_ARPA_INET_H +#define HAVE_TIME_H +#define HAVE_NETDB_H +#define HAVE_NETINET_IN_H +#define HAVE_STRUCT_CMSGHDR +#define HAVE_PTHREAD_H +#define HAVE_PTHREAD_MUTEX_LOCK + +#define ipi_spec_dst ipi_addr +struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ +}; +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((((__const uint32_t *) (a))[0] == 0) \ + && (((__const uint32_t *) (a))[1] == 0) \ + && (((__const uint32_t *) (a))[2] == htonl (0xffff))) + +/* As not defined, just need to define is as something innocuous */ +#define IPV6_PKTINFO IPV6_CHECKSUM + +#define PACKAGE_NAME "libcoap-posix" +#define PACKAGE_VERSION "4.3.1" + +#ifdef CONFIG_MBEDTLS_TLS_ENABLED +#define HAVE_MBEDTLS +#endif /* CONFIG_MBEDTLS_TLS_ENABLED */ +#define COAP_CONSTRAINED_STACK 1 +#define ESPIDF_VERSION + +#define gai_strerror(x) "gai_strerror() not supported" + +#endif /* WITH_POSIX */ +#endif /* COAP_CONFIG_POSIX_H_ */ diff --git a/examples/espidf-coap-server/platformio.ini b/examples/espidf-coap-server/platformio.ini index 2a72c71fc..78383c341 100644 --- a/examples/espidf-coap-server/platformio.ini +++ b/examples/espidf-coap-server/platformio.ini @@ -5,13 +5,13 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env] platform = espressif32 framework = espidf monitor_speed = 115200 -board_build.embed_txtfiles = +board_build.embed_txtfiles = src/certs/coap_ca.pem src/certs/coap_server.crt src/certs/coap_server.key diff --git a/examples/espidf-coap-server/sdkconfig.defaults b/examples/espidf-coap-server/sdkconfig.defaults index 19e6d679b..8bc64e086 100644 --- a/examples/espidf-coap-server/sdkconfig.defaults +++ b/examples/espidf-coap-server/sdkconfig.defaults @@ -1,5 +1,5 @@ -CONFIG_EXAMPLE_WIFI_SSID="MYSSID" -CONFIG_EXAMPLE_WIFI_PASSWORD="MYPASS" CONFIG_MBEDTLS_SSL_PROTO_DTLS=y CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_LWIP_NETBUF_RECVINFO=y +CONFIG_COAP_SERVER_SUPPORT=y diff --git a/examples/espidf-coap-server/src/CMakeLists.txt b/examples/espidf-coap-server/src/CMakeLists.txt index c28a7be75..a014088ec 100644 --- a/examples/espidf-coap-server/src/CMakeLists.txt +++ b/examples/espidf-coap-server/src/CMakeLists.txt @@ -1,2 +1,3 @@ idf_component_register(SRCS "coap_server_example_main.c" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS "." + EMBED_TXTFILES certs/coap_ca.pem certs/coap_server.crt certs/coap_server.key) diff --git a/examples/espidf-coap-server/src/Kconfig.projbuild b/examples/espidf-coap-server/src/Kconfig.projbuild index 19da8165a..3c0fbfc23 100644 --- a/examples/espidf-coap-server/src/Kconfig.projbuild +++ b/examples/espidf-coap-server/src/Kconfig.projbuild @@ -8,4 +8,54 @@ menu "Example CoAP Server Configuration" The Preshared Key to use to encrypt the communicatons. The same key must be used at both ends of the CoAP connection, and the CoaP client must request an URI prefixed with coaps:// instead of coap:// for DTLS to be used. + + choice EXAMPLE_COAP_MCAST_IP_MODE + prompt "Receive Multicast IP type" + help + Example can receive multicast IPV4, IPV6, both or none. + + config EXAMPLE_COAP_MCAST_NONE + bool "None" + + config EXAMPLE_COAP_MCAST_IPV4_V6 + bool "IPV4 & IPV6" + select EXAMPLE_COAP_MCAST_IPV4 + select EXAMPLE_COAP_MCAST_IPV6 + + config EXAMPLE_COAP_MCAST_IPV4_ONLY + bool "IPV4" + select EXAMPLE_COAP_MCAST_IPV4 + + config EXAMPLE_COAP_MCAST_IPV6_ONLY + bool "IPV6" + select EXAMPLE_COAP_MCAST_IPV6 + + endchoice + + config EXAMPLE_COAP_MCAST_IPV4 + bool + config EXAMPLE_COAP_MCAST_IPV6 + bool + select EXAMPLE_CONNECT_IPV6 if IDF_TARGET_ESP32 + + config EXAMPLE_COAP_MULTICAST_IPV4_ADDR + string "CoAP Multicast IPV4 Address (receive)" + default "224.0.1.187" + depends on EXAMPLE_COAP_MCAST_IPV4 + help + IPV4 multicast address to receive multicast traffic on. + + The default CoAP IPV4 address is 224.0.1.187. + + config EXAMPLE_COAP_MULTICAST_IPV6_ADDR + string "CoAP Multicast IPV6 Address (receive)" + default "FF02::FD" + depends on EXAMPLE_COAP_MCAST_IPV6 + help + IPV6 multicast address to receive multicast traffic on. + + The default CoAP FF02::FD address is a link-local multicast address. + Consult IPV6 specifications or documentation for information about + meaning of different IPV6 multicast ranges. + endmenu diff --git a/examples/espidf-coap-server/src/coap_server_example_main.c b/examples/espidf-coap-server/src/coap_server_example_main.c index ed96cc6e2..66ea76f61 100644 --- a/examples/espidf-coap-server/src/coap_server_example_main.c +++ b/examples/espidf-coap-server/src/coap_server_example_main.c @@ -31,6 +31,10 @@ #include "coap3/coap.h" +#ifndef CONFIG_COAP_SERVER_SUPPORT +#error COAP_SERVER_SUPPORT needs to be enabled +#endif /* COAP_SERVER_SUPPORT */ + /* The examples use simple Pre-Shared-Key configuration that you can set via 'idf.py menuconfig'. @@ -187,6 +191,7 @@ static void coap_example_server(void *p) while (1) { coap_endpoint_t *ep = NULL; unsigned wait_ms; + int have_dtls = 0; /* Prepare the CoAP server socket */ coap_address_init(&serv_addr); @@ -258,16 +263,18 @@ static void coap_example_server(void *p) ESP_LOGE(TAG, "udp: coap_new_endpoint() failed"); goto clean_up; } - ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_TCP); - if (!ep) { - ESP_LOGE(TAG, "tcp: coap_new_endpoint() failed"); - goto clean_up; + if (coap_tcp_is_supported()) { + ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_TCP); + if (!ep) { + ESP_LOGE(TAG, "tcp: coap_new_endpoint() failed"); + goto clean_up; + } } #if defined(CONFIG_COAP_MBEDTLS_PSK) || defined(CONFIG_COAP_MBEDTLS_PKI) if (coap_dtls_is_supported()) { #ifndef CONFIG_MBEDTLS_TLS_SERVER /* This is not critical as unencrypted support is still available */ - ESP_LOGI(TAG, "MbedTLS (D)TLS Server Mode not configured"); + ESP_LOGI(TAG, "MbedTLS DTLS Server Mode not configured"); #else /* CONFIG_MBEDTLS_TLS_SERVER */ serv_addr.addr.sin6.sin6_port = htons(COAPS_DEFAULT_PORT); ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_DTLS); @@ -275,8 +282,23 @@ static void coap_example_server(void *p) ESP_LOGE(TAG, "dtls: coap_new_endpoint() failed"); goto clean_up; } + have_dtls = 1; #endif /* CONFIG_MBEDTLS_TLS_SERVER */ - } else { + } + if (coap_tls_is_supported()) { +#ifndef CONFIG_MBEDTLS_TLS_SERVER + /* This is not critical as unencrypted support is still available */ + ESP_LOGI(TAG, "MbedTLS TLS Server Mode not configured"); +#else /* CONFIG_MBEDTLS_TLS_SERVER */ + serv_addr.addr.sin6.sin6_port = htons(COAPS_DEFAULT_PORT); + ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_TLS); + if (!ep) { + ESP_LOGE(TAG, "tls: coap_new_endpoint() failed"); + goto clean_up; + } +#endif /* CONFIG_MBEDTLS_TLS_SERVER */ + } + if (!have_dtls) { /* This is not critical as unencrypted support is still available */ ESP_LOGI(TAG, "MbedTLS (D)TLS Server Mode not configured"); } diff --git a/examples/espidf-exceptions/.travis.yml b/examples/espidf-exceptions/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-exceptions/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-exceptions/README.md b/examples/espidf-exceptions/README.md index fdec36f90..914e8fe7a 100644 --- a/examples/espidf-exceptions/README.md +++ b/examples/espidf-exceptions/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-exceptions/platformio.ini b/examples/espidf-exceptions/platformio.ini index 35879a6d5..a6c3cff92 100644 --- a/examples/espidf-exceptions/platformio.ini +++ b/examples/espidf-exceptions/platformio.ini @@ -5,7 +5,7 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env] platform = espressif32 diff --git a/examples/espidf-exceptions/src/CMakeLists.txt b/examples/espidf-exceptions/src/CMakeLists.txt index 6668d4f29..19ae5d7d6 100644 --- a/examples/espidf-exceptions/src/CMakeLists.txt +++ b/examples/espidf-exceptions/src/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRCS "exception_example_main.cpp" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS ".") diff --git a/examples/espidf-hello-world/.travis.yml b/examples/espidf-hello-world/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-hello-world/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-hello-world/README.md b/examples/espidf-hello-world/README.md index 4bad31e34..552984b2e 100644 --- a/examples/espidf-hello-world/README.md +++ b/examples/espidf-hello-world/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-hello-world/platformio.ini b/examples/espidf-hello-world/platformio.ini index 76fdc1860..226510eb1 100644 --- a/examples/espidf-hello-world/platformio.ini +++ b/examples/espidf-hello-world/platformio.ini @@ -5,7 +5,7 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env] platform = espressif32 diff --git a/examples/espidf-hello-world/src/CMakeLists.txt b/examples/espidf-hello-world/src/CMakeLists.txt index c299e0378..392c049cb 100644 --- a/examples/espidf-hello-world/src/CMakeLists.txt +++ b/examples/espidf-hello-world/src/CMakeLists.txt @@ -1,2 +1,4 @@ idf_component_register(SRCS "hello_world_main.c" - INCLUDE_DIRS "") \ No newline at end of file + INCLUDE_DIRS "") + +target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") diff --git a/examples/espidf-hello-world/src/hello_world_main.c b/examples/espidf-hello-world/src/hello_world_main.c index c17eb1b20..d924e1443 100644 --- a/examples/espidf-hello-world/src/hello_world_main.c +++ b/examples/espidf-hello-world/src/hello_world_main.c @@ -1,34 +1,42 @@ -/* Hello World Example +/* + * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ #include +#include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_system.h" -#include "esp_spi_flash.h" - +#include "esp_chip_info.h" +#include "esp_flash.h" -void app_main() +void app_main(void) { printf("Hello world!\n"); /* Print chip information */ esp_chip_info_t chip_info; + uint32_t flash_size; esp_chip_info(&chip_info); - printf("This is ESP32 chip with %d CPU cores, WiFi%s%s, ", - chip_info.cores, - (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", - (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); + printf("This is %s chip with %d CPU core(s), WiFi%s%s, ", + CONFIG_IDF_TARGET, + chip_info.cores, + (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", + (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); + + unsigned major_rev = chip_info.revision / 100; + unsigned minor_rev = chip_info.revision % 100; + printf("silicon revision v%d.%d, ", major_rev, minor_rev); + if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) { + printf("Get flash size failed"); + return; + } - printf("silicon revision %d, ", chip_info.revision); + printf("%uMB %s flash\n", flash_size / (1024 * 1024), + (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); - printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024), - (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); + printf("Minimum free heap size: %d bytes\n", esp_get_minimum_free_heap_size()); for (int i = 10; i >= 0; i--) { printf("Restarting in %d seconds...\n", i); diff --git a/examples/espidf-hello-world/test/test_dummy/test_dummy.c b/examples/espidf-hello-world/test/test_dummy/test_dummy.c new file mode 100644 index 000000000..b0c702565 --- /dev/null +++ b/examples/espidf-hello-world/test/test_dummy/test_dummy.c @@ -0,0 +1,15 @@ +#include + +void test_dummy(void) +{ + TEST_ASSERT_EQUAL(1, 1); +} + +void app_main() +{ + UNITY_BEGIN(); + + RUN_TEST(test_dummy); + + UNITY_END(); +} \ No newline at end of file diff --git a/examples/espidf-http-request/.travis.yml b/examples/espidf-http-request/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-http-request/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-http-request/README.md b/examples/espidf-http-request/README.md index 50c666595..b2cde11de 100644 --- a/examples/espidf-http-request/README.md +++ b/examples/espidf-http-request/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-http-request/platformio.ini b/examples/espidf-http-request/platformio.ini index 146e0dd5c..38756e618 100644 --- a/examples/espidf-http-request/platformio.ini +++ b/examples/espidf-http-request/platformio.ini @@ -5,7 +5,7 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env] platform = espressif32 diff --git a/examples/espidf-http-request/src/CMakeLists.txt b/examples/espidf-http-request/src/CMakeLists.txt index b4b91e9b8..60c38211d 100644 --- a/examples/espidf-http-request/src/CMakeLists.txt +++ b/examples/espidf-http-request/src/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRCS "http_request_example_main.c" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS ".") diff --git a/examples/espidf-http-request/src/http_request_example_main.c b/examples/espidf-http-request/src/http_request_example_main.c index 408bdc461..fdcefda9e 100644 --- a/examples/espidf-http-request/src/http_request_example_main.c +++ b/examples/espidf-http-request/src/http_request_example_main.c @@ -21,6 +21,7 @@ #include "lwip/sys.h" #include "lwip/netdb.h" #include "lwip/dns.h" +#include "sdkconfig.h" /* Constants that aren't configurable in menuconfig */ #define WEB_SERVER "example.com" diff --git a/examples/espidf-peripherals-uart/.travis.yml b/examples/espidf-peripherals-uart/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-peripherals-uart/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-peripherals-uart/README.md b/examples/espidf-peripherals-uart/README.md index 6df9193ae..40a561036 100644 --- a/examples/espidf-peripherals-uart/README.md +++ b/examples/espidf-peripherals-uart/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-peripherals-uart/platformio.ini b/examples/espidf-peripherals-uart/platformio.ini index c363d75b3..84e7f72d8 100644 --- a/examples/espidf-peripherals-uart/platformio.ini +++ b/examples/espidf-peripherals-uart/platformio.ini @@ -5,7 +5,7 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env] platform = espressif32 diff --git a/examples/espidf-peripherals-uart/src/CMakeLists.txt b/examples/espidf-peripherals-uart/src/CMakeLists.txt index b3eac5eff..a25733646 100644 --- a/examples/espidf-peripherals-uart/src/CMakeLists.txt +++ b/examples/espidf-peripherals-uart/src/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRCS "uart_echo_example_main.c" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS ".") diff --git a/examples/espidf-peripherals-uart/src/Kconfig.projbuild b/examples/espidf-peripherals-uart/src/Kconfig.projbuild new file mode 100644 index 000000000..23427866e --- /dev/null +++ b/examples/espidf-peripherals-uart/src/Kconfig.projbuild @@ -0,0 +1,45 @@ +menu "Echo Example Configuration" + + orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" + + config EXAMPLE_UART_PORT_NUM + int "UART port number" + range 0 2 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3 + default 2 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3 + range 0 1 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32H2 + default 1 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32H2 + help + UART communication port number for the example. + See UART documentation for available port numbers. + + config EXAMPLE_UART_BAUD_RATE + int "UART communication speed" + range 1200 115200 + default 115200 + help + UART communication speed for Modbus example. + + config EXAMPLE_UART_RXD + int "UART RXD pin number" + range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX + default 5 + help + GPIO number for UART RX pin. See UART documentation for more information + about available pin numbers for UART. + + config EXAMPLE_UART_TXD + int "UART TXD pin number" + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX + default 4 + help + GPIO number for UART TX pin. See UART documentation for more information + about available pin numbers for UART. + + config EXAMPLE_TASK_STACK_SIZE + int "UART echo example task stack size" + range 1024 16384 + default 2048 + help + Defines stack size for UART echo example. Insufficient stack size can cause crash. + +endmenu diff --git a/examples/espidf-peripherals-uart/src/uart_echo_example_main.c b/examples/espidf-peripherals-uart/src/uart_echo_example_main.c index 75283efab..20ba94fe9 100644 --- a/examples/espidf-peripherals-uart/src/uart_echo_example_main.c +++ b/examples/espidf-peripherals-uart/src/uart_echo_example_main.c @@ -11,23 +11,31 @@ #include "freertos/task.h" #include "driver/uart.h" #include "driver/gpio.h" +#include "sdkconfig.h" +#include "esp_log.h" /** - * This is an example which echos any data it receives on UART1 back to the sender, + * This is an example which echos any data it receives on configured UART back to the sender, * with hardware flow control turned off. It does not use UART driver event queue. * - * - Port: UART1 + * - Port: configured UART * - Receive (Rx) buffer: on * - Transmit (Tx) buffer: off * - Flow control: off * - Event queue: off - * - Pin assignment: see defines below + * - Pin assignment: see defines below (See Kconfig) */ -#define ECHO_TEST_TXD (GPIO_NUM_4) -#define ECHO_TEST_RXD (GPIO_NUM_5) -#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE) -#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE) +#define ECHO_TEST_TXD (CONFIG_EXAMPLE_UART_TXD) +#define ECHO_TEST_RXD (CONFIG_EXAMPLE_UART_RXD) +#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE) +#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE) + +#define ECHO_UART_PORT_NUM (CONFIG_EXAMPLE_UART_PORT_NUM) +#define ECHO_UART_BAUD_RATE (CONFIG_EXAMPLE_UART_BAUD_RATE) +#define ECHO_TASK_STACK_SIZE (CONFIG_EXAMPLE_TASK_STACK_SIZE) + +static const char *TAG = "UART TEST"; #define BUF_SIZE (1024) @@ -36,29 +44,39 @@ static void echo_task(void *arg) /* Configure parameters of an UART driver, * communication pins and install the driver */ uart_config_t uart_config = { - .baud_rate = 115200, + .baud_rate = ECHO_UART_BAUD_RATE, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, - .source_clk = UART_SCLK_APB, + .source_clk = UART_SCLK_DEFAULT, }; - uart_driver_install(UART_NUM_1, BUF_SIZE * 2, 0, 0, NULL, 0); - uart_param_config(UART_NUM_1, &uart_config); - uart_set_pin(UART_NUM_1, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS); + int intr_alloc_flags = 0; + +#if CONFIG_UART_ISR_IN_IRAM + intr_alloc_flags = ESP_INTR_FLAG_IRAM; +#endif + + ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags)); + ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config)); + ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS)); // Configure a temporary buffer for the incoming data uint8_t *data = (uint8_t *) malloc(BUF_SIZE); while (1) { // Read data from the UART - int len = uart_read_bytes(UART_NUM_1, data, BUF_SIZE, 20 / portTICK_RATE_MS); + int len = uart_read_bytes(ECHO_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS); // Write data back to the UART - uart_write_bytes(UART_NUM_1, (const char *) data, len); + uart_write_bytes(ECHO_UART_PORT_NUM, (const char *) data, len); + if (len) { + data[len] = '\0'; + ESP_LOGI(TAG, "Recv str: %s", (char *) data); + } } } void app_main(void) { - xTaskCreate(echo_task, "uart_echo_task", 1024, NULL, 10, NULL); + xTaskCreate(echo_task, "uart_echo_task", ECHO_TASK_STACK_SIZE, NULL, 10, NULL); } diff --git a/examples/espidf-peripherals-usb/.travis.yml b/examples/espidf-peripherals-usb/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-peripherals-usb/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-peripherals-usb/README.md b/examples/espidf-peripherals-usb/README.md index 3a9f308d3..80e7791c4 100644 --- a/examples/espidf-peripherals-usb/README.md +++ b/examples/espidf-peripherals-usb/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes b/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes new file mode 100644 index 000000000..2342decc3 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes @@ -0,0 +1,25 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +*.c text +*.cpp text +*.h text +*.icf text +*.js text +*.json text +*.ld text +*.md text +*.mk text +*.py text +*.rst text +*.s text +*.txt text +*.xml text +*.yml text + +Makefile text + +# Windows-only Visual Studio things + +*.sln text eol=crlf +*.csproj text eol=crlf diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore b/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore new file mode 100644 index 000000000..87a5faa80 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore @@ -0,0 +1,30 @@ +html +latex +*.d +*.o +*.P +*.map +*.axf +*.bin +*.jlink +*.emSession +*.elf +*.ind +.env +.settings/ +.idea/ +.gdb_history +/examples/*/*/build* +test_old/ +tests_obsolete/ +_build +/examples/*/*/ses +/examples/*/*/ozone +/examples/obsolete +# coverity intermediate files +cov-int +# cppcheck build directories +*-build-dir +/_bin/ +__pycache__ + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml b/examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml new file mode 100644 index 000000000..e83cd90fd --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml @@ -0,0 +1,18 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +version: 2 + +sphinx: + configuration: docs/conf.py + +python: + version: 3.8 + install: + - requirements: docs/requirements.txt + +submodules: + include: [] + recursive: false + \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt new file mode 100644 index 000000000..019a6f489 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt @@ -0,0 +1,73 @@ +idf_build_get_property(target IDF_TARGET) + +if(target STREQUAL "esp32s3") + set(tusb_mcu "OPT_MCU_ESP32S3") + set(tusb_family "esp32sx") +elseif(target STREQUAL "esp32s2") + set(tusb_mcu "OPT_MCU_ESP32S2") + set(tusb_family "esp32sx") +else() + message(FATAL_ERROR "TinyUSB is not support on ${target}.") + return() +endif() + +set(compile_options + "-DCFG_TUSB_MCU=${tusb_mcu}" + "-DCFG_TUSB_DEBUG=${CONFIG_TINYUSB_DEBUG_LEVEL}" + ) + +idf_component_get_property(freertos_component_dir freertos COMPONENT_DIR) + +set(includes_private + "hw/bsp/" + "src/" + "src/device" + "additions/include_private" + ) + +set(includes_public + "src/" + "additions/include" + # The FreeRTOS API include convention in tinyusb is different from esp-idf + "${freertos_component_dir}/FreeRTOS-Kernel/include/freertos" + ) + +set(srcs + "src/portable/espressif/${tusb_family}/dcd_${tusb_family}.c" + "src/class/cdc/cdc_device.c" + "src/class/hid/hid_device.c" + "src/class/midi/midi_device.c" + "src/class/msc/msc_device.c" + "src/class/vendor/vendor_device.c" + "src/common/tusb_fifo.c" + "src/device/usbd_control.c" + "src/device/usbd.c" + "src/tusb.c" + "additions/src/descriptors_control.c" + "additions/src/tinyusb.c" + "additions/src/usb_descriptors.c" + ) + +if(NOT CONFIG_TINYUSB_NO_DEFAULT_TASK) + list(APPEND srcs "additions/src/tusb_tasks.c") +endif() + +if(CONFIG_TINYUSB_CDC_ENABLED) + list(APPEND srcs + "additions/src/cdc.c" + "additions/src/tusb_cdc_acm.c" + "additions/src/tusb_console.c" + "additions/src/vfs_tinyusb.c" + ) +endif() # CONFIG_TINYUSB_CDC_ENABLED + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${includes_public} + PRIV_INCLUDE_DIRS ${includes_private} + PRIV_REQUIRES "vfs" "usb" "driver" + ) + +target_compile_options(${COMPONENT_LIB} PRIVATE ${compile_options}) + +# when no builtin class driver is enabled, an uint8_t data compared with `BUILTIN_DRIVER_COUNT` will always be false +set_source_files_properties("src/device/usbd.c" PROPERTIES COMPILE_FLAGS "-Wno-type-limits") diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst b/examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst new file mode 100644 index 000000000..4035c528f --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst @@ -0,0 +1,88 @@ +*************** +Code of Conduct +*************** + +Our Pledge +---------- + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our +project and our community a harassment-free experience for everyone, +regardless of age, body size, disability, ethnicity, sex +characteristics, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +Our Standards +------------- + +Examples of behavior that contributes to creating a positive environment +include: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual + attention or advances +- Trolling, insulting/derogatory comments, and personal or political + attacks +- Public or private harassment +- Publishing others' private information, such as a physical or + electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +Our Responsibilities +-------------------- + +Project maintainers are responsible for clarifying the standards of +acceptable behavior and are expected to take appropriate and fair +corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, +or reject comments, commits, code, wiki edits, issues, and other +contributions that are not aligned to this Code of Conduct, or to ban +temporarily or permanently any contributor for other behaviors that they +deem inappropriate, threatening, offensive, or harmful. + +Scope +----- + +This Code of Conduct applies both within project spaces and in public +spaces when an individual is representing the project or its community. +Examples of representing a project or community include using an +official project e-mail address, posting via an official social media +account, or acting as an appointed representative at an online or +offline event. Representation of a project may be further defined and +clarified by project maintainers. + +Enforcement +----------- + +Instances of abusive, harassing, or otherwise unacceptable behavior may +be reported by contacting the project team at thach@tinyusb.org. All +complaints will be reviewed and investigated and will result in a +response that is deemed necessary and appropriate to the circumstances. +The project team is obligated to maintain confidentiality with regard to +the reporter of an incident. Further details of specific enforcement +policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in +good faith may face temporary or permanent repercussions as determined +by other members of the project's leadership. + +Attribution +----------- + +This Code of Conduct is adapted from the `Contributor +Covenant `__, version 1.4, +available at +https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst b/examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst new file mode 100644 index 000000000..e3186f086 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst @@ -0,0 +1,192 @@ +************ +Contributors +************ + +Special thanks to all the people who spent their precious time and effort to help this project so far. +list contributors and their awesome work for the stack: + +Notable contributors +==================== + +(sorted alphabetically) + +`Adafruit Team `__ +----------------------------------------------- + +- Main supporter and sponsor for hardware boards and kits +- Discussion and suggestion for feature and improvement +- Design the project logo + + +`Ha Thach `__ +----------------------------------------- + +- *Author and maintainer* +- Most features development + + +`Hristo Gochkov `__ +------------------------------------------------- + +- Improve ESP32s2 DCD + + +`Jacob Berg Potter `__ +------------------------------------------------ + +- Add new class driver for network CDC-NCM + + +`Jan Dümpelmann `__ +----------------------------------------------- + +- Improve transfer performance for Synopsys DCD for STM32 MCUs + + +`Jeff Epler `__ +------------------------------------------ + +- Improve MIDI class driver + + +`Jerzy Kasenberg `__ +----------------------------------------------- + +- Add new DCD port for Dialog DA1469x +- Add new class driver for Bluetooth HCI +- Add ISO transfer for STM32 Synopsys, Nordic nRF, Dialog DA1469x +- Improve Audio driver and add uac2\_headset example +- Improve STM32 Synopsys DCD with various PRs + + +`J McCarthy `__ +-------------------------------------------------- + +- Add new DFU 1.1 class driver +- Add new example for dfu + + +`Kamil Tomaszewski `__ +---------------------------------------------------- + +- Add new DCD port for Sony CXD56 (spresnese board) + + +`Kay Sievers `__ +----------------------------------------------- + +- Improve MIDI driver with packet API + + +`Koji KITAYAMA `__ +----------------------------------------------- + +- Add new DCD port for NXP Kinetis KL25 +- Add new DCD port for Renesas RX family (RX600, RX700 ..) with GR-CITRUS, RX65n target board +- Add new class driver for USB Video Class (UVC 1.5) + + +`Nathan Conrad `__ +--------------------------------------------- + +- Add new DCD port for STM32 fsdev Fullspeed device for STM32 L0, + F0, F1, F3 etc ... +- Add new class driver for USB Test and Measurement Class (USBTMC) +- Various improvement e.g Zero-length packet, Lint setup +- Board support for STM32F070RB Nucleo, STM32F303 Discovery + + +`Peter Lawrence `__ +------------------------------------------------ + +- Add new DCD port for Nuvoton NUC 120, 121, 125, 126, 505 +- Add new class driver for network RNDIS, CDC-ECM +- Enhance CDC-NCM network driver to compatible with RNDIS/ECM +- Add *net\_lwip\_webserver* example for demonstration of usbnet with lwip +- Board support for NuTiny NUC120, NUC121s, NUC125s, NUC126V, NUC505 +- Improve multiple cdc interfaces API & add cdc\_dual\_ports example + + +`Rafael Silva `__ +---------------------------------------------- + +- Port DCD Synopsys to support Silabs EFM32GG12 with SLTB009A board +- Rewrite documentation in rst and setup for readthedocs + + +`Raspberry Pi Team `__ +------------------------------------------------------ + +- Add new DCD port for Raspberry Pi RP2040 +- Add new HCD port for Raspberry Pi RP2040 + + +`Reinhard Panhuber `__ +------------------------------------------------ + +- Add new class driver for USB Audio Class 2.0 (UAC2) +- Rework tu\_fifo with unmasked pointer, add DMA support, and constant address support +- Add new DCD/USBD edpt\_xfer\_fifo() API for optimizing endpoint transfer +- Add and greatly improve Isochronous transfer +- Add new audio examples: audio\_test and audio\_4\_channel\_mic + + +`Scott Shawcroft `__ +------------------------------------------------ + +- Add new DCD port for SAMD21 and SAMD51 +- Add new class driver for Musical Instrument Digital Interface (MIDI) +- Improve USBD control transfer, MSC, CDC class driver +- Board support for Metro M0 & M4 express +- Write the excellent porting.md documentation +- Add initial Makefile + +`Sean Cross `__ +---------------------------------------- + +- Add new DCD port for ValentyUSB eptri (fomu board) + + +`Sylvain "tnt" Munaut `__ +----------------------------------------------------- + +- Add new class driver for DFU Runtime + + +`Timon Skerutsch `__ +---------------------------------------------- + +- Add hid\_test.js script and extensive test for bi-directional raw HID + + +`Tod E. Kurt `__ +------------------------------------------- + +- Add hid\_test.js script and extensive test for bi-directional raw HID + + +`Uwe Bonnes `__ +--------------------------------------------- + +- Improve STM32 Synopsys highspeed DCD + + +`William D. Jones `__ +------------------------------------------------ + +- Add new DCD port for Synopsys DesignWare for STM32 L4, F2, F4, + F7, H7 etc ... +- Add new DCD port for TI MSP430 +- Board support for STM32F407 Discovery, STM32H743 Nucleo, pyboard v1.1, msp\_exp430f5529lp etc ... + + +`Zixun Li `__ +------------------------------------------- + +- Add new DCD port for Microchip SAMx7x +- Add IAR compiler support +- Improve UAC2, CDC, DFU class driver + + +`Full contributors list `__ +============================================================================ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig b/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig new file mode 100644 index 000000000..324fe70ec --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig @@ -0,0 +1,163 @@ +menu "TinyUSB Stack" + config TINYUSB_DEBUG_LEVEL + int "TinyUSB log level (0-3)" + default 0 + range 0 3 + help + Specify verbosity of TinyUSB log output. + + menu "TinyUSB task configuration" + config TINYUSB_NO_DEFAULT_TASK + bool "Do not create a TinyUSB task" + default n + help + This option allows to not create the FreeRTOS task during the driver initialization. + User will have to handle TinyUSB events manually. + + config TINYUSB_TASK_PRIORITY + int "TinyUSB task priority" + default 5 + depends on !TINYUSB_NO_DEFAULT_TASK + help + Set the priority of the default TinyUSB main task. + + config TINYUSB_TASK_STACK_SIZE + int "TinyUSB task stack size (bytes)" + default 4096 + depends on !TINYUSB_NO_DEFAULT_TASK + help + Set the stack size of the default TinyUSB main task. + endmenu + + menu "Descriptor configuration" + config TINYUSB_DESC_USE_ESPRESSIF_VID + bool "VID: Use Espressif's vendor ID" + default y + help + Enable this option, USB device will use Espressif's vendor ID as its VID. + This is helpful at product develop stage. + + config TINYUSB_DESC_CUSTOM_VID + hex "VID: Custom vendor ID" + default 0x1234 + depends on !TINYUSB_DESC_USE_ESPRESSIF_VID + help + Custom Vendor ID. + + config TINYUSB_DESC_USE_DEFAULT_PID + bool "PID: Use a default PID assigned to TinyUSB" + default y + help + Default TinyUSB PID assigning uses values 0x4000...0x4007. + + config TINYUSB_DESC_CUSTOM_PID + hex "PID: Custom product ID" + default 0x5678 + depends on !TINYUSB_DESC_USE_DEFAULT_PID + help + Custom Product ID. + + config TINYUSB_DESC_BCD_DEVICE + hex "bcdDevice" + default 0x0100 + help + Version of the firmware of the USB device. + + config TINYUSB_DESC_MANUFACTURER_STRING + string "Manufacturer name" + default "Espressif Systems" + help + Name of the manufacturer of the USB device. + + config TINYUSB_DESC_PRODUCT_STRING + string "Product name" + default "Espressif Device" + help + Name of the USB device. + + config TINYUSB_DESC_SERIAL_STRING + string "Serial string" + default "123456" + help + Serial number of the USB device. + + config TINYUSB_DESC_CDC_STRING + depends on TINYUSB_CDC_ENABLED + string "CDC Device String" + default "Espressif CDC Device" + help + Name of the CDC device. + + config TINYUSB_DESC_MSC_STRING + depends on TINYUSB_MSC_ENABLED + string "MSC Device String" + default "Espressif MSC Device" + help + Name of the MSC device. + endmenu # "Descriptor configuration" + + menu "Massive Storage Class (MSC)" + config TINYUSB_MSC_ENABLED + bool "Enable TinyUSB MSC feature" + default n + help + Enable TinyUSB MSC feature. + + config TINYUSB_MSC_BUFSIZE + depends on TINYUSB_MSC_ENABLED + int "MSC FIFO size" + default 512 + range 64 10000 + help + MSC FIFO size, in bytes. + endmenu # "Massive Storage Class" + + menu "Communication Device Class (CDC)" + config TINYUSB_CDC_ENABLED + bool "Enable TinyUSB CDC feature" + default n + help + Enable TinyUSB CDC feature. + + config TINYUSB_CDC_COUNT + int "CDC Channel Count" + default 1 + range 1 2 + depends on TINYUSB_CDC_ENABLED + help + Number of independent serial ports. + + config TINYUSB_CDC_RX_BUFSIZE + depends on TINYUSB_CDC_ENABLED + int "CDC FIFO size of RX channel" + default 64 + range 64 10000 + help + CDC FIFO size of RX channel. + + config TINYUSB_CDC_TX_BUFSIZE + depends on TINYUSB_CDC_ENABLED + int "CDC FIFO size of TX channel" + default 64 + help + CDC FIFO size of TX channel. + endmenu # "Communication Device Class" + + menu "Musical Instrument Digital Interface (MIDI)" + config TINYUSB_MIDI_COUNT + int "TinyUSB MIDI interfaces count" + default 0 + range 0 2 + help + Setting value greater than 0 will enable TinyUSB MIDI feature. + endmenu # "Musical Instrument Digital Interface (MIDI)" + + menu "Human Interface Device Class (HID)" + config TINYUSB_HID_COUNT + int "TinyUSB HID interfaces count" + default 0 + range 0 4 + help + Setting value greater than 0 will enable TinyUSB HID feature. + endmenu # "HID Device Class (HID)" +endmenu # "TinyUSB Stack" diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE b/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE new file mode 100644 index 000000000..ddd4ab410 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018, hathach (tinyusb.org) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst b/examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst new file mode 100644 index 000000000..4946e997e --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst @@ -0,0 +1,145 @@ +.. figure:: docs/assets/logo.svg + :alt: TinyUSB + +|Build Status| |Documentation Status| |License| + +TinyUSB is an open-source cross-platform USB Host/Device stack for +embedded system, designed to be memory-safe with no dynamic allocation +and thread-safe with all interrupt events are deferred then handled in +the non-ISR task function. + +Please take a look at the online `documentation `__. + +.. figure:: docs/assets/stack.svg + :width: 500px + :alt: stackup + +:: + + . + ├── docs # Documentation + ├── examples # Sample with Makefile build support + ├── hw + │   ├── bsp # Supported boards source files + │   └── mcu # Low level mcu core & peripheral drivers + ├── lib # Sources from 3rd party such as freeRTOS, fatfs ... + ├── src # All sources files for TinyUSB stack itself. + ├── test # Unit tests for the stack + └── tools # Files used internally + +Supported MCUs +============== + +The stack supports the following MCUs: + +- **Broadcom:** BCM2837, BCM2711 +- **Dialog:** DA1469x +- **Espressif:** ESP32-S2, ESP32-S3 +- **GigaDevice:** GD32VF103 +- **Infineon:** XMC4500 +- **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG55, SAML21, SAML22, SAME7x +- **NordicSemi:** nRF52833, nRF52840, nRF5340 +- **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505 +- **NXP:** + + - iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064 + - Kinetis: KL25, K32L2 + - LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55 + +- **Raspberry Pi:** RP2040 +- **Renesas:** RX63N, RX65N, RX72N +- **Silabs:** EFM32GG +- **Sony:** CXD56 +- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, G4, L0, L1, L4, L4+ +- **TI:** MSP430, MSP432E4, TM4C123 +- **ValentyUSB:** eptri + +Here is the list of `Supported Devices`_ that can be used with provided examples. + +Device Stack +============ + +Supports multiple device configurations by dynamically changing USB descriptors, low power functions such like suspend, resume, and remote wakeup. The following device classes are supported: + +- Audio Class 2.0 (UAC2) +- Bluetooth Host Controller Interface (BTH HCI) +- Communication Device Class (CDC) +- Device Firmware Update (DFU): DFU mode (WIP) and Runtinme +- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ... +- Mass Storage Class (MSC): with multiple LUNs +- Musical Instrument Digital Interface (MIDI) +- Network with RNDIS, Ethernet Control Model (ECM), Network Control Model (NCM) +- Test and Measurement Class (USBTMC) +- Video class 1.5 (UVC): work in progress +- Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file. +- `WebUSB `__ with vendor-specific class + +If you have a special requirement, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how the RPi team added their reset interface `raspberrypi/pico-sdk#197 `_ + +Host Stack +========== + +- Human Interface Device (HID): Keyboard, Mouse, Generic +- Mass Storage Class (MSC) +- Hub currently only supports 1 level of hub (due to my laziness) + +OS Abstraction layer +==================== + +TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) events into a central queue, then processing them later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as Communication Device Class (CDC) FIFO. Therefore the stack needs to use some of the OS's basic APIs. Following OSes are already supported out of the box. + +- **No OS** +- **FreeRTOS** +- `RT-Thread `_ +- **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its `own repo `_ + +Local Docs +========== + +- Info + + - `Uses`_ + - `Changelog`_ + - `Contributors`_ + +- `Reference`_ + + - `Supported Devices`_ + - `Getting Started`_ + - `Concurrency`_ + +- `Contributing`_ + + - `Code of Conduct`_ + - `Structure`_ + - `Porting`_ + +License +======= + +All TinyUSB sources in the ``src`` folder are licensed under MIT +license, the `Full license is here `__. However, each file can be +individually licensed especially those in ``lib`` and ``hw/mcu`` folder. +Please make sure you understand all the license term for files you use +in your project. + + +.. |Build Status| image:: https://github.com/hathach/tinyusb/workflows/Build/badge.svg + :target: https://github.com/hathach/tinyusb/actions +.. |Documentation Status| image:: https://readthedocs.org/projects/tinyusb/badge/?version=latest + :target: https://docs.tinyusb.org/en/latest/?badge=latest +.. |License| image:: https://img.shields.io/badge/license-MIT-brightgreen.svg + :target: https://opensource.org/licenses/MIT + + +.. _Uses: docs/info/uses.rst +.. _Changelog: docs/info/changelog.rst +.. _Contributors: CONTRIBUTORS.rst +.. _Reference: docs/reference/index.rst +.. _Supported Devices: docs/reference/supported.rst +.. _Getting Started: docs/reference/getting_started.rst +.. _Concurrency: docs/reference/concurrency.rst +.. _Contributing: docs/contributing/index.rst +.. _Code of Conduct: CODE_OF_CONDUCT.rst +.. _Structure: docs/contributing/structure.rst +.. _Porting: docs/contributing/porting.rst diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb.h new file mode 100644 index 000000000..255cf3bed --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb.h @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "tusb.h" +#include "tusb_option.h" +#include "tusb_config.h" +#include "tinyusb_types.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Configuration structure of the TinyUSB core + * + * USB specification mandates self-powered devices to monitor USB VBUS to detect connection/disconnection events. + * If you want to use this feature, connected VBUS to any free GPIO through a voltage divider or voltage comparator. + * The voltage divider output should be (0.75 * Vdd) if VBUS is 4.4V (lowest valid voltage at device port). + * The comparator thresholds should be set with hysteresis: 4.35V (falling edge) and 4.75V (raising edge). + */ +typedef struct { + union { + const tusb_desc_device_t *device_descriptor; /*!< Pointer to a device descriptor. If set to NULL, the TinyUSB device will use a default device descriptor whose values are set in Kconfig */ + const tusb_desc_device_t *descriptor __attribute__((deprecated)); /*!< Alias to `device_descriptor` for backward compatibility */ + }; + const char **string_descriptor; /*!< Pointer to an array of string descriptors */ + bool external_phy; /*!< Should USB use an external PHY */ + const uint8_t *configuration_descriptor; /*!< Pointer to a configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + bool self_powered; /*!< This is a self-powered USB device. USB VBUS must be monitored. */ + int vbus_monitor_io; /*!< GPIO for VBUS monitoring. Ignored if not self_powered. */ +} tinyusb_config_t; + +/** + * @brief This is an all-in-one helper function, including: + * 1. USB device driver initialization + * 2. Descriptors preparation + * 3. TinyUSB stack initialization + * 4. Creates and start a task to handle usb events + * + * @note Don't change Custom descriptor, but if it has to be done, + * Suggest to define as follows in order to match the Interface Association Descriptor (IAD): + * bDeviceClass = TUSB_CLASS_MISC, + * bDeviceSubClass = MISC_SUBCLASS_COMMON, + * + * @param config tinyusb stack specific configuration + * @retval ESP_ERR_INVALID_ARG Install driver and tinyusb stack failed because of invalid argument + * @retval ESP_FAIL Install driver and tinyusb stack failed because of internal error + * @retval ESP_OK Install driver and tinyusb stack successfully + */ +esp_err_t tinyusb_driver_install(const tinyusb_config_t *config); + +// TODO esp_err_t tinyusb_driver_uninstall(void); (IDF-1474) + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h new file mode 100644 index 000000000..1f01fe132 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define USB_ESPRESSIF_VID 0x303A +#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 8 // (4 + TINYUSB_STR_DESC_LEN) + +typedef enum{ + TINYUSB_USBDEV_0, +} tinyusb_usbdev_t; + +typedef const char *tusb_desc_strarray_device_t[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_cdc_acm.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_cdc_acm.h new file mode 100644 index 000000000..266ca86c8 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_cdc_acm.h @@ -0,0 +1,195 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/timers.h" +#include "tusb.h" +#include "tinyusb.h" + +/** + * @brief CDC ports available to setup + */ +typedef enum { + TINYUSB_CDC_ACM_0 = 0x0, + TINYUSB_CDC_ACM_1, + TINYUSB_CDC_ACM_MAX +} tinyusb_cdcacm_itf_t; + +/* Callbacks and events + ********************************************************************* */ + +/** + * @brief Data provided to the input of the `callback_rx_wanted_char` callback + */ +typedef struct { + char wanted_char; /*!< Wanted character */ +} cdcacm_event_rx_wanted_char_data_t; + +/** + * @brief Data provided to the input of the `callback_line_state_changed` callback + */ +typedef struct { + bool dtr; /*!< Data Terminal Ready (DTR) line state */ + bool rts; /*!< Request To Send (RTS) line state */ +} cdcacm_event_line_state_changed_data_t; + +/** + * @brief Data provided to the input of the `line_coding_changed` callback + */ +typedef struct { + cdc_line_coding_t const *p_line_coding; /*!< New line coding value */ +} cdcacm_event_line_coding_changed_data_t; + +/** + * @brief Types of CDC ACM events + */ +typedef enum { + CDC_EVENT_RX, + CDC_EVENT_RX_WANTED_CHAR, + CDC_EVENT_LINE_STATE_CHANGED, + CDC_EVENT_LINE_CODING_CHANGED +} cdcacm_event_type_t; + +/** + * @brief Describes an event passing to the input of a callbacks + */ +typedef struct { + cdcacm_event_type_t type; /*!< Event type */ + union { + cdcacm_event_rx_wanted_char_data_t rx_wanted_char_data; /*!< Data input of the `callback_rx_wanted_char` callback */ + cdcacm_event_line_state_changed_data_t line_state_changed_data; /*!< Data input of the `callback_line_state_changed` callback */ + cdcacm_event_line_coding_changed_data_t line_coding_changed_data; /*!< Data input of the `line_coding_changed` callback */ + }; +} cdcacm_event_t; + +/** + * @brief CDC-ACM callback type + */ +typedef void(*tusb_cdcacm_callback_t)(int itf, cdcacm_event_t *event); + +/*********************************************************************** Callbacks and events*/ +/* Other structs + ********************************************************************* */ + +/** + * @brief Configuration structure for CDC-ACM + */ +typedef struct { + tinyusb_usbdev_t usb_dev; /*!< Usb device to set up */ + tinyusb_cdcacm_itf_t cdc_port; /*!< CDC port */ + size_t rx_unread_buf_sz; /*!< Amount of data that can be passed to the ACM at once */ + tusb_cdcacm_callback_t callback_rx; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ + tusb_cdcacm_callback_t callback_rx_wanted_char; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ + tusb_cdcacm_callback_t callback_line_state_changed; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ + tusb_cdcacm_callback_t callback_line_coding_changed; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ +} tinyusb_config_cdcacm_t; + +/*********************************************************************** Other structs*/ +/* Public functions + ********************************************************************* */ +/** + * @brief Initialize CDC ACM. Initialization will be finished with + * the `tud_cdc_line_state_cb` callback + * + * @param cfg - init configuration structure + * @return esp_err_t + */ +esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg); + + +/** + * @brief Register a callback invoking on CDC event. If the callback had been + * already registered, it will be overwritten + * + * @param itf - number of a CDC object + * @param event_type - type of registered event for a callback + * @param callback - callback function + * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG + */ +esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf, + cdcacm_event_type_t event_type, + tusb_cdcacm_callback_t callback); + + +/** + * @brief Unregister a callback invoking on CDC event. + * + * @param itf - number of a CDC object + * @param event_type - type of registered event for a callback + * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG + */ +esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type); + + +/** + * @brief Sent one character to a write buffer + * + * @param itf - number of a CDC object + * @param ch - character to send + * @return size_t - amount of queued bytes + */ +size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch); + + +/** + * @brief Write data to write buffer from a byte array + * + * @param itf - number of a CDC object + * @param in_buf - a source array + * @param in_size - size to write from arr_src + * @return size_t - amount of queued bytes + */ +size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size); + +/** + * @brief Send all data from a write buffer. Use `tinyusb_cdcacm_write_queue` to add data to the buffer. + * + * WARNING! TinyUSB can block output Endpoint for several RX callbacks, after will do additional flush + * after the each trasfer. That can leads to the situation when you requested a flush, but it will fail until + * ont of the next callbacks ends. + * SO USING OF THE FLUSH WITH TIMEOUTS IN CALLBACKS IS NOT RECOMENDED - YOU CAN GET A LOCK FOR THE TIMEOUT + * + * @param itf - number of a CDC object + * @param timeout_ticks - waiting until flush will be considered as failed + * @return esp_err_t - ESP_OK if (timeout_ticks > 0) and and flush was successful, + * ESP_ERR_TIMEOUT if timeout occurred3 or flush was successful with (timeout_ticks == 0) + * ESP_FAIL if flush was unsuccessful + */ +esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks); + +/** + * @brief Read a content to the array, and defines it's size to the sz_store + * + * @param itf - number of a CDC object + * @param out_buf - to this array will be stored the object from a CDC buffer + * @param out_buf_sz - size of buffer for results + * @param rx_data_size - to this address will be stored the object's size + * @return esp_err_t ESP_OK, ESP_FAIL or ESP_ERR_INVALID_STATE + */ +esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size); + + +/** + * @brief Check if the ACM initialized + * + * @param itf - number of a CDC object + * @return true or false + */ +bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf); + +/*********************************************************************** Public functions*/ + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_config.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_config.h new file mode 100644 index 000000000..da2a5f9e7 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_config.h @@ -0,0 +1,103 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org), + * Additions Copyright (c) 2020, Espressif Systems (Shanghai) PTE LTD + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#pragma once + +#include "tusb_option.h" +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CONFIG_TINYUSB_CDC_ENABLED +# define CONFIG_TINYUSB_CDC_ENABLED 0 +#endif + +#ifndef CONFIG_TINYUSB_CDC_COUNT +# define CONFIG_TINYUSB_CDC_COUNT 0 +#endif + +#ifndef CONFIG_TINYUSB_MSC_ENABLED +# define CONFIG_TINYUSB_MSC_ENABLED 0 +#endif + +#ifndef CONFIG_TINYUSB_HID_COUNT +# define CONFIG_TINYUSB_HID_COUNT 0 +#endif + +#ifndef CONFIG_TINYUSB_MIDI_COUNT +# define CONFIG_TINYUSB_MIDI_COUNT 0 +#endif + +#ifndef CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED +# define CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED 0 +#endif + +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED +#define CFG_TUSB_OS OPT_OS_FREERTOS + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +# define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +# define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) +#endif + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +// CDC FIFO size of TX and RX +#define CFG_TUD_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE +#define CFG_TUD_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE + +// MSC Buffer size of Device Mass storage +#define CFG_TUD_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE + +#define CFG_TUD_MIDI_EP_BUFSIZE 64 +#define CFG_TUD_MIDI_EPSIZE CFG_TUD_MIDI_EP_BUFSIZE +#define CFG_TUD_MIDI_RX_BUFSIZE 64 +#define CFG_TUD_MIDI_TX_BUFSIZE 64 + +// Enabled device class driver +#define CFG_TUD_CDC CONFIG_TINYUSB_CDC_COUNT +#define CFG_TUD_MSC CONFIG_TINYUSB_MSC_ENABLED +#define CFG_TUD_HID CONFIG_TINYUSB_HID_COUNT +#define CFG_TUD_MIDI CONFIG_TINYUSB_MIDI_COUNT +#define CFG_TUD_CUSTOM_CLASS CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_console.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_console.h new file mode 100644 index 000000000..568fee099 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_console.h @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" + +/** + * @brief Redirect output to the USB serial + * @param cdc_intf - interface number of TinyUSB's CDC + * + * @return esp_err_t - ESP_OK, ESP_FAIL or an error code + */ +esp_err_t esp_tusb_init_console(int cdc_intf); + +/** + * @brief Switch log to the default output + * @param cdc_intf - interface number of TinyUSB's CDC + * + * @return esp_err_t + */ +esp_err_t esp_tusb_deinit_console(int cdc_intf); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_tasks.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_tasks.h new file mode 100644 index 000000000..22b6df6c2 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_tasks.h @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief This helper function creates and starts a task which wraps `tud_task()`. + * + * The wrapper function basically wraps tud_task and some log. + * Default parameters: stack size and priority as configured, argument = NULL, not pinned to any core. + * If you have more requirements for this task, you can create your own task which calls tud_task as the last step. + * + * @retval ESP_OK run tinyusb main task successfully + * @retval ESP_FAIL run tinyusb main task failed of internal error + * @retval ESP_ERR_INVALID_STATE tinyusb main task has been created before + */ +esp_err_t tusb_run_task(void); + +/** + * @brief This helper function stops and destroys the task created by `tusb_run_task()` + * + * @retval ESP_OK stop and destory tinyusb main task successfully + * @retval ESP_ERR_INVALID_STATE tinyusb main task hasn't been created yet + */ +esp_err_t tusb_stop_task(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h new file mode 100644 index 000000000..79c69bd72 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Register TinyUSB CDC at VFS with path + * @param cdc_intf - interface number of TinyUSB's CDC + * @param path - path where the CDC will be registered, `/dev/tusb_cdc` will be used if left NULL. + * + * @return esp_err_t ESP_OK or ESP_FAIL + */ +esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path); + +/** + * @brief Unregister TinyUSB CDC from VFS + * @param path - path where the CDC will be unregistered if NULL will be used `/dev/tusb_cdc` + * + * @return esp_err_t ESP_OK or ESP_FAIL + */ +esp_err_t esp_vfs_tusb_cdc_unregister(char const *path); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/cdc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/cdc.h new file mode 100644 index 000000000..c6eb92318 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/cdc.h @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/timers.h" +#include "tusb.h" +#include "tinyusb_types.h" + +/* CDC classification + ********************************************************************* */ +typedef enum { + TINYUSB_CDC_DATA = 0x00, +} cdc_data_sublcass_type_t; // CDC120 specification + +/* Note:other classification is represented in the file components\tinyusb\tinyusb\src\class\cdc\cdc.h */ + +/*********************************************************************** CDC classification*/ +/* Structs + ********************************************************************* */ +typedef struct { + tinyusb_usbdev_t usb_dev; /*!< USB device to set up */ + tusb_class_code_t cdc_class; /*!< CDC device class : Communications or Data device */ + union { + cdc_comm_sublcass_type_t comm_subclass; /*!< Communications device subclasses: ACM, ECM, etc. */ + cdc_data_sublcass_type_t data_subclass; /*!< Data device has only one subclass.*/ + } cdc_subclass; /*!< CDC device subclass according to Class Definitions for Communications Devices the CDC v.1.20 */ +} tinyusb_config_cdc_t; /*!< Main configuration structure of a CDC device */ + +typedef struct { + tinyusb_usbdev_t usb_dev; /*!< USB device used for the instance */ + tusb_class_code_t type; + union { + cdc_comm_sublcass_type_t comm_subclass; /*!< Communications device subclasses: ACM, ECM, etc. */ + cdc_data_sublcass_type_t data_subclass; /*!< Data device has only one subclass.*/ + } cdc_subclass; /*!< CDC device subclass according to Class Definitions for Communications Devices the CDC v.1.20 */ + void *subclass_obj; /*!< Dynamically allocated subclass specific object */ +} esp_tusb_cdc_t; +/*********************************************************************** Structs*/ +/* Functions + ********************************************************************* */ +/** + * @brief Initializing CDC basic object + * @param itf - number of a CDC object + * @param cfg - CDC configuration structure + * + * @return esp_err_t ESP_OK or ESP_FAIL + */ +esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg); + + +/** + * @brief De-initializing CDC. Clean its objects + * @param itf - number of a CDC object + * @return esp_err_t ESP_OK, ESP_ERR_INVALID_ARG, ESP_ERR_INVALID_STATE + * + */ +esp_err_t tinyusb_cdc_deinit(int itf); + + +/** + * @brief Return interface of a CDC device + * + * @param itf_num + * @return esp_tusb_cdc_t* pointer to the interface or (NULL) on error + */ +esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num); +/*********************************************************************** Functions*/ + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h new file mode 100644 index 000000000..b6516e1a7 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "tusb.h" +#include "tinyusb_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void tusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, const uint8_t *cfg_desc); +tusb_desc_device_t *tusb_get_active_desc(void); +char **tusb_get_active_str_desc(void); +void tusb_clear_descriptor(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h new file mode 100644 index 000000000..215010c94 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "tusb.h" +#include "tinyusb_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) + +extern tusb_desc_device_t descriptor_tinyusb; +extern tusb_desc_strarray_device_t descriptor_str_tinyusb; + +extern const tusb_desc_device_t descriptor_dev_kconfig; +extern tusb_desc_strarray_device_t descriptor_str_kconfig; +extern const uint8_t descriptor_cfg_kconfig[]; + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/cdc.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/cdc.c new file mode 100644 index 000000000..9e46c7ca4 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/cdc.c @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_check.h" +#include "esp_err.h" +#include "esp_log.h" +#include "tusb.h" +#include "cdc.h" + +#define CDC_INTF_NUM CFG_TUD_CDC // number of cdc blocks +static esp_tusb_cdc_t *cdc_obj[CDC_INTF_NUM] = {}; +static const char *TAG = "tusb_cdc"; + +esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num) +{ + if (itf_num >= CDC_INTF_NUM || itf_num < 0) { + return NULL; + } + return cdc_obj[itf_num]; +} + +static esp_err_t cdc_obj_check(int itf, bool expected_inited, tusb_class_code_t expected_type) +{ + esp_tusb_cdc_t *this_itf = tinyusb_cdc_get_intf(itf); + + bool inited = (this_itf != NULL); + ESP_RETURN_ON_FALSE(expected_inited == inited, ESP_ERR_INVALID_STATE, TAG, "Wrong state of the interface. Expected state: %s", expected_inited ? "initialized" : "not initialized"); + ESP_RETURN_ON_FALSE(!(inited && (expected_type != -1) && !(this_itf->type == expected_type)), ESP_ERR_INVALID_STATE, TAG, "Wrong type of the interface. Should be : 0x%x (tusb_class_code_t)", expected_type); + return ESP_OK; +} + +static esp_err_t tusb_cdc_comm_init(int itf) +{ + ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, -1), TAG, "cdc_obj_check failed"); + cdc_obj[itf] = calloc(1, sizeof(esp_tusb_cdc_t)); + if (cdc_obj[itf] != NULL) { + cdc_obj[itf]->type = TUSB_CLASS_CDC; + ESP_LOGD(TAG, "CDC Comm class initialized"); + return ESP_OK; + } else { + ESP_LOGE(TAG, "CDC Comm initialization error"); + return ESP_FAIL; + } +} + +static esp_err_t tusb_cdc_deinit_comm(int itf) +{ + ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, TUSB_CLASS_CDC), TAG, "cdc_obj_check failed"); + free(cdc_obj[itf]); + cdc_obj[itf] = NULL; + return ESP_OK; +} + +static esp_err_t tusb_cdc_data_init(int itf) +{ + ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, TUSB_CLASS_CDC_DATA), TAG, "cdc_obj_check failed"); + cdc_obj[itf] = calloc(1, sizeof(esp_tusb_cdc_t)); + if (cdc_obj[itf] != NULL) { + cdc_obj[itf]->type = TUSB_CLASS_CDC_DATA; + ESP_LOGD(TAG, "CDC Data class initialized"); + return ESP_OK; + } else { + ESP_LOGE(TAG, "CDC Data initialization error"); + return ESP_FAIL; + } +} + +static esp_err_t tusb_cdc_deinit_data(int itf) +{ + ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, TUSB_CLASS_CDC_DATA), TAG, "cdc_obj_check failed"); + free(cdc_obj[itf]); + cdc_obj[itf] = NULL; + return ESP_OK; +} + +esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg) +{ + ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, -1), TAG, "cdc_obj_check failed"); + + ESP_LOGD(TAG, "Init CDC %d", itf); + if (cfg->cdc_class == TUSB_CLASS_CDC) { + ESP_RETURN_ON_ERROR(tusb_cdc_comm_init(itf), TAG, "tusb_cdc_comm_init failed"); + cdc_obj[itf]->cdc_subclass.comm_subclass = cfg->cdc_subclass.comm_subclass; + } else { + ESP_RETURN_ON_ERROR(tusb_cdc_data_init(itf), TAG, "tusb_cdc_data_init failed"); + cdc_obj[itf]->cdc_subclass.data_subclass = cfg->cdc_subclass.data_subclass; + } + cdc_obj[itf]->usb_dev = cfg->usb_dev; + return ESP_OK; +} + +esp_err_t tinyusb_cdc_deinit(int itf) +{ + ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, -1), TAG, "cdc_obj_check failed"); + + ESP_LOGD(TAG, "Deinit CDC %d", itf); + if (cdc_obj[itf]->type == TUSB_CLASS_CDC) { + ESP_RETURN_ON_ERROR(tusb_cdc_deinit_comm(itf), TAG, "tusb_cdc_deinit_comm failed"); + } else if (cdc_obj[itf]->type == TUSB_CLASS_CDC_DATA) { + ESP_RETURN_ON_ERROR(tusb_cdc_deinit_data(itf), TAG, "tusb_cdc_deinit_data failed"); + } else { + return ESP_ERR_INVALID_ARG; + } + return ESP_OK; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c new file mode 100644 index 000000000..7e9ed4cbe --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c @@ -0,0 +1,150 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_log.h" +#include "descriptors_control.h" + +static const char *TAG = "tusb_desc"; +static tusb_desc_device_t s_device_descriptor; +static const uint8_t *s_configuration_descriptor; +static char *s_str_descriptor[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; +#define MAX_DESC_BUF_SIZE 32 + +// ============================================================================= +// CALLBACKS +// ============================================================================= + +/** + * @brief Invoked when received GET DEVICE DESCRIPTOR. + * Application returns pointer to descriptor + * + * @return uint8_t const* + */ +uint8_t const *tud_descriptor_device_cb(void) +{ + return (uint8_t const *)&s_device_descriptor; +} + +/** + * @brief Invoked when received GET CONFIGURATION DESCRIPTOR. + * Descriptor contents must exist long enough for transfer to complete + * + * @param index + * @return uint8_t const* Application return pointer to descriptor + */ +uint8_t const *tud_descriptor_configuration_cb(uint8_t index) +{ + (void)index; // for multiple configurations + return s_configuration_descriptor; +} + +static uint16_t _desc_str[MAX_DESC_BUF_SIZE]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; + + uint8_t chr_count; + + if ( index == 0) { + memcpy(&_desc_str[1], s_str_descriptor[0], 2); + chr_count = 1; + } else { + // Convert ASCII string into UTF-16 + + if ( index >= sizeof(s_str_descriptor) / sizeof(s_str_descriptor[0]) ) { + ESP_LOGE(TAG, "String index (%u) is out of bounds, check your string descriptor", index); + return NULL; + } + + if (s_str_descriptor[index] == NULL) { + ESP_LOGE(TAG, "String index (%u) points to NULL, check your string descriptor", index); + return NULL; + } + + const char *str = s_str_descriptor[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > MAX_DESC_BUF_SIZE - 1 ) { + chr_count = MAX_DESC_BUF_SIZE - 1; + } + + for (uint8_t i = 0; i < chr_count; i++) { + _desc_str[1 + i] = str[i]; + } + } + + // first byte is length (including header), second byte is string type + _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * chr_count + 2); + + return _desc_str; +} + +// ============================================================================= +// Driver functions +// ============================================================================= + +void tusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, const uint8_t *cfg_desc) +{ + ESP_LOGI(TAG, "\n" + "┌─────────────────────────────────┐\n" + "│ USB Device Descriptor Summary │\n" + "├───────────────────┬─────────────┤\n" + "│bDeviceClass │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│bDeviceSubClass │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│bDeviceProtocol │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│bMaxPacketSize0 │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│idVendor │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│idProduct │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│bcdDevice │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│iManufacturer │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│iProduct │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│iSerialNumber │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│bNumConfigurations │ %-#10x │\n" + "└───────────────────┴─────────────┘", + dev_desc->bDeviceClass, dev_desc->bDeviceSubClass, + dev_desc->bDeviceProtocol, dev_desc->bMaxPacketSize0, + dev_desc->idVendor, dev_desc->idProduct, dev_desc->bcdDevice, + dev_desc->iManufacturer, dev_desc->iProduct, dev_desc->iSerialNumber, + dev_desc->bNumConfigurations); + s_device_descriptor = *dev_desc; + s_configuration_descriptor = cfg_desc; + + if (str_desc != NULL) { + memcpy(s_str_descriptor, str_desc, + sizeof(s_str_descriptor[0])*USB_STRING_DESCRIPTOR_ARRAY_SIZE); + } +} + +tusb_desc_device_t *tusb_get_active_desc(void) +{ + return &s_device_descriptor; +} + +char **tusb_get_active_str_desc(void) +{ + return s_str_descriptor; +} + +void tusb_clear_descriptor(void) +{ + memset(&s_device_descriptor, 0, sizeof(s_device_descriptor)); + memset(&s_str_descriptor, 0, sizeof(s_str_descriptor)); +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tinyusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tinyusb.c new file mode 100644 index 000000000..a081030c3 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tinyusb.c @@ -0,0 +1,93 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "esp_log.h" +#include "esp_check.h" +#include "esp_err.h" +#include "esp_private/periph_ctrl.h" +#include "esp_private/usb_phy.h" +#include "soc/usb_pins.h" +#include "tinyusb.h" +#include "descriptors_control.h" +#include "usb_descriptors.h" +#include "tusb.h" +#include "tusb_tasks.h" + +const static char *TAG = "TinyUSB"; +static usb_phy_handle_t phy_hdl; + +esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) +{ + const tusb_desc_device_t *dev_descriptor; + const char **string_descriptor; + const uint8_t *cfg_descriptor; + ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + + // Configure USB PHY + usb_phy_config_t phy_conf = { + .controller = USB_PHY_CTRL_OTG, + .otg_mode = USB_OTG_MODE_DEVICE, + }; + + // External PHY IOs config + usb_phy_ext_io_conf_t ext_io_conf = { + .vp_io_num = USBPHY_VP_NUM, + .vm_io_num = USBPHY_VM_NUM, + .rcv_io_num = USBPHY_RCV_NUM, + .oen_io_num = USBPHY_OEN_NUM, + .vpo_io_num = USBPHY_VPO_NUM, + .vmo_io_num = USBPHY_VMO_NUM, + }; + if (config->external_phy) { + phy_conf.target = USB_PHY_TARGET_EXT; + phy_conf.ext_io_conf = &ext_io_conf; + } else { + phy_conf.target = USB_PHY_TARGET_INT; + } + + // OTG IOs config + const usb_phy_otg_io_conf_t otg_io_conf = USB_PHY_SELF_POWERED_DEVICE(config->vbus_monitor_io); + if (config->self_powered) { + phy_conf.otg_io_conf = &otg_io_conf; + } + ESP_RETURN_ON_ERROR(usb_new_phy(&phy_conf, &phy_hdl), TAG, "Install USB PHY failed"); + + if (config->configuration_descriptor) { + cfg_descriptor = config->configuration_descriptor; + } else { +#if (CONFIG_TINYUSB_HID_COUNT > 0 || CONFIG_TINYUSB_MIDI_COUNT > 0) + // For HID device, configuration descriptor must be provided + ESP_RETURN_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for this device"); +#else + cfg_descriptor = descriptor_cfg_kconfig; + ESP_LOGW(TAG, "The device's configuration descriptor is not provided by user, using default."); +#endif + } + + if (config->string_descriptor) { + string_descriptor = config->string_descriptor; + } else { + string_descriptor = descriptor_str_kconfig; + ESP_LOGW(TAG, "The device's string descriptor is not provided by user, using default."); + } + + if (config->device_descriptor) { + dev_descriptor = config->device_descriptor; + } else { + dev_descriptor = &descriptor_dev_kconfig; + ESP_LOGW(TAG, "The device's device descriptor is not provided by user, using default."); + } + + tusb_set_descriptor(dev_descriptor, string_descriptor, cfg_descriptor); + + ESP_RETURN_ON_FALSE(tusb_init(), ESP_FAIL, TAG, "Init TinyUSB stack failed"); +#if !CONFIG_TINYUSB_NO_DEFAULT_TASK + ESP_RETURN_ON_ERROR(tusb_run_task(), TAG, "Run TinyUSB task failed"); +#endif + ESP_LOGI(TAG, "TinyUSB Driver installed"); + return ESP_OK; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_cdc_acm.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_cdc_acm.c new file mode 100644 index 000000000..725426ead --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_cdc_acm.c @@ -0,0 +1,415 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_check.h" +#include "esp_err.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/ringbuf.h" +#include "tusb.h" +#include "tusb_cdc_acm.h" +#include "cdc.h" +#include "sdkconfig.h" + +#define RX_UNREADBUF_SZ_DEFAULT 64 // buffer storing all unread RX data +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) + + +typedef struct { + bool initialized; + size_t rx_unread_buf_sz; + RingbufHandle_t rx_unread_buf; + SemaphoreHandle_t ringbuf_read_mux; + uint8_t *rx_tfbuf; + tusb_cdcacm_callback_t callback_rx; + tusb_cdcacm_callback_t callback_rx_wanted_char; + tusb_cdcacm_callback_t callback_line_state_changed; + tusb_cdcacm_callback_t callback_line_coding_changed; +} esp_tusb_cdcacm_t; /*!< CDC_ACM object */ + +static const char *TAG = "tusb_cdc_acm"; + +static inline esp_tusb_cdcacm_t *get_acm(tinyusb_cdcacm_itf_t itf) +{ + esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf); + if (cdc_inst == NULL) { + return (esp_tusb_cdcacm_t *)NULL; + } + return (esp_tusb_cdcacm_t *)(cdc_inst->subclass_obj); +} + + +/* TinyUSB callbacks + ********************************************************************* */ + +/* Invoked by cdc interface when line state changed e.g connected/disconnected */ +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) +{ + esp_tusb_cdcacm_t *acm = get_acm(itf); + if (dtr && rts) { // connected + if (acm != NULL) { + ESP_LOGV(TAG, "Host connected to CDC no.%d.", itf); + } else { + ESP_LOGW(TAG, "Host is connected to CDC no.%d, but it is not initialized. Initialize it using `tinyusb_cdc_init`.", itf); + return; + } + } else { // disconnected + if (acm != NULL) { + ESP_LOGV(TAG, "Serial device is ready to connect to CDC no.%d", itf); + } else { + return; + } + } + if (acm) { + tusb_cdcacm_callback_t cb = acm->callback_line_state_changed; + if (cb) { + cdcacm_event_t event = { + .type = CDC_EVENT_LINE_STATE_CHANGED, + .line_state_changed_data = { + .dtr = dtr, + .rts = rts + } + }; + cb(itf, &event); + } + } +} + +/* Invoked when CDC interface received data from host */ +void tud_cdc_rx_cb(uint8_t itf) +{ + esp_tusb_cdcacm_t *acm = get_acm(itf); + if (acm) { + if (!acm->rx_unread_buf) { + ESP_LOGE(TAG, "There is no RX buffer created"); + abort(); + } + } else { + tud_cdc_n_read_flush(itf); // we have no place to store data, so just drop it + return; + } + while (tud_cdc_n_available(itf)) { + int read_res = tud_cdc_n_read( itf, + acm->rx_tfbuf, + CONFIG_TINYUSB_CDC_RX_BUFSIZE ); + int res = xRingbufferSend(acm->rx_unread_buf, + acm->rx_tfbuf, + read_res, 0); + if (res != pdTRUE) { + ESP_LOGW(TAG, "The unread buffer is too small, the data has been lost"); + } else { + ESP_LOGV(TAG, "Sent %d bytes to the buffer", read_res); + } + } + if (acm) { + tusb_cdcacm_callback_t cb = acm->callback_rx; + if (cb) { + cdcacm_event_t event = { + .type = CDC_EVENT_RX + }; + cb(itf, &event); + } + } +} + +// Invoked when line coding is change via SET_LINE_CODING +void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) +{ + esp_tusb_cdcacm_t *acm = get_acm(itf); + if (acm) { + tusb_cdcacm_callback_t cb = acm->callback_line_coding_changed; + if (cb) { + cdcacm_event_t event = { + .type = CDC_EVENT_LINE_CODING_CHANGED, + .line_coding_changed_data = { + .p_line_coding = p_line_coding, + } + }; + cb(itf, &event); + } + } else { + return; + } +} + +// Invoked when received `wanted_char` +void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) +{ + esp_tusb_cdcacm_t *acm = get_acm(itf); + if (acm) { + tusb_cdcacm_callback_t cb = acm->callback_rx_wanted_char; + if (cb) { + cdcacm_event_t event = { + .type = CDC_EVENT_RX_WANTED_CHAR, + .rx_wanted_char_data = { + .wanted_char = wanted_char, + } + }; + cb(itf, &event); + } + } else { + return; + } +} + +esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf, + cdcacm_event_type_t event_type, + tusb_cdcacm_callback_t callback) +{ + esp_tusb_cdcacm_t *acm = get_acm(itf); + if (acm) { + switch (event_type) { + case CDC_EVENT_RX: + acm->callback_rx = callback; + return ESP_OK; + case CDC_EVENT_RX_WANTED_CHAR: + acm->callback_rx_wanted_char = callback; + return ESP_OK; + case CDC_EVENT_LINE_STATE_CHANGED: + acm->callback_line_state_changed = callback; + return ESP_OK; + case CDC_EVENT_LINE_CODING_CHANGED: + acm->callback_line_coding_changed = callback; + return ESP_OK; + default: + ESP_LOGE(TAG, "Wrong event type"); + return ESP_ERR_INVALID_ARG; + } + } else { + ESP_LOGE(TAG, "CDC-ACM is not initialized"); + return ESP_ERR_INVALID_STATE; + } +} + +esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, + cdcacm_event_type_t event_type) +{ + esp_tusb_cdcacm_t *acm = get_acm(itf); + if (!acm) { + ESP_LOGE(TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization"); + return ESP_ERR_INVALID_STATE; + } + switch (event_type) { + case CDC_EVENT_RX: + acm->callback_rx = NULL; + return ESP_OK; + case CDC_EVENT_RX_WANTED_CHAR: + acm->callback_rx_wanted_char = NULL; + return ESP_OK; + case CDC_EVENT_LINE_STATE_CHANGED: + acm->callback_line_state_changed = NULL; + return ESP_OK; + case CDC_EVENT_LINE_CODING_CHANGED: + acm->callback_line_coding_changed = NULL; + return ESP_OK; + default: + ESP_LOGE(TAG, "Wrong event type"); + return ESP_ERR_INVALID_ARG; + } +} + +/*********************************************************************** TinyUSB callbacks*/ +/* CDC-ACM + ********************************************************************* */ + +static esp_err_t read_from_rx_unread_to_buffer(esp_tusb_cdcacm_t *acm, uint8_t *out_buf, size_t req_bytes, size_t *read_bytes) +{ + uint8_t *buf = xRingbufferReceiveUpTo(acm->rx_unread_buf, read_bytes, 0, req_bytes); + if (buf) { + memcpy(out_buf, buf, *read_bytes); + vRingbufferReturnItem(acm->rx_unread_buf, (void *)(buf)); + return ESP_OK; + } else { + return ESP_ERR_NO_MEM; + } +} + +static esp_err_t ringbuf_mux_take(esp_tusb_cdcacm_t *acm) +{ + if (xSemaphoreTake(acm->ringbuf_read_mux, 0) != pdTRUE) { + ESP_LOGW(TAG, "Read error: ACM is busy"); + return ESP_ERR_INVALID_STATE; + } + return ESP_OK; +} + +static esp_err_t ringbuf_mux_give(esp_tusb_cdcacm_t *acm) +{ + BaseType_t ret = xSemaphoreGive(acm->ringbuf_read_mux); + assert(ret == pdTRUE); + return ESP_OK; +} + +esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size) +{ + esp_tusb_cdcacm_t *acm = get_acm(itf); + ESP_RETURN_ON_FALSE(acm, ESP_ERR_INVALID_STATE, TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization"); + size_t read_sz; + + /* Take a mutex to proceed two uninterrupted read operations */ + ESP_RETURN_ON_ERROR(ringbuf_mux_take(acm), TAG, "ringbuf_mux_take failed"); + + esp_err_t res = read_from_rx_unread_to_buffer(acm, out_buf, out_buf_sz, &read_sz); + if (res != ESP_OK) { + ESP_RETURN_ON_ERROR(ringbuf_mux_give(acm), TAG, "ringbuf_mux_give failed"); + return res; + } + + *rx_data_size = read_sz; + /* Buffer's data can be wrapped, at that situations we should make another retrievement */ + if (read_from_rx_unread_to_buffer(acm, out_buf + read_sz, out_buf_sz - read_sz, &read_sz) == ESP_OK) { + *rx_data_size += read_sz; + } + + ESP_RETURN_ON_ERROR(ringbuf_mux_give(acm), TAG, "ringbuf_mux_give failed"); + return ESP_OK; +} + +size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch) +{ + if (!get_acm(itf)) { // non-initialized + return 0; + } + return tud_cdc_n_write_char(itf, ch); +} + +size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size) +{ + if (!get_acm(itf)) { // non-initialized + return 0; + } + const uint32_t size_available = tud_cdc_n_write_available(itf); + return tud_cdc_n_write(itf, in_buf, MIN(in_size, size_available)); +} + +static uint32_t tud_cdc_n_write_occupied(tinyusb_cdcacm_itf_t itf) +{ + return CFG_TUD_CDC_TX_BUFSIZE - tud_cdc_n_write_available(itf); +} + +esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks) +{ + if (!get_acm(itf)) { // non-initialized + return ESP_FAIL; + } + + if (!timeout_ticks) { // if no timeout - nonblocking mode + int res = tud_cdc_n_write_flush(itf); + if (!res) { + ESP_LOGW(TAG, "flush failed (res: %d)", res); + return ESP_FAIL; + } else { + if (tud_cdc_n_write_occupied(itf)) { + ESP_LOGW(TAG, "remained data to flush!"); + return ESP_FAIL; + } + } + return ESP_ERR_TIMEOUT; + } else { // trying during the timeout + uint32_t ticks_start = xTaskGetTickCount(); + uint32_t ticks_now = ticks_start; + while (1) { // loop until success or until the time runs out + ticks_now = xTaskGetTickCount(); + if (!tud_cdc_n_write_occupied(itf)) { // if nothing to write - nothing to flush + break; + } + if (tud_cdc_n_write_flush(itf)) { // Success + break; + } + if ( (ticks_now - ticks_start) > timeout_ticks ) { // Time is up + ESP_LOGW(TAG, "Flush failed"); + return ESP_ERR_TIMEOUT; + } + vTaskDelay(1); + } + return ESP_OK; + } +} + +static esp_err_t alloc_obj(tinyusb_cdcacm_itf_t itf) +{ + esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf); + cdc_inst->subclass_obj = calloc(1, sizeof(esp_tusb_cdcacm_t)); + if (!cdc_inst->subclass_obj) { + return ESP_FAIL; + } else { + return ESP_OK; + } +} + +static void free_obj(tinyusb_cdcacm_itf_t itf) +{ + esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf); + free(cdc_inst->subclass_obj); + cdc_inst->subclass_obj = NULL; +} + +esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg) +{ + int itf = (int)cfg->cdc_port; + /* Creating a CDC object */ + const tinyusb_config_cdc_t cdc_cfg = { + .usb_dev = cfg->usb_dev, + .cdc_class = TUSB_CLASS_CDC, + .cdc_subclass.comm_subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL + }; + ESP_RETURN_ON_ERROR(tinyusb_cdc_init(itf, &cdc_cfg), TAG, "tinyusb_cdc_init failed"); + ESP_RETURN_ON_ERROR(alloc_obj(itf), TAG, "alloc_obj failed"); + + esp_tusb_cdcacm_t *acm = get_acm(itf); + /* Callbacks setting up*/ + if (cfg->callback_rx) { + tinyusb_cdcacm_register_callback(itf, CDC_EVENT_RX, cfg->callback_rx); + } + if (cfg->callback_rx_wanted_char) { + tinyusb_cdcacm_register_callback(itf, CDC_EVENT_RX_WANTED_CHAR, cfg->callback_rx_wanted_char); + } + if (cfg->callback_line_state_changed) { + tinyusb_cdcacm_register_callback(itf, CDC_EVENT_LINE_STATE_CHANGED, cfg->callback_line_state_changed); + } + if (cfg->callback_line_coding_changed) { + tinyusb_cdcacm_register_callback( itf, CDC_EVENT_LINE_CODING_CHANGED, cfg->callback_line_coding_changed); + } + + /* Buffers */ + + acm->ringbuf_read_mux = xSemaphoreCreateMutex(); + if (acm->ringbuf_read_mux == NULL) { + ESP_LOGE(TAG, "Creation of a ringbuf mutex failed"); + free_obj(itf); + return ESP_ERR_NO_MEM; + } + + acm->rx_tfbuf = malloc(CONFIG_TINYUSB_CDC_RX_BUFSIZE); + if (!acm->rx_tfbuf) { + ESP_LOGE(TAG, "Creation buffer error"); + free_obj(itf); + return ESP_ERR_NO_MEM; + } + acm->rx_unread_buf_sz = cfg->rx_unread_buf_sz == 0 ? RX_UNREADBUF_SZ_DEFAULT : cfg->rx_unread_buf_sz; + acm->rx_unread_buf = xRingbufferCreate(acm->rx_unread_buf_sz, RINGBUF_TYPE_BYTEBUF); + if (acm->rx_unread_buf == NULL) { + ESP_LOGE(TAG, "Creation buffer error"); + free_obj(itf); + return ESP_ERR_NO_MEM; + } else { + ESP_LOGD(TAG, "Comm Initialized buff:%d bytes", cfg->rx_unread_buf_sz); + return ESP_OK; + } +} + +bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf) +{ + esp_tusb_cdcacm_t *acm = get_acm(itf); + if (acm) { + return true; + } else { + return false; + } +} +/*********************************************************************** CDC-ACM*/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_console.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_console.c new file mode 100644 index 000000000..97c3e256d --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_console.c @@ -0,0 +1,115 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include +#include +#include "esp_log.h" +#include "cdc.h" +#include "tusb_console.h" +#include "tinyusb.h" +#include "vfs_tinyusb.h" +#include "esp_check.h" + +#define STRINGIFY(s) STRINGIFY2(s) +#define STRINGIFY2(s) #s + +static const char *TAG = "tusb_console"; + +typedef struct { + FILE *in; + FILE *out; + FILE *err; +} console_handle_t; + +static console_handle_t con; + + +/** + * @brief Reopen standard streams using a new path + * + * @param f_in - pointer to a pointer holding a file for in or NULL to don't change stdin + * @param f_out - pointer to a pointer holding a file for out or NULL to don't change stdout + * @param f_err - pointer to a pointer holding a file for err or NULL to don't change stderr + * @param path - mount point + * @return esp_err_t ESP_FAIL or ESP_OK + */ +static esp_err_t redirect_std_streams_to(FILE **f_in, FILE **f_out, FILE **f_err, const char *path) +{ + if (f_in) { + *f_in = freopen(path, "r", stdin); + if (*f_in == NULL) { + ESP_LOGE(TAG, "Failed to reopen in!"); + return ESP_FAIL; + } + } + if (f_out) { + *f_out = freopen(path, "w", stdout); + if (*f_out == NULL) { + ESP_LOGE(TAG, "Failed to reopen out!"); + return ESP_FAIL; + } + } + if (f_err) { + *f_err = freopen(path, "w", stderr); + if (*f_err == NULL) { + ESP_LOGE(TAG, "Failed to reopen err!"); + return ESP_FAIL; + } + } + + return ESP_OK; +} + +/** + * @brief Restore output to default + * + * @param f_in - pointer to a pointer of an in file updated with `redirect_std_streams_to` or NULL to don't change stdin + * @param f_out - pointer to a pointer of an out file updated with `redirect_std_streams_to` or NULL to don't change stdout + * @param f_err - pointer to a pointer of an err file updated with `redirect_std_streams_to` or NULL to don't change stderr + * @return esp_err_t ESP_FAIL or ESP_OK + */ +static esp_err_t restore_std_streams(FILE **f_in, FILE **f_out, FILE **f_err) +{ + const char *default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM); + if (f_in) { + stdin = freopen(default_uart_dev, "r", *f_in); + if (stdin == NULL) { + ESP_LOGE(TAG, "Failed to reopen stdin!"); + return ESP_FAIL; + } + } + if (f_out) { + stdout = freopen(default_uart_dev, "w", *f_out); + if (stdout == NULL) { + ESP_LOGE(TAG, "Failed to reopen stdout!"); + return ESP_FAIL; + } + } + if (f_err) { + stderr = freopen(default_uart_dev, "w", *f_err); + if (stderr == NULL) { + ESP_LOGE(TAG, "Failed to reopen stderr!"); + return ESP_FAIL; + } + } + return ESP_OK; +} + +esp_err_t esp_tusb_init_console(int cdc_intf) +{ + /* Registering TUSB at VFS */ + ESP_RETURN_ON_ERROR(esp_vfs_tusb_cdc_register(cdc_intf, NULL), TAG, ""); + ESP_RETURN_ON_ERROR(redirect_std_streams_to(&con.in, &con.out, &con.err, "/dev/tusb_cdc"), TAG, "Failed to redirect STD streams"); + return ESP_OK; +} + +esp_err_t esp_tusb_deinit_console(int cdc_intf) +{ + ESP_RETURN_ON_ERROR(restore_std_streams(&con.in, &con.out, &con.err), TAG, "Failed to restore STD streams"); + esp_vfs_tusb_cdc_unregister(NULL); + return ESP_OK; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c new file mode 100644 index 000000000..bf0681db5 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_check.h" +#include "tinyusb.h" +#include "tusb_tasks.h" + +const static char *TAG = "tusb_tsk"; +static TaskHandle_t s_tusb_tskh; + +/** + * @brief This top level thread processes all usb events and invokes callbacks + */ +static void tusb_device_task(void *arg) +{ + ESP_LOGD(TAG, "tinyusb task started"); + while (1) { // RTOS forever loop + tud_task(); + } +} + +esp_err_t tusb_run_task(void) +{ + // This function is not garanteed to be thread safe, if invoked multiple times without calling `tusb_stop_task`, will cause memory leak + // doing a sanity check anyway + ESP_RETURN_ON_FALSE(!s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task already started"); + // Create a task for tinyusb device stack: + xTaskCreate(tusb_device_task, "TinyUSB", CONFIG_TINYUSB_TASK_STACK_SIZE, NULL, CONFIG_TINYUSB_TASK_PRIORITY, &s_tusb_tskh); + ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_FAIL, TAG, "create TinyUSB main task failed"); + return ESP_OK; +} + +esp_err_t tusb_stop_task(void) +{ + ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task not started yet"); + vTaskDelete(s_tusb_tskh); + s_tusb_tskh = NULL; + return ESP_OK; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/usb_descriptors.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/usb_descriptors.c new file mode 100644 index 000000000..d4d3004e7 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/usb_descriptors.c @@ -0,0 +1,186 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "usb_descriptors.h" +#include "sdkconfig.h" + +/* + * A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] HID | MSC | CDC [LSB] + */ +#define USB_TUSB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) ) //| _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) + +/**** TinyUSB default ****/ +tusb_desc_device_t descriptor_tinyusb = { + .bLength = sizeof(descriptor_tinyusb), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + +#if CFG_TUD_CDC + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, +#else + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, +#endif + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_TUSB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +tusb_desc_strarray_device_t descriptor_str_tinyusb = { + // array of pointer to string descriptors + (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + "123456", // 3: Serials, should use chip ID +}; +/* End of TinyUSB default */ + +/**** Kconfig driven Descriptor ****/ +const tusb_desc_device_t descriptor_dev_kconfig = { + .bLength = sizeof(descriptor_dev_kconfig), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + +#if CFG_TUD_CDC + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, +#else + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, +#endif + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + +#if CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID + .idVendor = USB_ESPRESSIF_VID, +#else + .idVendor = CONFIG_TINYUSB_DESC_CUSTOM_VID, +#endif + +#if CONFIG_TINYUSB_DESC_USE_DEFAULT_PID + .idProduct = USB_TUSB_PID, +#else + .idProduct = CONFIG_TINYUSB_DESC_CUSTOM_PID, +#endif + + .bcdDevice = CONFIG_TINYUSB_DESC_BCD_DEVICE, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +tusb_desc_strarray_device_t descriptor_str_kconfig = { + // array of pointer to string descriptors + (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) + CONFIG_TINYUSB_DESC_MANUFACTURER_STRING, // 1: Manufacturer + CONFIG_TINYUSB_DESC_PRODUCT_STRING, // 2: Product + CONFIG_TINYUSB_DESC_SERIAL_STRING, // 3: Serials, should use chip ID + +#if CONFIG_TINYUSB_CDC_ENABLED + CONFIG_TINYUSB_DESC_CDC_STRING, // 4: CDC Interface +#else + "", +#endif + +#if CONFIG_TINYUSB_MSC_ENABLED + CONFIG_TINYUSB_DESC_MSC_STRING, // 5: MSC Interface +#else + "", +#endif + +}; + +//------------- Configuration Descriptor -------------// +enum { +#if CFG_TUD_CDC + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, +#endif + +#if CFG_TUD_CDC > 1 + ITF_NUM_CDC1, + ITF_NUM_CDC1_DATA, +#endif + +#if CFG_TUD_MSC + ITF_NUM_MSC, +#endif + + ITF_NUM_TOTAL +}; + +enum { + TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN + + CFG_TUD_CDC * TUD_CDC_DESC_LEN + + CFG_TUD_MSC * TUD_MSC_DESC_LEN +}; + +//------------- USB Endpoint numbers -------------// +enum { + // Available USB Endpoints: 5 IN/OUT EPs and 1 IN EP + EP_EMPTY = 0, +#if CFG_TUD_CDC + EPNUM_0_CDC_NOTIF, + EPNUM_0_CDC, +#endif + +#if CFG_TUD_CDC > 1 + EPNUM_1_CDC_NOTIF, + EPNUM_1_CDC, +#endif + +#if CFG_TUD_MSC + EPNUM_MSC, +#endif +}; + +uint8_t const descriptor_cfg_kconfig[] = { + // Configuration number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + +#if CFG_TUD_CDC + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, CFG_TUD_CDC_EP_BUFSIZE), +#endif + +#if CFG_TUD_CDC > 1 + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, CFG_TUD_CDC_EP_BUFSIZE), +#endif + +#if CFG_TUD_MSC + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512 +#endif +}; + +/* End of Kconfig driven Descriptor */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/vfs_tinyusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/vfs_tinyusb.c new file mode 100644 index 000000000..fdf31e6a9 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/vfs_tinyusb.c @@ -0,0 +1,289 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_vfs.h" +#include "esp_vfs_dev.h" +#include "tinyusb.h" +#include "tusb_cdc_acm.h" +#include "vfs_tinyusb.h" +#include "sdkconfig.h" + +const static char *TAG = "tusb_vfs"; +#define VFS_TUSB_MAX_PATH 16 +#define VFS_TUSB_PATH_DEFAULT "/dev/tusb_cdc" + +// Token signifying that no character is available +#define NONE -1 + +#define FD_CHECK(fd, ret_val) do { \ + if ((fd) != 0) { \ + errno = EBADF; \ + return (ret_val); \ + } \ + } while (0) + + + +#if CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF +# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CRLF +#elif CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR +# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CR +#else +# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_LF +#endif + +#if CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF +# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CRLF +#elif CONFIG_NEWLIB_STDIN_LINE_ENDING_CR +# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CR +#else +# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_LF +#endif + +typedef struct { + _lock_t write_lock; + _lock_t read_lock; + esp_line_endings_t tx_mode; // Newline conversion mode when transmitting + esp_line_endings_t rx_mode; // Newline conversion mode when receiving + uint32_t flags; + char vfs_path[VFS_TUSB_MAX_PATH]; + int cdc_intf; +} vfs_tinyusb_t; + +static vfs_tinyusb_t s_vfstusb; + + +static esp_err_t apply_path(char const *path) +{ + if (path != NULL) { + size_t path_len = strlen(path) + 1; + if (path_len > VFS_TUSB_MAX_PATH) { + ESP_LOGE(TAG, "The path is too long; maximum is %d characters", VFS_TUSB_MAX_PATH); + return ESP_ERR_INVALID_ARG; + } + strncpy(s_vfstusb.vfs_path, path, (VFS_TUSB_MAX_PATH - 1)); + } else { + strncpy(s_vfstusb.vfs_path, + VFS_TUSB_PATH_DEFAULT, + (VFS_TUSB_MAX_PATH - 1)); + } + ESP_LOGV(TAG, "Path is set to `%s`", s_vfstusb.vfs_path); + return ESP_OK; +} + +/** + * @brief Fill s_vfstusb + * + * @param cdc_intf - interface of tusb for registration + * @param path - a path where the CDC will be registered + * @return esp_err_t ESP_OK or ESP_ERR_INVALID_ARG + */ +static esp_err_t vfstusb_init(int cdc_intf, char const *path) +{ + s_vfstusb.cdc_intf = cdc_intf; + s_vfstusb.tx_mode = DEFAULT_TX_MODE; + s_vfstusb.rx_mode = DEFAULT_RX_MODE; + + return apply_path(path); +} + +/** + * @brief Clear s_vfstusb to default values + */ +static void vfstusb_deinit(void) +{ + memset(&s_vfstusb, 0, sizeof(s_vfstusb)); +} + + +static int tusb_open(const char *path, int flags, int mode) +{ + (void) mode; + (void) path; + s_vfstusb.flags = flags | O_NONBLOCK; // for now only non-blocking mode is implemented + return 0; +} + +static ssize_t tusb_write(int fd, const void *data, size_t size) +{ + FD_CHECK(fd, -1); + size_t written_sz = 0; + const char *data_c = (const char *)data; + _lock_acquire(&(s_vfstusb.write_lock)); + for (size_t i = 0; i < size; i++) { + int c = data_c[i]; + /* handling the EOL */ + if (c == '\n' && s_vfstusb.tx_mode != ESP_LINE_ENDINGS_LF) { + if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, '\r')) { + written_sz++; + } else { + break; // can't write anymore + } + if (s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CR) { + continue; + } + } + /* write a char */ + if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, c)) { + written_sz++; + } else { + break; // can't write anymore + } + + } + tud_cdc_n_write_flush(s_vfstusb.cdc_intf); + _lock_release(&(s_vfstusb.write_lock)); + return written_sz; +} + +static int tusb_close(int fd) +{ + FD_CHECK(fd, -1); + return 0; +} + +static ssize_t tusb_read(int fd, void *data, size_t size) +{ + FD_CHECK(fd, -1); + char *data_c = (char *) data; + size_t received = 0; + _lock_acquire(&(s_vfstusb.read_lock)); + int cm1 = NONE; + int c = NONE; + + while (received < size) { + cm1 = c; // store the old char + int c = tud_cdc_n_read_char(0); // get a new one + if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) { + if (c == '\r') { + c = '\n'; + } + } else if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) { + if ((c == '\n') & (cm1 == '\r')) { + --received; // step back + c = '\n'; + } + } + if ( c == NONE) { // if data ends + break; + } + data_c[received] = (char) c; + ++received; + if (c == '\n') { + break; + } + } + _lock_release(&(s_vfstusb.read_lock)); + if (received > 0) { + return received; + } + errno = EWOULDBLOCK; + return -1; +} + + +static int tusb_fstat(int fd, struct stat *st) +{ + FD_CHECK(fd, -1); + memset(st, 0, sizeof(*st)); + st->st_mode = S_IFCHR; + return 0; +} + +static int tusb_fcntl(int fd, int cmd, int arg) +{ + FD_CHECK(fd, -1); + int result = 0; + switch (cmd) { + case F_GETFL: + result = s_vfstusb.flags; + break; + case F_SETFL: + s_vfstusb.flags = arg; + break; + default: + result = -1; + errno = ENOSYS; + break; + } + return result; +} + +esp_err_t esp_vfs_tusb_cdc_unregister(char const *path) +{ + ESP_LOGD(TAG, "Unregistering TinyUSB driver"); + int res; + + if (path == NULL) { // NULL means using the default path for unregistering: VFS_TUSB_PATH_DEFAULT + res = strcmp(s_vfstusb.vfs_path, VFS_TUSB_PATH_DEFAULT); + } else { + res = strcmp(s_vfstusb.vfs_path, path); + } + + if (res) { + res = ESP_ERR_INVALID_ARG; + ESP_LOGE(TAG, "There is no TinyUSB driver registerred to the path '%s' (err: 0x%x)", s_vfstusb.vfs_path, res); + return res; + } + + + + res = esp_vfs_unregister(s_vfstusb.vfs_path); + if (res != ESP_OK) { + ESP_LOGE(TAG, "Can't unregister TinyUSB driver from '%s' (err: 0x%x)", s_vfstusb.vfs_path, res); + } else { + ESP_LOGD(TAG, "Unregistered TinyUSB driver"); + vfstusb_deinit(); + } + return res; +} + + + + +esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path) +{ + ESP_LOGD(TAG, "Registering TinyUSB CDC driver"); + int res; + if (!tusb_cdc_acm_initialized(cdc_intf)) { + ESP_LOGE(TAG, "TinyUSB CDC#%d is not initialized", cdc_intf); + return ESP_ERR_INVALID_STATE; + } + + res = vfstusb_init(cdc_intf, path); + if (res != ESP_OK) { + return res; + } + + esp_vfs_t vfs = { + .flags = ESP_VFS_FLAG_DEFAULT, + .close = &tusb_close, + .fcntl = &tusb_fcntl, + .fstat = &tusb_fstat, + .open = &tusb_open, + .read = &tusb_read, + .write = &tusb_write, + }; + + res = esp_vfs_register(s_vfstusb.vfs_path, &vfs, NULL); + if (res != ESP_OK) { + ESP_LOGE(TAG, "Can't register TinyUSB driver (err: %x)", res); + } else { + ESP_LOGD(TAG, "TinyUSB CDC registered (%s)", s_vfstusb.vfs_path); + } + return res; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h new file mode 100644 index 000000000..35342cfe5 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h @@ -0,0 +1,97 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup group_board + * \defgroup group_ansi_esc ANSI Esacpe Code + * @{ */ + +#ifndef _TUSB_ANSI_ESC_CODE_H_ +#define _TUSB_ANSI_ESC_CODE_H_ + + +#ifdef __cplusplus + extern "C" { +#endif + +#define CSI_CODE(seq) "\33[" seq +#define CSI_SGR(x) CSI_CODE(#x) "m" + +//------------- Cursor movement -------------// +/** \defgroup group_ansi_cursor Cursor Movement + * @{ */ +#define ANSI_CURSOR_UP(n) CSI_CODE(#n "A") ///< Move cursor up +#define ANSI_CURSOR_DOWN(n) CSI_CODE(#n "B") ///< Move cursor down +#define ANSI_CURSOR_FORWARD(n) CSI_CODE(#n "C") ///< Move cursor forward +#define ANSI_CURSOR_BACKWARD(n) CSI_CODE(#n "D") ///< Move cursor backward +#define ANSI_CURSOR_LINE_DOWN(n) CSI_CODE(#n "E") ///< Move cursor to the beginning of the line (n) down +#define ANSI_CURSOR_LINE_UP(n) CSI_CODE(#n "F") ///< Move cursor to the beginning of the line (n) up +#define ANSI_CURSOR_POSITION(n, m) CSI_CODE(#n ";" #m "H") ///< Move cursor to position (n, m) +/** @} */ + +//------------- Screen -------------// +/** \defgroup group_ansi_screen Screen Control + * @{ */ +#define ANSI_ERASE_SCREEN(n) CSI_CODE(#n "J") ///< Erase the screen +#define ANSI_ERASE_LINE(n) CSI_CODE(#n "K") ///< Erase the line (n) +#define ANSI_SCROLL_UP(n) CSI_CODE(#n "S") ///< Scroll the whole page up (n) lines +#define ANSI_SCROLL_DOWN(n) CSI_CODE(#n "T") ///< Scroll the whole page down (n) lines +/** @} */ + +//------------- Text Color -------------// +/** \defgroup group_ansi_text Text Color + * @{ */ +#define ANSI_TEXT_BLACK CSI_SGR(30) +#define ANSI_TEXT_RED CSI_SGR(31) +#define ANSI_TEXT_GREEN CSI_SGR(32) +#define ANSI_TEXT_YELLOW CSI_SGR(33) +#define ANSI_TEXT_BLUE CSI_SGR(34) +#define ANSI_TEXT_MAGENTA CSI_SGR(35) +#define ANSI_TEXT_CYAN CSI_SGR(36) +#define ANSI_TEXT_WHITE CSI_SGR(37) +#define ANSI_TEXT_DEFAULT CSI_SGR(39) +/** @} */ + +//------------- Background Color -------------// +/** \defgroup group_ansi_background Background Color + * @{ */ +#define ANSI_BG_BLACK CSI_SGR(40) +#define ANSI_BG_RED CSI_SGR(41) +#define ANSI_BG_GREEN CSI_SGR(42) +#define ANSI_BG_YELLOW CSI_SGR(43) +#define ANSI_BG_BLUE CSI_SGR(44) +#define ANSI_BG_MAGENTA CSI_SGR(45) +#define ANSI_BG_CYAN CSI_SGR(46) +#define ANSI_BG_WHITE CSI_SGR(47) +#define ANSI_BG_DEFAULT CSI_SGR(49) +/** @} */ + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_ANSI_ESC_CODE_H_ */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c new file mode 100644 index 000000000..e208624ba --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c @@ -0,0 +1,149 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018, hathach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "board.h" + +#if 0 +#define LED_PHASE_MAX 8 + +static struct +{ + uint32_t phase[LED_PHASE_MAX]; + uint8_t phase_count; + + bool led_state; + uint8_t current_phase; + uint32_t current_ms; +}led_pattern; + +void board_led_pattern(uint32_t const phase_ms[], uint8_t count) +{ + memcpy(led_pattern.phase, phase_ms, 4*count); + led_pattern.phase_count = count; + + // reset with 1st phase is on + led_pattern.current_ms = board_millis(); + led_pattern.current_phase = 0; + led_pattern.led_state = true; + board_led_on(); +} + +void board_led_task(void) +{ + if ( led_pattern.phase_count == 0 ) return; + + uint32_t const duration = led_pattern.phase[led_pattern.current_phase]; + + // return if not enough time + if (board_millis() - led_pattern.current_ms < duration) return; + + led_pattern.led_state = !led_pattern.led_state; + board_led_write(led_pattern.led_state); + + led_pattern.current_ms += duration; + led_pattern.current_phase++; + + if (led_pattern.current_phase == led_pattern.phase_count) + { + led_pattern.current_phase = 0; + led_pattern.led_state = true; + board_led_on(); + } +} +#endif + +//--------------------------------------------------------------------+ +// newlib read()/write() retarget +//--------------------------------------------------------------------+ + +#if defined(__MSP430__) || defined(__RX__) + #define sys_write write + #define sys_read read +#else + #define sys_write _write + #define sys_read _read +#endif + +#if defined(LOGGER_RTT) +// Logging with RTT + +// If using SES IDE, use the Syscalls/SEGGER_RTT_Syscalls_SES.c instead +#if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM) +#include "SEGGER_RTT.h" + +TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) +{ + (void) fhdl; + SEGGER_RTT_Write(0, (const char*) buf, (int) count); + return count; +} + +TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) +{ + (void) fhdl; + return SEGGER_RTT_Read(0, buf, count); +} +#endif + +#elif defined(LOGGER_SWO) +// Logging with SWO for ARM Cortex + +#include "board_mcu.h" + +TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) +{ + (void) fhdl; + uint8_t const* buf8 = (uint8_t const*) buf; + for(size_t i=0; i +#include + +#include "ansi_escape.h" +#include "tusb.h" + +#define CFG_BOARD_UART_BAUDRATE 115200 + +//--------------------------------------------------------------------+ +// Board Porting API +// For simplicity, only one LED and one Button are used +//--------------------------------------------------------------------+ + +// Initialize on-board peripherals : led, button, uart and USB +void board_init(void); + +// Turn LED on or off +void board_led_write(bool state); + +// Control led pattern using phase duration in ms. +// For each phase, LED is toggle then repeated, board_led_task() is required to be called +//void board_led_pattern(uint32_t const phase_ms[], uint8_t count); + +// Get the current state of button +// a '1' means active (pressed), a '0' means inactive. +uint32_t board_button_read(void); + +// Get characters from UART +int board_uart_read(uint8_t* buf, int len); + +// Send characters to UART +int board_uart_write(void const * buf, int len); + +#if CFG_TUSB_OS == OPT_OS_NONE + // Get current milliseconds, must be implemented when no RTOS is used + uint32_t board_millis(void); + +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + static inline uint32_t board_millis(void) + { + return ( ( ((uint64_t) xTaskGetTickCount()) * 1000) / configTICK_RATE_HZ ); + } + +#elif CFG_TUSB_OS == OPT_OS_MYNEWT + static inline uint32_t board_millis(void) + { + return os_time_ticks_to_ms32( os_time_get() ); + } + +#elif CFG_TUSB_OS == OPT_OS_PICO + #include "pico/time.h" + static inline uint32_t board_millis(void) + { + return to_ms_since_boot(get_absolute_time()); + } + +#elif CFG_TUSB_OS == OPT_OS_RTTHREAD + static inline uint32_t board_millis(void) + { + return (((uint64_t)rt_tick_get()) * 1000 / RT_TICK_PER_SECOND); + } + +#else + #error "board_millis() is not implemented for this OS" +#endif + +//--------------------------------------------------------------------+ +// Helper functions +//--------------------------------------------------------------------+ +static inline void board_led_on(void) +{ + board_led_write(true); +} + +static inline void board_led_off(void) +{ + board_led_write(false); +} + +// TODO remove +static inline void board_delay(uint32_t ms) +{ + uint32_t start_ms = board_millis(); + while (board_millis() - start_ms < ms) + { + #if TUSB_OPT_DEVICE_ENABLED + // take chance to run usb background + tud_task(); + #endif + } +} + +static inline int board_uart_getchar(void) +{ + uint8_t c; + return board_uart_read(&c, 1) ? (int) c : (-1); +} + +static inline int board_uart_putchar(uint8_t c) +{ + return board_uart_write(&c, 1); +} + +#ifdef __cplusplus + } +#endif + +#endif /* _BSP_BOARD_H_ */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h new file mode 100644 index 000000000..b911e1e53 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h @@ -0,0 +1,157 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + + +#ifndef BOARD_MCU_H_ +#define BOARD_MCU_H_ + +#include "tusb_option.h" + +//--------------------------------------------------------------------+ +// Low Level MCU header include. TinyUSB stack and example should be +// platform independent and mostly doesn't need to include this file. +// However there are still certain situation where this file is needed: +// - FreeRTOSConfig.h to set up correct clock and NVIC interrupts for ARM Cortex +// - SWO logging for Cortex M with ITM_SendChar() / ITM_ReceiveChar() +//--------------------------------------------------------------------+ + +// Include order follows OPT_MCU_ number +#if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC15XX || CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ + CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC40XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX + #include "chip.h" + +#elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ + CFG_TUSB_MCU == OPT_MCU_LPC55XX || CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || \ + CFG_TUSB_MCU == OPT_MCU_K32L2BXX + #include "fsl_device_registers.h" + +#elif CFG_TUSB_MCU == OPT_MCU_NRF5X + #include "nrf.h" + +#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ + CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ + CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21 + #include "sam.h" + +#elif CFG_TUSB_MCU == OPT_MCU_SAMG + #undef LITTLE_ENDIAN // hack to suppress "LITTLE_ENDIAN" redefined + #include "sam.h" + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F0 + #include "stm32f0xx.h" + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 + #include "stm32f1xx.h" + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F2 + #include "stm32f2xx.h" + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F3 + #include "stm32f3xx.h" + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F4 + #include "stm32f4xx.h" + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F7 + #include "stm32f7xx.h" + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H7 + #include "stm32h7xx.h" + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 + #include "stm32l0xx.h" + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 + #include "stm32l1xx.h" + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 + #include "stm32l4xx.h" + +#elif CFG_TUSB_MCU == OPT_MCU_CXD56 + // no header needed + +#elif CFG_TUSB_MCU == OPT_MCU_MSP430x5xx + #include "msp430.h" + +#elif CFG_TUSB_MCU == OPT_MCU_MSP432E4 + #include "msp.h" + +#elif CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI + // no header needed + +#elif CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX + #include "fsl_device_registers.h" + +#elif CFG_TUSB_MCU == OPT_MCU_NUC120 + #include "NUC100Series.h" + +#elif CFG_TUSB_MCU == OPT_MCU_NUC121 || CFG_TUSB_MCU == OPT_MCU_NUC126 + #include "NuMicro.h" + +#elif CFG_TUSB_MCU == OPT_MCU_NUC505 + #include "NUC505Series.h" + +#elif CFG_TUSB_MCU == OPT_MCU_ESP32S2 + // no header needed + +#elif CFG_TUSB_MCU == OPT_MCU_ESP32S3 + // no header needed + +#elif CFG_TUSB_MCU == OPT_MCU_DA1469X + #include "DA1469xAB.h" + +#elif CFG_TUSB_MCU == OPT_MCU_RP2040 + #include "pico.h" + +#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG + #include "em_device.h" + +#elif CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X + // no header needed + +#elif CFG_TUSB_MCU == OPT_MCU_GD32VF103 + #include "gd32vf103.h" + +#elif CFG_TUSB_MCU == OPT_MCU_MM32F327X + #include "mm32_device.h" + +#elif CFG_TUSB_MCU == OPT_MCU_XMC4000 + #include "xmc_device.h" + +#elif CFG_TUSB_MCU == OPT_MCU_TM4C123 + #include "TM4C123.h" + +#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) + // no header needed + +#else + #error "Missing MCU header" +#endif + + +#endif /* BOARD_MCU_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt new file mode 100644 index 000000000..c3c687a70 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt @@ -0,0 +1,12 @@ +idf_component_register(SRCS esp32s2.c + INCLUDE_DIRS "." "${BOARD}" + PRIV_REQUIRES "driver" + REQUIRES freertos src led_strip) + +# Apply board specific content +include("${BOARD}/board.cmake") + +target_include_directories(${COMPONENT_TARGET} PUBLIC + "${TOP}/hw" + "${TOP}/src" +) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake new file mode 100644 index 000000000..d33962676 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake @@ -0,0 +1,17 @@ +# Apply board specific content here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +idf_build_get_property(idf_target IDF_TARGET) + +message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") + +if(NOT ${idf_target} STREQUAL "esp32s2") + message(FATAL_ERROR "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET}(${idf_target}), try to clean the build first." ) +endif() + +set(IDF_TARGET "esp32s2" FORCE) + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h new file mode 100644 index 000000000..43e00901d --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 33 +#define NEOPIXEL_POWER_PIN 21 +#define NEOPIXEL_POWER_STATE 1 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake new file mode 100644 index 000000000..d33962676 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake @@ -0,0 +1,17 @@ +# Apply board specific content here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +idf_build_get_property(idf_target IDF_TARGET) + +message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") + +if(NOT ${idf_target} STREQUAL "esp32s2") + message(FATAL_ERROR "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET}(${idf_target}), try to clean the build first." ) +endif() + +set(IDF_TARGET "esp32s2" FORCE) + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h new file mode 100644 index 000000000..16e30b685 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 1 +#define NEOPIXEL_POWER_PIN 21 +#define NEOPIXEL_POWER_STATE 0 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake new file mode 100644 index 000000000..d5c17b9be --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake @@ -0,0 +1,17 @@ +# Apply board specific content here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +idf_build_get_property(idf_target IDF_TARGET) + +message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") + +if(NOT ${idf_target} STREQUAL "esp32s2") + message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." ) +endif() + +set(IDF_TARGET "esp32s2" FORCE) + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h new file mode 100644 index 000000000..49a2474bc --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 45 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c new file mode 100644 index 000000000..a81181672 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c @@ -0,0 +1,148 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "../../board.h" +#include "board.h" + +#include "esp_rom_gpio.h" +#include "hal/gpio_ll.h" +#include "hal/usb_hal.h" +#include "soc/usb_periph.h" + +#include "driver/periph_ctrl.h" +#include "driver/rmt.h" + +#ifdef NEOPIXEL_PIN +#include "led_strip.h" +static led_strip_t *strip; +#endif + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +static void configure_pins(usb_hal_context_t *usb); + +// Initialize on-board peripherals : led, button, uart and USB +void board_init(void) +{ + +#ifdef NEOPIXEL_PIN + #ifdef NEOPIXEL_POWER_PIN + gpio_reset_pin(NEOPIXEL_POWER_PIN); + gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT); + gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE); + #endif + + // WS2812 Neopixel driver with RMT peripheral + rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0); + config.clk_div = 2; // set counter clock to 40MHz + + rmt_config(&config); + rmt_driver_install(config.channel, 0, 0); + + led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel); + strip = led_strip_new_rmt_ws2812(&strip_config); + strip->clear(strip, 100); // off led +#endif + + // Button + esp_rom_gpio_pad_select_gpio(BUTTON_PIN); + gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); + gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); + + // USB Controller Hal init + periph_module_reset(PERIPH_USB_MODULE); + periph_module_enable(PERIPH_USB_MODULE); + + usb_hal_context_t hal = { + .use_external_phy = false // use built-in PHY + }; + usb_hal_init(&hal); + configure_pins(&hal); +} + +static void configure_pins(usb_hal_context_t *usb) +{ + /* usb_periph_iopins currently configures USB_OTG as USB Device. + * Introduce additional parameters in usb_hal_context_t when adding support + * for USB Host. + */ + for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { + if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { + esp_rom_gpio_pad_select_gpio(iopin->pin); + if (iopin->is_output) { + esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false); + } else { + esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false); +#if ESP_IDF_VERSION_MAJOR > 4 + if ((iopin->pin != GPIO_MATRIX_CONST_ZERO_INPUT) && (iopin->pin != GPIO_MATRIX_CONST_ONE_INPUT)) +#else + if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) +#endif + { + gpio_ll_input_enable(&GPIO, iopin->pin); + } + } + esp_rom_gpio_pad_unhold(iopin->pin); + } + } + if (!usb->use_external_phy) { + gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); + gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); + } +} + +// Turn LED on or off +void board_led_write(bool state) +{ +#ifdef NEOPIXEL_PIN + strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00); + strip->refresh(strip, 100); +#endif +} + +// Get the current state of button +// a '1' means active (pressed), a '0' means inactive. +uint32_t board_button_read(void) +{ + return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE; +} + +// Get characters from UART +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +// Send characters to UART +int board_uart_write(void const * buf, int len) +{ + (void) buf; (void) len; + return 0; +} + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake new file mode 100644 index 000000000..d5c17b9be --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake @@ -0,0 +1,17 @@ +# Apply board specific content here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +idf_build_get_property(idf_target IDF_TARGET) + +message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") + +if(NOT ${idf_target} STREQUAL "esp32s2") + message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." ) +endif() + +set(IDF_TARGET "esp32s2" FORCE) + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h new file mode 100644 index 000000000..6bb44f76d --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// Note: need to insert jumper next to WS2812 pixel +#define NEOPIXEL_PIN 45 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake new file mode 100644 index 000000000..d5c17b9be --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake @@ -0,0 +1,17 @@ +# Apply board specific content here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +idf_build_get_property(idf_target IDF_TARGET) + +message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") + +if(NOT ${idf_target} STREQUAL "esp32s2") + message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." ) +endif() + +set(IDF_TARGET "esp32s2" FORCE) + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h new file mode 100644 index 000000000..f450b9a8b --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// Note: On the production version (v1.2) WS2812 is connected to GPIO 18, +// however earlier revision v1.1 WS2812 is connected to GPIO 17 +#define NEOPIXEL_PIN 18 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt new file mode 100644 index 000000000..6d0fcbc86 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt @@ -0,0 +1,8 @@ +set(component_srcs "src/led_strip_rmt_ws2812.c") + +idf_component_register(SRCS "${component_srcs}" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "" + PRIV_REQUIRES "driver" + REQUIRES "") + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h new file mode 100644 index 000000000..a9dffc325 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h @@ -0,0 +1,126 @@ +// Copyright 2019 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 "esp_err.h" + +/** +* @brief LED Strip Type +* +*/ +typedef struct led_strip_s led_strip_t; + +/** +* @brief LED Strip Device Type +* +*/ +typedef void *led_strip_dev_t; + +/** +* @brief Declare of LED Strip Type +* +*/ +struct led_strip_s { + /** + * @brief Set RGB for a specific pixel + * + * @param strip: LED strip + * @param index: index of pixel to set + * @param red: red part of color + * @param green: green part of color + * @param blue: blue part of color + * + * @return + * - ESP_OK: Set RGB for a specific pixel successfully + * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters + * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred + */ + esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); + + /** + * @brief Refresh memory colors to LEDs + * + * @param strip: LED strip + * @param timeout_ms: timeout value for refreshing task + * + * @return + * - ESP_OK: Refresh successfully + * - ESP_ERR_TIMEOUT: Refresh failed because of timeout + * - ESP_FAIL: Refresh failed because some other error occurred + * + * @note: + * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. + */ + esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms); + + /** + * @brief Clear LED strip (turn off all LEDs) + * + * @param strip: LED strip + * @param timeout_ms: timeout value for clearing task + * + * @return + * - ESP_OK: Clear LEDs successfully + * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout + * - ESP_FAIL: Clear LEDs failed because some other error occurred + */ + esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); + + /** + * @brief Free LED strip resources + * + * @param strip: LED strip + * + * @return + * - ESP_OK: Free resources successfully + * - ESP_FAIL: Free resources failed because error occurred + */ + esp_err_t (*del)(led_strip_t *strip); +}; + +/** +* @brief LED Strip Configuration Type +* +*/ +typedef struct { + uint32_t max_leds; /*!< Maximum LEDs in a single strip */ + led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */ +} led_strip_config_t; + +/** + * @brief Default configuration for LED strip + * + */ +#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \ + { \ + .max_leds = number, \ + .dev = dev_hdl, \ + } + +/** +* @brief Install a new ws2812 driver (based on RMT peripheral) +* +* @param config: LED strip configuration +* @return +* LED strip instance or NULL +*/ +led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c new file mode 100644 index 000000000..025d3c590 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c @@ -0,0 +1,171 @@ +// Copyright 2019 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. +#include +#include +#include +#include "esp_log.h" +#include "esp_attr.h" +#include "led_strip.h" +#include "driver/rmt.h" + +static const char *TAG = "ws2812"; +#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ + do \ + { \ + if (!(a)) \ + { \ + ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ret = ret_value; \ + goto goto_tag; \ + } \ + } while (0) + +#define WS2812_T0H_NS (350) +#define WS2812_T0L_NS (1000) +#define WS2812_T1H_NS (1000) +#define WS2812_T1L_NS (350) +#define WS2812_RESET_US (280) + +static uint32_t ws2812_t0h_ticks = 0; +static uint32_t ws2812_t1h_ticks = 0; +static uint32_t ws2812_t0l_ticks = 0; +static uint32_t ws2812_t1l_ticks = 0; + +typedef struct { + led_strip_t parent; + rmt_channel_t rmt_channel; + uint32_t strip_len; + uint8_t buffer[0]; +} ws2812_t; + +/** + * @brief Conver RGB data to RMT format. + * + * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t) + * + * @param[in] src: source data, to converted to RMT format + * @param[in] dest: place where to store the convert result + * @param[in] src_size: size of source data + * @param[in] wanted_num: number of RMT items that want to get + * @param[out] translated_size: number of source data that got converted + * @param[out] item_num: number of RMT items which are converted from source data + */ +static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, + size_t wanted_num, size_t *translated_size, size_t *item_num) +{ + if (src == NULL || dest == NULL) { + *translated_size = 0; + *item_num = 0; + return; + } + const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0 + const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1 + size_t size = 0; + size_t num = 0; + uint8_t *psrc = (uint8_t *)src; + rmt_item32_t *pdest = dest; + while (size < src_size && num < wanted_num) { + for (int i = 0; i < 8; i++) { + // MSB first + if (*psrc & (1 << (7 - i))) { + pdest->val = bit1.val; + } else { + pdest->val = bit0.val; + } + num++; + pdest++; + } + size++; + psrc++; + } + *translated_size = size; + *item_num = num; +} + +static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) +{ + esp_err_t ret = ESP_OK; + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG); + uint32_t start = index * 3; + // In thr order of GRB + ws2812->buffer[start + 0] = green & 0xFF; + ws2812->buffer[start + 1] = red & 0xFF; + ws2812->buffer[start + 2] = blue & 0xFF; + return ESP_OK; +err: + return ret; +} + +static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms) +{ + esp_err_t ret = ESP_OK; + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK, + "transmit RMT samples failed", err, ESP_FAIL); + return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms)); +err: + return ret; +} + +static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms) +{ + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + // Write zero to turn off all leds + memset(ws2812->buffer, 0, ws2812->strip_len * 3); + return ws2812_refresh(strip, timeout_ms); +} + +static esp_err_t ws2812_del(led_strip_t *strip) +{ + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + free(ws2812); + return ESP_OK; +} + +led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) +{ + led_strip_t *ret = NULL; + STRIP_CHECK(config, "configuration can't be null", err, NULL); + + // 24 bits per led + uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3; + ws2812_t *ws2812 = calloc(1, ws2812_size); + STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL); + + uint32_t counter_clk_hz = 0; + STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK, + "get rmt counter clock failed", err, NULL); + // ns -> ticks + float ratio = (float)counter_clk_hz / 1e9; + ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); + ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); + ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); + ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); + + // set ws2812 to rmt adapter + rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter); + + ws2812->rmt_channel = (rmt_channel_t)config->dev; + ws2812->strip_len = config->max_leds; + + ws2812->parent.set_pixel = ws2812_set_pixel; + ws2812->parent.refresh = ws2812_refresh; + ws2812->parent.clear = ws2812_clear; + ws2812->parent.del = ws2812_del; + + return &ws2812->parent; +err: + return ret; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake new file mode 100644 index 000000000..f3d41d041 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.5) + +# Add example src and bsp directories +set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components") +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(SUPPORTED_TARGETS esp32s2) +set(FAMILY_MCUS ESP32S2) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk new file mode 100644 index 000000000..4b9000a6a --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk @@ -0,0 +1,23 @@ +#DEPS_SUBMODULES += + +.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu + +all: + idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) -DIDF_TARGET=esp32s2 build + +build: all + +fullclean: + if test -f sdkconfig; then $(RM) -f sdkconfig ; fi + if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi + +clean flash bootloader-flash app-flash erase monitor dfu-flash dfu size size-components size-files: + idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ + +uf2: $(BUILD)/$(PROJECT).uf2 + +UF2_FAMILY_ID = 0xbfdd4eee +$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin + @echo CREATE $@ + $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^ + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt new file mode 100644 index 000000000..e1b921ae9 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt @@ -0,0 +1,14 @@ +idf_component_register(SRCS esp32s3.c + INCLUDE_DIRS "." "${BOARD}" + PRIV_REQUIRES "driver" + REQUIRES freertos src led_strip) + +# Apply board specific content +include("${BOARD}/board.cmake") + +idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) +target_include_directories(${COMPONENT_TARGET} PUBLIC + "${FREERTOS_ORIG_INCLUDE_PATH}" + "${TOP}/hw" + "${TOP}/src" +) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c new file mode 100644 index 000000000..a81181672 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c @@ -0,0 +1,148 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "../../board.h" +#include "board.h" + +#include "esp_rom_gpio.h" +#include "hal/gpio_ll.h" +#include "hal/usb_hal.h" +#include "soc/usb_periph.h" + +#include "driver/periph_ctrl.h" +#include "driver/rmt.h" + +#ifdef NEOPIXEL_PIN +#include "led_strip.h" +static led_strip_t *strip; +#endif + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +static void configure_pins(usb_hal_context_t *usb); + +// Initialize on-board peripherals : led, button, uart and USB +void board_init(void) +{ + +#ifdef NEOPIXEL_PIN + #ifdef NEOPIXEL_POWER_PIN + gpio_reset_pin(NEOPIXEL_POWER_PIN); + gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT); + gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE); + #endif + + // WS2812 Neopixel driver with RMT peripheral + rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0); + config.clk_div = 2; // set counter clock to 40MHz + + rmt_config(&config); + rmt_driver_install(config.channel, 0, 0); + + led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel); + strip = led_strip_new_rmt_ws2812(&strip_config); + strip->clear(strip, 100); // off led +#endif + + // Button + esp_rom_gpio_pad_select_gpio(BUTTON_PIN); + gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); + gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); + + // USB Controller Hal init + periph_module_reset(PERIPH_USB_MODULE); + periph_module_enable(PERIPH_USB_MODULE); + + usb_hal_context_t hal = { + .use_external_phy = false // use built-in PHY + }; + usb_hal_init(&hal); + configure_pins(&hal); +} + +static void configure_pins(usb_hal_context_t *usb) +{ + /* usb_periph_iopins currently configures USB_OTG as USB Device. + * Introduce additional parameters in usb_hal_context_t when adding support + * for USB Host. + */ + for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { + if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { + esp_rom_gpio_pad_select_gpio(iopin->pin); + if (iopin->is_output) { + esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false); + } else { + esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false); +#if ESP_IDF_VERSION_MAJOR > 4 + if ((iopin->pin != GPIO_MATRIX_CONST_ZERO_INPUT) && (iopin->pin != GPIO_MATRIX_CONST_ONE_INPUT)) +#else + if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) +#endif + { + gpio_ll_input_enable(&GPIO, iopin->pin); + } + } + esp_rom_gpio_pad_unhold(iopin->pin); + } + } + if (!usb->use_external_phy) { + gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); + gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); + } +} + +// Turn LED on or off +void board_led_write(bool state) +{ +#ifdef NEOPIXEL_PIN + strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00); + strip->refresh(strip, 100); +#endif +} + +// Get the current state of button +// a '1' means active (pressed), a '0' means inactive. +uint32_t board_button_read(void) +{ + return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE; +} + +// Get characters from UART +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +// Send characters to UART +int board_uart_write(void const * buf, int len) +{ + (void) buf; (void) len; + return 0; +} + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake new file mode 100644 index 000000000..8996ff9dc --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake @@ -0,0 +1,7 @@ +# Apply board specific content here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h new file mode 100644 index 000000000..fff24ba44 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// Note: On the production version (v1.1) WS2812 is connected to GPIO 47 +#define NEOPIXEL_PIN 47 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake new file mode 100644 index 000000000..8996ff9dc --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake @@ -0,0 +1,7 @@ +# Apply board specific content here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h new file mode 100644 index 000000000..c7940c56e --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 48 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake new file mode 100644 index 000000000..8996ff9dc --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake @@ -0,0 +1,7 @@ +# Apply board specific content here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h new file mode 100644 index 000000000..c7940c56e --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 48 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt new file mode 100644 index 000000000..6d0fcbc86 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt @@ -0,0 +1,8 @@ +set(component_srcs "src/led_strip_rmt_ws2812.c") + +idf_component_register(SRCS "${component_srcs}" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "" + PRIV_REQUIRES "driver" + REQUIRES "") + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h new file mode 100644 index 000000000..a9dffc325 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h @@ -0,0 +1,126 @@ +// Copyright 2019 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 "esp_err.h" + +/** +* @brief LED Strip Type +* +*/ +typedef struct led_strip_s led_strip_t; + +/** +* @brief LED Strip Device Type +* +*/ +typedef void *led_strip_dev_t; + +/** +* @brief Declare of LED Strip Type +* +*/ +struct led_strip_s { + /** + * @brief Set RGB for a specific pixel + * + * @param strip: LED strip + * @param index: index of pixel to set + * @param red: red part of color + * @param green: green part of color + * @param blue: blue part of color + * + * @return + * - ESP_OK: Set RGB for a specific pixel successfully + * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters + * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred + */ + esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); + + /** + * @brief Refresh memory colors to LEDs + * + * @param strip: LED strip + * @param timeout_ms: timeout value for refreshing task + * + * @return + * - ESP_OK: Refresh successfully + * - ESP_ERR_TIMEOUT: Refresh failed because of timeout + * - ESP_FAIL: Refresh failed because some other error occurred + * + * @note: + * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. + */ + esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms); + + /** + * @brief Clear LED strip (turn off all LEDs) + * + * @param strip: LED strip + * @param timeout_ms: timeout value for clearing task + * + * @return + * - ESP_OK: Clear LEDs successfully + * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout + * - ESP_FAIL: Clear LEDs failed because some other error occurred + */ + esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); + + /** + * @brief Free LED strip resources + * + * @param strip: LED strip + * + * @return + * - ESP_OK: Free resources successfully + * - ESP_FAIL: Free resources failed because error occurred + */ + esp_err_t (*del)(led_strip_t *strip); +}; + +/** +* @brief LED Strip Configuration Type +* +*/ +typedef struct { + uint32_t max_leds; /*!< Maximum LEDs in a single strip */ + led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */ +} led_strip_config_t; + +/** + * @brief Default configuration for LED strip + * + */ +#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \ + { \ + .max_leds = number, \ + .dev = dev_hdl, \ + } + +/** +* @brief Install a new ws2812 driver (based on RMT peripheral) +* +* @param config: LED strip configuration +* @return +* LED strip instance or NULL +*/ +led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c new file mode 100644 index 000000000..025d3c590 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c @@ -0,0 +1,171 @@ +// Copyright 2019 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. +#include +#include +#include +#include "esp_log.h" +#include "esp_attr.h" +#include "led_strip.h" +#include "driver/rmt.h" + +static const char *TAG = "ws2812"; +#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ + do \ + { \ + if (!(a)) \ + { \ + ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ret = ret_value; \ + goto goto_tag; \ + } \ + } while (0) + +#define WS2812_T0H_NS (350) +#define WS2812_T0L_NS (1000) +#define WS2812_T1H_NS (1000) +#define WS2812_T1L_NS (350) +#define WS2812_RESET_US (280) + +static uint32_t ws2812_t0h_ticks = 0; +static uint32_t ws2812_t1h_ticks = 0; +static uint32_t ws2812_t0l_ticks = 0; +static uint32_t ws2812_t1l_ticks = 0; + +typedef struct { + led_strip_t parent; + rmt_channel_t rmt_channel; + uint32_t strip_len; + uint8_t buffer[0]; +} ws2812_t; + +/** + * @brief Conver RGB data to RMT format. + * + * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t) + * + * @param[in] src: source data, to converted to RMT format + * @param[in] dest: place where to store the convert result + * @param[in] src_size: size of source data + * @param[in] wanted_num: number of RMT items that want to get + * @param[out] translated_size: number of source data that got converted + * @param[out] item_num: number of RMT items which are converted from source data + */ +static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, + size_t wanted_num, size_t *translated_size, size_t *item_num) +{ + if (src == NULL || dest == NULL) { + *translated_size = 0; + *item_num = 0; + return; + } + const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0 + const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1 + size_t size = 0; + size_t num = 0; + uint8_t *psrc = (uint8_t *)src; + rmt_item32_t *pdest = dest; + while (size < src_size && num < wanted_num) { + for (int i = 0; i < 8; i++) { + // MSB first + if (*psrc & (1 << (7 - i))) { + pdest->val = bit1.val; + } else { + pdest->val = bit0.val; + } + num++; + pdest++; + } + size++; + psrc++; + } + *translated_size = size; + *item_num = num; +} + +static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) +{ + esp_err_t ret = ESP_OK; + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG); + uint32_t start = index * 3; + // In thr order of GRB + ws2812->buffer[start + 0] = green & 0xFF; + ws2812->buffer[start + 1] = red & 0xFF; + ws2812->buffer[start + 2] = blue & 0xFF; + return ESP_OK; +err: + return ret; +} + +static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms) +{ + esp_err_t ret = ESP_OK; + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK, + "transmit RMT samples failed", err, ESP_FAIL); + return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms)); +err: + return ret; +} + +static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms) +{ + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + // Write zero to turn off all leds + memset(ws2812->buffer, 0, ws2812->strip_len * 3); + return ws2812_refresh(strip, timeout_ms); +} + +static esp_err_t ws2812_del(led_strip_t *strip) +{ + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + free(ws2812); + return ESP_OK; +} + +led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) +{ + led_strip_t *ret = NULL; + STRIP_CHECK(config, "configuration can't be null", err, NULL); + + // 24 bits per led + uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3; + ws2812_t *ws2812 = calloc(1, ws2812_size); + STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL); + + uint32_t counter_clk_hz = 0; + STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK, + "get rmt counter clock failed", err, NULL); + // ns -> ticks + float ratio = (float)counter_clk_hz / 1e9; + ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); + ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); + ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); + ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); + + // set ws2812 to rmt adapter + rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter); + + ws2812->rmt_channel = (rmt_channel_t)config->dev; + ws2812->strip_len = config->max_leds; + + ws2812->parent.set_pixel = ws2812_set_pixel; + ws2812->parent.refresh = ws2812_refresh; + ws2812->parent.clear = ws2812_clear; + ws2812->parent.del = ws2812_del; + + return &ws2812->parent; +err: + return ret; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake new file mode 100644 index 000000000..511dd58bb --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.5) + +# Add example src and bsp directories +set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s3/boards" "${TOP}/hw/bsp/esp32s3/components") +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(SUPPORTED_TARGETS esp32s3) +set(FAMILY_MCUS ESP32S3) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk new file mode 100644 index 000000000..cf153ffc2 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk @@ -0,0 +1,26 @@ +#DEPS_SUBMODULES += + +.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu + +all: + idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) -DIDF_TARGET=esp32s3 build + +build: all + +clean: + idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) clean + +fullclean: + if test -f sdkconfig; then $(RM) -f sdkconfig ; fi + if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi + +flash bootloader-flash app-flash erase monitor dfu-flash dfu: + idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ + +uf2: $(BUILD)/$(PROJECT).uf2 + +UF2_FAMILY_ID = 0xc47e5767 +$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin + @echo CREATE $@ + $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^ + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake new file mode 100644 index 000000000..a8cc1f363 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake @@ -0,0 +1,100 @@ +if (NOT TARGET _family_support_marker) + add_library(_family_support_marker INTERFACE) + + if (NOT FAMILY) + message(FATAL_ERROR "You must set a FAMILY variable for the build (e.g. rp2040, eps32s2, esp32s3). You can do this via -DFAMILY=xxx on the camke command line") + endif() + + if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake) + message(FATAL_ERROR "Family '${FAMILY}' is not known/supported") + endif() + + function(family_filter RESULT DIR) + get_filename_component(DIR ${DIR} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + + if (EXISTS "${DIR}/only.txt") + file(READ "${DIR}/only.txt" ONLYS) + # Replace newlines with semicolon so that it is treated as a list by CMake + string(REPLACE "\n" ";" ONLYS_LINES ${ONLYS}) + # For each mcu + foreach(MCU IN LISTS FAMILY_MCUS) + # For each line in only.txt + foreach(_line ${ONLYS_LINES}) + # If mcu:xxx exists for this mcu then include + if (${_line} STREQUAL "mcu:${MCU}") + set(${RESULT} 1 PARENT_SCOPE) + return() + endif() + endforeach() + endforeach() + + # Didn't find it in only file so don't build + set(${RESULT} 0 PARENT_SCOPE) + + elseif (EXISTS "${DIR}/skip.txt") + file(READ "${DIR}/skip.txt" SKIPS) + # Replace newlines with semicolon so that it is treated as a list by CMake + string(REPLACE "\n" ";" SKIPS_LINES ${SKIPS}) + # For each mcu + foreach(MCU IN LISTS FAMILY_MCUS) + # For each line in only.txt + foreach(_line ${SKIPS_LINES}) + # If mcu:xxx exists for this mcu then skip + if (${_line} STREQUAL "mcu:${MCU}") + set(${RESULT} 0 PARENT_SCOPE) + return() + endif() + endforeach() + endforeach() + + # Didn't find in skip file so build + set(${RESULT} 1 PARENT_SCOPE) + + else() + + # Didn't find skip or only file so build + set(${RESULT} 1 PARENT_SCOPE) + + endif() + + endfunction() + + function(family_add_subdirectory DIR) + family_filter(SHOULD_ADD "${DIR}") + if (SHOULD_ADD) + add_subdirectory(${DIR}) + endif() + endfunction() + + function(family_get_project_name OUTPUT_NAME DIR) + get_filename_component(SHORT_NAME ${DIR} NAME) + set(${OUTPUT_NAME} ${TINYUSB_FAMILY_PROJECT_NAME_PREFIX}${SHORT_NAME} PARENT_SCOPE) + endfunction() + + function(family_initialize_project PROJECT DIR) + family_filter(ALLOWED "${DIR}") + if (NOT ALLOWED) + get_filename_component(SHORT_NAME ${DIR} NAME) + message(FATAL_ERROR "${SHORT_NAME} is not supported on FAMILY=${FAMILY}") + endif() + endfunction() + + # configure an executable target to link to tinyusb in device mode, and add the board implementation + function(family_configure_device_example TARGET) + # default implentation is empty, the function should be redefined in the FAMILY/family.cmake + endfunction() + + # configure an executable target to link to tinyusb in host mode, and add the board implementation + function(family_configure_host_example TARGET) + # default implentation is empty, the function should be redefined in the FAMILY/family.cmake + endfunction() + + include(${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake) + + if (NOT FAMILY_MCUS) + set(FAMILY_MCUS ${FAMILY}) + endif() + + # save it in case of re-inclusion + set(FAMILY_MCUS ${FAMILY_MCUS} CACHE INTERNAL "") +endif() \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml new file mode 100644 index 000000000..f9bc726e5 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml @@ -0,0 +1,8 @@ +dependencies: + idf: '>=5.0' +description: TinyUSB ported to Espressif's SoCs +targets: +- esp32s2 +- esp32s3 +url: https://github.com/espressif/tinyusb +version: 0.0.1 diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt new file mode 100644 index 000000000..e1f5f89ff --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt @@ -0,0 +1,34 @@ +Important - Read carefully: + +SEGGER RTT - Real Time Transfer for embedded targets + +All rights reserved. + +SEGGER strongly recommends to not make any changes +to or modify the source code of this software in order to stay +compatible with the RTT protocol and J-Link. + +Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following +condition is met: + +o Redistributions of source code must retain the above copyright + notice, this condition and the following disclaimer. + +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 SEGGER Microcontroller 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. + + +(c) 2014 - 2016 SEGGER Microcontroller GmbH +www.segger.com diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt new file mode 100644 index 000000000..49ec655c4 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt @@ -0,0 +1,20 @@ +README.txt for the SEGGER RTT Implementation Pack. + +Included files: +=============== +Root Directory + - Examples + - Main_RTT_InputEchoApp.c - Sample application which echoes input on Channel 0. + - Main_RTT_MenuApp.c - Sample application to demonstrate RTT bi-directional functionality. + - Main_RTT_PrintfTest.c - Sample application to test RTT small printf implementation. + - Main_RTT_SpeedTestApp.c - Sample application for measuring RTT performance. embOS needed. + - RTT + - SEGGER_RTT.c - The RTT implementation. + - SEGGER_RTT.h - Header for RTT implementation. + - SEGGER_RTT_Conf.h - Pre-processor configuration for the RTT implementation. + - SEGGER_RTT_Printf.c - Simple implementation of printf to write formatted strings via RTT. + - Syscalls + - RTT_Syscalls_GCC.c - Low-level syscalls to retarget printf() to RTT with GCC / Newlib. + - RTT_Syscalls_IAR.c - Low-level syscalls to retarget printf() to RTT with IAR compiler. + - RTT_Syscalls_KEIL.c - Low-level syscalls to retarget printf() to RTT with KEIL/uVision compiler. + - RTT_Syscalls_SES.c - Low-level syscalls to retarget printf() to RTT with SEGGER Embedded Studio. diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c new file mode 100644 index 000000000..3ad2b1a12 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c @@ -0,0 +1,2005 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2019 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* condition is met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this condition and the following disclaimer. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.c +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +Revision: $Rev: 17697 $ + +Additional information: + Type "int" is assumed to be 32-bits in size + H->T Host to target communication + T->H Target to host communication + + RTT channel 0 is always present and reserved for Terminal usage. + Name is fixed to "Terminal" + + Effective buffer size: SizeOfBuffer - 1 + + WrOff == RdOff: Buffer is empty + WrOff == (RdOff - 1): Buffer is full + WrOff > RdOff: Free space includes wrap-around + WrOff < RdOff: Used space includes wrap-around + (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): + Buffer full and wrap-around after next byte + + +---------------------------------------------------------------------- +*/ + +#include "SEGGER_RTT.h" + +#include // for memcpy + +/********************************************************************* +* +* Configuration, default values +* +********************************************************************** +*/ + +#ifndef BUFFER_SIZE_UP + #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host +#endif + +#ifndef BUFFER_SIZE_DOWN + #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) +#endif + +#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS + #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target +#endif + +#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS + #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target +#endif + +#ifndef SEGGER_RTT_BUFFER_SECTION + #if defined(SEGGER_RTT_SECTION) + #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION + #endif +#endif + +#ifndef SEGGER_RTT_ALIGNMENT + #define SEGGER_RTT_ALIGNMENT 0 +#endif + +#ifndef SEGGER_RTT_BUFFER_ALIGNMENT + #define SEGGER_RTT_BUFFER_ALIGNMENT 0 +#endif + +#ifndef SEGGER_RTT_MODE_DEFAULT + #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP +#endif + +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK() +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK() +#endif + +#ifndef STRLEN + #define STRLEN(a) strlen((a)) +#endif + +#ifndef STRCPY + #define STRCPY(pDest, pSrc, NumBytes) strcpy((pDest), (pSrc)) +#endif + +#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP + #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 +#endif + +#ifndef SEGGER_RTT_MEMCPY + #ifdef MEMCPY + #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes)) + #else + #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) + #endif +#endif + +#ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +// +// For some environments, NULL may not be defined until certain headers are included +// +#ifndef NULL + #define NULL 0 +#endif + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ +#if (defined __ICCARM__) || (defined __ICCRX__) + #define RTT_PRAGMA(P) _Pragma(#P) +#endif + +#if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT + #if (defined __GNUC__) + #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) + #elif (defined __ICCARM__) || (defined __ICCRX__) + #define PRAGMA(A) _Pragma(#A) +#define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ + Var + #elif (defined __CC_ARM) + #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) + #else + #error "Alignment not supported for this compiler." + #endif +#else + #define SEGGER_RTT_ALIGN(Var, Alignment) Var +#endif + +#if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) + #if (defined __GNUC__) + #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var + #elif (defined __ICCARM__) || (defined __ICCRX__) +#define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ + Var + #elif (defined __CC_ARM) + #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var + #else + #error "Section placement not supported for this compiler." + #endif +#else + #define SEGGER_RTT_PUT_SECTION(Var, Section) Var +#endif + + +#if SEGGER_RTT_ALIGNMENT + #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) +#else + #define SEGGER_RTT_CB_ALIGN(Var) Var +#endif + +#if SEGGER_RTT_BUFFER_ALIGNMENT + #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) +#else + #define SEGGER_RTT_BUFFER_ALIGN(Var) Var +#endif + + +#if defined(SEGGER_RTT_SECTION) + #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) +#else + #define SEGGER_RTT_PUT_CB_SECTION(Var) Var +#endif + +#if defined(SEGGER_RTT_BUFFER_SECTION) + #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) +#else + #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var +#endif + +/********************************************************************* +* +* Static const data +* +********************************************************************** +*/ + +static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + +/********************************************************************* +* +* Static data +* +********************************************************************** +*/ +// +// RTT Control Block and allocate buffers for channel 0 +// +SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); + +SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP])); +SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN])); + +static unsigned char _ActiveTerminal; + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _DoInit() +* +* Function description +* Initializes the control block an buffers. +* May only be called via INIT() to avoid overriding settings. +* +*/ +#define INIT() do { \ + if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ + } while (0) +static void _DoInit(void) { + SEGGER_RTT_CB* p; + // + // Initialize control block + // + p = &_SEGGER_RTT; + p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; + p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; + // + // Initialize up buffer 0 + // + p->aUp[0].sName = "Terminal"; + p->aUp[0].pBuffer = _acUpBuffer; + p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); + p->aUp[0].RdOff = 0u; + p->aUp[0].WrOff = 0u; + p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Initialize down buffer 0 + // + p->aDown[0].sName = "Terminal"; + p->aDown[0].pBuffer = _acDownBuffer; + p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); + p->aDown[0].RdOff = 0u; + p->aDown[0].WrOff = 0u; + p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Finish initialization of the control block. + // Copy Id string in three steps to make sure "SEGGER RTT" is not found + // in initializer memory (usually flash) by J-Link + // + STRCPY(&p->acID[7], "RTT", 9); + STRCPY(&p->acID[0], "SEGGER", 7); + p->acID[6] = ' '; +} + +/********************************************************************* +* +* _WriteBlocking() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* The caller is responsible for managing the write chunk sizes as +* _WriteBlocking() will block until all data has been posted successfully. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* >= 0 - Number of bytes written into buffer. +*/ +static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { + unsigned NumBytesToWrite; + unsigned NumBytesWritten; + unsigned RdOff; + unsigned WrOff; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + // + // Write data to buffer and handle wrap-around if necessary + // + NumBytesWritten = 0u; + WrOff = pRing->WrOff; + do { + RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime + if (RdOff > WrOff) { + NumBytesToWrite = RdOff - WrOff - 1u; + } else { + NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); + } + NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around + NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + NumBytesWritten += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; + while (NumBytesToWrite--) { + *pDst++ = *pBuffer++; + }; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); + NumBytesWritten += NumBytesToWrite; + pBuffer += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; +#endif + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0u; + } + pRing->WrOff = WrOff; + } while (NumBytes); + // + return NumBytesWritten; +} + +/********************************************************************* +* +* _WriteNoCheck() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* It is callers responsibility to make sure data actually fits in buffer. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking +*/ +static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { + unsigned NumBytesAtOnce; + unsigned WrOff; + unsigned Rem; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + + WrOff = pRing->WrOff; + Rem = pRing->SizeOfBuffer - WrOff; + if (Rem > NumBytes) { + // + // All data fits before wrap around + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff = WrOff; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + } else { + // + // We reach the end of the buffer, so need to wrap around + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + WrOff; + NumBytesAtOnce = Rem; + while (NumBytesAtOnce--) { + *pDst++ = *pData++; + }; + pDst = pRing->pBuffer; + NumBytesAtOnce = NumBytes - Rem; + while (NumBytesAtOnce--) { + *pDst++ = *pData++; + }; + pRing->WrOff = NumBytes - Rem; +#else + NumBytesAtOnce = Rem; + SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); + NumBytesAtOnce = NumBytes - Rem; + SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce); + pRing->WrOff = NumBytesAtOnce; +#endif + } +} + +/********************************************************************* +* +* _PostTerminalSwitch() +* +* Function description +* Switch terminal to the given terminal ID. It is the caller's +* responsibility to ensure the terminal ID is correct and there is +* enough space in the buffer for this to complete successfully. +* +* Parameters +* pRing Ring buffer to post to. +* TerminalId Terminal ID to switch to. +*/ +static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { + unsigned char ac[2]; + + ac[0] = 0xFFu; + ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit + _WriteBlocking(pRing, (const char*)ac, 2u); +} + +/********************************************************************* +* +* _GetAvailWriteSpace() +* +* Function description +* Returns the number of bytes that can be written to the ring +* buffer without blocking. +* +* Parameters +* pRing Ring buffer to check. +* +* Return value +* Number of bytes that are free in the buffer. +*/ +static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { + unsigned RdOff; + unsigned WrOff; + unsigned r; + // + // Avoid warnings regarding volatile access order. It's not a problem + // in this case, but dampen compiler enthusiasm. + // + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + if (RdOff <= WrOff) { + r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; + } else { + r = RdOff - WrOff - 1u; + } + return r; +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_ReadUpBufferNoLock() +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the application. +* Do not lock against interrupts and multiple access. +* Used to do the same operation that J-Link does, to transfer +* RTT data via other channels, such as TCP/IP or UART. +* +* Parameters +* BufferIndex Index of Up-buffer to be used. +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +* +* Additional information +* This function must not be called when J-Link might also do RTT. +*/ +unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { + unsigned NumBytesRem; + unsigned NumBytesRead; + unsigned RdOff; + unsigned WrOff; + unsigned char* pBuffer; + SEGGER_RTT_BUFFER_UP* pRing; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + const char* pSrc; +#endif + // + INIT(); + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + pBuffer = (unsigned char*)pData; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + NumBytesRead = 0u; + // + // Read from current read position to wrap-around of buffer, first + // + if (RdOff > WrOff) { + NumBytesRem = pRing->SizeOfBuffer - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pSrc = pRing->pBuffer + RdOff; + NumBytesRead += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + while (NumBytesRem--) { + *pBuffer++ = *pSrc++; + }; +#else + SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; +#endif + // + // Handle wrap-around of buffer + // + if (RdOff == pRing->SizeOfBuffer) { + RdOff = 0u; + } + } + // + // Read remaining items of buffer + // + NumBytesRem = WrOff - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + if (NumBytesRem > 0u) { +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pSrc = pRing->pBuffer + RdOff; + NumBytesRead += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + while (NumBytesRem--) { + *pBuffer++ = *pSrc++; + }; +#else + SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; +#endif + } + // + // Update read offset of buffer + // + if (NumBytesRead) { + pRing->RdOff = RdOff; + } + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_ReadNoLock() +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* Do not lock against interrupts and multiple access. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { + unsigned NumBytesRem; + unsigned NumBytesRead; + unsigned RdOff; + unsigned WrOff; + unsigned char* pBuffer; + SEGGER_RTT_BUFFER_DOWN* pRing; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + const char* pSrc; +#endif + // + INIT(); + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + pBuffer = (unsigned char*)pData; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + NumBytesRead = 0u; + // + // Read from current read position to wrap-around of buffer, first + // + if (RdOff > WrOff) { + NumBytesRem = pRing->SizeOfBuffer - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pSrc = pRing->pBuffer + RdOff; + NumBytesRead += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + while (NumBytesRem--) { + *pBuffer++ = *pSrc++; + }; +#else + SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; +#endif + // + // Handle wrap-around of buffer + // + if (RdOff == pRing->SizeOfBuffer) { + RdOff = 0u; + } + } + // + // Read remaining items of buffer + // + NumBytesRem = WrOff - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + if (NumBytesRem > 0u) { +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pSrc = pRing->pBuffer + RdOff; + NumBytesRead += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + while (NumBytesRem--) { + *pBuffer++ = *pSrc++; + }; +#else + SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; +#endif + } + if (NumBytesRead) { + pRing->RdOff = RdOff; + } + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_ReadUpBuffer +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the application. +* Used to do the same operation that J-Link does, to transfer +* RTT data via other channels, such as TCP/IP or UART. +* +* Parameters +* BufferIndex Index of Up-buffer to be used. +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +* +* Additional information +* This function must not be called when J-Link might also do RTT. +* This function locks against all other RTT operations. I.e. during +* the read operation, writing is also locked. +* If only one consumer reads from the up buffer, +* call sEGGER_RTT_ReadUpBufferNoLock() instead. +*/ +unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { + unsigned NumBytesRead; + // + SEGGER_RTT_LOCK(); + // + // Call the non-locking read function + // + NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_Read +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { + unsigned NumBytesRead; + // + SEGGER_RTT_LOCK(); + // + // Call the non-locking read function + // + NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteWithOverwriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block. +* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application +* and overwrites data if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, data is overwritten. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link +* connection reads RTT data. +*/ +void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + char* pDst; +#endif + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Check if we will overwrite data and need to adjust the RdOff. + // + if (pRing->WrOff == pRing->RdOff) { + Avail = pRing->SizeOfBuffer - 1u; + } else if ( pRing->WrOff < pRing->RdOff) { + Avail = pRing->RdOff - pRing->WrOff - 1u; + } else { + Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; + } + if (NumBytes > Avail) { + pRing->RdOff += (NumBytes - Avail); + while (pRing->RdOff >= pRing->SizeOfBuffer) { + pRing->RdOff -= pRing->SizeOfBuffer; + } + } + // + // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds + // + Avail = pRing->SizeOfBuffer - pRing->WrOff; + do { + if (Avail > NumBytes) { + // + // Last round + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + pRing->WrOff; + Avail = NumBytes; + while (NumBytes--) { + *pDst++ = *pData++; + }; + pRing->WrOff += Avail; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes); + pRing->WrOff += NumBytes; +#endif + break; + } else { + // + // Wrap-around necessary, write until wrap-around and reset WrOff + // +#if SEGGER_RTT_MEMCPY_USE_BYTELOOP + pDst = pRing->pBuffer + pRing->WrOff; + NumBytes -= Avail; + while (Avail--) { + *pDst++ = *pData++; + }; + pRing->WrOff = 0; +#else + SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail); + pData += Avail; + pRing->WrOff = 0; + NumBytes -= Avail; +#endif + Avail = (pRing->SizeOfBuffer - 1); + } + } while (NumBytes); +} + +/********************************************************************* +* +* SEGGER_RTT_WriteSkipNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteSkipNoLock does not lock the application and +* skips all data, if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* MUST be > 0!!! +* This is done for performance reasons, so no initial check has do be done. +* +* Return value +* 1: Data has been copied +* 0: No space, data has not been copied +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, all data is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +#if (RTT_USE_ASM == 0) +unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + unsigned RdOff; + unsigned WrOff; + unsigned Rem; + // + // Cases: + // 1) RdOff <= WrOff => Space until wrap-around is sufficient + // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) + // 3) RdOff < WrOff => No space in buf + // 4) RdOff > WrOff => Space is sufficient + // 5) RdOff > WrOff => No space in buf + // + // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough + // + pData = (const char *)pBuffer; + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + if (RdOff <= WrOff) { // Case 1), 2) or 3) + Avail = pRing->SizeOfBuffer - WrOff - 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) + if (Avail >= NumBytes) { // Case 1)? +CopyStraight: + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + return 1; + } + Avail += RdOff; // Space incl. wrap-around + if (Avail >= NumBytes) { // Case 2? => If not, we have case 3) (does not fit) + Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer + memcpy(pRing->pBuffer + WrOff, pData, Rem); // Copy 1st chunk + NumBytes -= Rem; + // + // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used + // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element + // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks + // Therefore, check if 2nd memcpy is necessary at all + // + if (NumBytes) { + memcpy(pRing->pBuffer, pData + Rem, NumBytes); + } + pRing->WrOff = NumBytes; + return 1; + } + } else { // Potential case 4) + Avail = RdOff - WrOff - 1u; + if (Avail >= NumBytes) { // Case 4)? => If not, we have case 5) (does not fit) + goto CopyStraight; + } + } + return 0; // No space in buffer +} +#endif + +/********************************************************************* +* +* SEGGER_RTT_WriteDownBufferNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block inside a buffer. +* SEGGER_RTT_WriteDownBufferNoLock does not lock the application. +* Used to do the same operation that J-Link does, to transfer +* RTT data from other channels, such as TCP/IP or UART. +* +* Parameters +* BufferIndex Index of "Down"-buffer to be used. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Down"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +* +* Additional information +* This function must not be called when J-Link might also do RTT. +*/ +unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + unsigned Avail; + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + + pData = (const char *)pBuffer; + // + // Get "to-target" ring buffer. + // It is save to cast that to a "to-host" buffer. Up and Down buffer differ in volatility of offsets that might be modified by J-Link. + // + pRing = (SEGGER_RTT_BUFFER_UP*)&_SEGGER_RTT.aDown[BufferIndex]; + // + // How we output depends upon the mode... + // + switch (pRing->Flags) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother. + // + Avail = _GetAvailWriteSpace(pRing); + if (Avail < NumBytes) { + Status = 0u; + } else { + Status = NumBytes; + _WriteNoCheck(pRing, pData, NumBytes); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode, trim to what we can output without blocking. + // + Avail = _GetAvailWriteSpace(pRing); + Status = Avail < NumBytes ? Avail : NumBytes; + _WriteNoCheck(pRing, pData, Status); + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + Status = _WriteBlocking(pRing, pData, NumBytes); + break; + default: + Status = 0u; + break; + } + // + // Finish up. + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteNoLock does not lock the application. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + unsigned Avail; + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // How we output depends upon the mode... + // + switch (pRing->Flags) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother. + // + Avail = _GetAvailWriteSpace(pRing); + if (Avail < NumBytes) { + Status = 0u; + } else { + Status = NumBytes; + _WriteNoCheck(pRing, pData, NumBytes); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode, trim to what we can output without blocking. + // + Avail = _GetAvailWriteSpace(pRing); + Status = Avail < NumBytes ? Avail : NumBytes; + _WriteNoCheck(pRing, pData, Status); + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + Status = _WriteBlocking(pRing, pData, NumBytes); + break; + default: + Status = 0u; + break; + } + // + // Finish up. + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteDownBuffer +* +* Function description +* Stores a specified number of characters in SEGGER RTT control block in a buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Down"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +* +* Additional information +* This function must not be called when J-Link might also do RTT. +* This function locks against all other RTT operations. I.e. during +* the write operation, writing from the application is also locked. +* If only one consumer writes to the down buffer, +* call SEGGER_RTT_WriteDownBufferNoLock() instead. +*/ +unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Call the non-locking write function + // + Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_Write +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +*/ +unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Call the non-locking write function + // + Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteString +* +* Function description +* Stores string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* s Pointer to string. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +* (2) String passed to this function has to be \0 terminated +* (3) \0 termination character is *not* stored in RTT buffer +*/ +unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { + unsigned Len; + + Len = STRLEN(s); + return SEGGER_RTT_Write(BufferIndex, s, Len); +} + +/********************************************************************* +* +* SEGGER_RTT_PutCharSkipNoLock +* +* Function description +* Stores a single character/byte in SEGGER RTT buffer. +* SEGGER_RTT_PutCharSkipNoLock does not lock the application and +* skips the byte, if it does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* c Byte to be stored. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, the character is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ + +unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned WrOff; + unsigned Status; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Get write position and handle wrap-around if necessary + // + WrOff = pRing->WrOff + 1; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0; + } + // + // Output byte if free space is available + // + if (WrOff != pRing->RdOff) { + pRing->pBuffer[pRing->WrOff] = c; + pRing->WrOff = WrOff; + Status = 1; + } else { + Status = 0; + } + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_PutCharSkip +* +* Function description +* Stores a single character/byte in SEGGER RTT buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* c Byte to be stored. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, the character is dropped. +*/ + +unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned WrOff; + unsigned Status; + // + // Prepare + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Get write position and handle wrap-around if necessary + // + WrOff = pRing->WrOff + 1; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0; + } + // + // Output byte if free space is available + // + if (WrOff != pRing->RdOff) { + pRing->pBuffer[pRing->WrOff] = c; + pRing->WrOff = WrOff; + Status = 1; + } else { + Status = 0; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + + /********************************************************************* +* +* SEGGER_RTT_PutChar +* +* Function description +* Stores a single character/byte in SEGGER RTT buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* c Byte to be stored. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) Data is stored according to buffer flags. +*/ + +unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned WrOff; + unsigned Status; + // + // Prepare + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Get write position and handle wrap-around if necessary + // + WrOff = pRing->WrOff + 1; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0; + } + // + // Wait for free space if mode is set to blocking + // + if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + while (WrOff == pRing->RdOff) { + ; + } + } + // + // Output byte if free space is available + // + if (WrOff != pRing->RdOff) { + pRing->pBuffer[pRing->WrOff] = c; + pRing->WrOff = WrOff; + Status = 1; + } else { + Status = 0; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_GetKey +* +* Function description +* Reads one character from the SEGGER RTT buffer. +* Host has previously stored data there. +* +* Return value +* < 0 - No character available (buffer empty). +* >= 0 - Character which has been read. (Possible values: 0 - 255) +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0. +*/ +int SEGGER_RTT_GetKey(void) { + char c; + int r; + + r = (int)SEGGER_RTT_Read(0u, &c, 1u); + if (r == 1) { + r = (int)(unsigned char)c; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_WaitKey +* +* Function description +* Waits until at least one character is avaible in the SEGGER RTT buffer. +* Once a character is available, it is read and this function returns. +* +* Return value +* >=0 - Character which has been read. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +* (2) This function is blocking if no character is present in RTT buffer +*/ +int SEGGER_RTT_WaitKey(void) { + int r; + + do { + r = SEGGER_RTT_GetKey(); + } while (r < 0); + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasKey +* +* Function description +* Checks if at least one character for reading is available in the SEGGER RTT buffer. +* +* Return value +* == 0 - No characters are available to read. +* == 1 - At least one character is available. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +*/ +int SEGGER_RTT_HasKey(void) { + unsigned RdOff; + int r; + + INIT(); + RdOff = _SEGGER_RTT.aDown[0].RdOff; + if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { + r = 1; + } else { + r = 0; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasData +* +* Function description +* Check if there is data from the host in the given buffer. +* +* Return value: +* ==0: No data +* !=0: Data in buffer +* +*/ +unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { + SEGGER_RTT_BUFFER_DOWN* pRing; + unsigned v; + + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + v = pRing->WrOff; + return v - pRing->RdOff; +} + +/********************************************************************* +* +* SEGGER_RTT_HasDataUp +* +* Function description +* Check if there is data remaining to be sent in the given buffer. +* +* Return value: +* ==0: No data +* !=0: Data in buffer +* +*/ +unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) { + SEGGER_RTT_BUFFER_UP* pRing; + unsigned v; + + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + v = pRing->RdOff; + return pRing->WrOff - v; +} + +/********************************************************************* +* +* SEGGER_RTT_AllocDownBuffer +* +* Function description +* Run-time configuration of the next down-buffer (H->T). +* The next buffer, which is not used yet is configured. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. Buffer Index +* < 0 - Error +*/ +int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int BufferIndex; + + INIT(); + SEGGER_RTT_LOCK(); + BufferIndex = 0; + do { + if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { + break; + } + BufferIndex++; + } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); + if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + } else { + BufferIndex = -1; + } + SEGGER_RTT_UNLOCK(); + return BufferIndex; +} + +/********************************************************************* +* +* SEGGER_RTT_AllocUpBuffer +* +* Function description +* Run-time configuration of the next up-buffer (T->H). +* The next buffer, which is not used yet is configured. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. Buffer Index +* < 0 - Error +*/ +int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int BufferIndex; + + INIT(); + SEGGER_RTT_LOCK(); + BufferIndex = 0; + do { + if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { + break; + } + BufferIndex++; + } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); + if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + } else { + BufferIndex = -1; + } + SEGGER_RTT_UNLOCK(); + return BufferIndex; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer (T->H). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. +* < 0 - Error +* +* Additional information +* Buffer 0 is configured on compile-time. +* May only be called once per buffer. +* Buffer name and flags can be reconfigured using the appropriate functions. +*/ +int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + if (BufferIndex > 0u) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigDownBuffer +* +* Function description +* Run-time configuration of a specific down-buffer (H->T). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 O.K. +* < 0 Error +* +* Additional information +* Buffer 0 is configured on compile-time. +* May only be called once per buffer. +* Buffer name and flags can be reconfigured using the appropriate functions. +*/ +int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + if (BufferIndex > 0u) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameDownBuffer +* +* Function description +* Run-time configuration of a specific Down-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetFlagsUpBuffer +* +* Function description +* Run-time configuration of specific up-buffer flags (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer. +* Flags Flags to set for the buffer. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetFlagsDownBuffer +* +* Function description +* Run-time configuration of specific Down-buffer flags (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* Flags Flags to set for the buffer. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_Init +* +* Function description +* Initializes the RTT Control Block. +* Should be used in RAM targets, at start of the application. +* +*/ +void SEGGER_RTT_Init (void) { + _DoInit(); +} + +/********************************************************************* +* +* SEGGER_RTT_SetTerminal +* +* Function description +* Sets the terminal to be used for output on channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* +* Return value +* >= 0 O.K. +* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) +*/ +int SEGGER_RTT_SetTerminal (unsigned char TerminalId) { + unsigned char ac[2]; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + int r; + // + INIT(); + // + r = 0; + ac[0] = 0xFFu; + if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels + ac[1] = _aTerminalId[TerminalId]; + pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed + SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing + if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + _ActiveTerminal = TerminalId; + _WriteBlocking(pRing, (const char*)ac, 2u); + } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes + Avail = _GetAvailWriteSpace(pRing); + if (Avail >= 2) { + _ActiveTerminal = TerminalId; // Only change active terminal in case of success + _WriteNoCheck(pRing, (const char*)ac, 2u); + } else { + r = -1; + } + } + SEGGER_RTT_UNLOCK(); + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_TerminalOut +* +* Function description +* Writes a string to the given terminal +* without changing the terminal for channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* s String to be printed on the terminal. +* +* Return value +* >= 0 - Number of bytes written. +* < 0 - Error. +* +*/ +int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) { + int Status; + unsigned FragLen; + unsigned Avail; + SEGGER_RTT_BUFFER_UP* pRing; + // + INIT(); + // + // Validate terminal ID. + // + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[0]; + // + // Need to be able to change terminal, write data, change back. + // Compute the fixed and variable sizes. + // + FragLen = STRLEN(s); + // + // How we output depends upon the mode... + // + SEGGER_RTT_LOCK(); + Avail = _GetAvailWriteSpace(pRing); + switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother switching terminals at all. + // + if (Avail < (FragLen + 4u)) { + Status = 0; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode and there is not enough space for everything, + // trim the output but always include the terminal switch. If no room + // for terminal switch, skip that totally. + // + if (Avail < 4u) { + Status = -1; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + break; + default: + Status = -1; + break; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + } else { + Status = -1; + } + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_GetAvailWriteSpace +* +* Function description +* Returns the number of bytes available in the ring buffer. +* +* Parameters +* BufferIndex Index of the up buffer. +* +* Return value +* Number of bytes that are free in the selected up buffer. +*/ +unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex){ + return _GetAvailWriteSpace(&_SEGGER_RTT.aUp[BufferIndex]); +} + + +/********************************************************************* +* +* SEGGER_RTT_GetBytesInBuffer() +* +* Function description +* Returns the number of bytes currently used in the up buffer. +* +* Parameters +* BufferIndex Index of the up buffer. +* +* Return value +* Number of bytes that are used in the buffer. +*/ +unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex) { + unsigned RdOff; + unsigned WrOff; + unsigned r; + // + // Avoid warnings regarding volatile access order. It's not a problem + // in this case, but dampen compiler enthusiasm. + // + RdOff = _SEGGER_RTT.aUp[BufferIndex].RdOff; + WrOff = _SEGGER_RTT.aUp[BufferIndex].WrOff; + if (RdOff <= WrOff) { + r = WrOff - RdOff; + } else { + r = _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff); + } + return r; +} + +/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h new file mode 100644 index 000000000..3c04df55f --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h @@ -0,0 +1,321 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2019 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* condition is met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this condition and the following disclaimer. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.h +Purpose : Implementation of SEGGER real-time transfer which allows + real-time communication on targets which support debugger + memory accesses while the CPU is running. +Revision: $Rev: 17697 $ +---------------------------------------------------------------------- +*/ + +#ifndef SEGGER_RTT_H +#define SEGGER_RTT_H + +#include "SEGGER_RTT_Conf.h" + + + +/********************************************************************* +* +* Defines, defaults +* +********************************************************************** +*/ +#ifndef RTT_USE_ASM + #if (defined __SES_ARM) // SEGGER Embedded Studio + #define _CC_HAS_RTT_ASM_SUPPORT 1 + #elif (defined __CROSSWORKS_ARM) // Rowley Crossworks + #define _CC_HAS_RTT_ASM_SUPPORT 1 + #elif (defined __GNUC__) // GCC + #define _CC_HAS_RTT_ASM_SUPPORT 1 + #elif (defined __clang__) // Clang compiler + #define _CC_HAS_RTT_ASM_SUPPORT 1 + #elif (defined __IASMARM__) // IAR assembler + #define _CC_HAS_RTT_ASM_SUPPORT 1 + #elif (defined __ICCARM__) // IAR compiler + #define _CC_HAS_RTT_ASM_SUPPORT 1 + #else + #define _CC_HAS_RTT_ASM_SUPPORT 0 + #endif + #if (defined __ARM_ARCH_7M__) // Cortex-M3/4 + #define _CORE_HAS_RTT_ASM_SUPPORT 1 + #elif (defined __ARM_ARCH_7EM__) // Cortex-M7 + #define _CORE_HAS_RTT_ASM_SUPPORT 1 + #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 + #define _CORE_HAS_RTT_ASM_SUPPORT 1 + #elif (defined __ARM7M__) // IAR Cortex-M3/4 + #if (__CORE__ == __ARM7M__) + #define _CORE_HAS_RTT_ASM_SUPPORT 1 + #else + #define _CORE_HAS_RTT_ASM_SUPPORT 0 + #endif + #elif (defined __ARM7EM__) // IAR Cortex-M7 + #if (__CORE__ == __ARM7EM__) + #define _CORE_HAS_RTT_ASM_SUPPORT 1 + #else + #define _CORE_HAS_RTT_ASM_SUPPORT 0 + #endif + #else + #define _CORE_HAS_RTT_ASM_SUPPORT 0 + #endif + // + // If IDE and core support the ASM version, enable ASM version by default + // + #if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT) + #define RTT_USE_ASM (1) + #else + #define RTT_USE_ASM (0) + #endif +#endif + +#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file +#include +#include + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as up-buffer (T->H) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + unsigned WrOff; // Position of next item to be written by either target. + volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_BUFFER_UP; + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as down-buffer (H->T) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. + unsigned RdOff; // Position of next item to be read by target (down-buffer). + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_BUFFER_DOWN; + +// +// RTT control block which describes the number of buffers available +// as well as the configuration for each buffer +// +// +typedef struct { + char acID[16]; // Initialized to "SEGGER RTT" + int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) + int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) + SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host + SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target +} SEGGER_RTT_CB; + +/********************************************************************* +* +* Global data +* +********************************************************************** +*/ +extern SEGGER_RTT_CB _SEGGER_RTT; + +/********************************************************************* +* +* RTT API functions +* +********************************************************************** +*/ +#ifdef __cplusplus + extern "C" { +#endif +int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_GetKey (void); +unsigned SEGGER_RTT_HasData (unsigned BufferIndex); +int SEGGER_RTT_HasKey (void); +unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex); +void SEGGER_RTT_Init (void); +unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); +unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); +int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); +int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); +int SEGGER_RTT_WaitKey (void); +unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); +void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); +unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); +unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); +unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); +unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); +// +// Function macro for performance optimization +// +#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) + +#if RTT_USE_ASM + #define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock +#endif + +/********************************************************************* +* +* RTT transfer functions to send RTT data via other channels. +* +********************************************************************** +*/ +unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); +unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); +unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); + +#define SEGGER_RTT_HASDATA_UP(n) (_SEGGER_RTT.aUp[n].WrOff - _SEGGER_RTT.aUp[n].RdOff) + +/********************************************************************* +* +* RTT "Terminal" API functions +* +********************************************************************** +*/ +int SEGGER_RTT_SetTerminal (unsigned char TerminalId); +int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s); + +/********************************************************************* +* +* RTT printf functions (require SEGGER_RTT_printf.c) +* +********************************************************************** +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +#ifdef __cplusplus + } +#endif + +#endif // ifndef(SEGGER_RTT_ASM) + +/********************************************************************* +* +* Defines +* +********************************************************************** +*/ + +// +// Operating modes. Define behavior if buffer is full (not enough space for entire message) +// +#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default) +#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits. +#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer. +#define SEGGER_RTT_MODE_MASK (3) + +// +// Control sequences, based on ANSI. +// Can be used to control color, and clear the screen +// +#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors +#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left + +#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" +#define RTT_CTRL_TEXT_RED "\x1B[2;31m" +#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" +#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" +#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" +#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" +#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" +#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" + +#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" +#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" +#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" +#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" +#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" +#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" +#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" +#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" + +#define RTT_CTRL_BG_BLACK "\x1B[24;40m" +#define RTT_CTRL_BG_RED "\x1B[24;41m" +#define RTT_CTRL_BG_GREEN "\x1B[24;42m" +#define RTT_CTRL_BG_YELLOW "\x1B[24;43m" +#define RTT_CTRL_BG_BLUE "\x1B[24;44m" +#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" +#define RTT_CTRL_BG_CYAN "\x1B[24;46m" +#define RTT_CTRL_BG_WHITE "\x1B[24;47m" + +#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" +#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" +#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" +#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" +#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" +#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" +#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" +#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" + + +#endif + +/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S new file mode 100644 index 000000000..78cde4d75 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S @@ -0,0 +1,235 @@ +/********************************************************************* +* (c) SEGGER Microcontroller GmbH * +* The Embedded Experts * +* www.segger.com * +********************************************************************** + +-------------------------- END-OF-HEADER ----------------------------- + +File : SEGGER_RTT_ASM_ARMv7M.S +Purpose : Assembler implementation of RTT functions for ARMv7M + +Additional information: + This module is written to be assembler-independent and works with + GCC and clang (Embedded Studio) and IAR. +*/ + +#define SEGGER_RTT_ASM // Used to control processed input from header file +#include "SEGGER_RTT.h" + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ +#define _CCIAR 0 +#define _CCCLANG 1 + +#if (defined __SES_ARM) || (defined __GNUC__) || (defined __clang__) + #define _CC_TYPE _CCCLANG + #define _PUB_SYM .global + #define _EXT_SYM .extern + #define _END .end + #define _WEAK .weak + #define _THUMB_FUNC .thumb_func + #define _THUMB_CODE .code 16 + #define _WORD .word + #define _SECTION(Sect, Type, AlignExp) .section Sect ##, "ax" + #define _ALIGN(Exp) .align Exp + #define _PLACE_LITS .ltorg + #define _DATA_SECT_START + #define _C_STARTUP _start + #define _STACK_END __stack_end__ + #define _RAMFUNC + // + // .text => Link to flash + // .fast => Link to RAM + // OtherSect => Usually link to RAM + // Alignment is 2^x + // +#elif defined (__IASMARM__) + #define _CC_TYPE _CCIAR + #define _PUB_SYM PUBLIC + #define _EXT_SYM EXTERN + #define _END END + #define _WEAK _WEAK + #define _THUMB_FUNC + #define _THUMB_CODE THUMB + #define _WORD DCD + #define _SECTION(Sect, Type, AlignExp) SECTION Sect ## : ## Type ## :REORDER:NOROOT ## (AlignExp) + #define _ALIGN(Exp) alignrom Exp + #define _PLACE_LITS + #define _DATA_SECT_START DATA + #define _C_STARTUP __iar_program_start + #define _STACK_END sfe(CSTACK) + #define _RAMFUNC SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR + // + // .text => Link to flash + // .textrw => Link to RAM + // OtherSect => Usually link to RAM + // NOROOT => Allows linker to throw away the function, if not referenced + // Alignment is 2^x + // +#endif + +#if (_CC_TYPE == _CCIAR) + NAME SEGGER_RTT_ASM_ARMv7M +#else + .syntax unified +#endif + +#if defined (RTT_USE_ASM) && (RTT_USE_ASM == 1) + #define SHT_PROGBITS 0x1 + +/********************************************************************* +* +* Public / external symbols +* +********************************************************************** +*/ + + _EXT_SYM __aeabi_memcpy + _EXT_SYM __aeabi_memcpy4 + _EXT_SYM _SEGGER_RTT + + _PUB_SYM SEGGER_RTT_ASM_WriteSkipNoLock + +/********************************************************************* +* +* SEGGER_RTT_WriteSkipNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteSkipNoLock does not lock the application and +* skips all data, if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* MUST be > 0!!! +* This is done for performance reasons, so no initial check has do be done. +* +* Return value +* 1: Data has been copied +* 0: No space, data has not been copied +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, all data is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ + _SECTION(.text, CODE, 2) + _ALIGN(2) + _THUMB_FUNC +SEGGER_RTT_ASM_WriteSkipNoLock: // unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pData, unsigned NumBytes) { + // + // Cases: + // 1) RdOff <= WrOff => Space until wrap-around is sufficient + // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) + // 3) RdOff < WrOff => No space in buf + // 4) RdOff > WrOff => Space is sufficient + // 5) RdOff > WrOff => No space in buf + // + // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough + // + // Register usage: + // R0 Temporary needed as RdOff, register later on + // R1 pData + // R2 + // R3 register. Hold free for subroutine calls + // R4 + // R5 pRing->pBuffer + // R6 pRing (Points to active struct SEGGER_RTT_BUFFER_DOWN) + // R7 WrOff + // + PUSH {R4-R7} + ADD R3,R0,R0, LSL #+1 + LDR.W R0,=_SEGGER_RTT // pRing = &_SEGGER_RTT.aUp[BufferIndex]; + ADD R0,R0,R3, LSL #+3 + ADD R6,R0,#+24 + LDR R0,[R6, #+16] // RdOff = pRing->RdOff; + LDR R7,[R6, #+12] // WrOff = pRing->WrOff; + LDR R5,[R6, #+4] // pRing->pBuffer + CMP R7,R0 + BCC.N _CheckCase4 // if (RdOff <= WrOff) { => Case 1), 2) or 3) + // + // Handling for case 1, later on identical to case 4 + // + LDR R3,[R6, #+8] // Avail = pRing->SizeOfBuffer - WrOff - 1u; => Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) + SUBS R4,R3,R7 // (Used in case we jump into case 2 afterwards) + SUBS R3,R4,#+1 // + CMP R3,R2 + BCC.N _CheckCase2 // if (Avail >= NumBytes) { => Case 1)? +_Case4: + ADDS R5,R7,R5 // pBuffer += WrOff + ADDS R0,R2,R7 // v = WrOff + NumBytes + // + // 2x unrolling for the copy loop that is used most of the time + // This is a special optimization for small SystemView packets and makes them even faster + // + _ALIGN(2) +_LoopCopyStraight: // memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + LDRB R3,[R1], #+1 + STRB R3,[R5], #+1 // *pDest++ = *pSrc++ + SUBS R2,R2,#+1 + BEQ _CSDone + LDRB R3,[R1], #+1 + STRB R3,[R5], #+1 // *pDest++ = *pSrc++ + SUBS R2,R2,#+1 + BNE _LoopCopyStraight +_CSDone: + STR R0,[R6, #+12] // pRing->WrOff = WrOff + NumBytes; + MOVS R0,#+1 + POP {R4-R7} + BX LR // Return 1 +_CheckCase2: + ADDS R0,R0,R3 // Avail += RdOff; => Space incl. wrap-around + CMP R0,R2 + BCC.N _Case3 // if (Avail >= NumBytes) { => Case 2? => If not, we have case 3) (does not fit) + // + // Handling for case 2 + // + ADDS R0,R7,R5 // v = pRing->pBuffer + WrOff => Do not change pRing->pBuffer here because 2nd chunk needs org. value + SUBS R2,R2,R4 // NumBytes -= Rem; (Rem = pRing->SizeOfBuffer - WrOff; => Space until end of buffer) +_LoopCopyBeforeWrapAround: // memcpy(pRing->pBuffer + WrOff, pData, Rem); => Copy 1st chunk + LDRB R3,[R1], #+1 + STRB R3,[R0], #+1 // *pDest++ = *pSrc++ + SUBS R4,R4,#+1 + BNE _LoopCopyBeforeWrapAround + // + // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used + // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element + // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks + // Therefore, check if 2nd memcpy is necessary at all + // + ADDS R4,R2,#+0 // Save (needed as counter in loop but must be written to after the loop). Also use this inst to update the flags to skip 2nd loop if possible + BEQ.N _No2ChunkNeeded // if (NumBytes) { +_LoopCopyAfterWrapAround: // memcpy(pRing->pBuffer, pData + Rem, NumBytes); + LDRB R3,[R1], #+1 // pData already points to the next src byte due to copy loop increment before this loop + STRB R3,[R5], #+1 // *pDest++ = *pSrc++ + SUBS R2,R2,#+1 + BNE _LoopCopyAfterWrapAround +_No2ChunkNeeded: + STR R4,[R6, #+12] // pRing->WrOff = NumBytes; => Must be written after copying data because J-Link may read control block asynchronously while writing into buffer + MOVS R0,#+1 + POP {R4-R7} + BX LR // Return 1 +_CheckCase4: + SUBS R0,R0,R7 + SUBS R0,R0,#+1 // Avail = RdOff - WrOff - 1u; + CMP R0,R2 + BCS.N _Case4 // if (Avail >= NumBytes) { => Case 4) == 1) ? => If not, we have case 5) == 3) (does not fit) +_Case3: + MOVS R0,#+0 + POP {R4-R7} + BX LR // Return 0 + _PLACE_LITS + +#endif // defined (RTT_USE_ASM) && (RTT_USE_ASM == 1) + _END + +/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h new file mode 100644 index 000000000..5e79d7e67 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h @@ -0,0 +1,384 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2019 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* condition is met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this condition and the following disclaimer. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Conf.h +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +Revision: $Rev: 18601 $ + +*/ + +#ifndef SEGGER_RTT_CONF_H +#define SEGGER_RTT_CONF_H + +#ifdef __IAR_SYSTEMS_ICC__ + #include +#endif + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ +#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS + #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3) +#endif + +#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS + #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3) +#endif + +#ifndef BUFFER_SIZE_UP + #define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) +#endif + +#ifndef BUFFER_SIZE_DOWN + #define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) +#endif + +#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE + #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) +#endif + +#ifndef SEGGER_RTT_MODE_DEFAULT + #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) +#endif + +/********************************************************************* +* +* RTT memcpy configuration +* +* memcpy() is good for large amounts of data, +* but the overhead is big for small amounts, which are usually stored via RTT. +* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead. +* +* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions. +* This is may be required with memory access restrictions, +* such as on Cortex-A devices with MMU. +*/ +#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP + #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop +#endif +// +// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets +// +//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__)) +// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes)) +//#endif + +// +// Target is not allowed to perform other RTT operations while string still has not been stored completely. +// Otherwise we would probably end up with a mixed string in the buffer. +// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. +// +// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. +// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. +// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. +// (Higher priority = lower priority number) +// Default value for embOS: 128u +// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC +// or define SEGGER_RTT_LOCK() to completely disable interrupts. +// +#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) +#endif + +/********************************************************************* +* +* RTT lock configuration for SEGGER Embedded Studio, +* Rowley CrossStudio and GCC +*/ +#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32)) + #if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__)) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs %0, primask \n\t" \ + "movs r1, $1 \n\t" \ + "msr primask, r1 \n\t" \ + : "=r" (LockState) \ + : \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ + : \ + : "r" (LockState) \ + : \ + ); \ + } + #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs %0, basepri \n\t" \ + "mov r1, %1 \n\t" \ + "msr basepri, r1 \n\t" \ + : "=r" (LockState) \ + : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ + : \ + : "r" (LockState) \ + : \ + ); \ + } + + #elif defined(__ARM_ARCH_7A__) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs r1, CPSR \n\t" \ + "mov %0, r1 \n\t" \ + "orr r1, r1, #0xC0 \n\t" \ + "msr CPSR_c, r1 \n\t" \ + : "=r" (LockState) \ + : \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ + "mrs r1, CPSR \n\t" \ + "bic r1, r1, #0xC0 \n\t" \ + "and r0, r0, #0xC0 \n\t" \ + "orr r1, r1, r0 \n\t" \ + "msr CPSR_c, r1 \n\t" \ + : \ + : "r" (LockState) \ + : "r0", "r1" \ + ); \ + } + #elif defined(__riscv) || defined(__riscv_xlen) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("csrr %0, mstatus \n\t" \ + "csrci mstatus, 8 \n\t" \ + "andi %0, %0, 8 \n\t" \ + : "=r" (LockState) \ + : \ + : \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \ + "or %0, %0, a1 \n\t" \ + "csrs mstatus, %0 \n\t" \ + : \ + : "r" (LockState) \ + : "a1" \ + ); \ + } + #else + #define SEGGER_RTT_LOCK() + #define SEGGER_RTT_UNLOCK() + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR EWARM +*/ +#ifdef __ICCARM__ + #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \ + (defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__)) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_PRIMASK(); \ + __set_PRIMASK(1); + + #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ + } + #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \ + (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \ + (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \ + (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_BASEPRI(); \ + __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); + + #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR RX +*/ +#ifdef __ICCRX__ + #define SEGGER_RTT_LOCK() { \ + unsigned long LockState; \ + LockState = __get_interrupt_state(); \ + __disable_interrupt(); + + #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ + } +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR RL78 +*/ +#ifdef __ICCRL78__ + #define SEGGER_RTT_LOCK() { \ + __istate_t LockState; \ + LockState = __get_interrupt_state(); \ + __disable_interrupt(); + + #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ + } +#endif + +/********************************************************************* +* +* RTT lock configuration for KEIL ARM +*/ +#ifdef __CC_ARM + #if (defined __TARGET_ARCH_6S_M) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + register unsigned char PRIMASK __asm( "primask"); \ + LockState = PRIMASK; \ + PRIMASK = 1u; \ + __schedule_barrier(); + + #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ + __schedule_barrier(); \ + } + #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + register unsigned char BASEPRI __asm( "basepri"); \ + LockState = BASEPRI; \ + BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ + __schedule_barrier(); + + #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ + __schedule_barrier(); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for TI ARM +*/ +#ifdef __TI_ARM__ + #if defined (__TI_ARM_V6M0__) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_PRIMASK(); \ + __set_PRIMASK(1); + + #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ + } + #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); + + #define SEGGER_RTT_UNLOCK() _set_interrupt_priority(LockState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for CCRX +*/ +#ifdef __RX + #define SEGGER_RTT_LOCK() { \ + unsigned long LockState; \ + LockState = get_psw() & 0x010000; \ + clrpsw_i(); + + #define SEGGER_RTT_UNLOCK() set_psw(get_psw() | LockState); \ + } +#endif + +/********************************************************************* +* +* RTT lock configuration for embOS Simulation on Windows +* (Can also be used for generic RTT locking with embOS) +*/ +#if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS) + +void OS_SIM_EnterCriticalSection(void); +void OS_SIM_LeaveCriticalSection(void); + +#define SEGGER_RTT_LOCK() { \ + OS_SIM_EnterCriticalSection(); + +#define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \ + } +#endif + +/********************************************************************* +* +* RTT lock configuration fallback +*/ +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) +#endif + +#endif +/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c new file mode 100644 index 000000000..4c996b408 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c @@ -0,0 +1,500 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2019 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* condition is met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this condition and the following disclaimer. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_printf.c +Purpose : Replacement for printf to write formatted data via RTT +Revision: $Rev: 17697 $ +---------------------------------------------------------------------- +*/ +#include "SEGGER_RTT.h" +#include "SEGGER_RTT_Conf.h" + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE + #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) +#endif + +#include +#include + + +#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) +#define FORMAT_FLAG_PAD_ZERO (1u << 1) +#define FORMAT_FLAG_PRINT_SIGN (1u << 2) +#define FORMAT_FLAG_ALTERNATE (1u << 3) + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +typedef struct { + char* pBuffer; + unsigned BufferSize; + unsigned Cnt; + + int ReturnValue; + + unsigned RTTBufferIndex; +} SEGGER_RTT_PRINTF_DESC; + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ + +/********************************************************************* +* +* Static code +* +********************************************************************** +*/ +/********************************************************************* +* +* _StoreChar +*/ +static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { + unsigned Cnt; + + Cnt = p->Cnt; + if ((Cnt + 1u) <= p->BufferSize) { + *(p->pBuffer + Cnt) = c; + p->Cnt = Cnt + 1u; + p->ReturnValue++; + } + // + // Write part of string, when the buffer is full + // + if (p->Cnt == p->BufferSize) { + if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { + p->ReturnValue = -1; + } else { + p->Cnt = 0u; + } + } +} + +/********************************************************************* +* +* _PrintUnsigned +*/ +static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + unsigned Div; + unsigned Digit; + unsigned Number; + unsigned Width; + char c; + + Number = v; + Digit = 1u; + // + // Get actual field width + // + Width = 1u; + while (Number >= Base) { + Number = (Number / Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + // + // Print leading chars if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { + if (FieldWidth != 0u) { + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { + c = '0'; + } else { + c = ' '; + } + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, c); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Compute Digit. + // Loop until Digit has the value of the highest digit required. + // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. + // + while (1) { + if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) + NumDigits--; + } else { + Div = v / Digit; + if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done + break; + } + } + Digit *= Base; + } + // + // Output digits + // + do { + Div = v / Digit; + v -= Div * Digit; + _StoreChar(pBufferDesc, _aV2C[Div]); + if (pBufferDesc->ReturnValue < 0) { + break; + } + Digit /= Base; + } while (Digit); + // + // Print trailing spaces if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + } +} + +/********************************************************************* +* +* _PrintInt +*/ +static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + unsigned Width; + int Number; + + Number = (v < 0) ? -v : v; + + // + // Get actual field width + // + Width = 1u; + while (Number >= (int)Base) { + Number = (Number / (int)Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { + FieldWidth--; + } + + // + // Print leading spaces if necessary + // + if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + // + // Print sign if necessary + // + if (pBufferDesc->ReturnValue >= 0) { + if (v < 0) { + v = -v; + _StoreChar(pBufferDesc, '-'); + } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { + _StoreChar(pBufferDesc, '+'); + } else { + + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print leading zeros if necessary + // + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, '0'); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print number without sign + // + _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); + } + } + } +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_vprintf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string +* pParamList Pointer to the list of arguments for the format string +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { + char c; + SEGGER_RTT_PRINTF_DESC BufferDesc; + int v; + unsigned NumDigits; + unsigned FormatFlags; + unsigned FieldWidth; + char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; + + BufferDesc.pBuffer = acBuffer; + BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; + BufferDesc.Cnt = 0u; + BufferDesc.RTTBufferIndex = BufferIndex; + BufferDesc.ReturnValue = 0; + + do { + c = *sFormat; + sFormat++; + if (c == 0u) { + break; + } + if (c == '%') { + // + // Filter out flags + // + FormatFlags = 0u; + v = 1; + do { + c = *sFormat; + switch (c) { + case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; + case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; + case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; + case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; + default: v = 0; break; + } + } while (v); + // + // filter out field with + // + FieldWidth = 0u; + do { + c = *sFormat; + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); + } while (1); + + // + // Filter out precision (number of digits to display) + // + NumDigits = 0u; + c = *sFormat; + if (c == '.') { + sFormat++; + do { + c = *sFormat; + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + NumDigits = NumDigits * 10u + ((unsigned)c - '0'); + } while (1); + } + // + // Filter out length modifier + // + c = *sFormat; + do { + if ((c == 'l') || (c == 'h')) { + sFormat++; + c = *sFormat; + } else { + break; + } + } while (1); + // + // Handle specifiers + // + switch (c) { + case 'c': { + char c0; + v = va_arg(*pParamList, int); + c0 = (char)v; + _StoreChar(&BufferDesc, c0); + break; + } + case 'd': + v = va_arg(*pParamList, int); + _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'u': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'x': + case 'X': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); + break; + case 's': + { + const char * s = va_arg(*pParamList, const char *); + do { + c = *s; + s++; + if (c == '\0') { + break; + } + _StoreChar(&BufferDesc, c); + } while (BufferDesc.ReturnValue >= 0); + } + break; + case 'p': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); + break; + case '%': + _StoreChar(&BufferDesc, '%'); + break; + default: + break; + } + sFormat++; + } else { + _StoreChar(&BufferDesc, c); + } + } while (BufferDesc.ReturnValue >= 0); + + if (BufferDesc.ReturnValue > 0) { + // + // Write remaining data, if any + // + if (BufferDesc.Cnt != 0u) { + SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); + } + BufferDesc.ReturnValue += (int)BufferDesc.Cnt; + } + return BufferDesc.ReturnValue; +} + +/********************************************************************* +* +* SEGGER_RTT_printf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string, followed by the arguments for conversion +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +* +* Notes +* (1) Conversion specifications have following syntax: +* %[flags][FieldWidth][.Precision]ConversionSpecifier +* (2) Supported flags: +* -: Left justify within the field width +* +: Always print sign extension for signed conversions +* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision +* Supported conversion specifiers: +* c: Print the argument as one char +* d: Print the argument as a signed integer +* u: Print the argument as an unsigned integer +* x: Print the argument as an hexadecimal integer +* s: Print the string pointed to by the argument +* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { + int r; + va_list ParamList; + + va_start(ParamList, sFormat); + r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); + va_end(ParamList); + return r; +} +/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c new file mode 100644 index 000000000..da4a4b5f5 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c @@ -0,0 +1,120 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2019 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* condition is met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this condition and the following disclaimer. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Syscalls_GCC.c +Purpose : Low-level functions for using printf() via RTT in GCC. + To use RTT for printf output, include this file in your + application. +Revision: $Rev: 17697 $ +---------------------------------------------------------------------- +*/ +#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) + +#include // required for _write_r +#include "SEGGER_RTT.h" + + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ +// +// If necessary define the _reent struct +// to match the one passed by the used standard library. +// +struct _reent; + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +int _write(int file, char *ptr, int len); +int _write_r(struct _reent *r, int file, const void *ptr, int len); + +/********************************************************************* +* +* Global functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _write() +* +* Function description +* Low-level write function. +* libc subroutines will use this system routine for output to all files, +* including stdout. +* Write data via RTT. +*/ +int _write(int file, char *ptr, int len) { + (void) file; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, ptr, len); + return len; +} + +/********************************************************************* +* +* _write_r() +* +* Function description +* Low-level reentrant write function. +* libc subroutines will use this system routine for output to all files, +* including stdout. +* Write data via RTT. +*/ +int _write_r(struct _reent *r, int file, const void *ptr, int len) { + (void) file; /* Not used, avoid warning */ + (void) r; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, ptr, len); + return len; +} + +#endif +/****** End Of File *************************************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c new file mode 100644 index 000000000..4c76752b3 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c @@ -0,0 +1,115 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2019 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* condition is met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this condition and the following disclaimer. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Syscalls_IAR.c +Purpose : Low-level functions for using printf() via RTT in IAR. + To use RTT for printf output, include this file in your + application and set the Library Configuration to Normal. +Revision: $Rev: 17697 $ +---------------------------------------------------------------------- +*/ +#ifdef __IAR_SYSTEMS_ICC__ + +// +// Since IAR EWARM V8 and EWRX V4, yfuns.h is considered as deprecated and LowLevelIOInterface.h +// shall be used instead. To not break any compatibility with older compiler versions, we have a +// version check in here. +// +#if ((defined __ICCARM__) && (__VER__ >= 8000000)) || ((defined __ICCRX__) && (__VER__ >= 400)) + #include +#else + #include +#endif + +#include "SEGGER_RTT.h" +#pragma module_name = "?__write" + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +size_t __write(int handle, const unsigned char * buffer, size_t size); + +/********************************************************************* +* +* Global functions +* +********************************************************************** +*/ +/********************************************************************* +* +* __write() +* +* Function description +* Low-level write function. +* Standard library subroutines will use this system routine +* for output to all files, including stdout. +* Write data via RTT. +*/ +size_t __write(int handle, const unsigned char * buffer, size_t size) { + (void) handle; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, (const char*)buffer, size); + return size; +} + +/********************************************************************* +* +* __write_buffered() +* +* Function description +* Low-level write function. +* Standard library subroutines will use this system routine +* for output to all files, including stdout. +* Write data via RTT. +*/ +size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) { + (void) handle; /* Not used, avoid warning */ + SEGGER_RTT_Write(0, (const char*)buffer, size); + return size; +} + +#endif +/****** End Of File *************************************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c new file mode 100644 index 000000000..f7f5aed48 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c @@ -0,0 +1,386 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2019 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* condition is met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this condition and the following disclaimer. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : RTT_Syscalls_KEIL.c +Purpose : Retargeting module for KEIL MDK-CM3. + Low-level functions for using printf() via RTT +Revision: $Rev: 17697 $ +---------------------------------------------------------------------- +*/ +#ifdef __CC_ARM + +#include +#include +#include +#include +#include + +#include "SEGGER_RTT.h" +/********************************************************************* +* +* #pragmas +* +********************************************************************** +*/ +#pragma import(__use_no_semihosting) + +#ifdef _MICROLIB + #pragma import(__use_full_stdio) +#endif + +/********************************************************************* +* +* Defines non-configurable +* +********************************************************************** +*/ + +/* Standard IO device handles - arbitrary, but any real file system handles must be + less than 0x8000. */ +#define STDIN 0x8001 // Standard Input Stream +#define STDOUT 0x8002 // Standard Output Stream +#define STDERR 0x8003 // Standard Error Stream + +/********************************************************************* +* +* Public const +* +********************************************************************** +*/ +#if __ARMCC_VERSION < 5000000 +//const char __stdin_name[] = "STDIN"; +const char __stdout_name[] = "STDOUT"; +const char __stderr_name[] = "STDERR"; +#endif + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ + +/********************************************************************* +* +* _ttywrch +* +* Function description: +* Outputs a character to the console +* +* Parameters: +* c - character to output +* +*/ +void _ttywrch(int c) { + fputc(c, stdout); // stdout + fflush(stdout); +} + +/********************************************************************* +* +* _sys_open +* +* Function description: +* Opens the device/file in order to do read/write operations +* +* Parameters: +* sName - sName of the device/file to open +* OpenMode - This parameter is currently ignored +* +* Return value: +* != 0 - Handle to the object to open, otherwise +* == 0 -"device" is not handled by this module +* +*/ +FILEHANDLE _sys_open(const char * sName, int OpenMode) { + (void)OpenMode; + // Register standard Input Output devices. + if (strcmp(sName, __stdout_name) == 0) { + return (STDOUT); + } else if (strcmp(sName, __stderr_name) == 0) { + return (STDERR); + } else + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_close +* +* Function description: +* Closes the handle to the open device/file +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* 0 - device/file closed +* +*/ +int _sys_close(FILEHANDLE hFile) { + (void)hFile; + return 0; // Not implemented +} + +/********************************************************************* +* +* _sys_write +* +* Function description: +* Writes the data to an open handle. +* Currently this function only outputs data to the console +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* pBuffer - Pointer to the data that shall be written +* NumBytes - Number of bytes to write +* Mode - The Mode that shall be used +* +* Return value: +* Number of bytes *not* written to the file/device +* +*/ +int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) { + int r = 0; + + (void)Mode; + if (hFile == STDOUT) { + SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes); + return 0; + } + return r; +} + +/********************************************************************* +* +* _sys_read +* +* Function description: +* Reads data from an open handle. +* Currently this modules does nothing. +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* pBuffer - Pointer to buffer to store the read data +* NumBytes - Number of bytes to read +* Mode - The Mode that shall be used +* +* Return value: +* Number of bytes read from the file/device +* +*/ +int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) { + (void)hFile; + (void)pBuffer; + (void)NumBytes; + (void)Mode; + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_istty +* +* Function description: +* This function shall return whether the opened file +* is a console device or not. +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* 1 - Device is a console +* 0 - Device is not a console +* +*/ +int _sys_istty(FILEHANDLE hFile) { + if (hFile > 0x8000) { + return (1); + } + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_seek +* +* Function description: +* Seeks via the file to a specific position +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* Pos - +* +* Return value: +* int - +* +*/ +int _sys_seek(FILEHANDLE hFile, long Pos) { + (void)hFile; + (void)Pos; + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_ensure +* +* Function description: +* +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* int - +* +*/ +int _sys_ensure(FILEHANDLE hFile) { + (void)hFile; + return (-1); // Not implemented +} + +/********************************************************************* +* +* _sys_flen +* +* Function description: +* Returns the length of the opened file handle +* +* Parameters: +* hFile - Handle to a file opened via _sys_open +* +* Return value: +* Length of the file +* +*/ +long _sys_flen(FILEHANDLE hFile) { + (void)hFile; + return (0); // Not implemented +} + +/********************************************************************* +* +* _sys_tmpnam +* +* Function description: +* This function converts the file number fileno for a temporary +* file to a unique filename, for example, tmp0001. +* +* Parameters: +* pBuffer - Pointer to a buffer to store the name +* FileNum - file number to convert +* MaxLen - Size of the buffer +* +* Return value: +* 1 - Error +* 0 - Success +* +*/ +int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) { + (void)pBuffer; + (void)FileNum; + (void)MaxLen; + return (1); // Not implemented +} + +/********************************************************************* +* +* _sys_command_string +* +* Function description: +* This function shall execute a system command. +* +* Parameters: +* cmd - Pointer to the command string +* len - Length of the string +* +* Return value: +* == NULL - Command was not successfully executed +* == sCmd - Command was passed successfully +* +*/ +char * _sys_command_string(char * cmd, int len) { + (void)len; + return cmd; // Not implemented +} + +/********************************************************************* +* +* _sys_exit +* +* Function description: +* This function is called when the application returns from main +* +* Parameters: +* ReturnCode - Return code from the main function +* +* +*/ +void _sys_exit(int ReturnCode) { + (void)ReturnCode; + while (1); // Not implemented +} + +#if __ARMCC_VERSION >= 5000000 +/********************************************************************* +* +* stdout_putchar +* +* Function description: +* Put a character to the stdout +* +* Parameters: +* ch - Character to output +* +* +*/ +int stdout_putchar(int ch) { + (void)ch; + return ch; // Not implemented +} +#endif + +#endif +/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c new file mode 100644 index 000000000..5ce8457e1 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c @@ -0,0 +1,247 @@ +/********************************************************************* +* SEGGER Microcontroller GmbH * +* The Embedded Experts * +********************************************************************** +* * +* (c) 1995 - 2019 SEGGER Microcontroller GmbH * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* SEGGER strongly recommends to not make any changes * +* to or modify the source code of this software in order to stay * +* compatible with the RTT protocol and J-Link. * +* * +* Redistribution and use in source and binary forms, with or * +* without modification, are permitted provided that the following * +* condition is met: * +* * +* o Redistributions of source code must retain the above copyright * +* notice, this condition and the following disclaimer. * +* * +* 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 SEGGER Microcontroller 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. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_Syscalls_SES.c +Purpose : Reimplementation of printf, puts and __getchar using RTT + in SEGGER Embedded Studio. + To use RTT for printf output, include this file in your + application. +Revision: $Rev: 18539 $ +---------------------------------------------------------------------- +*/ +#if (defined __SES_ARM) || (defined __SES_RISCV) || (defined __CROSSWORKS_ARM) + +#include "SEGGER_RTT.h" +#include +#include +#include "limits.h" +#include "__libc.h" +#include "__vfprintf.h" + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ +// +// Select string formatting implementation. +// +// RTT printf formatting +// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h) +// - No maximum string length. +// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c) +// Standard library printf formatting +// - Configurable formatting capabilities. +// - Full conversion specifier and flag support. +// - Maximum string length has to be known or (slightly) slower character-wise output. +// +// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting +// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting +// +#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING + #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 +#endif +// +// If using standard library formatting, +// select maximum output string buffer size or character-wise output. +// +// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output +// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length +// +#ifndef PRINTF_BUFFER_SIZE + #define PRINTF_BUFFER_SIZE 128 +#endif + +#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +/********************************************************************* +* +* Global functions, printf +* +********************************************************************** +*/ +/********************************************************************* +* +* printf() +* +* Function description +* print a formatted string using RTT and SEGGER RTT formatting. +*/ +int printf(const char *fmt,...) { + int n; + va_list args; + + va_start (args, fmt); + n = SEGGER_RTT_vprintf(0, fmt, &args); + va_end(args); + return n; +} + +#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ +static int _putchar(int x, __printf_tag_ptr ctx) { + (void)ctx; + SEGGER_RTT_Write(0, (char *)&x, 1); + return x; +} + +/********************************************************************* +* +* Global functions, printf +* +********************************************************************** +*/ +/********************************************************************* +* +* printf() +* +* Function description +* print a formatted string character-wise, using RTT and standard +* library formatting. +*/ +int printf(const char *fmt, ...) { + int n; + va_list args; + __printf_t iod; + + va_start(args, fmt); + iod.string = 0; + iod.maxchars = INT_MAX; + iod.output_fn = _putchar; + SEGGER_RTT_LOCK(); + n = __vfprintf(&iod, fmt, args); + SEGGER_RTT_UNLOCK(); + va_end(args); + return n; +} + +#else // Use standard library formatting with static buffer + +/********************************************************************* +* +* Global functions, printf +* +********************************************************************** +*/ +/********************************************************************* +* +* printf() +* +* Function description +* print a formatted string using RTT and standard library formatting. +*/ +int printf(const char *fmt,...) { + int n; + char aBuffer[PRINTF_BUFFER_SIZE]; + va_list args; + + va_start (args, fmt); + n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args); + if (n > (int)sizeof(aBuffer)) { + SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer)); + } else if (n > 0) { + SEGGER_RTT_Write(0, aBuffer, n); + } + va_end(args); + return n; +} +#endif + +/********************************************************************* +* +* Global functions +* +********************************************************************** +*/ +/********************************************************************* +* +* puts() +* +* Function description +* print a string using RTT. +*/ +int puts(const char *s) { + return SEGGER_RTT_WriteString(0, s); +} + +/********************************************************************* +* +* __putchar() +* +* Function description +* Write one character via RTT. +*/ +int __putchar(int x, __printf_tag_ptr ctx) { + (void)ctx; + SEGGER_RTT_Write(0, (char *)&x, 1); + return x; +} + +/********************************************************************* +* +* __getchar() +* +* Function description +* Wait for and get a character via RTT. +*/ +int __getchar() { + return SEGGER_RTT_WaitKey(); +} + +#endif +/****** End Of File *************************************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt new file mode 100644 index 000000000..f7330e924 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt @@ -0,0 +1,138 @@ +FatFs Module Source Files R0.09b (C)ChaN, 2013 + + +FILES + + ffconf.h Configuration file for FatFs module. + ff.h Common include file for FatFs and application module. + ff.c FatFs module. + diskio.h Common include file for FatFs and disk I/O module. + diskio.c An example of glue function to attach existing disk I/O module to FatFs. + integer.h Integer type definitions for FatFs. + option Optional external functions. + + Low level disk I/O module is not included in this archive because the FatFs + module is only a generic file system layer and not depend on any specific + storage device. You have to provide a low level disk I/O module that written + to control your storage device. + + + +AGREEMENTS + + FatFs module is an open source software to implement FAT file system to + small embedded systems. This is a free software and is opened for education, + research and commercial developments under license policy of following trems. + + Copyright (C) 2012, ChaN, all right reserved. + + * The FatFs module is a free software and there is NO WARRANTY. + * No restriction on use. You can use, modify and redistribute it for + personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. + * Redistributions of source code must retain the above copyright notice. + + + +REVISION HISTORY + + Feb 26, 2006 R0.00 Prototype + + Apr 29, 2006 R0.01 First release. + + Jun 01, 2006 R0.02 Added FAT12. + Removed unbuffered mode. + Fixed a problem on small (<32M) patition. + + Jun 10, 2006 R0.02a Added a configuration option _FS_MINIMUM. + + Sep 22, 2006 R0.03 Added f_rename. + Changed option _FS_MINIMUM to _FS_MINIMIZE. + + Dec 11, 2006 R0.03a Improved cluster scan algolithm to write files fast. + Fixed f_mkdir creates incorrect directory on FAT32. + + Feb 04, 2007 R0.04 Supported multiple drive system. (FatFs) + Changed some APIs for multiple drive system. + Added f_mkfs. (FatFs) + Added _USE_FAT32 option. (Tiny-FatFs) + + Apr 01, 2007 R0.04a Supported multiple partitions on a plysical drive. (FatFs) + Fixed an endian sensitive code in f_mkfs. (FatFs) + Added a capability of extending the file size to f_lseek. + Added minimization level 3. + Fixed a problem that can collapse a sector when recreate an + existing file in any sub-directory at non FAT32 cfg. (Tiny-FatFs) + + May 05, 2007 R0.04b Added _USE_NTFLAG option. + Added FSInfo support. + Fixed some problems corresponds to FAT32. (Tiny-FatFs) + Fixed DBCS name can result FR_INVALID_NAME. + Fixed short seek (0 < ofs <= csize) collapses the file object. + + Aug 25, 2007 R0.05 Changed arguments of f_read, f_write. + Changed arguments of f_mkfs. (FatFs) + Fixed f_mkfs on FAT32 creates incorrect FSInfo. (FatFs) + Fixed f_mkdir on FAT32 creates incorrect directory. (FatFs) + + Feb 03, 2008 R0.05a Added f_truncate(). + Added f_utime(). + Fixed off by one error at FAT sub-type determination. + Fixed btr in f_read() can be mistruncated. + Fixed cached sector is not flushed when create and close without write. + + Apr 01, 2008 R0.06 Added f_forward(). (Tiny-FatFs) + Added string functions: fputc(), fputs(), fprintf() and fgets(). + Improved performance of f_lseek() on move to the same or following cluster. + + Apr 01, 2009, R0.07 Merged Tiny-FatFs as a buffer configuration option. + Added long file name support. + Added multiple code page support. + Added re-entrancy for multitask operation. + Added auto cluster size selection to f_mkfs(). + Added rewind option to f_readdir(). + Changed result code of critical errors. + Renamed string functions to avoid name collision. + + Apr 14, 2009, R0.07a Separated out OS dependent code on reentrant cfg. + Added multiple sector size support. + + Jun 21, 2009, R0.07c Fixed f_unlink() may return FR_OK on error. + Fixed wrong cache control in f_lseek(). + Added relative path feature. + Added f_chdir(). + Added f_chdrive(). + Added proper case conversion for extended characters. + + Nov 03, 2009 R0.07e Separated out configuration options from ff.h to ffconf.h. + Added a configuration option, _LFN_UNICODE. + Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. + Fixed name matching error on the 13 char boundary. + Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. + + May 15, 2010, R0.08 Added a memory configuration option. (_USE_LFN) + Added file lock feature. (_FS_SHARE) + Added fast seek feature. (_USE_FASTSEEK) + Changed some types on the API, XCHAR->TCHAR. + Changed fname member in the FILINFO structure on Unicode cfg. + String functions support UTF-8 encoding files on Unicode cfg. + + Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2) + Added sector erase feature. (_USE_ERASE) + Moved file lock semaphore table from fs object to the bss. + Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. + Fixed f_mkfs() creates wrong FAT32 volume. + + Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). + f_lseek() reports required table size on creating CLMP. + Extended format syntax of f_printf function. + Ignores duplicated directory separators in given path names. + + Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. + Added f_fdisk(). (_MULTI_PARTITION = 2) + + Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16. + Changed f_open() and f_opendir() reject null object pointer to avoid crash. + Changed option name _FS_SHARE to _FS_LOCK. + + Jan 23,'13 R0.09b Added f_getlabel() and f_setlabel(). (_USE_LABEL == 1) + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c new file mode 100644 index 000000000..07d6f0983 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c @@ -0,0 +1,543 @@ +/*------------------------------------------------------------------------*/ +/* Unicode - Local code bidirectional converter (C)ChaN, 2012 */ +/* (SBCS code pages) */ +/*------------------------------------------------------------------------*/ +/* 437 U.S. (OEM) +/ 720 Arabic (OEM) +/ 1256 Arabic (Windows) +/ 737 Greek (OEM) +/ 1253 Greek (Windows) +/ 1250 Central Europe (Windows) +/ 775 Baltic (OEM) +/ 1257 Baltic (Windows) +/ 850 Multilingual Latin 1 (OEM) +/ 852 Latin 2 (OEM) +/ 1252 Latin 1 (Windows) +/ 855 Cyrillic (OEM) +/ 1251 Cyrillic (Windows) +/ 866 Russian (OEM) +/ 857 Turkish (OEM) +/ 1254 Turkish (Windows) +/ 858 Multilingual Latin 1 + Euro (OEM) +/ 862 Hebrew (OEM) +/ 1255 Hebrew (Windows) +/ 874 Thai (OEM, Windows) +/ 1258 Vietnam (OEM, Windows) +*/ + +#include "ff.h" + +#if CFG_TUH_MSC + +#if _CODE_PAGE == 437 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, + 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 720 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */ + 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, + 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, + 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, + 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 737 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */ + 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, + 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, + 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, + 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, + 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, + 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, + 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, + 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 775 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */ + 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, + 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, + 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, + 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, + 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, + 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, + 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, + 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, + 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, + 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, + 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 850 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, + 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, + 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, + 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 852 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, + 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, + 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, + 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, + 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, + 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, + 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, + 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, + 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, + 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 855 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */ + 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, + 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, + 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, + 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, + 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, + 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, + 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, + 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, + 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, + 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, + 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, + 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 857 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, + 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, + 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, + 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, + 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 858 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, + 0x00A9, 0x2563, 0x2551, 0x2557, 0x2550, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE, + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, + 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, + 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 862 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */ + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, + 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, + 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, + 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 866 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 874 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, + 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, + 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, + 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, + 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, + 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, + 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, + 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, + 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, + 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, + 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, + 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +#elif _CODE_PAGE == 1250 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, + 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, + 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 +}; + +#elif _CODE_PAGE == 1251 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */ + 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, + 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, + 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, + 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, + 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, + 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, + 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F +}; + +#elif _CODE_PAGE == 1252 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF +}; + +#elif _CODE_PAGE == 1253 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, + 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000 +}; + +#elif _CODE_PAGE == 1254 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF +}; + +#elif _CODE_PAGE == 1255 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, + 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, + 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, + 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, + 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, + 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000 +}; + +#elif _CODE_PAGE == 1256 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, + 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, + 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, + 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, + 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643, + 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, + 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, + 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2 +} + +#elif _CODE_PAGE == 1257 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000, + 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7, + 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, + 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, + 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, + 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, + 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, + 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, + 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, + 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, + 0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9 +}; + +#elif _CODE_PAGE == 1258 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, + 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, + 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF +}; + +#endif + + +#if !_TBLDEF || !_USE_LFN +#error This file is not needed in current configuration. Remove from the project. +#endif + + +WCHAR ff_convert ( /* Converted character, Returns zero on error */ + WCHAR chr, /* Character code to be converted */ + UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ +) +{ + WCHAR c; + + + if (chr < 0x80) { /* ASCII */ + c = chr; + + } else { + if (dir) { /* OEMCP to Unicode */ + c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80]; + + } else { /* Unicode to OEMCP */ + for (c = 0; c < 0x80; c++) { + if (chr == Tbl[c]) break; + } + c = (c + 0x80) & 0xFF; + } + } + + return c; +} + + +WCHAR ff_wtoupper ( /* Upper converted character */ + WCHAR chr /* Input character */ +) +{ + static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; + static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; + int i; + + + for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; + + return tbl_lower[i] ? tbl_upper[i] : chr; +} + +#endif // CFG_TUH_MSC diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c new file mode 100644 index 000000000..a6132f27b --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c @@ -0,0 +1,193 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb.h" + +#if CFG_TUH_MSC +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "ffconf.h" +#include "diskio.h" +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +// TODO change it to portable init +static DSTATUS disk_state[CFG_TUH_DEVICE_MAX]; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// IMPLEMENTATION +//--------------------------------------------------------------------+ +static DRESULT wait_for_io_complete(uint8_t usb_addr) +{ + // TODO with RTOS, this should use semaphore instead of blocking + while ( !tuh_msc_ready(usb_addr) ) + { + // TODO should have timeout here + #if CFG_TUSB_OS != OPT_OS_NONE + osal_task_delay(10); + #endif + } + + return RES_OK; +} + +void diskio_init(void) +{ + memset(disk_state, STA_NOINIT, CFG_TUH_DEVICE_MAX); +} + +//pdrv Specifies the physical drive number. +DSTATUS disk_initialize ( BYTE pdrv ) +{ + disk_state[pdrv] &= (~STA_NOINIT); // clear NOINIT bit + return disk_state[pdrv]; +} + +void disk_deinitialize ( BYTE pdrv ) +{ + disk_state[pdrv] |= STA_NOINIT; // set NOINIT bit +} + +DSTATUS disk_status (BYTE pdrv) +{ + return disk_state[pdrv]; +} + +//pdrv +// Specifies the physical drive number --> == dev_addr-1 +//buff +// Pointer to the byte array to store the read data. The size of buffer must be in sector size * sector count. +//sector +// Specifies the start sector number in logical block address (LBA). +//count +// Specifies number of sectors to read. The value can be 1 to 128. Generally, a multiple sector transfer request +// must not be split into single sector transactions to the device, or you may not get good read performance. +DRESULT disk_read (BYTE pdrv, BYTE*buff, DWORD sector, BYTE count) +{ + uint8_t usb_addr = pdrv+1; + + if ( TUSB_ERROR_NONE != tuh_msc_read10(usb_addr, 0, buff, sector, count) ) return RES_ERROR; + + return wait_for_io_complete(usb_addr); +} + + +DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, BYTE count) +{ + uint8_t usb_addr = pdrv+1; + + if ( TUSB_ERROR_NONE != tuh_msc_write10(usb_addr, 0, buff, sector, count) ) return RES_ERROR; + + return wait_for_io_complete(usb_addr); +} + +/* [IN] Drive number */ +/* [IN] Control command code */ +/* [I/O] Parameter and data buffer */ +DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff) +{ + (void) buff; (void) pdrv; // compiler warnings + + if (cmd != CTRL_SYNC) return RES_ERROR; + return RES_OK; +} + +static inline uint8_t month2number(char* p_ch) +{ + char const * const month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + for(uint8_t i=0; i<12; i++) + { + if ( strncmp(p_ch, month_str[i], 3) == 0 ) return i+1; + } + + return 1; +} + +static inline uint8_t c2i(char ch) +{ + return ch - '0'; +} + +DWORD get_fattime (void) +{ + union { + struct { + DWORD second : 5; + DWORD minute : 6; + DWORD hour : 5; + DWORD day_in_month : 5; + DWORD month : 4; + DWORD year : 7; + }; + + DWORD value; + } timestamp; + + //------------- Date is compiled date-------------// + char compile_date[] = __DATE__; // eg. "Sep 26 2013" + char* p_ch; + + p_ch = strtok (compile_date, " "); + timestamp.month = month2number(p_ch); + + p_ch = strtok (NULL, " "); + timestamp.day_in_month = 10*c2i(p_ch[0])+ c2i(p_ch[1]); + + p_ch = strtok (NULL, " "); + timestamp.year = 1000*c2i(p_ch[0]) + 100*c2i(p_ch[1]) + 10*c2i(p_ch[2]) + c2i(p_ch[3]) - 1980; + + //------------- Time each time this function call --> sec ++ -------------// + static uint8_t sec = 0; + static uint8_t min = 0; + static uint8_t hour = 0; + + if (++sec >= 60) + { + sec = 0; + if (++min >= 60) + { + min = 0; + if (++hour >= 24) + { + hour = 0; // assume demo wont call this function more than 24*60*60 times + } + } + } + + timestamp.hour = hour; + timestamp.minute = min; + timestamp.second = sec; + + return timestamp.value; +} + +#endif // CFG_TUH_MSC diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h new file mode 100644 index 000000000..f1f4bd327 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h @@ -0,0 +1,95 @@ +/*----------------------------------------------------------------------- +/ Low level disk interface modlue include file (C)ChaN, 2013 +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +#define _USE_WRITE 1 /* 1: Enable disk_write function */ +#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */ + +#include "integer.h" +#include + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/* Disk Status Bits (DSTATUS) */ +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl fucntion */ + +/* Generic command (used by FatFs) */ +#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ +#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ +#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ + +/* Generic command (not used by FatFs) */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ +#define CTRL_FORMAT 8 /* Create physical format on the media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ + + +/* MMC card type flags (MMC_GET_TYPE) */ +#define CT_MMC 0x01 /* MMC ver 3 */ +#define CT_SD1 0x02 /* SD ver 1 */ +#define CT_SD2 0x04 /* SD ver 2 */ +#define CT_SDC (CT_SD1|CT_SD2) /* SD */ +#define CT_BLOCK 0x08 /* Block addressing */ + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ + +void diskio_init(void); +void disk_deinitialize ( BYTE pdrv ); +DSTATUS disk_initialize (BYTE pdrv); +DSTATUS disk_status (BYTE pdrv); +DRESULT disk_read (BYTE pdrv, BYTE*buff, DWORD sector, BYTE count); +DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, BYTE count); +DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); + +static inline bool disk_is_ready(BYTE pdrv); +static inline bool disk_is_ready(BYTE pdrv) +{ + return (pdrv < CFG_TUH_DEVICE_MAX) && + ( (disk_status(pdrv) & (STA_NOINIT | STA_NODISK)) == 0 ); +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c new file mode 100644 index 000000000..79414af07 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c @@ -0,0 +1,4330 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - FAT file system module R0.09b (C)ChaN, 2013 +/-----------------------------------------------------------------------------/ +/ FatFs module is a generic FAT file system module for small embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2013, ChaN, all right reserved. +/ +/ * The FatFs module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-----------------------------------------------------------------------------/ +/ Feb 26,'06 R0.00 Prototype. +/ +/ Apr 29,'06 R0.01 First stable version. +/ +/ Jun 01,'06 R0.02 Added FAT12 support. +/ Removed unbuffered mode. +/ Fixed a problem on small (<32M) partition. +/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM). +/ +/ Sep 22,'06 R0.03 Added f_rename(). +/ Changed option _FS_MINIMUM to _FS_MINIMIZE. +/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast. +/ Fixed f_mkdir() creates incorrect directory on FAT32. +/ +/ Feb 04,'07 R0.04 Supported multiple drive system. +/ Changed some interfaces for multiple drive system. +/ Changed f_mountdrv() to f_mount(). +/ Added f_mkfs(). +/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive. +/ Added a capability of extending file size to f_lseek(). +/ Added minimization level 3. +/ Fixed an endian sensitive code in f_mkfs(). +/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG. +/ Added FSInfo support. +/ Fixed DBCS name can result FR_INVALID_NAME. +/ Fixed short seek (<= csize) collapses the file object. +/ +/ Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs(). +/ Fixed f_mkfs() on FAT32 creates incorrect FSInfo. +/ Fixed f_mkdir() on FAT32 creates incorrect directory. +/ Feb 03,'08 R0.05a Added f_truncate() and f_utime(). +/ Fixed off by one error at FAT sub-type determination. +/ Fixed btr in f_read() can be mistruncated. +/ Fixed cached sector is not flushed when create and close without write. +/ +/ Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets(). +/ Improved performance of f_lseek() on moving to the same or following cluster. +/ +/ Apr 01,'09 R0.07 Merged Tiny-FatFs as a configuration option. (_FS_TINY) +/ Added long file name feature. +/ Added multiple code page feature. +/ Added re-entrancy for multitask operation. +/ Added auto cluster size selection to f_mkfs(). +/ Added rewind option to f_readdir(). +/ Changed result code of critical errors. +/ Renamed string functions to avoid name collision. +/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg. +/ Added multiple sector size feature. +/ Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error. +/ Fixed wrong cache control in f_lseek(). +/ Added relative path feature. +/ Added f_chdir() and f_chdrive(). +/ Added proper case conversion to extended char. +/ Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h. +/ Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. +/ Fixed name matching error on the 13 char boundary. +/ Added a configuration option, _LFN_UNICODE. +/ Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. +/ +/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3) +/ Added file lock feature. (_FS_SHARE) +/ Added fast seek feature. (_USE_FASTSEEK) +/ Changed some types on the API, XCHAR->TCHAR. +/ Changed fname member in the FILINFO structure on Unicode cfg. +/ String functions support UTF-8 encoding files on Unicode cfg. +/ Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2) +/ Added sector erase feature. (_USE_ERASE) +/ Moved file lock semaphore table from fs object to the bss. +/ Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. +/ Fixed f_mkfs() creates wrong FAT32 volume. +/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). +/ f_lseek() reports required table size on creating CLMP. +/ Extended format syntax of f_printf function. +/ Ignores duplicated directory separators in given path name. +/ +/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. +/ Added f_fdisk(). (_MULTI_PARTITION = 2) +/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume. +/ Changed f_open() and f_opendir reject null object pointer to avoid crash. +/ Changed option name _FS_SHARE to _FS_LOCK. +/ Jan 24,'13 R0.09b Added f_setlabel() and f_getlabel(). (_USE_LABEL = 1) +/---------------------------------------------------------------------------*/ + +#include "ff.h" /* FatFs configurations and declarations */ +#include "diskio.h" /* Declarations of low level disk I/O functions */ + +#if CFG_TUH_MSC +/*-------------------------------------------------------------------------- + + Module Private Definitions + +---------------------------------------------------------------------------*/ + +#if _FATFS != 82786 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + + +/* Definitions on sector size */ +#if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096 +#error Wrong sector size. +#endif +#if _MAX_SS != 512 +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#else +#define SS(fs) 512U /* Fixed sector size */ +#endif + + +/* Reentrancy related */ +#if _FS_REENTRANT +#if _USE_LFN == 1 +#error Static LFN work area must not be used in re-entrant configuration. +#endif +#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#else +#define ENTER_FF(fs) +#define LEAVE_FF(fs, res) return res +#endif + +#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } + + +/* File access control feature */ +#if _FS_LOCK +#if _FS_READONLY +#error _FS_LOCK must be 0 on read-only cfg. +#endif +typedef struct { + FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ + DWORD clu; /* File ID 2, directory */ + WORD idx; /* File ID 3, directory index */ + WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */ +} FILESEM; +#endif + + + +/* DBCS code ranges and SBCS extend char conversion table */ + +#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ +#define _DF1S 0x81 /* DBC 1st byte range 1 start */ +#define _DF1E 0x9F /* DBC 1st byte range 1 end */ +#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ +#define _DF2E 0xFC /* DBC 1st byte range 2 end */ +#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ +#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ +#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ +#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ + +#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0x80 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 949 /* Korean */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x41 +#define _DS1E 0x5A +#define _DS2S 0x61 +#define _DS2E 0x7A +#define _DS3S 0x81 +#define _DS3E 0xFE + +#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0xA1 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 437 /* U.S. (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 720 /* Arabic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 737 /* Greek (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 775 /* Baltic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} + +#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 857 /* Turkish (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 866 /* Russian (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} + +#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1253 /* Greek (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ + 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} + +#elif _CODE_PAGE == 1254 /* Turkish (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1256 /* Arabic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1257 /* Baltic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} + +#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ +#if _USE_LFN +#error Cannot use LFN feature without valid code page. +#endif +#define _DF1S 0 + +#else +#error Unknown code page + +#endif + + +/* Character code support macros */ +#define IsUpper(c) (((c)>='A')&&((c)<='Z')) +#define IsLower(c) (((c)>='a')&&((c)<='z')) +#define IsDigit(c) (((c)>='0')&&((c)<='9')) + +#if _DF1S /* Code page is DBCS */ + +#ifdef _DF2S /* Two 1st byte areas */ +#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) +#else /* One 1st byte area */ +#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) +#endif + +#ifdef _DS3S /* Three 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) +#else /* Two 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) +#endif + +#else /* Code page is SBCS */ + +#define IsDBCS1(c) 0 +#define IsDBCS2(c) 0 + +#endif /* _DF1S */ + + +/* Name status flags */ +#define NS 11 /* Index of name status byte in fn[] */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ + + +/* FAT sub-type boundaries */ +/* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */ +#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ +#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ + + +/* FatFs refers the members in the FAT structures as byte array instead of +/ structure member because the structure is not binary compatible between +/ different platforms */ + +#define BS_jmpBoot 0 /* Jump instruction (3) */ +#define BS_OEMName 3 /* OEM name (8) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */ +#define BPB_NumFATs 16 /* Number of FAT copies (1) */ +#define BPB_RootEntCnt 17 /* Number of root dir entries for FAT12/16 (2) */ +#define BPB_TotSec16 19 /* Volume size [sector] (2) */ +#define BPB_Media 21 /* Media descriptor (1) */ +#define BPB_FATSz16 22 /* FAT size [sector] (2) */ +#define BPB_SecPerTrk 24 /* Track size [sector] (2) */ +#define BPB_NumHeads 26 /* Number of heads (2) */ +#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */ +#define BPB_TotSec32 32 /* Volume size [sector] (4) */ +#define BS_DrvNum 36 /* Physical drive number (2) */ +#define BS_BootSig 38 /* Extended boot signature (1) */ +#define BS_VolID 39 /* Volume serial number (4) */ +#define BS_VolLab 43 /* Volume label (8) */ +#define BS_FilSysType 54 /* File system type (1) */ +#define BPB_FATSz32 36 /* FAT size [sector] (4) */ +#define BPB_ExtFlags 40 /* Extended flags (2) */ +#define BPB_FSVer 42 /* File system version (2) */ +#define BPB_RootClus 44 /* Root dir first cluster (4) */ +#define BPB_FSInfo 48 /* Offset of FSInfo sector (2) */ +#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */ +#define BS_DrvNum32 64 /* Physical drive number (2) */ +#define BS_BootSig32 66 /* Extended boot signature (1) */ +#define BS_VolID32 67 /* Volume serial number (4) */ +#define BS_VolLab32 71 /* Volume label (8) */ +#define BS_FilSysType32 82 /* File system type (1) */ +#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ +#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ +#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ +#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ +#define MBR_Table 446 /* MBR: Partition table offset (2) */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define BS_55AA 510 /* Boot sector signature (2) */ + +#define DIR_Name 0 /* Short file name (11) */ +#define DIR_Attr 11 /* Attribute (1) */ +#define DIR_NTres 12 /* NT flag (1) */ +#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */ +#define DIR_CrtTime 14 /* Created time (2) */ +#define DIR_CrtDate 16 /* Created date (2) */ +#define DIR_LstAccDate 18 /* Last accessed date (2) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ +#define DIR_WrtTime 22 /* Modified time (2) */ +#define DIR_WrtDate 24 /* Modified date (2) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */ +#define DIR_FileSize 28 /* File size (4) */ +#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */ +#define LDIR_Attr 11 /* LFN attribute (1) */ +#define LDIR_Type 12 /* LFN type (1) */ +#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */ +#define LDIR_FstClusLO 26 /* Filled by zero (0) */ +#define SZ_DIR 32 /* Size of a directory entry */ +#define LLE 0x40 /* Last long entry flag in LDIR_Ord */ +#define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */ +#define NDDE 0x05 /* Replacement of the character collides with DDE */ + + +/*------------------------------------------------------------*/ +/* Module private work area */ +/*------------------------------------------------------------*/ +/* Note that uninitialized variables with static duration are +/ zeroed/nulled at start-up. If not, the compiler or start-up +/ routine is out of ANSI-C standard. +*/ + +#if _VOLUMES +static +FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ +#else +#error Number of volumes must not be 0. +#endif + +static +WORD Fsid; /* File system mount ID */ + +#if _FS_RPATH +static +BYTE CurrVol; /* Current drive */ +#endif + +#if _FS_LOCK +static +FILESEM Files[_FS_LOCK]; /* File lock semaphores */ +#endif + +#if _USE_LFN == 0 /* No LFN feature */ +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) (dobj).fn = sfn +#define FREE_BUF() + +#elif _USE_LFN == 1 /* LFN feature with static working buffer */ +static WCHAR LfnBuf[_MAX_LFN+1]; +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } +#define FREE_BUF() + +#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } +#define FREE_BUF() + +#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn +#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ + if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ + (dobj).lfn = lfn; (dobj).fn = sfn; } +#define FREE_BUF() ff_memfree(lfn) + +#else +#error Wrong LFN configuration. +#endif + + +#ifdef _EXCVT +static +const BYTE ExCvt[] = _EXCVT; /* Upper conversion table for extended chars */ +#endif + + + + + + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* String functions */ +/*-----------------------------------------------------------------------*/ + +/* Copy memory to memory */ +static +void mem_cpy (void* dst, const void* src, UINT cnt) { + BYTE *d = (BYTE*)dst; + const BYTE *s = (const BYTE*)src; + +#if _WORD_ACCESS == 1 + while (cnt >= sizeof (int)) { + *(int*)d = *(int*)s; + d += sizeof (int); s += sizeof (int); + cnt -= sizeof (int); + } +#endif + while (cnt--) + *d++ = *s++; +} + +/* Fill memory */ +static +void mem_set (void* dst, int val, UINT cnt) { + BYTE *d = (BYTE*)dst; + + while (cnt--) + *d++ = (BYTE)val; +} + +/* Compare memory to memory */ +static +int mem_cmp (const void* dst, const void* src, UINT cnt) { + const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; + int r = 0; + + while (cnt-- && (r = *d++ - *s++) == 0) ; + return r; +} + +/* Check if chr is contained in the string */ +static +int chk_chr (const char* str, int chr) { + while (*str && *str != chr) str++; + return *str; +} + + + +/*-----------------------------------------------------------------------*/ +/* Request/Release grant to access the volume */ +/*-----------------------------------------------------------------------*/ +#if _FS_REENTRANT + +static +int lock_fs ( + FATFS *fs /* File system object */ +) +{ + return ff_req_grant(fs->sobj); +} + + +static +void unlock_fs ( + FATFS *fs, /* File system object */ + FRESULT res /* Result code to be returned */ +) +{ + if (fs && + res != FR_NOT_ENABLED && + res != FR_INVALID_DRIVE && + res != FR_INVALID_OBJECT && + res != FR_TIMEOUT) { + ff_rel_grant(fs->sobj); + } +} +#endif + + + +/*-----------------------------------------------------------------------*/ +/* File lock control functions */ +/*-----------------------------------------------------------------------*/ +#if _FS_LOCK + +static +FRESULT chk_lock ( /* Check if the file can be accessed */ + DIR* dj, /* Directory object pointing the file to be checked */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i, be; + + /* Search file semaphore table */ + for (i = be = 0; i < _FS_LOCK; i++) { + if (Files[i].fs) { /* Existing entry */ + if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */ + Files[i].clu == dj->sclust && + Files[i].idx == dj->index) break; + } else { /* Blank entry */ + be++; + } + } + if (i == _FS_LOCK) /* The file is not opened */ + return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ + + /* The file has been opened. Reject any open against writing file and all write mode open */ + return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; +} + + +static +int enq_lock (void) /* Check if an entry is available for a new file */ +{ + UINT i; + + for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; + return (i == _FS_LOCK) ? 0 : 1; +} + + +static +UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */ + DIR* dj, /* Directory object pointing the file to register or increment */ + int acc /* Desired access mode (0:Read, !0:Write) */ +) +{ + UINT i; + + + for (i = 0; i < _FS_LOCK; i++) { /* Find the file */ + if (Files[i].fs == dj->fs && + Files[i].clu == dj->sclust && + Files[i].idx == dj->index) break; + } + + if (i == _FS_LOCK) { /* Not opened. Register it as new. */ + for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; + if (i == _FS_LOCK) return 0; /* No space to register (int err) */ + Files[i].fs = dj->fs; + Files[i].clu = dj->sclust; + Files[i].idx = dj->index; + Files[i].ctr = 0; + } + + if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; +} + + +static +FRESULT dec_lock ( /* Decrement file open counter */ + UINT i /* Semaphore index */ +) +{ + WORD n; + FRESULT res; + + + if (--i < _FS_LOCK) { + n = Files[i].ctr; + if (n == 0x100) n = 0; + if (n) n--; + Files[i].ctr = n; + if (!n) Files[i].fs = 0; + res = FR_OK; + } else { + res = FR_INT_ERR; + } + return res; +} + + +static +void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs +) +{ + UINT i; + + for (i = 0; i < _FS_LOCK; i++) { + if (Files[i].fs == fs) Files[i].fs = 0; + } +} +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Move/Flush disk access window */ +/*-----------------------------------------------------------------------*/ + + +#if !_FS_READONLY +static +FRESULT sync_window ( + FATFS *fs /* File system object */ +) +{ + DWORD wsect; + UINT nf; + + + if (fs->wflag) { /* Write back the sector if it is dirty */ + wsect = fs->winsect; /* Current sector number */ + if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) + return FR_DISK_ERR; + fs->wflag = 0; + if (wsect >= fs->fatbase && wsect < (fs->fatbase + fs->fsize)) { /* In FAT area? */ + for (nf = fs->n_fats; nf >= 2; nf--) { /* Reflect the change to all FAT copies */ + wsect += fs->fsize; + disk_write(fs->drv, fs->win, wsect, 1); + } + } + } + return FR_OK; +} +#endif + + +static +FRESULT move_window ( + FATFS *fs, /* File system object */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ +) +{ + if (sector != fs->winsect) { /* Changed current window */ +#if !_FS_READONLY + if (sync_window(fs) != FR_OK) + return FR_DISK_ERR; +#endif + if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) + return FR_DISK_ERR; + fs->winsect = sector; + } + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize file system and strage device */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */ + FATFS *fs /* File system object */ +) +{ + FRESULT res; + + + res = sync_window(fs); + if (res == FR_OK) { + /* Update FSInfo sector if needed */ + if (fs->fs_type == FS_FAT32 && fs->fsi_flag) { + fs->winsect = 0; + /* Create FSInfo structure */ + mem_set(fs->win, 0, 512); + ST_WORD(fs->win+BS_55AA, 0xAA55); + ST_DWORD(fs->win+FSI_LeadSig, 0x41615252); + ST_DWORD(fs->win+FSI_StrucSig, 0x61417272); + ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust); + ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust); + /* Write it into the FSInfo sector */ + disk_write(fs->drv, fs->win, fs->fsi_sector, 1); + fs->fsi_flag = 0; + } + /* Make sure that no pending write process in the physical drive */ + if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) + res = FR_DISK_ERR; + } + + return res; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Get sector# from cluster# */ +/*-----------------------------------------------------------------------*/ + + +DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to be converted */ +) +{ + clst -= 2; + if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ + return clst * fs->csize + fs->database; +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Read value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + + +DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to get the link information */ +) +{ + UINT wc, bc; + BYTE *p; + + + if (clst < 2 || clst >= fs->n_fatent) /* Check range */ + return 1; + + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc = fs->win[bc % SS(fs)]; bc++; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc |= fs->win[bc % SS(fs)] << 8; + return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); + + case FS_FAT16 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break; + p = &fs->win[clst * 2 % SS(fs)]; + return LD_WORD(p); + + case FS_FAT32 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break; + p = &fs->win[clst * 4 % SS(fs)]; + return LD_DWORD(p) & 0x0FFFFFFF; + } + + return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Change value of a FAT entry */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY + +FRESULT put_fat ( + FATFS *fs, /* File system object */ + DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ + DWORD val /* New value to mark the cluster */ +) +{ + UINT bc; + BYTE *p; + FRESULT res; + + + if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ + res = FR_INT_ERR; + + } else { + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = &fs->win[bc % SS(fs)]; + *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; + bc++; + fs->wflag = 1; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = &fs->win[bc % SS(fs)]; + *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); + break; + + case FS_FAT16 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); + if (res != FR_OK) break; + p = &fs->win[clst * 2 % SS(fs)]; + ST_WORD(p, (WORD)val); + break; + + case FS_FAT32 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); + if (res != FR_OK) break; + p = &fs->win[clst * 4 % SS(fs)]; + val |= LD_DWORD(p) & 0xF0000000; + ST_DWORD(p, val); + break; + + default : + res = FR_INT_ERR; + } + fs->wflag = 1; + } + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Remove a cluster chain */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT remove_chain ( + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to remove a chain from */ +) +{ + FRESULT res; + DWORD nxt; +#if _USE_ERASE + DWORD scl = clst, ecl = clst, rt[2]; +#endif + + if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ + res = FR_INT_ERR; + + } else { + res = FR_OK; + while (clst < fs->n_fatent) { /* Not a last link? */ + nxt = get_fat(fs, clst); /* Get cluster status */ + if (nxt == 0) break; /* Empty cluster? */ + if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ + if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */ + res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */ + if (res != FR_OK) break; + if (fs->free_clust != 0xFFFFFFFF) { /* Update FSInfo */ + fs->free_clust++; + fs->fsi_flag = 1; + } +#if _USE_ERASE + if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ + ecl = nxt; + } else { /* End of contiguous clusters */ + rt[0] = clust2sect(fs, scl); /* Start sector */ + rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ + disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt); /* Erase the block */ + scl = ecl = nxt; + } +#endif + clst = nxt; /* Next cluster */ + } + } + + return res; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Stretch or Create a cluster chain */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ +) +{ + DWORD cs, ncl, scl; + FRESULT res; + + + if (clst == 0) { /* Create a new chain */ + scl = fs->last_clust; /* Get suggested start point */ + if (!scl || scl >= fs->n_fatent) scl = 1; + } + else { /* Stretch the current chain */ + cs = get_fat(fs, clst); /* Check the cluster status */ + if (cs < 2) return 1; /* It is an invalid cluster */ + if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ + scl = clst; + } + + ncl = scl; /* Start cluster */ + for (;;) { + ncl++; /* Next cluster */ + if (ncl >= fs->n_fatent) { /* Wrap around */ + ncl = 2; + if (ncl > scl) return 0; /* No free cluster */ + } + cs = get_fat(fs, ncl); /* Get the cluster status */ + if (cs == 0) break; /* Found a free cluster */ + if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ + return cs; + if (ncl == scl) return 0; /* No free cluster */ + } + + res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */ + if (res == FR_OK && clst != 0) { + res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */ + } + if (res == FR_OK) { + fs->last_clust = ncl; /* Update FSINFO */ + if (fs->free_clust != 0xFFFFFFFF) { + fs->free_clust--; + fs->fsi_flag = 1; + } + } else { + ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; + } + + return ncl; /* Return new cluster number or error code */ +} +#endif /* !_FS_READONLY */ + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Convert offset into cluster with link map table */ +/*-----------------------------------------------------------------------*/ + +#if _USE_FASTSEEK +static +DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ + FIL* fp, /* Pointer to the file object */ + DWORD ofs /* File offset to be converted to cluster# */ +) +{ + DWORD cl, ncl, *tbl; + + + tbl = fp->cltbl + 1; /* Top of CLMT */ + cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */ + for (;;) { + ncl = *tbl++; /* Number of cluters in the fragment */ + if (!ncl) return 0; /* End of table? (error) */ + if (cl < ncl) break; /* In this fragment? */ + cl -= ncl; tbl++; /* Next fragment */ + } + return cl + *tbl; /* Return the cluster number */ +} +#endif /* _USE_FASTSEEK */ + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Set directory index */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_sdi ( + DIR *dj, /* Pointer to directory object */ + WORD idx /* Index of directory table */ +) +{ + DWORD clst; + WORD ic; + + + dj->index = idx; + clst = dj->sclust; + if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */ + return FR_INT_ERR; + if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ + clst = dj->fs->dirbase; + + if (clst == 0) { /* Static table (root-dir in FAT12/16) */ + dj->clust = clst; + if (idx >= dj->fs->n_rootdir) /* Index is out of range */ + return FR_INT_ERR; + dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ + } + else { /* Dynamic table (sub-dirs or root-dir in FAT32) */ + ic = SS(dj->fs) / SZ_DIR * dj->fs->csize; /* Entries per cluster */ + while (idx >= ic) { /* Follow cluster chain */ + clst = get_fat(dj->fs, clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */ + return FR_INT_ERR; + idx -= ic; + } + dj->clust = clst; + dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ + } + + dj->dir = dj->fs->win + (idx % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; /* Ptr to the entry in the sector */ + + return FR_OK; /* Seek succeeded */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Move directory table index next */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ + DIR *dj, /* Pointer to the directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +) +{ + DWORD clst; + WORD i; + + + stretch = stretch; /* To suppress warning on read-only cfg. */ + i = dj->index + 1; + if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ + return FR_NO_FILE; + + if (!(i % (SS(dj->fs) / SZ_DIR))) { /* Sector changed? */ + dj->sect++; /* Next sector */ + + if (dj->clust == 0) { /* Static table */ + if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */ + return FR_NO_FILE; + } + else { /* Dynamic table */ + if (((i / (SS(dj->fs) / SZ_DIR)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */ + clst = get_fat(dj->fs, dj->clust); /* Get next cluster */ + if (clst <= 1) return FR_INT_ERR; + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; + if (clst >= dj->fs->n_fatent) { /* When it reached end of dynamic table */ +#if !_FS_READONLY + BYTE c; + if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */ + clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */ + if (clst == 0) return FR_DENIED; /* No free cluster */ + if (clst == 1) return FR_INT_ERR; + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; + /* Clean-up stretched table */ + if (sync_window(dj->fs)) return FR_DISK_ERR; /* Flush active window */ + mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */ + dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */ + for (c = 0; c < dj->fs->csize; c++) { /* Fill the new cluster with 0 */ + dj->fs->wflag = 1; + if (sync_window(dj->fs)) return FR_DISK_ERR; + dj->fs->winsect++; + } + dj->fs->winsect -= c; /* Rewind window address */ +#else + return FR_NO_FILE; /* Report EOT */ +#endif + } + dj->clust = clst; /* Initialize data for new cluster */ + dj->sect = clust2sect(dj->fs, clst); + } + } + } + + dj->index = i; + dj->dir = dj->fs->win + (i % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Reserve directory entry */ +/*-----------------------------------------------------------------------*/ + +#if !_FS_READONLY +static +FRESULT dir_alloc ( + DIR* dj, /* Pointer to the directory object */ + UINT nent /* Number of contiguous entries to allocate (1-21) */ +) +{ + FRESULT res; + UINT n; + + + res = dir_sdi(dj, 0); + if (res == FR_OK) { + n = 0; + do { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + if (dj->dir[0] == DDE || dj->dir[0] == 0) { /* Is it a blank entry? */ + if (++n == nent) break; /* A block of contiguous entry is found */ + } else { + n = 0; /* Not a blank entry. Restart to search */ + } + res = dir_next(dj, 1); /* Next entry with table stretch enabled */ + } while (res == FR_OK); + } + return res; +} +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Load/Store start cluster number */ +/*-----------------------------------------------------------------------*/ + +static +DWORD ld_clust ( + FATFS *fs, /* Pointer to the fs object */ + BYTE *dir /* Pointer to the directory entry */ +) +{ + DWORD cl; + + cl = LD_WORD(dir+DIR_FstClusLO); + if (fs->fs_type == FS_FAT32) + cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16; + + return cl; +} + + +#if !_FS_READONLY +static +void st_clust ( + BYTE *dir, /* Pointer to the directory entry */ + DWORD cl /* Value to be set */ +) +{ + ST_WORD(dir+DIR_FstClusLO, cl); + ST_WORD(dir+DIR_FstClusHI, cl >> 16); +} +#endif + + + +/*-----------------------------------------------------------------------*/ +/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +static +const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN chars in the directory entry */ + + +static +int cmp_lfn ( /* 1:Matched, 0:Not matched */ + WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ + BYTE *dir /* Pointer to the directory entry containing a part of LFN */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */ + s = 0; wc = 1; + do { + uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ + if (wc) { /* Last char has not been processed */ + wc = ff_wtoupper(uc); /* Convert it to upper case */ + if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */ + return 0; /* Not matched */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } while (++s < 13); /* Repeat until all chars in the entry are checked */ + + if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i]) /* Last segment matched but different length */ + return 0; + + return 1; /* The part of LFN matched */ +} + + + +static +int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ + WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */ + BYTE *dir /* Pointer to the directory entry */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + + s = 0; wc = 1; + do { + uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ + if (wc) { /* Last char has not been processed */ + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i++] = wc = uc; /* Store it */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } while (++s < 13); /* Read all character in the entry */ + + if (dir[LDIR_Ord] & LLE) { /* Put terminator if it is the last LFN part */ + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i] = 0; + } + + return 1; +} + + +#if !_FS_READONLY +static +void fit_lfn ( + const WCHAR *lfnbuf, /* Pointer to the LFN buffer */ + BYTE *dir, /* Pointer to the directory entry */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* SFN sum */ +) +{ + UINT i, s; + WCHAR wc; + + + dir[LDIR_Chksum] = sum; /* Set check sum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + ST_WORD(dir+LDIR_FstClusLO, 0); + + i = (ord - 1) * 13; /* Get offset in the LFN buffer */ + s = wc = 0; + do { + if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective char */ + ST_WORD(dir+LfnOfs[s], wc); /* Put it */ + if (!wc) wc = 0xFFFF; /* Padding chars following last char */ + } while (++s < 13); + if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLE; /* Bottom LFN part is the start of LFN sequence */ + dir[LDIR_Ord] = ord; /* Set the LFN order */ +} + +#endif +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Create numbered name */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +void gen_numname ( + BYTE *dst, /* Pointer to generated SFN */ + const BYTE *src, /* Pointer to source SFN to be modified */ + const WCHAR *lfn, /* Pointer to LFN */ + WORD seq /* Sequence number */ +) +{ + BYTE ns[8], c; + UINT i, j; + + + mem_cpy(dst, src, 11); + + if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */ + do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn); + } + + /* itoa (hexdecimal) */ + i = 7; + do { + c = (seq % 16) + '0'; + if (c > '9') c += 7; + ns[i--] = c; + seq /= 16; + } while (seq); + ns[i] = '~'; + + /* Append the number */ + for (j = 0; j < i && dst[j] != ' '; j++) { + if (IsDBCS1(dst[j])) { + if (j == i - 1) break; + j++; + } + } + do { + dst[j++] = (i < 8) ? ns[i++] : ' '; + } while (j < 8); +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Calculate sum of an SFN */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +static +BYTE sum_sfn ( + const BYTE *dir /* Ptr to directory entry */ +) +{ + BYTE sum = 0; + UINT n = 11; + + do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); + return sum; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Find an object in the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_find ( + DIR *dj /* Pointer to the directory object linked to the file name */ +) +{ + FRESULT res; + BYTE c, *dir; +#if _USE_LFN + BYTE a, ord, sum; +#endif + + res = dir_sdi(dj, 0); /* Rewind directory object */ + if (res != FR_OK) return res; + +#if _USE_LFN + ord = sum = 0xFF; +#endif + do { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + dir = dj->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ +#if _USE_LFN /* LFN configuration */ + a = dir[DIR_Attr] & AM_MASK; + if (c == DDE || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (dj->lfn) { + if (c & LLE) { /* Is it start of LFN sequence? */ + sum = dir[LDIR_Chksum]; + c &= ~LLE; ord = c; /* LFN start order */ + dj->lfn_idx = dj->index; + } + /* Check validity of the LFN entry and compare it with given name */ + ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; + } + } else { /* An SFN entry is found */ + if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */ + ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */ + if (!(dj->fn[NS] & NS_LOSS) && !mem_cmp(dir, dj->fn, 11)) break; /* SFN matched? */ + } + } +#else /* Non LFN configuration */ + if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ + break; +#endif + res = dir_next(dj, 0); /* Next entry */ + } while (res == FR_OK); + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read an object from the directory */ +/*-----------------------------------------------------------------------*/ +#if _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 +static +FRESULT dir_read ( + DIR *dj, /* Pointer to the directory object */ + int vol /* Filtered by 0:file/dir or 1:volume label */ +) +{ + FRESULT res; + BYTE a, c, *dir; +#if _USE_LFN + BYTE ord = 0xFF, sum = 0xFF; +#endif + + res = FR_NO_FILE; + while (dj->sect) { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + dir = dj->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ + a = dir[DIR_Attr] & AM_MASK; +#if _USE_LFN /* LFN configuration */ + if (c == DDE || (!_FS_RPATH && c == '.') || (a == AM_VOL) != vol) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (c & LLE) { /* Is it start of LFN sequence? */ + sum = dir[LDIR_Chksum]; + c &= ~LLE; ord = c; + dj->lfn_idx = dj->index; + } + /* Check LFN validity and capture it */ + ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; + } else { /* An SFN entry is found */ + if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */ + dj->lfn_idx = 0xFFFF; /* It has no LFN. */ + break; + } + } +#else /* Non LFN configuration */ + if (c != DDE && (_FS_RPATH || c != '.') && a != AM_LFN && (a == AM_VOL) == vol) /* Is it a valid entry? */ + break; +#endif + res = dir_next(dj, 0); /* Next entry */ + if (res != FR_OK) break; + } + + if (res != FR_OK) dj->sect = 0; + + return res; +} +#endif /* _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 */ + + + +/*-----------------------------------------------------------------------*/ +/* Register an object to the directory */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ + DIR *dj /* Target directory with object name to be created */ +) +{ + FRESULT res; +#if _USE_LFN /* LFN configuration */ + WORD n, ne; + BYTE sn[12], *fn, sum; + WCHAR *lfn; + + + fn = dj->fn; lfn = dj->lfn; + mem_cpy(sn, fn, 12); + + if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */ + return FR_INVALID_NAME; + + if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ + fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ + for (n = 1; n < 100; n++) { + gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ + res = dir_find(dj); /* Check if the name collides with existing SFN */ + if (res != FR_OK) break; + } + if (n == 100) return FR_DENIED; /* Abort if too many collisions */ + if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ + fn[NS] = sn[NS]; dj->lfn = lfn; + } + + if (sn[NS] & NS_LFN) { /* When LFN is to be created, allocate entries for an SFN + LFNs. */ + for (n = 0; lfn[n]; n++) ; + ne = (n + 25) / 13; + } else { /* Otherwise allocate an entry for an SFN */ + ne = 1; + } + res = dir_alloc(dj, ne); /* Allocate entries */ + + if (res == FR_OK && --ne) { /* Set LFN entry if needed */ + res = dir_sdi(dj, (WORD)(dj->index - ne)); + if (res == FR_OK) { + sum = sum_sfn(dj->fn); /* Sum value of the SFN tied to the LFN */ + do { /* Store LFN entries in bottom first */ + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum); + dj->fs->wflag = 1; + res = dir_next(dj, 0); /* Next entry */ + } while (res == FR_OK && --ne); + } + } +#else /* Non LFN configuration */ + res = dir_alloc(dj, 1); /* Allocate an entry for SFN */ +#endif + + if (res == FR_OK) { /* Set SFN entry */ + res = move_window(dj->fs, dj->sect); + if (res == FR_OK) { + mem_set(dj->dir, 0, SZ_DIR); /* Clean the entry */ + mem_cpy(dj->dir, dj->fn, 11); /* Put SFN */ +#if _USE_LFN + dj->dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */ +#endif + dj->fs->wflag = 1; + } + } + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Remove an object from the directory */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY && !_FS_MINIMIZE +static +FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ + DIR *dj /* Directory object pointing the entry to be removed */ +) +{ + FRESULT res; +#if _USE_LFN /* LFN configuration */ + WORD i; + + i = dj->index; /* SFN index */ + res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */ + if (res == FR_OK) { + do { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + *dj->dir = DDE; /* Mark the entry "deleted" */ + dj->fs->wflag = 1; + if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ + res = dir_next(dj, 0); /* Next entry */ + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR; + } + +#else /* Non LFN configuration */ + res = dir_sdi(dj, dj->index); + if (res == FR_OK) { + res = move_window(dj->fs, dj->sect); + if (res == FR_OK) { + *dj->dir = DDE; /* Mark the entry "deleted" */ + dj->fs->wflag = 1; + } + } +#endif + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Pick a segment and create the object name in directory form */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT create_name ( + DIR *dj, /* Pointer to the directory object */ + const TCHAR **path /* Pointer to pointer to the segment in the path string */ +) +{ +#if _USE_LFN /* LFN configuration */ + BYTE b, cf; + WCHAR w, *lfn; + UINT i, ni, si, di; + const TCHAR *p; + + /* Create LFN in Unicode */ + for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ + lfn = dj->lfn; + si = di = 0; + for (;;) { + w = p[si++]; /* Get a character */ + if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ + if (di >= _MAX_LFN) /* Reject too long name */ + return FR_INVALID_NAME; +#if !_LFN_UNICODE + w &= 0xFF; + if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + b = (BYTE)p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(b)) + return FR_INVALID_NAME; /* Reject invalid sequence */ + w = (w << 8) + b; /* Create a DBC */ + } + w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ + if (!w) return FR_INVALID_NAME; /* Reject invalid code */ +#endif + if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */ + return FR_INVALID_NAME; + lfn[di++] = w; /* Store the Unicode char */ + } + *path = &p[si]; /* Return pointer to the next segment */ + cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ +#if _FS_RPATH + if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */ + (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) { + lfn[di] = 0; + for (i = 0; i < 11; i++) + dj->fn[i] = (i < di) ? '.' : ' '; + dj->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } +#endif + while (di) { /* Strip trailing spaces and dots */ + w = lfn[di-1]; + if (w != ' ' && w != '.') break; + di--; + } + if (!di) return FR_INVALID_NAME; /* Reject nul string */ + + lfn[di] = 0; /* LFN is created */ + + /* Create SFN in directory form */ + mem_set(dj->fn, ' ', 11); + for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ + if (si) cf |= NS_LOSS | NS_LFN; + while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ + + b = i = 0; ni = 8; + for (;;) { + w = lfn[si++]; /* Get an LFN char */ + if (!w) break; /* Break on end of the LFN */ + if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ + cf |= NS_LOSS | NS_LFN; continue; + } + + if (i >= ni || si == di) { /* Extension or end of SFN */ + if (ni == 11) { /* Long extension */ + cf |= NS_LOSS | NS_LFN; break; + } + if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ + if (si > di) break; /* No extension */ + si = di; i = 8; ni = 11; /* Enter extension section */ + b <<= 2; continue; + } + + if (w >= 0x80) { /* Non ASCII char */ +#ifdef _EXCVT + w = ff_convert(w, 0); /* Unicode -> OEM code */ + if (w) w = ExCvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ +#else + w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ +#endif + cf |= NS_LFN; /* Force create LFN entry */ + } + + if (_DF1S && w >= 0x100) { /* Double byte char (always false on SBCS cfg) */ + if (i >= ni - 1) { + cf |= NS_LOSS | NS_LFN; i = ni; continue; + } + dj->fn[i++] = (BYTE)(w >> 8); + } else { /* Single byte char */ + if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */ + w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } else { + if (IsUpper(w)) { /* ASCII large capital */ + b |= 2; + } else { + if (IsLower(w)) { /* ASCII small capital */ + b |= 1; w -= 0x20; + } + } + } + } + dj->fn[i++] = (BYTE)w; + } + + if (dj->fn[0] == DDE) dj->fn[0] = NDDE; /* If the first char collides with deleted mark, replace it with 0x05 */ + + if (ni == 8) b <<= 2; + if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ + cf |= NS_LFN; + if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended char, NT flags are created */ + if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ + if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ + } + + dj->fn[NS] = cf; /* SFN is created */ + + return FR_OK; + + +#else /* Non-LFN configuration */ + BYTE b, c, d, *sfn; + UINT ni, si, i; + const char *p; + + /* Create file name in directory form */ + for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ + sfn = dj->fn; + mem_set(sfn, ' ', 11); + si = i = b = 0; ni = 8; +#if _FS_RPATH + if (p[si] == '.') { /* Is this a dot entry? */ + for (;;) { + c = (BYTE)p[si++]; + if (c != '.' || si >= 3) break; + sfn[i++] = c; + } + if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; + *path = &p[si]; /* Return pointer to the next segment */ + sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ + return FR_OK; + } +#endif + for (;;) { + c = (BYTE)p[si++]; + if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ + if (c == '.' || i >= ni) { + if (ni != 8 || c != '.') return FR_INVALID_NAME; + i = 8; ni = 11; + b <<= 2; continue; + } + if (c >= 0x80) { /* Extended char? */ + b |= 3; /* Eliminate NT flag */ +#ifdef _EXCVT + c = ExCvt[c - 0x80]; /* To upper extended chars (SBCS cfg) */ +#else +#if !_DF1S + return FR_INVALID_NAME; /* Reject extended chars (ASCII cfg) */ +#endif +#endif + } + if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + d = (BYTE)p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ + return FR_INVALID_NAME; + sfn[i++] = c; + sfn[i++] = d; + } else { /* Single byte code */ + if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ + return FR_INVALID_NAME; + if (IsUpper(c)) { /* ASCII large capital? */ + b |= 2; + } else { + if (IsLower(c)) { /* ASCII small capital? */ + b |= 1; c -= 0x20; + } + } + sfn[i++] = c; + } + } + *path = &p[si]; /* Return pointer to the next segment */ + c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ + + if (!i) return FR_INVALID_NAME; /* Reject nul string */ + if (sfn[0] == DDE) sfn[0] = NDDE; /* When first char collides with DDE, replace it with 0x05 */ + + if (ni == 8) b <<= 2; + if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ + if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */ + + sfn[NS] = c; /* Store NT flag, File name is created */ + + return FR_OK; +#endif +} + + + + +/*-----------------------------------------------------------------------*/ +/* Get file information from directory entry */ +/*-----------------------------------------------------------------------*/ +#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 +static +void get_fileinfo ( /* No return code */ + DIR *dj, /* Pointer to the directory object */ + FILINFO *fno /* Pointer to the file information to be filled */ +) +{ + UINT i; + BYTE nt, *dir; + TCHAR *p, c; + + + p = fno->fname; + if (dj->sect) { + dir = dj->dir; + nt = dir[DIR_NTres]; /* NT flag */ + for (i = 0; i < 8; i++) { /* Copy name body */ + c = dir[i]; + if (c == ' ') break; + if (c == NDDE) c = (TCHAR)DDE; + if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20; +#if _LFN_UNICODE + if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1])) + c = (c << 8) | dir[++i]; + c = ff_convert(c, 1); + if (!c) c = '?'; +#endif + *p++ = c; + } + if (dir[8] != ' ') { /* Copy name extension */ + *p++ = '.'; + for (i = 8; i < 11; i++) { + c = dir[i]; + if (c == ' ') break; + if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20; +#if _LFN_UNICODE + if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1])) + c = (c << 8) | dir[++i]; + c = ff_convert(c, 1); + if (!c) c = '?'; +#endif + *p++ = c; + } + } + fno->fattrib = dir[DIR_Attr]; /* Attribute */ + fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ + fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ + fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ + } + *p = 0; /* Terminate SFN str by a \0 */ + +#if _USE_LFN + if (fno->lfname && fno->lfsize) { + TCHAR *tp = fno->lfname; + WCHAR w, *lfn; + + i = 0; + if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */ + lfn = dj->lfn; + while ((w = *lfn++) != 0) { /* Get an LFN char */ +#if !_LFN_UNICODE + w = ff_convert(w, 0); /* Unicode -> OEM conversion */ + if (!w) { i = 0; break; } /* Could not convert, no LFN */ + if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ + tp[i++] = (TCHAR)(w >> 8); +#endif + if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overflow, no LFN */ + tp[i++] = (TCHAR)w; + } + } + tp[i] = 0; /* Terminate the LFN str by a \0 */ + } +#endif +} +#endif /* _FS_MINIMIZE <= 1 || _FS_RPATH >= 2*/ + + + + +/*-----------------------------------------------------------------------*/ +/* Follow a file path */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR *dj, /* Directory object to return last directory and found object */ + const TCHAR *path /* Full-path string to find a file or directory */ +) +{ + FRESULT res; + BYTE *dir, ns; + + +#if _FS_RPATH + if (*path == '/' || *path == '\\') { /* There is a heading separator */ + path++; dj->sclust = 0; /* Strip it and start from the root dir */ + } else { /* No heading separator */ + dj->sclust = dj->fs->cdir; /* Start from the current dir */ + } +#else + if (*path == '/' || *path == '\\') /* Strip heading separator if exist */ + path++; + dj->sclust = 0; /* Start from the root dir */ +#endif + + if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ + res = dir_sdi(dj, 0); + dj->dir = 0; + } else { /* Follow path */ + for (;;) { + res = create_name(dj, &path); /* Get a segment */ + if (res != FR_OK) break; + res = dir_find(dj); /* Find it */ + ns = *(dj->fn+NS); + if (res != FR_OK) { /* Failed to find the object */ + if (res != FR_NO_FILE) break; /* Abort if any hard error occurred */ + /* Object not found */ + if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */ + dj->sclust = 0; dj->dir = 0; /* It is the root dir */ + res = FR_OK; + if (!(ns & NS_LAST)) continue; + } else { /* Could not find the object */ + if (!(ns & NS_LAST)) res = FR_NO_PATH; + } + break; + } + if (ns & NS_LAST) break; /* Last segment match. Function completed. */ + dir = dj->dir; /* There is next segment. Follow the sub directory */ + if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ + res = FR_NO_PATH; break; + } + dj->sclust = ld_clust(dj->fs, dir); + } + } + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an FAT Volume Boot Record */ +/*-----------------------------------------------------------------------*/ + +static +BYTE check_fs ( /* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */ + FATFS *fs, /* File system object */ + DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ +) +{ + if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) /* Load boot record */ + return 3; + if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ + return 2; + + if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ + return 0; + if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) + return 0; + + return 1; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file system object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ + const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ + FATFS **rfs, /* Pointer to pointer to the found file system object */ + BYTE wmode /* !=0: Check write protection for write access */ +) +{ + BYTE fmt, b, pi, *tbl; + UINT vol; + DSTATUS stat; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat; + WORD nrsv; + const TCHAR *p = *path; + FATFS *fs; + + + /* Get logical drive number from the path name */ + vol = p[0] - '0'; /* Is there a drive number? */ + if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ + p += 2; *path = p; /* Return pointer to the path name */ + } else { /* No drive number, use default drive */ +#if _FS_RPATH + vol = CurrVol; /* Use current drive */ +#else + vol = 0; /* Use drive 0 */ +#endif + } + + /* Check if the file system object is valid or not */ + *rfs = 0; + if (vol >= _VOLUMES) /* Is the drive number valid? */ + return FR_INVALID_DRIVE; + fs = FatFs[vol]; /* Get corresponding file system object */ + if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ + + ENTER_FF(fs); /* Lock volume */ + + *rfs = fs; /* Return pointer to the corresponding file system object */ + if (fs->fs_type) { /* If the volume has been mounted */ + stat = disk_status(fs->drv); + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ + if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */ + return FR_WRITE_PROTECTED; + return FR_OK; /* The file system object is valid */ + } + } + + /* The file system object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ + + fs->fs_type = 0; /* Clear the file system object */ + fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->drv); /* Initialize the physical drive */ + if (stat & STA_NOINIT) /* Check if the initialization succeeded */ + return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ + if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */ + return FR_WRITE_PROTECTED; +#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ + if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) + return FR_DISK_ERR; +#endif + /* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */ + fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */ + if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */ + if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */ + /* Check the partition listed in the partition table */ + pi = LD2PT(vol); + if (pi) pi--; + tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */ + if (tbl[4]) { /* Is the partition existing? */ + bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ + fmt = check_fs(fs, bsect); /* Check the partition */ + } + } + if (fmt == 3) return FR_DISK_ERR; + if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + + /* An FAT volume is found. Following code initializes the file system object */ + + if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ + return FR_NO_FILESYSTEM; + + fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */ + if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32); + fs->fsize = fasize; + + fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */ + if (b != 1 && b != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + fasize *= b; /* Number of sectors for FAT area */ + + fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ + if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + + fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */ + if (fs->n_rootdir % (SS(fs) / SZ_DIR)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ + + tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */ + if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32); + + nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIR); /* RSV+FAT+DIR */ + if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ + if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + fmt = FS_FAT12; + if (nclst >= MIN_FAT16) fmt = FS_FAT16; + if (nclst >= MIN_FAT32) fmt = FS_FAT32; + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->volbase = bsect; /* Volume start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + fs->database = bsect + sysect; /* Data start sector */ + if (fmt == FS_FAT32) { + if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Required FAT size) */ + } else { + if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); + } + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than required) */ + return FR_NO_FILESYSTEM; + +#if !_FS_READONLY + /* Initialize cluster allocation information */ + fs->free_clust = 0xFFFFFFFF; + fs->last_clust = 0; + + /* Get fsinfo if available */ + if (fmt == FS_FAT32) { + fs->fsi_flag = 0; + fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo); + if (disk_read(fs->drv, fs->win, fs->fsi_sector, 1) == RES_OK && + LD_WORD(fs->win+BS_55AA) == 0xAA55 && + LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 && + LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) { + fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free); + fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count); + } + } +#endif + fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* File system mount ID */ + fs->winsect = 0; /* Invalidate sector cache */ + fs->wflag = 0; +#if _FS_RPATH + fs->cdir = 0; /* Current directory (root dir) */ +#endif +#if _FS_LOCK /* Clear file lock semaphores */ + clear_lock(fs); +#endif + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file/dir object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ + void* obj /* Pointer to the object FIL/DIR to check validity */ +) +{ + FIL *fil = (FIL*)obj; /* Assuming offset of fs and id in the FIL/DIR is identical */ + + + if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id) + return FR_INVALID_OBJECT; + + ENTER_FF(fil->fs); /* Lock file system */ + + if (disk_status(fil->fs->drv) & STA_NOINIT) + return FR_NOT_READY; + + return FR_OK; +} + + + + +/*-------------------------------------------------------------------------- + + Public Functions + +--------------------------------------------------------------------------*/ + + + +/*-----------------------------------------------------------------------*/ +/* Mount/Unmount a Logical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mount ( + BYTE vol, /* Logical drive number to be mounted/unmounted */ + FATFS *fs /* Pointer to new file system object (NULL for unmount)*/ +) +{ + FATFS *rfs; + + + if (vol >= _VOLUMES) /* Check if the drive number is valid */ + return FR_INVALID_DRIVE; + rfs = FatFs[vol]; /* Get current fs object */ + + if (rfs) { +#if _FS_LOCK + clear_lock(rfs); +#endif +#if _FS_REENTRANT /* Discard sync object of the current volume */ + if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; +#endif + rfs->fs_type = 0; /* Clear old fs object */ + } + + if (fs) { + fs->fs_type = 0; /* Clear new fs object */ +#if _FS_REENTRANT /* Create sync object for the new volume */ + if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR; +#endif + } + FatFs[vol] = fs; /* Register new fs object */ + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Open or Create a File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_open ( + FIL *fp, /* Pointer to the blank file object */ + const TCHAR *path, /* Pointer to the file name */ + BYTE mode /* Access mode and file open mode flags */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + if (!fp) return FR_INVALID_OBJECT; + fp->fs = 0; /* Clear file object */ + +#if !_FS_READONLY + mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; + res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ)); +#else + mode &= FA_READ; + res = chk_mounted(&path, &dj.fs, 0); +#endif + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + dir = dj.dir; +#if !_FS_READONLY /* R/W configuration */ + if (res == FR_OK) { + if (!dir) /* Current dir itself */ + res = FR_INVALID_NAME; +#if _FS_LOCK + else + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); +#endif + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { + DWORD dw, cl; + + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ +#if _FS_LOCK + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#else + res = dir_register(&dj); +#endif + mode |= FA_CREATE_ALWAYS; /* File is created */ + dir = dj.dir; /* New entry */ + } + else { /* Any object is already existing */ + if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ + res = FR_DENIED; + } else { + if (mode & FA_CREATE_NEW) /* Cannot create as new file */ + res = FR_EXIST; + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ + dw = get_fattime(); /* Created time */ + ST_DWORD(dir+DIR_CrtTime, dw); + dir[DIR_Attr] = 0; /* Reset attribute */ + ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ + cl = ld_clust(dj.fs, dir); /* Get start cluster */ + st_clust(dir, 0); /* cluster = 0 */ + dj.fs->wflag = 1; + if (cl) { /* Remove the cluster chain if exist */ + dw = dj.fs->winsect; + res = remove_chain(dj.fs, cl); + if (res == FR_OK) { + dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ + res = move_window(dj.fs, dw); + } + } + } + } + else { /* Open an existing file */ + if (res == FR_OK) { /* Follow succeeded */ + if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ + res = FR_DENIED; + } + } + } + if (res == FR_OK) { + if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ + mode |= FA__WRITTEN; + fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dir; +#if _FS_LOCK + fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + if (!fp->lockid) res = FR_INT_ERR; +#endif + } + +#else /* R/O configuration */ + if (res == FR_OK) { /* Follow succeeded */ + dir = dj.dir; + if (!dir) { /* Current dir itself */ + res = FR_INVALID_NAME; + } else { + if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ + res = FR_NO_FILE; + } + } +#endif + FREE_BUF(); + + if (res == FR_OK) { + fp->flag = mode; /* File access mode */ + fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */ + fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ + fp->fptr = 0; /* File pointer */ + fp->dsect = 0; +#if _USE_FASTSEEK + fp->cltbl = 0; /* Normal seek mode */ +#endif + fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ + } + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_read ( + FIL *fp, /* Pointer to the file object */ + void *buff, /* Pointer to data buffer */ + UINT btr, /* Number of bytes to read */ + UINT *br /* Pointer to number of bytes read */ +) +{ + FRESULT res; + DWORD clst, sect, remain; + UINT rcnt, cc; + BYTE csect, *rbuff = (BYTE*)buff; + + + *br = 0; /* Clear read byte counter */ + + res = validate(fp); /* Check validity */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Aborted file? */ + LEAVE_FF(fp->fs, FR_INT_ERR); + if (!(fp->flag & FA_READ)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + remain = fp->fsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr; /* Repeat until all data read */ + rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if (!csect) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->sclust; /* Follow from the origin */ + } else { /* Middle or end of the file */ +#if _USE_FASTSEEK + if (fp->cltbl) + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else +#endif + clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */ + } + if (clst < 2) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) { /* Read maximum contiguous sectors directly */ + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - csect; + if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); +#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ +#if _FS_TINY + if (fp->fs->wflag && fp->fs->winsect - sect < cc) + mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); +#else + if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) + mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); +#endif +#endif + rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + continue; + } +#if !_FS_TINY + if (fp->dsect != sect) { /* Load data sector if not in cache */ +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */ + ABORT(fp->fs, FR_DISK_ERR); + } +#endif + fp->dsect = sect; + } + rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ + if (rcnt > btr) rcnt = btr; +#if _FS_TINY + if (move_window(fp->fs, fp->dsect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ +#else + mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ +#endif + } + + LEAVE_FF(fp->fs, FR_OK); +} + + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Write File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_write ( + FIL *fp, /* Pointer to the file object */ + const void *buff, /* Pointer to the data to be written */ + UINT btw, /* Number of bytes to write */ + UINT *bw /* Pointer to number of bytes written */ +) +{ + FRESULT res; + DWORD clst, sect; + UINT wcnt, cc; + const BYTE *wbuff = (const BYTE*)buff; + BYTE csect; + + + *bw = 0; /* Clear write byte counter */ + + res = validate(fp); /* Check validity */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Aborted file? */ + LEAVE_FF(fp->fs, FR_INT_ERR); + if (!(fp->flag & FA_WRITE)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + if ((DWORD)(fp->fsize + btw) < fp->fsize) btw = 0; /* File size cannot reach 4GB */ + + for ( ; btw; /* Repeat until all data written */ + wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if (!csect) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->sclust; /* Follow from the origin */ + if (clst == 0) /* When no cluster is allocated, */ + fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ + } else { /* Middle or end of the file */ +#if _USE_FASTSEEK + if (fp->cltbl) + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else +#endif + clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */ + } + if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ + if (clst == 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } +#if _FS_TINY + if (fp->fs->winsect == fp->dsect && sync_window(fp->fs)) /* Write-back sector cache */ + ABORT(fp->fs, FR_DISK_ERR); +#else + if (fp->flag & FA__DIRTY) { /* Write-back sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) { /* Write maximum contiguous sectors directly */ + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - csect; + if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); +#if _FS_TINY + if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); + fp->fs->wflag = 0; + } +#else + if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); + fp->flag &= ~FA__DIRTY; + } +#endif + wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + continue; + } +#if _FS_TINY + if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */ + if (sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR); + fp->fs->winsect = sect; + } +#else + if (fp->dsect != sect) { /* Fill sector cache with file data */ + if (fp->fptr < fp->fsize && + disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + } +#endif + fp->dsect = sect; + } + wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ + if (wcnt > btw) wcnt = btw; +#if _FS_TINY + if (move_window(fp->fs, fp->dsect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ + fp->fs->wflag = 1; +#else + mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ + fp->flag |= FA__DIRTY; +#endif + } + + if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */ + fp->flag |= FA__WRITTEN; /* Set file change flag */ + + LEAVE_FF(fp->fs, FR_OK); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize the File Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_sync ( + FIL *fp /* Pointer to the file object */ +) +{ + FRESULT res; + DWORD tm; + BYTE *dir; + + + res = validate(fp); /* Check validity of the object */ + if (res == FR_OK) { + if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ +#if !_FS_TINY /* Write-back dirty buffer */ + if (fp->flag & FA__DIRTY) { + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + LEAVE_FF(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + /* Update the directory entry */ + res = move_window(fp->fs, fp->dir_sect); + if (res == FR_OK) { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ + ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ + st_clust(dir, fp->sclust); /* Update start cluster */ + tm = get_fattime(); /* Update updated time */ + ST_DWORD(dir+DIR_WrtTime, tm); + ST_WORD(dir+DIR_LstAccDate, 0); + fp->flag &= ~FA__WRITTEN; + fp->fs->wflag = 1; + res = sync_fs(fp->fs); + } + } + } + + LEAVE_FF(fp->fs, res); +} + +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Close File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_close ( + FIL *fp /* Pointer to the file object to be closed */ +) +{ + FRESULT res; + + +#if _FS_READONLY + res = validate(fp); + { +#if _FS_REENTRANT + FATFS *fs = fp->fs; +#endif + if (res == FR_OK) fp->fs = 0; /* Discard file object */ + LEAVE_FF(fs, res); + } +#else + res = f_sync(fp); /* Flush cached data */ +#if _FS_LOCK + if (res == FR_OK) { /* Decrement open counter */ +#if _FS_REENTRANT + FATFS *fs = fp->fs;; + res = validate(fp); + if (res == FR_OK) { + res = dec_lock(fp->lockid); + unlock_fs(fs, FR_OK); + } +#else + res = dec_lock(fp->lockid); +#endif + } +#endif + if (res == FR_OK) fp->fs = 0; /* Discard file object */ + return res; +#endif +} + + + + +/*-----------------------------------------------------------------------*/ +/* Current Drive/Directory Handlings */ +/*-----------------------------------------------------------------------*/ + +#if _FS_RPATH >= 1 + +FRESULT f_chdrive ( + BYTE drv /* Drive number */ +) +{ + if (drv >= _VOLUMES) return FR_INVALID_DRIVE; + + CurrVol = drv; + + return FR_OK; +} + +BYTE f_get_current_drive(void) +{ + return CurrVol; +} + +FRESULT f_chdir ( + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 0); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the path */ + FREE_BUF(); + if (res == FR_OK) { /* Follow completed */ + if (!dj.dir) { + dj.fs->cdir = dj.sclust; /* Start directory itself */ + } else { + if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ + dj.fs->cdir = ld_clust(dj.fs, dj.dir); + else + res = FR_NO_PATH; /* Reached but a file */ + } + } + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + + LEAVE_FF(dj.fs, res); +} + + +#if _FS_RPATH >= 2 +FRESULT f_getcwd ( + TCHAR *buff, /* Pointer to the directory path */ + UINT len /* Size of path */ +) +{ + FRESULT res; + DIR dj; + UINT i, n; + DWORD ccl; + TCHAR *tp; + FILINFO fno; + DEF_NAMEBUF; + + + *buff = 0; + res = chk_mounted((const TCHAR**)&buff, &dj.fs, 0); /* Get current volume */ + if (res == FR_OK) { + INIT_BUF(dj); + i = len; /* Bottom of buffer (dir stack base) */ + dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */ + while ((ccl = dj.sclust) != 0) { /* Repeat while current dir is a sub-dir */ + res = dir_sdi(&dj, 1); /* Get parent dir */ + if (res != FR_OK) break; + res = dir_read(&dj, 0); + if (res != FR_OK) break; + dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent dir */ + res = dir_sdi(&dj, 0); + if (res != FR_OK) break; + do { /* Find the entry links to the child dir */ + res = dir_read(&dj, 0); + if (res != FR_OK) break; + if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ + if (res != FR_OK) break; +#if _USE_LFN + fno.lfname = buff; + fno.lfsize = i; +#endif + get_fileinfo(&dj, &fno); /* Get the dir name and push it to the buffer */ + tp = fno.fname; + if (_USE_LFN && *buff) tp = buff; + for (n = 0; tp[n]; n++) ; + if (i < n + 3) { + res = FR_NOT_ENOUGH_CORE; break; + } + while (n) buff[--i] = tp[--n]; + buff[--i] = '/'; + } + tp = buff; + if (res == FR_OK) { + *tp++ = '0' + CurrVol; /* Put drive number */ + *tp++ = ':'; + if (i == len) { /* Root-dir */ + *tp++ = '/'; + } else { /* Sub-dir */ + do /* Add stacked path str */ + *tp++ = buff[i++]; + while (i < len); + } + } + *tp = 0; + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} +#endif /* _FS_RPATH >= 2 */ +#endif /* _FS_RPATH >= 1 */ + + + +#if _FS_MINIMIZE <= 2 +/*-----------------------------------------------------------------------*/ +/* Seek File R/W Pointer */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_lseek ( + FIL *fp, /* Pointer to the file object */ + DWORD ofs /* File pointer from top of file */ +) +{ + FRESULT res; + + + res = validate(fp); /* Check validity of the object */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Check abort flag */ + LEAVE_FF(fp->fs, FR_INT_ERR); + +#if _USE_FASTSEEK + if (fp->cltbl) { /* Fast seek */ + DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; + + if (ofs == CREATE_LINKMAP) { /* Create CLMT */ + tbl = fp->cltbl; + tlen = *tbl++; ulen = 2; /* Given table size and required table size */ + cl = fp->sclust; /* Top of the chain */ + if (cl) { + do { + /* Get a fragment */ + tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ + do { + pcl = cl; ncl++; + cl = get_fat(fp->fs, cl); + if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); + if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + } while (cl == pcl + 1); + if (ulen <= tlen) { /* Store the length and top of the fragment */ + *tbl++ = ncl; *tbl++ = tcl; + } + } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */ + } + *fp->cltbl = ulen; /* Number of items used */ + if (ulen <= tlen) + *tbl = 0; /* Terminate table */ + else + res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ + + } else { /* Fast seek */ + if (ofs > fp->fsize) /* Clip offset at the file size */ + ofs = fp->fsize; + fp->fptr = ofs; /* Set file pointer */ + if (ofs) { + fp->clust = clmt_clust(fp, ofs - 1); + dsc = clust2sect(fp->fs, fp->clust); + if (!dsc) ABORT(fp->fs, FR_INT_ERR); + dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1); + if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */ +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */ + ABORT(fp->fs, FR_DISK_ERR); +#endif + fp->dsect = dsc; + } + } + } + } else +#endif + + /* Normal Seek */ + { + DWORD clst, bcs, nsect, ifptr; + + if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ +#if !_FS_READONLY + && !(fp->flag & FA_WRITE) +#endif + ) ofs = fp->fsize; + + ifptr = fp->fptr; + fp->fptr = nsect = 0; + if (ofs) { + bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ + if (ifptr > 0 && + (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ + fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->clust; + } else { /* When seek to back cluster, */ + clst = fp->sclust; /* start from the first cluster */ +#if !_FS_READONLY + if (clst == 0) { /* If no cluster chain, create a new chain */ + clst = create_chain(fp->fs, 0); + if (clst == 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->sclust = clst; + } +#endif + fp->clust = clst; + } + if (clst != 0) { + while (ofs > bcs) { /* Cluster following loop */ +#if !_FS_READONLY + if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ + clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */ + if (clst == 0) { /* When disk gets full, clip file size */ + ofs = bcs; break; + } + } else +#endif + clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); + fp->clust = clst; + fp->fptr += bcs; + ofs -= bcs; + } + fp->fptr += ofs; + if (ofs % SS(fp->fs)) { + nsect = clust2sect(fp->fs, clst); /* Current sector */ + if (!nsect) ABORT(fp->fs, FR_INT_ERR); + nsect += ofs / SS(fp->fs); + } + } + } + if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */ +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */ + ABORT(fp->fs, FR_DISK_ERR); +#endif + fp->dsect = nsect; + } +#if !_FS_READONLY + if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */ + fp->fsize = fp->fptr; + fp->flag |= FA__WRITTEN; + } +#endif + } + + LEAVE_FF(fp->fs, res); +} + + + +#if _FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Create a Directory Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_opendir ( + DIR *dj, /* Pointer to directory object to create */ + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + FATFS *fs; + DEF_NAMEBUF; + + + if (!dj) return FR_INVALID_OBJECT; + + res = chk_mounted(&path, &dj->fs, 0); + fs = dj->fs; + if (res == FR_OK) { + INIT_BUF(*dj); + res = follow_path(dj, path); /* Follow the path to the directory */ + FREE_BUF(); + if (res == FR_OK) { /* Follow completed */ + if (dj->dir) { /* It is not the root dir */ + if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ + dj->sclust = ld_clust(fs, dj->dir); + } else { /* The object is not a directory */ + res = FR_NO_PATH; + } + } + if (res == FR_OK) { + dj->id = fs->id; + res = dir_sdi(dj, 0); /* Rewind dir */ + } + } + if (res == FR_NO_FILE) res = FR_NO_PATH; + if (res != FR_OK) dj->fs = 0; /* Invalidate the dir object if function faild */ + } else { + dj->fs = 0; + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read Directory Entry in Sequence */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_readdir ( + DIR *dj, /* Pointer to the open directory object */ + FILINFO *fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DEF_NAMEBUF; + + + res = validate(dj); /* Check validity of the object */ + if (res == FR_OK) { + if (!fno) { + res = dir_sdi(dj, 0); /* Rewind the directory object */ + } else { + INIT_BUF(*dj); + res = dir_read(dj, 0); /* Read an item */ + if (res == FR_NO_FILE) { /* Reached end of dir */ + dj->sect = 0; + res = FR_OK; + } + if (res == FR_OK) { /* A valid entry is found */ + get_fileinfo(dj, fno); /* Get the object information */ + res = dir_next(dj, 0); /* Increment index for next */ + if (res == FR_NO_FILE) { + dj->sect = 0; + res = FR_OK; + } + } + FREE_BUF(); + } + } + + LEAVE_FF(dj->fs, res); +} + + + +#if _FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Get File Status */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_stat ( + const TCHAR *path, /* Pointer to the file path */ + FILINFO *fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DIR dj; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 0); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.dir) /* Found an object */ + get_fileinfo(&dj, fno); + else /* It is root dir */ + res = FR_INVALID_NAME; + } + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Get Number of Free Clusters */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getfree ( + const TCHAR *path, /* Path name of the logical drive number */ + DWORD *nclst, /* Pointer to a variable to return number of free clusters */ + FATFS **fatfs /* Pointer to return pointer to corresponding file system object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD n, clst, sect, stat; + UINT i; + BYTE fat, *p; + + + /* Get drive number */ + res = chk_mounted(&path, fatfs, 0); + fs = *fatfs; + if (res == FR_OK) { + /* If free_clust is valid, return it without full cluster scan */ + if (fs->free_clust <= fs->n_fatent - 2) { + *nclst = fs->free_clust; + } else { + /* Get number of free clusters */ + fat = fs->fs_type; + n = 0; + if (fat == FS_FAT12) { + clst = 2; + do { + stat = get_fat(fs, clst); + if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (stat == 1) { res = FR_INT_ERR; break; } + if (stat == 0) n++; + } while (++clst < fs->n_fatent); + } else { + clst = fs->n_fatent; + sect = fs->fatbase; + i = 0; p = 0; + do { + if (!i) { + res = move_window(fs, sect++); + if (res != FR_OK) break; + p = fs->win; + i = SS(fs); + } + if (fat == FS_FAT16) { + if (LD_WORD(p) == 0) n++; + p += 2; i -= 2; + } else { + if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; + p += 4; i -= 4; + } + } while (--clst); + } + fs->free_clust = n; + if (fat == FS_FAT32) fs->fsi_flag = 1; + *nclst = n; + } + } + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Truncate File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_truncate ( + FIL *fp /* Pointer to the file object */ +) +{ + FRESULT res; + DWORD ncl; + + + res = validate(fp); /* Check validity of the object */ + if (res == FR_OK) { + if (fp->flag & FA__ERROR) { /* Check abort flag */ + res = FR_INT_ERR; + } else { + if (!(fp->flag & FA_WRITE)) /* Check access mode */ + res = FR_DENIED; + } + } + if (res == FR_OK) { + if (fp->fsize > fp->fptr) { + fp->fsize = fp->fptr; /* Set file size to current R/W point */ + fp->flag |= FA__WRITTEN; + if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ + res = remove_chain(fp->fs, fp->sclust); + fp->sclust = 0; + } else { /* When truncate a part of the file, remove remaining clusters */ + ncl = get_fat(fp->fs, fp->clust); + res = FR_OK; + if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (ncl == 1) res = FR_INT_ERR; + if (res == FR_OK && ncl < fp->fs->n_fatent) { + res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF); + if (res == FR_OK) res = remove_chain(fp->fs, ncl); + } + } + } + if (res != FR_OK) fp->flag |= FA__ERROR; + } + + LEAVE_FF(fp->fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Delete a File or Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_unlink ( + const TCHAR *path /* Pointer to the file or directory path */ +) +{ + FRESULT res; + DIR dj, sdj; + BYTE *dir; + DWORD dclst; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; /* Cannot remove dot entry */ +#if _FS_LOCK + if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ +#endif + if (res == FR_OK) { /* The object is accessible */ + dir = dj.dir; + if (!dir) { + res = FR_INVALID_NAME; /* Cannot remove the start directory */ + } else { + if (dir[DIR_Attr] & AM_RDO) + res = FR_DENIED; /* Cannot remove R/O object */ + } + dclst = ld_clust(dj.fs, dir); + if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ + if (dclst < 2) { + res = FR_INT_ERR; + } else { + mem_cpy(&sdj, &dj, sizeof (DIR)); /* Check if the sub-dir is empty or not */ + sdj.sclust = dclst; + res = dir_sdi(&sdj, 2); /* Exclude dot entries */ + if (res == FR_OK) { + res = dir_read(&sdj, 0); /* Read an item */ + if (res == FR_OK /* Not empty dir */ +#if _FS_RPATH + || dclst == dj.fs->cdir /* Current dir */ +#endif + ) res = FR_DENIED; + if (res == FR_NO_FILE) res = FR_OK; /* Empty */ + } + } + } + if (res == FR_OK) { + res = dir_remove(&dj); /* Remove the directory entry */ + if (res == FR_OK) { + if (dclst) /* Remove the cluster chain if exist */ + res = remove_chain(dj.fs, dclst); + if (res == FR_OK) res = sync_fs(dj.fs); + } + } + } + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create a Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkdir ( + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir, n; + DWORD dsc, dcl, pcl, tm = get_fattime(); + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ + if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_NO_FILE) { /* Can create a new directory */ + dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */ + res = FR_OK; + if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ + if (dcl == 1) res = FR_INT_ERR; + if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) /* Flush FAT */ + res = sync_window(dj.fs); + if (res == FR_OK) { /* Initialize the new directory table */ + dsc = clust2sect(dj.fs, dcl); + dir = dj.fs->win; + mem_set(dir, 0, SS(dj.fs)); + mem_set(dir+DIR_Name, ' ', 11); /* Create "." entry */ + dir[DIR_Name] = '.'; + dir[DIR_Attr] = AM_DIR; + ST_DWORD(dir+DIR_WrtTime, tm); + st_clust(dir, dcl); + mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */ + dir[33] = '.'; pcl = dj.sclust; + if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) + pcl = 0; + st_clust(dir+SZ_DIR, pcl); + for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ + dj.fs->winsect = dsc++; + dj.fs->wflag = 1; + res = sync_window(dj.fs); + if (res != FR_OK) break; + mem_set(dir, 0, SS(dj.fs)); + } + } + if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ + if (res != FR_OK) { + remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ + } else { + dir = dj.dir; + dir[DIR_Attr] = AM_DIR; /* Attribute */ + ST_DWORD(dir+DIR_WrtTime, tm); /* Created time */ + st_clust(dir, dcl); /* Table start cluster */ + dj.fs->wflag = 1; + res = sync_fs(dj.fs); + } + } + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Attribute */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chmod ( + const TCHAR *path, /* Pointer to the file path */ + BYTE value, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + FREE_BUF(); + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_OK) { + dir = dj.dir; + if (!dir) { /* Is it a root directory? */ + res = FR_INVALID_NAME; + } else { /* File or sub directory */ + mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ + dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + dj.fs->wflag = 1; + res = sync_fs(dj.fs); + } + } + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Timestamp */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_utime ( + const TCHAR *path, /* Pointer to the file/directory name */ + const FILINFO *fno /* Pointer to the time stamp to be set */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + FREE_BUF(); + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_OK) { + dir = dj.dir; + if (!dir) { /* Root directory */ + res = FR_INVALID_NAME; + } else { /* File or sub-directory */ + ST_WORD(dir+DIR_WrtTime, fno->ftime); + ST_WORD(dir+DIR_WrtDate, fno->fdate); + dj.fs->wflag = 1; + res = sync_fs(dj.fs); + } + } + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Rename File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_rename ( + const TCHAR *path_old, /* Pointer to the old name */ + const TCHAR *path_new /* Pointer to the new name */ +) +{ + FRESULT res; + DIR djo, djn; + BYTE buf[21], *dir; + DWORD dw; + DEF_NAMEBUF; + + + res = chk_mounted(&path_old, &djo.fs, 1); + if (res == FR_OK) { + djn.fs = djo.fs; + INIT_BUF(djo); + res = follow_path(&djo, path_old); /* Check old object */ + if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; +#if _FS_LOCK + if (res == FR_OK) res = chk_lock(&djo, 2); +#endif + if (res == FR_OK) { /* Old object is found */ + if (!djo.dir) { /* Is root dir? */ + res = FR_NO_FILE; + } else { + mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ + mem_cpy(&djn, &djo, sizeof (DIR)); /* Check new object */ + res = follow_path(&djn, path_new); + if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ + if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ +/* Start critical section that any interruption can cause a cross-link */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + dir = djn.dir; /* Copy object information except for name */ + mem_cpy(dir+13, buf+2, 19); + dir[DIR_Attr] = buf[0] | AM_ARC; + djo.fs->wflag = 1; + if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ + dw = clust2sect(djo.fs, ld_clust(djo.fs, dir)); + if (!dw) { + res = FR_INT_ERR; + } else { + res = move_window(djo.fs, dw); + dir = djo.fs->win+SZ_DIR; /* .. entry */ + if (res == FR_OK && dir[1] == '.') { + dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust; + st_clust(dir, dw); + djo.fs->wflag = 1; + } + } + } + if (res == FR_OK) { + res = dir_remove(&djo); /* Remove old entry */ + if (res == FR_OK) + res = sync_fs(djo.fs); + } + } +/* End critical section */ + } + } + } + FREE_BUF(); + } + + LEAVE_FF(djo.fs, res); +} + +#endif /* !_FS_READONLY */ +#endif /* _FS_MINIMIZE == 0 */ +#endif /* _FS_MINIMIZE <= 1 */ +#endif /* _FS_MINIMIZE <= 2 */ + + + +#if _USE_LABEL +/*-----------------------------------------------------------------------*/ +/* Get volume label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getlabel ( + const TCHAR* path, /* Path name of the logical drive number */ + TCHAR* label, /* Pointer to a buffer to return the volume label */ + DWORD* sn /* Pointer to a variable to return the volume serial number */ +) +{ + FRESULT res; + DIR dj; + UINT i, j; + + + /* Get logical drive */ + res = chk_mounted(&path, &dj.fs, 0); + + /* Get volume label */ + if (res == FR_OK && label) { + dj.sclust = 0; /* Open root dir */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = dir_read(&dj, 1); /* Get an entry with AM_VOL */ + if (res == FR_OK) { /* A volume label is exist */ +#if _LFN_UNICODE + WCHAR w; + i = j = 0; + do { + w = (i < 11) ? dj.dir[i++] : ' '; + if (IsDBCS1(w) && i < 11 && IsDBCS2(dj.dir[i])) + w = (w << 8) | dj.dir[i++]; + label[j++] = ff_convert(w, 1); + } while (j < 11); +#else + mem_cpy(label, dj.dir, 11); +#endif + j = 11; + do { + label[j] = 0; + if (!j) break; + } while (label[--j] == ' '); + } + if (res == FR_NO_FILE) { /* No label, return nul string */ + label[0] = 0; + res = FR_OK; + } + } + } + + /* Get volume serial number */ + if (res == FR_OK && sn) { + res = move_window(dj.fs, dj.fs->volbase); + if (res == FR_OK) { + i = dj.fs->fs_type == FS_FAT32 ? BS_VolID32 : BS_VolID; + *sn = LD_DWORD(&dj.fs->win[i]); + } + } + + LEAVE_FF(dj.fs, res); +} + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Set volume label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setlabel ( + const TCHAR* label /* Pointer to the volume label to set */ +) +{ + FRESULT res; + DIR dj; + BYTE vn[11]; + UINT i, j, sl; + WCHAR w; + DWORD tm; + + + /* Get logical drive */ + res = chk_mounted(&label, &dj.fs, 1); + if (res) LEAVE_FF(dj.fs, res); + + /* Create a volume label in directory form */ + vn[0] = 0; + for (sl = 0; label[sl]; sl++) ; /* Get name length */ + for ( ; sl && label[sl-1] == ' '; sl--) ; /* Remove trailing spaces */ + if (sl) { /* Create volume label in directory form */ + i = j = 0; + do { +#if _LFN_UNICODE + w = ff_convert(ff_wtoupper(label[i++]), 0); +#else + w = (BYTE)label[i++]; + if (IsDBCS1(w)) + w = (j < 10 && i < sl && IsDBCS2(label[i])) ? (w << 8) | (BYTE)label[i++] : 0; +#if _USE_LFN + w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0); +#else + if (IsLower(w)) w -= 0x20; /* To upper ASCII chars */ +#ifdef _EXCVT + if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended chars (SBCS cfg) */ +#else + if (!_DF1S && w >= 0x80) w = 0; /* Reject extended chars (ASCII cfg) */ +#endif +#endif +#endif + if (!w || chk_chr("\"*+,.:;<=>\?[]|\x7F", w) || j >= (UINT)((w >= 0x100) ? 10 : 11)) /* Reject invalid chars for volume label */ + LEAVE_FF(dj.fs, FR_INVALID_NAME); + if (w >= 0x100) vn[j++] = (BYTE)(w >> 8); + vn[j++] = (BYTE)w; + } while (i < sl); + while (j < 11) vn[j++] = ' '; + } + + /* Set volume label */ + dj.sclust = 0; /* Open root dir */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = dir_read(&dj, 1); /* Get an entry with AM_VOL */ + if (res == FR_OK) { /* A volume label is found */ + if (vn[0]) { + mem_cpy(dj.dir, vn, 11); /* Change the volume label name */ + tm = get_fattime(); + ST_DWORD(dj.dir+DIR_WrtTime, tm); + } else { + dj.dir[0] = DDE; /* Remove the volume label */ + } + dj.fs->wflag = 1; + res = sync_fs(dj.fs); + } else { /* No volume label is found or error */ + if (res == FR_NO_FILE) { + res = FR_OK; + if (vn[0]) { /* Create volume label as new */ + res = dir_alloc(&dj, 1); /* Allocate an entry for volume label */ + if (res == FR_OK) { + mem_set(dj.dir, 0, SZ_DIR); /* Set volume label */ + mem_cpy(dj.dir, vn, 11); + dj.dir[DIR_Attr] = AM_VOL; + tm = get_fattime(); + ST_DWORD(dj.dir+DIR_WrtTime, tm); + dj.fs->wflag = 1; + res = sync_fs(dj.fs); + } + } + } + } + } + + LEAVE_FF(dj.fs, res); +} + +#endif /* !_FS_READONLY */ +#endif /* _USE_LABEL */ + + + +/*-----------------------------------------------------------------------*/ +/* Forward data to the stream directly (available on only tiny cfg) */ +/*-----------------------------------------------------------------------*/ +#if _USE_FORWARD && _FS_TINY + +FRESULT f_forward ( + FIL *fp, /* Pointer to the file object */ + UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ + UINT btf, /* Number of bytes to forward */ + UINT *bf /* Pointer to number of bytes forwarded */ +) +{ + FRESULT res; + DWORD remain, clst, sect; + UINT rcnt; + BYTE csect; + + + *bf = 0; /* Clear transfer byte counter */ + + res = validate(fp); /* Check validity of the object */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Check error flag */ + LEAVE_FF(fp->fs, FR_INT_ERR); + if (!(fp->flag & FA_READ)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + + remain = fp->fsize - fp->fptr; + if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ + + for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ + fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + if (!csect) { /* On the cluster boundary? */ + clst = (fp->fptr == 0) ? /* On the top of the file? */ + fp->sclust : get_fat(fp->fs, fp->clust); + if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + } + sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + if (move_window(fp->fs, sect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + fp->dsect = sect; + rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */ + if (rcnt > btf) rcnt = btf; + rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt); + if (!rcnt) ABORT(fp->fs, FR_INT_ERR); + } + + LEAVE_FF(fp->fs, FR_OK); +} +#endif /* _USE_FORWARD */ + + + +#if _USE_MKFS && !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Create File System on the Drive */ +/*-----------------------------------------------------------------------*/ +#define N_ROOTDIR 512 /* Number of root dir entries for FAT12/16 */ +#define N_FATS 1 /* Number of FAT copies (1 or 2) */ + + +FRESULT f_mkfs ( + BYTE vol, /* Logical drive number */ + BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ + UINT au /* Allocation unit size [bytes] */ +) +{ + static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; + static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; + BYTE fmt, md, sys, *tbl, pdrv, part; + DWORD n_clst, vs, n, wsect; + UINT i; + DWORD b_vol, b_fat, b_dir, b_data; /* LBA */ + DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ + FATFS *fs; + DSTATUS stat; + + + /* Check mounted drive and clear work area */ + if (vol >= _VOLUMES) return FR_INVALID_DRIVE; + if (sfd > 1) return FR_INVALID_PARAMETER; + if (au & (au - 1)) return FR_INVALID_PARAMETER; + fs = FatFs[vol]; + if (!fs) return FR_NOT_ENABLED; + fs->fs_type = 0; + pdrv = LD2PD(vol); /* Physical drive */ + part = LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/ + + /* Get disk statics */ + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; +#if _MAX_SS != 512 /* Get disk sector size */ + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) + return FR_DISK_ERR; +#endif + if (_MULTI_PARTITION && part) { + /* Get partition information from partition table in the MBR */ + if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; + if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */ + b_vol = LD_DWORD(tbl+8); /* Volume start sector */ + n_vol = LD_DWORD(tbl+12); /* Volume size */ + } else { + /* Create a partition in this function */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) + return FR_DISK_ERR; + b_vol = (sfd) ? 0 : 63; /* Volume start sector */ + n_vol -= b_vol; /* Volume size */ + } + + if (!au) { /* AU auto selection */ + vs = n_vol / (2000 / (SS(fs) / 512)); + for (i = 0; vs < vst[i]; i++) ; + au = cst[i]; + } + au /= SS(fs); /* Number of sectors per cluster */ + if (au == 0) au = 1; + if (au > 128) au = 128; + + /* Pre-compute number of clusters and FAT sub-type */ + n_clst = n_vol / au; + fmt = FS_FAT12; + if (n_clst >= MIN_FAT16) fmt = FS_FAT16; + if (n_clst >= MIN_FAT32) fmt = FS_FAT32; + + /* Determine offset and size of FAT structure */ + if (fmt == FS_FAT32) { + n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); + n_rsv = 32; + n_dir = 0; + } else { + n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; + n_fat = (n_fat + SS(fs) - 1) / SS(fs); + n_rsv = 1; + n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs); + } + b_fat = b_vol + n_rsv; /* FAT area start sector */ + b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ + b_data = b_dir + n_dir; /* Data area start sector */ + if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ + + /* Align data start sector to erase block boundary (for flash memory media) */ + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; + n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ + n = (n - b_data) / N_FATS; + if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ + n_rsv += n; + b_fat += n; + } else { /* FAT12/16: Expand FAT size */ + n_fat += n; + } + + /* Determine number of clusters and final check of validity of the FAT sub-type */ + n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; + if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) + || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) + return FR_MKFS_ABORTED; + + switch (fmt) { /* Determine system ID for partition table */ + case FS_FAT12: sys = 0x01; break; + case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break; + default: sys = 0x0C; + } + + if (_MULTI_PARTITION && part) { + /* Update system ID in the partition table */ + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + tbl[4] = sys; + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; + md = 0xF8; + } else { + if (sfd) { /* No partition table (SFD) */ + md = 0xF0; + } else { /* Create partition table (FDISK) */ + mem_set(fs->win, 0, SS(fs)); + tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */ + tbl[1] = 1; /* Partition start head */ + tbl[2] = 1; /* Partition start sector */ + tbl[3] = 0; /* Partition start cylinder */ + tbl[4] = sys; /* System type */ + tbl[5] = 254; /* Partition end head */ + n = (b_vol + n_vol) / 63 / 255; + tbl[6] = (BYTE)((n >> 2) | 63); /* Partition end sector */ + tbl[7] = (BYTE)n; /* End cylinder */ + ST_DWORD(tbl+8, 63); /* Partition start in LBA */ + ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ + ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */ + return FR_DISK_ERR; + md = 0xF8; + } + } + + /* Create BPB in the VBR */ + tbl = fs->win; /* Clear sector */ + mem_set(tbl, 0, SS(fs)); + mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */ + i = SS(fs); /* Sector size */ + ST_WORD(tbl+BPB_BytsPerSec, i); + tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ + ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ + tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ + i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ + ST_WORD(tbl+BPB_RootEntCnt, i); + if (n_vol < 0x10000) { /* Number of total sectors */ + ST_WORD(tbl+BPB_TotSec16, n_vol); + } else { + ST_DWORD(tbl+BPB_TotSec32, n_vol); + } + tbl[BPB_Media] = md; /* Media descriptor */ + ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ + ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ + ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ + n = get_fattime(); /* Use current time as VSN */ + if (fmt == FS_FAT32) { + ST_DWORD(tbl+BS_VolID32, n); /* VSN */ + ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ + ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ + ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */ + ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ + tbl[BS_DrvNum32] = 0x80; /* Drive number */ + tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ + } else { + ST_DWORD(tbl+BS_VolID, n); /* VSN */ + ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ + tbl[BS_DrvNum] = 0x80; /* Drive number */ + tbl[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + } + ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ + if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */ + return FR_DISK_ERR; + if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */ + disk_write(pdrv, tbl, b_vol + 6, 1); + + /* Initialize FAT area */ + wsect = b_fat; + for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */ + mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ + n = md; /* Media descriptor byte */ + if (fmt != FS_FAT32) { + n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; + ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */ + } else { + n |= 0xFFFFFF00; + ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */ + ST_DWORD(tbl+4, 0xFFFFFFFF); + ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ + } + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) + return FR_DISK_ERR; + mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ + for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) + return FR_DISK_ERR; + } + } + + /* Initialize root directory */ + i = (fmt == FS_FAT32) ? au : n_dir; + do { + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) + return FR_DISK_ERR; + } while (--i); + +#if _USE_ERASE /* Erase data area if needed */ + { + DWORD eb[2]; + + eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; + disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb); + } +#endif + + /* Create FSInfo if needed */ + if (fmt == FS_FAT32) { + ST_DWORD(tbl+FSI_LeadSig, 0x41615252); + ST_DWORD(tbl+FSI_StrucSig, 0x61417272); + ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */ + ST_WORD(tbl+BS_55AA, 0xAA55); + disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ + disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ + } + + return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; +} + + +#if _MULTI_PARTITION +/*-----------------------------------------------------------------------*/ +/* Divide Physical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const DWORD szt[], /* Pointer to the size table for each partitions */ + void* work /* Pointer to the working buffer */ +) +{ + UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; + DSTATUS stat; + DWORD sz_disk, sz_part, s_part; + + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; + + /* Determine CHS in the table regardless of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + if (n == 256) n--; + e_hd = n - 1; + sz_cyl = 63 * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + mem_set(buf, 0, _MAX_SS); + p = buf + MBR_Table; b_cyl = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) { + p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; + if (!p_cyl) continue; + s_part = (DWORD)sz_cyl * b_cyl; + sz_part = (DWORD)sz_cyl * p_cyl; + if (i == 0) { /* Exclude first track of cylinder 0 */ + s_hd = 1; + s_part += 63; sz_part -= 63; + } else { + s_hd = 0; + } + e_cyl = b_cyl + p_cyl - 1; + if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x06; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + ST_DWORD(p + 8, s_part); /* Start sector in LBA */ + ST_DWORD(p + 12, sz_part); /* Partition size */ + + /* Next partition */ + b_cyl += p_cyl; + } + ST_WORD(p, 0xAA55); + + /* Write it to the MBR */ + return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK; +} + + +#endif /* _MULTI_PARTITION */ +#endif /* _USE_MKFS && !_FS_READONLY */ + + + + +#if _USE_STRFUNC +/*-----------------------------------------------------------------------*/ +/* Get a string from the file */ +/*-----------------------------------------------------------------------*/ + +TCHAR* f_gets ( + TCHAR* buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (characters) */ + FIL* fp /* Pointer to the file object */ +) +{ + int n = 0; + TCHAR c, *p = buff; + BYTE s[2]; + UINT rc; + + + while (n < len - 1) { /* Read bytes until buffer gets filled */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; /* Break on EOF or error */ + c = s[0]; +#if _LFN_UNICODE /* Read a character in UTF-8 encoding */ + if (c >= 0x80) { + if (c < 0xC0) continue; /* Skip stray trailer */ + if (c < 0xE0) { /* Two-byte sequence */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = ((c & 0x1F) << 6) | (s[0] & 0x3F); + if (c < 0x80) c = '?'; + } else { + if (c < 0xF0) { /* Three-byte sequence */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F); + if (c < 0x800) c = '?'; + } else { /* Reject four-byte sequence */ + c = '?'; + } + } + } +#endif +#if _USE_STRFUNC >= 2 + if (c == '\r') continue; /* Strip '\r' */ +#endif + *p++ = c; + n++; + if (c == '\n') break; /* Break on EOL */ + } + *p = 0; + return n ? buff : 0; /* When no data read (eof or error), return with error. */ +} + + + +#if !_FS_READONLY +#include +/*-----------------------------------------------------------------------*/ +/* Put a character to the file */ +/*-----------------------------------------------------------------------*/ + +int f_putc ( + TCHAR c, /* A character to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + UINT bw, btw; + BYTE s[3]; + + +#if _USE_STRFUNC >= 2 + if (c == '\n') f_putc ('\r', fp); /* LF -> CRLF conversion */ +#endif + +#if _LFN_UNICODE /* Write the character in UTF-8 encoding */ + if (c < 0x80) { /* 7-bit */ + s[0] = (BYTE)c; + btw = 1; + } else { + if (c < 0x800) { /* 11-bit */ + s[0] = (BYTE)(0xC0 | (c >> 6)); + s[1] = (BYTE)(0x80 | (c & 0x3F)); + btw = 2; + } else { /* 16-bit */ + s[0] = (BYTE)(0xE0 | (c >> 12)); + s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F)); + s[2] = (BYTE)(0x80 | (c & 0x3F)); + btw = 3; + } + } +#else /* Write the character without conversion */ + s[0] = (BYTE)c; + btw = 1; +#endif + f_write(fp, s, btw, &bw); /* Write the char to the file */ + return (bw == btw) ? 1 : EOF; /* Return the result */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a string to the file */ +/*-----------------------------------------------------------------------*/ + +int f_puts ( + const TCHAR* str, /* Pointer to the string to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + int n; + + + for (n = 0; *str; str++, n++) { + if (f_putc(*str, fp) == EOF) return EOF; + } + return n; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a formatted string to the file */ +/*-----------------------------------------------------------------------*/ + +int f_printf ( + FIL* fp, /* Pointer to the file object */ + const TCHAR* str, /* Pointer to the format string */ + ... /* Optional arguments... */ +) +{ + va_list arp; + BYTE f, r; + UINT i, j, w; + ULONG v; + TCHAR c, d, s[16], *p; + int res, chc, cc; + + + va_start(arp, str); + + for (cc = res = 0; cc != EOF; res += cc) { + c = *str++; + if (c == 0) break; /* End of string */ + if (c != '%') { /* Non escape character */ + cc = f_putc(c, fp); + if (cc != EOF) cc = 1; + continue; + } + w = f = 0; + c = *str++; + if (c == '0') { /* Flag: '0' padding */ + f = 1; c = *str++; + } else { + if (c == '-') { /* Flag: left justified */ + f = 2; c = *str++; + } + } + while (IsDigit(c)) { /* Precision */ + w = w * 10 + c - '0'; + c = *str++; + } + if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ + f |= 4; c = *str++; + } + if (!c) break; + d = c; + if (IsLower(d)) d -= 0x20; + switch (d) { /* Type is... */ + case 'S' : /* String */ + p = va_arg(arp, TCHAR*); + for (j = 0; p[j]; j++) ; + chc = 0; + if (!(f & 2)) { + while (j++ < w) chc += (cc = f_putc(' ', fp)); + } + chc += (cc = f_puts(p, fp)); + while (j++ < w) chc += (cc = f_putc(' ', fp)); + if (cc != EOF) cc = chc; + continue; + case 'C' : /* Character */ + cc = f_putc((TCHAR)va_arg(arp, int), fp); continue; + case 'B' : /* Binary */ + r = 2; break; + case 'O' : /* Octal */ + r = 8; break; + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + case 'X' : /* Hexdecimal */ + r = 16; break; + default: /* Unknown type (pass-through) */ + cc = f_putc(c, fp); continue; + } + + /* Get an argument and put it in numeral */ + v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) { + v = 0 - v; + f |= 8; + } + i = 0; + do { + d = (TCHAR)(v % r); v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; + s[i++] = d + '0'; + } while (v && i < sizeof s / sizeof s[0]); + if (f & 8) s[i++] = '-'; + j = i; d = (f & 1) ? '0' : ' '; + chc = 0; + while (!(f & 2) && j++ < w) chc += (cc = f_putc(d, fp)); + do chc += (cc = f_putc(s[--i], fp)); while(i); + while (j++ < w) chc += (cc = f_putc(' ', fp)); + if (cc != EOF) cc = chc; + } + + va_end(arp); + return (cc == EOF) ? cc : res; +} + +#endif /* !_FS_READONLY */ +#endif /* _USE_STRFUNC */ + +#endif // CFG_TUH_MSC diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h new file mode 100644 index 000000000..5c2a611ae --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h @@ -0,0 +1,342 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module include file R0.09b (C)ChaN, 2013 +/----------------------------------------------------------------------------/ +/ FatFs module is a generic FAT file system module for small embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2013, ChaN, all right reserved. +/ +/ * The FatFs module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/----------------------------------------------------------------------------*/ + +#ifndef _FATFS +#define _FATFS 82786 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" /* Basic integer types */ +#include "ffconf.h" /* FatFs configuration options */ +#include "tusb_config.h" + +#if _FATFS != _FFCONF +#error Wrong configuration file (ffconf.h). +#endif + + + +/* Definitions of volume management */ + +#if _MULTI_PARTITION /* Multiple partition configuration */ +typedef struct { + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ +} PARTITION; +extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ +#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ +#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ + +#else /* Single partition configuration */ +#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ +#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */ + +#endif + + + +/* Type of path name strings on FatFs API */ + +#if _LFN_UNICODE /* Unicode string */ +#if !_USE_LFN +#error _LFN_UNICODE must be 0 in non-LFN cfg. +#endif +#ifndef _INC_TCHAR +typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#endif + +#else /* ANSI/OEM string */ +#ifndef _INC_TCHAR +typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif + +#endif + + + +/* File system object structure (FATFS) */ + +typedef struct { + BYTE fs_type; /* FAT sub-type (0:Not mounted) */ + BYTE drv; /* Physical drive number */ + BYTE csize; /* Sectors per cluster (1,2,4...128) */ + BYTE n_fats; /* Number of FAT copies (1,2) */ + BYTE wflag; /* win[] dirty flag (1:must be written back) */ + BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ + WORD id; /* File system mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ +#if _MAX_SS != 512 + WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ +#endif +#if _FS_REENTRANT + _SYNC_t sobj; /* Identifier of sync object */ +#endif +#if !_FS_READONLY + DWORD last_clust; /* Last allocated cluster */ + DWORD free_clust; /* Number of free clusters */ + DWORD fsi_sector; /* fsinfo sector (FAT32) */ +#endif +#if _FS_RPATH + DWORD cdir; /* Current directory start cluster (0:root) */ +#endif + DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ + DWORD fsize; /* Sectors per FAT */ + DWORD volbase; /* Volume start sector */ + DWORD fatbase; /* FAT start sector */ + DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ + DWORD database; /* Data start sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ +} FATFS; + + + +/* File object structure (FIL) */ + +typedef struct { + FATFS* fs; /* Pointer to the related file system object (**do not change order**) */ + WORD id; /* Owner file system mount ID (**do not change order**) */ + BYTE flag; /* File status flags */ + BYTE pad1; + DWORD fptr; /* File read/write pointer (0ed on file open) */ + DWORD fsize; /* File size */ + DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */ + DWORD clust; /* Current cluster of fpter */ + DWORD dsect; /* Current data sector of fpter */ +#if !_FS_READONLY + DWORD dir_sect; /* Sector containing the directory entry */ + BYTE* dir_ptr; /* Pointer to the directory entry in the window */ +#endif +#if _USE_FASTSEEK + DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ +#endif +#if _FS_LOCK + UINT lockid; /* File lock ID (index of file semaphore table Files[]) */ +#endif +#if !_FS_TINY + BYTE buf[_MAX_SS]; /* File data read/write buffer */ +#endif +} FIL; + + + +/* Directory object structure (DIR) */ + +typedef struct { + FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */ + WORD id; /* Owner file system mount ID (**do not change order**) */ + WORD index; /* Current read/write index number */ + DWORD sclust; /* Table start cluster (0:Root dir) */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector */ + BYTE* dir; /* Pointer to the current SFN entry in the win[] */ + BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ +#if _USE_LFN + WCHAR* lfn; /* Pointer to the LFN working buffer */ + WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ +#endif +} DIR; + + + +/* File status structure (FILINFO) */ + +typedef struct { + DWORD fsize; /* File size */ + WORD fdate; /* Last modified date */ + WORD ftime; /* Last modified time */ + BYTE fattrib; /* Attribute */ + TCHAR fname[13]; /* Short file name (8.3 format) */ +#if _USE_LFN + TCHAR* lfname; /* Pointer to the LFN buffer */ + UINT lfsize; /* Size of LFN buffer in TCHAR */ +#endif +} FILINFO; + + + +/* File function return code (FRESULT) */ + +typedef enum { + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Access denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ +} FRESULT; + + + +/*--------------------------------------------------------------*/ +/* FatFs module application interface */ + +FRESULT f_mount (BYTE vol, FATFS* fs); /* Mount/Unmount a logical drive */ +FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ +FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */ +FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */ +FRESULT f_close (FIL* fp); /* Close an open file object */ +FRESULT f_opendir (DIR* dj, const TCHAR* path); /* Open an existing directory */ +FRESULT f_readdir (DIR* dj, FILINFO* fno); /* Read a directory item */ +FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ +FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */ +FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ +FRESULT f_truncate (FIL* fp); /* Truncate file */ +FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */ +FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ +FRESULT f_mkdir (const TCHAR* path); /* Create a new directory */ +FRESULT f_chmod (const TCHAR* path, BYTE value, BYTE mask); /* Change attribute of the file/dir */ +FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */ +FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ +FRESULT f_chdrive (BYTE drv); /* Change current drive */ +BYTE f_get_current_drive(void); +FRESULT f_chdir (const TCHAR* path); /* Change current directory */ +FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ +FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* sn); /* Get volume label */ +FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ +FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ +FRESULT f_mkfs (BYTE vol, BYTE sfd, UINT au); /* Create a file system on the drive */ +FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */ +int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ +int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ +int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ +TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ + +#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) +#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->fsize) + +#ifndef EOF +#define EOF (-1) +#endif + + + + +/*--------------------------------------------------------------*/ +/* Additional user defined functions */ + +/* RTC function */ +#if !_FS_READONLY +DWORD get_fattime (void); +#endif + +/* Unicode support functions */ +#if _USE_LFN /* Unicode - OEM code conversion */ +WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ +WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */ +#if _USE_LFN == 3 /* Memory functions */ +void* ff_memalloc (UINT msize); /* Allocate memory block */ +void ff_memfree (void* mblock); /* Free memory block */ +#endif +#endif + +/* Sync functions */ +#if _FS_REENTRANT +int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */ +int ff_req_grant (_SYNC_t sobj); /* Lock sync object */ +void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */ +int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */ +#endif + + + + +/*--------------------------------------------------------------*/ +/* Flags and offset address */ + + +/* File access control and file status flags (FIL.flag) */ + +#define FA_READ 0x01 +#define FA_OPEN_EXISTING 0x00 +#define FA__ERROR 0x80 + +#if !_FS_READONLY +#define FA_WRITE 0x02 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA__WRITTEN 0x20 +#define FA__DIRTY 0x40 +#endif + + +/* FAT sub type (FATFS.fs_type) */ + +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 + + +/* File attribute bits for directory entry */ + +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ +#define AM_MASK 0x3F /* Mask of defined bits */ + + +/* Fast seek feature */ +#define CREATE_LINKMAP 0xFFFFFFFF + + + +/*--------------------------------*/ +/* Multi-byte word access macros */ + +#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) +#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) +#else /* Use byte-by-byte access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) +#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _FATFS */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h new file mode 100644 index 000000000..782057ea4 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module configuration file R0.09b (C)ChaN, 2013 +/----------------------------------------------------------------------------/ +/ +/ CAUTION! Do not forget to make clean the project after any changes to +/ the configuration options. +/ +/----------------------------------------------------------------------------*/ +#ifndef _FFCONF +#define _FFCONF 82786 /* Revision ID */ + +#include "tusb_config.h" + +/*---------------------------------------------------------------------------/ +/ Functions and Buffer Configurations +/----------------------------------------------------------------------------*/ + +#define _FS_TINY 0 /* 0:Normal or 1:Tiny */ +/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system +/ object instead of the sector buffer in the individual file object for file +/ data transfer. This reduces memory consumption 512 bytes each file object. */ + + +#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ +/* Setting _FS_READONLY to 1 defines read only configuration. This removes +/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, +/ f_truncate and useless f_getfree. */ + + +#define _FS_MINIMIZE 0 /* 0 to 3 */ +/* The _FS_MINIMIZE option defines minimization level to remove some functions. +/ +/ 0: Full function. +/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename +/ are removed. +/ 2: f_opendir and f_readdir are removed in addition to 1. +/ 3: f_lseek is removed in addition to 2. */ + + +#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */ +/* To enable string functions, set _USE_STRFUNC to 1 or 2. */ + + +#define _USE_MKFS 0 /* 0:Disable or 1:Enable */ +/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ + + +#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ +/* To enable fast seek feature, set _USE_FASTSEEK to 1. */ + + +#define _USE_LABEL 1 /* 0:Disable or 1:Enable */ +/* To enable volume label functions, set _USE_LAVEL to 1 */ + + +#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ +/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/----------------------------------------------------------------------------*/ + +#define _CODE_PAGE 437 +/* The _CODE_PAGE specifies the OEM code page to be used on the target system. +/ Incorrect setting of the code page can cause a file open failure. +/ +/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows) +/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows) +/ 949 - Korean (DBCS, OEM, Windows) +/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) +/ 1250 - Central Europe (Windows) +/ 1251 - Cyrillic (Windows) +/ 1252 - Latin 1 (Windows) +/ 1253 - Greek (Windows) +/ 1254 - Turkish (Windows) +/ 1255 - Hebrew (Windows) +/ 1256 - Arabic (Windows) +/ 1257 - Baltic (Windows) +/ 1258 - Vietnam (OEM, Windows) +/ 437 - U.S. (OEM) +/ 720 - Arabic (OEM) +/ 737 - Greek (OEM) +/ 775 - Baltic (OEM) +/ 850 - Multilingual Latin 1 (OEM) +/ 858 - Multilingual Latin 1 + Euro (OEM) +/ 852 - Latin 2 (OEM) +/ 855 - Cyrillic (OEM) +/ 866 - Russian (OEM) +/ 857 - Turkish (OEM) +/ 862 - Hebrew (OEM) +/ 874 - Thai (OEM, Windows) +/ 1 - ASCII only (Valid for non LFN cfg.) +*/ + + +#define _USE_LFN 1 /* 0 to 3 */ +#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ +/* The _USE_LFN option switches the LFN support. +/ +/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN, +/ Unicode handling functions ff_convert() and ff_wtoupper() must be added +/ to the project. When enable to use heap, memory control functions +/ ff_memalloc() and ff_memfree() must be added to the project. */ + + +#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ +/* To switch the character code set on FatFs API to Unicode, +/ enable LFN feature and set _LFN_UNICODE to 1. */ + + +#define _FS_RPATH 2 /* 0 to 2 */ +/* The _FS_RPATH option configures relative path feature. +/ +/ 0: Disable relative path feature and remove related functions. +/ 1: Enable relative path. f_chdrive() and f_chdir() are available. +/ 2: f_getcwd() is available in addition to 1. +/ +/ Note that output of the f_readdir fnction is affected by this option. */ + + +/*---------------------------------------------------------------------------/ +/ Physical Drive Configurations +/----------------------------------------------------------------------------*/ + +#define _VOLUMES CFG_TUH_DEVICE_MAX +/* Number of volumes (logical drives) to be used. */ + + +#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ +/* Maximum sector size to be handled. +/ Always set 512 for memory card and hard disk but a larger value may be +/ required for on-board flash memory, floppy disk and optical disk. +/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size +/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */ + + +#define _MULTI_PARTITION 0 /* 0:Single partition, 1:Enable multiple partition */ +/* When set to 0, each volume is bound to the same physical drive number and +/ it can mount only first primaly partition. When it is set to 1, each volume +/ is tied to the partitions listed in VolToPart[]. */ + + +#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ +/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command +/ should be added to the disk_ioctl functio. */ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/----------------------------------------------------------------------------*/ + +#define _WORD_ACCESS 0 /* 0 or 1 */ +/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS +/ option defines which access method is used to the word data on the FAT volume. +/ +/ 0: Byte-by-byte access. +/ 1: Word access. Do not choose this unless following condition is met. +/ +/ When the byte order on the memory is big-endian or address miss-aligned word +/ access results incorrect behavior, the _WORD_ACCESS must be set to 0. +/ If it is not the case, the value can also be set to 1 to improve the +/ performance and code size. +*/ + + +/* A header file that defines sync object types on the O/S, such as +/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */ + +#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ +#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ +#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ + +/* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module. +/ +/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. +/ 1: Enable reentrancy. Also user provided synchronization handlers, +/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj +/ function must be added to the project. */ + + +#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */ +/* To enable file lock control feature, set _FS_LOCK to 1 or greater. + The value defines how many files can be opened simultaneously. */ + + +#endif /* _FFCONFIG */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h new file mode 100644 index 000000000..f34f56d92 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h @@ -0,0 +1,36 @@ +/*-------------------------------------------*/ +/* Integer type definitions for FatFs module */ +/*-------------------------------------------*/ + +#ifndef _INTEGER +#define _INTEGER + +#ifdef _WIN32 /* FatFs development platform */ + +#include +#include + +#else /* Embedded platform */ + +/* These types must be 16-bit, 32-bit or larger integer */ +typedef int INT; +typedef unsigned int UINT; + +/* These types must be 8-bit integer */ +typedef unsigned char UCHAR; +typedef unsigned char BYTE; + +/* These types must be 16-bit integer */ +typedef short SHORT; +typedef unsigned short USHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types must be 32-bit integer */ +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long DWORD; + +#endif + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c new file mode 100644 index 000000000..590739236 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c @@ -0,0 +1,348 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dhserver.h" + +/* DHCP message type */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/* DHCP options */ +enum DHCP_OPTIONS +{ + DHCP_PAD = 0, + DHCP_SUBNETMASK = 1, + DHCP_ROUTER = 3, + DHCP_DNSSERVER = 6, + DHCP_HOSTNAME = 12, + DHCP_DNSDOMAIN = 15, + DHCP_MTU = 26, + DHCP_BROADCAST = 28, + DHCP_PERFORMROUTERDISC = 31, + DHCP_STATICROUTE = 33, + DHCP_NISDOMAIN = 40, + DHCP_NISSERVER = 41, + DHCP_NTPSERVER = 42, + DHCP_VENDOR = 43, + DHCP_IPADDRESS = 50, + DHCP_LEASETIME = 51, + DHCP_OPTIONSOVERLOADED = 52, + DHCP_MESSAGETYPE = 53, + DHCP_SERVERID = 54, + DHCP_PARAMETERREQUESTLIST = 55, + DHCP_MESSAGE = 56, + DHCP_MAXMESSAGESIZE = 57, + DHCP_RENEWALTIME = 58, + DHCP_REBINDTIME = 59, + DHCP_CLASSID = 60, + DHCP_CLIENTID = 61, + DHCP_USERCLASS = 77, /* RFC 3004 */ + DHCP_FQDN = 81, + DHCP_DNSSEARCH = 119, /* RFC 3397 */ + DHCP_CSR = 121, /* RFC 3442 */ + DHCP_MSCSR = 249, /* MS code for RFC 3442 */ + DHCP_END = 255 +}; + +typedef struct +{ + uint8_t dp_op; /* packet opcode type */ + uint8_t dp_htype; /* hardware addr type */ + uint8_t dp_hlen; /* hardware addr length */ + uint8_t dp_hops; /* gateway hops */ + uint32_t dp_xid; /* transaction ID */ + uint16_t dp_secs; /* seconds since boot began */ + uint16_t dp_flags; + uint8_t dp_ciaddr[4]; /* client IP address */ + uint8_t dp_yiaddr[4]; /* 'your' IP address */ + uint8_t dp_siaddr[4]; /* server IP address */ + uint8_t dp_giaddr[4]; /* gateway IP address */ + uint8_t dp_chaddr[16]; /* client hardware address */ + uint8_t dp_legacy[192]; + uint8_t dp_magic[4]; + uint8_t dp_options[275]; /* options area */ +} DHCP_TYPE; + +DHCP_TYPE dhcp_data; +static struct udp_pcb *pcb = NULL; +static const dhcp_config_t *config = NULL; + +char magic_cookie[] = {0x63,0x82,0x53,0x63}; + +static ip4_addr_t get_ip(const uint8_t *pnt) +{ + ip4_addr_t result; + memcpy(&result, pnt, sizeof(result)); + return result; +} + +static void set_ip(uint8_t *pnt, ip4_addr_t value) +{ + memcpy(pnt, &value.addr, sizeof(value.addr)); +} + +static dhcp_entry_t *entry_by_ip(ip4_addr_t ip) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (config->entries[i].addr.addr == ip.addr) + return &config->entries[i]; + return NULL; +} + +static dhcp_entry_t *entry_by_mac(uint8_t *mac) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (memcmp(config->entries[i].mac, mac, 6) == 0) + return &config->entries[i]; + return NULL; +} + +static __inline bool is_vacant(dhcp_entry_t *entry) +{ + return memcmp("\0\0\0\0\0", entry->mac, 6) == 0; +} + +static dhcp_entry_t *vacant_address(void) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (is_vacant(config->entries + i)) + return config->entries + i; + return NULL; +} + +static __inline void free_entry(dhcp_entry_t *entry) +{ + memset(entry->mac, 0, 6); +} + +uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) +{ + int i = 0; + while ((i + 1) < size) + { + int next = i + attrs[i + 1] + 2; + if (next > size) return NULL; + if (attrs[i] == attr) + return attrs + i; + i = next; + } + return NULL; +} + +int fill_options(void *dest, + uint8_t msg_type, + const char *domain, + ip4_addr_t dns, + int lease_time, + ip4_addr_t serverid, + ip4_addr_t router, + ip4_addr_t subnet) +{ + uint8_t *ptr = (uint8_t *)dest; + /* ACK message type */ + *ptr++ = 53; + *ptr++ = 1; + *ptr++ = msg_type; + + /* dhcp server identifier */ + *ptr++ = DHCP_SERVERID; + *ptr++ = 4; + set_ip(ptr, serverid); + ptr += 4; + + /* lease time */ + *ptr++ = DHCP_LEASETIME; + *ptr++ = 4; + *ptr++ = (lease_time >> 24) & 0xFF; + *ptr++ = (lease_time >> 16) & 0xFF; + *ptr++ = (lease_time >> 8) & 0xFF; + *ptr++ = (lease_time >> 0) & 0xFF; + + /* subnet mask */ + *ptr++ = DHCP_SUBNETMASK; + *ptr++ = 4; + set_ip(ptr, subnet); + ptr += 4; + + /* router */ + if (router.addr != 0) + { + *ptr++ = DHCP_ROUTER; + *ptr++ = 4; + set_ip(ptr, router); + ptr += 4; + } + + /* domain name */ + if (domain != NULL) + { + int len = strlen(domain); + *ptr++ = DHCP_DNSDOMAIN; + *ptr++ = len; + memcpy(ptr, domain, len); + ptr += len; + } + + /* domain name server (DNS) */ + if (dns.addr != 0) + { + *ptr++ = DHCP_DNSSERVER; + *ptr++ = 4; + set_ip(ptr, dns); + ptr += 4; + } + + /* end */ + *ptr++ = DHCP_END; + return ptr - (uint8_t *)dest; +} + +static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + uint8_t *ptr; + dhcp_entry_t *entry; + struct pbuf *pp; + struct netif *netif = netif_get_by_index(p->if_idx); + + (void)arg; + (void)addr; + + unsigned n = p->len; + if (n > sizeof(dhcp_data)) n = sizeof(dhcp_data); + memcpy(&dhcp_data, p->payload, n); + switch (dhcp_data.dp_options[2]) + { + case DHCP_DISCOVER: + entry = entry_by_mac(dhcp_data.dp_chaddr); + if (entry == NULL) entry = vacant_address(); + if (entry == NULL) break; + + dhcp_data.dp_op = 2; /* reply */ + dhcp_data.dp_secs = 0; + dhcp_data.dp_flags = 0; + set_ip(dhcp_data.dp_yiaddr, entry->addr); + memcpy(dhcp_data.dp_magic, magic_cookie, 4); + + memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); + + fill_options(dhcp_data.dp_options, + DHCP_OFFER, + config->domain, + config->dns, + entry->lease, + *netif_ip4_addr(netif), + config->router, + *netif_ip4_netmask(netif)); + + pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); + if (pp == NULL) break; + memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); + udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); + pbuf_free(pp); + break; + + case DHCP_REQUEST: + /* 1. find requested ipaddr in option list */ + ptr = find_dhcp_option(dhcp_data.dp_options, sizeof(dhcp_data.dp_options), DHCP_IPADDRESS); + if (ptr == NULL) break; + if (ptr[1] != 4) break; + ptr += 2; + + /* 2. does hw-address registered? */ + entry = entry_by_mac(dhcp_data.dp_chaddr); + if (entry != NULL) free_entry(entry); + + /* 3. find requested ipaddr */ + entry = entry_by_ip(get_ip(ptr)); + if (entry == NULL) break; + if (!is_vacant(entry)) break; + + /* 4. fill struct fields */ + memcpy(dhcp_data.dp_yiaddr, ptr, 4); + dhcp_data.dp_op = 2; /* reply */ + dhcp_data.dp_secs = 0; + dhcp_data.dp_flags = 0; + memcpy(dhcp_data.dp_magic, magic_cookie, 4); + + /* 5. fill options */ + memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); + + fill_options(dhcp_data.dp_options, + DHCP_ACK, + config->domain, + config->dns, + entry->lease, + *netif_ip4_addr(netif), + config->router, + *netif_ip4_netmask(netif)); + + /* 6. send ACK */ + pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); + if (pp == NULL) break; + memcpy(entry->mac, dhcp_data.dp_chaddr, 6); + memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); + udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); + pbuf_free(pp); + break; + + default: + break; + } + pbuf_free(p); +} + +err_t dhserv_init(const dhcp_config_t *c) +{ + err_t err; + udp_init(); + dhserv_free(); + pcb = udp_new(); + if (pcb == NULL) + return ERR_MEM; + err = udp_bind(pcb, IP_ADDR_ANY, c->port); + if (err != ERR_OK) + { + dhserv_free(); + return err; + } + udp_recv(pcb, udp_recv_proc, NULL); + config = c; + return ERR_OK; +} + +void dhserv_free(void) +{ + if (pcb == NULL) return; + udp_remove(pcb); + pcb = NULL; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h new file mode 100644 index 000000000..2a0b15854 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h @@ -0,0 +1,62 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dhcp ipv4 server using lwip (pcb) + * ref: https://lists.gnu.org/archive/html/lwip-users/2012-12/msg00016.html + */ + +#ifndef DHSERVER_H +#define DHSERVER_H + +#include +#include +#include +#include +#include "lwip/err.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +typedef struct dhcp_entry +{ + uint8_t mac[6]; + ip4_addr_t addr; + uint32_t lease; +} dhcp_entry_t; + +typedef struct dhcp_config +{ + ip4_addr_t router; + uint16_t port; + ip4_addr_t dns; + const char *domain; + int num_entry; + dhcp_entry_t *entries; +} dhcp_config_t; + +err_t dhserv_init(const dhcp_config_t *config); +void dhserv_free(void); + +#endif /* DHSERVER_H */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c new file mode 100644 index 000000000..e4e7c3492 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c @@ -0,0 +1,200 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dns ipv4 server using lwip (pcb) + */ + +#include "dnserver.h" + +#define DNS_MAX_HOST_NAME_LEN 128 + +static struct udp_pcb *pcb = NULL; +dns_query_proc_t query_proc = NULL; + +#pragma pack(push, 1) +typedef struct +{ +#if BYTE_ORDER == LITTLE_ENDIAN + uint8_t rd: 1, /* Recursion Desired */ + tc: 1, /* Truncation Flag */ + aa: 1, /* Authoritative Answer Flag */ + opcode: 4, /* Operation code */ + qr: 1; /* Query/Response Flag */ + uint8_t rcode: 4, /* Response Code */ + z: 3, /* Zero */ + ra: 1; /* Recursion Available */ +#else + uint8_t qr: 1, /* Query/Response Flag */ + opcode: 4, /* Operation code */ + aa: 1, /* Authoritative Answer Flag */ + tc: 1, /* Truncation Flag */ + rd: 1; /* Recursion Desired */ + uint8_t ra: 1, /* Recursion Available */ + z: 3, /* Zero */ + rcode: 4; /* Response Code */ +#endif +} dns_header_flags_t; + +typedef struct +{ + uint16_t id; + dns_header_flags_t flags; + uint16_t n_record[4]; +} dns_header_t; + +typedef struct dns_answer +{ + uint16_t name; + uint16_t type; + uint16_t Class; + uint32_t ttl; + uint16_t len; + uint32_t addr; +} dns_answer_t; +#pragma pack(pop) + +typedef struct dns_query +{ + char name[DNS_MAX_HOST_NAME_LEN]; + uint16_t type; + uint16_t Class; +} dns_query_t; + +static uint16_t get_uint16(const uint8_t *pnt) +{ + uint16_t result; + memcpy(&result, pnt, sizeof(result)); + return result; +} + +static int parse_next_query(void *data, int size, dns_query_t *query) +{ + int len; + int lables; + uint8_t *ptr; + + len = 0; + lables = 0; + ptr = (uint8_t *)data; + + while (true) + { + uint8_t lable_len; + if (size <= 0) return -1; + lable_len = *ptr++; + size--; + if (lable_len == 0) break; + if (lables > 0) + { + if (len == DNS_MAX_HOST_NAME_LEN) return -2; + query->name[len++] = '.'; + } + if (lable_len > size) return -1; + if (len + lable_len >= DNS_MAX_HOST_NAME_LEN) return -2; + memcpy(&query->name[len], ptr, lable_len); + len += lable_len; + ptr += lable_len; + size -= lable_len; + lables++; + } + + if (size < 4) return -1; + query->name[len] = 0; + query->type = get_uint16(ptr); + ptr += 2; + query->Class = get_uint16(ptr); + ptr += 2; + return ptr - (uint8_t *)data; +} + +static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + int len; + dns_header_t *header; + static dns_query_t query; + struct pbuf *out; + ip4_addr_t host_addr; + dns_answer_t *answer; + + (void)arg; + + if (p->len <= sizeof(dns_header_t)) goto error; + header = (dns_header_t *)p->payload; + if (header->flags.qr != 0) goto error; + if (ntohs(header->n_record[0]) != 1) goto error; + + len = parse_next_query(header + 1, p->len - sizeof(dns_header_t), &query); + if (len < 0) goto error; + if (!query_proc(query.name, &host_addr)) goto error; + + len += sizeof(dns_header_t); + out = pbuf_alloc(PBUF_TRANSPORT, len + 16, PBUF_POOL); + if (out == NULL) goto error; + + memcpy(out->payload, p->payload, len); + header = (dns_header_t *)out->payload; + header->flags.qr = 1; + header->n_record[1] = htons(1); + answer = (struct dns_answer *)((uint8_t *)out->payload + len); + answer->name = htons(0xC00C); + answer->type = htons(1); + answer->Class = htons(1); + answer->ttl = htonl(32); + answer->len = htons(4); + answer->addr = host_addr.addr; + + udp_sendto(upcb, out, addr, port); + pbuf_free(out); + +error: + pbuf_free(p); +} + +err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t qp) +{ + err_t err; + udp_init(); + dnserv_free(); + pcb = udp_new(); + if (pcb == NULL) + return ERR_MEM; + err = udp_bind(pcb, bind, port); + if (err != ERR_OK) + { + dnserv_free(); + return err; + } + udp_recv(pcb, udp_recv_proc, NULL); + query_proc = qp; + return ERR_OK; +} + +void dnserv_free() +{ + if (pcb == NULL) return; + udp_remove(pcb); + pcb = NULL; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h new file mode 100644 index 000000000..a062e3aa7 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dns ipv4 server using lwip (pcb) + */ + +#ifndef DNSERVER +#define DNSERVER + +#include +#include +#include +#include +#include "lwip/def.h" +#include "lwip/err.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +typedef bool (*dns_query_proc_t)(const char *name, ip4_addr_t *addr); + +err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t query_proc); +void dnserv_free(void); + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h new file mode 100644 index 000000000..1c737574c --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h @@ -0,0 +1,266 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ndis.h *************************************************************** + * + * \brief + * This file contains the possible external configuration of the USB. + * + * \addtogroup usbstick + * + * + ******************************************************************************/ + +/** + \ingroup usbstick + \defgroup RNDIS RNDIS Support + @{ + */ + +/* + * ndis.h + * + * Modified by Colin O'Flynn + * ntddndis.h modified by Benedikt Spranger + * + * Thanks to the cygwin development team, + * espacially to Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef _LINUX_NDIS_H +#define _LINUX_NDIS_H + + +#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 +#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A +#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B + +/* from drivers/net/sk98lin/h/skgepnmi.h */ +#define OID_PNP_CAPABILITIES 0xFD010100 +#define OID_PNP_SET_POWER 0xFD010101 +#define OID_PNP_QUERY_POWER 0xFD010102 +#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 +#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 +#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 + +enum NDIS_DEVICE_POWER_STATE { + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, + NdisDeviceStateD1, + NdisDeviceStateD2, + NdisDeviceStateD3, + NdisDeviceStateMaximum +}; + +struct NDIS_PM_WAKE_UP_CAPABILITIES { + enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; + enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp; + enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; +}; + +/* NDIS_PNP_CAPABILITIES.Flags constants */ +#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001 +#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 +#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 + +/* +struct NDIS_PNP_CAPABILITIES { + __le32 Flags; + struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; +}; + +struct NDIS_PM_PACKET_PATTERN { + __le32 Priority; + __le32 Reserved; + __le32 MaskSize; + __le32 PatternOffset; + __le32 PatternSize; + __le32 PatternFlags; +}; +*/ + +/* Required Object IDs (OIDs) */ +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define OID_GEN_SUPPORTED_GUIDS 0x00010117 +#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 +#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 +#define OID_GEN_MACHINE_NAME 0x0001021A +#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B +#define OID_GEN_VLAN_ID 0x0001021C + +/* Optional OIDs */ +#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 +#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 + +/* Required statistics OIDs */ +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +/* Optional statistics OIDs */ +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define OID_GEN_GET_TIME_CAPS 0x0002020F +#define OID_GEN_GET_NETCARD_TIME 0x00020210 +#define OID_GEN_NETCARD_LOAD 0x00020211 +#define OID_GEN_DEVICE_PROFILE 0x00020212 +#define OID_GEN_INIT_TIME_MS 0x00020213 +#define OID_GEN_RESET_COUNTS 0x00020214 +#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215 +#define OID_GEN_FRIENDLY_NAME 0x00020216 +#define OID_GEN_MINIPORT_INFO 0x00020217 +#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218 + +/* IEEE 802.3 (Ethernet) OIDs */ +#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 + +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define OID_802_3_MAC_OPTIONS 0x01010105 +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +/* Wireless LAN OIDs */ +/* Mandatory */ +#define OID_802_11_BSSID 0x0D010101 /* Q S */ +#define OID_802_11_SSID 0x0D010102 /* Q S */ +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */ +#define OID_802_11_RSSI 0x0D010206 /* Q I */ +#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */ +#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */ +#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */ +#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */ +#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */ +#define OID_802_11_ADD_WEP 0x0D010113 /* S */ +#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */ +#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */ +#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */ +#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */ +#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */ + + + +/* OID_GEN_MINIPORT_INFO constants */ +#define NDIS_MINIPORT_BUS_MASTER 0x00000001 +#define NDIS_MINIPORT_WDM_DRIVER 0x00000002 +#define NDIS_MINIPORT_SG_LIST 0x00000004 +#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008 +#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010 +#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020 +#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040 +#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080 +#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100 +#define NDIS_MINIPORT_IS_NDIS_5 0x00000200 +#define NDIS_MINIPORT_IS_CO 0x00000400 +#define NDIS_MINIPORT_DESERIALIZE 0x00000800 +#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000 +#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000 +#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000 +#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000 +#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000 +#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000 +#define NDIS_MINIPORT_HIDDEN 0x00040000 +#define NDIS_MINIPORT_SWENUM 0x00080000 +#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000 +#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000 +#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000 +#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000 +#define NDIS_MINIPORT_64BITS_DMA 0x01000000 + +#define NDIS_MEDIUM_802_3 0x00000000 +#define NDIS_MEDIUM_802_5 0x00000001 +#define NDIS_MEDIUM_FDDI 0x00000002 +#define NDIS_MEDIUM_WAN 0x00000003 +#define NDIS_MEDIUM_LOCAL_TALK 0x00000004 +#define NDIS_MEDIUM_DIX 0x00000005 +#define NDIS_MEDIUM_ARCENT_RAW 0x00000006 +#define NDIS_MEDIUM_ARCENT_878_2 0x00000007 +#define NDIS_MEDIUM_ATM 0x00000008 +#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009 +#define NDIS_MEDIUM_IRDA 0x0000000A +#define NDIS_MEDIUM_BPC 0x0000000B +#define NDIS_MEDIUM_CO_WAN 0x0000000C +#define NDIS_MEDIUM_1394 0x0000000D + +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 +#define NDIS_PACKET_TYPE_SMT 0x00000040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 +#define NDIS_PACKET_TYPE_GROUP 0x00000100 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 + +#define NDIS_MEDIA_STATE_CONNECTED 0x00000000 +#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001 + +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 + +#endif /* _LINUX_NDIS_H */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h new file mode 100644 index 000000000..b45860eeb --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h @@ -0,0 +1,307 @@ +/** + * \file rndis_protocol.h + * RNDIS Defines + * + * \author + * Colin O'Flynn + * + * \addtogroup usbstick + */ + +/* Copyright (c) 2008 Colin O'Flynn + + 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 the copyright holders nor the names of + 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. +*/ + +#ifndef _RNDIS_H +#define _RNDIS_H + +/** + \addtogroup RNDIS + @{ + */ + +#include + +#define RNDIS_MAJOR_VERSION 1 +#define RNDIS_MINOR_VERSION 0 + +#define RNDIS_STATUS_SUCCESS 0X00000000 +#define RNDIS_STATUS_FAILURE 0XC0000001 +#define RNDIS_STATUS_INVALID_DATA 0XC0010015 +#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB +#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B +#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C + + +/* Message set for Connectionless (802.3) Devices */ +#define REMOTE_NDIS_PACKET_MSG 0x00000001 +#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002 +#define REMOTE_NDIS_HALT_MSG 0X00000003 +#define REMOTE_NDIS_QUERY_MSG 0X00000004 +#define REMOTE_NDIS_SET_MSG 0X00000005 +#define REMOTE_NDIS_RESET_MSG 0X00000006 +#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007 +#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008 +#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002 +#define REMOTE_NDIS_QUERY_CMPLT 0X80000004 +#define REMOTE_NDIS_SET_CMPLT 0X80000005 +#define REMOTE_NDIS_RESET_CMPLT 0X80000006 +#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008 + +typedef uint32_t rndis_MessageType_t; +typedef uint32_t rndis_MessageLength_t; +typedef uint32_t rndis_RequestId_t; +typedef uint32_t rndis_MajorVersion_t; +typedef uint32_t rndis_MinorVersion_t; +typedef uint32_t rndis_MaxTransferSize_t; +typedef uint32_t rndis_Status_t; + + +/* Device Flags */ +#define RNDIS_DF_CONNECTIONLESS 0x00000001 +#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 +typedef uint32_t rndis_DeviceFlags_t; + +/* Mediums */ +#define RNDIS_MEDIUM_802_3 0x00000000 +typedef uint32_t rndis_Medium_t; + + +typedef uint32_t rndis_MaxPacketsPerTransfer_t; +typedef uint32_t rndis_PacketAlignmentFactor_t; +typedef uint32_t rndis_AfListOffset_t; +typedef uint32_t rndis_AfListSize_t; + +/*** Remote NDIS Generic Message type ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + } rndis_generic_msg_t; + + +/*** Remote NDIS Initialize Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_MajorVersion_t MajorVersion; + rndis_MinorVersion_t MinorVersion; + rndis_MaxTransferSize_t MaxTransferSize; + } rndis_initialize_msg_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + rndis_MajorVersion_t MajorVersion; + rndis_MinorVersion_t MinorVersion; + rndis_DeviceFlags_t DeviceFlags; + rndis_Medium_t Medium; + rndis_MaxPacketsPerTransfer_t MaxPacketsPerTransfer; + rndis_MaxTransferSize_t MaxTransferSize; + rndis_PacketAlignmentFactor_t PacketAlignmentFactor; + rndis_AfListOffset_t AfListOffset; + rndis_AfListSize_t AfListSize; + } rndis_initialize_cmplt_t; + + +/*** Remote NDIS Halt Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + } rndis_halt_msg_t; + +typedef uint32_t rndis_Oid_t; +typedef uint32_t rndis_InformationBufferLength_t; +typedef uint32_t rndis_InformationBufferOffset_t; +typedef uint32_t rndis_DeviceVcHandle_t; + +/*** Remote NDIS Query Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Oid_t Oid; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + rndis_DeviceVcHandle_t DeviceVcHandle; + } rndis_query_msg_t; + +/* Response: */ + +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + } rndis_query_cmplt_t; + +/*** Remote NDIS Set Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Oid_t Oid; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + rndis_DeviceVcHandle_t DeviceVcHandle; + } rndis_set_msg_t; + +/* Response */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + }rndis_set_cmplt_t; + +/* Information buffer layout for OID_GEN_RNDIS_CONFIG_PARAMETER */ +typedef uint32_t rndis_ParameterNameOffset_t; +typedef uint32_t rndis_ParameterNameLength_t; +typedef uint32_t rndis_ParameterType_t; +typedef uint32_t rndis_ParameterValueOffset_t; +typedef uint32_t rndis_ParameterValueLength_t; + +#define PARAMETER_TYPE_STRING 2 +#define PARAMETER_TYPE_NUMERICAL 0 + +typedef struct{ + rndis_ParameterNameOffset_t ParameterNameOffset; + rndis_ParameterNameLength_t ParameterNameLength; + rndis_ParameterType_t ParameterType; + rndis_ParameterValueOffset_t ParameterValueOffset; + rndis_ParameterValueLength_t ParameterValueLength; + }rndis_config_parameter_t; + +typedef uint32_t rndis_Reserved_t; + +/*** Remote NDIS Soft Reset Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Reserved_t Reserved; + } rndis_reset_msg_t; + +typedef uint32_t rndis_AddressingReset_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Status_t Status; + rndis_AddressingReset_t AddressingReset; + } rndis_reset_cmplt_t; + +/*** Remote NDIS Indicate Status Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Status_t Status; + rndis_Status_t StatusBufferLength; + rndis_Status_t StatusBufferOffset; + } rndis_indicate_status_t; + +typedef uint32_t rndis_DiagStatus_t; +typedef uint32_t rndis_ErrorOffset_t; + +typedef struct { + rndis_DiagStatus_t DiagStatus; + rndis_ErrorOffset_t ErrorOffset; + }rndis_diagnostic_info_t; + +/*** Remote NDIS Keepalive Message */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + }rndis_keepalive_msg_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + }rndis_keepalive_cmplt_t; + +/*** Remote NDIS Data Packet ***/ + +typedef uint32_t rndis_DataOffset_t; +typedef uint32_t rndis_DataLength_t; +typedef uint32_t rndis_OOBDataOffset_t; +typedef uint32_t rndis_OOBDataLength_t; +typedef uint32_t rndis_NumOOBDataElements_t; +typedef uint32_t rndis_PerPacketInfoOffset_t; +typedef uint32_t rndis_PerPacketInfoLength_t; + +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_DataOffset_t DataOffset; + rndis_DataLength_t DataLength; + rndis_OOBDataOffset_t OOBDataOffset; + rndis_OOBDataLength_t OOBDataLength; + rndis_NumOOBDataElements_t NumOOBDataElements; + rndis_PerPacketInfoOffset_t PerPacketInfoOffset; + rndis_PerPacketInfoLength_t PerPacketInfoLength; + rndis_DeviceVcHandle_t DeviceVcHandle; + rndis_Reserved_t Reserved; + }rndis_data_packet_t; + +typedef uint32_t rndis_ClassInformationOffset_t; +typedef uint32_t rndis_Size_t; +typedef uint32_t rndis_Type_t; + +typedef struct{ + rndis_Size_t Size; + rndis_Type_t Type; + rndis_ClassInformationOffset_t ClassInformationType; + }rndis_OOB_packet_t; + +#include "ndis.h" + +typedef enum rnids_state_e { + rndis_uninitialized, + rndis_initialized, + rndis_data_initialized + } rndis_state_t; + +typedef struct { + uint32_t txok; + uint32_t rxok; + uint32_t txbad; + uint32_t rxbad; +} usb_eth_stat_t; + +#endif /* _RNDIS_H */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c new file mode 100644 index 000000000..ee611c883 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c @@ -0,0 +1,303 @@ +/* + The original version of this code was lrndis/usbd_rndis_core.c from https://github.com/fetisov/lrndis + It has since been overhauled to suit this application +*/ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include "class/net/net_device.h" +#include "rndis_protocol.h" +#include "netif/ethernet.h" + +#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */ +#define RNDIS_VENDOR "TinyUSB" /* NIC vendor name */ + +static const uint8_t *const station_hwaddr = tud_network_mac_address; +static const uint8_t *const permanent_hwaddr = tud_network_mac_address; + +static usb_eth_stat_t usb_eth_stat = { 0, 0, 0, 0 }; +static uint32_t oid_packet_filter = 0x0000000; +static rndis_state_t rndis_state; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t ndis_report[8] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + +static const uint32_t OIDSupportedList[] = +{ + OID_GEN_SUPPORTED_LIST, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_VENDOR_DRIVER_VERSION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_PROTOCOL_OPTIONS, + OID_GEN_MAC_OPTIONS, + OID_GEN_MEDIA_CONNECT_STATUS, + OID_GEN_MAXIMUM_SEND_PACKETS, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_MAC_OPTIONS +}; + +#define OID_LIST_LENGTH TU_ARRAY_SIZE(OIDSupportedList) +#define ENC_BUF_SIZE (OID_LIST_LENGTH * 4 + 32) + +static void *encapsulated_buffer; + +static void rndis_report(void) +{ + netd_report(ndis_report, sizeof(ndis_report)); +} + +static void rndis_query_cmplt32(int status, uint32_t data) +{ + rndis_query_cmplt_t *c; + c = (rndis_query_cmplt_t *)encapsulated_buffer; + c->MessageType = REMOTE_NDIS_QUERY_CMPLT; + c->MessageLength = sizeof(rndis_query_cmplt_t) + 4; + c->InformationBufferLength = 4; + c->InformationBufferOffset = 16; + c->Status = status; + memcpy(c + 1, &data, sizeof(data)); + rndis_report(); +} + +static void rndis_query_cmplt(int status, const void *data, int size) +{ + rndis_query_cmplt_t *c; + c = (rndis_query_cmplt_t *)encapsulated_buffer; + c->MessageType = REMOTE_NDIS_QUERY_CMPLT; + c->MessageLength = sizeof(rndis_query_cmplt_t) + size; + c->InformationBufferLength = size; + c->InformationBufferOffset = 16; + c->Status = status; + memcpy(c + 1, data, size); + rndis_report(); +} + +#define MAC_OPT NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \ + NDIS_MAC_OPTION_RECEIVE_SERIALIZED | \ + NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | \ + NDIS_MAC_OPTION_NO_LOOPBACK + +static const char *rndis_vendor = RNDIS_VENDOR; + +static void rndis_query(void) +{ + switch (((rndis_query_msg_t *)encapsulated_buffer)->Oid) + { + case OID_GEN_SUPPORTED_LIST: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, OIDSupportedList, 4 * OID_LIST_LENGTH); return; + case OID_GEN_VENDOR_DRIVER_VERSION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00001000); return; + case OID_802_3_CURRENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, station_hwaddr, 6); return; + case OID_802_3_PERMANENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, permanent_hwaddr, 6); return; + case OID_GEN_MEDIA_SUPPORTED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_MEDIA_IN_USE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_PHYSICAL_MEDIUM: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_HARDWARE_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_GEN_LINK_SPEED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, RNDIS_LINK_SPEED / 100); return; + case OID_GEN_VENDOR_ID: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00FFFFFF); return; + case OID_GEN_VENDOR_DESCRIPTION: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, rndis_vendor, strlen(rndis_vendor) + 1); return; + case OID_GEN_CURRENT_PACKET_FILTER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, oid_packet_filter); return; + case OID_GEN_MAXIMUM_FRAME_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU - SIZEOF_ETH_HDR); return; + case OID_GEN_MAXIMUM_TOTAL_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_TRANSMIT_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_RECEIVE_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_MEDIA_CONNECT_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIA_STATE_CONNECTED); return; + case OID_GEN_RNDIS_CONFIG_PARAMETER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_MAXIMUM_LIST_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 1); return; + case OID_802_3_MULTICAST_LIST: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; + case OID_802_3_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; + case OID_GEN_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, /*MAC_OPT*/ 0); return; + case OID_802_3_RCV_ERROR_ALIGNMENT: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_XMIT_ONE_COLLISION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_XMIT_MORE_COLLISIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_GEN_XMIT_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txok); return; + case OID_GEN_RCV_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxok); return; + case OID_GEN_RCV_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxbad); return; + case OID_GEN_XMIT_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txbad); return; + case OID_GEN_RCV_NO_BUFFER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + default: rndis_query_cmplt(RNDIS_STATUS_FAILURE, NULL, 0); return; + } +} + +#define INFBUF ((uint8_t *)&(m->RequestId) + m->InformationBufferOffset) + +static void rndis_handle_config_parm(const char *data, int keyoffset, int valoffset, int keylen, int vallen) +{ + (void)data; + (void)keyoffset; + (void)valoffset; + (void)keylen; + (void)vallen; +} + +static void rndis_packetFilter(uint32_t newfilter) +{ + (void)newfilter; +} + +static void rndis_handle_set_msg(void) +{ + rndis_set_cmplt_t *c; + rndis_set_msg_t *m; + rndis_Oid_t oid; + + c = (rndis_set_cmplt_t *)encapsulated_buffer; + m = (rndis_set_msg_t *)encapsulated_buffer; + + oid = m->Oid; + c->MessageType = REMOTE_NDIS_SET_CMPLT; + c->MessageLength = sizeof(rndis_set_cmplt_t); + c->Status = RNDIS_STATUS_SUCCESS; + + switch (oid) + { + /* Parameters set up in 'Advanced' tab */ + case OID_GEN_RNDIS_CONFIG_PARAMETER: + { + rndis_config_parameter_t *p; + char *ptr = (char *)m; + ptr += sizeof(rndis_generic_msg_t); + ptr += m->InformationBufferOffset; + p = (rndis_config_parameter_t *) ((void*) ptr); + rndis_handle_config_parm(ptr, p->ParameterNameOffset, p->ParameterValueOffset, p->ParameterNameLength, p->ParameterValueLength); + } + break; + + /* Mandatory general OIDs */ + case OID_GEN_CURRENT_PACKET_FILTER: + memcpy(&oid_packet_filter, INFBUF, 4); + if (oid_packet_filter) + { + rndis_packetFilter(oid_packet_filter); + rndis_state = rndis_data_initialized; + } + else + { + rndis_state = rndis_initialized; + } + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + break; + + case OID_GEN_PROTOCOL_OPTIONS: + break; + + /* Mandatory 802_3 OIDs */ + case OID_802_3_MULTICAST_LIST: + break; + + /* Power Managment: fails for now */ + case OID_PNP_ADD_WAKE_UP_PATTERN: + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + case OID_PNP_ENABLE_WAKE_UP: + default: + c->Status = RNDIS_STATUS_FAILURE; + break; + } + + /* c->MessageID is same as before */ + rndis_report(); + return; +} + +void rndis_class_set_handler(uint8_t *data, int size) +{ + encapsulated_buffer = data; + (void)size; + + switch (((rndis_generic_msg_t *)encapsulated_buffer)->MessageType) + { + case REMOTE_NDIS_INITIALIZE_MSG: + { + rndis_initialize_cmplt_t *m; + m = ((rndis_initialize_cmplt_t *)encapsulated_buffer); + /* m->MessageID is same as before */ + m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; + m->MessageLength = sizeof(rndis_initialize_cmplt_t); + m->MajorVersion = RNDIS_MAJOR_VERSION; + m->MinorVersion = RNDIS_MINOR_VERSION; + m->Status = RNDIS_STATUS_SUCCESS; + m->DeviceFlags = RNDIS_DF_CONNECTIONLESS; + m->Medium = RNDIS_MEDIUM_802_3; + m->MaxPacketsPerTransfer = 1; + m->MaxTransferSize = CFG_TUD_NET_MTU + sizeof(rndis_data_packet_t); + m->PacketAlignmentFactor = 0; + m->AfListOffset = 0; + m->AfListSize = 0; + rndis_state = rndis_initialized; + rndis_report(); + } + break; + + case REMOTE_NDIS_QUERY_MSG: + rndis_query(); + break; + + case REMOTE_NDIS_SET_MSG: + rndis_handle_set_msg(); + break; + + case REMOTE_NDIS_RESET_MSG: + { + rndis_reset_cmplt_t * m; + m = ((rndis_reset_cmplt_t *)encapsulated_buffer); + rndis_state = rndis_uninitialized; + m->MessageType = REMOTE_NDIS_RESET_CMPLT; + m->MessageLength = sizeof(rndis_reset_cmplt_t); + m->Status = RNDIS_STATUS_SUCCESS; + m->AddressingReset = 1; /* Make it look like we did something */ + /* m->AddressingReset = 0; - Windows halts if set to 1 for some reason */ + rndis_report(); + } + break; + + case REMOTE_NDIS_KEEPALIVE_MSG: + { + rndis_keepalive_cmplt_t * m; + m = (rndis_keepalive_cmplt_t *)encapsulated_buffer; + m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; + m->MessageLength = sizeof(rndis_keepalive_cmplt_t); + m->Status = RNDIS_STATUS_SUCCESS; + } + /* We have data to send back */ + rndis_report(); + break; + + default: + break; + } +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml new file mode 100644 index 000000000..331445024 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml @@ -0,0 +1,14 @@ +pkg.name: tinyusb +pkg.description: A silly USB stack for embedded +pkg.author: "Ha Thach " +pkg.homepage: "https://github.com/hathach/tinyusb" +pkg.keywords: + - usb + +pkg.type: sdk + +pkg.deps: + - "@apache-mynewt-core/kernel/os" + +pkg.include_dirs: + - src diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml new file mode 100644 index 000000000..21d092373 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml @@ -0,0 +1,15 @@ +repo.name: tinyusb +repo.versions: + "0.0.0": "master" + "0.5.0": "0.5.0" + "0.6.0": "0.6.0" + "0.7.0": "0.7.0" + "0.8.0": "0.8.0" + "0.9.0": "0.9.0" + "0.10.0": "0.10.0" + "0.10.1": "0.10.1" + "0.11.0": "0.11.0" + + "0-dev": "0.0.0" # master + "0-latest": "0.11.0" # latest stable release + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename b/examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename new file mode 100644 index 000000000..6aea8579a --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename @@ -0,0 +1,22 @@ +# sdkconfig replacement configurations for deprecated options formatted as +# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION +CONFIG_USB_ENABLED CONFIG_TINYUSB +CONFIG_USB_DO_NOT_CREATE_TASK CONFIG_TINYUSB_NO_DEFAULT_TASK +CONFIG_USB_TASK_PRIORITY CONFIG_TINYUSB_TASK_PRIORITY +CONFIG_USB_DESC_USE_ESPRESSIF_VID CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID +CONFIG_USB_DESC_CUSTOM_VID CONFIG_TINYUSB_DESC_CUSTOM_VID +CONFIG_USB_DESC_USE_DEFAULT_PID CONFIG_TINYUSB_DESC_USE_DEFAULT_PID +CONFIG_USB_DESC_CUSTOM_PID CONFIG_TINYUSB_DESC_CUSTOM_PID +CONFIG_USB_DESC_BCDDEVICE CONFIG_TINYUSB_DESC_BCD_DEVICE +CONFIG_USB_DESC_MANUFACTURER_STRING CONFIG_TINYUSB_DESC_MANUFACTURER_STRING +CONFIG_USB_DESC_PRODUCT_STRING CONFIG_TINYUSB_DESC_PRODUCT_STRING +CONFIG_USB_DESC_SERIAL_STRING CONFIG_TINYUSB_DESC_SERIAL_STRING +CONFIG_USB_DESC_CDC_STRING CONFIG_TINYUSB_DESC_CDC_STRING +CONFIG_USB_DESC_MSC_STRING CONFIG_TINYUSB_DESC_MSC_STRING +CONFIG_USB_DESC_HID_STRING CONFIG_TINYUSB_DESC_HID_STRING +CONFIG_USB_MSC_ENABLED CONFIG_TINYUSB_MSC_ENABLED +CONFIG_USB_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE +CONFIG_USB_CDC_ENABLED CONFIG_TINYUSB_CDC_ENABLED +CONFIG_USB_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE +CONFIG_USB_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE +CONFIG_USB_DEBUG_LEVEL CONFIG_TINYUSB_DEBUG_LEVEL diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h new file mode 100644 index 000000000..6f9c1a6b5 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h @@ -0,0 +1,933 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Reinhard Panhuber + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup group_class + * \defgroup ClassDriver_Audio Audio + * Currently only MIDI subclass is supported + * @{ */ + +#ifndef _TUSB_AUDIO_H__ +#define _TUSB_AUDIO_H__ + +#include "common/tusb_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// Audio Device Class Codes + +/// A.2 - Audio Function Subclass Codes +typedef enum +{ + AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, +} audio_function_subclass_type_t; + +/// A.3 - Audio Function Protocol Codes +typedef enum +{ + AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_function_protocol_code_t; + +/// A.5 - Audio Interface Subclass Codes +typedef enum +{ + AUDIO_SUBCLASS_UNDEFINED = 0x00, + AUDIO_SUBCLASS_CONTROL , ///< Audio Control + AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming + AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming +} audio_subclass_type_t; + +/// A.6 - Audio Interface Protocol Codes +typedef enum +{ + AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_interface_protocol_code_t; + +/// A.7 - Audio Function Category Codes +typedef enum +{ + AUDIO_FUNC_UNDEF = 0x00, + AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, + AUDIO_FUNC_HOME_THEATER = 0x02, + AUDIO_FUNC_MICROPHONE = 0x03, + AUDIO_FUNC_HEADSET = 0x04, + AUDIO_FUNC_TELEPHONE = 0x05, + AUDIO_FUNC_CONVERTER = 0x06, + AUDIO_FUNC_SOUND_RECODER = 0x07, + AUDIO_FUNC_IO_BOX = 0x08, + AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, + AUDIO_FUNC_PRO_AUDIO = 0x0A, + AUDIO_FUNC_AUDIO_VIDEO = 0x0B, + AUDIO_FUNC_CONTROL_PANEL = 0x0C, + AUDIO_FUNC_OTHER = 0xFF, +} audio_function_code_t; + +/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AC_INTERFACE_HEADER = 0x01, + AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, + AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, + AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, + AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, + AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, + AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, + AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, + AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, + AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, + AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, + AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, + AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, +} audio_cs_ac_interface_subtype_t; + +/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, + AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, + AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, + AUDIO_CS_AS_INTERFACE_DECODER = 0x04, +} audio_cs_as_interface_subtype_t; + +/// A.11 - Effect Unit Effect Types +typedef enum +{ + AUDIO_EFFECT_TYPE_UNDEF = 0x00, + AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, + AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, + AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, + AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, +} audio_effect_unit_effect_type_t; + +/// A.12 - Processing Unit Process Types +typedef enum +{ + AUDIO_PROCESS_TYPE_UNDEF = 0x00, + AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, + AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, + AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, +} audio_processing_unit_process_type_t; + +/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, + AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio_cs_ep_subtype_t; + +/// A.14 - Audio Class-Specific Request Codes +typedef enum +{ + AUDIO_CS_REQ_UNDEF = 0x00, + AUDIO_CS_REQ_CUR = 0x01, + AUDIO_CS_REQ_RANGE = 0x02, + AUDIO_CS_REQ_MEM = 0x03, +} audio_cs_req_t; + +/// A.17 - Control Selector Codes + +/// A.17.1 - Clock Source Control Selectors +typedef enum +{ + AUDIO_CS_CTRL_UNDEF = 0x00, + AUDIO_CS_CTRL_SAM_FREQ = 0x01, + AUDIO_CS_CTRL_CLK_VALID = 0x02, +} audio_clock_src_control_selector_t; + +/// A.17.2 - Clock Selector Control Selectors +typedef enum +{ + AUDIO_CX_CTRL_UNDEF = 0x00, + AUDIO_CX_CTRL_CONTROL = 0x01, +} audio_clock_sel_control_selector_t; + +/// A.17.3 - Clock Multiplier Control Selectors +typedef enum +{ + AUDIO_CM_CTRL_UNDEF = 0x00, + AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, + AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, +} audio_clock_mul_control_selector_t; + +/// A.17.4 - Terminal Control Selectors +typedef enum +{ + AUDIO_TE_CTRL_UNDEF = 0x00, + AUDIO_TE_CTRL_COPY_PROTECT = 0x01, + AUDIO_TE_CTRL_CONNECTOR = 0x02, + AUDIO_TE_CTRL_OVERLOAD = 0x03, + AUDIO_TE_CTRL_CLUSTER = 0x04, + AUDIO_TE_CTRL_UNDERFLOW = 0x05, + AUDIO_TE_CTRL_OVERFLOW = 0x06, + AUDIO_TE_CTRL_LATENCY = 0x07, +} audio_terminal_control_selector_t; + +/// A.17.5 - Mixer Control Selectors +typedef enum +{ + AUDIO_MU_CTRL_UNDEF = 0x00, + AUDIO_MU_CTRL_MIXER = 0x01, + AUDIO_MU_CTRL_CLUSTER = 0x02, + AUDIO_MU_CTRL_UNDERFLOW = 0x03, + AUDIO_MU_CTRL_OVERFLOW = 0x04, + AUDIO_MU_CTRL_LATENCY = 0x05, +} audio_mixer_control_selector_t; + +/// A.17.6 - Selector Control Selectors +typedef enum +{ + AUDIO_SU_CTRL_UNDEF = 0x00, + AUDIO_SU_CTRL_SELECTOR = 0x01, + AUDIO_SU_CTRL_LATENCY = 0x02, +} audio_sel_control_selector_t; + +/// A.17.7 - Feature Unit Control Selectors +typedef enum +{ + AUDIO_FU_CTRL_UNDEF = 0x00, + AUDIO_FU_CTRL_MUTE = 0x01, + AUDIO_FU_CTRL_VOLUME = 0x02, + AUDIO_FU_CTRL_BASS = 0x03, + AUDIO_FU_CTRL_MID = 0x04, + AUDIO_FU_CTRL_TREBLE = 0x05, + AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, + AUDIO_FU_CTRL_AGC = 0x07, + AUDIO_FU_CTRL_DELAY = 0x08, + AUDIO_FU_CTRL_BASS_BOOST = 0x09, + AUDIO_FU_CTRL_LOUDNESS = 0x0A, + AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, + AUDIO_FU_CTRL_GAIN_PAD = 0x0C, + AUDIO_FU_CTRL_INVERTER = 0x0D, + AUDIO_FU_CTRL_UNDERFLOW = 0x0E, + AUDIO_FU_CTRL_OVERVLOW = 0x0F, + AUDIO_FU_CTRL_LATENCY = 0x10, +} audio_feature_unit_control_selector_t; + +/// A.17.8 Effect Unit Control Selectors + +/// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors +typedef enum +{ + AUDIO_PE_CTRL_UNDEF = 0x00, + AUDIO_PE_CTRL_ENABLE = 0x01, + AUDIO_PE_CTRL_CENTERFREQ = 0x02, + AUDIO_PE_CTRL_QFACTOR = 0x03, + AUDIO_PE_CTRL_GAIN = 0x04, + AUDIO_PE_CTRL_UNDERFLOW = 0x05, + AUDIO_PE_CTRL_OVERFLOW = 0x06, + AUDIO_PE_CTRL_LATENCY = 0x07, +} audio_parametric_equalizer_control_selector_t; + +/// A.17.8.2 Reverberation Effect Unit Control Selectors +typedef enum +{ + AUDIO_RV_CTRL_UNDEF = 0x00, + AUDIO_RV_CTRL_ENABLE = 0x01, + AUDIO_RV_CTRL_TYPE = 0x02, + AUDIO_RV_CTRL_LEVEL = 0x03, + AUDIO_RV_CTRL_TIME = 0x04, + AUDIO_RV_CTRL_FEEDBACK = 0x05, + AUDIO_RV_CTRL_PREDELAY = 0x06, + AUDIO_RV_CTRL_DENSITY = 0x07, + AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, + AUDIO_RV_CTRL_UNDERFLOW = 0x09, + AUDIO_RV_CTRL_OVERFLOW = 0x0A, + AUDIO_RV_CTRL_LATENCY = 0x0B, +} audio_reverberation_effect_control_selector_t; + +/// A.17.8.3 Modulation Delay Effect Unit Control Selectors +typedef enum +{ + AUDIO_MD_CTRL_UNDEF = 0x00, + AUDIO_MD_CTRL_ENABLE = 0x01, + AUDIO_MD_CTRL_BALANCE = 0x02, + AUDIO_MD_CTRL_RATE = 0x03, + AUDIO_MD_CTRL_DEPTH = 0x04, + AUDIO_MD_CTRL_TIME = 0x05, + AUDIO_MD_CTRL_FEEDBACK = 0x06, + AUDIO_MD_CTRL_UNDERFLOW = 0x07, + AUDIO_MD_CTRL_OVERFLOW = 0x08, + AUDIO_MD_CTRL_LATENCY = 0x09, +} audio_modulation_delay_control_selector_t; + +/// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors +typedef enum +{ + AUDIO_DR_CTRL_UNDEF = 0x00, + AUDIO_DR_CTRL_ENABLE = 0x01, + AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, + AUDIO_DR_CTRL_MAXAMPL = 0x03, + AUDIO_DR_CTRL_THRESHOLD = 0x04, + AUDIO_DR_CTRL_ATTACK_TIME = 0x05, + AUDIO_DR_CTRL_RELEASE_TIME = 0x06, + AUDIO_DR_CTRL_UNDERFLOW = 0x07, + AUDIO_DR_CTRL_OVERFLOW = 0x08, + AUDIO_DR_CTRL_LATENCY = 0x09, +} audio_dynamic_range_compression_control_selector_t; + +/// A.17.9 Processing Unit Control Selectors + +/// A.17.9.1 Up/Down-mix Processing Unit Control Selectors +typedef enum +{ + AUDIO_UD_CTRL_UNDEF = 0x00, + AUDIO_UD_CTRL_ENABLE = 0x01, + AUDIO_UD_CTRL_MODE_SELECT = 0x02, + AUDIO_UD_CTRL_CLUSTER = 0x03, + AUDIO_UD_CTRL_UNDERFLOW = 0x04, + AUDIO_UD_CTRL_OVERFLOW = 0x05, + AUDIO_UD_CTRL_LATENCY = 0x06, +} audio_up_down_mix_control_selector_t; + +/// A.17.9.2 Dolby Prologic ™ Processing Unit Control Selectors +typedef enum +{ + AUDIO_DP_CTRL_UNDEF = 0x00, + AUDIO_DP_CTRL_ENABLE = 0x01, + AUDIO_DP_CTRL_MODE_SELECT = 0x02, + AUDIO_DP_CTRL_CLUSTER = 0x03, + AUDIO_DP_CTRL_UNDERFLOW = 0x04, + AUDIO_DP_CTRL_OVERFLOW = 0x05, + AUDIO_DP_CTRL_LATENCY = 0x06, +} audio_dolby_prologic_control_selector_t; + +/// A.17.9.3 Stereo Extender Processing Unit Control Selectors +typedef enum +{ + AUDIO_ST_EXT_CTRL_UNDEF = 0x00, + AUDIO_ST_EXT_CTRL_ENABLE = 0x01, + AUDIO_ST_EXT_CTRL_WIDTH = 0x02, + AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, + AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, + AUDIO_ST_EXT_CTRL_LATENCY = 0x05, +} audio_stereo_extender_control_selector_t; + +/// A.17.10 Extension Unit Control Selectors +typedef enum +{ + AUDIO_XU_CTRL_UNDEF = 0x00, + AUDIO_XU_CTRL_ENABLE = 0x01, + AUDIO_XU_CTRL_CLUSTER = 0x02, + AUDIO_XU_CTRL_UNDERFLOW = 0x03, + AUDIO_XU_CTRL_OVERFLOW = 0x04, + AUDIO_XU_CTRL_LATENCY = 0x05, +} audio_extension_unit_control_selector_t; + +/// A.17.11 AudioStreaming Interface Control Selectors +typedef enum +{ + AUDIO_AS_CTRL_UNDEF = 0x00, + AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, + AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, + AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, +} audio_audiostreaming_interface_control_selector_t; + +/// A.17.12 Encoder Control Selectors +typedef enum +{ + AUDIO_EN_CTRL_UNDEF = 0x00, + AUDIO_EN_CTRL_BIT_RATE = 0x01, + AUDIO_EN_CTRL_QUALITY = 0x02, + AUDIO_EN_CTRL_VBR = 0x03, + AUDIO_EN_CTRL_TYPE = 0x04, + AUDIO_EN_CTRL_UNDERFLOW = 0x05, + AUDIO_EN_CTRL_OVERFLOW = 0x06, + AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, + AUDIO_EN_CTRL_PARAM1 = 0x08, + AUDIO_EN_CTRL_PARAM2 = 0x09, + AUDIO_EN_CTRL_PARAM3 = 0x0A, + AUDIO_EN_CTRL_PARAM4 = 0x0B, + AUDIO_EN_CTRL_PARAM5 = 0x0C, + AUDIO_EN_CTRL_PARAM6 = 0x0D, + AUDIO_EN_CTRL_PARAM7 = 0x0E, + AUDIO_EN_CTRL_PARAM8 = 0x0F, +} audio_encoder_control_selector_t; + +/// A.17.13 Decoder Control Selectors + +/// A.17.13.1 MPEG Decoder Control Selectors +typedef enum +{ + AUDIO_MPD_CTRL_UNDEF = 0x00, + AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, + AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, + AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, + AUDIO_MPD_CTRL_DYN_RANGE = 0x04, + AUDIO_MPD_CTRL_SCALING = 0x05, + AUDIO_MPD_CTRL_HILO_SCALING = 0x06, + AUDIO_MPD_CTRL_UNDERFLOW = 0x07, + AUDIO_MPD_CTRL_OVERFLOW = 0x08, + AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, +} audio_MPEG_decoder_control_selector_t; + +/// A.17.13.2 AC-3 Decoder Control Selectors +typedef enum +{ + AUDIO_AD_CTRL_UNDEF = 0x00, + AUDIO_AD_CTRL_MODE = 0x01, + AUDIO_AD_CTRL_DYN_RANGE = 0x02, + AUDIO_AD_CTRL_SCALING = 0x03, + AUDIO_AD_CTRL_HILO_SCALING = 0x04, + AUDIO_AD_CTRL_UNDERFLOW = 0x05, + AUDIO_AD_CTRL_OVERFLOW = 0x06, + AUDIO_AD_CTRL_DECODER_ERROR = 0x07, +} audio_AC3_decoder_control_selector_t; + +/// A.17.13.3 WMA Decoder Control Selectors +typedef enum +{ + AUDIO_WD_CTRL_UNDEF = 0x00, + AUDIO_WD_CTRL_UNDERFLOW = 0x01, + AUDIO_WD_CTRL_OVERFLOW = 0x02, + AUDIO_WD_CTRL_DECODER_ERROR = 0x03, +} audio_WMA_decoder_control_selector_t; + +/// A.17.13.4 DTS Decoder Control Selectors +typedef enum +{ + AUDIO_DD_CTRL_UNDEF = 0x00, + AUDIO_DD_CTRL_UNDERFLOW = 0x01, + AUDIO_DD_CTRL_OVERFLOW = 0x02, + AUDIO_DD_CTRL_DECODER_ERROR = 0x03, +} audio_DTS_decoder_control_selector_t; + +/// A.17.14 Endpoint Control Selectors +typedef enum +{ + AUDIO_EP_CTRL_UNDEF = 0x00, + AUDIO_EP_CTRL_PITCH = 0x01, + AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, + AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, +} audio_EP_control_selector_t; + +/// Terminal Types + +/// 2.1 - Audio Class-Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, + AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, + AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, +} audio_terminal_type_t; + +/// 2.2 - Audio Class-Input Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, + AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, + AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, + AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, + AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, + AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, + AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, +} audio_terminal_input_type_t; + +/// 2.3 - Audio Class-Output Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, + AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, + AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, + AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, + AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, + AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, + AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, + AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, +} audio_terminal_output_type_t; + +/// Rest is yet to be implemented + +/// Additional Audio Device Class Codes - Source: Audio Data Formats + +/// A.1 - Audio Class-Format Type Codes UAC2 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +// A.2.1 - Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), + AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), + AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, +} audio_data_format_type_I_t; + +/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification + +/// Audio Class-Control Values UAC2 +typedef enum +{ + AUDIO_CTRL_NONE = 0x00, ///< No Host access + AUDIO_CTRL_R = 0x01, ///< Host read access only + AUDIO_CTRL_RW = 0x03, ///< Host read write access +} audio_control_t; + +/// Audio Class-Specific AC Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, +} audio_cs_ac_interface_control_pos_t; + +/// Audio Class-Specific AS Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, + AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, +} audio_cs_as_interface_control_pos_t; + +/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, + AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, +} audio_cs_as_iso_data_ep_attribute_t; + +/// Audio Class-Specific AS Isochronous Data EP Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, +} audio_cs_as_iso_data_ep_control_pos_t; + +/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, +} audio_cs_as_iso_data_ep_lock_delay_unit_t; + +/// Audio Class-Clock Source Attributes UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, + AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, + AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, + AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, + AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, +} audio_clock_source_attribute_t; + +/// Audio Class-Clock Source Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, + AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, +} audio_clock_source_control_pos_t; + +/// Audio Class-Clock Selector Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, +} audio_clock_selector_control_pos_t; + +/// Audio Class-Clock Multiplier Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, + AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, +} audio_clock_multiplier_control_pos_t; + +/// Audio Class-Input Terminal Controls UAC2 +typedef enum +{ + AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, + AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, + AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, +} audio_terminal_input_control_pos_t; + +/// Audio Class-Output Terminal Controls UAC2 +typedef enum +{ + AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, + AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, +} audio_terminal_output_control_pos_t; + +/// Audio Class-Feature Unit Controls UAC2 +typedef enum +{ + AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, + AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, + AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, + AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, + AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, + AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, + AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, + AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, + AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, + AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, + AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, + AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, + AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, +} audio_feature_unit_control_pos_t; + +/// Audio Class-Audio Channel Configuration UAC2 +typedef enum +{ + AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, + AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, + AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, + AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, + AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, + AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, + AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, + AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, + AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, + AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, + AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, + AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, + AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, +} audio_channel_config_t; + +/// AUDIO Channel Cluster Descriptor (4.1) +typedef struct TU_ATTR_PACKED { + uint8_t bNrChannels; ///< Number of channels currently connected. + audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. + uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. +} audio_desc_channel_cluster_t; + +/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. + uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). + uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. + uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. + uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. +} audio_desc_cs_ac_interface_t; + +/// AUDIO Clock Source Descriptor (4.7.2.1) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. + uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. + uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. +} audio_desc_clock_source_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. + uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. + uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. +} audio_desc_clock_selector_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins +#define audio_desc_clock_selector_n_t(source_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; \ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bClockID ; \ + uint8_t bNrInPins ; \ + struct TU_ATTR_PACKED { \ + uint8_t baSourceID ; \ + } sourceID[source_num] ; \ + uint8_t bmControls ; \ + uint8_t iClockSource ; \ +} + +/// AUDIO Clock Multiplier Descriptor (4.7.2.3) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. + uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. +} audio_desc_clock_multiplier_t; + +/// AUDIO Input Terminal Descriptor(4.7.2.4) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. + uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. + uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. + uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. +} audio_desc_input_terminal_t; + +/// AUDIO Output Terminal Descriptor(4.7.2.5) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. + uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. + uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. + uint16_t bmControls ; ///< See: audio_terminal_output_type_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. +} audio_desc_output_terminal_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. + uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. + struct TU_ATTR_PACKED { + uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. + } controls[2] ; + uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. +} audio_desc_feature_unit_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels +#define audio_desc_feature_unit_n_t(ch_num)\ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; /* 6+(ch_num+1)*4 */\ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bUnitID ; \ + uint8_t bSourceID ; \ + struct TU_ATTR_PACKED { \ + uint32_t bmaControls ; \ + } controls[ch_num+1] ; \ + uint8_t iTerminal ; \ +} + +/// AUDIO Class-Specific AS Interface Descriptor(4.9.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. + uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. + uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. + uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. + uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. + uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. +} audio_desc_cs_as_interface_t; + +/// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. + uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. + uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. +} audio_desc_type_I_format_t; + +/// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. + uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. + uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. + uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. + uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. +} audio_desc_cs_as_iso_data_ep_t; + +// 5.2.2 Control Request Layout +typedef struct TU_ATTR_PACKED +{ + union + { + struct TU_ATTR_PACKED + { + uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. + uint8_t type : 2; ///< Request type tusb_request_type_t. + uint8_t direction : 1; ///< Direction type. tusb_dir_t + } bmRequestType_bit; + + uint8_t bmRequestType; + }; + + uint8_t bRequest; ///< Request type audio_cs_req_t + uint8_t bChannelNumber; + uint8_t bControlSelector; + union + { + uint8_t bInterface; + uint8_t bEndpoint; + }; + uint8_t bEntityID; + uint16_t wLength; +} audio_control_request_t; + +//// 5.2.3 Control Request Parameter Block Layout + +// 5.2.3.1 1-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_1_t; + +// 5.2.3.2 2-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_2_t; + +// 5.2.3.3 4-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_4_t; + +// Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like +// 5.2.3.1 1-byte Control RANGE Parameter Block +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; +} audio_control_range_1_t; + +// 5.2.3.2 2-byte Control RANGE Parameter Block +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; +} audio_control_range_2_t; + +// 5.2.3.3 4-byte Control RANGE Parameter Block +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; +} audio_control_range_4_t; + +// 5.2.3.1 1-byte Control RANGE Parameter Block +#define audio_control_range_1_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges] ; \ +} + +/// 5.2.3.2 2-byte Control RANGE Parameter Block +#define audio_control_range_2_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges]; \ +} + +// 5.2.3.3 4-byte Control RANGE Parameter Block +#define audio_control_range_4_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges]; \ +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c new file mode 100644 index 000000000..d21980060 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c @@ -0,0 +1,2294 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Reinhard Panhuber, Jerzy Kasenberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* + * This driver supports at most one out EP, one in EP, one control EP, and one feedback EP and one alternative interface other than zero. Hence, only one input terminal and one output terminal are support, if you need more adjust the driver! + * It supports multiple TX and RX channels. + * + * In case you need more alternate interfaces, you need to define additional defines for this specific alternate interface. Just define them and set them in the set_interface function. + * + * There are three data flow structures currently implemented, where at least one SW-FIFO is used to decouple the asynchronous processes MCU vs. host + * + * 1. Input data -> SW-FIFO -> MCU USB + * + * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_xfer_fifo() is available) + * + * 2. Input data -> SW-FIFO -> Linear buffer -> MCU USB + * + * In case the target MCU can not handle a SW-FIFO, a linear buffer is used. This uses the default function dcd_edpt_xfer(). In this case more memory is required. + * + * 3. (Input data 1 | Input data 2 | ... | Input data N) -> (SW-FIFO 1 | SW-FIFO 2 | ... | SW-FIFO N) -> Linear buffer -> MCU USB + * + * This case is used if you have more channels which need to be combined into one stream. Every channel has its own SW-FIFO. All data is encoded into an Linear buffer. + * + * The same holds in the RX case. + * + * */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "audio_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +// Use ring buffer if it's available, some MCUs need extra RAM requirements +#ifndef TUD_AUDIO_PREFER_RING_BUFFER +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX +#define TUD_AUDIO_PREFER_RING_BUFFER 0 +#else +#define TUD_AUDIO_PREFER_RING_BUFFER 1 +#endif +#endif + +// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer +// is available or driver is would need to be changed dramatically + +// Only STM32 synopsys and dcd_transdimension use non-linear buffer for now +// Synopsys detection copied from dcd_synopsys.c (refactor later on) +#if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ + defined (STM32F107xB) || defined (STM32F107xC) +#define STM32F1_SYNOPSYS +#endif + +#if defined (STM32L475xx) || defined (STM32L476xx) || \ + defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ + defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define STM32L4_SYNOPSYS +#endif + +#if (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ + CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ + CFG_TUSB_MCU == OPT_MCU_RX63X || \ + CFG_TUSB_MCU == OPT_MCU_RX65X || \ + CFG_TUSB_MCU == OPT_MCU_RX72N || \ + CFG_TUSB_MCU == OPT_MCU_GD32VF103 || \ + CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ + CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_MSP432E4 +#if TUD_AUDIO_PREFER_RING_BUFFER +#define USE_LINEAR_BUFFER 0 +#else +#define USE_LINEAR_BUFFER 1 +#endif +#else +#define USE_LINEAR_BUFFER 1 +#endif + +// Declaration of buffers + +// Check for maximum supported numbers +#if CFG_TUD_AUDIO > 3 +#error Maximum number of audio functions restricted to three! +#endif + +// EP IN software buffers and mutexes +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + +// Linear buffer TX in case: +// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR +// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into +#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + +// EP OUT software buffers and mutexes +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + +// Linear buffer RX in case: +// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR +// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + +// Control buffers +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; +#if CFG_TUD_AUDIO > 1 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; +#endif +#if CFG_TUD_AUDIO > 2 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; +#endif + +// Active alternate setting of interfaces +uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 +uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 +uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +#endif + +// Software encoding/decoding support FIFOs +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#endif + +typedef struct +{ + uint8_t rhport; + uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function + +#if CFG_TUD_AUDIO_ENABLE_EP_IN + uint8_t ep_in; // TX audio data EP. + uint16_t ep_in_sz; // Current size of TX EP + uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + uint8_t ep_out; // Incoming (into uC) audio data EP. + uint16_t ep_out_sz; // Current size of RX EP + uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint8_t ep_fb; // Feedback EP. +#endif + +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + uint8_t ep_int_ctr; // Audio control interrupt EP. +#endif + + /*------------- From this point, data is not cleared by bus reset -------------*/ + + uint16_t desc_length; // Length of audio function descriptor + + // Buffer for control requests + uint8_t * ctrl_buf; + uint8_t ctrl_buf_sz; + + // Current active alternate settings + uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! + + // EP Transfer buffers and FIFOs +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#if !CFG_TUD_AUDIO_ENABLE_DECODING + tu_fifo_t ep_out_ff; +#endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). +#endif +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + tu_fifo_t ep_in_ff; +#endif + + // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; +#endif + + // Decoding parameters - parameters are set when alternate AS interface is set by host + // Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently. +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + audio_format_type_t format_type_rx; + uint8_t n_channels_rx; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio_data_format_type_I_t format_type_I_rx; + uint8_t n_bytes_per_sampe_rx; + uint8_t n_channels_per_ff_rx; + uint8_t n_ff_used_rx; +#endif +#endif + + // Encoding parameters - parameters are set when alternate AS interface is set by host +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + audio_format_type_t format_type_tx; + uint8_t n_channels_tx; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + audio_data_format_type_I_t format_type_I_tx; + uint8_t n_bytes_per_sampe_tx; + uint8_t n_channels_per_ff_tx; + uint8_t n_ff_used_tx; +#endif +#endif + + // Support FIFOs for software encoding and decoding +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + tu_fifo_t * rx_supp_ff; + uint8_t n_rx_supp_ff; + uint16_t rx_supp_ff_sz_max; +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + tu_fifo_t * tx_supp_ff; + uint8_t n_tx_supp_ff; + uint16_t tx_supp_ff_sz_max; +#endif + + // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + uint8_t * lin_buf_out; +#define USE_LINEAR_BUFFER_RX 1 +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) + uint8_t * lin_buf_in; +#define USE_LINEAR_BUFFER_TX 1 +#endif + +} audiod_function_t; + +#ifndef USE_LINEAR_BUFFER_TX +#define USE_LINEAR_BUFFER_TX 0 +#endif + +#ifndef USE_LINEAR_BUFFER_RX +#define USE_LINEAR_BUFFER_RX 0 +#endif + +#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ctrl_buf) + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); +#endif + +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN +static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t* audio); +#endif + +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN +static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio); +#endif + +static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); +static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); + +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id); +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id); +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id); +static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); + +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING +static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); + +static inline uint8_t tu_desc_subtype(void const* desc) +{ + return ((uint8_t const*) desc)[2]; +} +#endif + +bool tud_audio_n_mounted(uint8_t func_id) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO); + audiod_function_t* audio = &_audiod_fct[func_id]; + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + if (audio->ep_out == 0) return false; +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN + if (audio->ep_in == 0) return false; +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + if (audio->ep_int_ctr == 0) return false; +#endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if (audio->ep_fb == 0) return false; +#endif + + return true; +} + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + +uint16_t tud_audio_n_available(uint8_t func_id) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_count(&_audiod_fct[func_id].ep_out_ff); +} + +uint16_t tud_audio_n_read(uint8_t func_id, void* buffer, uint16_t bufsize) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_read_n(&_audiod_fct[func_id].ep_out_ff, buffer, bufsize); +} + +bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); +} + +tu_fifo_t* tud_audio_n_get_ep_out_ff(uint8_t func_id) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_out_ff; + return NULL; +} + +#endif + +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT +// Delete all content in the support RX FIFOs +bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); +} + +uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); +} + +uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); +} + +tu_fifo_t* tud_audio_n_get_rx_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff) return &_audiod_fct[func_id].rx_supp_ff[ff_idx]; + return NULL; +} +#endif + +// This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_DECODING = 0. + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + +static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) +{ + uint8_t idxItf; + uint8_t const *dummy2; + uint8_t idx_audio_fct = 0; + + if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) + { + idx_audio_fct = audiod_get_audio_fct_idx(audio); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); + } + + // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); + +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT + + switch (audio->format_type_rx) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); + TU_BREAKPOINT(); + break; + + case AUDIO_FORMAT_TYPE_I: + + switch (audio->format_type_I_tx) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: + TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); + break; + + default: + // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX encoding not implemented!\r\n"); + TU_BREAKPOINT(); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented!\r\n"); + TU_BREAKPOINT(); + break; + } + + // Prepare for next transmission + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); + +#else + +#if USE_LINEAR_BUFFER_RX + // Data currently is in linear buffer, copy into EP OUT FIFO + TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); + + // Schedule for next receive + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); +#else + // Data is already placed in EP FIFO, schedule for next receive + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); +#endif + +#endif + + // Call a weak callback here - a possibility for user to get informed decoding was completed + if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); + + return true; +} + +#endif //CFG_TUD_AUDIO_ENABLE_EP_OUT + +// The following functions are used in case CFG_TUD_AUDIO_ENABLE_DECODING != 0 +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT + +// Decoding according to 2.3.1.5 Audio Streams + +// Helper function +static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) +{ + + // This function is an optimized version of + // while((uint8_t *)dst < dst_end) + // { + // memcpy(dst, src, nBytesToCopy); + // dst = (uint8_t *)dst + nBytesToCopy; + // src += nBytesToCopy * n_ff_used; + // } + + // Optimize for fast half word copies + typedef struct{ + uint16_t val; + } __attribute((__packed__)) unaligned_uint16_t; + + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + switch (nBytesToCopy) + { + case 1: + while((uint8_t *)dst < dst_end) + { + *(uint8_t *)dst++ = *src; + src += n_ff_used; + } + break; + + case 2: + while((uint8_t *)dst < dst_end) + { + *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; + dst += 2; + src += 2 * n_ff_used; + } + break; + + case 3: + while((uint8_t *)dst < dst_end) + { + // memcpy(dst, src, 3); + // dst = (uint8_t *)dst + 3; + // src += 3 * n_ff_used; + + // TODO: Is there a faster way to copy 3 bytes? + *(uint8_t *)dst++ = *src++; + *(uint8_t *)dst++ = *src++; + *(uint8_t *)dst++ = *src++; + + src += 3 * (n_ff_used - 1); + } + break; + + case 4: + while((uint8_t *)dst < dst_end) + { + *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + dst += 4; + src += 4 * n_ff_used; + } + break; + } + + return src; +} + +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) +{ + (void) rhport; + + // Determine amount of samples + uint8_t const n_ff_used = audio->n_ff_used_rx; + uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; + uint8_t cnt_ff; + + // Decode + uint8_t * src; + uint8_t * dst_end; + + tu_fifo_buffer_info_t info; + + for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) + { + tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info); + + if (info.len_lin != 0) + { + info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); + src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; + dst_end = info.ptr_lin + info.len_lin; + src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used); + + // Handle wrapped part of FIFO + info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); + if (info.len_wrap != 0) + { + dst_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used); + } + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); + } + } + + // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it + // TU_VERIFY(cnt != n_bytes); + + return true; +} +#endif //CFG_TUD_AUDIO_ENABLE_DECODING + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + +/** + * \brief Write data to EP in buffer + * + * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). + * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. + * + * \param[in] func_id: Index of audio function interface + * \param[in] data: Pointer to data array to be copied from + * \param[in] len: # of array elements to copy + * \return Number of bytes actually written + */ +uint16_t tud_audio_n_write(uint8_t func_id, const void * data, uint16_t len) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_write_n(&_audiod_fct[func_id].ep_in_ff, data, len); +} + +bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) // Delete all content in the EP IN FIFO +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); +} + +tu_fifo_t* tud_audio_n_get_ep_in_ff(uint8_t func_id) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_in_ff; + return NULL; +} + +#endif + +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN + +uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + audiod_function_t* audio = &_audiod_fct[func_id]; + + uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); + + TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio)); + + n_bytes_copied -= tu_fifo_count(&audio->tx_supp_ff[0]); + n_bytes_copied = n_bytes_copied*audio->tx_supp_ff[0].item_size; + + return n_bytes_copied; +} + +bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); +} + +uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); +} + +tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff) return &_audiod_fct[func_id].tx_supp_ff[ff_idx]; + return NULL; +} + +#endif + + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + +// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user +uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint16_t len) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + + // We write directly into the EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr)); + + // Check length + TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); + + memcpy(_audiod_fct[func_id].ep_int_ctr_buf, buffer, len); + + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr, _audiod_fct[func_id].ep_int_ctr_buf, len)); + + return true; +} + +#endif + + +// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. + +// n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. +#if CFG_TUD_AUDIO_ENABLE_EP_IN +static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) +{ + uint8_t idxItf; + uint8_t const *dummy2; + + uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); + + // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications + if (audio->alt_setting[idxItf] == 0) return false; + + // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or + // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). + if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); + + // Send everything in ISO EP FIFO + uint16_t n_bytes_tx; + + // If support FIFOs are used, encode and schedule transmit +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN + switch (audio->format_type_tx) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); + TU_BREAKPOINT(); + n_bytes_tx = 0; + break; + + case AUDIO_FORMAT_TYPE_I: + + switch (audio->format_type_I_tx) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: + + n_bytes_tx = audiod_encode_type_I_pcm(rhport, audio); + break; + + default: + // YOUR ENCODING IS REQUIRED HERE! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); + TU_BREAKPOINT(); + n_bytes_tx = 0; + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); + TU_BREAKPOINT(); + n_bytes_tx = 0; + break; + } + + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); + +#else + // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule + + n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO + +#if USE_LINEAR_BUFFER_TX + tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); +#else + // Send everything in ISO EP FIFO + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); +#endif + +#endif + + // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); + + return true; +} + +#endif //CFG_TUD_AUDIO_ENABLE_EP_IN + +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN +// Take samples from the support buffer and encode them into the IN EP software FIFO +// Returns number of bytes written into linear buffer + +/* 2.3.1.7.1 PCM Format +The PCM (Pulse Coded Modulation) format is the most commonly used audio format to represent audio +data streams. The audio data is not compressed and uses a signed two’s-complement fixed point format. It +is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused +bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the +range [-1, +1) + */ + +/* + * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples + * in the support FIFOs according to 2.3.1.5 Audio Streams. It does not control justification (left or right) and + * does not change the number of bytes per sample. + * */ + +// Helper function +static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) +{ + // Optimize for fast half word copies + typedef struct{ + uint16_t val; + } __attribute((__packed__)) unaligned_uint16_t; + + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + switch (nBytesToCopy) + { + case 1: + while(src < src_end) + { + *dst = *src++; + dst += n_ff_used; + } + break; + + case 2: + while(src < src_end) + { + *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; + src += 2; + dst += 2 * n_ff_used; + } + break; + + case 3: + while(src < src_end) + { + // memcpy(dst, src, 3); + // src = (uint8_t *)src + 3; + // dst += 3 * n_ff_used; + + // TODO: Is there a faster way to copy 3 bytes? + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + + dst += 3 * (n_ff_used - 1); + } + break; + + case 4: + while(src < src_end) + { + *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + src += 4; + dst += 4 * n_ff_used; + } + break; + } + + return dst; +} + +static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio) +{ + // This function relies on the fact that the length of the support FIFOs was configured to be a multiple of the active sample size in bytes s.t. no sample is split within a wrap + // This is ensured within set_interface, where the FIFOs are reconfigured according to this size + + // We encode directly into IN EP's linear buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); + + // Determine amount of samples + uint8_t const n_ff_used = audio->n_ff_used_tx; + uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; + uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes + uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); + uint8_t cnt_ff; + + for (cnt_ff = 1; cnt_ff < n_ff_used; cnt_ff++) + { + uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); + if (count < nBytesPerFFToSend) + { + nBytesPerFFToSend = count; + } + } + + // Check if there is enough + if (nBytesPerFFToSend == 0) return 0; + + // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! + nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); + + // Round to full number of samples (flooring) + nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; + + // Encode + uint8_t * dst; + uint8_t * src_end; + + tu_fifo_buffer_info_t info; + + for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) + { + dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; + + tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); + + if (info.len_lin != 0) + { + info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length + src_end = (uint8_t *)info.ptr_lin + info.len_lin; + dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used); + + // Limit up to desired length + info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); + + // Handle wrapped part of FIFO + if (info.len_wrap != 0) + { + src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used); + } + + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); + } + } + + return nBytesPerFFToSend * n_ff_used; +} +#endif //CFG_TUD_AUDIO_ENABLE_ENCODING + +// This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) +{ + return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->fb_val, 4); +} +#endif + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void audiod_init(void) +{ + tu_memclr(_audiod_fct, sizeof(_audiod_fct)); + + for(uint8_t i=0; ictrl_buf = ctrl_buf_1; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; + break; +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 + case 1: + audio->ctrl_buf = ctrl_buf_2; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 + case 2: + audio->ctrl_buf = ctrl_buf_3; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; + break; +#endif + } + + // Initialize active alternate interface buffers + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 + case 0: + audio->alt_setting = alt_setting_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 + case 1: + audio->alt_setting = alt_setting_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 + case 2: + audio->alt_setting = alt_setting_3; + break; +#endif + } + + // Initialize IN EP FIFO if required +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 + case 0: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_1), NULL); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 + case 1: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_2), NULL); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 + case 2: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_3), NULL); +#endif + break; +#endif + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + + // Initialize linear buffers +#if USE_LINEAR_BUFFER_TX + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 + case 0: + audio->lin_buf_in = lin_buf_in_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 + case 1: + audio->lin_buf_in = lin_buf_in_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 + case 2: + audio->lin_buf_in = lin_buf_in_3; + break; +#endif + } +#endif // USE_LINEAR_BUFFER_TX + + // Initialize OUT EP FIFO if required +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 + case 0: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_1)); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 + case 1: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_2)); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 + case 2: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_3)); +#endif + break; +#endif + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + + // Initialize linear buffers +#if USE_LINEAR_BUFFER_RX + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 + case 0: + audio->lin_buf_out = lin_buf_out_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 + case 1: + audio->lin_buf_out = lin_buf_out_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 + case 2: + audio->lin_buf_out = lin_buf_out_3; + break; +#endif + } +#endif // USE_LINEAR_BUFFER_TX + + // Initialize TX support FIFOs if required +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->tx_supp_ff = tx_supp_ff_1; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; + audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->tx_supp_ff = tx_supp_ff_2; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; + audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->tx_supp_ff = tx_supp_ff_3; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; + audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + // Set encoding parameters for Type_I formats +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX; + break; +#endif + } +#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + + // Initialize RX support FIFOs if required +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->rx_supp_ff = rx_supp_ff_1; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; + audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->rx_supp_ff = rx_supp_ff_2; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; + audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->rx_supp_ff = rx_supp_ff_3; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; + audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + // Set encoding parameters for Type_I formats +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX; + break; +#endif + } +#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + } +} + +void audiod_reset(uint8_t rhport) +{ + (void) rhport; + + for(uint8_t i=0; iep_in_ff); +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + tu_fifo_clear(&audio->ep_out_ff); +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->tx_supp_ff[cnt]); + } +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->rx_supp_ff[cnt]); + } +#endif + } +} + +uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + (void) max_len; + + TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); + + // Verify version is correct - this check can be omitted + TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); + + // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted + if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed + { + TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); + } + + // Alternate setting MUST be zero - this check can be omitted + TU_VERIFY(itf_desc->bAlternateSetting == 0); + + // Find available audio driver interface + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (!_audiod_fct[i].p_desc) + { + _audiod_fct[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one + _audiod_fct[i].rhport = rhport; + + // Setup descriptor lengths + switch (i) + { + case 0: + _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_1_DESC_LEN; + break; +#if CFG_TUD_AUDIO > 1 + case 1: + _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; + break; +#endif +#if CFG_TUD_AUDIO > 2 + case 2: + _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; + break; +#endif + } + + break; + } + } + + // Verify we found a free one + TU_ASSERT( i < CFG_TUD_AUDIO ); + + // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) + uint16_t drv_len = _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + + return drv_len; +} + +static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) +{ + uint8_t const itf = tu_u16_low(p_request->wIndex); + + // Find index of audio streaming interface + uint8_t func_id, idxItf; + uint8_t const *dummy; + + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[func_id].alt_setting[idxItf], 1)); + + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[func_id].alt_setting[idxItf]); + + return true; +} + +static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Here we need to do the following: + + // 1. Find the audio driver assigned to the given interface to be set + // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. + // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching + + // 2. Close EPs which are currently open + // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them + + // 3. Open new EP + + uint8_t const itf = tu_u16_low(p_request->wIndex); + uint8_t const alt = tu_u16_low(p_request->wValue); + + TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); + + // Find index of audio streaming interface and index of interface + uint8_t func_id, idxItf; + uint8_t const *p_desc; + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc)); + + audiod_function_t* audio = &_audiod_fct[func_id]; + + // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) +#if CFG_TUD_AUDIO_ENABLE_EP_IN + if (audio->ep_in_as_intf_num == itf) + { + audio->ep_in_as_intf_num = 0; + usbd_edpt_close(rhport, audio->ep_in); + + // Clear FIFOs, since data is no longer valid +#if !CFG_TUD_AUDIO_ENABLE_ENCODING + tu_fifo_clear(&audio->ep_in_ff); +#else + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->tx_supp_ff[cnt]); + } +#endif + + // Invoke callback - can be used to stop data sampling + if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + + audio->ep_in = 0; // Necessary? + + } +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + if (audio->ep_out_as_intf_num == itf) + { + audio->ep_out_as_intf_num = 0; + usbd_edpt_close(rhport, audio->ep_out); + + // Clear FIFOs, since data is no longer valid +#if !CFG_TUD_AUDIO_ENABLE_DECODING + tu_fifo_clear(&audio->ep_out_ff); +#else + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->rx_supp_ff[cnt]); + } +#endif + + // Invoke callback - can be used to stop data sampling + if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + + audio->ep_out = 0; // Necessary? + + // Close corresponding feedback EP +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + usbd_edpt_close(rhport, audio->ep_fb); + audio->ep_fb = 0; // Necessary? +#endif + } +#endif + + // Save current alternative interface setting + audio->alt_setting[idxItf] = alt; + + // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface + // Get pointer at end + uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; + + // p_desc starts at required interface with alternate setting zero + while (p_desc < p_desc_end) + { + // Find correct interface + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) + { +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING + uint8_t const * p_desc_parse_for_params = p_desc; +#endif + // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary + uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; + while (foundEPs < nEps && p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) + { + tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); + + uint8_t const ep_addr = desc_ep->bEndpointAddress; + + //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! + usbd_edpt_clear_stall(rhport, ep_addr); + +#if CFG_TUD_AUDIO_ENABLE_EP_IN + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 0x00) // Check if usage is data EP + { + // Save address + audio->ep_in = ep_addr; + audio->ep_in_as_intf_num = itf; + audio->ep_in_sz = tu_edpt_packet_size(desc_ep); + + // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters +#if CFG_TUD_AUDIO_ENABLE_ENCODING + audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); + + // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + const uint16_t active_fifo_depth = (audio->tx_supp_ff_sz_max / audio->n_bytes_per_sampe_tx) * audio->n_bytes_per_sampe_tx; + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) + { + tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); + } + audio->n_ff_used_tx = audio->n_channels_tx / audio->n_channels_per_ff_tx; + TU_ASSERT( audio->n_ff_used_tx <= audio->n_tx_supp_ff ); +#endif + +#endif + // Invoke callback - can be used to trigger data sampling if not already running + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + + // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded + // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary + { + // Save address + audio->ep_out = ep_addr; + audio->ep_out_as_intf_num = itf; + audio->ep_out_sz = tu_edpt_packet_size(desc_ep); + +#if CFG_TUD_AUDIO_ENABLE_DECODING + audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); + + // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sampe_rx) * audio->n_bytes_per_sampe_rx; + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) + { + tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); + } + audio->n_ff_used_rx = audio->n_channels_rx / audio->n_channels_per_ff_rx; + TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff ); +#endif +#endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // In case of asynchronous EP, call Cb after ep_fb is set + if ( !(desc_ep->bmAttributes.sync == 0x01 && audio->ep_fb == 0) ) + { + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + } +#else + // Invoke callback + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); +#endif + // Prepare for incoming data +#if USE_LINEAR_BUFFER_RX + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); +#else + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); +#endif + } + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) // Check if usage is explicit data feedback + { + audio->ep_fb = ep_addr; + + // Invoke callback after ep_out is set + if (audio->ep_out != 0) + { + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + } + } +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT + + foundEPs += 1; + } + p_desc = tu_desc_next(p_desc); + } + + TU_VERIFY(foundEPs == nEps); + + // We are done - abort loop + break; + } + + // Moving forward + p_desc = tu_desc_next(p_desc); + } + + tud_control_status(rhport, p_request); + + return true; +} + +// Invoked when class request DATA stage is finished. +// return false to stall control EP (e.g Host send non-sense DATA) +static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) +{ + // Handle audio class specific set requests + if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) + { + uint8_t func_id; + + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: + { + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + if (entityID != 0) + { + if (tud_audio_set_req_entity_cb) + { + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + } + else + { + TU_LOG2(" No entity set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + else + { + if (tud_audio_set_req_itf_cb) + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + } + else + { + TU_LOG2(" No interface set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + } + break; + + case TUSB_REQ_RCPT_ENDPOINT: + { + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + if (tud_audio_set_req_ep_cb) + { + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + + // Invoke callback + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + } + else + { + TU_LOG2(" No EP set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + break; + // Unknown/Unsupported recipient + default: TU_BREAKPOINT(); return false; + } + } + return true; +} + +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) + { + switch (p_request->bRequest) + { + case TUSB_REQ_GET_INTERFACE: + return audiod_get_interface(rhport, p_request); + + case TUSB_REQ_SET_INTERFACE: + return audiod_set_interface(rhport, p_request); + + // Unknown/Unsupported request + default: TU_BREAKPOINT(); return false; + } + } + + // Handle class requests + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + { + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t func_id; + + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: + { + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall + } + } + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall + } + } + } + } + break; + + case TUSB_REQ_RCPT_ENDPOINT: + { + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_ep_cb) + { + return tud_audio_get_req_ep_cb(rhport, p_request); + } + else + { + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall + } + } + } + break; + + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } + + // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz)); + return true; + } + + // There went something wrong - unsupported control request type + TU_BREAKPOINT(); + return false; +} + +bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage == CONTROL_STAGE_SETUP ) + { + return audiod_control_request(rhport, request); + } + else if ( stage == CONTROL_STAGE_DATA ) + { + return audiod_control_complete(rhport, request); + } + + return true; +} + +bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) result; + (void) xferred_bytes; + + // Search for interface belonging to given end point address and proceed as required + uint8_t func_id; + for (func_id = 0; func_id < CFG_TUD_AUDIO; func_id++) + { + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + + // Data transmission of control interrupt finished + if (_audiod_fct[func_id].ep_int_ctr == ep_addr) + { + // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) + // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? + // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? + + // I assume here, that things above are handled by PHY + // All transmission is done - what remains to do is to inform job was completed + + if (tud_audio_int_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, (uint16_t) xferred_bytes)); + } + +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN + + // Data transmission of audio packet finished + if (_audiod_fct[func_id].ep_in == ep_addr && _audiod_fct[func_id].alt_setting != 0) + { + // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." + // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." + // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. + + // Check if there is data to load into EPs buffer - if not load it with ZLP + // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! + // This is the only place where we can fill something into the EPs buffer! + + // Load new data + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); + + // Transmission of ZLP is done by audiod_tx_done_cb() + return true; + } +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + + // New audio packet received + if (_audiod_fct[func_id].ep_out == ep_addr) + { + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[func_id], (uint16_t) xferred_bytes)); + return true; + } + + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // Transmission of feedback EP finished + if (_audiod_fct[func_id].ep_fb == ep_addr) + { + if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); + + // Schedule a transmit with the new value if EP is not busy + if (!usbd_edpt_busy(rhport, _audiod_fct[func_id].ep_fb)) + { + // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent + return audiod_fb_send(rhport, &_audiod_fct[func_id]); + } + } +#endif +#endif + } + + return false; +} + +bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) +{ + // Handles only sending of data not receiving + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; + + // Get corresponding driver index + uint8_t func_id; + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: + { + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + } + } + break; + + case TUSB_REQ_RCPT_ENDPOINT: + { + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + } + break; + + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } + + // Crop length + if (len > _audiod_fct[func_id].ctrl_buf_sz) len = _audiod_fct[func_id].ctrl_buf_sz; + + // Copy into buffer + memcpy((void *)_audiod_fct[func_id].ctrl_buf, data, (size_t)len); + + // Schedule transmit + return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len); +} + +// This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function +// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and +// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. +static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int) +{ + if (audio->p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; + + // Advance past AC descriptors + uint8_t const *p_desc = tu_desc_next(audio->p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + uint8_t tmp = 0; + while (p_desc < p_desc_end) + { + // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0) + { + if (((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *pp_desc_int = p_desc; + return true; + } + // Increase index, bytes read, and pointer + tmp++; + } + p_desc = tu_desc_next(p_desc); + } + } + return false; +} + +// This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function +// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and +// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int) +{ + // Loop over audio driver interfaces + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) + { + *func_id = i; + return true; + } + } + + return false; +} + +// Verify an entity with the given ID exists and returns also the corresponding driver index +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + // Look for the correct driver by checking if the unique standard AC interface number fits + if (_audiod_fct[i].p_desc && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) + { + // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between + uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); // Points to CS AC descriptor + uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; + p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor + + while (p_desc < p_desc_end) + { + if (p_desc[3] == entityID) // Entity IDs are always at offset 3 + { + *func_id = i; + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_fct[i].p_desc) + { + // Get pointer at beginning and end + uint8_t const *p_desc = _audiod_fct[i].p_desc; + uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) + { + *func_id = i; + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_fct[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length; + + // Advance past AC descriptors - EP we look for are streaming EPs + uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) + { + *func_id = i; + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING +// p_desc points to the AS interface of alternate setting zero +// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter +// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! +static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf) +{ + p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor + + while (p_desc < p_desc_end) + { + // Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break; + + // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) + { +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT + if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT + if (as_itf != audio->ep_in_as_intf_num) break; +#endif +#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT + if (as_itf != audio->ep_out_as_intf_num) break; +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN + if (as_itf == audio->ep_in_as_intf_num) + { + audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; + audio->format_type_tx = (audio_format_type_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType); + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + audio->format_type_I_tx = (audio_data_format_type_I_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats); +#endif + } +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + if (as_itf == audio->ep_out_as_intf_num) + { + audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; + audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; +#endif + } +#endif + } + + // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) + { +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT + if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT + if (as_itf != audio->ep_in_as_intf_num) break; +#endif +#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT + if (as_itf != audio->ep_out_as_intf_num) break; +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN + if (as_itf == audio->ep_in_as_intf_num) + { + audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; + } +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + if (as_itf == audio->ep_out_as_intf_num) + { + audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; + } +#endif + } +#endif + + // Other format types are not supported yet + + p_desc = tu_desc_next(p_desc); + } +} +#endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + +bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + + // Format the feedback value +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION + if ( TUSB_SPEED_FULL == tud_speed_get() ) + { + uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; + + // For FS format is 10.14 + *(fb++) = (feedback >> 2) & 0xFF; + *(fb++) = (feedback >> 10) & 0xFF; + *(fb++) = (feedback >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + *fb = 0; + }else +#else + { + // Send value as-is, caller will choose the appropriate format + _audiod_fct[func_id].fb_val = feedback; + } +#endif + + // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value + if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) + { + return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]); + } + + return true; +} +#endif + +// No security checks here - internal function only which should always succeed +uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) +{ + for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO; cnt++) + { + if (&_audiod_fct[cnt] == audio) return cnt; + } + return 0; +} + +#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h new file mode 100644 index 000000000..f406cf281 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h @@ -0,0 +1,637 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Reinhard Panhuber + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_AUDIO_DEVICE_H_ +#define _TUSB_AUDIO_DEVICE_H_ + +#include "audio.h" + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +// All sizes are in bytes! + +#ifndef CFG_TUD_AUDIO_FUNC_1_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#endif + +// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces +#ifndef CFG_TUD_AUDIO_FUNC_1_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif +#endif + +// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors +#ifndef CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ +#error You must define an audio class control request buffer size! +#endif + +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ +#error You must define an audio class control request buffer size! +#endif +#endif + +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ +#error You must define an audio class control request buffer size! +#endif +#endif + +// End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 +#ifndef CFG_TUD_AUDIO_ENABLE_EP_IN +#define CFG_TUD_AUDIO_ENABLE_EP_IN 0 // TX +#endif + +#ifndef CFG_TUD_AUDIO_ENABLE_EP_OUT +#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0 // RX +#endif + +// Maximum EP sizes for all alternate AS interface settings - used for checks and buffer allocation +#if CFG_TUD_AUDIO_ENABLE_EP_IN +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT + +// Software EP FIFO buffer sizes - must be >= max EP SIZEs! +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ 0 +#endif + +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0 +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size +#endif + +#if CFG_TUD_AUDIO > 1 +#if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size +#endif +#endif + +#if CFG_TUD_AUDIO > 2 +#if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size +#endif +#endif +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size +#endif + +#if CFG_TUD_AUDIO > 1 +#if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size +#endif +#endif + +#if CFG_TUD_AUDIO > 2 +#if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size +#endif +#endif +#endif + +// Enable/disable feedback EP (required for asynchronous RX applications) +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 +#endif + +// Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set(). +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 +#endif + +// Audio interrupt control EP size - disabled if 0 +#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) +#endif + +#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#endif + +// Use software encoding/decoding + +// The software coding feature of the driver is not mandatory. It is useful if, for instance, you have two I2S streams which need to be interleaved +// into a single PCM stream as SAMPLE_1 | SAMPLE_2 | SAMPLE_3 | SAMPLE_4. +// +// Currently, only PCM type I encoding/decoding is supported! +// +// If the coding feature is to be used, support FIFOs need to be configured. Their sizes and numbers are defined below. + +// Encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the +// support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using +// - tud_audio_n_write() or +// - tud_audio_n_read(). +// To write/read to/from the support FIFOs use +// - tud_audio_n_write_support_ff() or +// - tud_audio_n_read_support_ff(). +// +// The encoding/decoding format type done is defined below. +// +// The encoding/decoding starts when the private callback functions +// - audio_tx_done_cb() +// - audio_rx_done_cb() +// are invoked. If support FIFOs are used, the corresponding encoding/decoding functions are called from there. +// Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions +// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() +// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() +// if you want to get informed what happened. +// +// If you don't use the support FIFOs you may use the public callback functions +// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() +// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() +// to write/read from/into the EP_X_SW_BUFFER_FIFOs at the right time. +// +// If you need a different encoding which is not support so far implement it in the +// - audio_tx_done_cb() +// - audio_rx_done_cb() +// functions. + +// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size +// The actual coding parameters of active AS alternate interface is parsed from the descriptors + +// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)! +// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!! + +// For PCM encoding/decoding + +#ifndef CFG_TUD_AUDIO_ENABLE_ENCODING +#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 +#endif + +#ifndef CFG_TUD_AUDIO_ENABLE_DECODING +#define CFG_TUD_AUDIO_ENABLE_DECODING 0 +#endif + +// This enabling allows to save the current coding parameters e.g. # of bytes per sample etc. - TYPE_I includes common PCM encoding +#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 +#endif + +#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING 0 +#endif + +// Type I Coding parameters not given within UAC2 descriptors +// It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING +#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif +#endif +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING +#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif +#endif +#endif + +// Remaining types not support so far + +// Number of support FIFOs to set up - multiple channels can be handled by one FIFO - very common is two channels per FIFO stemming from one I2S interface +#ifndef CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO 0 +#endif + +#ifndef CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO 0 +#endif + +// Size of support FIFOs IN BYTES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_FUNC_X_N_TX_SUPP_SW_FIFO and CFG_TUD_AUDIO_FUNC_X_N_RX_SUPP_SW_FIFO +#ifndef CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of TX channels) / (# of TX support FIFOs) * max(# of bytes per sample) +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ 0 +#endif + +#ifndef CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of RX channels) / (# of RX support FIFOs) * max(# of bytes per sample) +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ 0 +#endif + +//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); + +// Supported types of this driver: +// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup AUDIO_Serial Serial + * @{ + * \defgroup AUDIO_Serial_Device Device + * @{ */ + +//--------------------------------------------------------------------+ +// Application API (Multiple Interfaces) +// CFG_TUD_AUDIO > 1 +//--------------------------------------------------------------------+ +bool tud_audio_n_mounted (uint8_t func_id); + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +uint16_t tud_audio_n_available (uint8_t func_id); +uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); +bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO +tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id); +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING +bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs +uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); +uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); +tu_fifo_t* tud_audio_n_get_rx_support_ff (uint8_t func_id, uint8_t ff_idx); +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); +bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO +tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id); +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING +uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO +bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); +uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); +tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len); +#endif + +//--------------------------------------------------------------------+ +// Application API (Interface0) +//--------------------------------------------------------------------+ + +static inline bool tud_audio_mounted (void); + +// RX API + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +static inline uint16_t tud_audio_available (void); +static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO +static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +static inline tu_fifo_t* tud_audio_get_ep_out_ff (void); +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING +static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); +static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); +static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); +static inline tu_fifo_t* tud_audio_get_rx_support_ff (uint8_t ff_idx); +#endif + +// TX API + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +static inline uint16_t tud_audio_write (const void * data, uint16_t len); +static inline bool tud_audio_clear_ep_in_ff (void); +static inline tu_fifo_t* tud_audio_get_ep_in_ff (void); +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING +static inline uint16_t tud_audio_flush_tx_support_ff (void); +static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); +static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); +static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx); +#endif + +// INT CTR API + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); +#endif + +// Buffer control EP data and schedule a transmit +// This function is intended to be used if you do not have a persistent buffer or memory location available (e.g. non-local variables) and need to answer onto a +// get request. This function buffers your answer request frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it. +// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer pointer in pointing. If you already have such +// available you may directly use 'tud_control_xfer(...)'. In this case data does not need to be copied into an additional buffer and you save some time. +// If the request's wLength is zero, a status packet is sent instead. +bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len); + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_ENABLE_EP_IN +TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); + +// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed. +// +// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default, +// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set, then tinyusb +// expects 16.16 format and handles the conversion to 10.14 on FS. +// +// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and macOS it seems the +// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format. +bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); +static inline bool tud_audio_fb_set(uint32_t feedback); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied); +#endif + +// Invoked when audio set interface request received +TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio set interface request received which closes an EP +TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific set request received for an EP +TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); + +// Invoked when audio class specific set request received for an interface +TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); + +// Invoked when audio class specific set request received for an entity +TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); + +// Invoked when audio class specific get request received for an EP +TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an interface +TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an entity +TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ + +static inline bool tud_audio_mounted(void) +{ + return tud_audio_n_mounted(0); +} + +// RX API + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + +static inline uint16_t tud_audio_available(void) +{ + return tud_audio_n_available(0); +} + +static inline uint16_t tud_audio_read(void* buffer, uint16_t bufsize) +{ + return tud_audio_n_read(0, buffer, bufsize); +} + +static inline bool tud_audio_clear_ep_out_ff(void) +{ + return tud_audio_n_clear_ep_out_ff(0); +} + +static inline tu_fifo_t* tud_audio_get_ep_out_ff(void) +{ + return tud_audio_n_get_ep_out_ff(0); +} + +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + +static inline bool tud_audio_clear_rx_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_clear_rx_support_ff(0, ff_idx); +} + +static inline uint16_t tud_audio_available_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_available_support_ff(0, ff_idx); +} + +static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, uint16_t bufsize) +{ + return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); +} + +static inline tu_fifo_t* tud_audio_get_rx_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_get_rx_support_ff(0, ff_idx); +} + +#endif + +// TX API + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + +static inline uint16_t tud_audio_write(const void * data, uint16_t len) +{ + return tud_audio_n_write(0, data, len); +} + +static inline bool tud_audio_clear_ep_in_ff(void) +{ + return tud_audio_n_clear_ep_in_ff(0); +} + +static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) +{ + return tud_audio_n_get_ep_in_ff(0); +} + +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + +static inline uint16_t tud_audio_flush_tx_support_ff(void) +{ + return tud_audio_n_flush_tx_support_ff(0); +} + +static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_clear_tx_support_ff(0, ff_idx); +} + +static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * data, uint16_t len) +{ + return tud_audio_n_write_support_ff(0, ff_idx, data, len); +} + +static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_get_tx_support_ff(0, ff_idx); +} + +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) +{ + return tud_audio_int_ctr_n_write(0, buffer, len); +} +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +static inline bool tud_audio_fb_set(uint32_t feedback) +{ + return tud_audio_n_fb_set(0, feedback); +} +#endif + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void audiod_init (void); +void audiod_reset (uint8_t rhport); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_AUDIO_DEVICE_H_ */ + +/** @} */ +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c new file mode 100644 index 000000000..8ef609622 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c @@ -0,0 +1,258 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_BTH) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "bth_device.h" +#include + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_ev; + uint8_t ep_acl_in; + uint8_t ep_acl_out; + uint8_t ep_voice[2]; // Not used yet + uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT]; + + // Endpoint Transfer buffer + CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE]; + +} btd_interface_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf; + +static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) +{ + // skip if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(TUD_OPT_RHPORT, ep)); + + TU_ASSERT(usbd_edpt_xfer(TUD_OPT_RHPORT, ep, data, len)); + + return true; +} + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ + +bool tud_bt_event_send(void *event, uint16_t event_len) +{ + return bt_tx_data(_btd_itf.ep_ev, event, event_len); +} + +bool tud_bt_acl_data_send(void *event, uint16_t event_len) +{ + return bt_tx_data(_btd_itf.ep_acl_in, event, event_len); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void btd_init(void) +{ + tu_memclr(&_btd_itf, sizeof(_btd_itf)); +} + +void btd_reset(uint8_t rhport) +{ + (void)rhport; +} + +uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +{ + tusb_desc_endpoint_t const *desc_ep; + uint16_t drv_len = 0; + // Size of single alternative of ISO interface + const uint16_t iso_alt_itf_size = sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t); + // Size of hci interface + const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); + // Ensure this is BT Primary Controller + TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && + TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); + + TU_ASSERT(itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size); + + _btd_itf.itf_num = itf_desc->bInterfaceNumber; + + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); + _btd_itf.ep_ev = desc_ep->bEndpointAddress; + + // Open endpoint pair + TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, + &_btd_itf.ep_acl_in), 0); + + itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(tu_desc_next(desc_ep))); + + // Prepare for incoming data from host + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); + + drv_len = hci_itf_size; + + // Ensure this is still BT Primary Controller + TU_ASSERT(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && + TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); + TU_ASSERT(itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size + drv_len); + + uint8_t dir; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); + drv_len += iso_alt_itf_size; + + for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { + // Make sure rest of alternatives matches + itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); + if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || + TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || + TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) + { + // Not an Iso interface instance + break; + } + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); + drv_len += iso_alt_itf_size; + } + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) +{ + (void)rhport; + + if ( stage == CONTROL_STAGE_SETUP ) + { + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) + { + // HCI command packet addressing for single function Primary Controllers + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); + } + else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) + { + if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + { + // TODO: Set interface it would involve changing size of endpoint size + } + else + { + // HCI command packet for Primary Controller function in a composite device + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + } + } + else return false; + + return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, sizeof(_btd_itf.hci_cmd)); + } + else if ( stage == CONTROL_STAGE_DATA ) + { + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, tu_min16(request->wLength, sizeof(_btd_itf.hci_cmd))); + } + + return true; +} + +bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void)result; + + // received new data from host + if (ep_addr == _btd_itf.ep_acl_out) + { + if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes); + + // prepare for next data + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); + } + else if (ep_addr == _btd_itf.ep_ev) + { + if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes); + } + else if (ep_addr == _btd_itf.ep_acl_in) + { + if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); + } + + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h new file mode 100644 index 000000000..1b90d0915 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h @@ -0,0 +1,109 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_BTH_DEVICE_H_ +#define _TUSB_BTH_DEVICE_H_ + +#include +#include + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ +#ifndef CFG_TUD_BTH_EVENT_EPSIZE +#define CFG_TUD_BTH_EVENT_EPSIZE 16 +#endif +#ifndef CFG_TUD_BTH_DATA_EPSIZE +#define CFG_TUD_BTH_DATA_EPSIZE 64 +#endif + +typedef struct TU_ATTR_PACKED +{ + uint16_t op_code; + uint8_t param_length; + uint8_t param[255]; +} bt_hci_cmd_t; + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when HCI command was received over USB from Bluetooth host. +// Detailed format is described in Bluetooth core specification Vol 2, +// Part E, 5.4.1. +// Length of the command is from 3 bytes (2 bytes for OpCode, +// 1 byte for parameter total length) to 258. +TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); + +// Invoked when ACL data was received over USB from Bluetooth host. +// Detailed format is described in Bluetooth core specification Vol 2, +// Part E, 5.4.2. +// Length is from 4 bytes, (12 bits for Handle, 4 bits for flags +// and 16 bits for data total length) to endpoint size. +TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); + +// Called when event sent with tud_bt_event_send() was delivered to BT stack. +// Controller can release/reuse buffer with Event packet at this point. +TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes); + +// Called when ACL data that was sent with tud_bt_acl_data_send() +// was delivered to BT stack. +// Controller can release/reuse buffer with ACL packet at this point. +TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); + +// Bluetooth controller calls this function when it wants to send even packet +// as described in Bluetooth core specification Vol 2, Part E, 5.4.4. +// Event has at least 2 bytes, first is Event code second contains parameter +// total length. Controller can release/reuse event memory after +// tud_bt_event_sent_cb() is called. +bool tud_bt_event_send(void *event, uint16_t event_len); + +// Bluetooth controller calls this to send ACL data packet +// as described in Bluetooth core specification Vol 2, Part E, 5.4.2 +// Minimum length is 4 bytes, (12 bits for Handle, 4 bits for flags +// and 16 bits for data total length). Upper limit is not limited +// to endpoint size since buffer is allocate by controller +// and must not be reused till tud_bt_acl_data_sent_cb() is called. +bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void btd_init (void); +void btd_reset (uint8_t rhport); +uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool btd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *request); +bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_BTH_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h new file mode 100644 index 000000000..e345139ea --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h @@ -0,0 +1,409 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup group_class + * \defgroup ClassDriver_CDC Communication Device Class (CDC) + * Currently only Abstract Control Model subclass is supported + * @{ */ + +#ifndef _TUSB_CDC_H__ +#define _TUSB_CDC_H__ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/** \defgroup ClassDriver_CDC_Common Common Definitions + * @{ */ + +// TODO remove +/// CDC Pipe ID, used to indicate which pipe the API is addressing to (Notification, Out, In) +typedef enum +{ + CDC_PIPE_NOTIFICATION , ///< Notification pipe + CDC_PIPE_DATA_IN , ///< Data in pipe + CDC_PIPE_DATA_OUT , ///< Data out pipe + CDC_PIPE_ERROR , ///< Invalid Pipe ID +}cdc_pipeid_t; + +//--------------------------------------------------------------------+ +// CDC Communication Interface Class +//--------------------------------------------------------------------+ + +/// Communication Interface Subclass Codes +typedef enum +{ + CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01 , ///< Direct Line Control Model [USBPSTN1.2] + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL = 0x02 , ///< Abstract Control Model [USBPSTN1.2] + CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL = 0x03 , ///< Telephone Control Model [USBPSTN1.2] + CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL = 0x04 , ///< Multi-Channel Control Model [USBISDN1.2] + CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL = 0x05 , ///< CAPI Control Model [USBISDN1.2] + CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL = 0x06 , ///< Ethernet Networking Control Model [USBECM1.2] + CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL = 0x07 , ///< ATM Networking Control Model [USBATM1.2] + CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL = 0x08 , ///< Wireless Handset Control Model [USBWMC1.1] + CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT = 0x09 , ///< Device Management [USBWMC1.1] + CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL = 0x0A , ///< Mobile Direct Line Model [USBWMC1.1] + CDC_COMM_SUBCLASS_OBEX = 0x0B , ///< OBEX [USBWMC1.1] + CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL = 0x0C , ///< Ethernet Emulation Model [USBEEM1.0] + CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL = 0x0D ///< Network Control Model [USBNCM1.0] +} cdc_comm_sublcass_type_t; + +/// Communication Interface Protocol Codes +typedef enum +{ + CDC_COMM_PROTOCOL_NONE = 0x00 , ///< No specific protocol + CDC_COMM_PROTOCOL_ATCOMMAND = 0x01 , ///< AT Commands: V.250 etc + CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 = 0x02 , ///< AT Commands defined by PCCA-101 + CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO = 0x03 , ///< AT Commands defined by PCCA-101 & Annex O + CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 = 0x04 , ///< AT Commands defined by GSM 07.07 + CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 = 0x05 , ///< AT Commands defined by 3GPP 27.007 + CDC_COMM_PROTOCOL_ATCOMMAND_CDMA = 0x06 , ///< AT Commands defined by TIA for CDMA + CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL = 0x07 ///< Ethernet Emulation Model +} cdc_comm_protocol_type_t; + +//------------- SubType Descriptor in COMM Functional Descriptor -------------// +/// Communication Interface SubType Descriptor +typedef enum +{ + CDC_FUNC_DESC_HEADER = 0x00 , ///< Header Functional Descriptor, which marks the beginning of the concatenated set of functional descriptors for the interface. + CDC_FUNC_DESC_CALL_MANAGEMENT = 0x01 , ///< Call Management Functional Descriptor. + CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT = 0x02 , ///< Abstract Control Management Functional Descriptor. + CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT = 0x03 , ///< Direct Line Management Functional Descriptor. + CDC_FUNC_DESC_TELEPHONE_RINGER = 0x04 , ///< Telephone Ringer Functional Descriptor. + CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY = 0x05 , ///< Telephone Call and Line State Reporting Capabilities Functional Descriptor. + CDC_FUNC_DESC_UNION = 0x06 , ///< Union Functional Descriptor + CDC_FUNC_DESC_COUNTRY_SELECTION = 0x07 , ///< Country Selection Functional Descriptor + CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES = 0x08 , ///< Telephone Operational ModesFunctional Descriptor + CDC_FUNC_DESC_USB_TERMINAL = 0x09 , ///< USB Terminal Functional Descriptor + CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL = 0x0A , ///< Network Channel Terminal Descriptor + CDC_FUNC_DESC_PROTOCOL_UNIT = 0x0B , ///< Protocol Unit Functional Descriptor + CDC_FUNC_DESC_EXTENSION_UNIT = 0x0C , ///< Extension Unit Functional Descriptor + CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT = 0x0D , ///< Multi-Channel Management Functional Descriptor + CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT = 0x0E , ///< CAPI Control Management Functional Descriptor + CDC_FUNC_DESC_ETHERNET_NETWORKING = 0x0F , ///< Ethernet Networking Functional Descriptor + CDC_FUNC_DESC_ATM_NETWORKING = 0x10 , ///< ATM Networking Functional Descriptor + CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL = 0x11 , ///< Wireless Handset Control Model Functional Descriptor + CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL = 0x12 , ///< Mobile Direct Line Model Functional Descriptor + CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL = 0x13 , ///< MDLM Detail Functional Descriptor + CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL = 0x14 , ///< Device Management Model Functional Descriptor + CDC_FUNC_DESC_OBEX = 0x15 , ///< OBEX Functional Descriptor + CDC_FUNC_DESC_COMMAND_SET = 0x16 , ///< Command Set Functional Descriptor + CDC_FUNC_DESC_COMMAND_SET_DETAIL = 0x17 , ///< Command Set Detail Functional Descriptor + CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL = 0x18 , ///< Telephone Control Model Functional Descriptor + CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER = 0x19 , ///< OBEX Service Identifier Functional Descriptor + CDC_FUNC_DESC_NCM = 0x1A , ///< NCM Functional Descriptor +}cdc_func_desc_type_t; + +//--------------------------------------------------------------------+ +// CDC Data Interface Class +//--------------------------------------------------------------------+ + +// SUBCLASS code of Data Interface is not used and should/must be zero + +// Data Interface Protocol Codes +typedef enum{ + CDC_DATA_PROTOCOL_ISDN_BRI = 0x30, ///< Physical interface protocol for ISDN BRI + CDC_DATA_PROTOCOL_HDLC = 0x31, ///< HDLC + CDC_DATA_PROTOCOL_TRANSPARENT = 0x32, ///< Transparent + CDC_DATA_PROTOCOL_Q921_MANAGEMENT = 0x50, ///< Management protocol for Q.921 data link protocol + CDC_DATA_PROTOCOL_Q921_DATA_LINK = 0x51, ///< Data link protocol for Q.931 + CDC_DATA_PROTOCOL_Q921_TEI_MULTIPLEXOR = 0x52, ///< TEI-multiplexor for Q.921 data link protocol + CDC_DATA_PROTOCOL_V42BIS_DATA_COMPRESSION = 0x90, ///< Data compression procedures + CDC_DATA_PROTOCOL_EURO_ISDN = 0x91, ///< Euro-ISDN protocol control + CDC_DATA_PROTOCOL_V24_RATE_ADAPTION_TO_ISDN = 0x92, ///< V.24 rate adaptation to ISDN + CDC_DATA_PROTOCOL_CAPI_COMMAND = 0x93, ///< CAPI Commands + CDC_DATA_PROTOCOL_HOST_BASED_DRIVER = 0xFD, ///< Host based driver. Note: This protocol code should only be used in messages between host and device to identify the host driver portion of a protocol stack. + CDC_DATA_PROTOCOL_IN_PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0xFE ///< The protocol(s) are described using a ProtocolUnit Functional Descriptors on Communications Class Interface +}cdc_data_protocol_type_t; + +//--------------------------------------------------------------------+ +// Management Element Request (Control Endpoint) +//--------------------------------------------------------------------+ + +/// Communication Interface Management Element Request Codes +typedef enum +{ + CDC_REQUEST_SEND_ENCAPSULATED_COMMAND = 0x00, ///< is used to issue a command in the format of the supported control protocol of the Communications Class interface + CDC_REQUEST_GET_ENCAPSULATED_RESPONSE = 0x01, ///< is used to request a response in the format of the supported control protocol of the Communications Class interface. + CDC_REQUEST_SET_COMM_FEATURE = 0x02, + CDC_REQUEST_GET_COMM_FEATURE = 0x03, + CDC_REQUEST_CLEAR_COMM_FEATURE = 0x04, + + CDC_REQUEST_SET_AUX_LINE_STATE = 0x10, + CDC_REQUEST_SET_HOOK_STATE = 0x11, + CDC_REQUEST_PULSE_SETUP = 0x12, + CDC_REQUEST_SEND_PULSE = 0x13, + CDC_REQUEST_SET_PULSE_TIME = 0x14, + CDC_REQUEST_RING_AUX_JACK = 0x15, + + CDC_REQUEST_SET_LINE_CODING = 0x20, + CDC_REQUEST_GET_LINE_CODING = 0x21, + CDC_REQUEST_SET_CONTROL_LINE_STATE = 0x22, + CDC_REQUEST_SEND_BREAK = 0x23, + + CDC_REQUEST_SET_RINGER_PARMS = 0x30, + CDC_REQUEST_GET_RINGER_PARMS = 0x31, + CDC_REQUEST_SET_OPERATION_PARMS = 0x32, + CDC_REQUEST_GET_OPERATION_PARMS = 0x33, + CDC_REQUEST_SET_LINE_PARMS = 0x34, + CDC_REQUEST_GET_LINE_PARMS = 0x35, + CDC_REQUEST_DIAL_DIGITS = 0x36, + CDC_REQUEST_SET_UNIT_PARAMETER = 0x37, + CDC_REQUEST_GET_UNIT_PARAMETER = 0x38, + CDC_REQUEST_CLEAR_UNIT_PARAMETER = 0x39, + CDC_REQUEST_GET_PROFILE = 0x3A, + + CDC_REQUEST_SET_ETHERNET_MULTICAST_FILTERS = 0x40, + CDC_REQUEST_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41, + CDC_REQUEST_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42, + CDC_REQUEST_SET_ETHERNET_PACKET_FILTER = 0x43, + CDC_REQUEST_GET_ETHERNET_STATISTIC = 0x44, + + CDC_REQUEST_SET_ATM_DATA_FORMAT = 0x50, + CDC_REQUEST_GET_ATM_DEVICE_STATISTICS = 0x51, + CDC_REQUEST_SET_ATM_DEFAULT_VC = 0x52, + CDC_REQUEST_GET_ATM_VC_STATISTICS = 0x53, + + CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60, +}cdc_management_request_t; + +//--------------------------------------------------------------------+ +// Management Elemenent Notification (Notification Endpoint) +//--------------------------------------------------------------------+ + +/// 6.3 Notification Codes +typedef enum +{ + CDC_NOTIF_NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status. + CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request. + CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, + CDC_NOTIF_RING_DETECT = 0x09, + CDC_NOTIF_SERIAL_STATE = 0x20, + CDC_NOTIF_CALL_STATE_CHANGE = 0x28, + CDC_NOTIF_LINE_STATE_CHANGE = 0x29, + CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, ///< This notification allows the device to inform the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred + CDC_NOTIF_MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40, +}cdc_notification_request_t; + +//--------------------------------------------------------------------+ +// Class Specific Functional Descriptor (Communication Interface) +//--------------------------------------------------------------------+ + +// Start of all packed definitions for compiler without per-type packed +TU_ATTR_PACKED_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN + +/// Header Functional Descriptor (Communication Interface) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ + uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal +}cdc_desc_func_header_t; + +/// Union Functional Descriptor (Communication Interface) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + uint8_t bControlInterface ; ///< Interface number of Communication Interface + uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface +}cdc_desc_func_union_t; + +#define cdc_desc_func_union_n_t(no_slave)\ + struct TU_ATTR_PACKED { \ + uint8_t bLength ;\ + uint8_t bDescriptorType ;\ + uint8_t bDescriptorSubType ;\ + uint8_t bControlInterface ;\ + uint8_t bSubordinateInterface[no_slave] ;\ +} + +/// Country Selection Functional Descriptor (Communication Interface) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. + uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. +}cdc_desc_func_country_selection_t; + +#define cdc_desc_func_country_selection_n_t(no_country) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ;\ + uint8_t bDescriptorType ;\ + uint8_t bDescriptorSubType ;\ + uint8_t iCountryCodeRelDate ;\ + uint16_t wCountryCode[no_country] ;\ +} + +//--------------------------------------------------------------------+ +// PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS +//--------------------------------------------------------------------+ + +/// \brief Call Management Functional Descriptor +/// \details This functional descriptor describes the processing of calls for the Communications Class interface. +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + + struct { + uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. + uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. + uint8_t TU_RESERVED : 6; + } bmCapabilities; + + uint8_t bDataInterface; +}cdc_desc_func_call_management_t; + +typedef struct TU_ATTR_PACKED +{ + uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. + uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. + uint8_t support_send_break : 1; ///< Device supports the request Send_Break + uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. + uint8_t TU_RESERVED : 4; +}cdc_acm_capability_t; + +TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); + +/// Abstract Control Management Functional Descriptor +/// This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + cdc_acm_capability_t bmCapabilities ; +}cdc_desc_func_acm_t; + +/// \brief Direct Line Management Functional Descriptor +/// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + struct { + uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. + uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. + uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. + uint8_t TU_RESERVED : 5; + } bmCapabilities; +}cdc_desc_func_direct_line_management_t; + +/// \brief Telephone Ringer Functional Descriptor +/// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, +/// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + uint8_t bRingerVolSteps ; + uint8_t bNumRingerPatterns ; +}cdc_desc_func_telephone_ringer_t; + +/// \brief Telephone Operational Modes Functional Descriptor +/// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by +/// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + struct { + uint8_t simple_mode : 1; + uint8_t standalone_mode : 1; + uint8_t computer_centric_mode : 1; + uint8_t TU_RESERVED : 5; + } bmCapabilities; +}cdc_desc_func_telephone_operational_modes_t; + +/// \brief Telephone Call and Line State Reporting Capabilities Descriptor +/// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a +/// telephone device to report optional call and line states. +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + struct { + uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone + uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states. + uint32_t caller_id : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information. + uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns. + uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line. + uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification + uint32_t TU_RESERVED : 26; + } bmCapabilities; +}cdc_desc_func_telephone_call_state_reporting_capabilities_t; + +// TODO remove +static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) +{ + return p_desc[2]; +} + +//--------------------------------------------------------------------+ +// Requests +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED +{ + uint32_t bit_rate; + uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits + uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space + uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 +} cdc_line_coding_t; + +TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); + +typedef struct TU_ATTR_PACKED +{ + uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR. + uint16_t half_duplex_carrier_control : 1; + uint16_t : 14; +} cdc_line_control_state_t; + +TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); + +TU_ATTR_PACKED_END // End of all packed definitions +TU_ATTR_BIT_FIELD_ORDER_END + +#ifdef __cplusplus + } +#endif + +#endif + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c new file mode 100644 index 000000000..08f2af253 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c @@ -0,0 +1,486 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "cdc_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +enum +{ + BULK_PACKET_SIZE = (TUD_OPT_HIGH_SPEED ? 512 : 64) +}; + +typedef struct +{ + uint8_t itf_num; + uint8_t ep_notif; + uint8_t ep_in; + uint8_t ep_out; + + // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) + uint8_t line_state; + + /*------------- From this point, data is not cleared by bus reset -------------*/ + char wanted_char; + cdc_line_coding_t line_coding; + + // FIFO + tu_fifo_t rx_ff; + tu_fifo_t tx_ff; + + uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; + uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE]; + +#if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex; + osal_mutex_def_t tx_ff_mutex; +#endif + + // Endpoint Transfer buffer + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE]; + +}cdcd_interface_t; + +#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char) + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; + +static bool _prep_out_transaction (cdcd_interface_t* p_cdc) +{ + uint8_t const rhport = TUD_OPT_RHPORT; + uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); + + // Prepare for incoming data but only allow what we can store in the ring buffer. + // TODO Actually we can still carry out the transfer, keeping count of received bytes + // and slowly move it to the FIFO when read(). + // This pre-check reduces endpoint claiming + TU_VERIFY(available >= sizeof(p_cdc->epout_buf)); + + // claim endpoint + TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out)); + + // fifo can be changed before endpoint is claimed + available = tu_fifo_remaining(&p_cdc->rx_ff); + + if ( available >= sizeof(p_cdc->epout_buf) ) + { + return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + }else + { + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, p_cdc->ep_out); + + return false; + } +} + +//--------------------------------------------------------------------+ +// APPLICATION API +//--------------------------------------------------------------------+ +bool tud_cdc_n_connected(uint8_t itf) +{ + // DTR (bit 0) active is considered as connected + return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0); +} + +uint8_t tud_cdc_n_get_line_state (uint8_t itf) +{ + return _cdcd_itf[itf].line_state; +} + +void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding) +{ + (*coding) = _cdcd_itf[itf].line_coding; +} + +void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted) +{ + _cdcd_itf[itf].wanted_char = wanted; +} + + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ +uint32_t tud_cdc_n_available(uint8_t itf) +{ + return tu_fifo_count(&_cdcd_itf[itf].rx_ff); +} + +uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) +{ + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, bufsize); + _prep_out_transaction(p_cdc); + return num_read; +} + +bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) +{ + return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); +} + +void tud_cdc_n_read_flush (uint8_t itf) +{ + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + tu_fifo_clear(&p_cdc->rx_ff); + _prep_out_transaction(p_cdc); +} + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ +uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) +{ + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, bufsize); + + // flush if queue more than packet size + if ( tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE ) + { + tud_cdc_n_write_flush(itf); + } + + return ret; +} + +uint32_t tud_cdc_n_write_flush (uint8_t itf) +{ + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + + // Skip if usb is not ready yet + TU_VERIFY( tud_ready(), 0 ); + + // No data to send + if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; + + uint8_t const rhport = TUD_OPT_RHPORT; + + // Claim the endpoint + TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); + + // Pull data from FIFO + uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); + + if ( count ) + { + TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); + return count; + }else + { + // Release endpoint since we don't make any transfer + // Note: data is dropped if terminal is not connected + usbd_edpt_release(rhport, p_cdc->ep_in); + return 0; + } +} + +uint32_t tud_cdc_n_write_available (uint8_t itf) +{ + return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff); +} + +bool tud_cdc_n_write_clear (uint8_t itf) +{ + return tu_fifo_clear(&_cdcd_itf[itf].tx_ff); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void cdcd_init(void) +{ + tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); + + for(uint8_t i=0; iwanted_char = (char) -1; + + // default line coding is : stop bit = 1, parity = none, data bits = 8 + p_cdc->line_coding.bit_rate = 115200; + p_cdc->line_coding.stop_bits = 0; + p_cdc->line_coding.parity = 0; + p_cdc->line_coding.data_bits = 8; + + // Config RX fifo + tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); + + // Config TX fifo as overwritable at initialization and will be changed to non-overwritable + // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal. + // In this way, the most current data is prioritized. + tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); + +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, osal_mutex_create(&p_cdc->rx_ff_mutex)); + tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex), NULL); +#endif + } +} + +void cdcd_reset(uint8_t rhport) +{ + (void) rhport; + + for(uint8_t i=0; irx_ff); + tu_fifo_clear(&p_cdc->tx_ff); + tu_fifo_set_overwritable(&p_cdc->tx_ff, true); + } +} + +uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + // Only support ACM subclass + TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); + + // Find available interface + cdcd_interface_t * p_cdc = NULL; + for(uint8_t cdc_id=0; cdc_iditf_num = itf_desc->bInterfaceNumber; + + uint16_t drv_len = sizeof(tusb_desc_interface_t); + uint8_t const * p_desc = tu_desc_next( itf_desc ); + + // Communication Functional Descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) + { + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + // notification endpoint + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + + TU_ASSERT( usbd_edpt_open(rhport, desc_ep), 0 ); + p_cdc->ep_notif = desc_ep->bEndpointAddress; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + //------------- Data Interface (if any) -------------// + if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + { + // next to endpoint descriptor + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + + // Open endpoint pair + TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); + + drv_len += 2*sizeof(tusb_desc_endpoint_t); + } + + // Prepare for incoming data + _prep_out_transaction(p_cdc); + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + uint8_t itf = 0; + cdcd_interface_t* p_cdc = _cdcd_itf; + + // Identify which interface to use + for ( ; ; itf++, p_cdc++) + { + if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false; + + if ( p_cdc->itf_num == request->wIndex ) break; + } + + switch ( request->bRequest ) + { + case CDC_REQUEST_SET_LINE_CODING: + if (stage == CONTROL_STAGE_SETUP) + { + TU_LOG2(" Set Line Coding\r\n"); + tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + } + else if ( stage == CONTROL_STAGE_ACK) + { + if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); + } + break; + + case CDC_REQUEST_GET_LINE_CODING: + if (stage == CONTROL_STAGE_SETUP) + { + TU_LOG2(" Get Line Coding\r\n"); + tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + } + break; + + case CDC_REQUEST_SET_CONTROL_LINE_STATE: + if (stage == CONTROL_STAGE_SETUP) + { + tud_control_status(rhport, request); + } + else if (stage == CONTROL_STAGE_ACK) + { + // CDC PSTN v1.2 section 6.3.12 + // Bit 0: Indicates if DTE is present or not. + // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) + // Bit 1: Carrier control for half-duplex modems. + // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) + bool const dtr = tu_bit_test(request->wValue, 0); + bool const rts = tu_bit_test(request->wValue, 1); + + p_cdc->line_state = (uint8_t) request->wValue; + + // Disable fifo overwriting if DTR bit is set + tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); + + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); + + // Invoke callback + if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); + } + break; + case CDC_REQUEST_SEND_BREAK: + if (stage == CONTROL_STAGE_SETUP) + { + tud_control_status(rhport, request); + } + else if (stage == CONTROL_STAGE_ACK) + { + TU_LOG2(" Send Break\r\n"); + if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); + } + break; + + default: return false; // stall unsupported request + } + + return true; +} + +bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) result; + + uint8_t itf; + cdcd_interface_t* p_cdc; + + // Identify which interface to use + for (itf = 0; itf < CFG_TUD_CDC; itf++) + { + p_cdc = &_cdcd_itf[itf]; + if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break; + } + TU_ASSERT(itf < CFG_TUD_CDC); + + // Received new data + if ( ep_addr == p_cdc->ep_out ) + { + tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); + + // Check for wanted char and invoke callback if needed + if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) + { + for ( uint32_t i = 0; i < xferred_bytes; i++ ) + { + if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) + { + tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + } + } + } + + // invoke receive callback (if there is still data) + if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); + + // prepare for OUT transaction + _prep_out_transaction(p_cdc); + } + + // Data sent to host, we continue to fetch from tx fifo to send. + // Note: This will cause incorrect baudrate set in line coding. + // Though maybe the baudrate is not really important !!! + if ( ep_addr == p_cdc->ep_in ) + { + // invoke transmit callback to possibly refill tx fifo + if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); + + if ( 0 == tud_cdc_n_write_flush(itf) ) + { + // If there is no data left, a ZLP should be sent if + // xferred_bytes is multiple of EP Packet size and not zero + if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE-1))) ) + { + if ( usbd_edpt_claim(rhport, p_cdc->ep_in) ) + { + usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); + } + } + } + } + + // nothing to do with notif endpoint for now + + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h new file mode 100644 index 000000000..fbc7162a3 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h @@ -0,0 +1,260 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_CDC_DEVICE_H_ +#define _TUSB_CDC_DEVICE_H_ + +#include "common/tusb_common.h" +#include "cdc.h" + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ +#if !defined(CFG_TUD_CDC_EP_BUFSIZE) && defined(CFG_TUD_CDC_EPSIZE) + #warning CFG_TUD_CDC_EPSIZE is renamed to CFG_TUD_CDC_EP_BUFSIZE, please update to use the new name + #define CFG_TUD_CDC_EP_BUFSIZE CFG_TUD_CDC_EPSIZE +#endif + +#ifndef CFG_TUD_CDC_EP_BUFSIZE + #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/** \addtogroup CDC_Serial Serial + * @{ + * \defgroup CDC_Serial_Device Device + * @{ */ + +//--------------------------------------------------------------------+ +// Application API (Multiple Ports) +// CFG_TUD_CDC > 1 +//--------------------------------------------------------------------+ + +// Check if terminal is connected to this port +bool tud_cdc_n_connected (uint8_t itf); + +// Get current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) +uint8_t tud_cdc_n_get_line_state (uint8_t itf); + +// Get current line encoding: bit rate, stop bits parity etc .. +void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding); + +// Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving +void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted); + +// Get the number of bytes available for reading +uint32_t tud_cdc_n_available (uint8_t itf); + +// Read received bytes +uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize); + +// Read a byte, return -1 if there is none +static inline +int32_t tud_cdc_n_read_char (uint8_t itf); + +// Clear the received FIFO +void tud_cdc_n_read_flush (uint8_t itf); + +// Get a byte from FIFO at the specified position without removing it +bool tud_cdc_n_peek (uint8_t itf, uint8_t* ui8); + +// Write bytes to TX FIFO, data may remain in the FIFO for a while +uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); + +// Write a byte +static inline +uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); + +// Write a null-terminated string +static inline +uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); + +// Force sending data if possible, return number of forced bytes +uint32_t tud_cdc_n_write_flush (uint8_t itf); + +// Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. +uint32_t tud_cdc_n_write_available (uint8_t itf); + +// Clear the transmit FIFO +bool tud_cdc_n_write_clear (uint8_t itf); + +//--------------------------------------------------------------------+ +// Application API (Single Port) +//--------------------------------------------------------------------+ +static inline bool tud_cdc_connected (void); +static inline uint8_t tud_cdc_get_line_state (void); +static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding); +static inline void tud_cdc_set_wanted_char (char wanted); + +static inline uint32_t tud_cdc_available (void); +static inline int32_t tud_cdc_read_char (void); +static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize); +static inline void tud_cdc_read_flush (void); +static inline bool tud_cdc_peek (uint8_t* ui8); + +static inline uint32_t tud_cdc_write_char (char ch); +static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); +static inline uint32_t tud_cdc_write_str (char const* str); +static inline uint32_t tud_cdc_write_flush (void); +static inline uint32_t tud_cdc_write_available (void); +static inline bool tud_cdc_write_clear (void); + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when received new data +TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); + +// Invoked when received `wanted_char` +TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); + +// Invoked when space becomes available in TX buffer +TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf); + +// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE +TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); + +// Invoked when line coding is change via SET_LINE_CODING +TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); + +// Invoked when received send break +TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); + +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ +static inline int32_t tud_cdc_n_read_char (uint8_t itf) +{ + uint8_t ch; + return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1; +} + +static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch) +{ + return tud_cdc_n_write(itf, &ch, 1); +} + +static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str) +{ + return tud_cdc_n_write(itf, str, strlen(str)); +} + +static inline bool tud_cdc_connected (void) +{ + return tud_cdc_n_connected(0); +} + +static inline uint8_t tud_cdc_get_line_state (void) +{ + return tud_cdc_n_get_line_state(0); +} + +static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding) +{ + tud_cdc_n_get_line_coding(0, coding); +} + +static inline void tud_cdc_set_wanted_char (char wanted) +{ + tud_cdc_n_set_wanted_char(0, wanted); +} + +static inline uint32_t tud_cdc_available (void) +{ + return tud_cdc_n_available(0); +} + +static inline int32_t tud_cdc_read_char (void) +{ + return tud_cdc_n_read_char(0); +} + +static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize) +{ + return tud_cdc_n_read(0, buffer, bufsize); +} + +static inline void tud_cdc_read_flush (void) +{ + tud_cdc_n_read_flush(0); +} + +static inline bool tud_cdc_peek (uint8_t* ui8) +{ + return tud_cdc_n_peek(0, ui8); +} + +static inline uint32_t tud_cdc_write_char (char ch) +{ + return tud_cdc_n_write_char(0, ch); +} + +static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) +{ + return tud_cdc_n_write(0, buffer, bufsize); +} + +static inline uint32_t tud_cdc_write_str (char const* str) +{ + return tud_cdc_n_write_str(0, str); +} + +static inline uint32_t tud_cdc_write_flush (void) +{ + return tud_cdc_n_write_flush(0); +} + +static inline uint32_t tud_cdc_write_available(void) +{ + return tud_cdc_n_write_available(0); +} + +static inline bool tud_cdc_write_clear(void) +{ + return tud_cdc_n_write_clear(0); +} + +/** @} */ +/** @} */ + +//--------------------------------------------------------------------+ +// INTERNAL USBD-CLASS DRIVER API +//--------------------------------------------------------------------+ +void cdcd_init (void); +void cdcd_reset (uint8_t rhport); +uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CDC_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c new file mode 100644 index 000000000..f4fb6c1d6 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c @@ -0,0 +1,249 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC) + +#include "host/usbh.h" +#include "host/usbh_classdriver.h" + +#include "cdc_host.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct { + uint8_t itf_num; + uint8_t itf_protocol; + + uint8_t ep_notif; + uint8_t ep_in; + uint8_t ep_out; + + cdc_acm_capability_t acm_capability; + +} cdch_data_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +static cdch_data_t cdch_data[CFG_TUH_DEVICE_MAX]; + +static inline cdch_data_t* get_itf(uint8_t dev_addr) +{ + return &cdch_data[dev_addr-1]; +} + +bool tuh_cdc_mounted(uint8_t dev_addr) +{ + cdch_data_t* cdc = get_itf(dev_addr); + return cdc->ep_in && cdc->ep_out; +} + +bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) +{ + if ( !tuh_cdc_mounted(dev_addr) ) return false; + + cdch_data_t const * p_cdc = get_itf(dev_addr); + + switch (pipeid) + { + case CDC_PIPE_NOTIFICATION: + return usbh_edpt_busy(dev_addr, p_cdc->ep_notif ); + + case CDC_PIPE_DATA_IN: + return usbh_edpt_busy(dev_addr, p_cdc->ep_in ); + + case CDC_PIPE_DATA_OUT: + return usbh_edpt_busy(dev_addr, p_cdc->ep_out ); + + default: + return false; + } +} + +//--------------------------------------------------------------------+ +// APPLICATION API (parameter validation needed) +//--------------------------------------------------------------------+ +bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) +{ + // TODO consider all AT Command as serial candidate + return tuh_cdc_mounted(dev_addr) && + (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA); +} + +bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify) +{ + (void) is_notify; + TU_VERIFY( tuh_cdc_mounted(dev_addr) ); + TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA); + + uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; + if ( usbh_edpt_busy(dev_addr, ep_out) ) return false; + + return usbh_edpt_xfer(dev_addr, ep_out, (void*)(uintptr_t) p_data, length); +} + +bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify) +{ + (void) is_notify; + TU_VERIFY( tuh_cdc_mounted(dev_addr) ); + TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA); + + uint8_t const ep_in = cdch_data[dev_addr-1].ep_in; + if ( usbh_edpt_busy(dev_addr, ep_in) ) return false; + + return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); +} + +bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb) +{ + cdch_data_t const * p_cdc = get_itf(dev_addr); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, + .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0), + .wIndex = p_cdc->itf_num, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, complete_cb) ); + return true; +} + +//--------------------------------------------------------------------+ +// USBH-CLASS DRIVER API +//--------------------------------------------------------------------+ +void cdch_init(void) +{ + tu_memclr(cdch_data, sizeof(cdch_data)); +} + +bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +{ + (void) max_len; + + // Only support ACM subclass + // Protocol 0xFF can be RNDIS device for windows XP + TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0xFF != itf_desc->bInterfaceProtocol); + + cdch_data_t * p_cdc = get_itf(dev_addr); + + p_cdc->itf_num = itf_desc->bInterfaceNumber; + p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; + + //------------- Communication Interface -------------// + uint16_t drv_len = tu_desc_len(itf_desc); + uint8_t const * p_desc = tu_desc_next(itf_desc); + + // Communication Functional Descriptors + while( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) + { + if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) + { + // save ACM bmCapabilities + p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; + } + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + // notification endpoint + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + p_cdc->ep_notif = desc_ep->bEndpointAddress; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + //------------- Data Interface (if any) -------------// + if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + { + // next to endpoint descriptor + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + + // data endpoints expected to be in pairs + for(uint32_t i=0; i<2; i++) + { + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); + + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); + + if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) + { + p_cdc->ep_in = desc_ep->bEndpointAddress; + }else + { + p_cdc->ep_out = desc_ep->bEndpointAddress; + } + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next( p_desc ); + } + } + + return true; +} + +bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + (void) dev_addr; (void) itf_num; + return true; +} + +bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +{ + (void) ep_addr; + tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes ); + return true; +} + +void cdch_close(uint8_t dev_addr) +{ + TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); + + cdch_data_t * p_cdc = get_itf(dev_addr); + tu_memclr(p_cdc, sizeof(cdch_data_t)); +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h new file mode 100644 index 000000000..0d435138b --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h @@ -0,0 +1,134 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_CDC_HOST_H_ +#define _TUSB_CDC_HOST_H_ + +#include "cdc.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// CDC APPLICATION PUBLIC API +//--------------------------------------------------------------------+ +/** \ingroup ClassDriver_CDC Communication Device Class (CDC) + * \addtogroup CDC_Serial Serial + * @{ + * \defgroup CDC_Serial_Host Host + * @{ */ + +bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb); + +static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) +{ + return tuh_cdc_set_control_line_state(dev_addr, true, true, complete_cb); +} + +static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) +{ + return tuh_cdc_set_control_line_state(dev_addr, false, false, complete_cb); +} + +/** \brief Check if device support CDC Serial interface or not + * \param[in] dev_addr device address + * \retval true if device supports + * \retval false if device does not support or is not mounted + */ +bool tuh_cdc_serial_is_mounted(uint8_t dev_addr); + +/** \brief Check if the interface is currently busy or not + * \param[in] dev_addr device address + * \param[in] pipeid value from \ref cdc_pipeid_t to indicate target pipe. + * \retval true if the interface is busy, meaning the stack is still transferring/waiting data from/to device + * \retval false if the interface is not busy, meaning the stack successfully transferred data from/to device + * \note This function is used to check if previous transfer is complete (success or error), so that the next transfer + * can be scheduled. User needs to make sure the corresponding interface is mounted + * (by \ref tuh_cdc_serial_is_mounted) before calling this function. + */ +bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid); + +/** \brief Perform USB OUT transfer to device + * \param[in] dev_addr device address + * \param[in] p_data Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) + * \param[in] length Number of bytes to be transferred via USB bus + * \retval TUSB_ERROR_NONE on success + * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device + * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) + * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct + * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the + * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION. + */ +bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify); + +/** \brief Perform USB IN transfer to get data from device + * \param[in] dev_addr device address + * \param[in] p_buffer Buffer containing received data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) + * \param[in] length Number of bytes to be transferred via USB bus + * \retval TUSB_ERROR_NONE on success + * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device + * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) + * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct + * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the + * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION. + */ +bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify); + +//--------------------------------------------------------------------+ +// CDC APPLICATION CALLBACKS +//--------------------------------------------------------------------+ + +/** \brief Callback function that is invoked when an transferring event occurred + * \param[in] dev_addr Address of device + * \param[in] event an value from \ref xfer_result_t + * \param[in] pipe_id value from \ref cdc_pipeid_t indicate the pipe + * \param[in] xferred_bytes Number of bytes transferred via USB bus + * \note event can be one of following + * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. + * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. + * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. + * \note + */ +void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes); + +/// @} // group CDC_Serial_Host +/// @} + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void cdch_init (void); +bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); +bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void cdch_close (uint8_t dev_addr); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CDC_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h new file mode 100644 index 000000000..e0f129fe3 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h @@ -0,0 +1,301 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup ClassDriver_CDC Communication Device Class (CDC) + * \defgroup CDC_RNDIS Remote Network Driver Interface Specification (RNDIS) + * @{ + * \defgroup CDC_RNDIS_Common Common Definitions + * @{ */ + +#ifndef _TUSB_CDC_RNDIS_H_ +#define _TUSB_CDC_RNDIS_H_ + +#include "cdc.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef __CC_ARM +#pragma diag_suppress 66 // Suppress Keil warnings #66-D: enumeration value is out of "int" range +#endif + +/// RNDIS Message Types +typedef enum +{ + RNDIS_MSG_PACKET = 0x00000001UL, ///< The host and device use this to send network data to one another. + + RNDIS_MSG_INITIALIZE = 0x00000002UL, ///< Sent by the host to initialize the device. + RNDIS_MSG_INITIALIZE_CMPLT = 0x80000002UL, ///< Device response to an initialize message. + + RNDIS_MSG_HALT = 0x00000003UL, ///< Sent by the host to halt the device. This does not have a response. It is optional for the device to send this message to the host. + + RNDIS_MSG_QUERY = 0x00000004UL, ///< Sent by the host to send a query OID. + RNDIS_MSG_QUERY_CMPLT = 0x80000004UL, ///< Device response to a query OID. + + RNDIS_MSG_SET = 0x00000005UL, ///< Sent by the host to send a set OID. + RNDIS_MSG_SET_CMPLT = 0x80000005UL, ///< Device response to a set OID. + + RNDIS_MSG_RESET = 0x00000006UL, ///< Sent by the host to perform a soft reset on the device. + RNDIS_MSG_RESET_CMPLT = 0x80000006UL, ///< Device response to reset message. + + RNDIS_MSG_INDICATE_STATUS = 0x00000007UL, ///< Sent by the device to indicate its status or an error when an unrecognized message is received. + + RNDIS_MSG_KEEP_ALIVE = 0x00000008UL, ///< During idle periods, sent every few seconds by the host to check that the device is still responsive. It is optional for the device to send this message to check if the host is active. + RNDIS_MSG_KEEP_ALIVE_CMPLT = 0x80000008UL ///< The device response to a keepalivemessage. The host can respond with this message to a keepalive message from the device when the device implements the optional KeepAliveTimer. +}rndis_msg_type_t; + +/// RNDIS Message Status Values +typedef enum +{ + RNDIS_STATUS_SUCCESS = 0x00000000UL, ///< Success + RNDIS_STATUS_FAILURE = 0xC0000001UL, ///< Unspecified error + RNDIS_STATUS_INVALID_DATA = 0xC0010015UL, ///< Invalid data error + RNDIS_STATUS_NOT_SUPPORTED = 0xC00000BBUL, ///< Unsupported request error + RNDIS_STATUS_MEDIA_CONNECT = 0x4001000BUL, ///< Device is connected to a network medium. + RNDIS_STATUS_MEDIA_DISCONNECT = 0x4001000CUL ///< Device is disconnected from the medium. +}rndis_msg_status_t; + +#ifdef __CC_ARM +#pragma diag_default 66 // return Keil 66 to normal severity +#endif + +//--------------------------------------------------------------------+ +// MESSAGE STRUCTURE +//--------------------------------------------------------------------+ + +//------------- Initialize -------------// +/// \brief Initialize Message +/// \details This message MUST be sent by the host to initialize the device. +typedef struct { + uint32_t type ; ///< Message type, must be \ref RNDIS_MSG_INITIALIZE + uint32_t length ; ///< Message length in bytes, must be 0x18 + uint32_t request_id ; ///< A 32-bit integer value, generated by the host, used to match the host's sent request to the response from the device. + uint32_t major_version ; ///< The major version of the RNDIS Protocol implemented by the host. + uint32_t minor_version ; ///< The minor version of the RNDIS Protocol implemented by the host + uint32_t max_xfer_size ; ///< The maximum size, in bytes, of any single bus data transfer that the host expects to receive from the device. +}rndis_msg_initialize_t; + +/// \brief Initialize Complete Message +/// \details This message MUST be sent by the device in response to an initialize message. +typedef struct { + uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_INITIALIZE_CMPLT + uint32_t length ; ///< Message length in bytes, must be 0x30 + uint32_t request_id ; ///< A 32-bit integer value from \a request_id field of the \ref rndis_msg_initialize_t to which this message is a response. + uint32_t status ; ///< The initialization status of the device, has value from \ref rndis_msg_status_t + uint32_t major_version ; ///< the highest-numbered RNDIS Protocol version supported by the device. + uint32_t minor_version ; ///< the highest-numbered RNDIS Protocol version supported by the device. + uint32_t device_flags ; ///< MUST be set to 0x000000010. Other values are reserved for future use. + uint32_t medium ; ///< is 0x00 for RNDIS_MEDIUM_802_3 + uint32_t max_packet_per_xfer ; ///< The maximum number of concatenated \ref RNDIS_MSG_PACKET messages that the device can handle in a single bus transfer to it. This value MUST be at least 1. + uint32_t max_xfer_size ; ///< The maximum size, in bytes, of any single bus data transfer that the device expects to receive from the host. + uint32_t packet_alignment_factor ; ///< The byte alignment the device expects for each RNDIS message that is part of a multimessage transfer to it. The value is specified as an exponent of 2; for example, the host uses 2{PacketAlignmentFactor} as the alignment value. + uint32_t reserved[2] ; +} rndis_msg_initialize_cmplt_t; + +//------------- Query -------------// +/// \brief Query Message +/// \details This message MUST be sent by the host to query an OID. +typedef struct { + uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_QUERY + uint32_t length ; ///< Message length in bytes, including the header and the \a oid_buffer + uint32_t request_id ; ///< A 32-bit integer value, generated by the host, used to match the host's sent request to the response from the device. + uint32_t oid ; ///< The integer value of the host operating system-defined identifier, for the parameter of the device being queried for. + uint32_t buffer_length ; ///< The length, in bytes, of the input data required for the OID query. This MUST be set to 0 when there is no input data associated with the OID. + uint32_t buffer_offset ; ///< The offset, in bytes, from the beginning of \a request_id field where the input data for the query is located in the message. This value MUST be set to 0 when there is no input data associated with the OID. + uint32_t reserved ; + uint8_t oid_buffer[] ; ///< Flexible array contains the input data supplied by the host, required for the OID query request processing by the device, as per the host NDIS specification. +} rndis_msg_query_t, rndis_msg_set_t; + +TU_VERIFY_STATIC(sizeof(rndis_msg_query_t) == 28, "Make sure flexible array member does not affect layout"); + +/// \brief Query Complete Message +/// \details This message MUST be sent by the device in response to a query OID message. +typedef struct { + uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_QUERY_CMPLT + uint32_t length ; ///< Message length in bytes, including the header and the \a oid_buffer + uint32_t request_id ; ///< A 32-bit integer value from \a request_id field of the \ref rndis_msg_query_t to which this message is a response. + uint32_t status ; ///< The status of processing for the query request, has value from \ref rndis_msg_status_t. + uint32_t buffer_length ; ///< The length, in bytes, of the data in the response to the query. This MUST be set to 0 when there is no OIDInputBuffer. + uint32_t buffer_offset ; ///< The offset, in bytes, from the beginning of \a request_id field where the response data for the query is located in the message. This MUST be set to 0 when there is no \ref oid_buffer. + uint8_t oid_buffer[] ; ///< Flexible array member contains the response data to the OID query request as specified by the host. +} rndis_msg_query_cmplt_t; + +TU_VERIFY_STATIC(sizeof(rndis_msg_query_cmplt_t) == 24, "Make sure flexible array member does not affect layout"); + +//------------- Reset -------------// +/// \brief Reset Message +/// \details This message MUST be sent by the host to perform a soft reset on the device. +typedef struct { + uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_RESET + uint32_t length ; ///< Message length in bytes, MUST be 0x06 + uint32_t reserved ; +} rndis_msg_reset_t; + +/// \brief Reset Complete Message +/// \details This message MUST be sent by the device in response to a reset message. +typedef struct { + uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_RESET_CMPLT + uint32_t length ; ///< Message length in bytes, MUST be 0x10 + uint32_t status ; ///< The status of processing for the \ref rndis_msg_reset_t, has value from \ref rndis_msg_status_t. + uint32_t addressing_reset ; ///< This field indicates whether the addressing information, which is the multicast address list or packet filter, has been lost during the reset operation. This MUST be set to 0x00000001 if the device requires that the host to resend addressing information or MUST be set to zero otherwise. +} rndis_msg_reset_cmplt_t; + +//typedef struct { +// uint32_t type; +// uint32_t length; +// uint32_t status; +// uint32_t buffer_length; +// uint32_t buffer_offset; +// uint32_t diagnostic_status; // optional +// uint32_t diagnostic_error_offset; // optional +// uint32_t status_buffer[0]; // optional +//} rndis_msg_indicate_status_t; + +/// \brief Keep Alive Message +/// \details This message MUST be sent by the host to check that device is still responsive. It is optional for the device to send this message to check if the host is active +typedef struct { + uint32_t type ; ///< Message Type + uint32_t length ; ///< Message length in bytes, MUST be 0x10 + uint32_t request_id ; +} rndis_msg_keep_alive_t, rndis_msg_halt_t; + +/// \brief Set Complete Message +/// \brief This message MUST be sent in response to a the request message +typedef struct { + uint32_t type ; ///< Message Type + uint32_t length ; ///< Message length in bytes, MUST be 0x10 + uint32_t request_id ; ///< must be the same as requesting message + uint32_t status ; ///< The status of processing for the request message request by the device to which this message is the response. +} rndis_msg_set_cmplt_t, rndis_msg_keep_alive_cmplt_t; + +/// \brief Packet Data Message +/// \brief This message MUST be used by the host and the device to send network data to one another. +typedef struct { + uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_PACKET + uint32_t length ; ///< Message length in bytes, The total length of this RNDIS message including the header, payload, and padding. + uint32_t data_offset ; ///< Specifies the offset, in bytes, from the start of this \a data_offset field of this message to the start of the data. This MUST be an integer multiple of 4. + uint32_t data_length ; ///< Specifies the number of bytes in the payload of this message. + uint32_t out_of_band_data_offet ; ///< Specifies the offset, in bytes, of the first out-of-band data record from the start of the DataOffset field in this message. MUST be an integer multiple of 4 when out-of-band data is present or set to 0 otherwise. When there are multiple out-ofband data records, each subsequent record MUST immediately follow the previous out-of-band data record. + uint32_t out_of_band_data_length ; ///< Specifies, in bytes, the total length of the out-of-band data. + uint32_t num_out_of_band_data_elements ; ///< Specifies the number of out-of-band records in this message. + uint32_t per_packet_info_offset ; ///< Specifies the offset, in bytes, of the start of per-packet-info data record from the start of the \a data_offset field in this message. MUST be an integer multiple of 4 when per-packet-info data record is present or MUST be set to 0 otherwise. When there are multiple per-packet-info data records, each subsequent record MUST immediately follow the previous record. + uint32_t per_packet_info_length ; ///< Specifies, in bytes, the total length of per-packetinformation contained in this message. + uint32_t reserved[2] ; + uint32_t payload[0] ; ///< Network data contained in this message. + + // uint8_t padding[0] + // Additional bytes of zeros added at the end of the message to comply with + // the internal and external padding requirements. Internal padding SHOULD be as per the + // specification of the out-of-band data record and per-packet-info data record. The external + //padding size SHOULD be determined based on the PacketAlignmentFactor field specification + //in REMOTE_NDIS_INITIALIZE_CMPLT message by the device, when multiple + //REMOTE_NDIS_PACKET_MSG messages are bundled together in a single bus-native message. + //In this case, all but the very last REMOTE_NDIS_PACKET_MSG MUST respect the + //PacketAlignmentFactor field. + + // rndis_msg_packet_t [0] : (optional) more packet if multiple packet per bus transaction is supported +} rndis_msg_packet_t; + + +typedef struct { + uint32_t size ; ///< Length, in bytes, of this header and appended data and padding. This value MUST be an integer multiple of 4. + uint32_t type ; ///< MUST be as per host operating system specification. + uint32_t offset ; ///< The byte offset from the beginning of this record to the beginning of data. + uint32_t data[0] ; ///< Flexible array contains data +} rndis_msg_out_of_band_data_t, rndis_msg_per_packet_info_t; + +//--------------------------------------------------------------------+ +// NDIS Object ID +//--------------------------------------------------------------------+ + +/// NDIS Object ID +typedef enum +{ + //------------- General Required OIDs -------------// + RNDIS_OID_GEN_SUPPORTED_LIST = 0x00010101, ///< List of supported OIDs + RNDIS_OID_GEN_HARDWARE_STATUS = 0x00010102, ///< Hardware status + RNDIS_OID_GEN_MEDIA_SUPPORTED = 0x00010103, ///< Media types supported (encoded) + RNDIS_OID_GEN_MEDIA_IN_USE = 0x00010104, ///< Media types in use (encoded) + RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD = 0x00010105, ///< + RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE = 0x00010106, ///< Maximum frame size in bytes + RNDIS_OID_GEN_LINK_SPEED = 0x00010107, ///< Link speed in units of 100 bps + RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE = 0x00010108, ///< Transmit buffer space + RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE = 0x00010109, ///< Receive buffer space + RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE = 0x0001010A, ///< Minimum amount of storage, in bytes, that a single packet occupies in the transmit buffer space of the NIC + RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE = 0x0001010B, ///< Amount of storage, in bytes, that a single packet occupies in the receive buffer space of the NIC + RNDIS_OID_GEN_VENDOR_ID = 0x0001010C, ///< Vendor NIC code + RNDIS_OID_GEN_VENDOR_DESCRIPTION = 0x0001010D, ///< Vendor network card description + RNDIS_OID_GEN_CURRENT_PACKET_FILTER = 0x0001010E, ///< Current packet filter (encoded) + RNDIS_OID_GEN_CURRENT_LOOKAHEAD = 0x0001010F, ///< Current lookahead size in bytes + RNDIS_OID_GEN_DRIVER_VERSION = 0x00010110, ///< NDIS version number used by the driver + RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE = 0x00010111, ///< Maximum total packet length in bytes + RNDIS_OID_GEN_PROTOCOL_OPTIONS = 0x00010112, ///< Optional protocol flags (encoded) + RNDIS_OID_GEN_MAC_OPTIONS = 0x00010113, ///< Optional NIC flags (encoded) + RNDIS_OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114, ///< Whether the NIC is connected to the network + RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS = 0x00010115, ///< The maximum number of send packets the driver can accept per call to its MiniportSendPacketsfunction + + //------------- General Optional OIDs -------------// + RNDIS_OID_GEN_VENDOR_DRIVER_VERSION = 0x00010116, ///< Vendor-assigned version number of the driver + RNDIS_OID_GEN_SUPPORTED_GUIDS = 0x00010117, ///< The custom GUIDs (Globally Unique Identifier) supported by the miniport driver + RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES = 0x00010118, ///< List of network-layer addresses associated with the binding between a transport and the driver + RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET = 0x00010119, ///< Size of packets' additional headers + RNDIS_OID_GEN_MEDIA_CAPABILITIES = 0x00010201, ///< + RNDIS_OID_GEN_PHYSICAL_MEDIUM = 0x00010202, ///< Physical media supported by the miniport driver (encoded) + + //------------- 802.3 Objects (Ethernet) -------------// + RNDIS_OID_802_3_PERMANENT_ADDRESS = 0x01010101, ///< Permanent station address + RNDIS_OID_802_3_CURRENT_ADDRESS = 0x01010102, ///< Current station address + RNDIS_OID_802_3_MULTICAST_LIST = 0x01010103, ///< Current multicast address list + RNDIS_OID_802_3_MAXIMUM_LIST_SIZE = 0x01010104, ///< Maximum size of multicast address list +} rndis_oid_type_t; + +/// RNDIS Packet Filter Bits \ref RNDIS_OID_GEN_CURRENT_PACKET_FILTER. +typedef enum +{ + RNDIS_PACKET_TYPE_DIRECTED = 0x00000001, ///< Directed packets. Directed packets contain a destination address equal to the station address of the NIC. + RNDIS_PACKET_TYPE_MULTICAST = 0x00000002, ///< Multicast address packets sent to addresses in the multicast address list. + RNDIS_PACKET_TYPE_ALL_MULTICAST = 0x00000004, ///< All multicast address packets, not just the ones enumerated in the multicast address list. + RNDIS_PACKET_TYPE_BROADCAST = 0x00000008, ///< Broadcast packets. + RNDIS_PACKET_TYPE_SOURCE_ROUTING = 0x00000010, ///< All source routing packets. If the protocol driver sets this bit, the NDIS library attempts to act as a source routing bridge. + RNDIS_PACKET_TYPE_PROMISCUOUS = 0x00000020, ///< Specifies all packets regardless of whether VLAN filtering is enabled or not and whether the VLAN identifier matches or not. + RNDIS_PACKET_TYPE_SMT = 0x00000040, ///< SMT packets that an FDDI NIC receives. + RNDIS_PACKET_TYPE_ALL_LOCAL = 0x00000080, ///< All packets sent by installed protocols and all packets indicated by the NIC that is identified by a given NdisBindingHandle. + RNDIS_PACKET_TYPE_GROUP = 0x00001000, ///< Packets sent to the current group address. + RNDIS_PACKET_TYPE_ALL_FUNCTIONAL = 0x00002000, ///< All functional address packets, not just the ones in the current functional address. + RNDIS_PACKET_TYPE_FUNCTIONAL = 0x00004000, ///< Functional address packets sent to addresses included in the current functional address. + RNDIS_PACKET_TYPE_MAC_FRAME = 0x00008000, ///< NIC driver frames that a Token Ring NIC receives. + RNDIS_PACKET_TYPE_NO_LOCAL = 0x00010000, +} rndis_packet_filter_type_t; + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CDC_RNDIS_H_ */ + +/** @} */ +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c new file mode 100644 index 000000000..cc4ffd1cf --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c @@ -0,0 +1,279 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC && CFG_TUH_CDC_RNDIS) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "common/tusb_common.h" +#include "cdc_host.h" +#include "cdc_rndis_host.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +#define RNDIS_MSG_PAYLOAD_MAX (1024*4) + +CFG_TUSB_MEM_SECTION static uint8_t msg_notification[CFG_TUH_DEVICE_MAX][8]; +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX]; + +static rndish_data_t rndish_data[CFG_TUH_DEVICE_MAX]; + +// TODO Microsoft requires message length for any get command must be at least 4096 bytes + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +static tusb_error_t rndis_body_subtask(void); +static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, + uint8_t * p_mess, uint32_t mess_length, + uint8_t *p_response ); + +//--------------------------------------------------------------------+ +// APPLICATION API +//--------------------------------------------------------------------+ +tusb_error_t tusbh_cdc_rndis_get_mac_addr(uint8_t dev_addr, uint8_t mac_address[6]) +{ + TU_ASSERT( tusbh_cdc_rndis_is_mounted(dev_addr), TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED); + TU_VERIFY( mac_address, TUSB_ERROR_INVALID_PARA); + + memcpy(mac_address, rndish_data[dev_addr-1].mac_address, 6); + + return TUSB_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// IMPLEMENTATION +//--------------------------------------------------------------------+ + +// To enable the TASK_ASSERT style (quick return on false condition) in a real RTOS, a task must act as a wrapper +// and is used mainly to call subtasks. Within a subtask return statement can be called freely, the task with +// forever loop cannot have any return at all. +OSAL_TASK_FUNCTION(cdch_rndis_task) (void* param;) +{ + OSAL_TASK_BEGIN + rndis_body_subtask(); + OSAL_TASK_END +} + +static tusb_error_t rndis_body_subtask(void) +{ + static uint8_t relative_addr; + + OSAL_SUBTASK_BEGIN + + for (relative_addr = 0; relative_addr < CFG_TUH_DEVICE_MAX; relative_addr++) + { + + } + + osal_task_delay(100); + + OSAL_SUBTASK_END +} + +//--------------------------------------------------------------------+ +// RNDIS-CDC Driver API +//--------------------------------------------------------------------+ +void rndish_init(void) +{ + tu_memclr(rndish_data, sizeof(rndish_data_t)*CFG_TUH_DEVICE_MAX); + + //------------- Task creation -------------// + + //------------- semaphore creation for notificaiton pipe -------------// + for(uint8_t i=0; itype == RNDIS_MSG_INITIALIZE_CMPLT && p_init_cmpt->status == RNDIS_STATUS_SUCCESS && + p_init_cmpt->max_packet_per_xfer == 1 && p_init_cmpt->max_xfer_size <= RNDIS_MSG_PAYLOAD_MAX); + rndish_data[dev_addr-1].max_xfer_size = p_init_cmpt->max_xfer_size; + + //------------- Message Query 802.3 Permanent Address -------------// + memcpy(msg_payload, &msg_query_permanent_addr, sizeof(rndis_msg_query_t)); + tu_memclr(msg_payload + sizeof(rndis_msg_query_t), 6); // 6 bytes for MAC address + + STASK_INVOKE( + send_message_get_response_subtask( dev_addr, p_cdc, + msg_payload, sizeof(rndis_msg_query_t) + 6, + msg_payload), + error + ); + if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); + + rndis_msg_query_cmplt_t * const p_query_cmpt = (rndis_msg_query_cmplt_t *) msg_payload; + STASK_ASSERT(p_query_cmpt->type == RNDIS_MSG_QUERY_CMPLT && p_query_cmpt->status == RNDIS_STATUS_SUCCESS); + memcpy(rndish_data[dev_addr-1].mac_address, msg_payload + 8 + p_query_cmpt->buffer_offset, 6); + + //------------- Set OID_GEN_CURRENT_PACKET_FILTER to (DIRECTED | MULTICAST | BROADCAST) -------------// + memcpy(msg_payload, &msg_set_packet_filter, sizeof(rndis_msg_set_t)); + tu_memclr(msg_payload + sizeof(rndis_msg_set_t), 4); // 4 bytes for filter flags + ((rndis_msg_set_t*) msg_payload)->oid_buffer[0] = (RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_MULTICAST | RNDIS_PACKET_TYPE_BROADCAST); + + STASK_INVOKE( + send_message_get_response_subtask( dev_addr, p_cdc, + msg_payload, sizeof(rndis_msg_set_t) + 4, + msg_payload), + error + ); + if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); + + rndis_msg_set_cmplt_t * const p_set_cmpt = (rndis_msg_set_cmplt_t *) msg_payload; + STASK_ASSERT(p_set_cmpt->type == RNDIS_MSG_SET_CMPLT && p_set_cmpt->status == RNDIS_STATUS_SUCCESS); + + tusbh_cdc_rndis_mounted_cb(dev_addr); + + OSAL_SUBTASK_END +} + +void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) +{ + if ( pipehandle_is_equal(pipe_hdl, p_cdc->pipe_notification) ) + { + osal_semaphore_post( rndish_data[pipe_hdl.dev_addr-1].sem_notification_hdl ); + } +} + +//--------------------------------------------------------------------+ +// INTERNAL & HELPER +//--------------------------------------------------------------------+ +static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, + uint8_t * p_mess, uint32_t mess_length, + uint8_t *p_response) +{ + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + //------------- Send RNDIS Control Message -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), + CDC_REQUEST_SEND_ENCAPSULATED_COMMAND, 0, p_cdc->interface_number, + mess_length, p_mess), + error + ); + if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); + + //------------- waiting for Response Available notification -------------// + (void) usbh_edpt_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8); + osal_semaphore_wait(rndish_data[dev_addr-1].sem_notification_hdl, OSAL_TIMEOUT_NORMAL, &error); + if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); + STASK_ASSERT(msg_notification[dev_addr-1][0] == 1); + + //------------- Get RNDIS Message Initialize Complete -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), + CDC_REQUEST_GET_ENCAPSULATED_RESPONSE, 0, p_cdc->interface_number, + RNDIS_MSG_PAYLOAD_MAX, p_response), + error + ); + if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); + + OSAL_SUBTASK_END +} + +//static tusb_error_t send_process_msg_initialize_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) +//{ +// tusb_error_t error; +// +// OSAL_SUBTASK_BEGIN +// +// *((rndis_msg_initialize_t*) msg_payload) = (rndis_msg_initialize_t) +// { +// .type = RNDIS_MSG_INITIALIZE, +// .length = sizeof(rndis_msg_initialize_t), +// .request_id = 1, // TODO should use some magic number +// .major_version = 1, +// .minor_version = 0, +// .max_xfer_size = 0x4000 // TODO mimic windows +// }; +// +// +// +// OSAL_SUBTASK_END +//} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h new file mode 100644 index 000000000..170cb3b0e --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h @@ -0,0 +1,63 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup CDC_RNDIS + * \defgroup CDC_RNSID_Host Host + * @{ */ + +#ifndef _TUSB_CDC_RNDIS_HOST_H_ +#define _TUSB_CDC_RNDIS_HOST_H_ + +#include "common/tusb_common.h" +#include "host/usbh.h" +#include "cdc_rndis.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// INTERNAL RNDIS-CDC Driver API +//--------------------------------------------------------------------+ +typedef struct { + OSAL_SEM_DEF(semaphore_notification); + osal_semaphore_handle_t sem_notification_hdl; // used to wait on notification pipe + uint32_t max_xfer_size; // got from device's msg initialize complete + uint8_t mac_address[6]; +}rndish_data_t; + +void rndish_init(void); +tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc); +void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); +void rndish_close(uint8_t dev_addr); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CDC_RNDIS_HOST_H_ */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h new file mode 100644 index 000000000..114c827b8 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h @@ -0,0 +1,119 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_H_ +#define _TUSB_DFU_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Common Definitions +//--------------------------------------------------------------------+ + +// DFU Protocol +typedef enum +{ + DFU_PROTOCOL_RT = 0x01, + DFU_PROTOCOL_DFU = 0x02, +} dfu_protocol_type_t; + +// DFU Descriptor Type +typedef enum +{ + DFU_DESC_FUNCTIONAL = 0x21, +} dfu_descriptor_type_t; + +// DFU Requests +typedef enum { + DFU_REQUEST_DETACH = 0, + DFU_REQUEST_DNLOAD = 1, + DFU_REQUEST_UPLOAD = 2, + DFU_REQUEST_GETSTATUS = 3, + DFU_REQUEST_CLRSTATUS = 4, + DFU_REQUEST_GETSTATE = 5, + DFU_REQUEST_ABORT = 6, +} dfu_requests_t; + +// DFU States +typedef enum { + APP_IDLE = 0, + APP_DETACH = 1, + DFU_IDLE = 2, + DFU_DNLOAD_SYNC = 3, + DFU_DNBUSY = 4, + DFU_DNLOAD_IDLE = 5, + DFU_MANIFEST_SYNC = 6, + DFU_MANIFEST = 7, + DFU_MANIFEST_WAIT_RESET = 8, + DFU_UPLOAD_IDLE = 9, + DFU_ERROR = 10, +} dfu_state_t; + +// DFU Status +typedef enum { + DFU_STATUS_OK = 0x00, + DFU_STATUS_ERR_TARGET = 0x01, + DFU_STATUS_ERR_FILE = 0x02, + DFU_STATUS_ERR_WRITE = 0x03, + DFU_STATUS_ERR_ERASE = 0x04, + DFU_STATUS_ERR_CHECK_ERASED = 0x05, + DFU_STATUS_ERR_PROG = 0x06, + DFU_STATUS_ERR_VERIFY = 0x07, + DFU_STATUS_ERR_ADDRESS = 0x08, + DFU_STATUS_ERR_NOTDONE = 0x09, + DFU_STATUS_ERR_FIRMWARE = 0x0A, + DFU_STATUS_ERR_VENDOR = 0x0B, + DFU_STATUS_ERR_USBR = 0x0C, + DFU_STATUS_ERR_POR = 0x0D, + DFU_STATUS_ERR_UNKNOWN = 0x0E, + DFU_STATUS_ERR_STALLEDPKT = 0x0F, +} dfu_status_t; + +#define DFU_ATTR_CAN_DOWNLOAD (1u << 0) +#define DFU_ATTR_CAN_UPLOAD (1u << 1) +#define DFU_ATTR_MANIFESTATION_TOLERANT (1u << 2) +#define DFU_ATTR_WILL_DETACH (1u << 3) + +// DFU Status Request Payload +typedef struct TU_ATTR_PACKED +{ + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +} dfu_status_response_t; + +TU_VERIFY_STATIC( sizeof(dfu_status_response_t) == 6, "size is not correct"); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c new file mode 100644 index 000000000..ddfa608e4 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c @@ -0,0 +1,458 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "dfu_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t attrs; + uint8_t alt; + + dfu_state_t state; + dfu_status_t status; + + bool flashing_in_progress; + uint16_t block; + uint16_t length; + + CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE]; +} dfu_state_ctx_t; + +// Only a single dfu state is allowed +CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_ctx; + +static void reset_state(void) +{ + _dfu_ctx.state = DFU_IDLE; + _dfu_ctx.status = DFU_STATUS_OK; + _dfu_ctx.flashing_in_progress = false; +} + +static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout); +static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +static tu_lookup_entry_t const _dfu_request_lookup[] = +{ + { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, + { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, + { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, + { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, + { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, + { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, + { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, +}; + +static tu_lookup_table_t const _dfu_request_table = +{ + .count = TU_ARRAY_SIZE(_dfu_request_lookup), + .items = _dfu_request_lookup +}; + +static tu_lookup_entry_t const _dfu_state_lookup[] = +{ + { .key = APP_IDLE , .data = "APP_IDLE" }, + { .key = APP_DETACH , .data = "APP_DETACH" }, + { .key = DFU_IDLE , .data = "IDLE" }, + { .key = DFU_DNLOAD_SYNC , .data = "DNLOAD_SYNC" }, + { .key = DFU_DNBUSY , .data = "DNBUSY" }, + { .key = DFU_DNLOAD_IDLE , .data = "DNLOAD_IDLE" }, + { .key = DFU_MANIFEST_SYNC , .data = "MANIFEST_SYNC" }, + { .key = DFU_MANIFEST , .data = "MANIFEST" }, + { .key = DFU_MANIFEST_WAIT_RESET , .data = "MANIFEST_WAIT_RESET" }, + { .key = DFU_UPLOAD_IDLE , .data = "UPLOAD_IDLE" }, + { .key = DFU_ERROR , .data = "ERROR" }, +}; + +static tu_lookup_table_t const _dfu_state_table = +{ + .count = TU_ARRAY_SIZE(_dfu_state_lookup), + .items = _dfu_state_lookup +}; + +static tu_lookup_entry_t const _dfu_status_lookup[] = +{ + { .key = DFU_STATUS_OK , .data = "OK" }, + { .key = DFU_STATUS_ERR_TARGET , .data = "errTARGET" }, + { .key = DFU_STATUS_ERR_FILE , .data = "errFILE" }, + { .key = DFU_STATUS_ERR_WRITE , .data = "errWRITE" }, + { .key = DFU_STATUS_ERR_ERASE , .data = "errERASE" }, + { .key = DFU_STATUS_ERR_CHECK_ERASED , .data = "errCHECK_ERASED" }, + { .key = DFU_STATUS_ERR_PROG , .data = "errPROG" }, + { .key = DFU_STATUS_ERR_VERIFY , .data = "errVERIFY" }, + { .key = DFU_STATUS_ERR_ADDRESS , .data = "errADDRESS" }, + { .key = DFU_STATUS_ERR_NOTDONE , .data = "errNOTDONE" }, + { .key = DFU_STATUS_ERR_FIRMWARE , .data = "errFIRMWARE" }, + { .key = DFU_STATUS_ERR_VENDOR , .data = "errVENDOR" }, + { .key = DFU_STATUS_ERR_USBR , .data = "errUSBR" }, + { .key = DFU_STATUS_ERR_POR , .data = "errPOR" }, + { .key = DFU_STATUS_ERR_UNKNOWN , .data = "errUNKNOWN" }, + { .key = DFU_STATUS_ERR_STALLEDPKT , .data = "errSTALLEDPKT" }, +}; + +static tu_lookup_table_t const _dfu_status_table = +{ + .count = TU_ARRAY_SIZE(_dfu_status_lookup), + .items = _dfu_status_lookup +}; + +#endif + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void dfu_moded_reset(uint8_t rhport) +{ + (void) rhport; + + _dfu_ctx.attrs = 0; + _dfu_ctx.alt = 0; + + reset_state(); +} + +void dfu_moded_init(void) +{ + dfu_moded_reset(0); +} + +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + (void) rhport; + + //------------- Interface (with Alt) descriptor -------------// + uint8_t const itf_num = itf_desc->bInterfaceNumber; + uint8_t alt_count = 0; + + uint16_t drv_len = 0; + while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) + { + TU_ASSERT(max_len > drv_len, 0); + + // Alternate must have the same interface number + TU_ASSERT(itf_desc->bInterfaceNumber == itf_num, 0); + + // Alt should increase by one every time + TU_ASSERT(itf_desc->bAlternateSetting == alt_count, 0); + alt_count++; + + drv_len += tu_desc_len(itf_desc); + itf_desc = (tusb_desc_interface_t const *) tu_desc_next(itf_desc); + } + + //------------- DFU Functional descriptor -------------// + tusb_desc_dfu_functional_t const *func_desc = (tusb_desc_dfu_functional_t const *) itf_desc; + TU_ASSERT(tu_desc_type(func_desc) == TUSB_DESC_FUNCTIONAL, 0); + drv_len += sizeof(tusb_desc_dfu_functional_t); + + _dfu_ctx.attrs = func_desc->bAttributes; + + // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR + uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t const*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) ); + TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len); + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + + TU_LOG2(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status)); + + if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) + { + // Standard request include GET/SET_INTERFACE + switch ( request->bRequest ) + { + case TUSB_REQ_SET_INTERFACE: + if ( stage == CONTROL_STAGE_SETUP ) + { + // Switch Alt interface and reset state machine + _dfu_ctx.alt = (uint8_t) request->wValue; + reset_state(); + return tud_control_status(rhport, request); + } + break; + + case TUSB_REQ_GET_INTERFACE: + if(stage == CONTROL_STAGE_SETUP) + { + return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1); + } + break; + + // unsupported request + default: return false; + } + } + else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS ) + { + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + + // Class request + switch ( request->bRequest ) + { + case DFU_REQUEST_DETACH: + if ( stage == CONTROL_STAGE_SETUP ) + { + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( tud_dfu_detach_cb ) tud_dfu_detach_cb(); + } + break; + + case DFU_REQUEST_CLRSTATUS: + if ( stage == CONTROL_STAGE_SETUP ) + { + reset_state(); + tud_control_status(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + if ( stage == CONTROL_STAGE_SETUP ) + { + tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); + } + break; + + case DFU_REQUEST_ABORT: + if ( stage == CONTROL_STAGE_SETUP ) + { + reset_state(); + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt); + } + break; + + case DFU_REQUEST_UPLOAD: + if ( stage == CONTROL_STAGE_SETUP ) + { + TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); + TU_VERIFY(tud_dfu_upload_cb); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); + + uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength); + + return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); + } + break; + + case DFU_REQUEST_DNLOAD: + if ( stage == CONTROL_STAGE_SETUP ) + { + TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD); + TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); + + // set to true for both download and manifest + _dfu_ctx.flashing_in_progress = true; + + // save block and length for flashing + _dfu_ctx.block = request->wValue; + _dfu_ctx.length = request->wLength; + + if ( request->wLength ) + { + // Download with payload -> transition to DOWNLOAD SYNC + _dfu_ctx.state = DFU_DNLOAD_SYNC; + return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); + } + else + { + // Download is complete -> transition to MANIFEST SYNC + _dfu_ctx.state = DFU_MANIFEST_SYNC; + return tud_control_status(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATUS: + switch ( _dfu_ctx.state ) + { + case DFU_DNLOAD_SYNC: + return process_download_get_status(rhport, stage, request); + break; + + case DFU_MANIFEST_SYNC: + return process_manifest_get_status(rhport, stage, request); + break; + + default: + if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0); + break; + } + break; + + default: return false; // stall unsupported request + } + }else + { + return false; // unsupported request + } + + return true; +} + +void tud_dfu_finish_flashing(uint8_t status) +{ + _dfu_ctx.flashing_in_progress = false; + + if ( status == DFU_STATUS_OK ) + { + if (_dfu_ctx.state == DFU_DNBUSY) + { + _dfu_ctx.state = DFU_DNLOAD_SYNC; + } + else if (_dfu_ctx.state == DFU_MANIFEST) + { + _dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) + ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET; + } + } + else + { + // failed while flashing, move to dfuError + _dfu_ctx.state = DFU_ERROR; + _dfu_ctx.status = (dfu_status_t)status; + } +} + +static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage == CONTROL_STAGE_SETUP ) + { + // only transition to next state on CONTROL_STAGE_ACK + dfu_state_t next_state; + uint32_t timeout; + + if ( _dfu_ctx.flashing_in_progress ) + { + next_state = DFU_DNBUSY; + timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state); + } + else + { + next_state = DFU_DNLOAD_IDLE; + timeout = 0; + } + + return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( _dfu_ctx.flashing_in_progress ) + { + _dfu_ctx.state = DFU_DNBUSY; + tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length); + }else + { + _dfu_ctx.state = DFU_DNLOAD_IDLE; + } + } + + return true; +} + +static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage == CONTROL_STAGE_SETUP ) + { + // only transition to next state on CONTROL_STAGE_ACK + dfu_state_t next_state; + uint32_t timeout; + + if ( _dfu_ctx.flashing_in_progress ) + { + next_state = DFU_MANIFEST; + timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state); + } + else + { + next_state = DFU_IDLE; + timeout = 0; + } + + return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( _dfu_ctx.flashing_in_progress ) + { + _dfu_ctx.state = DFU_MANIFEST; + tud_dfu_manifest_cb(_dfu_ctx.alt); + } + else + { + _dfu_ctx.state = DFU_IDLE; + } + } + + return true; +} + +static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout) +{ + dfu_status_response_t resp; + resp.bStatus = (uint8_t) status; + resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); + resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); + resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); + resp.bState = (uint8_t) state; + resp.iString = 0; + + return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h new file mode 100644 index 000000000..fecf8596f --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h @@ -0,0 +1,98 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_DEVICE_H_ +#define _TUSB_DFU_DEVICE_H_ + +#include "dfu.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver Default Configure & Validation +//--------------------------------------------------------------------+ + +#if !defined(CFG_TUD_DFU_XFER_BUFSIZE) + #error "CFG_TUD_DFU_XFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" +#endif + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// Must be called when the application is done with flashing started by +// tud_dfu_download_cb() and tud_dfu_manifest_cb(). +// status is DFU_STATUS_OK if successful, any other error status will cause state to enter dfuError +void tud_dfu_finish_flashing(uint8_t status); + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. + +// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) +// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. +// During this period, USB host won't try to communicate with us. +uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state); + +// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests +// This callback could be returned before flashing op is complete (async). +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_download_cb (uint8_t alt, uint16_t block_num, uint8_t const *data, uint16_t length); + +// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) +// Application can do checksum, or actual flashing if buffered entire image previously. +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_manifest_cb(uint8_t alt); + +// Invoked when received DFU_UPLOAD request +// Application must populate data with up to length bytes and +// Return the number of written bytes +TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); + +// Invoked when a DFU_DETACH request is received +TU_ATTR_WEAK void tud_dfu_detach_cb(void); + +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void dfu_moded_init(void); +void dfu_moded_reset(uint8_t rhport); +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c new file mode 100644 index 000000000..afee2aa1f --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c @@ -0,0 +1,128 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Sylvain Munaut + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "dfu_rt_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void dfu_rtd_init(void) +{ +} + +void dfu_rtd_reset(uint8_t rhport) +{ + (void) rhport; +} + +uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + (void) rhport; + (void) max_len; + + // Ensure this is DFU Runtime + TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT), 0); + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + uint16_t drv_len = sizeof(tusb_desc_interface_t); + + if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + { + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + // nothing to do with DATA or ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; + + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + + // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_SET_INTERFACE == request->bRequest ) + { + tud_control_status(rhport, request); + return true; + } + + // Handle class request only from here + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + switch (request->bRequest) + { + case DFU_REQUEST_DETACH: + { + TU_LOG2(" DFU RT Request: DETACH\r\n"); + tud_control_status(rhport, request); + tud_dfu_runtime_reboot_to_dfu_cb(); + } + break; + + case DFU_REQUEST_GETSTATUS: + { + TU_LOG2(" DFU RT Request: GETSTATUS\r\n"); + dfu_status_response_t resp; + // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 + memset(&resp, 0x00, sizeof(dfu_status_response_t)); + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); + } + break; + + default: + { + TU_LOG2(" DFU RT Unexpected Request: %d\r\n", request->bRequest); + return false; // stall unsupported request + } + } + + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h new file mode 100644 index 000000000..babaa8214 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h @@ -0,0 +1,54 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Sylvain Munaut + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_RT_DEVICE_H_ +#define _TUSB_DFU_RT_DEVICE_H_ + +#include "dfu.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ +// Invoked when a DFU_DETACH request is received and bitWillDetach is set +void tud_dfu_runtime_reboot_to_dfu_cb(void); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void dfu_rtd_init(void); +void dfu_rtd_reset(uint8_t rhport); +uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_RT_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h new file mode 100644 index 000000000..9265a2ede --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h @@ -0,0 +1,1119 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup group_class + * \defgroup ClassDriver_HID Human Interface Device (HID) + * @{ */ + +#ifndef _TUSB_HID_H_ +#define _TUSB_HID_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Common Definitions +//--------------------------------------------------------------------+ +/** \defgroup ClassDriver_HID_Common Common Definitions + * @{ */ + + /// USB HID Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; /**< Numeric expression that is the total size of the HID descriptor */ + uint8_t bDescriptorType; /**< Constant name specifying type of HID descriptor. */ + + uint16_t bcdHID; /**< Numeric expression identifying the HID Class Specification release */ + uint8_t bCountryCode; /**< Numeric expression identifying country code of the localized hardware. */ + uint8_t bNumDescriptors; /**< Numeric expression specifying the number of class descriptors */ + + uint8_t bReportType; /**< Type of HID class report. */ + uint16_t wReportLength; /**< the total size of the Report descriptor. */ +} tusb_hid_descriptor_hid_t; + +/// HID Subclass +typedef enum +{ + HID_SUBCLASS_NONE = 0, ///< No Subclass + HID_SUBCLASS_BOOT = 1 ///< Boot Interface Subclass +}hid_subclass_enum_t; + +/// HID Interface Protocol +typedef enum +{ + HID_ITF_PROTOCOL_NONE = 0, ///< None + HID_ITF_PROTOCOL_KEYBOARD = 1, ///< Keyboard + HID_ITF_PROTOCOL_MOUSE = 2 ///< Mouse +}hid_interface_protocol_enum_t; + +/// HID Descriptor Type +typedef enum +{ + HID_DESC_TYPE_HID = 0x21, ///< HID Descriptor + HID_DESC_TYPE_REPORT = 0x22, ///< Report Descriptor + HID_DESC_TYPE_PHYSICAL = 0x23 ///< Physical Descriptor +}hid_descriptor_enum_t; + +/// HID Request Report Type +typedef enum +{ + HID_REPORT_TYPE_INVALID = 0, + HID_REPORT_TYPE_INPUT, ///< Input + HID_REPORT_TYPE_OUTPUT, ///< Output + HID_REPORT_TYPE_FEATURE ///< Feature +}hid_report_type_t; + +/// HID Class Specific Control Request +typedef enum +{ + HID_REQ_CONTROL_GET_REPORT = 0x01, ///< Get Report + HID_REQ_CONTROL_GET_IDLE = 0x02, ///< Get Idle + HID_REQ_CONTROL_GET_PROTOCOL = 0x03, ///< Get Protocol + HID_REQ_CONTROL_SET_REPORT = 0x09, ///< Set Report + HID_REQ_CONTROL_SET_IDLE = 0x0a, ///< Set Idle + HID_REQ_CONTROL_SET_PROTOCOL = 0x0b ///< Set Protocol +}hid_request_enum_t; + +/// HID Local Code +typedef enum +{ + HID_LOCAL_NotSupported = 0 , ///< NotSupported + HID_LOCAL_Arabic , ///< Arabic + HID_LOCAL_Belgian , ///< Belgian + HID_LOCAL_Canadian_Bilingual , ///< Canadian_Bilingual + HID_LOCAL_Canadian_French , ///< Canadian_French + HID_LOCAL_Czech_Republic , ///< Czech_Republic + HID_LOCAL_Danish , ///< Danish + HID_LOCAL_Finnish , ///< Finnish + HID_LOCAL_French , ///< French + HID_LOCAL_German , ///< German + HID_LOCAL_Greek , ///< Greek + HID_LOCAL_Hebrew , ///< Hebrew + HID_LOCAL_Hungary , ///< Hungary + HID_LOCAL_International , ///< International + HID_LOCAL_Italian , ///< Italian + HID_LOCAL_Japan_Katakana , ///< Japan_Katakana + HID_LOCAL_Korean , ///< Korean + HID_LOCAL_Latin_American , ///< Latin_American + HID_LOCAL_Netherlands_Dutch , ///< Netherlands/Dutch + HID_LOCAL_Norwegian , ///< Norwegian + HID_LOCAL_Persian_Farsi , ///< Persian (Farsi) + HID_LOCAL_Poland , ///< Poland + HID_LOCAL_Portuguese , ///< Portuguese + HID_LOCAL_Russia , ///< Russia + HID_LOCAL_Slovakia , ///< Slovakia + HID_LOCAL_Spanish , ///< Spanish + HID_LOCAL_Swedish , ///< Swedish + HID_LOCAL_Swiss_French , ///< Swiss/French + HID_LOCAL_Swiss_German , ///< Swiss/German + HID_LOCAL_Switzerland , ///< Switzerland + HID_LOCAL_Taiwan , ///< Taiwan + HID_LOCAL_Turkish_Q , ///< Turkish-Q + HID_LOCAL_UK , ///< UK + HID_LOCAL_US , ///< US + HID_LOCAL_Yugoslavia , ///< Yugoslavia + HID_LOCAL_Turkish_F ///< Turkish-F +} hid_local_enum_t; + +// HID protocol value used by GetProtocol / SetProtocol +typedef enum +{ + HID_PROTOCOL_BOOT = 0, + HID_PROTOCOL_REPORT = 1 +} hid_protocol_mode_enum_t; + +/** @} */ + +//--------------------------------------------------------------------+ +// GAMEPAD +//--------------------------------------------------------------------+ +/** \addtogroup ClassDriver_HID_Gamepad Gamepad + * @{ */ + +/* From https://www.kernel.org/doc/html/latest/input/gamepad.html + ____________________________ __ + / [__ZL__] [__ZR__] \ | + / [__ TL __] [__ TR __] \ | Front Triggers + __/________________________________\__ __| + / _ \ | + / /\ __ (N) \ | + / || __ |MO| __ _ _ \ | Main Pad + | <===DP===> |SE| |ST| (W) -|- (E) | | + \ || ___ ___ _ / | + /\ \/ / \ / \ (S) /\ __| + / \________ | LS | ____ | RS | ________/ \ | +| / \ \___/ / \ \___/ / \ | | Control Sticks +| / \_____/ \_____/ \ | __| +| / \ | + \_____/ \_____/ + + |________|______| |______|___________| + D-Pad Left Right Action Pad + Stick Stick + + |_____________| + Menu Pad + + Most gamepads have the following features: + - Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST. + - D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right. + - Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START. + - Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also + provide a digital button if you press them. + - Triggers are located on the upper-side of the pad in vertical direction. The upper buttons + are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right. + - Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors. + */ + +/// HID Gamepad Protocol Report. +typedef struct TU_ATTR_PACKED +{ + int8_t x; ///< Delta x movement of left analog-stick + int8_t y; ///< Delta y movement of left analog-stick + int8_t z; ///< Delta z movement of right analog-joystick + int8_t rz; ///< Delta Rz movement of right analog-joystick + int8_t rx; ///< Delta Rx movement of analog left trigger + int8_t ry; ///< Delta Ry movement of analog right trigger + uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat + uint32_t buttons; ///< Buttons mask for currently pressed buttons +}hid_gamepad_report_t; + +/// Standard Gamepad Buttons Bitmap +typedef enum +{ + GAMEPAD_BUTTON_0 = TU_BIT(0), + GAMEPAD_BUTTON_1 = TU_BIT(1), + GAMEPAD_BUTTON_2 = TU_BIT(2), + GAMEPAD_BUTTON_3 = TU_BIT(3), + GAMEPAD_BUTTON_4 = TU_BIT(4), + GAMEPAD_BUTTON_5 = TU_BIT(5), + GAMEPAD_BUTTON_6 = TU_BIT(6), + GAMEPAD_BUTTON_7 = TU_BIT(7), + GAMEPAD_BUTTON_8 = TU_BIT(8), + GAMEPAD_BUTTON_9 = TU_BIT(9), + GAMEPAD_BUTTON_10 = TU_BIT(10), + GAMEPAD_BUTTON_11 = TU_BIT(11), + GAMEPAD_BUTTON_12 = TU_BIT(12), + GAMEPAD_BUTTON_13 = TU_BIT(13), + GAMEPAD_BUTTON_14 = TU_BIT(14), + GAMEPAD_BUTTON_15 = TU_BIT(15), + GAMEPAD_BUTTON_16 = TU_BIT(16), + GAMEPAD_BUTTON_17 = TU_BIT(17), + GAMEPAD_BUTTON_18 = TU_BIT(18), + GAMEPAD_BUTTON_19 = TU_BIT(19), + GAMEPAD_BUTTON_20 = TU_BIT(20), + GAMEPAD_BUTTON_21 = TU_BIT(21), + GAMEPAD_BUTTON_22 = TU_BIT(22), + GAMEPAD_BUTTON_23 = TU_BIT(23), + GAMEPAD_BUTTON_24 = TU_BIT(24), + GAMEPAD_BUTTON_25 = TU_BIT(25), + GAMEPAD_BUTTON_26 = TU_BIT(26), + GAMEPAD_BUTTON_27 = TU_BIT(27), + GAMEPAD_BUTTON_28 = TU_BIT(28), + GAMEPAD_BUTTON_29 = TU_BIT(29), + GAMEPAD_BUTTON_30 = TU_BIT(30), + GAMEPAD_BUTTON_31 = TU_BIT(31), +}hid_gamepad_button_bm_t; + +/// Standard Gamepad Buttons Naming from Linux input event codes +/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h +#define GAMEPAD_BUTTON_A GAMEPAD_BUTTON_0 +#define GAMEPAD_BUTTON_SOUTH GAMEPAD_BUTTON_0 + +#define GAMEPAD_BUTTON_B GAMEPAD_BUTTON_1 +#define GAMEPAD_BUTTON_EAST GAMEPAD_BUTTON_1 + +#define GAMEPAD_BUTTON_C GAMEPAD_BUTTON_2 + +#define GAMEPAD_BUTTON_X GAMEPAD_BUTTON_3 +#define GAMEPAD_BUTTON_NORTH GAMEPAD_BUTTON_3 + +#define GAMEPAD_BUTTON_Y GAMEPAD_BUTTON_4 +#define GAMEPAD_BUTTON_WEST GAMEPAD_BUTTON_4 + +#define GAMEPAD_BUTTON_Z GAMEPAD_BUTTON_5 +#define GAMEPAD_BUTTON_TL GAMEPAD_BUTTON_6 +#define GAMEPAD_BUTTON_TR GAMEPAD_BUTTON_7 +#define GAMEPAD_BUTTON_TL2 GAMEPAD_BUTTON_8 +#define GAMEPAD_BUTTON_TR2 GAMEPAD_BUTTON_9 +#define GAMEPAD_BUTTON_SELECT GAMEPAD_BUTTON_10 +#define GAMEPAD_BUTTON_START GAMEPAD_BUTTON_11 +#define GAMEPAD_BUTTON_MODE GAMEPAD_BUTTON_12 +#define GAMEPAD_BUTTON_THUMBL GAMEPAD_BUTTON_13 +#define GAMEPAD_BUTTON_THUMBR GAMEPAD_BUTTON_14 + +/// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) +typedef enum +{ + GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED + GAMEPAD_HAT_UP = 1, ///< DPAD_UP + GAMEPAD_HAT_UP_RIGHT = 2, ///< DPAD_UP_RIGHT + GAMEPAD_HAT_RIGHT = 3, ///< DPAD_RIGHT + GAMEPAD_HAT_DOWN_RIGHT = 4, ///< DPAD_DOWN_RIGHT + GAMEPAD_HAT_DOWN = 5, ///< DPAD_DOWN + GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT + GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT + GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT +}hid_gamepad_hat_t; + +/// @} + +//--------------------------------------------------------------------+ +// MOUSE +//--------------------------------------------------------------------+ +/** \addtogroup ClassDriver_HID_Mouse Mouse + * @{ */ + +/// Standard HID Boot Protocol Mouse Report. +typedef struct TU_ATTR_PACKED +{ + uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */ + int8_t x; /**< Current delta x movement of the mouse. */ + int8_t y; /**< Current delta y movement on the mouse. */ + int8_t wheel; /**< Current delta wheel movement on the mouse. */ + int8_t pan; // using AC Pan +} hid_mouse_report_t; + +/// Standard Mouse Buttons Bitmap +typedef enum +{ + MOUSE_BUTTON_LEFT = TU_BIT(0), ///< Left button + MOUSE_BUTTON_RIGHT = TU_BIT(1), ///< Right button + MOUSE_BUTTON_MIDDLE = TU_BIT(2), ///< Middle button + MOUSE_BUTTON_BACKWARD = TU_BIT(3), ///< Backward button, + MOUSE_BUTTON_FORWARD = TU_BIT(4), ///< Forward button, +}hid_mouse_button_bm_t; + +/// @} + +//--------------------------------------------------------------------+ +// Keyboard +//--------------------------------------------------------------------+ +/** \addtogroup ClassDriver_HID_Keyboard Keyboard + * @{ */ + +/// Standard HID Boot Protocol Keyboard Report. +typedef struct TU_ATTR_PACKED +{ + uint8_t modifier; /**< Keyboard modifier (KEYBOARD_MODIFIER_* masks). */ + uint8_t reserved; /**< Reserved for OEM use, always set to 0. */ + uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */ +} hid_keyboard_report_t; + +/// Keyboard modifier codes bitmap +typedef enum +{ + KEYBOARD_MODIFIER_LEFTCTRL = TU_BIT(0), ///< Left Control + KEYBOARD_MODIFIER_LEFTSHIFT = TU_BIT(1), ///< Left Shift + KEYBOARD_MODIFIER_LEFTALT = TU_BIT(2), ///< Left Alt + KEYBOARD_MODIFIER_LEFTGUI = TU_BIT(3), ///< Left Window + KEYBOARD_MODIFIER_RIGHTCTRL = TU_BIT(4), ///< Right Control + KEYBOARD_MODIFIER_RIGHTSHIFT = TU_BIT(5), ///< Right Shift + KEYBOARD_MODIFIER_RIGHTALT = TU_BIT(6), ///< Right Alt + KEYBOARD_MODIFIER_RIGHTGUI = TU_BIT(7) ///< Right Window +}hid_keyboard_modifier_bm_t; + +typedef enum +{ + KEYBOARD_LED_NUMLOCK = TU_BIT(0), ///< Num Lock LED + KEYBOARD_LED_CAPSLOCK = TU_BIT(1), ///< Caps Lock LED + KEYBOARD_LED_SCROLLLOCK = TU_BIT(2), ///< Scroll Lock LED + KEYBOARD_LED_COMPOSE = TU_BIT(3), ///< Composition Mode + KEYBOARD_LED_KANA = TU_BIT(4) ///< Kana mode +}hid_keyboard_led_bm_t; + +/// @} + +//--------------------------------------------------------------------+ +// HID KEYCODE +//--------------------------------------------------------------------+ +#define HID_KEY_NONE 0x00 +#define HID_KEY_A 0x04 +#define HID_KEY_B 0x05 +#define HID_KEY_C 0x06 +#define HID_KEY_D 0x07 +#define HID_KEY_E 0x08 +#define HID_KEY_F 0x09 +#define HID_KEY_G 0x0A +#define HID_KEY_H 0x0B +#define HID_KEY_I 0x0C +#define HID_KEY_J 0x0D +#define HID_KEY_K 0x0E +#define HID_KEY_L 0x0F +#define HID_KEY_M 0x10 +#define HID_KEY_N 0x11 +#define HID_KEY_O 0x12 +#define HID_KEY_P 0x13 +#define HID_KEY_Q 0x14 +#define HID_KEY_R 0x15 +#define HID_KEY_S 0x16 +#define HID_KEY_T 0x17 +#define HID_KEY_U 0x18 +#define HID_KEY_V 0x19 +#define HID_KEY_W 0x1A +#define HID_KEY_X 0x1B +#define HID_KEY_Y 0x1C +#define HID_KEY_Z 0x1D +#define HID_KEY_1 0x1E +#define HID_KEY_2 0x1F +#define HID_KEY_3 0x20 +#define HID_KEY_4 0x21 +#define HID_KEY_5 0x22 +#define HID_KEY_6 0x23 +#define HID_KEY_7 0x24 +#define HID_KEY_8 0x25 +#define HID_KEY_9 0x26 +#define HID_KEY_0 0x27 +#define HID_KEY_ENTER 0x28 +#define HID_KEY_ESCAPE 0x29 +#define HID_KEY_BACKSPACE 0x2A +#define HID_KEY_TAB 0x2B +#define HID_KEY_SPACE 0x2C +#define HID_KEY_MINUS 0x2D +#define HID_KEY_EQUAL 0x2E +#define HID_KEY_BRACKET_LEFT 0x2F +#define HID_KEY_BRACKET_RIGHT 0x30 +#define HID_KEY_BACKSLASH 0x31 +#define HID_KEY_EUROPE_1 0x32 +#define HID_KEY_SEMICOLON 0x33 +#define HID_KEY_APOSTROPHE 0x34 +#define HID_KEY_GRAVE 0x35 +#define HID_KEY_COMMA 0x36 +#define HID_KEY_PERIOD 0x37 +#define HID_KEY_SLASH 0x38 +#define HID_KEY_CAPS_LOCK 0x39 +#define HID_KEY_F1 0x3A +#define HID_KEY_F2 0x3B +#define HID_KEY_F3 0x3C +#define HID_KEY_F4 0x3D +#define HID_KEY_F5 0x3E +#define HID_KEY_F6 0x3F +#define HID_KEY_F7 0x40 +#define HID_KEY_F8 0x41 +#define HID_KEY_F9 0x42 +#define HID_KEY_F10 0x43 +#define HID_KEY_F11 0x44 +#define HID_KEY_F12 0x45 +#define HID_KEY_PRINT_SCREEN 0x46 +#define HID_KEY_SCROLL_LOCK 0x47 +#define HID_KEY_PAUSE 0x48 +#define HID_KEY_INSERT 0x49 +#define HID_KEY_HOME 0x4A +#define HID_KEY_PAGE_UP 0x4B +#define HID_KEY_DELETE 0x4C +#define HID_KEY_END 0x4D +#define HID_KEY_PAGE_DOWN 0x4E +#define HID_KEY_ARROW_RIGHT 0x4F +#define HID_KEY_ARROW_LEFT 0x50 +#define HID_KEY_ARROW_DOWN 0x51 +#define HID_KEY_ARROW_UP 0x52 +#define HID_KEY_NUM_LOCK 0x53 +#define HID_KEY_KEYPAD_DIVIDE 0x54 +#define HID_KEY_KEYPAD_MULTIPLY 0x55 +#define HID_KEY_KEYPAD_SUBTRACT 0x56 +#define HID_KEY_KEYPAD_ADD 0x57 +#define HID_KEY_KEYPAD_ENTER 0x58 +#define HID_KEY_KEYPAD_1 0x59 +#define HID_KEY_KEYPAD_2 0x5A +#define HID_KEY_KEYPAD_3 0x5B +#define HID_KEY_KEYPAD_4 0x5C +#define HID_KEY_KEYPAD_5 0x5D +#define HID_KEY_KEYPAD_6 0x5E +#define HID_KEY_KEYPAD_7 0x5F +#define HID_KEY_KEYPAD_8 0x60 +#define HID_KEY_KEYPAD_9 0x61 +#define HID_KEY_KEYPAD_0 0x62 +#define HID_KEY_KEYPAD_DECIMAL 0x63 +#define HID_KEY_EUROPE_2 0x64 +#define HID_KEY_APPLICATION 0x65 +#define HID_KEY_POWER 0x66 +#define HID_KEY_KEYPAD_EQUAL 0x67 +#define HID_KEY_F13 0x68 +#define HID_KEY_F14 0x69 +#define HID_KEY_F15 0x6A +#define HID_KEY_F16 0x6B +#define HID_KEY_F17 0x6C +#define HID_KEY_F18 0x6D +#define HID_KEY_F19 0x6E +#define HID_KEY_F20 0x6F +#define HID_KEY_F21 0x70 +#define HID_KEY_F22 0x71 +#define HID_KEY_F23 0x72 +#define HID_KEY_F24 0x73 +#define HID_KEY_EXECUTE 0x74 +#define HID_KEY_HELP 0x75 +#define HID_KEY_MENU 0x76 +#define HID_KEY_SELECT 0x77 +#define HID_KEY_STOP 0x78 +#define HID_KEY_AGAIN 0x79 +#define HID_KEY_UNDO 0x7A +#define HID_KEY_CUT 0x7B +#define HID_KEY_COPY 0x7C +#define HID_KEY_PASTE 0x7D +#define HID_KEY_FIND 0x7E +#define HID_KEY_MUTE 0x7F +#define HID_KEY_VOLUME_UP 0x80 +#define HID_KEY_VOLUME_DOWN 0x81 +#define HID_KEY_LOCKING_CAPS_LOCK 0x82 +#define HID_KEY_LOCKING_NUM_LOCK 0x83 +#define HID_KEY_LOCKING_SCROLL_LOCK 0x84 +#define HID_KEY_KEYPAD_COMMA 0x85 +#define HID_KEY_KEYPAD_EQUAL_SIGN 0x86 +#define HID_KEY_KANJI1 0x87 +#define HID_KEY_KANJI2 0x88 +#define HID_KEY_KANJI3 0x89 +#define HID_KEY_KANJI4 0x8A +#define HID_KEY_KANJI5 0x8B +#define HID_KEY_KANJI6 0x8C +#define HID_KEY_KANJI7 0x8D +#define HID_KEY_KANJI8 0x8E +#define HID_KEY_KANJI9 0x8F +#define HID_KEY_LANG1 0x90 +#define HID_KEY_LANG2 0x91 +#define HID_KEY_LANG3 0x92 +#define HID_KEY_LANG4 0x93 +#define HID_KEY_LANG5 0x94 +#define HID_KEY_LANG6 0x95 +#define HID_KEY_LANG7 0x96 +#define HID_KEY_LANG8 0x97 +#define HID_KEY_LANG9 0x98 +#define HID_KEY_ALTERNATE_ERASE 0x99 +#define HID_KEY_SYSREQ_ATTENTION 0x9A +#define HID_KEY_CANCEL 0x9B +#define HID_KEY_CLEAR 0x9C +#define HID_KEY_PRIOR 0x9D +#define HID_KEY_RETURN 0x9E +#define HID_KEY_SEPARATOR 0x9F +#define HID_KEY_OUT 0xA0 +#define HID_KEY_OPER 0xA1 +#define HID_KEY_CLEAR_AGAIN 0xA2 +#define HID_KEY_CRSEL_PROPS 0xA3 +#define HID_KEY_EXSEL 0xA4 +// RESERVED 0xA5-DF +#define HID_KEY_CONTROL_LEFT 0xE0 +#define HID_KEY_SHIFT_LEFT 0xE1 +#define HID_KEY_ALT_LEFT 0xE2 +#define HID_KEY_GUI_LEFT 0xE3 +#define HID_KEY_CONTROL_RIGHT 0xE4 +#define HID_KEY_SHIFT_RIGHT 0xE5 +#define HID_KEY_ALT_RIGHT 0xE6 +#define HID_KEY_GUI_RIGHT 0xE7 + + +//--------------------------------------------------------------------+ +// REPORT DESCRIPTOR +//--------------------------------------------------------------------+ + +//------------- ITEM & TAG -------------// +#define HID_REPORT_DATA_0(data) +#define HID_REPORT_DATA_1(data) , data +#define HID_REPORT_DATA_2(data) , U16_TO_U8S_LE(data) +#define HID_REPORT_DATA_3(data) , U32_TO_U8S_LE(data) + +#define HID_REPORT_ITEM(data, tag, type, size) \ + (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data) + +// Report Item Types +enum { + RI_TYPE_MAIN = 0, + RI_TYPE_GLOBAL = 1, + RI_TYPE_LOCAL = 2 +}; + +//------------- Main Items - HID 1.11 section 6.2.2.4 -------------// + +// Report Item Main group +enum { + RI_MAIN_INPUT = 8, + RI_MAIN_OUTPUT = 9, + RI_MAIN_COLLECTION = 10, + RI_MAIN_FEATURE = 11, + RI_MAIN_COLLECTION_END = 12 +}; + +#define HID_INPUT(x) HID_REPORT_ITEM(x, RI_MAIN_INPUT , RI_TYPE_MAIN, 1) +#define HID_OUTPUT(x) HID_REPORT_ITEM(x, RI_MAIN_OUTPUT , RI_TYPE_MAIN, 1) +#define HID_COLLECTION(x) HID_REPORT_ITEM(x, RI_MAIN_COLLECTION , RI_TYPE_MAIN, 1) +#define HID_FEATURE(x) HID_REPORT_ITEM(x, RI_MAIN_FEATURE , RI_TYPE_MAIN, 1) +#define HID_COLLECTION_END HID_REPORT_ITEM(x, RI_MAIN_COLLECTION_END, RI_TYPE_MAIN, 0) + +//------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// +#define HID_DATA (0<<0) +#define HID_CONSTANT (1<<0) + +#define HID_ARRAY (0<<1) +#define HID_VARIABLE (1<<1) + +#define HID_ABSOLUTE (0<<2) +#define HID_RELATIVE (1<<2) + +#define HID_WRAP_NO (0<<3) +#define HID_WRAP (1<<3) + +#define HID_LINEAR (0<<4) +#define HID_NONLINEAR (1<<4) + +#define HID_PREFERRED_STATE (0<<5) +#define HID_PREFERRED_NO (1<<5) + +#define HID_NO_NULL_POSITION (0<<6) +#define HID_NULL_STATE (1<<6) + +#define HID_NON_VOLATILE (0<<7) +#define HID_VOLATILE (1<<7) + +#define HID_BITFIELD (0<<8) +#define HID_BUFFERED_BYTES (1<<8) + +//------------- Collection Item - HID 1.11 section 6.2.2.6 -------------// +enum { + HID_COLLECTION_PHYSICAL = 0, + HID_COLLECTION_APPLICATION, + HID_COLLECTION_LOGICAL, + HID_COLLECTION_REPORT, + HID_COLLECTION_NAMED_ARRAY, + HID_COLLECTION_USAGE_SWITCH, + HID_COLLECTION_USAGE_MODIFIER +}; + +//------------- Global Items - HID 1.11 section 6.2.2.7 -------------// + +// Report Item Global group +enum { + RI_GLOBAL_USAGE_PAGE = 0, + RI_GLOBAL_LOGICAL_MIN = 1, + RI_GLOBAL_LOGICAL_MAX = 2, + RI_GLOBAL_PHYSICAL_MIN = 3, + RI_GLOBAL_PHYSICAL_MAX = 4, + RI_GLOBAL_UNIT_EXPONENT = 5, + RI_GLOBAL_UNIT = 6, + RI_GLOBAL_REPORT_SIZE = 7, + RI_GLOBAL_REPORT_ID = 8, + RI_GLOBAL_REPORT_COUNT = 9, + RI_GLOBAL_PUSH = 10, + RI_GLOBAL_POP = 11 +}; + +#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, 1) +#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, n) + +#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, 1) +#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, n) + +#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, 1) +#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, n) + +#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, 1) +#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, n) + +#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, 1) +#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, n) + +#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, 1) +#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, n) + +#define HID_UNIT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, 1) +#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, n) + +#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, 1) +#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, n) + +#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, 1), +#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, n), + +#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, 1) +#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, n) + +#define HID_PUSH HID_REPORT_ITEM(x, RI_GLOBAL_PUSH, RI_TYPE_GLOBAL, 0) +#define HID_POP HID_REPORT_ITEM(x, RI_GLOBAL_POP, RI_TYPE_GLOBAL, 0) + +//------------- LOCAL ITEMS 6.2.2.8 -------------// + +enum { + RI_LOCAL_USAGE = 0, + RI_LOCAL_USAGE_MIN = 1, + RI_LOCAL_USAGE_MAX = 2, + RI_LOCAL_DESIGNATOR_INDEX = 3, + RI_LOCAL_DESIGNATOR_MIN = 4, + RI_LOCAL_DESIGNATOR_MAX = 5, + // 6 is reserved + RI_LOCAL_STRING_INDEX = 7, + RI_LOCAL_STRING_MIN = 8, + RI_LOCAL_STRING_MAX = 9, + RI_LOCAL_DELIMITER = 10, +}; + +#define HID_USAGE(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, 1) +#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, n) + +#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, 1) +#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, n) + +#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, 1) +#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, n) + +//--------------------------------------------------------------------+ +// Usage Table +//--------------------------------------------------------------------+ + +/// HID Usage Table - Table 1: Usage Page Summary +enum { + HID_USAGE_PAGE_DESKTOP = 0x01, + HID_USAGE_PAGE_SIMULATE = 0x02, + HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03, + HID_USAGE_PAGE_SPORT = 0x04, + HID_USAGE_PAGE_GAME = 0x05, + HID_USAGE_PAGE_GENERIC_DEVICE = 0x06, + HID_USAGE_PAGE_KEYBOARD = 0x07, + HID_USAGE_PAGE_LED = 0x08, + HID_USAGE_PAGE_BUTTON = 0x09, + HID_USAGE_PAGE_ORDINAL = 0x0a, + HID_USAGE_PAGE_TELEPHONY = 0x0b, + HID_USAGE_PAGE_CONSUMER = 0x0c, + HID_USAGE_PAGE_DIGITIZER = 0x0d, + HID_USAGE_PAGE_PID = 0x0f, + HID_USAGE_PAGE_UNICODE = 0x10, + HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14, + HID_USAGE_PAGE_MEDICAL = 0x40, + HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83 + HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87 + HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c, + HID_USAGE_PAGE_SCALE = 0x8d, + HID_USAGE_PAGE_MSR = 0x8e, + HID_USAGE_PAGE_CAMERA = 0x90, + HID_USAGE_PAGE_ARCADE = 0x91, + HID_USAGE_PAGE_VENDOR = 0xFF00 // 0xFF00 - 0xFFFF +}; + +/// HID Usage Table - Table 6: Generic Desktop Page +enum { + HID_USAGE_DESKTOP_POINTER = 0x01, + HID_USAGE_DESKTOP_MOUSE = 0x02, + HID_USAGE_DESKTOP_JOYSTICK = 0x04, + HID_USAGE_DESKTOP_GAMEPAD = 0x05, + HID_USAGE_DESKTOP_KEYBOARD = 0x06, + HID_USAGE_DESKTOP_KEYPAD = 0x07, + HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER = 0x08, + HID_USAGE_DESKTOP_TABLET_PC_SYSTEM = 0x09, + HID_USAGE_DESKTOP_X = 0x30, + HID_USAGE_DESKTOP_Y = 0x31, + HID_USAGE_DESKTOP_Z = 0x32, + HID_USAGE_DESKTOP_RX = 0x33, + HID_USAGE_DESKTOP_RY = 0x34, + HID_USAGE_DESKTOP_RZ = 0x35, + HID_USAGE_DESKTOP_SLIDER = 0x36, + HID_USAGE_DESKTOP_DIAL = 0x37, + HID_USAGE_DESKTOP_WHEEL = 0x38, + HID_USAGE_DESKTOP_HAT_SWITCH = 0x39, + HID_USAGE_DESKTOP_COUNTED_BUFFER = 0x3a, + HID_USAGE_DESKTOP_BYTE_COUNT = 0x3b, + HID_USAGE_DESKTOP_MOTION_WAKEUP = 0x3c, + HID_USAGE_DESKTOP_START = 0x3d, + HID_USAGE_DESKTOP_SELECT = 0x3e, + HID_USAGE_DESKTOP_VX = 0x40, + HID_USAGE_DESKTOP_VY = 0x41, + HID_USAGE_DESKTOP_VZ = 0x42, + HID_USAGE_DESKTOP_VBRX = 0x43, + HID_USAGE_DESKTOP_VBRY = 0x44, + HID_USAGE_DESKTOP_VBRZ = 0x45, + HID_USAGE_DESKTOP_VNO = 0x46, + HID_USAGE_DESKTOP_FEATURE_NOTIFICATION = 0x47, + HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER = 0x48, + HID_USAGE_DESKTOP_SYSTEM_CONTROL = 0x80, + HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN = 0x81, + HID_USAGE_DESKTOP_SYSTEM_SLEEP = 0x82, + HID_USAGE_DESKTOP_SYSTEM_WAKE_UP = 0x83, + HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU = 0x84, + HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU = 0x85, + HID_USAGE_DESKTOP_SYSTEM_APP_MENU = 0x86, + HID_USAGE_DESKTOP_SYSTEM_MENU_HELP = 0x87, + HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT = 0x88, + HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT = 0x89, + HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT = 0x8A, + HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT = 0x8B, + HID_USAGE_DESKTOP_SYSTEM_MENU_UP = 0x8C, + HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN = 0x8D, + HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART = 0x8E, + HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART = 0x8F, + HID_USAGE_DESKTOP_DPAD_UP = 0x90, + HID_USAGE_DESKTOP_DPAD_DOWN = 0x91, + HID_USAGE_DESKTOP_DPAD_RIGHT = 0x92, + HID_USAGE_DESKTOP_DPAD_LEFT = 0x93, + HID_USAGE_DESKTOP_SYSTEM_DOCK = 0xA0, + HID_USAGE_DESKTOP_SYSTEM_UNDOCK = 0xA1, + HID_USAGE_DESKTOP_SYSTEM_SETUP = 0xA2, + HID_USAGE_DESKTOP_SYSTEM_BREAK = 0xA3, + HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK = 0xA4, + HID_USAGE_DESKTOP_APPLICATION_BREAK = 0xA5, + HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK = 0xA6, + HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE = 0xA7, + HID_USAGE_DESKTOP_SYSTEM_HIBERNATE = 0xA8, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT = 0xB0, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL = 0xB1, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL = 0xB2, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH = 0xB3, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL = 0xB4, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7 +}; + + +/// HID Usage Table: Consumer Page (0x0C) +/// Only contains controls that supported by Windows (whole list is too long) +enum +{ + // Generic Control + HID_USAGE_CONSUMER_CONTROL = 0x0001, + + // Power Control + HID_USAGE_CONSUMER_POWER = 0x0030, + HID_USAGE_CONSUMER_RESET = 0x0031, + HID_USAGE_CONSUMER_SLEEP = 0x0032, + + // Screen Brightness + HID_USAGE_CONSUMER_BRIGHTNESS_INCREMENT = 0x006F, + HID_USAGE_CONSUMER_BRIGHTNESS_DECREMENT = 0x0070, + + // These HID usages operate only on mobile systems (battery powered) and + // require Windows 8 (build 8302 or greater). + HID_USAGE_CONSUMER_WIRELESS_RADIO_CONTROLS = 0x000C, + HID_USAGE_CONSUMER_WIRELESS_RADIO_BUTTONS = 0x00C6, + HID_USAGE_CONSUMER_WIRELESS_RADIO_LED = 0x00C7, + HID_USAGE_CONSUMER_WIRELESS_RADIO_SLIDER_SWITCH = 0x00C8, + + // Media Control + HID_USAGE_CONSUMER_PLAY_PAUSE = 0x00CD, + HID_USAGE_CONSUMER_SCAN_NEXT = 0x00B5, + HID_USAGE_CONSUMER_SCAN_PREVIOUS = 0x00B6, + HID_USAGE_CONSUMER_STOP = 0x00B7, + HID_USAGE_CONSUMER_VOLUME = 0x00E0, + HID_USAGE_CONSUMER_MUTE = 0x00E2, + HID_USAGE_CONSUMER_BASS = 0x00E3, + HID_USAGE_CONSUMER_TREBLE = 0x00E4, + HID_USAGE_CONSUMER_BASS_BOOST = 0x00E5, + HID_USAGE_CONSUMER_VOLUME_INCREMENT = 0x00E9, + HID_USAGE_CONSUMER_VOLUME_DECREMENT = 0x00EA, + HID_USAGE_CONSUMER_BASS_INCREMENT = 0x0152, + HID_USAGE_CONSUMER_BASS_DECREMENT = 0x0153, + HID_USAGE_CONSUMER_TREBLE_INCREMENT = 0x0154, + HID_USAGE_CONSUMER_TREBLE_DECREMENT = 0x0155, + + // Application Launcher + HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x0183, + HID_USAGE_CONSUMER_AL_EMAIL_READER = 0x018A, + HID_USAGE_CONSUMER_AL_CALCULATOR = 0x0192, + HID_USAGE_CONSUMER_AL_LOCAL_BROWSER = 0x0194, + + // Browser/Explorer Specific + HID_USAGE_CONSUMER_AC_SEARCH = 0x0221, + HID_USAGE_CONSUMER_AC_HOME = 0x0223, + HID_USAGE_CONSUMER_AC_BACK = 0x0224, + HID_USAGE_CONSUMER_AC_FORWARD = 0x0225, + HID_USAGE_CONSUMER_AC_STOP = 0x0226, + HID_USAGE_CONSUMER_AC_REFRESH = 0x0227, + HID_USAGE_CONSUMER_AC_BOOKMARKS = 0x022A, + + // Mouse Horizontal scroll + HID_USAGE_CONSUMER_AC_PAN = 0x0238, +}; + +/*-------------------------------------------------------------------- + * ASCII to KEYCODE Conversion + * Expand to array of [128][2] (shift, keycode) + * + * Usage: example to convert input chr into keyboard report (modifier + keycode) + * + * uint8_t const conv_table[128][2] = { HID_ASCII_TO_KEYCODE }; + * + * uint8_t keycode[6] = { 0 }; + * uint8_t modifier = 0; + * + * if ( conv_table[chr][0] ) modifier = KEYBOARD_MODIFIER_LEFTSHIFT; + * keycode[0] = conv_table[chr][1]; + * tud_hid_keyboard_report(report_id, modifier, keycode); + * + *--------------------------------------------------------------------*/ +#define HID_ASCII_TO_KEYCODE \ + {0, 0 }, /* 0x00 Null */ \ + {0, 0 }, /* 0x01 */ \ + {0, 0 }, /* 0x02 */ \ + {0, 0 }, /* 0x03 */ \ + {0, 0 }, /* 0x04 */ \ + {0, 0 }, /* 0x05 */ \ + {0, 0 }, /* 0x06 */ \ + {0, 0 }, /* 0x07 */ \ + {0, HID_KEY_BACKSPACE }, /* 0x08 Backspace */ \ + {0, HID_KEY_TAB }, /* 0x09 Tab */ \ + {0, HID_KEY_ENTER }, /* 0x0A Line Feed */ \ + {0, 0 }, /* 0x0B */ \ + {0, 0 }, /* 0x0C */ \ + {0, HID_KEY_ENTER }, /* 0x0D CR */ \ + {0, 0 }, /* 0x0E */ \ + {0, 0 }, /* 0x0F */ \ + {0, 0 }, /* 0x10 */ \ + {0, 0 }, /* 0x11 */ \ + {0, 0 }, /* 0x12 */ \ + {0, 0 }, /* 0x13 */ \ + {0, 0 }, /* 0x14 */ \ + {0, 0 }, /* 0x15 */ \ + {0, 0 }, /* 0x16 */ \ + {0, 0 }, /* 0x17 */ \ + {0, 0 }, /* 0x18 */ \ + {0, 0 }, /* 0x19 */ \ + {0, 0 }, /* 0x1A */ \ + {0, HID_KEY_ESCAPE }, /* 0x1B Escape */ \ + {0, 0 }, /* 0x1C */ \ + {0, 0 }, /* 0x1D */ \ + {0, 0 }, /* 0x1E */ \ + {0, 0 }, /* 0x1F */ \ + \ + {0, HID_KEY_SPACE }, /* 0x20 */ \ + {1, HID_KEY_1 }, /* 0x21 ! */ \ + {1, HID_KEY_APOSTROPHE }, /* 0x22 " */ \ + {1, HID_KEY_3 }, /* 0x23 # */ \ + {1, HID_KEY_4 }, /* 0x24 $ */ \ + {1, HID_KEY_5 }, /* 0x25 % */ \ + {1, HID_KEY_7 }, /* 0x26 & */ \ + {0, HID_KEY_APOSTROPHE }, /* 0x27 ' */ \ + {1, HID_KEY_9 }, /* 0x28 ( */ \ + {1, HID_KEY_0 }, /* 0x29 ) */ \ + {1, HID_KEY_8 }, /* 0x2A * */ \ + {1, HID_KEY_EQUAL }, /* 0x2B + */ \ + {0, HID_KEY_COMMA }, /* 0x2C , */ \ + {0, HID_KEY_MINUS }, /* 0x2D - */ \ + {0, HID_KEY_PERIOD }, /* 0x2E . */ \ + {0, HID_KEY_SLASH }, /* 0x2F / */ \ + {0, HID_KEY_0 }, /* 0x30 0 */ \ + {0, HID_KEY_1 }, /* 0x31 1 */ \ + {0, HID_KEY_2 }, /* 0x32 2 */ \ + {0, HID_KEY_3 }, /* 0x33 3 */ \ + {0, HID_KEY_4 }, /* 0x34 4 */ \ + {0, HID_KEY_5 }, /* 0x35 5 */ \ + {0, HID_KEY_6 }, /* 0x36 6 */ \ + {0, HID_KEY_7 }, /* 0x37 7 */ \ + {0, HID_KEY_8 }, /* 0x38 8 */ \ + {0, HID_KEY_9 }, /* 0x39 9 */ \ + {1, HID_KEY_SEMICOLON }, /* 0x3A : */ \ + {0, HID_KEY_SEMICOLON }, /* 0x3B ; */ \ + {1, HID_KEY_COMMA }, /* 0x3C < */ \ + {0, HID_KEY_EQUAL }, /* 0x3D = */ \ + {1, HID_KEY_PERIOD }, /* 0x3E > */ \ + {1, HID_KEY_SLASH }, /* 0x3F ? */ \ + \ + {1, HID_KEY_2 }, /* 0x40 @ */ \ + {1, HID_KEY_A }, /* 0x41 A */ \ + {1, HID_KEY_B }, /* 0x42 B */ \ + {1, HID_KEY_C }, /* 0x43 C */ \ + {1, HID_KEY_D }, /* 0x44 D */ \ + {1, HID_KEY_E }, /* 0x45 E */ \ + {1, HID_KEY_F }, /* 0x46 F */ \ + {1, HID_KEY_G }, /* 0x47 G */ \ + {1, HID_KEY_H }, /* 0x48 H */ \ + {1, HID_KEY_I }, /* 0x49 I */ \ + {1, HID_KEY_J }, /* 0x4A J */ \ + {1, HID_KEY_K }, /* 0x4B K */ \ + {1, HID_KEY_L }, /* 0x4C L */ \ + {1, HID_KEY_M }, /* 0x4D M */ \ + {1, HID_KEY_N }, /* 0x4E N */ \ + {1, HID_KEY_O }, /* 0x4F O */ \ + {1, HID_KEY_P }, /* 0x50 P */ \ + {1, HID_KEY_Q }, /* 0x51 Q */ \ + {1, HID_KEY_R }, /* 0x52 R */ \ + {1, HID_KEY_S }, /* 0x53 S */ \ + {1, HID_KEY_T }, /* 0x55 T */ \ + {1, HID_KEY_U }, /* 0x55 U */ \ + {1, HID_KEY_V }, /* 0x56 V */ \ + {1, HID_KEY_W }, /* 0x57 W */ \ + {1, HID_KEY_X }, /* 0x58 X */ \ + {1, HID_KEY_Y }, /* 0x59 Y */ \ + {1, HID_KEY_Z }, /* 0x5A Z */ \ + {0, HID_KEY_BRACKET_LEFT }, /* 0x5B [ */ \ + {0, HID_KEY_BACKSLASH }, /* 0x5C '\' */ \ + {0, HID_KEY_BRACKET_RIGHT }, /* 0x5D ] */ \ + {1, HID_KEY_6 }, /* 0x5E ^ */ \ + {1, HID_KEY_MINUS }, /* 0x5F _ */ \ + \ + {0, HID_KEY_GRAVE }, /* 0x60 ` */ \ + {0, HID_KEY_A }, /* 0x61 a */ \ + {0, HID_KEY_B }, /* 0x62 b */ \ + {0, HID_KEY_C }, /* 0x63 c */ \ + {0, HID_KEY_D }, /* 0x66 d */ \ + {0, HID_KEY_E }, /* 0x65 e */ \ + {0, HID_KEY_F }, /* 0x66 f */ \ + {0, HID_KEY_G }, /* 0x67 g */ \ + {0, HID_KEY_H }, /* 0x68 h */ \ + {0, HID_KEY_I }, /* 0x69 i */ \ + {0, HID_KEY_J }, /* 0x6A j */ \ + {0, HID_KEY_K }, /* 0x6B k */ \ + {0, HID_KEY_L }, /* 0x6C l */ \ + {0, HID_KEY_M }, /* 0x6D m */ \ + {0, HID_KEY_N }, /* 0x6E n */ \ + {0, HID_KEY_O }, /* 0x6F o */ \ + {0, HID_KEY_P }, /* 0x70 p */ \ + {0, HID_KEY_Q }, /* 0x71 q */ \ + {0, HID_KEY_R }, /* 0x72 r */ \ + {0, HID_KEY_S }, /* 0x73 s */ \ + {0, HID_KEY_T }, /* 0x75 t */ \ + {0, HID_KEY_U }, /* 0x75 u */ \ + {0, HID_KEY_V }, /* 0x76 v */ \ + {0, HID_KEY_W }, /* 0x77 w */ \ + {0, HID_KEY_X }, /* 0x78 x */ \ + {0, HID_KEY_Y }, /* 0x79 y */ \ + {0, HID_KEY_Z }, /* 0x7A z */ \ + {1, HID_KEY_BRACKET_LEFT }, /* 0x7B { */ \ + {1, HID_KEY_BACKSLASH }, /* 0x7C | */ \ + {1, HID_KEY_BRACKET_RIGHT }, /* 0x7D } */ \ + {1, HID_KEY_GRAVE }, /* 0x7E ~ */ \ + {0, HID_KEY_DELETE } /* 0x7F Delete */ \ + +/*-------------------------------------------------------------------- + * KEYCODE to Ascii Conversion + * Expand to array of [128][2] (ascii without shift, ascii with shift) + * + * Usage: example to convert ascii from keycode (key) and shift modifier (shift). + * Here we assume key < 128 ( printable ) + * + * uint8_t const conv_table[128][2] = { HID_KEYCODE_TO_ASCII }; + * char ch = shift ? conv_table[chr][1] : conv_table[chr][0]; + * + *--------------------------------------------------------------------*/ +#define HID_KEYCODE_TO_ASCII \ + {0 , 0 }, /* 0x00 */ \ + {0 , 0 }, /* 0x01 */ \ + {0 , 0 }, /* 0x02 */ \ + {0 , 0 }, /* 0x03 */ \ + {'a' , 'A' }, /* 0x04 */ \ + {'b' , 'B' }, /* 0x05 */ \ + {'c' , 'C' }, /* 0x06 */ \ + {'d' , 'D' }, /* 0x07 */ \ + {'e' , 'E' }, /* 0x08 */ \ + {'f' , 'F' }, /* 0x09 */ \ + {'g' , 'G' }, /* 0x0a */ \ + {'h' , 'H' }, /* 0x0b */ \ + {'i' , 'I' }, /* 0x0c */ \ + {'j' , 'J' }, /* 0x0d */ \ + {'k' , 'K' }, /* 0x0e */ \ + {'l' , 'L' }, /* 0x0f */ \ + {'m' , 'M' }, /* 0x10 */ \ + {'n' , 'N' }, /* 0x11 */ \ + {'o' , 'O' }, /* 0x12 */ \ + {'p' , 'P' }, /* 0x13 */ \ + {'q' , 'Q' }, /* 0x14 */ \ + {'r' , 'R' }, /* 0x15 */ \ + {'s' , 'S' }, /* 0x16 */ \ + {'t' , 'T' }, /* 0x17 */ \ + {'u' , 'U' }, /* 0x18 */ \ + {'v' , 'V' }, /* 0x19 */ \ + {'w' , 'W' }, /* 0x1a */ \ + {'x' , 'X' }, /* 0x1b */ \ + {'y' , 'Y' }, /* 0x1c */ \ + {'z' , 'Z' }, /* 0x1d */ \ + {'1' , '!' }, /* 0x1e */ \ + {'2' , '@' }, /* 0x1f */ \ + {'3' , '#' }, /* 0x20 */ \ + {'4' , '$' }, /* 0x21 */ \ + {'5' , '%' }, /* 0x22 */ \ + {'6' , '^' }, /* 0x23 */ \ + {'7' , '&' }, /* 0x24 */ \ + {'8' , '*' }, /* 0x25 */ \ + {'9' , '(' }, /* 0x26 */ \ + {'0' , ')' }, /* 0x27 */ \ + {'\r' , '\r' }, /* 0x28 */ \ + {'\x1b', '\x1b' }, /* 0x29 */ \ + {'\b' , '\b' }, /* 0x2a */ \ + {'\t' , '\t' }, /* 0x2b */ \ + {' ' , ' ' }, /* 0x2c */ \ + {'-' , '_' }, /* 0x2d */ \ + {'=' , '+' }, /* 0x2e */ \ + {'[' , '{' }, /* 0x2f */ \ + {']' , '}' }, /* 0x30 */ \ + {'\\' , '|' }, /* 0x31 */ \ + {'#' , '~' }, /* 0x32 */ \ + {';' , ':' }, /* 0x33 */ \ + {'\'' , '\"' }, /* 0x34 */ \ + {'`' , '~' }, /* 0x35 */ \ + {',' , '<' }, /* 0x36 */ \ + {'.' , '>' }, /* 0x37 */ \ + {'/' , '?' }, /* 0x38 */ \ + \ + {0 , 0 }, /* 0x39 */ \ + {0 , 0 }, /* 0x3a */ \ + {0 , 0 }, /* 0x3b */ \ + {0 , 0 }, /* 0x3c */ \ + {0 , 0 }, /* 0x3d */ \ + {0 , 0 }, /* 0x3e */ \ + {0 , 0 }, /* 0x3f */ \ + {0 , 0 }, /* 0x40 */ \ + {0 , 0 }, /* 0x41 */ \ + {0 , 0 }, /* 0x42 */ \ + {0 , 0 }, /* 0x43 */ \ + {0 , 0 }, /* 0x44 */ \ + {0 , 0 }, /* 0x45 */ \ + {0 , 0 }, /* 0x46 */ \ + {0 , 0 }, /* 0x47 */ \ + {0 , 0 }, /* 0x48 */ \ + {0 , 0 }, /* 0x49 */ \ + {0 , 0 }, /* 0x4a */ \ + {0 , 0 }, /* 0x4b */ \ + {0 , 0 }, /* 0x4c */ \ + {0 , 0 }, /* 0x4d */ \ + {0 , 0 }, /* 0x4e */ \ + {0 , 0 }, /* 0x4f */ \ + {0 , 0 }, /* 0x50 */ \ + {0 , 0 }, /* 0x51 */ \ + {0 , 0 }, /* 0x52 */ \ + {0 , 0 }, /* 0x53 */ \ + \ + {'/' , '/' }, /* 0x54 */ \ + {'*' , '*' }, /* 0x55 */ \ + {'-' , '-' }, /* 0x56 */ \ + {'+' , '+' }, /* 0x57 */ \ + {'\r' , '\r' }, /* 0x58 */ \ + {'1' , 0 }, /* 0x59 */ \ + {'2' , 0 }, /* 0x5a */ \ + {'3' , 0 }, /* 0x5b */ \ + {'4' , 0 }, /* 0x5c */ \ + {'5' , '5' }, /* 0x5d */ \ + {'6' , 0 }, /* 0x5e */ \ + {'7' , 0 }, /* 0x5f */ \ + {'8' , 0 }, /* 0x60 */ \ + {'9' , 0 }, /* 0x61 */ \ + {'0' , 0 }, /* 0x62 */ \ + {'0' , 0 }, /* 0x63 */ \ + {'=' , '=' }, /* 0x67 */ \ + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_HID_H__ */ + +/// @} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c new file mode 100644 index 000000000..588b61254 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c @@ -0,0 +1,417 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_HID) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "hid_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; // optional Out endpoint + uint8_t itf_protocol; // Boot mouse or keyboard + + uint8_t protocol_mode; // Boot (0) or Report protocol (1) + uint8_t idle_rate; // up to application to handle idle rate + uint16_t report_desc_len; + + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; + + // TODO save hid descriptor since host can specifically request this after enumeration + // Note: HID descriptor may be not available from application after enumeration + tusb_hid_descriptor_hid_t const * hid_descriptor; +} hidd_interface_t; + +CFG_TUSB_MEM_SECTION static hidd_interface_t _hidd_itf[CFG_TUD_HID]; + +/*------------- Helpers -------------*/ +static inline uint8_t get_index_by_itfnum(uint8_t itf_num) +{ + for (uint8_t i=0; i < CFG_TUD_HID; i++ ) + { + if ( itf_num == _hidd_itf[i].itf_num ) return i; + } + + return 0xFF; +} + +//--------------------------------------------------------------------+ +// APPLICATION API +//--------------------------------------------------------------------+ +bool tud_hid_n_ready(uint8_t instance) +{ + uint8_t const ep_in = _hidd_itf[instance].ep_in; + return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); +} + +bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len) +{ + uint8_t const rhport = 0; + hidd_interface_t * p_hid = &_hidd_itf[instance]; + + // claim endpoint + TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); + + // prepare data + if (report_id) + { + len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); + + p_hid->epin_buf[0] = report_id; + memcpy(p_hid->epin_buf+1, report, len); + len++; + }else + { + // If report id = 0, skip ID field + len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE); + memcpy(p_hid->epin_buf, report, len); + } + + return usbd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len); +} + +uint8_t tud_hid_n_interface_protocol(uint8_t instance) +{ + return _hidd_itf[instance].itf_protocol; +} + +uint8_t tud_hid_n_get_protocol(uint8_t instance) +{ + return _hidd_itf[instance].protocol_mode; +} + +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) +{ + hid_keyboard_report_t report; + + report.modifier = modifier; + report.reserved = 0; + + if ( keycode ) + { + memcpy(report.keycode, keycode, 6); + }else + { + tu_memclr(report.keycode, 6); + } + + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); +} + +bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, + uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) +{ + hid_mouse_report_t report = + { + .buttons = buttons, + .x = x, + .y = y, + .wheel = vertical, + .pan = horizontal + }; + + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); +} + +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, + int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) +{ + hid_gamepad_report_t report = + { + .x = x, + .y = y, + .z = z, + .rz = rz, + .rx = rx, + .ry = ry, + .hat = hat, + .buttons = buttons, + }; + + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); +} + +//--------------------------------------------------------------------+ +// USBD-CLASS API +//--------------------------------------------------------------------+ +void hidd_init(void) +{ + hidd_reset(TUD_OPT_RHPORT); +} + +void hidd_reset(uint8_t rhport) +{ + (void) rhport; + tu_memclr(_hidd_itf, sizeof(_hidd_itf)); +} + +uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) +{ + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); + + // len = interface + hid + n*endpoints + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(max_len >= drv_len, 0); + + // Find available interface + hidd_interface_t * p_hid = NULL; + uint8_t hid_id; + for(hid_id=0; hid_idhid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc; + + //------------- Endpoint Descriptor -------------// + p_desc = tu_desc_next(p_desc); + TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); + + if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; + + p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode + p_hid->itf_num = desc_itf->bInterfaceNumber; + + // Use offsetof to avoid pointer to the odd/misaligned address + p_hid->report_desc_len = tu_unaligned_read16((uint8_t const*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength)); + + // Prepare for output endpoint + if (p_hid->ep_out) + { + if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) ) + { + TU_LOG_FAILED(); + TU_BREAKPOINT(); + } + } + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + + uint8_t const hid_itf = get_index_by_itfnum((uint8_t) request->wIndex); + TU_VERIFY(hid_itf < CFG_TUD_HID); + + hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; + + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) + { + //------------- STD Request -------------// + if ( stage == CONTROL_STAGE_SETUP ) + { + uint8_t const desc_type = tu_u16_high(request->wValue); + //uint8_t const desc_index = tu_u16_low (request->wValue); + + if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) + { + TU_VERIFY(p_hid->hid_descriptor); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); + } + else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) + { + uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); + tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_report, p_hid->report_desc_len); + } + else + { + return false; // stall unsupported request + } + } + } + else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + { + //------------- Class Specific Request -------------// + switch( request->bRequest ) + { + case HID_REQ_CONTROL_GET_REPORT: + if ( stage == CONTROL_STAGE_SETUP ) + { + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + uint8_t* report_buf = p_hid->epin_buf; + uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); + + uint16_t xferlen = 0; + + // If host request a specific Report ID, add ID to as 1 byte of response + if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) ) + { + *report_buf++ = report_id; + req_len--; + + xferlen++; + } + + xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len); + TU_ASSERT( xferlen > 0 ); + + tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); + } + break; + + case HID_REQ_CONTROL_SET_REPORT: + if ( stage == CONTROL_STAGE_SETUP ) + { + TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); + tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + uint8_t const* report_buf = p_hid->epout_buf; + uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); + + // If host request a specific Report ID, extract report ID in buffer before invoking callback + if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) ) + { + report_buf++; + report_len--; + } + + tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len); + } + break; + + case HID_REQ_CONTROL_SET_IDLE: + if ( stage == CONTROL_STAGE_SETUP ) + { + p_hid->idle_rate = tu_u16_high(request->wValue); + if ( tud_hid_set_idle_cb ) + { + // stall request if callback return false + TU_VERIFY( tud_hid_set_idle_cb( hid_itf, p_hid->idle_rate) ); + } + + tud_control_status(rhport, request); + } + break; + + case HID_REQ_CONTROL_GET_IDLE: + if ( stage == CONTROL_STAGE_SETUP ) + { + // TODO idle rate of report + tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); + } + break; + + case HID_REQ_CONTROL_GET_PROTOCOL: + if ( stage == CONTROL_STAGE_SETUP ) + { + tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1); + } + break; + + case HID_REQ_CONTROL_SET_PROTOCOL: + if ( stage == CONTROL_STAGE_SETUP ) + { + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + p_hid->protocol_mode = (uint8_t) request->wValue; + if (tud_hid_set_protocol_cb) + { + tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode); + } + } + break; + + default: return false; // stall unsupported request + } + }else + { + return false; // stall unsupported request + } + + return true; +} + +bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) result; + + uint8_t instance = 0; + hidd_interface_t * p_hid = _hidd_itf; + + // Identify which interface to use + for (instance = 0; instance < CFG_TUD_HID; instance++) + { + p_hid = &_hidd_itf[instance]; + if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; + } + TU_ASSERT(instance < CFG_TUD_HID); + + // Sent report successfully + if (ep_addr == p_hid->ep_in) + { + if (tud_hid_report_complete_cb) + { + tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint8_t) xferred_bytes); + } + } + // Received report + else if (ep_addr == p_hid->ep_out) + { + tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); + TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); + } + + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h new file mode 100644 index 000000000..078b67349 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h @@ -0,0 +1,393 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_HID_DEVICE_H_ +#define _TUSB_HID_DEVICE_H_ + +#include "hid.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver Default Configure & Validation +//--------------------------------------------------------------------+ + +#if !defined(CFG_TUD_HID_EP_BUFSIZE) & defined(CFG_TUD_HID_BUFSIZE) + // TODO warn user to use new name later on + // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE, please update to use the new name + #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE +#endif + +#ifndef CFG_TUD_HID_EP_BUFSIZE + #define CFG_TUD_HID_EP_BUFSIZE 64 +#endif + +//--------------------------------------------------------------------+ +// Application API (Multiple Instances) +// CFG_TUD_HID > 1 +//--------------------------------------------------------------------+ + +// Check if the interface is ready to use +bool tud_hid_n_ready(uint8_t instance); + +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values +uint8_t tud_hid_n_interface_protocol(uint8_t instance); + +// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +uint8_t tud_hid_n_get_protocol(uint8_t instance); + +// Send report to host +bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len); + +// KEYBOARD: convenient helper to send keyboard report if application +// use template layout report as defined by hid_keyboard_report_t +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); + +// MOUSE: convenient helper to send mouse report if application +// use template layout report as defined by hid_mouse_report_t +bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); + +// Gamepad: convenient helper to send gamepad report if application +// use template layout report TUD_HID_REPORT_DESC_GAMEPAD +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); + +//--------------------------------------------------------------------+ +// Application API (Single Port) +//--------------------------------------------------------------------+ +static inline bool tud_hid_ready(void); +static inline uint8_t tud_hid_interface_protocol(void); +static inline uint8_t tud_hid_get_protocol(void); +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); + +//--------------------------------------------------------------------+ +// Callbacks (Weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when received GET HID REPORT DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance); + +// Invoked when received GET_REPORT control request +// Application must fill buffer report's content and return its length. +// Return zero will cause the stack to STALL request +uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); + +// Invoked when received SET_REPORT control request or +// received data on OUT endpoint ( Report ID = 0, Type = 0 ) +void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); + +// Invoked when received SET_PROTOCOL request +// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol); + +// Invoked when received SET_IDLE request. return false will stall the request +// - Idle Rate = 0 : only send report if there is changes, i.e skip duplication +// - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). +TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate); + +// Invoked when sent REPORT successfully to host +// Application can use this to send the next report +// Note: For composite reports, report[0] is report ID +TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len); + + +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ +static inline bool tud_hid_ready(void) +{ + return tud_hid_n_ready(0); +} + +static inline uint8_t tud_hid_interface_protocol(void) +{ + return tud_hid_n_interface_protocol(0); +} + +static inline uint8_t tud_hid_get_protocol(void) +{ + return tud_hid_n_get_protocol(0); +} + +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) +{ + return tud_hid_n_report(0, report_id, report, len); +} + +static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) +{ + return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); +} + +static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) +{ + return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); +} + +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) +{ + return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); +} + +/* --------------------------------------------------------------------+ + * HID Report Descriptor Template + * + * Convenient for declaring popular HID device (keyboard, mouse, consumer, + * gamepad etc...). Templates take "HID_REPORT_ID(n)" as input, leave + * empty if multiple reports is not used + * + * - Only 1 report: no parameter + * uint8_t const report_desc[] = { TUD_HID_REPORT_DESC_KEYBOARD() }; + * + * - Multiple Reports: "HID_REPORT_ID(ID)" must be passed to template + * uint8_t const report_desc[] = + * { + * TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(1) ) , + * TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(2) ) + * }; + *--------------------------------------------------------------------*/ + +// Keyboard Report Descriptor Template +#define TUD_HID_REPORT_DESC_KEYBOARD(...) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_KEYBOARD ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + /* Report ID if any */\ + __VA_ARGS__ \ + /* 8 bits Modifier Keys (Shfit, Control, Alt) */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ + HID_USAGE_MIN ( 224 ) ,\ + HID_USAGE_MAX ( 231 ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX ( 1 ) ,\ + HID_REPORT_COUNT ( 8 ) ,\ + HID_REPORT_SIZE ( 1 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* 8 bit reserved */ \ + HID_REPORT_COUNT ( 1 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_CONSTANT ) ,\ + /* Output 5-bit LED Indicator Kana | Compose | ScrollLock | CapsLock | NumLock */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_LED ) ,\ + HID_USAGE_MIN ( 1 ) ,\ + HID_USAGE_MAX ( 5 ) ,\ + HID_REPORT_COUNT ( 5 ) ,\ + HID_REPORT_SIZE ( 1 ) ,\ + HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* led padding */ \ + HID_REPORT_COUNT ( 1 ) ,\ + HID_REPORT_SIZE ( 3 ) ,\ + HID_OUTPUT ( HID_CONSTANT ) ,\ + /* 6-byte Keycodes */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ + HID_USAGE_MIN ( 0 ) ,\ + HID_USAGE_MAX_N ( 255, 2 ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX_N( 255, 2 ) ,\ + HID_REPORT_COUNT ( 6 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ + HID_COLLECTION_END \ + +// Mouse Report Descriptor Template +#define TUD_HID_REPORT_DESC_MOUSE(...) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + /* Report ID if any */\ + __VA_ARGS__ \ + HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\ + HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ + HID_USAGE_MIN ( 1 ) ,\ + HID_USAGE_MAX ( 5 ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX ( 1 ) ,\ + /* Left, Right, Middle, Backward, Forward buttons */ \ + HID_REPORT_COUNT( 5 ) ,\ + HID_REPORT_SIZE ( 1 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* 3 bit padding */ \ + HID_REPORT_COUNT( 1 ) ,\ + HID_REPORT_SIZE ( 3 ) ,\ + HID_INPUT ( HID_CONSTANT ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + /* X, Y position [-127, 127] */ \ + HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ + HID_LOGICAL_MIN ( 0x81 ) ,\ + HID_LOGICAL_MAX ( 0x7f ) ,\ + HID_REPORT_COUNT( 2 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ + /* Verital wheel scroll [-127, 127] */ \ + HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\ + HID_LOGICAL_MIN ( 0x81 ) ,\ + HID_LOGICAL_MAX ( 0x7f ) ,\ + HID_REPORT_COUNT( 1 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \ + /* Horizontal wheel scroll [-127, 127] */ \ + HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \ + HID_LOGICAL_MIN ( 0x81 ), \ + HID_LOGICAL_MAX ( 0x7f ), \ + HID_REPORT_COUNT( 1 ), \ + HID_REPORT_SIZE ( 8 ), \ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \ + HID_COLLECTION_END , \ + HID_COLLECTION_END \ + +// Consumer Control Report Descriptor Template +#define TUD_HID_REPORT_DESC_CONSUMER(...) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ) ,\ + HID_USAGE ( HID_USAGE_CONSUMER_CONTROL ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + /* Report ID if any */\ + __VA_ARGS__ \ + HID_LOGICAL_MIN ( 0x00 ) ,\ + HID_LOGICAL_MAX_N( 0x03FF, 2 ) ,\ + HID_USAGE_MIN ( 0x00 ) ,\ + HID_USAGE_MAX_N ( 0x03FF, 2 ) ,\ + HID_REPORT_COUNT ( 1 ) ,\ + HID_REPORT_SIZE ( 16 ) ,\ + HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ + HID_COLLECTION_END \ + +/* System Control Report Descriptor Template + * 0x00 - do nothing + * 0x01 - Power Off + * 0x02 - Standby + * 0x03 - Wake Host + */ +#define TUD_HID_REPORT_DESC_SYSTEM_CONTROL(...) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_CONTROL ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + /* Report ID if any */\ + __VA_ARGS__ \ + /* 2 bit system power control */ \ + HID_LOGICAL_MIN ( 1 ) ,\ + HID_LOGICAL_MAX ( 3 ) ,\ + HID_REPORT_COUNT ( 1 ) ,\ + HID_REPORT_SIZE ( 2 ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_SLEEP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_WAKE_UP ) ,\ + HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ + /* 6 bit padding */ \ + HID_REPORT_COUNT ( 1 ) ,\ + HID_REPORT_SIZE ( 6 ) ,\ + HID_INPUT ( HID_CONSTANT ) ,\ + HID_COLLECTION_END \ + +// Gamepad Report Descriptor Template +// with 32 buttons, 2 joysticks and 1 hat/dpad with following layout +// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (4 bytes) | +#define TUD_HID_REPORT_DESC_GAMEPAD(...) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + /* Report ID if any */\ + __VA_ARGS__ \ + /* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\ + HID_LOGICAL_MIN ( 0x81 ) ,\ + HID_LOGICAL_MAX ( 0x7f ) ,\ + HID_REPORT_COUNT ( 6 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* 8 bit DPad/Hat Button Map */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\ + HID_LOGICAL_MIN ( 1 ) ,\ + HID_LOGICAL_MAX ( 8 ) ,\ + HID_PHYSICAL_MIN ( 0 ) ,\ + HID_PHYSICAL_MAX_N ( 315, 2 ) ,\ + HID_REPORT_COUNT ( 1 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* 32 bit Button Map */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ + HID_USAGE_MIN ( 1 ) ,\ + HID_USAGE_MAX ( 32 ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX ( 1 ) ,\ + HID_REPORT_COUNT ( 32 ) ,\ + HID_REPORT_SIZE ( 1 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + HID_COLLECTION_END \ + +// HID Generic Input & Output +// - 1st parameter is report size (mandatory) +// - 2nd parameter is report id HID_REPORT_ID(n) (optional) +#define TUD_HID_REPORT_DESC_GENERIC_INOUT(report_size, ...) \ + HID_USAGE_PAGE_N ( HID_USAGE_PAGE_VENDOR, 2 ),\ + HID_USAGE ( 0x01 ),\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ),\ + /* Report ID if any */\ + __VA_ARGS__ \ + /* Input */ \ + HID_USAGE ( 0x02 ),\ + HID_LOGICAL_MIN ( 0x00 ),\ + HID_LOGICAL_MAX_N ( 0xff, 2 ),\ + HID_REPORT_SIZE ( 8 ),\ + HID_REPORT_COUNT( report_size ),\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ + /* Output */ \ + HID_USAGE ( 0x03 ),\ + HID_LOGICAL_MIN ( 0x00 ),\ + HID_LOGICAL_MAX_N ( 0xff, 2 ),\ + HID_REPORT_SIZE ( 8 ),\ + HID_REPORT_COUNT( report_size ),\ + HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ + HID_COLLECTION_END \ + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void hidd_init (void); +void hidd_reset (uint8_t rhport); +uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_HID_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c new file mode 100644 index 000000000..f19f1ba81 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c @@ -0,0 +1,636 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) + +#include "host/usbh.h" +#include "host/usbh_classdriver.h" + +#include "hid_host.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +typedef struct +{ + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; + + uint8_t itf_protocol; // None, Keyboard, Mouse + uint8_t protocol_mode; // Boot (0) or Report protocol (1) + + uint8_t report_desc_type; + uint16_t report_desc_len; + + uint16_t epin_size; + uint16_t epout_size; + + uint8_t epin_buf[CFG_TUH_HID_EPIN_BUFSIZE]; + uint8_t epout_buf[CFG_TUH_HID_EPOUT_BUFSIZE]; +} hidh_interface_t; + +typedef struct +{ + uint8_t inst_count; + hidh_interface_t instances[CFG_TUH_HID]; +} hidh_device_t; + +static hidh_device_t _hidh_dev[CFG_TUH_DEVICE_MAX]; + +//------------- Internal prototypes -------------// + +// Get HID device & interface +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); +static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); +static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); + +//--------------------------------------------------------------------+ +// Interface API +//--------------------------------------------------------------------+ + +uint8_t tuh_hid_instance_count(uint8_t dev_addr) +{ + return get_dev(dev_addr)->inst_count; +} + +bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); +} + +uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return hid_itf->itf_protocol; +} + +//--------------------------------------------------------------------+ +// Control Endpoint API +//--------------------------------------------------------------------+ + +uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return hid_itf->protocol_mode; +} + +static bool set_protocol_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) request->wValue; + + if (tuh_hid_set_protocol_complete_cb) + { + tuh_hid_set_protocol_complete_cb(dev_addr, instance, hid_itf->protocol_mode); + } + + return true; +} + +bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); + + TU_LOG2("HID Set Protocol = %d\r\n", protocol); + + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = protocol, + .wIndex = hid_itf->itf_num, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_protocol_complete) ); + return true; +} + +static bool set_report_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_LOG2("HID Set Report complete\r\n"); + + if (tuh_hid_set_report_complete_cb) + { + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? request->wLength : 0); + } + + return true; +} + +bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); + + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_REPORT, + .wValue = tu_u16(report_type, report_id), + .wIndex = hid_itf->itf_num, + .wLength = len + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, report, set_report_complete) ); + return true; +} + +//--------------------------------------------------------------------+ +// Interrupt Endpoint API +//--------------------------------------------------------------------+ + +bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + // claim endpoint + TU_VERIFY( usbh_edpt_claim(dev_addr, hid_itf->ep_in) ); + + return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); +} + +//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) +//{ +// TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); +// +// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); +// return !usbh_edpt_busy(dev_addr, hid_itf->ep_in); +//} + +//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); + +//--------------------------------------------------------------------+ +// USBH API +//--------------------------------------------------------------------+ +void hidh_init(void) +{ + tu_memclr(_hidh_dev, sizeof(_hidh_dev)); +} + +bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) result; + + uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const instance = get_instance_id_by_epaddr(dev_addr, ep_addr); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + if ( dir == TUSB_DIR_IN ) + { + TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance); + TU_LOG3_MEM(hid_itf->epin_buf, xferred_bytes, 2); + tuh_hid_report_received_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); + }else + { + if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(dev_addr, instance, hid_itf->epout_buf, xferred_bytes); + } + + return true; +} + +void hidh_close(uint8_t dev_addr) +{ + TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); + + hidh_device_t* hid_dev = get_dev(dev_addr); + + if (tuh_hid_umount_cb) + { + for (uint8_t inst = 0; inst < hid_dev->inst_count; inst++ ) tuh_hid_umount_cb(dev_addr, inst); + } + + tu_memclr(hid_dev, sizeof(hidh_device_t)); +} + +//--------------------------------------------------------------------+ +// Enumeration +//--------------------------------------------------------------------+ + +static bool config_set_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + +static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); + +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +{ + (void) max_len; + + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + + TU_LOG2("HID opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); + + // len = interface + hid + n*endpoints + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(max_len >= drv_len); + + uint8_t const *p_desc = (uint8_t const *) desc_itf; + + //------------- HID descriptor -------------// + p_desc = tu_desc_next(p_desc); + tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); + + // not enough interface, try to increase CFG_TUH_HID + // TODO multiple devices + hidh_device_t* hid_dev = get_dev(dev_addr); + TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0); + + //------------- Endpoint Descriptor -------------// + p_desc = tu_desc_next(p_desc); + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + + // first endpoint may be OUT, skip to IN endpoint + // TODO also open endpoint OUT + if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT) + { + p_desc = tu_desc_next(p_desc); + desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + } + + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + + hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); + hid_dev->inst_count++; + + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->ep_in = desc_ep->bEndpointAddress; + hid_itf->epin_size = tu_edpt_packet_size(desc_ep); + + // Assume bNumDescriptors = 1 + hid_itf->report_desc_type = desc_hid->bReportType; + hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + + // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config + hid_itf->protocol_mode = HID_PROTOCOL_BOOT; + if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; + + return true; +} + +bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + // Idle rate = 0 mean only report when there is changes + uint16_t const idle_rate = 0; + + // SET IDLE request, device can stall if not support this request + TU_LOG2("HID Set Idle \r\n"); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_IDLE, + .wValue = idle_rate, + .wIndex = itf_num, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc) ); + + return true; +} + +// Force device to work in BOOT protocol +static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + // Stall is a valid response for SET_IDLE, therefore we could ignore its result + (void) result; + + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + TU_LOG2("HID Set Protocol to Boot Mode\r\n"); + hid_itf->protocol_mode = HID_PROTOCOL_BOOT; + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = HID_PROTOCOL_BOOT, + .wIndex = hid_itf->itf_num, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); + return true; +} + +static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + // We can be here after SET_IDLE or SET_PROTOCOL (boot device) + // Trigger assert if result is not successful with set protocol + if ( request->bRequest != HID_REQ_CONTROL_SET_IDLE ) + { + TU_ASSERT(result == XFER_RESULT_SUCCESS); + } + + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + // Get Report Descriptor if possible + // using usbh enumeration buffer since report descriptor can be very long + if( hid_itf->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) + { + TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len); + + // Driver is mounted without report descriptor + config_driver_mount_complete(dev_addr, instance, NULL, 0); + }else + { + TU_LOG2("HID Get Report Descriptor\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_u16(hid_itf->report_desc_type, 0), + .wIndex = itf_num, + .wLength = hid_itf->report_desc_len + }; + + TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); + } + + return true; +} + +static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + + uint8_t const* desc_report = usbh_get_enum_buf(); + uint16_t const desc_len = request->wLength; + + config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); + + return true; +} + +static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + // enumeration is complete + tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len); + + // notify usbh that driver enumeration is complete + usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num); +} + +//--------------------------------------------------------------------+ +// Report Descriptor Parser +//--------------------------------------------------------------------+ + +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) +{ + // Report Item 6.2.2.2 USB HID 1.11 + union TU_ATTR_PACKED + { + uint8_t byte; + struct TU_ATTR_PACKED + { + uint8_t size : 2; + uint8_t type : 2; + uint8_t tag : 4; + }; + } header; + + tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t)); + + uint8_t report_num = 0; + tuh_hid_report_info_t* info = report_info_arr; + + // current parsed report count & size from descriptor +// uint8_t ri_report_count = 0; +// uint8_t ri_report_size = 0; + + uint8_t ri_collection_depth = 0; + + while(desc_len && report_num < arr_count) + { + header.byte = *desc_report++; + desc_len--; + + uint8_t const tag = header.tag; + uint8_t const type = header.type; + uint8_t const size = header.size; + + uint8_t const data8 = desc_report[0]; + + TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size); + for(uint32_t i=0; iusage_page, desc_report, size); + break; + + case RI_GLOBAL_LOGICAL_MIN : break; + case RI_GLOBAL_LOGICAL_MAX : break; + case RI_GLOBAL_PHYSICAL_MIN : break; + case RI_GLOBAL_PHYSICAL_MAX : break; + + case RI_GLOBAL_REPORT_ID: + info->report_id = data8; + break; + + case RI_GLOBAL_REPORT_SIZE: +// ri_report_size = data8; + break; + + case RI_GLOBAL_REPORT_COUNT: +// ri_report_count = data8; + break; + + case RI_GLOBAL_UNIT_EXPONENT : break; + case RI_GLOBAL_UNIT : break; + case RI_GLOBAL_PUSH : break; + case RI_GLOBAL_POP : break; + + default: break; + } + break; + + case RI_TYPE_LOCAL: + switch(tag) + { + case RI_LOCAL_USAGE: + // only take in account the "usage" before starting REPORT ID + if ( ri_collection_depth == 0 ) info->usage = data8; + break; + + case RI_LOCAL_USAGE_MIN : break; + case RI_LOCAL_USAGE_MAX : break; + case RI_LOCAL_DESIGNATOR_INDEX : break; + case RI_LOCAL_DESIGNATOR_MIN : break; + case RI_LOCAL_DESIGNATOR_MAX : break; + case RI_LOCAL_STRING_INDEX : break; + case RI_LOCAL_STRING_MIN : break; + case RI_LOCAL_STRING_MAX : break; + case RI_LOCAL_DELIMITER : break; + default: break; + } + break; + + // error + default: break; + } + + desc_report += size; + desc_len -= size; + } + + for ( uint8_t i = 0; i < report_num; i++ ) + { + info = report_info_arr+i; + TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); + } + + return report_num; +} + +//--------------------------------------------------------------------+ +// Helper +//--------------------------------------------------------------------+ + +// Get Device by address +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) +{ + return &_hidh_dev[dev_addr-1]; +} + +// Get Interface by instance number +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) +{ + return &_hidh_dev[dev_addr-1].instances[instance]; +} + +// Get instance ID by interface number +static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return inst; + } + + return 0xff; +} + +// Get instance ID by endpoint address +static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (ep_addr == hid->ep_in) || ( ep_addr == hid->ep_out) ) return inst; + } + + return 0xff; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h new file mode 100644 index 000000000..fe09b03b2 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h @@ -0,0 +1,152 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_HID_HOST_H_ +#define _TUSB_HID_HOST_H_ + +#include "hid.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +// TODO Highspeed interrupt can be up to 512 bytes +#ifndef CFG_TUH_HID_EPIN_BUFSIZE +#define CFG_TUH_HID_EPIN_BUFSIZE 64 +#endif + +#ifndef CFG_TUH_HID_EPOUT_BUFSIZE +#define CFG_TUH_HID_EPOUT_BUFSIZE 64 +#endif + + +typedef struct +{ + uint8_t report_id; + uint8_t usage; + uint16_t usage_page; + + // TODO still use the endpoint size for now +// uint8_t in_len; // length of IN report +// uint8_t out_len; // length of OUT report +} tuh_hid_report_info_t; + +//--------------------------------------------------------------------+ +// Interface API +//--------------------------------------------------------------------+ + +// Get the number of HID instances +uint8_t tuh_hid_instance_count(uint8_t dev_addr); + +// Check if HID instance is mounted +bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); + +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values +uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); + +// Parse report descriptor into array of report_info struct and return number of reports. +// For complicated report, application should write its own parser. +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; + +//--------------------------------------------------------------------+ +// Control Endpoint API +//--------------------------------------------------------------------+ + +// Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +// Note: Device will be initialized in Boot protocol for simplicity. +// Application can use set_protocol() to switch back to Report protocol. +uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); + +// Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +// This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) +bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); + +// Set Report using control endpoint +// report_type is either Intput, Output or Feature, (value from hid_report_type_t) +bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); + +//--------------------------------------------------------------------+ +// Interrupt Endpoint API +//--------------------------------------------------------------------+ + +// Check if the interface is ready to use +//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); + +// Try to receive next report on Interrupt Endpoint. Immediately return +// - true If succeeded, tuh_hid_report_received_cb() callback will be invoked when report is available +// - false if failed to queue the transfer e.g endpoint is busy +bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance); + +// Send report using interrupt endpoint +// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent. +//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); + +//--------------------------------------------------------------------+ +// Callbacks (Weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when device with hid interface is mounted +// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() +// can be used to parse common/simple enough descriptor. +// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped +// therefore report_desc = NULL, desc_len = 0 +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); + +// Invoked when device with hid interface is un-mounted +TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); + +// Invoked when received report from device via interrupt endpoint +// Note: if there is report ID (composite), it is 1st byte of report +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); + +// Invoked when sent report to device successfully via interrupt endpoint +TU_ATTR_WEAK void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); + +// Invoked when Sent Report to device via either control endpoint +// len = 0 indicate there is error in the transfer e.g stalled response +TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); + +// Invoked when Set Protocol request is complete +TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void hidh_init (void); +bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void hidh_close (uint8_t dev_addr); + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_HID_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h new file mode 100644 index 000000000..74dc41749 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h @@ -0,0 +1,212 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup group_class + * \defgroup ClassDriver_CDC Communication Device Class (CDC) + * Currently only Abstract Control Model subclass is supported + * @{ */ + +#ifndef _TUSB_MIDI_H__ +#define _TUSB_MIDI_H__ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Specific Descriptor +//--------------------------------------------------------------------+ + +typedef enum +{ + MIDI_CS_INTERFACE_HEADER = 0x01, + MIDI_CS_INTERFACE_IN_JACK = 0x02, + MIDI_CS_INTERFACE_OUT_JACK = 0x03, + MIDI_CS_INTERFACE_ELEMENT = 0x04, +} midi_cs_interface_subtype_t; + +typedef enum +{ + MIDI_CS_ENDPOINT_GENERAL = 0x01 +} midi_cs_endpoint_subtype_t; + +typedef enum +{ + MIDI_JACK_EMBEDDED = 0x01, + MIDI_JACK_EXTERNAL = 0x02 +} midi_jack_type_t; + +typedef enum +{ + MIDI_CIN_MISC = 0, + MIDI_CIN_CABLE_EVENT = 1, + MIDI_CIN_SYSCOM_2BYTE = 2, // 2 byte system common message e.g MTC, SongSelect + MIDI_CIN_SYSCOM_3BYTE = 3, // 3 byte system common message e.g SPP + MIDI_CIN_SYSEX_START = 4, // SysEx starts or continue + MIDI_CIN_SYSEX_END_1BYTE = 5, // SysEx ends with 1 data, or 1 byte system common message + MIDI_CIN_SYSEX_END_2BYTE = 6, // SysEx ends with 2 data + MIDI_CIN_SYSEX_END_3BYTE = 7, // SysEx ends with 3 data + MIDI_CIN_NOTE_ON = 8, + MIDI_CIN_NOTE_OFF = 9, + MIDI_CIN_POLY_KEYPRESS = 10, + MIDI_CIN_CONTROL_CHANGE = 11, + MIDI_CIN_PROGRAM_CHANGE = 12, + MIDI_CIN_CHANNEL_PRESSURE = 13, + MIDI_CIN_PITCH_BEND_CHANGE = 14, + MIDI_CIN_1BYTE_DATA = 15 +} midi_code_index_number_t; + +// MIDI 1.0 status byte +enum +{ + //------------- System Exclusive -------------// + MIDI_STATUS_SYSEX_START = 0xF0, + MIDI_STATUS_SYSEX_END = 0xF7, + + //------------- System Common -------------// + MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME = 0xF1, + MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER = 0xF2, + MIDI_STATUS_SYSCOM_SONG_SELECT = 0xF3, + // F4, F5 is undefined + MIDI_STATUS_SYSCOM_TUNE_REQUEST = 0xF6, + + //------------- System RealTime -------------// + MIDI_STATUS_SYSREAL_TIMING_CLOCK = 0xF8, + // 0xF9 is undefined + MIDI_STATUS_SYSREAL_START = 0xFA, + MIDI_STATUS_SYSREAL_CONTINUE = 0xFB, + MIDI_STATUS_SYSREAL_STOP = 0xFC, + // 0xFD is undefined + MIDI_STATUS_SYSREAL_ACTIVE_SENSING = 0xFE, + MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF, +}; + +/// MIDI Interface Header Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType + uint16_t bcdMSC ; ///< MidiStreaming SubClass release number in Binary-Coded Decimal + uint16_t wTotalLength ; +} midi_desc_header_t; + +/// MIDI In Jack Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType + uint8_t bJackType ; ///< Embedded or External + uint8_t bJackID ; ///< Unique ID for MIDI IN Jack + uint8_t iJack ; ///< string descriptor +} midi_desc_in_jack_t; + + +/// MIDI Out Jack Descriptor with single pin +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType + uint8_t bJackType ; ///< Embedded or External + uint8_t bJackID ; ///< Unique ID for MIDI IN Jack + uint8_t bNrInputPins; + + uint8_t baSourceID; + uint8_t baSourcePin; + + uint8_t iJack ; ///< string descriptor +} midi_desc_out_jack_t ; + +/// MIDI Out Jack Descriptor with multiple pins +#define midi_desc_out_jack_n_t(input_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; \ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bJackType ; \ + uint8_t bJackID ; \ + uint8_t bNrInputPins ; \ + struct TU_ATTR_PACKED { \ + uint8_t baSourceID; \ + uint8_t baSourcePin; \ + } pins[input_num]; \ + uint8_t iJack ; \ + } + +/// MIDI Element Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType ; ///< Descriptor SubType + uint8_t bElementID; + + uint8_t bNrInputPins; + uint8_t baSourceID; + uint8_t baSourcePin; + + uint8_t bNrOutputPins; + uint8_t bInTerminalLink; + uint8_t bOutTerminalLink; + uint8_t bElCapsSize; + + uint16_t bmElementCaps; + uint8_t iElement; +} midi_desc_element_t; + +/// MIDI Element Descriptor with multiple pins +#define midi_desc_element_n_t(input_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint8_t bElementID; \ + uint8_t bNrInputPins; \ + struct TU_ATTR_PACKED { \ + uint8_t baSourceID; \ + uint8_t baSourcePin; \ + } pins[input_num]; \ + uint8_t bNrOutputPins; \ + uint8_t bInTerminalLink; \ + uint8_t bOutTerminalLink; \ + uint8_t bElCapsSize; \ + uint16_t bmElementCaps; \ + uint8_t iElement; \ + } + +/** @} */ + +#ifdef __cplusplus + } +#endif + +#endif + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c new file mode 100644 index 000000000..b08b362f9 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c @@ -0,0 +1,545 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MIDI) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "midi_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +typedef struct +{ + uint8_t buffer[4]; + uint8_t index; + uint8_t total; +}midid_stream_t; + +typedef struct +{ + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; + + // For Stream read()/write() API + // Messages are always 4 bytes long, queue them for reading and writing so the + // callers can use the Stream interface with single-byte read/write calls. + midid_stream_t stream_write; + midid_stream_t stream_read; + + /*------------- From this point, data is not cleared by bus reset -------------*/ + // FIFO + tu_fifo_t rx_ff; + tu_fifo_t tx_ff; + uint8_t rx_ff_buf[CFG_TUD_MIDI_RX_BUFSIZE]; + uint8_t tx_ff_buf[CFG_TUD_MIDI_TX_BUFSIZE]; + + #if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex; + osal_mutex_def_t tx_ff_mutex; + #endif + + // Endpoint Transfer buffer + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE]; + +} midid_interface_t; + +#define ITF_MEM_RESET_SIZE offsetof(midid_interface_t, rx_ff) + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION midid_interface_t _midid_itf[CFG_TUD_MIDI]; + +bool tud_midi_n_mounted (uint8_t itf) +{ + midid_interface_t* midi = &_midid_itf[itf]; + return midi->ep_in && midi->ep_out; +} + +static void _prep_out_transaction (midid_interface_t* p_midi) +{ + uint8_t const rhport = TUD_OPT_RHPORT; + uint16_t available = tu_fifo_remaining(&p_midi->rx_ff); + + // Prepare for incoming data but only allow what we can store in the ring buffer. + // TODO Actually we can still carry out the transfer, keeping count of received bytes + // and slowly move it to the FIFO when read(). + // This pre-check reduces endpoint claiming + TU_VERIFY(available >= sizeof(p_midi->epout_buf), ); + + // claim endpoint + TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), ); + + // fifo can be changed before endpoint is claimed + available = tu_fifo_remaining(&p_midi->rx_ff); + + if ( available >= sizeof(p_midi->epout_buf) ) { + usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, sizeof(p_midi->epout_buf)); + }else + { + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, p_midi->ep_out); + } +} + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ +uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) +{ + (void) cable_num; + + midid_interface_t* midi = &_midid_itf[itf]; + midid_stream_t const* stream = &midi->stream_read; + + // when using with packet API stream total & index are both zero + return tu_fifo_count(&midi->rx_ff) + (stream->total - stream->index); +} + +uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) +{ + (void) cable_num; + TU_VERIFY(bufsize, 0); + + uint8_t* buf8 = (uint8_t*) buffer; + + midid_interface_t* midi = &_midid_itf[itf]; + midid_stream_t* stream = &midi->stream_read; + + uint32_t total_read = 0; + while( bufsize ) + { + // Get new packet from fifo, then set packet expected bytes + if ( stream->total == 0 ) + { + // return if there is no more data from fifo + if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read; + + uint8_t const code_index = stream->buffer[0] & 0x0f; + + // MIDI 1.0 Table 4-1: Code Index Number Classifications + switch(code_index) + { + case MIDI_CIN_MISC: + case MIDI_CIN_CABLE_EVENT: + // These are reserved and unused, possibly issue somewhere, skip this packet + return 0; + break; + + case MIDI_CIN_SYSEX_END_1BYTE: + case MIDI_CIN_1BYTE_DATA: + stream->total = 1; + break; + + case MIDI_CIN_SYSCOM_2BYTE : + case MIDI_CIN_SYSEX_END_2BYTE : + case MIDI_CIN_PROGRAM_CHANGE : + case MIDI_CIN_CHANNEL_PRESSURE : + stream->total = 2; + break; + + default: + stream->total = 3; + break; + } + } + + // Copy data up to bufsize + uint32_t const count = tu_min32(stream->total - stream->index, bufsize); + + // Skip the header (1st byte) in the buffer + memcpy(buf8, stream->buffer + 1 + stream->index, count); + + total_read += count; + stream->index += count; + buf8 += count; + bufsize -= count; + + // complete current event packet, reset stream + if ( stream->total == stream->index ) + { + stream->index = 0; + stream->total = 0; + } + } + + return total_read; +} + +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) +{ + midid_interface_t* midi = &_midid_itf[itf]; + TU_VERIFY(midi->ep_out); + + uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4); + _prep_out_transaction(midi); + return (num_read == 4); +} + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ + +static uint32_t write_flush(midid_interface_t* midi) +{ + // No data to send + if ( !tu_fifo_count(&midi->tx_ff) ) return 0; + + uint8_t const rhport = TUD_OPT_RHPORT; + + // skip if previous transfer not complete + TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); + + uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); + + if (count) + { + TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); + return count; + }else + { + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, midi->ep_in); + return 0; + } +} + +uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +{ + midid_interface_t* midi = &_midid_itf[itf]; + TU_VERIFY(midi->ep_in, 0); + + midid_stream_t* stream = &midi->stream_write; + + uint32_t i = 0; + while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) + { + uint8_t const data = buffer[i]; + i++; + + if ( stream->index == 0 ) + { + //------------- New event packet -------------// + + uint8_t const msg = data >> 4; + + stream->index = 2; + stream->buffer[1] = data; + + // Check to see if we're still in a SysEx transmit. + if ( stream->buffer[0] == MIDI_CIN_SYSEX_START ) + { + if ( data == MIDI_STATUS_SYSEX_END ) + { + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; + } + else + { + stream->total = 4; + } + } + else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) + { + // Channel Voice Messages + stream->buffer[0] = (cable_num << 4) | msg; + stream->total = 4; + } + else if ( msg == 0xC || msg == 0xD) + { + // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) + stream->buffer[0] = (cable_num << 4) | msg; + stream->total = 3; + } + else if ( msg == 0xf ) + { + // System message + if ( data == MIDI_STATUS_SYSEX_START ) + { + stream->buffer[0] = MIDI_CIN_SYSEX_START; + stream->total = 4; + } + else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) + { + stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; + stream->total = 3; + } + else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) + { + stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; + stream->total = 4; + } + else + { + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; + } + } + else + { + // Pack individual bytes if we don't support packing them into words. + stream->buffer[0] = cable_num << 4 | 0xf; + stream->buffer[2] = 0; + stream->buffer[3] = 0; + stream->index = 2; + stream->total = 2; + } + } + else + { + //------------- On-going (buffering) packet -------------// + + TU_ASSERT(stream->index < 4, i); + stream->buffer[stream->index] = data; + stream->index++; + + // See if this byte ends a SysEx. + if ( stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) + { + stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1); + stream->total = stream->index; + } + } + + // Send out packet + if ( stream->index == stream->total ) + { + // zeroes unused bytes + for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; + + uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); + + // complete current event packet, reset stream + stream->index = stream->total = 0; + + // FIFO overflown, since we already check fifo remaining. It is probably race condition + TU_ASSERT(count == 4, i); + } + } + + write_flush(midi); + + return i; +} + +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) +{ + midid_interface_t* midi = &_midid_itf[itf]; + TU_VERIFY(midi->ep_in); + + if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; + + tu_fifo_write_n(&midi->tx_ff, packet, 4); + write_flush(midi); + + return true; +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void midid_init(void) +{ + tu_memclr(_midid_itf, sizeof(_midid_itf)); + + for(uint8_t i=0; irx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); // true, true + tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. + + #if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&midi->rx_ff, NULL, osal_mutex_create(&midi->rx_ff_mutex)); + tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex), NULL); + #endif + } +} + +void midid_reset(uint8_t rhport) +{ + (void) rhport; + + for(uint8_t i=0; irx_ff); + tu_fifo_clear(&midi->tx_ff); + } +} + +uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) +{ + // 1st Interface is Audio Control v1 + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); + + uint16_t drv_len = tu_desc_len(desc_itf); + uint8_t const * p_desc = tu_desc_next(desc_itf); + + // Skip Class Specific descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) + { + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + // 2nd Interface is MIDI Streaming + TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); + tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; + + TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && + AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); + + // Find available interface + midid_interface_t * p_midi = NULL; + for(uint8_t i=0; iitf_num = desc_midi->bInterfaceNumber; + (void) p_midi->itf_num; + + // next descriptor + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + + // Find and open endpoint descriptors + uint8_t found_endpoints = 0; + while ( (found_endpoints < desc_midi->bNumEndpoints) && (drv_len <= max_len) ) + { + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) + { + p_midi->ep_in = ep_addr; + } else { + p_midi->ep_out = ep_addr; + } + + // Class Specific MIDI Stream endpoint descriptor + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + + found_endpoints += 1; + } + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + // Prepare for incoming data + _prep_out_transaction(p_midi); + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + (void) rhport; + (void) stage; + (void) request; + + // driver doesn't support any request yet + return false; +} + +bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) result; + (void) rhport; + + uint8_t itf; + midid_interface_t* p_midi; + + // Identify which interface to use + for (itf = 0; itf < CFG_TUD_MIDI; itf++) + { + p_midi = &_midid_itf[itf]; + if ( ( ep_addr == p_midi->ep_out ) || ( ep_addr == p_midi->ep_in ) ) break; + } + TU_ASSERT(itf < CFG_TUD_MIDI); + + // receive new data + if ( ep_addr == p_midi->ep_out ) + { + tu_fifo_write_n(&p_midi->rx_ff, p_midi->epout_buf, xferred_bytes); + + // invoke receive callback if available + if (tud_midi_rx_cb) tud_midi_rx_cb(itf); + + // prepare for next + // TODO for now ep_out is not used by public API therefore there is no race condition, + // and does not need to claim like ep_in + _prep_out_transaction(p_midi); + } + else if ( ep_addr == p_midi->ep_in ) + { + if (0 == write_flush(p_midi)) + { + // If there is no data left, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + if ( !tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) + { + if ( usbd_edpt_claim(rhport, p_midi->ep_in) ) + { + usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); + } + } + } + } + + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h new file mode 100644 index 000000000..211edc8d1 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h @@ -0,0 +1,173 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_MIDI_DEVICE_H_ +#define _TUSB_MIDI_DEVICE_H_ + +#include "class/audio/audio.h" +#include "midi.h" + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +#if !defined(CFG_TUD_MIDI_EP_BUFSIZE) && defined(CFG_TUD_MIDI_EPSIZE) + #warning CFG_TUD_MIDI_EPSIZE is renamed to CFG_TUD_MIDI_EP_BUFSIZE, please update to use the new name + #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE +#endif + +#ifndef CFG_TUD_MIDI_EP_BUFSIZE + #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/** \addtogroup MIDI_Serial Serial + * @{ + * \defgroup MIDI_Serial_Device Device + * @{ */ + +//--------------------------------------------------------------------+ +// Application API (Multiple Interfaces) +// CFG_TUD_MIDI > 1 +//--------------------------------------------------------------------+ + +// Check if midi interface is mounted +bool tud_midi_n_mounted (uint8_t itf); + +// Get the number of bytes available for reading +uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); + +// Read byte stream (legacy) +uint32_t tud_midi_n_stream_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); + +// Write byte Stream (legacy) +uint32_t tud_midi_n_stream_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); + +// Read event packet (4 bytes) +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); + +// Write event packet (4 bytes) +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); + +//--------------------------------------------------------------------+ +// Application API (Single Interface) +//--------------------------------------------------------------------+ +static inline bool tud_midi_mounted (void); +static inline uint32_t tud_midi_available (void); + +static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize); +static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); + +static inline bool tud_midi_packet_read (uint8_t packet[4]); +static inline bool tud_midi_packet_write (uint8_t const packet[4]); + +//------------- Deprecated API name -------------// +// TODO remove after 0.10.0 release + +TU_ATTR_DEPRECATED("tud_midi_read() is renamed to tud_midi_stream_read()") +static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) +{ + return tud_midi_stream_read(buffer, bufsize); +} + +TU_ATTR_DEPRECATED("tud_midi_write() is renamed to tud_midi_stream_write()") +static inline uint32_t tud_midi_write(uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +{ + return tud_midi_stream_write(cable_num, buffer, bufsize); +} + + +TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") +static inline bool tud_midi_send(uint8_t packet[4]) +{ + return tud_midi_packet_write(packet); +} + +TU_ATTR_DEPRECATED("tud_midi_receive() is renamed to tud_midi_packet_read()") +static inline bool tud_midi_receive(uint8_t packet[4]) +{ + return tud_midi_packet_read(packet); +} + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); + +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ + +static inline bool tud_midi_mounted (void) +{ + return tud_midi_n_mounted(0); +} + +static inline uint32_t tud_midi_available (void) +{ + return tud_midi_n_available(0, 0); +} + +static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize) +{ + return tud_midi_n_stream_read(0, 0, buffer, bufsize); +} + +static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +{ + return tud_midi_n_stream_write(0, cable_num, buffer, bufsize); +} + +static inline bool tud_midi_packet_read (uint8_t packet[4]) +{ + return tud_midi_n_packet_read(0, packet); +} + +static inline bool tud_midi_packet_write (uint8_t const packet[4]) +{ + return tud_midi_n_packet_write(0, packet); +} + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void midid_init (void); +void midid_reset (uint8_t rhport); +uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_MIDI_DEVICE_H_ */ + +/** @} */ +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h new file mode 100644 index 000000000..84b6e4d79 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h @@ -0,0 +1,382 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_MSC_H_ +#define _TUSB_MSC_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Mass Storage Class Constant +//--------------------------------------------------------------------+ +/// MassStorage Subclass +typedef enum +{ + MSC_SUBCLASS_RBC = 1 , ///< Reduced Block Commands (RBC) T10 Project 1240-D + MSC_SUBCLASS_SFF_MMC , ///< SFF-8020i, MMC-2 (ATAPI). Typically used by a CD/DVD device + MSC_SUBCLASS_QIC , ///< QIC-157. Typically used by a tape device + MSC_SUBCLASS_UFI , ///< UFI. Typically used by Floppy Disk Drive (FDD) device + MSC_SUBCLASS_SFF , ///< SFF-8070i. Can be used by Floppy Disk Drive (FDD) device + MSC_SUBCLASS_SCSI ///< SCSI transparent command set +}msc_subclass_type_t; + +enum { + MSC_CBW_SIGNATURE = 0x43425355, ///< Constant value of 43425355h (little endian) + MSC_CSW_SIGNATURE = 0x53425355 ///< Constant value of 53425355h (little endian) +}; + +/// \brief MassStorage Protocol. +/// \details CBI only approved to use with full-speed floopy disk & should not used with highspeed or device other than floopy +typedef enum +{ + MSC_PROTOCOL_CBI = 0 , ///< Control/Bulk/Interrupt protocol (with command completion interrupt) + MSC_PROTOCOL_CBI_NO_INTERRUPT = 1 , ///< Control/Bulk/Interrupt protocol (without command completion interrupt) + MSC_PROTOCOL_BOT = 0x50 ///< Bulk-Only Transport +}msc_protocol_type_t; + +/// MassStorage Class-Specific Control Request +typedef enum +{ + MSC_REQ_GET_MAX_LUN = 254, ///< The Get Max LUN device request is used to determine the number of logical units supported by the device. Logical Unit Numbers on the device shall be numbered contiguously starting from LUN 0 to a maximum LUN of 15 + MSC_REQ_RESET = 255 ///< This request is used to reset the mass storage device and its associated interface. This class-specific request shall ready the device for the next CBW from the host. +}msc_request_type_t; + +/// \brief Command Block Status Values +/// \details Indicates the success or failure of the command. The device shall set this byte to zero if the command completed +/// successfully. A non-zero value shall indicate a failure during command execution according to the following +typedef enum +{ + MSC_CSW_STATUS_PASSED = 0 , ///< MSC_CSW_STATUS_PASSED + MSC_CSW_STATUS_FAILED , ///< MSC_CSW_STATUS_FAILED + MSC_CSW_STATUS_PHASE_ERROR ///< MSC_CSW_STATUS_PHASE_ERROR +}msc_csw_status_t; + +/// Command Block Wrapper +typedef struct TU_ATTR_PACKED +{ + uint32_t signature; ///< Signature that helps identify this data packet as a CBW. The signature field shall contain the value 43425355h (little endian), indicating a CBW. + uint32_t tag; ///< Tag sent by the host. The device shall echo the contents of this field back to the host in the dCSWTagfield of the associated CSW. The dCSWTagpositively associates a CSW with the corresponding CBW. + uint32_t total_bytes; ///< The number of bytes of data that the host expects to transfer on the Bulk-In or Bulk-Out endpoint (as indicated by the Direction bit) during the execution of this command. If this field is zero, the device and the host shall transfer no data between the CBW and the associated CSW, and the device shall ignore the value of the Direction bit in bmCBWFlags. + uint8_t dir; ///< Bit 7 of this field define transfer direction \n - 0 : Data-Out from host to the device. \n - 1 : Data-In from the device to the host. + uint8_t lun; ///< The device Logical Unit Number (LUN) to which the command block is being sent. For devices that support multiple LUNs, the host shall place into this field the LUN to which this command block is addressed. Otherwise, the host shall set this field to zero. + uint8_t cmd_len; ///< The valid length of the CBWCBin bytes. This defines the valid length of the command block. The only legal values are 1 through 16 + uint8_t command[16]; ///< The command block to be executed by the device. The device shall interpret the first cmd_len bytes in this field as a command block +}msc_cbw_t; + +TU_VERIFY_STATIC(sizeof(msc_cbw_t) == 31, "size is not correct"); + +/// Command Status Wrapper +typedef struct TU_ATTR_PACKED +{ + uint32_t signature ; ///< Signature that helps identify this data packet as a CSW. The signature field shall contain the value 53425355h (little endian), indicating CSW. + uint32_t tag ; ///< The device shall set this field to the value received in the dCBWTag of the associated CBW. + uint32_t data_residue ; ///< For Data-Out the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLength, and the actual amount of data processed by the device. For Data-In the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLengthand the actual amount of relevant data sent by the device + uint8_t status ; ///< indicates the success or failure of the command. Values from \ref msc_csw_status_t +}msc_csw_t; + +TU_VERIFY_STATIC(sizeof(msc_csw_t) == 13, "size is not correct"); + +//--------------------------------------------------------------------+ +// SCSI Constant +//--------------------------------------------------------------------+ + +/// SCSI Command Operation Code +typedef enum +{ + SCSI_CMD_TEST_UNIT_READY = 0x00, ///< The SCSI Test Unit Ready command is used to determine if a device is ready to transfer data (read/write), i.e. if a disk has spun up, if a tape is loaded and ready etc. The device does not perform a self-test operation. + SCSI_CMD_INQUIRY = 0x12, ///< The SCSI Inquiry command is used to obtain basic information from a target device. + SCSI_CMD_MODE_SELECT_6 = 0x15, ///< provides a means for the application client to specify medium, logical unit, or peripheral device parameters to the device server. Device servers that implement the MODE SELECT(6) command shall also implement the MODE SENSE(6) command. Application clients should issue MODE SENSE(6) prior to each MODE SELECT(6) to determine supported mode pages, page lengths, and other parameters. + SCSI_CMD_MODE_SENSE_6 = 0x1A, ///< provides a means for a device server to report parameters to an application client. It is a complementary command to the MODE SELECT(6) command. Device servers that implement the MODE SENSE(6) command shall also implement the MODE SELECT(6) command. + SCSI_CMD_START_STOP_UNIT = 0x1B, + SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E, + SCSI_CMD_READ_CAPACITY_10 = 0x25, ///< The SCSI Read Capacity command is used to obtain data capacity information from a target device. + SCSI_CMD_REQUEST_SENSE = 0x03, ///< The SCSI Request Sense command is part of the SCSI computer protocol standard. This command is used to obtain sense data -- status/error information -- from a target device. + SCSI_CMD_READ_FORMAT_CAPACITY = 0x23, ///< The command allows the Host to request a list of the possible format capacities for an installed writable media. This command also has the capability to report the writable capacity for a media when it is installed + SCSI_CMD_READ_10 = 0x28, ///< The READ (10) command requests that the device server read the specified logical block(s) and transfer them to the data-in buffer. + SCSI_CMD_WRITE_10 = 0x2A, ///< The WRITE (10) command requests thatthe device server transfer the specified logical block(s) from the data-out buffer and write them. +}scsi_cmd_type_t; + +/// SCSI Sense Key +typedef enum +{ + SCSI_SENSE_NONE = 0x00, ///< no specific Sense Key. This would be the case for a successful command + SCSI_SENSE_RECOVERED_ERROR = 0x01, ///< ndicates the last command completed successfully with some recovery action performed by the disc drive. + SCSI_SENSE_NOT_READY = 0x02, ///< Indicates the logical unit addressed cannot be accessed. + SCSI_SENSE_MEDIUM_ERROR = 0x03, ///< Indicates the command terminated with a non-recovered error condition. + SCSI_SENSE_HARDWARE_ERROR = 0x04, ///< Indicates the disc drive detected a nonrecoverable hardware failure while performing the command or during a self test. + SCSI_SENSE_ILLEGAL_REQUEST = 0x05, ///< Indicates an illegal parameter in the command descriptor block or in the additional parameters + SCSI_SENSE_UNIT_ATTENTION = 0x06, ///< Indicates the disc drive may have been reset. + SCSI_SENSE_DATA_PROTECT = 0x07, ///< Indicates that a command that reads or writes the medium was attempted on a block that is protected from this operation. The read or write operation is not performed. + SCSI_SENSE_FIRMWARE_ERROR = 0x08, ///< Vendor specific sense key. + SCSI_SENSE_ABORTED_COMMAND = 0x0b, ///< Indicates the disc drive aborted the command. + SCSI_SENSE_EQUAL = 0x0c, ///< Indicates a SEARCH DATA command has satisfied an equal comparison. + SCSI_SENSE_VOLUME_OVERFLOW = 0x0d, ///< Indicates a buffered peripheral device has reached the end of medium partition and data remains in the buffer that has not been written to the medium. + SCSI_SENSE_MISCOMPARE = 0x0e ///< ndicates that the source data did not match the data read from the medium. +}scsi_sense_key_type_t; + +//--------------------------------------------------------------------+ +// SCSI Primary Command (SPC-4) +//--------------------------------------------------------------------+ + +/// SCSI Test Unit Ready Command +typedef struct TU_ATTR_PACKED +{ + uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_TEST_UNIT_READY + uint8_t lun ; ///< Logical Unit + uint8_t reserved[3] ; + uint8_t control ; +} scsi_test_unit_ready_t; + +TU_VERIFY_STATIC(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct"); + +/// SCSI Inquiry Command +typedef struct TU_ATTR_PACKED +{ + uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_INQUIRY + uint8_t reserved1 ; + uint8_t page_code ; + uint8_t reserved2 ; + uint8_t alloc_length ; ///< specifies the maximum number of bytes that USB host has allocated in the Data-In Buffer. An allocation length of zero specifies that no data shall be transferred. + uint8_t control ; +} scsi_inquiry_t, scsi_request_sense_t; + +TU_VERIFY_STATIC(sizeof(scsi_inquiry_t) == 6, "size is not correct"); + +/// SCSI Inquiry Response Data +typedef struct TU_ATTR_PACKED +{ + uint8_t peripheral_device_type : 5; + uint8_t peripheral_qualifier : 3; + + uint8_t : 7; + uint8_t is_removable : 1; + + uint8_t version; + + uint8_t response_data_format : 4; + uint8_t hierarchical_support : 1; + uint8_t normal_aca : 1; + uint8_t : 2; + + uint8_t additional_length; + + uint8_t protect : 1; + uint8_t : 2; + uint8_t third_party_copy : 1; + uint8_t target_port_group_support : 2; + uint8_t access_control_coordinator : 1; + uint8_t scc_support : 1; + + uint8_t addr16 : 1; + uint8_t : 3; + uint8_t multi_port : 1; + uint8_t : 1; // vendor specific + uint8_t enclosure_service : 1; + uint8_t : 1; + + uint8_t : 1; // vendor specific + uint8_t cmd_que : 1; + uint8_t : 2; + uint8_t sync : 1; + uint8_t wbus16 : 1; + uint8_t : 2; + + uint8_t vendor_id[8] ; ///< 8 bytes of ASCII data identifying the vendor of the product. + uint8_t product_id[16]; ///< 16 bytes of ASCII data defined by the vendor. + uint8_t product_rev[4]; ///< 4 bytes of ASCII data defined by the vendor. +} scsi_inquiry_resp_t; + +TU_VERIFY_STATIC(sizeof(scsi_inquiry_resp_t) == 36, "size is not correct"); + + +typedef struct TU_ATTR_PACKED +{ + uint8_t response_code : 7; ///< 70h - current errors, Fixed Format 71h - deferred errors, Fixed Format + uint8_t valid : 1; + + uint8_t reserved; + + uint8_t sense_key : 4; + uint8_t : 1; + uint8_t ili : 1; ///< Incorrect length indicator + uint8_t end_of_medium : 1; + uint8_t filemark : 1; + + uint32_t information; + uint8_t add_sense_len; + uint32_t command_specific_info; + uint8_t add_sense_code; + uint8_t add_sense_qualifier; + uint8_t field_replaceable_unit_code; + + uint8_t sense_key_specific[3]; ///< sense key specific valid bit is bit 7 of key[0], aka MSB in Big Endian layout + +} scsi_sense_fixed_resp_t; + +TU_VERIFY_STATIC(sizeof(scsi_sense_fixed_resp_t) == 18, "size is not correct"); + +typedef struct TU_ATTR_PACKED +{ + uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_MODE_SENSE_6 + + uint8_t : 3; + uint8_t disable_block_descriptor : 1; + uint8_t : 4; + + uint8_t page_code : 6; + uint8_t page_control : 2; + + uint8_t subpage_code; + uint8_t alloc_length; + uint8_t control; +} scsi_mode_sense6_t; + +TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct"); + +// This is only a Mode parameter header(6). +typedef struct TU_ATTR_PACKED +{ + uint8_t data_len; + uint8_t medium_type; + + uint8_t reserved : 7; + bool write_protected : 1; + + uint8_t block_descriptor_len; +} scsi_mode_sense6_resp_t; + +TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_resp_t) == 4, "size is not correct"); + +typedef struct TU_ATTR_PACKED +{ + uint8_t cmd_code; ///< SCSI OpCode for \ref SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL + uint8_t reserved[3]; + uint8_t prohibit_removal; + uint8_t control; +} scsi_prevent_allow_medium_removal_t; + +TU_VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct"); + +typedef struct TU_ATTR_PACKED +{ + uint8_t cmd_code; + + uint8_t immded : 1; + uint8_t : 7; + + uint8_t TU_RESERVED; + + uint8_t power_condition_mod : 4; + uint8_t : 4; + + uint8_t start : 1; + uint8_t load_eject : 1; + uint8_t no_flush : 1; + uint8_t : 1; + uint8_t power_condition : 4; + + uint8_t control; +} scsi_start_stop_unit_t; + +TU_VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct"); + +//--------------------------------------------------------------------+ +// SCSI MMC +//--------------------------------------------------------------------+ +/// SCSI Read Format Capacity: Write Capacity +typedef struct TU_ATTR_PACKED +{ + uint8_t cmd_code; + uint8_t reserved[6]; + uint16_t alloc_length; + uint8_t control; +} scsi_read_format_capacity_t; + +TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_t) == 10, "size is not correct"); + +typedef struct TU_ATTR_PACKED{ + uint8_t reserved[3]; + uint8_t list_length; /// must be 8*n, length in bytes of formattable capacity descriptor followed it. + + uint32_t block_num; /// Number of Logical Blocks + uint8_t descriptor_type; // 00: reserved, 01 unformatted media , 10 Formatted media, 11 No media present + + uint8_t reserved2; + uint16_t block_size_u16; + +} scsi_read_format_capacity_data_t; + +TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_data_t) == 12, "size is not correct"); + +//--------------------------------------------------------------------+ +// SCSI Block Command (SBC-3) +// NOTE: All data in SCSI command are in Big Endian +//--------------------------------------------------------------------+ + +/// SCSI Read Capacity 10 Command: Read Capacity +typedef struct TU_ATTR_PACKED +{ + uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_READ_CAPACITY_10 + uint8_t reserved1 ; + uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command + uint16_t reserved2 ; + uint8_t partial_medium_indicator ; + uint8_t control ; +} scsi_read_capacity10_t; + +TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_t) == 10, "size is not correct"); + +/// SCSI Read Capacity 10 Response Data +typedef struct { + uint32_t last_lba ; ///< The last Logical Block Address of the device + uint32_t block_size ; ///< Block size in bytes +} scsi_read_capacity10_resp_t; + +TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_resp_t) == 8, "size is not correct"); + +/// SCSI Read 10 Command +typedef struct TU_ATTR_PACKED +{ + uint8_t cmd_code ; ///< SCSI OpCode + uint8_t reserved ; // has LUN according to wiki + uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command + uint8_t reserved2 ; + uint16_t block_count ; ///< Number of Blocks used by this command + uint8_t control ; +} scsi_read10_t, scsi_write10_t; + +TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_MSC_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c new file mode 100644 index 000000000..97837b114 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c @@ -0,0 +1,939 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MSC) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" +#include "device/dcd.h" // for faking dcd_event_xfer_complete + +#include "msc_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +// Can be selectively disabled to reduce logging when troubleshooting other driver +#define MSC_DEBUG 2 + +enum +{ + MSC_STAGE_CMD = 0, + MSC_STAGE_DATA, + MSC_STAGE_STATUS, + MSC_STAGE_STATUS_SENT, + MSC_STAGE_NEED_RESET, +}; + +typedef struct +{ + // TODO optimize alignment + CFG_TUSB_MEM_ALIGN msc_cbw_t cbw; + CFG_TUSB_MEM_ALIGN msc_csw_t csw; + + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; + + // Bulk Only Transfer (BOT) Protocol + uint8_t stage; + uint32_t total_len; // byte to be transferred, can be smaller than total_bytes in cbw + uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage + + // Sense Response Data + uint8_t sense_key; + uint8_t add_sense_code; + uint8_t add_sense_qualifier; +}mscd_interface_t; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static mscd_interface_t _mscd_itf; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE]; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); +static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc); + +static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); +static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes); + +TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) +{ + return tu_bit_test(dir, 7); +} + +static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc) +{ + // Data residue is always = host expect - actual transferred + p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; + + p_msc->stage = MSC_STAGE_STATUS_SENT; + return usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)); +} + +static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc) +{ + p_msc->stage = MSC_STAGE_CMD; + return usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)); +} + +static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status) +{ + msc_cbw_t const * p_cbw = &p_msc->cbw; + msc_csw_t * p_csw = &p_msc->csw; + + p_csw->status = status; + p_csw->data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; + p_msc->stage = MSC_STAGE_STATUS; + + // failed but sense key is not set: default to Illegal Request + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); + + // If there is data stage and not yet complete, stall it + if ( p_cbw->total_bytes && p_csw->data_residue ) + { + if ( is_data_in(p_cbw->dir) ) + { + usbd_edpt_stall(rhport, p_msc->ep_in); + } + else + { + usbd_edpt_stall(rhport, p_msc->ep_out); + } + } +} + +static inline uint32_t rdwr10_get_lba(uint8_t const command[]) +{ + // use offsetof to avoid pointer to the odd/unaligned address + uint32_t const lba = tu_unaligned_read32(command + offsetof(scsi_write10_t, lba)); + + // lba is in Big Endian + return tu_ntohl(lba); +} + +static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw) +{ + uint16_t const block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count)); + return tu_ntohs(block_count); +} + +static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) +{ + // first extract block count in the command + uint16_t const block_count = rdwr10_get_blockcount(cbw); + + // invalid block count + if (block_count == 0) return 0; + + return (uint16_t) (cbw->total_bytes / block_count); +} + +uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) +{ + uint8_t status = MSC_CSW_STATUS_PASSED; + uint16_t const block_count = rdwr10_get_blockcount(cbw); + + if ( cbw->total_bytes == 0 ) + { + if ( block_count ) + { + TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + }else + { + // no data transfer, only exist in complaint test suite + } + }else + { + if ( SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir) ) + { + TU_LOG(MSC_DEBUG, " SCSI case 10 (Ho <> Di)\r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + } + else if ( SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir) ) + { + TU_LOG(MSC_DEBUG, " SCSI case 8 (Hi <> Do)\r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + } + else if ( 0 == block_count ) + { + TU_LOG(MSC_DEBUG, " SCSI case 4 Hi > Dn (READ10) or case 9 Ho > Dn (WRITE10) \r\n"); + status = MSC_CSW_STATUS_FAILED; + } + else if ( cbw->total_bytes / block_count == 0 ) + { + TU_LOG(MSC_DEBUG, " Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + } + } + + return status; +} + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +TU_ATTR_UNUSED static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = +{ + { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, + { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, + { .key = SCSI_CMD_MODE_SELECT_6 , .data = "Mode_Select 6" }, + { .key = SCSI_CMD_MODE_SENSE_6 , .data = "Mode_Sense 6" }, + { .key = SCSI_CMD_START_STOP_UNIT , .data = "Start Stop Unit" }, + { .key = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL , .data = "Prevent Allow Medium Removal" }, + { .key = SCSI_CMD_READ_CAPACITY_10 , .data = "Read Capacity10" }, + { .key = SCSI_CMD_REQUEST_SENSE , .data = "Request Sense" }, + { .key = SCSI_CMD_READ_FORMAT_CAPACITY , .data = "Read Format Capacity" }, + { .key = SCSI_CMD_READ_10 , .data = "Read10" }, + { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } +}; + +TU_ATTR_UNUSED static tu_lookup_table_t const _msc_scsi_cmd_table = +{ + .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), + .items = _msc_scsi_cmd_lookup +}; + +#endif + +//--------------------------------------------------------------------+ +// APPLICATION API +//--------------------------------------------------------------------+ +bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier) +{ + (void) lun; + + _mscd_itf.sense_key = sense_key; + _mscd_itf.add_sense_code = add_sense_code; + _mscd_itf.add_sense_qualifier = add_sense_qualifier; + + return true; +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void mscd_init(void) +{ + tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); +} + +void mscd_reset(uint8_t rhport) +{ + (void) rhport; + tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); +} + +uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + // only support SCSI's BOT protocol + TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && + MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && + MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); + + // msc driver length is fixed + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + + // Max length must be at least 1 interface + 2 endpoints + TU_ASSERT(max_len >= drv_len, 0); + + mscd_interface_t * p_msc = &_mscd_itf; + p_msc->itf_num = itf_desc->bInterfaceNumber; + + // Open endpoint pair + TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); + + // Prepare for Command Block Wrapper + TU_ASSERT( prepare_cbw(rhport, p_msc), drv_len); + + return drv_len; +} + +static void proc_bot_reset(mscd_interface_t* p_msc) +{ + p_msc->stage = MSC_STAGE_CMD; + p_msc->total_len = 0; + p_msc->xferred_len = 0; + + p_msc->sense_key = 0; + p_msc->add_sense_code = 0; + p_msc->add_sense_qualifier = 0; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + // nothing to do with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP) return true; + + mscd_interface_t* p_msc = &_mscd_itf; + + // Clear Endpoint Feature (stall) for recovery + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_RCPT_ENDPOINT == request->bmRequestType_bit.recipient && + TUSB_REQ_CLEAR_FEATURE == request->bRequest && + TUSB_REQ_FEATURE_EDPT_HALT == request->wValue ) + { + uint8_t const ep_addr = tu_u16_low(request->wIndex); + + if ( p_msc->stage == MSC_STAGE_NEED_RESET ) + { + // reset recovery is required to recover from this stage + // Clear Stall request cannot resolve this -> continue to stall endpoint + usbd_edpt_stall(rhport, ep_addr); + } + else + { + if ( ep_addr == p_msc->ep_in ) + { + if ( p_msc->stage == MSC_STAGE_STATUS ) + { + // resume sending SCSI status if we are in this stage previously before stalled + TU_ASSERT( send_csw(rhport, p_msc) ); + } + } + else if ( ep_addr == p_msc->ep_out ) + { + if ( p_msc->stage == MSC_STAGE_CMD ) + { + // part of reset recovery (probably due to invalid CBW) -> prepare for new command + // Note: skip if already queued previously + if ( usbd_edpt_ready(rhport, p_msc->ep_out) ) + { + TU_ASSERT( prepare_cbw(rhport, p_msc) ); + } + } + } + } + + return true; + } + + // From this point only handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + switch ( request->bRequest ) + { + case MSC_REQ_RESET: + TU_LOG(MSC_DEBUG, " MSC BOT Reset\r\n"); + TU_VERIFY(request->wValue == 0 && request->wLength == 0); + + // driver state reset + proc_bot_reset(p_msc); + + tud_control_status(rhport, request); + break; + + case MSC_REQ_GET_MAX_LUN: + { + TU_LOG(MSC_DEBUG, " MSC Get Max Lun\r\n"); + TU_VERIFY(request->wValue == 0 && request->wLength == 1); + + uint8_t maxlun = 1; + if (tud_msc_get_maxlun_cb) maxlun = tud_msc_get_maxlun_cb(); + TU_VERIFY(maxlun); + + // MAX LUN is minus 1 by specs + maxlun--; + + tud_control_xfer(rhport, request, &maxlun, 1); + } + break; + + default: return false; // stall unsupported request + } + + return true; +} + +bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +{ + (void) event; + + mscd_interface_t* p_msc = &_mscd_itf; + msc_cbw_t const * p_cbw = &p_msc->cbw; + msc_csw_t * p_csw = &p_msc->csw; + + switch (p_msc->stage) + { + case MSC_STAGE_CMD: + //------------- new CBW received -------------// + // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it + if(ep_addr != p_msc->ep_out) return true; + + if ( !(xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE) ) + { + TU_LOG(MSC_DEBUG, " SCSI CBW is not valid\r\n"); + + // BOT 6.6.1 If CBW is not valid stall both endpoints until reset recovery + p_msc->stage = MSC_STAGE_NEED_RESET; + + // invalid CBW stall both endpoints + usbd_edpt_stall(rhport, p_msc->ep_in); + usbd_edpt_stall(rhport, p_msc->ep_out); + + return false; + } + + TU_LOG(MSC_DEBUG, " SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); + //TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); + + p_csw->signature = MSC_CSW_SIGNATURE; + p_csw->tag = p_cbw->tag; + p_csw->data_residue = 0; + p_csw->status = MSC_CSW_STATUS_PASSED; + + /*------------- Parse command and prepare DATA -------------*/ + p_msc->stage = MSC_STAGE_DATA; + p_msc->total_len = p_cbw->total_bytes; + p_msc->xferred_len = 0; + + // Read10 or Write10 + if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) ) + { + uint8_t const status = rdwr10_validate_cmd(p_cbw); + + if ( status != MSC_CSW_STATUS_PASSED) + { + fail_scsi_op(rhport, p_msc, status); + }else if ( p_cbw->total_bytes ) + { + if (SCSI_CMD_READ_10 == p_cbw->command[0]) + { + proc_read10_cmd(rhport, p_msc); + }else + { + proc_write10_cmd(rhport, p_msc); + } + }else + { + // no data transfer, only exist in complaint test suite + p_msc->stage = MSC_STAGE_STATUS; + } + } + else + { + // For other SCSI commands + // 1. OUT : queue transfer (invoke app callback after done) + // 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length + if ( (p_cbw->total_bytes > 0 ) && !is_data_in(p_cbw->dir) ) + { + if (p_cbw->total_bytes > sizeof(_mscd_buf)) + { + TU_LOG(MSC_DEBUG, " SCSI reject non READ10/WRITE10 with large data\r\n"); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + }else + { + // Didn't check for case 9 (Ho > Dn), which requires examining scsi command first + // but it is OK to just receive data then responded with failed status + TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) ); + } + }else + { + // First process if it is a built-in commands + int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf)); + + // Invoke user callback if not built-in + if ( (resplen < 0) && (p_msc->sense_key == 0) ) + { + resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len); + } + + if ( resplen < 0 ) + { + // unsupported command + TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n"); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + } + else if (resplen == 0) + { + if (p_cbw->total_bytes) + { + // 6.7 The 13 Cases: case 4 (Hi > Dn) + // TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + }else + { + // case 1 Hn = Dn: all good + p_msc->stage = MSC_STAGE_STATUS; + } + } + else + { + if ( p_cbw->total_bytes == 0 ) + { + // 6.7 The 13 Cases: case 2 (Hn < Di) + // TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + }else + { + // cannot return more than host expect + p_msc->total_len = tu_min32((uint32_t) resplen, p_cbw->total_bytes); + TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) ); + } + } + } + } + break; + + case MSC_STAGE_DATA: + TU_LOG(MSC_DEBUG, " SCSI Data\r\n"); + //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2); + + if (SCSI_CMD_READ_10 == p_cbw->command[0]) + { + p_msc->xferred_len += xferred_bytes; + + if ( p_msc->xferred_len >= p_msc->total_len ) + { + // Data Stage is complete + p_msc->stage = MSC_STAGE_STATUS; + }else + { + proc_read10_cmd(rhport, p_msc); + } + } + else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) + { + proc_write10_new_data(rhport, p_msc, xferred_bytes); + } + else + { + p_msc->xferred_len += xferred_bytes; + + // OUT transfer, invoke callback if needed + if ( !is_data_in(p_cbw->dir) ) + { + int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len); + + if ( cb_result < 0 ) + { + // unsupported command + TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n"); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + }else + { + // TODO haven't implement this scenario any further yet + } + } + + if ( p_msc->xferred_len >= p_msc->total_len ) + { + // Data Stage is complete + p_msc->stage = MSC_STAGE_STATUS; + } + else + { + // This scenario with command that take more than one transfer is already rejected at Command stage + TU_BREAKPOINT(); + } + } + break; + + case MSC_STAGE_STATUS: + // processed immediately after this switch, supposedly to be empty + break; + + case MSC_STAGE_STATUS_SENT: + // Wait for the Status phase to complete + if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) + { + TU_LOG(MSC_DEBUG, " SCSI Status = %u\r\n", p_csw->status); + // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2); + + // Invoke complete callback if defined + // Note: There is racing issue with samd51 + qspi flash testing with arduino + // if complete_cb() is invoked after queuing the status. + switch(p_cbw->command[0]) + { + case SCSI_CMD_READ_10: + if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun); + break; + + case SCSI_CMD_WRITE_10: + if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun); + break; + + default: + if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); + break; + } + + TU_ASSERT( prepare_cbw(rhport, p_msc) ); + }else + { + // Any xfer ended here is consider unknown error, ignore it + TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n"); + } + break; + + default : break; + } + + if ( p_msc->stage == MSC_STAGE_STATUS ) + { + // skip status if epin is currently stalled, will do it when received Clear Stall request + if ( !usbd_edpt_stalled(rhport, p_msc->ep_in) ) + { + if ( (p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir) ) + { + // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status + // TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); + usbd_edpt_stall(rhport, p_msc->ep_in); + }else + { + TU_ASSERT( send_csw(rhport, p_msc) ); + } + } + + #if TU_CHECK_MCU(OPT_MCU_CXD56) + // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD. + // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and + // hope everything will work + if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) + { + usbd_edpt_clear_stall(rhport, p_msc->ep_in); + send_csw(rhport, p_msc); + } + #endif + } + + return true; +} + +/*------------------------------------------------------------------*/ +/* SCSI Command Process + *------------------------------------------------------------------*/ + +// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) +// In case of a failed status, sense key must be set for reason of failure +static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) +{ + (void) bufsize; // TODO refractor later + int32_t resplen; + + mscd_interface_t* p_msc = &_mscd_itf; + + switch ( scsi_cmd[0] ) + { + case SCSI_CMD_TEST_UNIT_READY: + resplen = 0; + if ( !tud_msc_test_unit_ready_cb(lun) ) + { + // Failed status response + resplen = - 1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + } + break; + + case SCSI_CMD_START_STOP_UNIT: + resplen = 0; + + if (tud_msc_start_stop_cb) + { + scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; + if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) + { + // Failed status response + resplen = - 1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + } + } + break; + + case SCSI_CMD_READ_CAPACITY_10: + { + uint32_t block_count; + uint32_t block_size; + uint16_t block_size_u16; + + tud_msc_capacity_cb(lun, &block_count, &block_size_u16); + block_size = (uint32_t) block_size_u16; + + // Invalid block size/count from callback, possibly unit is not ready + // stall this request, set sense key to NOT READY + if (block_count == 0 || block_size == 0) + { + resplen = -1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + }else + { + scsi_read_capacity10_resp_t read_capa10; + + read_capa10.last_lba = tu_htonl(block_count-1); + read_capa10.block_size = tu_htonl(block_size); + + resplen = sizeof(read_capa10); + memcpy(buffer, &read_capa10, resplen); + } + } + break; + + case SCSI_CMD_READ_FORMAT_CAPACITY: + { + scsi_read_format_capacity_data_t read_fmt_capa = + { + .list_length = 8, + .block_num = 0, + .descriptor_type = 2, // formatted media + .block_size_u16 = 0 + }; + + uint32_t block_count; + uint16_t block_size; + + tud_msc_capacity_cb(lun, &block_count, &block_size); + + // Invalid block size/count from callback, possibly unit is not ready + // stall this request, set sense key to NOT READY + if (block_count == 0 || block_size == 0) + { + resplen = -1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + }else + { + read_fmt_capa.block_num = tu_htonl(block_count); + read_fmt_capa.block_size_u16 = tu_htons(block_size); + + resplen = sizeof(read_fmt_capa); + memcpy(buffer, &read_fmt_capa, resplen); + } + } + break; + + case SCSI_CMD_INQUIRY: + { + scsi_inquiry_resp_t inquiry_rsp = + { + .is_removable = 1, + .version = 2, + .response_data_format = 2, + }; + + // vendor_id, product_id, product_rev is space padded string + memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); + memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); + memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); + + tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); + + resplen = sizeof(inquiry_rsp); + memcpy(buffer, &inquiry_rsp, resplen); + } + break; + + case SCSI_CMD_MODE_SENSE_6: + { + scsi_mode_sense6_resp_t mode_resp = + { + .data_len = 3, + .medium_type = 0, + .write_protected = false, + .reserved = 0, + .block_descriptor_len = 0 // no block descriptor are included + }; + + bool writable = true; + if ( tud_msc_is_writable_cb ) + { + writable = tud_msc_is_writable_cb(lun); + } + + mode_resp.write_protected = !writable; + + resplen = sizeof(mode_resp); + memcpy(buffer, &mode_resp, resplen); + } + break; + + case SCSI_CMD_REQUEST_SENSE: + { + scsi_sense_fixed_resp_t sense_rsp = + { + .response_code = 0x70, + .valid = 1 + }; + + sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; + + sense_rsp.sense_key = p_msc->sense_key; + sense_rsp.add_sense_code = p_msc->add_sense_code; + sense_rsp.add_sense_qualifier = p_msc->add_sense_qualifier; + + resplen = sizeof(sense_rsp); + memcpy(buffer, &sense_rsp, resplen); + + // Clear sense data after copy + tud_msc_set_sense(lun, 0, 0, 0); + } + break; + + default: resplen = -1; break; + } + + return resplen; +} + +static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) +{ + msc_cbw_t const * p_cbw = &p_msc->cbw; + + // block size already verified not zero + uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); + + // Adjust lba with transferred bytes + uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); + + // remaining bytes capped at class buffer + int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); + + // Application can consume smaller bytes + uint32_t const offset = p_msc->xferred_len % block_sz; + nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_buf, (uint32_t) nbytes); + + if ( nbytes < 0 ) + { + // negative means error -> endpoint is stalled & status in CSW set to failed + TU_LOG(MSC_DEBUG, " tud_msc_read10_cb() return -1\r\n"); + + // Sense = Flash not ready for access + tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00); + + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + } + else if ( nbytes == 0 ) + { + // zero means not ready -> simulate an transfer complete so that this driver callback will fired again + dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); + } + else + { + TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, nbytes), ); + } +} + +static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) +{ + msc_cbw_t const * p_cbw = &p_msc->cbw; + bool writable = true; + + if ( tud_msc_is_writable_cb ) + { + writable = tud_msc_is_writable_cb(p_cbw->lun); + } + + if ( !writable ) + { + // Not writable, complete this SCSI op with error + // Sense = Write protected + tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + return; + } + + // remaining bytes capped at class buffer + int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); + + // Write10 callback will be called later when usb transfer complete + TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), ); +} + +// process new data arrived from WRITE10 +static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes) +{ + msc_cbw_t const * p_cbw = &p_msc->cbw; + + // block size already verified not zero + uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); + + // Adjust lba with transferred bytes + uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); + + // Invoke callback to consume new data + uint32_t const offset = p_msc->xferred_len % block_sz; + int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_buf, xferred_bytes); + + if ( nbytes < 0 ) + { + // negative means error -> failed this scsi op + TU_LOG(MSC_DEBUG, " tud_msc_write10_cb() return -1\r\n"); + + // update actual byte before failed + p_msc->xferred_len += xferred_bytes; + + // Sense = Flash not ready for access + tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00); + + fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + }else + { + // Application consume less than what we got (including zero) + if ( (uint32_t) nbytes < xferred_bytes ) + { + if ( nbytes > 0 ) + { + p_msc->xferred_len += nbytes; + memmove(_mscd_buf, _mscd_buf+nbytes, xferred_bytes-nbytes); + } + + // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter + dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, XFER_RESULT_SUCCESS, false); + } + else + { + // Application consume all bytes in our buffer + p_msc->xferred_len += xferred_bytes; + + if ( p_msc->xferred_len >= p_msc->total_len ) + { + // Data Stage is complete + p_msc->stage = MSC_STAGE_STATUS; + }else + { + // prepare to receive more data from host + proc_write10_cmd(rhport, p_msc); + } + } + } +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h new file mode 100644 index 000000000..d32694340 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h @@ -0,0 +1,159 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_MSC_DEVICE_H_ +#define _TUSB_MSC_DEVICE_H_ + +#include "common/tusb_common.h" +#include "msc.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +#if !defined(CFG_TUD_MSC_EP_BUFSIZE) & defined(CFG_TUD_MSC_BUFSIZE) + // TODO warn user to use new name later on + // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE, please update to use the new name + #define CFG_TUD_MSC_EP_BUFSIZE CFG_TUD_MSC_BUFSIZE +#endif + +#ifndef CFG_TUD_MSC_EP_BUFSIZE + #error CFG_TUD_MSC_EP_BUFSIZE must be defined, value of a block size should work well, the more the better +#endif + +TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// Set SCSI sense response +bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); + +//--------------------------------------------------------------------+ +// Application Callbacks (WEAK is optional) +//--------------------------------------------------------------------+ + +// Invoked when received SCSI READ10 command +// - Address = lba * BLOCK_SIZE + offset +// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. +// +// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If +// - read < bufsize : These bytes are transferred first and callback invoked again for remaining data. +// +// - read == 0 : Indicate application is not ready yet e.g disk I/O busy. +// Callback invoked again with the same parameters later on. +// +// - read < 0 : Indicate application error e.g invalid address. This request will be STALLed +// and return failed status in command status wrapper phase. +int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); + +// Invoked when received SCSI WRITE10 command +// - Address = lba * BLOCK_SIZE + offset +// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. +// +// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If +// - write < bufsize : callback invoked again with remaining data later on. +// +// - write == 0 : Indicate application is not ready yet e.g disk I/O busy. +// Callback invoked again with the same parameters later on. +// +// - write < 0 : Indicate application error e.g invalid address. This request will be STALLed +// and return failed status in command status wrapper phase. +// +// TODO change buffer to const uint8_t* +int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); + +// Invoked when received SCSI_CMD_INQUIRY +// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]); + +// Invoked when received Test Unit Ready command. +// return true allowing host to read/write this LUN e.g SD card inserted +bool tud_msc_test_unit_ready_cb(uint8_t lun); + +// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size +// Application update block count and block size +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size); + +/** + * Invoked when received an SCSI command not in built-in list below. + * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE + * - READ10 and WRITE10 has their own callbacks + * + * \param[in] lun Logical unit number + * \param[in] scsi_cmd SCSI command contents which application must examine to response accordingly + * \param[out] buffer Buffer for SCSI Data Stage. + * - For INPUT: application must fill this with response. + * - For OUTPUT it holds the Data from host + * \param[in] bufsize Buffer's length. + * + * \return Actual bytes processed, can be zero for no-data command. + * \retval negative Indicate error e.g unsupported command, tinyusb will \b STALL the corresponding + * endpoint and return failed status in command status wrapper phase. + */ +int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize); + +/*------------- Optional callbacks -------------*/ + +// Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation +TU_ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void); + +// Invoked when received Start Stop Unit command +// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage +// - Start = 1 : active mode, if load_eject = 1 : load disk storage +TU_ATTR_WEAK bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject); + +// Invoked when Read10 command is complete +TU_ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun); + +// Invoke when Write10 command is complete, can be used to flush flash caching +TU_ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun); + +// Invoked when command in tud_msc_scsi_cb is complete +TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]); + +// Invoked to check if device is writable as part of SCSI WRITE10 +TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void mscd_init (void); +void mscd_reset (uint8_t rhport); +uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); +bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_MSC_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c new file mode 100644 index 000000000..fa6519956 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c @@ -0,0 +1,491 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC + +#include "host/usbh.h" +#include "host/usbh_classdriver.h" + +#include "msc_host.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +enum +{ + MSC_STAGE_IDLE = 0, + MSC_STAGE_CMD, + MSC_STAGE_DATA, + MSC_STAGE_STATUS, +}; + +typedef struct +{ + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; + + uint8_t max_lun; + + volatile bool configured; // Receive SET_CONFIGURE + volatile bool mounted; // Enumeration is complete + + struct { + uint32_t block_size; + uint32_t block_count; + } capacity[CFG_TUH_MSC_MAXLUN]; + + //------------- SCSI -------------// + uint8_t stage; + void* buffer; + tuh_msc_complete_cb_t complete_cb; + + msc_cbw_t cbw; + msc_csw_t csw; +}msch_interface_t; + +CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; + +// buffer used to read scsi information when mounted +// largest response data currently is inquiry TODO Inquiry is not part of enum anymore +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) +static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; + +TU_ATTR_ALWAYS_INLINE +static inline msch_interface_t* get_itf(uint8_t dev_addr) +{ + return &_msch_itf[dev_addr-1]; +} + +//--------------------------------------------------------------------+ +// PUBLIC API +//--------------------------------------------------------------------+ +uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->max_lun; +} + +uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->capacity[lun].block_count; +} + +uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->capacity[lun].block_size; +} + +bool tuh_msc_mounted(uint8_t dev_addr) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->mounted; +} + +bool tuh_msc_ready(uint8_t dev_addr) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in); +} + +//--------------------------------------------------------------------+ +// PUBLIC API: SCSI COMMAND +//--------------------------------------------------------------------+ +static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) +{ + tu_memclr(cbw, sizeof(msc_cbw_t)); + cbw->signature = MSC_CBW_SIGNATURE; + cbw->tag = 0x54555342; // TUSB + cbw->lun = lun; +} + +bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured); + + // TODO claim endpoint + + p_msc->cbw = *cbw; + p_msc->stage = MSC_STAGE_CMD; + p_msc->buffer = data; + p_msc->complete_cb = complete_cb; + + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))); + + return true; +} + +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured); + + msc_cbw_t cbw; + cbw_init(&cbw, lun); + + cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read_capacity10_t); + cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; + + return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); +} + +bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->mounted); + + msc_cbw_t cbw; + cbw_init(&cbw, lun); + + cbw.total_bytes = sizeof(scsi_inquiry_resp_t); + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_inquiry_t); + + scsi_inquiry_t const cmd_inquiry = + { + .cmd_code = SCSI_CMD_INQUIRY, + .alloc_length = sizeof(scsi_inquiry_resp_t) + }; + memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); + + return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); +} + +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured); + + msc_cbw_t cbw; + cbw_init(&cbw, lun); + + cbw.total_bytes = 0; + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_test_unit_ready_t); + cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; + cbw.command[1] = lun; // according to wiki TODO need verification + + return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb); +} + +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb) +{ + msc_cbw_t cbw; + cbw_init(&cbw, lun); + + cbw.total_bytes = 18; // TODO sense response + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_request_sense_t); + + scsi_request_sense_t const cmd_request_sense = + { + .cmd_code = SCSI_CMD_REQUEST_SENSE, + .alloc_length = 18 + }; + + memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); + + return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb); +} + +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->mounted); + + msc_cbw_t cbw; + cbw_init(&cbw, lun); + + cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read10_t); + + scsi_read10_t const cmd_read10 = + { + .cmd_code = SCSI_CMD_READ_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) + }; + + memcpy(cbw.command, &cmd_read10, cbw.cmd_len); + + return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb); +} + +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->mounted); + + msc_cbw_t cbw; + cbw_init(&cbw, lun); + + cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_write10_t); + + scsi_write10_t const cmd_write10 = + { + .cmd_code = SCSI_CMD_WRITE_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) + }; + + memcpy(cbw.command, &cmd_write10, cbw.cmd_len); + + return tuh_msc_scsi_command(dev_addr, &cbw, (void*)(uintptr_t) buffer, complete_cb); +} + +#if 0 +// MSC interface Reset (not used now) +bool tuh_msc_reset(uint8_t dev_addr) +{ + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = MSC_REQ_RESET, + .wValue = 0, + .wIndex = p_msc->itf_num, + .wLength = 0 + }; + TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); +} +#endif + +//--------------------------------------------------------------------+ +// CLASS-USBH API +//--------------------------------------------------------------------+ +void msch_init(void) +{ + tu_memclr(_msch_itf, sizeof(_msch_itf)); +} + +void msch_close(uint8_t dev_addr) +{ + TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); + + msch_interface_t* p_msc = get_itf(dev_addr); + + // invoke Application Callback + if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + + tu_memclr(p_msc, sizeof(msch_interface_t)); +} + +bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + msc_cbw_t const * cbw = &p_msc->cbw; + msc_csw_t * csw = &p_msc->csw; + + switch (p_msc->stage) + { + case MSC_STAGE_CMD: + // Must be Command Block + TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); + + if ( cbw->total_bytes && p_msc->buffer ) + { + // Data stage if any + p_msc->stage = MSC_STAGE_DATA; + + uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out; + TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, cbw->total_bytes)); + }else + { + // Status stage + p_msc->stage = MSC_STAGE_STATUS; + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); + } + break; + + case MSC_STAGE_DATA: + // Status stage + p_msc->stage = MSC_STAGE_STATUS; + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); + break; + + case MSC_STAGE_STATUS: + // SCSI op is complete + p_msc->stage = MSC_STAGE_IDLE; + + if (p_msc->complete_cb) p_msc->complete_cb(dev_addr, cbw, csw); + break; + + // unknown state + default: break; + } + + return true; +} + +//--------------------------------------------------------------------+ +// MSC Enumeration +//--------------------------------------------------------------------+ + +static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); + +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +{ + TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && + MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); + + // msc driver length is fixed + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(drv_len <= max_len); + + msch_interface_t* p_msc = get_itf(dev_addr); + tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); + + for(uint32_t i=0; i<2; i++) + { + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); + + if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) + { + p_msc->ep_in = ep_desc->bEndpointAddress; + }else + { + p_msc->ep_out = ep_desc->bEndpointAddress; + } + + ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); + } + + p_msc->itf_num = desc_itf->bInterfaceNumber; + + return true; +} + +bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + TU_ASSERT(p_msc->itf_num == itf_num); + + p_msc->configured = true; + + //------------- Get Max Lun -------------// + TU_LOG2("MSC Get Max Lun\r\n"); + tusb_control_request_t request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = MSC_REQ_GET_MAX_LUN, + .wValue = 0, + .wIndex = itf_num, + .wLength = 1 + }; + TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, config_get_maxlun_complete)); + + return true; +} + +static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + + msch_interface_t* p_msc = get_itf(dev_addr); + + // STALL means zero + p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0; + p_msc->max_lun++; // MAX LUN is minus 1 by specs + + // TODO multiple LUN support + TU_LOG2("SCSI Test Unit Ready\r\n"); + uint8_t const lun = 0; + tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete); + + return true; +} + +static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + if (csw->status == 0) + { + // Unit is ready, read its capacity + TU_LOG2("SCSI Read Capacity\r\n"); + tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete); + }else + { + // Note: During enumeration, some device fails Test Unit Ready and require a few retries + // with Request Sense to start working !! + // TODO limit number of retries + TU_LOG2("SCSI Request Sense\r\n"); + TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete)); + } + + return true; +} + +static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + TU_ASSERT(csw->status == 0); + TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, config_test_unit_ready_complete)); + return true; +} + +static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + TU_ASSERT(csw->status == 0); + + msch_interface_t* p_msc = get_itf(dev_addr); + + // Capacity response field: Block size and Last LBA are both Big-Endian + scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer); + p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; + p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); + + // Mark enumeration is complete + p_msc->mounted = true; + if (tuh_msc_mount_cb) tuh_msc_mount_cb(dev_addr); + + // notify usbh that driver enumeration is complete + usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); + + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h new file mode 100644 index 000000000..7718ad4fe --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h @@ -0,0 +1,119 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_MSC_HOST_H_ +#define _TUSB_MSC_HOST_H_ + +#include "msc.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_MSC_MAXLUN +#define CFG_TUH_MSC_MAXLUN 4 +#endif + +typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// Check if device supports MassStorage interface. +// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() +bool tuh_msc_mounted(uint8_t dev_addr); + +// Check if the interface is currently ready or busy transferring data +bool tuh_msc_ready(uint8_t dev_addr); + +// Get Max Lun +uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); + +// Get number of block +uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun); + +// Get block size in bytes +uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun); + +// Perform a full SCSI command (cbw, data, csw) in non-blocking manner. +// Complete callback is invoked when SCSI op is complete. +// return true if success, false if there is already pending operation. +bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); + +// Perform SCSI Inquiry command +// Complete callback is invoked when SCSI op is complete. +bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); + +// Perform SCSI Test Unit Ready command +// Complete callback is invoked when SCSI op is complete. +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); + +// Perform SCSI Request Sense 10 command +// Complete callback is invoked when SCSI op is complete. +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); + +// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer +// Complete callback is invoked when SCSI op is complete. +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); + +// Perform SCSI Write 10 command. Write n blocks starting from LBA to device +// Complete callback is invoked when SCSI op is complete. +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); + +// Perform SCSI Read Capacity 10 command +// Complete callback is invoked when SCSI op is complete. +// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by +// simply call tuh_msc_get_block_count() and tuh_msc_get_block_size() +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); + +//------------- Application Callback -------------// + +// Invoked when a device with MassStorage interface is mounted +TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); + +// Invoked when a device with MassStorage interface is unmounted +TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ + +void msch_init (void); +bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); +void msch_close (uint8_t dev_addr); +bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_MSC_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c new file mode 100644 index 000000000..c6cd388e3 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c @@ -0,0 +1,445 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_ECM_RNDIS ) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "net_device.h" +#include "rndis_protocol.h" + +void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface + uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active + + uint8_t ep_notif; + uint8_t ep_in; + uint8_t ep_out; + + bool ecm_mode; + + // Endpoint descriptor use to open/close when receving SetInterface + // TODO since configuration descriptor may not be long-lived memory, we should + // keep a copy of endpoint attribute instead + uint8_t const * ecm_desc_epdata; + +} netd_interface_t; + +#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) +#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; + +struct ecm_notify_struct +{ + tusb_control_request_t header; + uint32_t downlink, uplink; +}; + +static const struct ecm_notify_struct ecm_notify_nc = +{ + .header = { + .bmRequestType = 0xA1, + .bRequest = 0 /* NETWORK_CONNECTION aka NetworkConnection */, + .wValue = 1 /* Connected */, + .wLength = 0, + }, +}; + +static const struct ecm_notify_struct ecm_notify_csc = +{ + .header = { + .bmRequestType = 0xA1, + .bRequest = 0x2A /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */, + .wLength = 8, + }, + .downlink = 9728000, + .uplink = 9728000, +}; + +// TODO remove CFG_TUSB_MEM_SECTION, control internal buffer is already in this special section +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union +{ + uint8_t rndis_buf[120]; + struct ecm_notify_struct ecm_buf; +} notify; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +// TODO remove CFG_TUSB_MEM_SECTION +CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf; + +static bool can_xmit; + +void tud_network_recv_renew(void) +{ + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_out, received, sizeof(received)); +} + +static void do_in_xfer(uint8_t *buf, uint16_t len) +{ + can_xmit = false; + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_in, buf, len); +} + +void netd_report(uint8_t *buf, uint16_t len) +{ + // skip if previous report not yet acknowledged by host + if ( usbd_edpt_busy(TUD_OPT_RHPORT, _netd_itf.ep_notif) ) return; + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void netd_init(void) +{ + tu_memclr(&_netd_itf, sizeof(_netd_itf)); +} + +void netd_reset(uint8_t rhport) +{ + (void) rhport; + + netd_init(); +} + +uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass && + TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol); + + bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0x00 == itf_desc->bInterfaceProtocol); + + TU_VERIFY(is_rndis || is_ecm, 0); + + // confirm interface hasn't already been allocated + TU_ASSERT(0 == _netd_itf.ep_notif, 0); + + // sanity check the descriptor + _netd_itf.ecm_mode = is_ecm; + + //------------- Management Interface -------------// + _netd_itf.itf_num = itf_desc->bInterfaceNumber; + + uint16_t drv_len = sizeof(tusb_desc_interface_t); + uint8_t const * p_desc = tu_desc_next( itf_desc ); + + // Communication Functional Descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) + { + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + // notification endpoint (if any) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); + + _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + //------------- Data Interface -------------// + // - RNDIS Data followed immediately by a pair of endpoints + // - CDC-ECM data interface has 2 alternate settings + // - 0 : zero endpoints for inactive (default) + // - 1 : IN & OUT endpoints for active networking + TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); + + do + { + tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; + TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len) ); + + // Pair of endpoints + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); + + if ( _netd_itf.ecm_mode ) + { + // ECM by default is in-active, save the endpoint attribute + // to open later when received setInterface + _netd_itf.ecm_desc_epdata = p_desc; + }else + { + // Open endpoint pair for RNDIS + TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0 ); + + tud_network_init_cb(); + + // we are ready to transmit a packet + can_xmit = true; + + // prepare for incoming packets + tud_network_recv_renew(); + } + + drv_len += 2*sizeof(tusb_desc_endpoint_t); + + return drv_len; +} + +static void ecm_report(bool nc) +{ + notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; + notify.ecm_buf.header.wIndex = _netd_itf.itf_num; + netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage == CONTROL_STAGE_SETUP ) + { + switch ( request->bmRequestType_bit.type ) + { + case TUSB_REQ_TYPE_STANDARD: + switch ( request->bRequest ) + { + case TUSB_REQ_GET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); + + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + } + break; + + case TUSB_REQ_SET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + uint8_t const req_alt = (uint8_t) request->wValue; + + // Only valid for Data Interface with Alternate is either 0 or 1 + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); + + // ACM-ECM only: qequest to enable/disable network activities + TU_VERIFY(_netd_itf.ecm_mode); + + _netd_itf.itf_data_alt = req_alt; + + if ( _netd_itf.itf_data_alt ) + { + // TODO since we don't actually close endpoint + // hack here to not re-open it + if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) + { + TU_ASSERT(_netd_itf.ecm_desc_epdata); + TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); + + // TODO should be merge with RNDIS's after endpoint opened + // Also should have opposite callback for application to disable network !! + tud_network_init_cb(); + can_xmit = true; // we are ready to transmit a packet + tud_network_recv_renew(); // prepare for incoming packets + } + }else + { + // TODO close the endpoint pair + // For now pretend that we did, this should have no harm since host won't try to + // communicate with the endpoints again + // _netd_itf.ep_in = _netd_itf.ep_out = 0 + } + + tud_control_status(rhport, request); + } + break; + + // unsupported request + default: return false; + } + break; + + case TUSB_REQ_TYPE_CLASS: + TU_VERIFY (_netd_itf.itf_num == request->wIndex); + + if (_netd_itf.ecm_mode) + { + /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ + if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + { + tud_control_xfer(rhport, request, NULL, 0); + ecm_report(true); + } + } + else + { + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf); + uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); + TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); + tud_control_xfer(rhport, request, notify.rndis_buf, msglen); + } + else + { + tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + } + } + break; + + // unsupported request + default: return false; + } + } + else if ( stage == CONTROL_STAGE_DATA ) + { + // Handle RNDIS class control OUT only + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.direction == TUSB_DIR_OUT && + _netd_itf.itf_num == request->wIndex) + { + if ( !_netd_itf.ecm_mode ) + { + rndis_class_set_handler(notify.rndis_buf, request->wLength); + } + } + } + + return true; +} + +static void handle_incoming_packet(uint32_t len) +{ + uint8_t *pnt = received; + uint32_t size = 0; + + if (_netd_itf.ecm_mode) + { + size = len; + } + else + { + rndis_data_packet_t *r = (rndis_data_packet_t *) ((void*) pnt); + if (len >= sizeof(rndis_data_packet_t)) + if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) + if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) + { + pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; + size = r->DataLength; + } + } + + if (!tud_network_recv_cb(pnt, size)) + { + /* if a buffer was never handled by user code, we must renew on the user's behalf */ + tud_network_recv_renew(); + } +} + +bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) rhport; + (void) result; + + /* new packet received */ + if ( ep_addr == _netd_itf.ep_out ) + { + handle_incoming_packet(xferred_bytes); + } + + /* data transmission finished */ + if ( ep_addr == _netd_itf.ep_in ) + { + /* TinyUSB requires the class driver to implement ZLP (since ZLP usage is class-specific) */ + + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE)) ) + { + do_in_xfer(NULL, 0); /* a ZLP is needed */ + } + else + { + /* we're finally finished */ + can_xmit = true; + } + } + + if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) + { + if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); + } + + return true; +} + +bool tud_network_can_xmit(uint16_t size) +{ + (void)size; + + return can_xmit; +} + +void tud_network_xmit(void *ref, uint16_t arg) +{ + uint8_t *data; + uint16_t len; + + if (!can_xmit) + return; + + len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; + data = transmitted + len; + + len += tud_network_xmit_cb(data, ref, arg); + + if (!_netd_itf.ecm_mode) + { + rndis_data_packet_t *hdr = (rndis_data_packet_t *) ((void*) transmitted); + memset(hdr, 0, sizeof(rndis_data_packet_t)); + hdr->MessageType = REMOTE_NDIS_PACKET_MSG; + hdr->MessageLength = len; + hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); + hdr->DataLength = len - sizeof(rndis_data_packet_t); + } + + do_in_xfer(transmitted, len); +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h new file mode 100644 index 000000000..96ba11fbc --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h @@ -0,0 +1,69 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + + +#ifndef _TUSB_NCM_H_ +#define _TUSB_NCM_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +// Table 4.3 Data Class Interface Protocol Codes +typedef enum +{ + NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK = 0x01 +} ncm_data_interface_protocol_code_t; + + +// Table 6.2 Class-Specific Request Codes for Network Control Model subclass +typedef enum +{ + NCM_SET_ETHERNET_MULTICAST_FILTERS = 0x40, + NCM_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41, + NCM_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42, + NCM_SET_ETHERNET_PACKET_FILTER = 0x43, + NCM_GET_ETHERNET_STATISTIC = 0x44, + NCM_GET_NTB_PARAMETERS = 0x80, + NCM_GET_NET_ADDRESS = 0x81, + NCM_SET_NET_ADDRESS = 0x82, + NCM_GET_NTB_FORMAT = 0x83, + NCM_SET_NTB_FORMAT = 0x84, + NCM_GET_NTB_INPUT_SIZE = 0x85, + NCM_SET_NTB_INPUT_SIZE = 0x86, + NCM_GET_MAX_DATAGRAM_SIZE = 0x87, + NCM_SET_MAX_DATAGRAM_SIZE = 0x88, + NCM_GET_CRC_MODE = 0x89, + NCM_SET_CRC_MODE = 0x8A, +} ncm_request_code_t; + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c new file mode 100644 index 000000000..3e131a85c --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c @@ -0,0 +1,510 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jacob Berg Potter + * Copyright (c) 2020 Peter Lawrence + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NCM ) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" +#include "net_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +#define NTH16_SIGNATURE 0x484D434E +#define NDP16_SIGNATURE_NCM0 0x304D434E +#define NDP16_SIGNATURE_NCM1 0x314D434E + +typedef struct TU_ATTR_PACKED +{ + uint16_t wLength; + uint16_t bmNtbFormatsSupported; + uint32_t dwNtbInMaxSize; + uint16_t wNdbInDivisor; + uint16_t wNdbInPayloadRemainder; + uint16_t wNdbInAlignment; + uint16_t wReserved; + uint32_t dwNtbOutMaxSize; + uint16_t wNdbOutDivisor; + uint16_t wNdbOutPayloadRemainder; + uint16_t wNdbOutAlignment; + uint16_t wNtbOutMaxDatagrams; +} ntb_parameters_t; + +typedef struct TU_ATTR_PACKED +{ + uint32_t dwSignature; + uint16_t wHeaderLength; + uint16_t wSequence; + uint16_t wBlockLength; + uint16_t wNdpIndex; +} nth16_t; + +typedef struct TU_ATTR_PACKED +{ + uint16_t wDatagramIndex; + uint16_t wDatagramLength; +} ndp16_datagram_t; + +typedef struct TU_ATTR_PACKED +{ + uint32_t dwSignature; + uint16_t wLength; + uint16_t wNextNdpIndex; + ndp16_datagram_t datagram[]; +} ndp16_t; + +typedef union TU_ATTR_PACKED { + struct { + nth16_t nth; + ndp16_t ndp; + }; + uint8_t data[CFG_TUD_NCM_IN_NTB_MAX_SIZE]; +} transmit_ntb_t; + +struct ecm_notify_struct +{ + tusb_control_request_t header; + uint32_t downlink, uplink; +}; + +typedef struct +{ + uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface + uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active + + uint8_t ep_notif; + uint8_t ep_in; + uint8_t ep_out; + + const ndp16_t *ndp; + uint8_t num_datagrams, current_datagram_index; + + enum { + REPORT_SPEED, + REPORT_CONNECTED, + REPORT_DONE + } report_state; + bool report_pending; + + uint8_t current_ntb; // Index in transmit_ntb[] that is currently being filled with datagrams + uint8_t datagram_count; // Number of datagrams in transmit_ntb[current_ntb] + uint16_t next_datagram_offset; // Offset in transmit_ntb[current_ntb].data to place the next datagram + uint16_t ntb_in_size; // Maximum size of transmitted (IN to host) NTBs; initially CFG_TUD_NCM_IN_NTB_MAX_SIZE + uint8_t max_datagrams_per_ntb; // Maximum number of datagrams per NTB; initially CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB + + uint16_t nth_sequence; // Sequence number counter for transmitted NTBs + + bool transferring; + +} ncm_interface_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static const ntb_parameters_t ntb_parameters = { + .wLength = sizeof(ntb_parameters_t), + .bmNtbFormatsSupported = 0x01, + .dwNtbInMaxSize = CFG_TUD_NCM_IN_NTB_MAX_SIZE, + .wNdbInDivisor = 4, + .wNdbInPayloadRemainder = 0, + .wNdbInAlignment = CFG_TUD_NCM_ALIGNMENT, + .wReserved = 0, + .dwNtbOutMaxSize = CFG_TUD_NCM_OUT_NTB_MAX_SIZE, + .wNdbOutDivisor = 4, + .wNdbOutPayloadRemainder = 0, + .wNdbOutAlignment = CFG_TUD_NCM_ALIGNMENT, + .wNtbOutMaxDatagrams = 0 +}; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static transmit_ntb_t transmit_ntb[2]; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t receive_ntb[CFG_TUD_NCM_OUT_NTB_MAX_SIZE]; + +static ncm_interface_t ncm_interface; + +/* + * Set up the NTB state in ncm_interface to be ready to add datagrams. + */ +static void ncm_prepare_for_tx(void) { + ncm_interface.datagram_count = 0; + // datagrams start after all the headers + ncm_interface.next_datagram_offset = sizeof(nth16_t) + sizeof(ndp16_t) + + ((CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB + 1) * sizeof(ndp16_datagram_t)); +} + +/* + * If not already transmitting, start sending the current NTB to the host and swap buffers + * to start filling the other one with datagrams. + */ +static void ncm_start_tx(void) { + if (ncm_interface.transferring) { + return; + } + + transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; + size_t ntb_length = ncm_interface.next_datagram_offset; + + // Fill in NTB header + ntb->nth.dwSignature = NTH16_SIGNATURE; + ntb->nth.wHeaderLength = sizeof(nth16_t); + ntb->nth.wSequence = ncm_interface.nth_sequence++; + ntb->nth.wBlockLength = ntb_length; + ntb->nth.wNdpIndex = sizeof(nth16_t); + + // Fill in NDP16 header and terminator + ntb->ndp.dwSignature = NDP16_SIGNATURE_NCM0; + ntb->ndp.wLength = sizeof(ndp16_t) + (ncm_interface.datagram_count + 1) * sizeof(ndp16_datagram_t); + ntb->ndp.wNextNdpIndex = 0; + ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = 0; + ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = 0; + + // Kick off an endpoint transfer + usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_in, ntb->data, ntb_length); + ncm_interface.transferring = true; + + // Swap to the other NTB and clear it out + ncm_interface.current_ntb = 1 - ncm_interface.current_ntb; + ncm_prepare_for_tx(); +} + +static struct ecm_notify_struct ncm_notify_connected = +{ + .header = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = CDC_NOTIF_NETWORK_CONNECTION, + .wValue = 1 /* Connected */, + .wLength = 0, + }, +}; + +static struct ecm_notify_struct ncm_notify_speed_change = +{ + .header = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE, + .wLength = 8, + }, + .downlink = 10000000, + .uplink = 10000000, +}; + +void tud_network_recv_renew(void) +{ + if (!ncm_interface.num_datagrams) + { + usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_out, receive_ntb, sizeof(receive_ntb)); + return; + } + + const ndp16_t *ndp = ncm_interface.ndp; + const int i = ncm_interface.current_datagram_index; + ncm_interface.current_datagram_index++; + ncm_interface.num_datagrams--; + + tud_network_recv_cb(receive_ntb + ndp->datagram[i].wDatagramIndex, ndp->datagram[i].wDatagramLength); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ + +void netd_init(void) +{ + tu_memclr(&ncm_interface, sizeof(ncm_interface)); + ncm_interface.ntb_in_size = CFG_TUD_NCM_IN_NTB_MAX_SIZE; + ncm_interface.max_datagrams_per_ntb = CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB; + ncm_prepare_for_tx(); +} + +void netd_reset(uint8_t rhport) +{ + (void) rhport; + + netd_init(); +} + +uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + // confirm interface hasn't already been allocated + TU_ASSERT(0 == ncm_interface.ep_notif, 0); + + //------------- Management Interface -------------// + ncm_interface.itf_num = itf_desc->bInterfaceNumber; + + uint16_t drv_len = sizeof(tusb_desc_interface_t); + uint8_t const * p_desc = tu_desc_next( itf_desc ); + + // Communication Functional Descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) + { + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + // notification endpoint (if any) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); + + ncm_interface.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + //------------- Data Interface -------------// + // - CDC-NCM data interface has 2 alternate settings + // - 0 : zero endpoints for inactive (default) + // - 1 : IN & OUT endpoints for transfer of NTBs + TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); + + do + { + tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; + TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } while((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len)); + + // Pair of endpoints + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); + + TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &ncm_interface.ep_out, &ncm_interface.ep_in) ); + + drv_len += 2*sizeof(tusb_desc_endpoint_t); + + return drv_len; +} + +static void ncm_report(void) +{ + if (ncm_interface.report_state == REPORT_SPEED) { + ncm_notify_speed_change.header.wIndex = ncm_interface.itf_num; + usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_speed_change, sizeof(ncm_notify_speed_change)); + ncm_interface.report_state = REPORT_CONNECTED; + ncm_interface.report_pending = true; + } else if (ncm_interface.report_state == REPORT_CONNECTED) { + ncm_notify_connected.header.wIndex = ncm_interface.itf_num; + usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_connected, sizeof(ncm_notify_connected)); + ncm_interface.report_state = REPORT_DONE; + ncm_interface.report_pending = true; + } +} + +TU_ATTR_WEAK void tud_network_link_state_cb(bool state) +{ + (void)state; +} + +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage != CONTROL_STAGE_SETUP ) return true; + + switch ( request->bmRequestType_bit.type ) + { + case TUSB_REQ_TYPE_STANDARD: + switch ( request->bRequest ) + { + case TUSB_REQ_GET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum); + + tud_control_xfer(rhport, request, &ncm_interface.itf_data_alt, 1); + } + break; + + case TUSB_REQ_SET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + uint8_t const req_alt = (uint8_t) request->wValue; + + // Only valid for Data Interface with Alternate is either 0 or 1 + TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum && req_alt < 2); + + if (req_alt != ncm_interface.itf_data_alt) { + ncm_interface.itf_data_alt = req_alt; + + if (ncm_interface.itf_data_alt) { + if (!usbd_edpt_busy(rhport, ncm_interface.ep_out)) { + tud_network_recv_renew(); // prepare for incoming datagrams + } + if (!ncm_interface.report_pending) { + ncm_report(); + } + } + + tud_network_link_state_cb(ncm_interface.itf_data_alt); + } + + tud_control_status(rhport, request); + } + break; + + // unsupported request + default: return false; + } + break; + + case TUSB_REQ_TYPE_CLASS: + TU_VERIFY (ncm_interface.itf_num == request->wIndex); + + if (NCM_GET_NTB_PARAMETERS == request->bRequest) + { + tud_control_xfer(rhport, request, (void*)&ntb_parameters, sizeof(ntb_parameters)); + } + + break; + + // unsupported request + default: return false; + } + + return true; +} + +static void handle_incoming_datagram(uint32_t len) +{ + uint32_t size = len; + + if (len == 0) { + return; + } + + TU_ASSERT(size >= sizeof(nth16_t), ); + + const nth16_t *hdr = (const nth16_t *)receive_ntb; + TU_ASSERT(hdr->dwSignature == NTH16_SIGNATURE, ); + TU_ASSERT(hdr->wNdpIndex >= sizeof(nth16_t) && (hdr->wNdpIndex + sizeof(ndp16_t)) <= len, ); + + const ndp16_t *ndp = (const ndp16_t *)(receive_ntb + hdr->wNdpIndex); + TU_ASSERT(ndp->dwSignature == NDP16_SIGNATURE_NCM0 || ndp->dwSignature == NDP16_SIGNATURE_NCM1, ); + TU_ASSERT(hdr->wNdpIndex + ndp->wLength <= len, ); + + int num_datagrams = (ndp->wLength - 12) / 4; + ncm_interface.current_datagram_index = 0; + ncm_interface.num_datagrams = 0; + ncm_interface.ndp = ndp; + for (int i = 0; i < num_datagrams && ndp->datagram[i].wDatagramIndex && ndp->datagram[i].wDatagramLength; i++) + { + ncm_interface.num_datagrams++; + } + + tud_network_recv_renew(); +} + +bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) rhport; + (void) result; + + /* new datagram receive_ntb */ + if (ep_addr == ncm_interface.ep_out ) + { + handle_incoming_datagram(xferred_bytes); + } + + /* data transmission finished */ + if (ep_addr == ncm_interface.ep_in ) + { + if (ncm_interface.transferring) { + ncm_interface.transferring = false; + } + + // If there are datagrams queued up that we tried to send while this NTB was being emitted, send them now + if (ncm_interface.datagram_count && ncm_interface.itf_data_alt == 1) { + ncm_start_tx(); + } + } + + if (ep_addr == ncm_interface.ep_notif ) + { + ncm_interface.report_pending = false; + ncm_report(); + } + + return true; +} + +// poll network driver for its ability to accept another packet to transmit +bool tud_network_can_xmit(uint16_t size) +{ + TU_VERIFY(ncm_interface.itf_data_alt == 1); + + if (ncm_interface.datagram_count >= ncm_interface.max_datagrams_per_ntb) { + TU_LOG2("NTB full [by count]\r\n"); + return false; + } + + size_t next_datagram_offset = ncm_interface.next_datagram_offset; + if (next_datagram_offset + size > ncm_interface.ntb_in_size) { + TU_LOG2("ntb full [by size]\r\n"); + return false; + } + + return true; +} + +void tud_network_xmit(void *ref, uint16_t arg) +{ + transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; + size_t next_datagram_offset = ncm_interface.next_datagram_offset; + + uint16_t size = tud_network_xmit_cb(ntb->data + next_datagram_offset, ref, arg); + + ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = ncm_interface.next_datagram_offset; + ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = size; + + ncm_interface.datagram_count++; + next_datagram_offset += size; + + // round up so the next datagram is aligned correctly + next_datagram_offset += (CFG_TUD_NCM_ALIGNMENT - 1); + next_datagram_offset -= (next_datagram_offset % CFG_TUD_NCM_ALIGNMENT); + + ncm_interface.next_datagram_offset = next_datagram_offset; + + ncm_start_tx(); +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h new file mode 100644 index 000000000..6e294465b --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h @@ -0,0 +1,118 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_NET_DEVICE_H_ +#define _TUSB_NET_DEVICE_H_ + +#include "class/cdc/cdc.h" + +#if CFG_TUD_ECM_RNDIS && CFG_TUD_NCM +#error "Cannot enable both ECM_RNDIS and NCM network drivers" +#endif + +#include "ncm.h" + +/* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ +#define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) + +/* Maximum Transmission Unit (in bytes) of the network, including Ethernet header */ +#ifndef CFG_TUD_NET_MTU +#define CFG_TUD_NET_MTU 1514 +#endif + +#ifndef CFG_TUD_NCM_IN_NTB_MAX_SIZE +#define CFG_TUD_NCM_IN_NTB_MAX_SIZE 3200 +#endif + +#ifndef CFG_TUD_NCM_OUT_NTB_MAX_SIZE +#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200 +#endif + +#ifndef CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB +#define CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB 8 +#endif + +#ifndef CFG_TUD_NCM_ALIGNMENT +#define CFG_TUD_NCM_ALIGNMENT 4 +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// indicate to network driver that client has finished with the packet provided to network_recv_cb() +void tud_network_recv_renew(void); + +// poll network driver for its ability to accept another packet to transmit +bool tud_network_can_xmit(uint16_t size); + +// if network_can_xmit() returns true, network_xmit() can be called once +void tud_network_xmit(void *ref, uint16_t arg); + +//--------------------------------------------------------------------+ +// Application Callbacks (WEAK is optional) +//--------------------------------------------------------------------+ + +// client must provide this: return false if the packet buffer was not accepted +bool tud_network_recv_cb(const uint8_t *src, uint16_t size); + +// client must provide this: copy from network stack packet pointer to dst +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg); + +//------------- ECM/RNDIS -------------// + +// client must provide this: initialize any network state back to the beginning +void tud_network_init_cb(void); + +// client must provide this: 48-bit MAC address +// TODO removed later since it is not part of tinyusb stack +extern const uint8_t tud_network_mac_address[6]; + +//------------- NCM -------------// + +// callback to client providing optional indication of internal state of network driver +void tud_network_link_state_cb(bool state); + +//--------------------------------------------------------------------+ +// INTERNAL USBD-CLASS DRIVER API +//--------------------------------------------------------------------+ +void netd_init (void); +void netd_reset (uint8_t rhport); +uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void netd_report (uint8_t *buf, uint16_t len); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_NET_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h new file mode 100644 index 000000000..7d7005c2e --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h @@ -0,0 +1,316 @@ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 N Conrad + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_USBTMC_H__ +#define _TUSB_USBTMC_H__ + +#include "common/tusb_common.h" + + +/* Implements USBTMC Revision 1.0, April 14, 2003 + + String descriptors must have a "LANGID=0x409"/US English string. + Characters must be 0x20 (' ') to 0x7E ('~') ASCII, + But MUST not contain: "/:?\* + Also must not have leading or trailing space (' ') + Device descriptor must state USB version 0x0200 or greater + + If USB488DeviceCapabilites.D2 = 1 (SR1), then there must be a INT endpoint. +*/ + +#define USBTMC_VERSION 0x0100 +#define USBTMC_488_VERSION 0x0100 + +typedef enum { + USBTMC_MSGID_DEV_DEP_MSG_OUT = 1u, + USBTMC_MSGID_DEV_DEP_MSG_IN = 2u, + USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT = 126u, + USBTMC_MSGID_VENDOR_SPECIFIC_IN = 127u, + USBTMC_MSGID_USB488_TRIGGER = 128u, +} usbtmc_msgid_enum; + +/// \brief Message header (For BULK OUT and BULK IN); 4 bytes +typedef struct TU_ATTR_PACKED +{ + uint8_t MsgID ; ///< Message type ID (usbtmc_msgid_enum) + uint8_t bTag ; ///< Transfer ID 1<=bTag<=255 + uint8_t bTagInverse ; ///< Complement of the tag + uint8_t _reserved ; ///< Must be 0x00 +} usbtmc_msg_header_t; + +typedef struct TU_ATTR_PACKED +{ + usbtmc_msg_header_t header; + uint8_t data[8]; +} usbtmc_msg_generic_t; + +/* Uses on the bulk-out endpoint: */ +// Next 8 bytes are message-specific +typedef struct TU_ATTR_PACKED { + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + struct TU_ATTR_PACKED + { + unsigned int EOM : 1 ; ///< EOM set on last byte + } bmTransferAttributes; + uint8_t _reserved[3]; +} usbtmc_msg_request_dev_dep_out; + +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_out) == 12u, "struct wrong length"); + +// Next 8 bytes are message-specific +typedef struct TU_ATTR_PACKED +{ + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + struct TU_ATTR_PACKED + { + unsigned int TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar + } bmTransferAttributes; + uint8_t TermChar; + uint8_t _reserved[2]; +} usbtmc_msg_request_dev_dep_in; + +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_in) == 12u, "struct wrong length"); + +/* Bulk-in headers */ + +typedef struct TU_ATTR_PACKED +{ + usbtmc_msg_header_t header; + uint32_t TransferSize; + struct TU_ATTR_PACKED + { + uint8_t EOM: 1; ///< Last byte of transfer is the end of the message + uint8_t UsingTermChar: 1; ///< Support TermChar && Request.TermCharEnabled && last char in transfer is TermChar + } bmTransferAttributes; + uint8_t _reserved[3]; +} usbtmc_msg_dev_dep_msg_in_header_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_msg_dev_dep_msg_in_header_t) == 12u, "struct wrong length"); + +/* Unsupported vendor things.... Are these ever used?*/ + +typedef struct TU_ATTR_PACKED +{ + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + uint8_t _reserved[4]; +} usbtmc_msg_request_vendor_specific_out; + + +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_out) == 12u, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ + usbtmc_msg_header_t header ; ///< Header + uint32_t TransferSize ; ///< Transfer size; LSB first + uint8_t _reserved[4]; +} usbtmc_msg_request_vendor_specific_in; + +TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_in) == 12u, "struct wrong length"); + +// Control request type should use tusb_control_request_t + +/* +typedef struct TU_ATTR_PACKED { + struct { + unsigned int Recipient : 5 ; ///< EOM set on last byte + unsigned int Type : 2 ; ///< EOM set on last byte + unsigned int DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN + } bmRequestType; + uint8_t bRequest ; ///< If bmRequestType.Type = Class, see usmtmc_request_type_enum + uint16_t wValue ; + uint16_t wIndex ; + uint16_t wLength ; // Number of bytes in data stage +} usbtmc_class_specific_control_req; + +*/ +// bulk-in protocol errors +enum { + USBTMC_BULK_IN_ERR_INCOMPLETE_HEADER = 1u, + USBTMC_BULK_IN_ERR_UNSUPPORTED = 2u, + USBTMC_BULK_IN_ERR_BAD_PARAMETER = 3u, + USBTMC_BULK_IN_ERR_DATA_TOO_SHORT = 4u, + USBTMC_BULK_IN_ERR_DATA_TOO_LONG = 5u, +}; +// bult-in halt errors +enum { + USBTMC_BULK_IN_ERR = 1u, ///< receives a USBTMC command message that expects a response while a + /// Bulk-IN transfer is in progress +}; + +typedef enum { + USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT = 1u, + USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS = 2u, + USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN = 3u, + USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS = 4u, + USBTMC_bREQUEST_INITIATE_CLEAR = 5u, + USBTMC_bREQUEST_CHECK_CLEAR_STATUS = 6u, + USBTMC_bREQUEST_GET_CAPABILITIES = 7u, + + USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional + + /****** USBTMC 488 *************/ + USB488_bREQUEST_READ_STATUS_BYTE = 128u, + USB488_bREQUEST_REN_CONTROL = 160u, + USB488_bREQUEST_GO_TO_LOCAL = 161u, + USB488_bREQUEST_LOCAL_LOCKOUT = 162u, + +} usmtmc_request_type_enum; + +typedef enum { + USBTMC_STATUS_SUCCESS = 0x01, + USBTMC_STATUS_PENDING = 0x02, + USBTMC_STATUS_FAILED = 0x80, + USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81, + USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS = 0x82, + USBTMC_STATUS_SPLIT_IN_PROGRESS = 0x83 +} usbtmc_status_enum; + +/************************************************************ + * Control Responses + */ + +typedef struct TU_ATTR_PACKED { + uint8_t USBTMC_status; ///< usbtmc_status_enum + uint8_t _reserved; + uint16_t bcdUSBTMC; ///< USBTMC_VERSION + + struct TU_ATTR_PACKED + { + unsigned int listenOnly :1; + unsigned int talkOnly :1; + unsigned int supportsIndicatorPulse :1; + } bmIntfcCapabilities; + struct TU_ATTR_PACKED + { + unsigned int canEndBulkInOnTermChar :1; + } bmDevCapabilities; + uint8_t _reserved2[6]; + uint8_t _reserved3[12]; +} usbtmc_response_capabilities_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_t) == 0x18, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + struct TU_ATTR_PACKED + { + unsigned int BulkInFifoBytes :1; + } bmClear; +} usbtmc_get_clear_status_rsp_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); + +// Used for both abort bulk IN and bulk OUT +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + uint8_t bTag; +} usbtmc_initiate_abort_rsp_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); + +// Used for both check_abort_bulk_in_status and check_abort_bulk_out_status +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + struct TU_ATTR_PACKED + { + unsigned int BulkInFifoBytes : 1; ///< Has queued data or a short packet that is queued + } bmAbortBulkIn; + uint8_t _reserved[2]; ///< Must be zero + uint32_t NBYTES_RXD_TXD; +} usbtmc_check_abort_bulk_rsp_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_check_abort_bulk_rsp_t) == 8u, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; ///< usbtmc_status_enum + uint8_t _reserved; + uint16_t bcdUSBTMC; ///< USBTMC_VERSION + + struct TU_ATTR_PACKED + { + unsigned int listenOnly :1; + unsigned int talkOnly :1; + unsigned int supportsIndicatorPulse :1; + } bmIntfcCapabilities; + + struct TU_ATTR_PACKED + { + unsigned int canEndBulkInOnTermChar :1; + } bmDevCapabilities; + + uint8_t _reserved2[6]; + uint16_t bcdUSB488; + + struct TU_ATTR_PACKED + { + unsigned int is488_2 :1; + unsigned int supportsREN_GTL_LLO :1; + unsigned int supportsTrigger :1; + } bmIntfcCapabilities488; + + struct TU_ATTR_PACKED + { + unsigned int SCPI :1; + unsigned int SR1 :1; + unsigned int RL1 :1; + unsigned int DT1 :1; + } bmDevCapabilities488; + uint8_t _reserved3[8]; +} usbtmc_response_capabilities_488_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_488_t) == 0x18, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ + uint8_t USBTMC_status; + uint8_t bTag; + uint8_t statusByte; +} usbtmc_read_stb_rsp_488_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length"); + +typedef struct TU_ATTR_PACKED +{ + struct TU_ATTR_PACKED + { + unsigned int bTag : 7; + unsigned int one : 1; + } bNotify1; + uint8_t StatusByte; +} usbtmc_read_stb_interrupt_488_t; + +TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_interrupt_488_t) == 2u, "struct wrong length"); + +#endif + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c new file mode 100644 index 000000000..26be987cf --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c @@ -0,0 +1,858 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Nathan Conrad + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* + * This library is not fully reentrant, though it is reentrant from the view + * of either the application layer or the USB stack. Due to its locking, + * it is not safe to call its functions from interrupts. + * + * The one exception is that its functions may not be called from the application + * until the USB stack is initialized. This should not be a problem since the + * device shouldn't be sending messages until it receives a request from the + * host. + */ + + +/* + * In the case of single-CPU "no OS", this task is never preempted other than by + * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. For "no OS", + * the mutex structure's main effect is to disable the USB interrupts. + * With an OS, this class driver uses the OSAL to perform locking. The code uses a single lock + * and does not call outside of this class with a lock held, so deadlocks won't happen. + */ + +//Limitations: +// "vendor-specific" commands are not handled. +// Dealing with "termchar" must be handled by the application layer, +// though additional error checking is does in this module. +// talkOnly and listenOnly are NOT supported. They're not permitted +// in USB488, anyway. + +/* Supported: + * + * Notification pulse + * Trigger + * Read status byte (both by interrupt endpoint and control message) + * + */ + + +// TODO: +// USBTMC 3.2.2 error conditions not strictly followed +// No local lock-out, REN, or GTL. +// Clear message available status byte at the correct time? (488 4.3.1.3) + + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "usbtmc_device.h" + +#ifdef xDEBUG +#include "uart_util.h" +static char logMsg[150]; +#endif + +/* + * The state machine does not allow simultaneous reading and writing. This is + * consistent with USBTMC. + */ + +typedef enum +{ + STATE_CLOSED, // Endpoints have not yet been opened since USB reset + STATE_NAK, // Bulk-out endpoint is in NAK state. + STATE_IDLE, // Bulk-out endpoint is waiting for CMD. + STATE_RCV, // Bulk-out is receiving DEV_DEP message + STATE_TX_REQUESTED, + STATE_TX_INITIATED, + STATE_TX_SHORTED, + STATE_CLEARING, + STATE_ABORTING_BULK_IN, + STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission + STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been transmitted + STATE_ABORTING_BULK_OUT, + STATE_NUM_STATES +} usbtmcd_state_enum; + +#if (CFG_TUD_USBTMC_ENABLE_488) + typedef usbtmc_response_capabilities_488_t usbtmc_capabilities_specific_t; +#else + typedef usbtmc_response_capabilities_t usbtmc_capabilities_specific_t; +#endif + + +typedef struct +{ + volatile usbtmcd_state_enum state; + + uint8_t itf_id; + uint8_t rhport; + uint8_t ep_bulk_in; + uint8_t ep_bulk_out; + uint8_t ep_int_in; + // IN buffer is only used for first packet, not the remainder + // in order to deal with prepending header + CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_MAX_PACKET_SIZE]; + // OUT buffer receives one packet at a time + CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; + uint32_t transfer_size_remaining; // also used for requested length for bulk IN. + uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) + + uint8_t lastBulkOutTag; // used for aborts (mostly) + uint8_t lastBulkInTag; // used for aborts (mostly) + + uint8_t const * devInBuffer; // pointer to application-layer used for transmissions + + usbtmc_capabilities_specific_t const * capabilities; +} usbtmc_interface_state_t; + +CFG_TUSB_MEM_SECTION static usbtmc_interface_state_t usbtmc_state = +{ + .itf_id = 0xFF, +}; + +// We need all headers to fit in a single packet in this implementation. +TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); +TU_VERIFY_STATIC( + (sizeof(usbtmc_state.ep_bulk_in_buf) % USBTMCD_MAX_PACKET_SIZE) == 0, + "packet buffer must be a multiple of the packet size"); + +static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); +static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); + +static uint8_t termChar; +static uint8_t termCharRequested = false; + + +osal_mutex_def_t usbtmcLockBuffer; +static osal_mutex_t usbtmcLock; + +// Our own private lock, mostly for the state variable. +#define criticalEnter() do {osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0) +#define criticalLeave() do {osal_mutex_unlock(usbtmcLock); } while (0) + +bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newState) +{ + bool ret = true; + criticalEnter(); + usbtmcd_state_enum oldState = usbtmc_state.state; + if (oldState == expectedState) + { + usbtmc_state.state = newState; + } + else + { + ret = false; + } + criticalLeave(); + return ret; +} + +// called from app +// We keep a reference to the buffer, so it MUST not change until the app is +// notified that the transfer is complete. +// length of data is specified in the hdr. + +// We can't just send the whole thing at once because we need to concatanate the +// header with the data. +bool tud_usbtmc_transmit_dev_msg_data( + const void * data, size_t len, + bool endOfMessage, + bool usingTermChar) +{ + const unsigned int txBufLen = sizeof(usbtmc_state.ep_bulk_in_buf); + +#ifndef NDEBUG + TU_ASSERT(len > 0u); + TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); + TU_ASSERT(usbtmc_state.transfer_size_sent == 0u); + if(usingTermChar) + { + TU_ASSERT(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); + TU_ASSERT(termCharRequested); + TU_ASSERT(((uint8_t const*)data)[len-1u] == termChar); + } +#endif + + TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); + usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_state.ep_bulk_in_buf; + tu_varclr(hdr); + hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; + hdr->header.bTag = usbtmc_state.lastBulkInTag; + hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); + hdr->TransferSize = len; + hdr->bmTransferAttributes.EOM = endOfMessage; + hdr->bmTransferAttributes.UsingTermChar = usingTermChar; + + // Copy in the header + const size_t headerLen = sizeof(*hdr); + const size_t dataLen = ((headerLen + hdr->TransferSize) <= txBufLen) ? + len : (txBufLen - headerLen); + const size_t packetLen = headerLen + dataLen; + + memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + headerLen, data, dataLen); + usbtmc_state.transfer_size_remaining = len - dataLen; + usbtmc_state.transfer_size_sent = dataLen; + usbtmc_state.devInBuffer = (uint8_t const*) data + (dataLen); + + bool stateChanged = + atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); + TU_VERIFY(stateChanged); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); + return true; +} + +void usbtmcd_init_cb(void) +{ + usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb(); +#ifndef NDEBUG +# if CFG_TUD_USBTMC_ENABLE_488 + if (usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) { + TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL,); + } + // Per USB488 spec: table 8 + TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); + TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); +# endif + if (usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) { + TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL,); + } +#endif + + usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); +} + +uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + (void)rhport; + + uint16_t drv_len; + uint8_t const * p_desc; + uint8_t found_endpoints = 0; + + TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS , 0); + TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS, 0); + +#ifndef NDEBUG + // Only 2 or 3 endpoints are allowed for USBTMC. + TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3), 0); +#endif + + TU_ASSERT(usbtmc_state.state == STATE_CLOSED, 0); + + // Interface + drv_len = 0u; + p_desc = (uint8_t const *) itf_desc; + + usbtmc_state.itf_id = itf_desc->bInterfaceNumber; + usbtmc_state.rhport = rhport; + + while (found_endpoints < itf_desc->bNumEndpoints && drv_len <= max_len) + { + if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + { + tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; + switch(ep_desc->bmAttributes.xfer) { + case TUSB_XFER_BULK: + TU_ASSERT(tu_edpt_packet_size(ep_desc) == USBTMCD_MAX_PACKET_SIZE, 0); + if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) + { + usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; + } else { + usbtmc_state.ep_bulk_out = ep_desc->bEndpointAddress; + } + + break; + case TUSB_XFER_INTERRUPT: +#ifndef NDEBUG + TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN, 0); + TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); +#endif + usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; + break; + default: + TU_ASSERT(false, 0); + } + TU_ASSERT( usbd_edpt_open(rhport, ep_desc), 0); + found_endpoints++; + } + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + // bulk endpoints are required, but interrupt IN is optional +#ifndef NDEBUG + TU_ASSERT(usbtmc_state.ep_bulk_in != 0, 0); + TU_ASSERT(usbtmc_state.ep_bulk_out != 0, 0); + if (itf_desc->bNumEndpoints == 2) + { + TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); + } + else if (itf_desc->bNumEndpoints == 3) + { + TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); + } +#if (CFG_TUD_USBTMC_ENABLE_488) + if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || + usbtmc_state.capabilities->bmDevCapabilities488.SR1) + { + TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); + } +#endif +#endif + atomicChangeState(STATE_CLOSED, STATE_NAK); + tud_usbtmc_open_cb(itf_desc->iInterface); + + return drv_len; +} +// Tell USBTMC class to set its bulk-in EP to ACK so that it can +// receive USBTMC commands. +// Returns false if it was already in an ACK state or is busy +// processing a command (such as a clear). Returns true if it was +// in the NAK state and successfully transitioned to the ACK wait +// state. +bool tud_usbtmc_start_bus_read() +{ + usbtmcd_state_enum oldState = usbtmc_state.state; + switch(oldState) + { + // These may transition to IDLE + case STATE_NAK: + case STATE_ABORTING_BULK_IN_ABORTED: + TU_VERIFY(atomicChangeState(oldState, STATE_IDLE)); + break; + // When receiving, let it remain receiving + case STATE_RCV: + break; + default: + TU_VERIFY(false); + } + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); + return true; +} + +void usbtmcd_reset_cb(uint8_t rhport) +{ + (void)rhport; + usbtmc_capabilities_specific_t const * capabilities = tud_usbtmc_get_capabilities_cb(); + + criticalEnter(); + tu_varclr(&usbtmc_state); + usbtmc_state.capabilities = capabilities; + usbtmc_state.itf_id = 0xFFu; + criticalLeave(); +} + +static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) +{ + (void)rhport; + // return true upon failure, as we can assume error is being handled elsewhere. + TU_VERIFY(atomicChangeState(STATE_IDLE, STATE_RCV), true); + usbtmc_state.transfer_size_sent = 0u; + + // must be a header, should have been confirmed before calling here. + usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + TU_VERIFY(tud_usbtmc_msgBulkOut_start_cb(msg)); + + TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); + usbtmc_state.lastBulkOutTag = msg->header.bTag; + return true; +} + +static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) +{ + (void)rhport; + // return true upon failure, as we can assume error is being handled elsewhere. + TU_VERIFY(usbtmc_state.state == STATE_RCV,true); + + bool shortPacket = (packetLen < USBTMCD_MAX_PACKET_SIZE); + + // Packet is to be considered complete when we get enough data or at a short packet. + bool atEnd = false; + if(len >= usbtmc_state.transfer_size_remaining || shortPacket) + { + atEnd = true; + TU_VERIFY(atomicChangeState(STATE_RCV, STATE_NAK)); + } + + len = tu_min32(len, usbtmc_state.transfer_size_remaining); + + usbtmc_state.transfer_size_remaining -= len; + usbtmc_state.transfer_size_sent += len; + + // App may (should?) call the wait_for_bus() command at this point + if(!tud_usbtmc_msg_data_cb(data, len, atEnd)) + { + // TODO: Go to an error state upon failure other than just stalling the EP? + return false; + } + + + return true; +} + +static bool handle_devMsgIn(void *data, size_t len) +{ + TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); + usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; + bool stateChanged = atomicChangeState(STATE_IDLE, STATE_TX_REQUESTED); + TU_VERIFY(stateChanged); + usbtmc_state.lastBulkInTag = msg->header.bTag; + usbtmc_state.transfer_size_remaining = msg->TransferSize; + usbtmc_state.transfer_size_sent = 0u; + + termCharRequested = msg->bmTransferAttributes.TermCharEnabled; + termChar = msg->TermChar; + + if(termCharRequested) + TU_VERIFY(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); + + TU_VERIFY(tud_usbtmc_msgBulkIn_request_cb(msg)); + return true; +} + +bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + TU_VERIFY(result == XFER_RESULT_SUCCESS); + //uart_tx_str_sync("TMC XFER CB\r\n"); + if(usbtmc_state.state == STATE_CLEARING) { + return true; /* I think we can ignore everything here */ + } + + if(ep_addr == usbtmc_state.ep_bulk_out) + { + usbtmc_msg_generic_t *msg = NULL; + + switch(usbtmc_state.state) + { + case STATE_IDLE: + TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t)); + msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); + uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); + TU_VERIFY(msg->header.bTag == invInvTag); + TU_VERIFY(msg->header.bTag != 0x00); + + switch(msg->header.MsgID) { + case USBTMC_MSGID_DEV_DEP_MSG_OUT: + if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) + { + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TU_VERIFY(false); + } + break; + + case USBTMC_MSGID_DEV_DEP_MSG_IN: + TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); + break; + +#if (CFG_TUD_USBTMC_ENABLE_488) + case USBTMC_MSGID_USB488_TRIGGER: + // Spec says we halt the EP if we didn't declare we support it. + TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); + TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg)); + + break; +#endif + case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: + case USBTMC_MSGID_VENDOR_SPECIFIC_IN: + default: + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TU_VERIFY(false); + return false; + } + return true; + + case STATE_RCV: + if(!handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)) + { + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + TU_VERIFY(false); + } + return true; + + case STATE_ABORTING_BULK_OUT: + TU_VERIFY(false); + return false; // Should be stalled by now, shouldn't have received a packet. + + case STATE_TX_REQUESTED: + case STATE_TX_INITIATED: + case STATE_ABORTING_BULK_IN: + case STATE_ABORTING_BULK_IN_SHORTED: + case STATE_ABORTING_BULK_IN_ABORTED: + default: + TU_VERIFY(false); + } + } + else if(ep_addr == usbtmc_state.ep_bulk_in) + { + switch(usbtmc_state.state) { + case STATE_TX_SHORTED: + TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); + TU_VERIFY(tud_usbtmc_msgBulkIn_complete_cb()); + break; + + case STATE_TX_INITIATED: + if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) + { + // FIXME! This removes const below! + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, + (void*)(uintptr_t) usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf))); + usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf); + usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf); + usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf); + } + else // last packet + { + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen) ); + if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) + { + usbtmc_state.state = STATE_TX_SHORTED; + } + } + return true; + + case STATE_ABORTING_BULK_IN: + // need to send short packet (ZLP?) + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); + usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; + return true; + + case STATE_ABORTING_BULK_IN_SHORTED: + /* Done. :)*/ + usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; + return true; + + default: + TU_ASSERT(false); + return false; + } + } + else if (ep_addr == usbtmc_state.ep_int_in) { + // Good? + return true; + } + return false; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + // nothing to do with DATA and ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; + + uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; +#if (CFG_TUD_USBTMC_ENABLE_488) + uint8_t bTag; +#endif + + if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && + (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && + (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && + (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) + { + uint32_t ep_addr = (request->wIndex); + + if(ep_addr == usbtmc_state.ep_bulk_out) + { + criticalEnter(); + usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us + criticalLeave(); + tud_usbtmc_bulkOut_clearFeature_cb(); + } + else if (ep_addr == usbtmc_state.ep_bulk_in) + { + tud_usbtmc_bulkIn_clearFeature_cb(); + } + else + { + return false; + } + return true; + } + + // Otherwise, we only handle class requests. + if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) + { + return false; + } + + // Verification that we own the interface is unneeded since it's been routed to us specifically. + + switch(request->bRequest) + { + // USBTMC required requests + case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: + { + usbtmc_initiate_abort_rsp_t rsp = { + .bTag = usbtmc_state.lastBulkOutTag, + }; + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); + + // wValue is the requested bTag to abort + if(usbtmc_state.state != STATE_RCV) + { + rsp.USBTMC_status = USBTMC_STATUS_FAILED; + } + else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0x7Fu)) + { + rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; + } + else + { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + // Check if we've queued a short packet + criticalEnter(); + usbtmc_state.state = STATE_ABORTING_BULK_OUT; + criticalLeave(); + TU_VERIFY(tud_usbtmc_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); + return true; + } + + case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: + { + usbtmc_check_abort_bulk_rsp_t rsp = { + .USBTMC_status = USBTMC_STATUS_SUCCESS, + .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent + }; + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); + TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); + return true; + } + + case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: + { + usbtmc_initiate_abort_rsp_t rsp = { + .bTag = usbtmc_state.lastBulkInTag, + }; + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); + // wValue is the requested bTag to abort + if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && + usbtmc_state.lastBulkInTag == (request->wValue & 0x7Fu)) + { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + usbtmc_state.transfer_size_remaining = 0u; + // Check if we've queued a short packet + criticalEnter(); + usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) == 0) ? + STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; + criticalLeave(); + if(usbtmc_state.transfer_size_sent == 0) + { + // Send short packet, nothing is in the buffer yet + TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); + usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; + } + TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); + } + else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) + { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... + rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; + } + else + { + rsp.USBTMC_status = USBTMC_STATUS_FAILED; + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); + return true; + } + + case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: + { + TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP + TU_VERIFY(request->wLength == 8u); + + usbtmc_check_abort_bulk_rsp_t rsp = + { + .USBTMC_status = USBTMC_STATUS_FAILED, + .bmAbortBulkIn = + { + .BulkInFifoBytes = (usbtmc_state.state != STATE_ABORTING_BULK_IN_ABORTED) + }, + .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, + }; + TU_VERIFY(tud_usbtmc_check_abort_bulk_in_cb(&rsp)); + criticalEnter(); + switch(usbtmc_state.state) + { + case STATE_ABORTING_BULK_IN_ABORTED: + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + usbtmc_state.state = STATE_IDLE; + break; + case STATE_ABORTING_BULK_IN: + case STATE_ABORTING_BULK_OUT: + rsp.USBTMC_status = USBTMC_STATUS_PENDING; + break; + default: + break; + } + criticalLeave(); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); + + return true; + } + + case USBTMC_bREQUEST_INITIATE_CLEAR: + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); + // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the + // control endpoint response shown in Table 31, and clear all input buffers and output buffers. + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + usbtmc_state.transfer_size_remaining = 0; + criticalEnter(); + usbtmc_state.state = STATE_CLEARING; + criticalLeave(); + TU_VERIFY(tud_usbtmc_initiate_clear_cb(&tmcStatusCode)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); + return true; + } + + case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; + TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); + + if(usbd_edpt_busy(rhport, usbtmc_state.ep_bulk_in)) + { + // Stuff stuck in TX buffer? + clearStatusRsp.bmClear.BulkInFifoBytes = 1; + clearStatusRsp.USBTMC_status = USBTMC_STATUS_PENDING; + } + else + { + // Let app check if it's clear + TU_VERIFY(tud_usbtmc_check_clear_cb(&clearStatusRsp)); + } + if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) + { + criticalEnter(); + usbtmc_state.state = STATE_IDLE; + criticalLeave(); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); + return true; + } + + case USBTMC_bREQUEST_GET_CAPABILITIES: + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(*(usbtmc_state.capabilities))); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); + return true; + } + // USBTMC Optional Requests + + case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); + TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse); + TU_VERIFY(tud_usbtmc_indicator_pulse_cb(request, &tmcStatusCode)); + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); + return true; + } +#if (CFG_TUD_USBTMC_ENABLE_488) + + // USB488 required requests + case USB488_bREQUEST_READ_STATUS_BYTE: + { + usbtmc_read_stb_rsp_488_t rsp; + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface + + bTag = request->wValue & 0x7F; + TU_VERIFY(request->bmRequestType == 0xA1); + TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero + TU_VERIFY(bTag >= 0x02 && bTag <= 127); + TU_VERIFY(request->wIndex == usbtmc_state.itf_id); + TU_VERIFY(request->wLength == 0x0003); + rsp.bTag = (uint8_t)bTag; + if(usbtmc_state.ep_int_in != 0) + { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + rsp.statusByte = 0x00; // Use interrupt endpoint, instead. + + usbtmc_read_stb_interrupt_488_t intMsg = + { + .bNotify1 = { + .one = 1, + .bTag = bTag & 0x7Fu, + }, + .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)) + }; + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); + } + else + { + rsp.statusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)); + } + TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); + return true; + } + // USB488 optional requests + case USB488_bREQUEST_REN_CONTROL: + case USB488_bREQUEST_GO_TO_LOCAL: + case USB488_bREQUEST_LOCAL_LOCKOUT: + { + TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(false); + return false; + } +#endif + + default: + TU_VERIFY(false); + return false; + } + TU_VERIFY(false); +} + +#endif /* CFG_TUD_TSMC */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h new file mode 100644 index 000000000..0549a1569 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h @@ -0,0 +1,116 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 N Conrad + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + + +#ifndef CLASS_USBTMC_USBTMC_DEVICE_H_ +#define CLASS_USBTMC_USBTMC_DEVICE_H_ + +#include "usbtmc.h" + +// Enable 488 mode by default +#if !defined(CFG_TUD_USBTMC_ENABLE_488) +#define CFG_TUD_USBTMC_ENABLE_488 (1) +#endif + +// USB spec says that full-speed must be 8,16,32, or 64. +// However, this driver implementation requires it to be >=32 +#define USBTMCD_MAX_PACKET_SIZE (64u) + +/*********************************************** + * Functions to be implemeted by the class implementation + */ + +// In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: +// * tud_usbtmc_open_cb +// * tud_usbtmc_msg_data_cb +// * tud_usbtmc_msgBulkIn_complete_cb +// * tud_usbtmc_msg_trigger_cb +// * (successful) tud_usbtmc_check_abort_bulk_out_cb +// * (successful) tud_usbtmc_check_abort_bulk_in_cb +// * (successful) tud_usmtmc_bulkOut_clearFeature_cb + +#if (CFG_TUD_USBTMC_ENABLE_488) +usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); +#else +usbtmc_response_capabilities_t const * tud_usbtmc_get_capabilities_cb(void); +#endif + +void tud_usbtmc_open_cb(uint8_t interface_id); + +bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); +// transfer_complete does not imply that a message is complete. +bool tud_usbtmc_msg_data_cb( void *data, size_t len, bool transfer_complete); +void tud_usbtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer + +bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); +bool tud_usbtmc_msgBulkIn_complete_cb(void); +void tud_usbtmc_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer + +bool tud_usbtmc_initiate_abort_bulk_in_cb(uint8_t *tmcResult); +bool tud_usbtmc_initiate_abort_bulk_out_cb(uint8_t *tmcResult); +bool tud_usbtmc_initiate_clear_cb(uint8_t *tmcResult); + +bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); +bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); + +// Indicator pulse should be 0.5 to 1.0 seconds long +TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); + +#if (CFG_TUD_USBTMC_ENABLE_488) +uint8_t tud_usbtmc_get_stb_cb(uint8_t *tmcResult); +TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg); +//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); +#endif + +/******************************************* + * Called from app + * + * We keep a reference to the buffer, so it MUST not change until the app is + * notified that the transfer is complete. + ******************************************/ + +bool tud_usbtmc_transmit_dev_msg_data( + const void * data, size_t len, + bool endOfMessage, bool usingTermChar); + +bool tud_usbtmc_start_bus_read(void); + + +/* "callbacks" from USB device core */ + +uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +void usbtmcd_reset_cb(uint8_t rhport); +bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +void usbtmcd_init_cb(void); + +/************************************************************ + * USBTMC Descriptor Templates + *************************************************************/ + + +#endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c new file mode 100644 index 000000000..8a4ca1d2e --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c @@ -0,0 +1,257 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VENDOR) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "vendor_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; + + /*------------- From this point, data is not cleared by bus reset -------------*/ + tu_fifo_t rx_ff; + tu_fifo_t tx_ff; + + uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE]; + uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE]; + +#if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex; + osal_mutex_def_t tx_ff_mutex; +#endif + + // Endpoint Transfer buffer + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_VENDOR_EPSIZE]; +} vendord_interface_t; + +CFG_TUSB_MEM_SECTION static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR]; + +#define ITF_MEM_RESET_SIZE offsetof(vendord_interface_t, rx_ff) + + +bool tud_vendor_n_mounted (uint8_t itf) +{ + return _vendord_itf[itf].ep_in && _vendord_itf[itf].ep_out; +} + +uint32_t tud_vendor_n_available (uint8_t itf) +{ + return tu_fifo_count(&_vendord_itf[itf].rx_ff); +} + +bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) +{ + return tu_fifo_peek(&_vendord_itf[itf].rx_ff, u8); +} + +//--------------------------------------------------------------------+ +// Read API +//--------------------------------------------------------------------+ +static void _prep_out_transaction (vendord_interface_t* p_itf) +{ + // skip if previous transfer not complete + if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_itf->ep_out) ) return; + + // Prepare for incoming data but only allow what we can store in the ring buffer. + uint16_t max_read = tu_fifo_remaining(&p_itf->rx_ff); + if ( max_read >= CFG_TUD_VENDOR_EPSIZE ) + { + usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_out, p_itf->epout_buf, CFG_TUD_VENDOR_EPSIZE); + } +} + +uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) +{ + vendord_interface_t* p_itf = &_vendord_itf[itf]; + uint32_t num_read = tu_fifo_read_n(&p_itf->rx_ff, buffer, bufsize); + _prep_out_transaction(p_itf); + return num_read; +} + +void tud_vendor_n_read_flush (uint8_t itf) +{ + vendord_interface_t* p_itf = &_vendord_itf[itf]; + tu_fifo_clear(&p_itf->rx_ff); + _prep_out_transaction(p_itf); +} + +//--------------------------------------------------------------------+ +// Write API +//--------------------------------------------------------------------+ +static bool maybe_transmit(vendord_interface_t* p_itf) +{ + // skip if previous transfer not complete + TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_itf->ep_in) ); + + uint16_t count = tu_fifo_read_n(&p_itf->tx_ff, p_itf->epin_buf, CFG_TUD_VENDOR_EPSIZE); + if (count > 0) + { + TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_in, p_itf->epin_buf, count) ); + } + return true; +} + +uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize) +{ + vendord_interface_t* p_itf = &_vendord_itf[itf]; + uint16_t ret = tu_fifo_write_n(&p_itf->tx_ff, buffer, bufsize); + maybe_transmit(p_itf); + return ret; +} + +uint32_t tud_vendor_n_write_available (uint8_t itf) +{ + return tu_fifo_remaining(&_vendord_itf[itf].tx_ff); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void vendord_init(void) +{ + tu_memclr(_vendord_itf, sizeof(_vendord_itf)); + + for(uint8_t i=0; irx_ff, p_itf->rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, 1, false); + tu_fifo_config(&p_itf->tx_ff, p_itf->tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, 1, false); + +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&p_itf->rx_ff, NULL, osal_mutex_create(&p_itf->rx_ff_mutex)); + tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex), NULL); +#endif + } +} + +void vendord_reset(uint8_t rhport) +{ + (void) rhport; + + for(uint8_t i=0; irx_ff); + tu_fifo_clear(&p_itf->tx_ff); + } +} + +uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) +{ + TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); + + uint8_t const * p_desc = tu_desc_next(desc_itf); + uint8_t const * desc_end = p_desc + max_len; + + // Find available interface + vendord_interface_t* p_vendor = NULL; + for(uint8_t i=0; iitf_num = desc_itf->bInterfaceNumber; + if (desc_itf->bNumEndpoints) + { + // skip non-endpoint descriptors + while ( (TUSB_DESC_ENDPOINT != tu_desc_type(p_desc)) && (p_desc < desc_end) ) + { + p_desc = tu_desc_next(p_desc); + } + + // Open endpoint pair with usbd helper + TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); + + p_desc += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + + // Prepare for incoming data + if ( p_vendor->ep_out ) + { + TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)), 0); + } + + if ( p_vendor->ep_in ) maybe_transmit(p_vendor); + } + + return (uintptr_t) p_desc - (uintptr_t) desc_itf; +} + +bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) rhport; + (void) result; + + uint8_t itf = 0; + vendord_interface_t* p_itf = _vendord_itf; + + for ( ; ; itf++, p_itf++) + { + if (itf >= TU_ARRAY_SIZE(_vendord_itf)) return false; + + if ( ( ep_addr == p_itf->ep_out ) || ( ep_addr == p_itf->ep_in ) ) break; + } + + if ( ep_addr == p_itf->ep_out ) + { + // Receive new data + tu_fifo_write_n(&p_itf->rx_ff, p_itf->epout_buf, xferred_bytes); + + // Invoked callback if any + if (tud_vendor_rx_cb) tud_vendor_rx_cb(itf); + + _prep_out_transaction(p_itf); + } + else if ( ep_addr == p_itf->ep_in ) + { + // Send complete, try to send more if possible + maybe_transmit(p_itf); + } + + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h new file mode 100644 index 000000000..d71c2a3e9 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h @@ -0,0 +1,136 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_VENDOR_DEVICE_H_ +#define _TUSB_VENDOR_DEVICE_H_ + +#include "common/tusb_common.h" + +#ifndef CFG_TUD_VENDOR_EPSIZE +#define CFG_TUD_VENDOR_EPSIZE 64 +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application API (Multiple Interfaces) +//--------------------------------------------------------------------+ +bool tud_vendor_n_mounted (uint8_t itf); + +uint32_t tud_vendor_n_available (uint8_t itf); +uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); +bool tud_vendor_n_peek (uint8_t itf, uint8_t* ui8); +void tud_vendor_n_read_flush (uint8_t itf); + +uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); +uint32_t tud_vendor_n_write_available (uint8_t itf); + +static inline +uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str); + +//--------------------------------------------------------------------+ +// Application API (Single Port) +//--------------------------------------------------------------------+ +static inline bool tud_vendor_mounted (void); +static inline uint32_t tud_vendor_available (void); +static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); +static inline bool tud_vendor_peek (uint8_t* ui8); +static inline void tud_vendor_read_flush (void); +static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); +static inline uint32_t tud_vendor_write_str (char const* str); +static inline uint32_t tud_vendor_write_available (void); + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when received new data +TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf); + +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ + +static inline uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str) +{ + return tud_vendor_n_write(itf, str, strlen(str)); +} + +static inline bool tud_vendor_mounted (void) +{ + return tud_vendor_n_mounted(0); +} + +static inline uint32_t tud_vendor_available (void) +{ + return tud_vendor_n_available(0); +} + +static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) +{ + return tud_vendor_n_read(0, buffer, bufsize); +} + +static inline bool tud_vendor_peek (uint8_t* ui8) +{ + return tud_vendor_n_peek(0, ui8); +} + +static inline void tud_vendor_read_flush(void) +{ + tud_vendor_n_read_flush(0); +} + +static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) +{ + return tud_vendor_n_write(0, buffer, bufsize); +} + +static inline uint32_t tud_vendor_write_str (char const* str) +{ + return tud_vendor_n_write_str(0, str); +} + +static inline uint32_t tud_vendor_write_available (void) +{ + return tud_vendor_n_write_available(0); +} + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void vendord_init(void); +void vendord_reset(uint8_t rhport); +uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_VENDOR_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c new file mode 100644 index 000000000..1e28e9af4 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c @@ -0,0 +1,146 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_VENDOR) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "host/usbh.h" +#include "vendor_host.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +custom_interface_info_t custom_interface[CFG_TUH_DEVICE_MAX]; + +static tusb_error_t cush_validate_paras(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) +{ + if ( !tusbh_custom_is_mounted(dev_addr, vendor_id, product_id) ) + { + return TUSB_ERROR_DEVICE_NOT_READY; + } + + TU_ASSERT( p_buffer != NULL && length != 0, TUSB_ERROR_INVALID_PARA); + + return TUSB_ERROR_NONE; +} +//--------------------------------------------------------------------+ +// APPLICATION API (need to check parameters) +//--------------------------------------------------------------------+ +tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) +{ + TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_buffer, length) ); + + if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_in) ) + { + return TUSB_ERROR_INTERFACE_IS_BUSY; + } + + (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length); + + return TUSB_ERROR_NONE; +} + +tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length) +{ + TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_data, length) ); + + if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_out) ) + { + return TUSB_ERROR_INTERFACE_IS_BUSY; + } + + (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length); + + return TUSB_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// USBH-CLASS API +//--------------------------------------------------------------------+ +void cush_init(void) +{ + tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUH_DEVICE_MAX); +} + +tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) +{ + // FIXME quick hack to test lpc1k custom class with 2 bulk endpoints + uint8_t const *p_desc = (uint8_t const *) p_interface_desc; + p_desc = tu_desc_next(p_desc); + + //------------- Bulk Endpoints Descriptor -------------// + for(uint32_t i=0; i<2; i++) + { + tusb_desc_endpoint_t const *p_endpoint = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint->bDescriptorType, TUSB_ERROR_INVALID_PARA); + + pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_IN_MASK ) ? + &custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out; + *p_pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); + TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); + + p_desc = tu_desc_next(p_desc); + } + + (*p_length) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + return TUSB_ERROR_NONE; +} + +void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event) +{ + +} + +void cush_close(uint8_t dev_addr) +{ + tusb_error_t err1, err2; + custom_interface_info_t * p_interface = &custom_interface[dev_addr-1]; + + // TODO re-consider to check pipe valid before calling pipe_close + if( pipehandle_is_valid( p_interface->pipe_in ) ) + { + err1 = hcd_pipe_close( p_interface->pipe_in ); + } + + if ( pipehandle_is_valid( p_interface->pipe_out ) ) + { + err2 = hcd_pipe_close( p_interface->pipe_out ); + } + + tu_memclr(p_interface, sizeof(custom_interface_info_t)); + + TU_ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 ); +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h new file mode 100644 index 000000000..07fa56c61 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h @@ -0,0 +1,67 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_VENDOR_HOST_H_ +#define _TUSB_VENDOR_HOST_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct { + pipe_handle_t pipe_in; + pipe_handle_t pipe_out; +}custom_interface_info_t; + +//--------------------------------------------------------------------+ +// USBH-CLASS DRIVER API +//--------------------------------------------------------------------+ +static inline bool tusbh_custom_is_mounted(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id) +{ + (void) vendor_id; // TODO check this later + (void) product_id; +// return (tusbh_device_get_mounted_class_flag(dev_addr) & TU_BIT(TUSB_CLASS_MAPPED_INDEX_END-1) ) != 0; + return false; +} + +tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length); +tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void cush_init(void); +tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); +void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event); +void cush_close(uint8_t dev_addr); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_VENDOR_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h new file mode 100644 index 000000000..844746546 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h @@ -0,0 +1,480 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Koji KITAYAMA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_VIDEO_H_ +#define TUSB_VIDEO_H_ + +#include "common/tusb_common.h" + +// Table 3-19 Color Matching Descriptor +typedef enum { + VIDEO_COLOR_PRIMARIES_UNDEFINED = 0x00, + VIDEO_COLOR_PRIMARIES_BT709, // sRGB (default) + VIDEO_COLOR_PRIMARIES_BT470_2M, + VIDEO_COLOR_PRIMARIES_BT470_2BG, + VIDEO_COLOR_PRIMARIES_SMPTE170M, + VIDEO_COLOR_PRIMARIES_SMPTE240M, +} video_color_primaries_t; + +// Table 3-19 Color Matching Descriptor +typedef enum { + VIDEO_COLOR_XFER_CH_UNDEFINED = 0x00, + VIDEO_COLOR_XFER_CH_BT709, // default + VIDEO_COLOR_XFER_CH_BT470_2M, + VIDEO_COLOR_XFER_CH_BT470_2BG, + VIDEO_COLOR_XFER_CH_SMPTE170M, + VIDEO_COLOR_XFER_CH_SMPTE240M, + VIDEO_COLOR_XFER_CH_LINEAR, + VIDEO_COLOR_XFER_CH_SRGB, +} video_color_transfer_characteristics_t; + +// Table 3-19 Color Matching Descriptor +typedef enum { + VIDEO_COLOR_COEF_UNDEFINED = 0x00, + VIDEO_COLOR_COEF_BT709, + VIDEO_COLOR_COEF_FCC, + VIDEO_COLOR_COEF_BT470_2BG, + VIDEO_COLOR_COEF_SMPTE170M, // BT.601 default + VIDEO_COLOR_COEF_SMPTE240M, +} video_color_matrix_coefficients_t; + +/* 4.2.1.2 Request Error Code Control */ +typedef enum { + VIDEO_ERROR_NONE = 0, /* The request succeeded. */ + VIDEO_ERROR_NOT_READY, + VIDEO_ERROR_WRONG_STATE, + VIDEO_ERROR_POWER, + VIDEO_ERROR_OUT_OF_RANGE, + VIDEO_ERROR_INVALID_UNIT, + VIDEO_ERROR_INVALID_CONTROL, + VIDEO_ERROR_INVALID_REQUEST, + VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE, + VIDEO_ERROR_UNKNOWN = 0xFF, +} video_error_code_t; + +/* A.2 Interface Subclass */ +typedef enum { + VIDEO_SUBCLASS_UNDEFINED = 0x00, + VIDEO_SUBCLASS_CONTROL, + VIDEO_SUBCLASS_STREAMING, + VIDEO_SUBCLASS_INTERFACE_COLLECTION, +} video_subclass_type_t; + +/* A.3 Interface Protocol */ +typedef enum { + VIDEO_ITF_PROTOCOL_UNDEFINED = 0x00, + VIDEO_ITF_PROTOCOL_15, +} video_interface_protocol_code_t; + +/* A.5 Class-Specific VideoControl Interface Descriptor Subtypes */ +typedef enum { + VIDEO_CS_ITF_VC_UNDEFINED = 0x00, + VIDEO_CS_ITF_VC_HEADER, + VIDEO_CS_ITF_VC_INPUT_TERMINAL, + VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + VIDEO_CS_ITF_VC_SELECTOR_UNIT, + VIDEO_CS_ITF_VC_PROCESSING_UNIT, + VIDEO_CS_ITF_VC_EXTENSION_UNIT, + VIDEO_CS_ITF_VC_ENCODING_UNIT, + VIDEO_CS_ITF_VC_MAX, +} video_cs_vc_interface_subtype_t; + +/* A.6 Class-Specific VideoStreaming Interface Descriptor Subtypes */ +typedef enum { + VIDEO_CS_ITF_VS_UNDEFINED = 0x00, + VIDEO_CS_ITF_VS_INPUT_HEADER = 0x01, + VIDEO_CS_ITF_VS_OUTPUT_HEADER = 0x02, + VIDEO_CS_ITF_VS_STILL_IMAGE_FRAME = 0x03, + VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED = 0x04, + VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED = 0x05, + VIDEO_CS_ITF_VS_FORMAT_MJPEG = 0x06, + VIDEO_CS_ITF_VS_FRAME_MJPEG = 0x07, + VIDEO_CS_ITF_VS_FORMAT_MPEG2TS = 0x0A, + VIDEO_CS_ITF_VS_FORMAT_DV = 0x0C, + VIDEO_CS_ITF_VS_COLORFORMAT = 0x0D, + VIDEO_CS_ITF_VS_FORMAT_FRAME_BASED = 0x10, + VIDEO_CS_ITF_VS_FRAME_FRAME_BASED = 0x11, + VIDEO_CS_ITF_VS_FORMAT_STREAM_BASED = 0x12, + VIDEO_CS_ITF_VS_FORMAT_H264 = 0x13, + VIDEO_CS_ITF_VS_FRAME_H264 = 0x14, + VIDEO_CS_ITF_VS_FORMAT_H264_SIMULCAST = 0x15, + VIDEO_CS_ITF_VS_FORMAT_VP8 = 0x16, + VIDEO_CS_ITF_VS_FRAME_VP8 = 0x17, + VIDEO_CS_ITF_VS_FORMAT_VP8_SIMULCAST = 0x18, +} video_cs_vs_interface_subtype_t; + +/* A.7. Class-Specific Endpoint Descriptor Subtypes */ +typedef enum { + VIDEO_CS_EP_UNDEFINED = 0x00, + VIDEO_CS_EP_GENERAL, + VIDEO_CS_EP_ENDPOINT, + VIDEO_CS_EP_INTERRUPT +} video_cs_ep_subtype_t; + +/* A.8 Class-Specific Request Codes */ +typedef enum { + VIDEO_REQUEST_UNDEFINED = 0x00, + VIDEO_REQUEST_SET_CUR = 0x01, + VIDEO_REQUEST_SET_CUR_ALL = 0x11, + VIDEO_REQUEST_GET_CUR = 0x81, + VIDEO_REQUEST_GET_MIN = 0x82, + VIDEO_REQUEST_GET_MAX = 0x83, + VIDEO_REQUEST_GET_RES = 0x84, + VIDEO_REQUEST_GET_LEN = 0x85, + VIDEO_REQUEST_GET_INFO = 0x86, + VIDEO_REQUEST_GET_DEF = 0x87, + VIDEO_REQUEST_GET_CUR_ALL = 0x91, + VIDEO_REQUEST_GET_MIN_ALL = 0x92, + VIDEO_REQUEST_GET_MAX_ALL = 0x93, + VIDEO_REQUEST_GET_RES_ALL = 0x94, + VIDEO_REQUEST_GET_DEF_ALL = 0x97 +} video_control_request_t; + +/* A.9.1 VideoControl Interface Control Selectors */ +typedef enum { + VIDEO_VC_CTL_UNDEFINED = 0x00, + VIDEO_VC_CTL_VIDEO_POWER_MODE, + VIDEO_VC_CTL_REQUEST_ERROR_CODE, +} video_interface_control_selector_t; + +/* A.9.8 VideoStreaming Interface Control Selectors */ +typedef enum { + VIDEO_VS_CTL_UNDEFINED = 0x00, + VIDEO_VS_CTL_PROBE, + VIDEO_VS_CTL_COMMIT, + VIDEO_VS_CTL_STILL_PROBE, + VIDEO_VS_CTL_STILL_COMMIT, + VIDEO_VS_CTL_STILL_IMAGE_TRIGGER, + VIDEO_VS_CTL_STREAM_ERROR_CODE, + VIDEO_VS_CTL_GENERATE_KEY_FRAME, + VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT, + VIDEO_VS_CTL_SYNCH_DELAY_CONTROL, +} video_interface_streaming_selector_t; + +/* B. Terminal Types */ +typedef enum { + // Terminal + VIDEO_TT_VENDOR_SPECIFIC = 0x0100, + VIDEO_TT_STREAMING = 0x0101, + + // Input + VIDEO_ITT_VENDOR_SPECIFIC = 0x0200, + VIDEO_ITT_CAMERA = 0x0201, + VIDEO_ITT_MEDIA_TRANSPORT_INPUT = 0x0202, + + // Output + VIDEO_OTT_VENDOR_SPECIFIC = 0x0300, + VIDEO_OTT_DISPLAY = 0x0301, + VIDEO_OTT_MEDIA_TRANSPORT_OUTPUT = 0x0302, + + // External + VIDEO_ETT_VENDOR_SPEIFIC = 0x0400, + VIDEO_ETT_COMPOSITE_CONNECTOR = 0x0401, + VIDEO_ETT_SVIDEO_CONNECTOR = 0x0402, + VIDEO_ETT_COMPONENT_CONNECTOR = 0x0403, +} video_terminal_type_t; + +//--------------------------------------------------------------------+ +// Descriptors +//--------------------------------------------------------------------+ + +/* 2.3.4.2 */ +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint16_t bcdUVC; + uint16_t wTotalLength; + uint32_t dwClockFrequency; + uint8_t bInCollection; + uint8_t baInterfaceNr[]; +} tusb_desc_cs_video_ctl_itf_hdr_t; + +/* 2.4.3.3 */ +typedef struct TU_ATTR_PACKED { + uint8_t bHeaderLength; + union { + uint8_t bmHeaderInfo; + struct { + uint8_t FrameID: 1; + uint8_t EndOfFrame: 1; + uint8_t PresentationTime: 1; + uint8_t SourceClockReference: 1; + uint8_t PayloadSpecific: 1; + uint8_t StillImage: 1; + uint8_t Error: 1; + uint8_t EndOfHeader: 1; + }; + }; +} tusb_video_payload_header_t; + +/* 3.9.2.1 */ +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bNumFormats; + uint16_t wTotalLength; + uint8_t bEndpointAddress; + uint8_t bmInfo; + uint8_t bTerminalLink; + uint8_t bStillCaptureMethod; + uint8_t bTriggerSupport; + uint8_t bTriggerUsage; + uint8_t bControlSize; + uint8_t bmaControls[]; +} tusb_desc_cs_video_stm_itf_in_hdr_t; + +/* 3.9.2.2 */ +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bNumFormats; + uint16_t wTotalLength; + uint8_t bEndpointAddress; + uint8_t bTerminalLink; + uint8_t bControlSize; + uint8_t bmaControls[]; +} tusb_desc_cs_video_stm_itf_out_hdr_t; + +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bNumFormats; + uint16_t wTotalLength; + uint8_t bEndpointAddress; + union { + struct { + uint8_t bmInfo; + uint8_t bTerminalLink; + uint8_t bStillCaptureMethod; + uint8_t bTriggerSupport; + uint8_t bTriggerUsage; + uint8_t bControlSize; + uint8_t bmaControls[]; + } input; + struct { + uint8_t bEndpointAddress; + uint8_t bTerminalLink; + uint8_t bControlSize; + uint8_t bmaControls[]; + } output; + }; +} tusb_desc_cs_video_stm_itf_hdr_t; + +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bFormatIndex; + uint8_t bNumFrameDescriptors; + uint8_t guidFormat[16]; + uint8_t bBitsPerPixel; + uint8_t bDefaultFrameIndex; + uint8_t bAspectRatioX; + uint8_t bAspectRatioY; + uint8_t bmInterlaceFlags; + uint8_t bCopyProtect; +} tusb_desc_cs_video_fmt_uncompressed_t; + +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bFrameIndex; + uint8_t bmCapabilities; + uint16_t wWidth; + uint16_t wHeight; + uint32_t dwMinBitRate; + uint32_t dwMaxBitRate; + uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ + uint32_t dwDefaultFrameInterval; + uint8_t bFrameIntervalType; + uint32_t dwFrameInterval[]; +} tusb_desc_cs_video_frm_uncompressed_t; + +//--------------------------------------------------------------------+ +// Requests +//--------------------------------------------------------------------+ + +/* 4.3.1.1 */ +typedef struct TU_ATTR_PACKED { + union { + uint8_t bmHint; + struct TU_ATTR_PACKED { + uint16_t dwFrameInterval: 1; + uint16_t wKeyFrameRatel : 1; + uint16_t wPFrameRate : 1; + uint16_t wCompQuality : 1; + uint16_t wCompWindowSize: 1; + uint16_t : 0; + } Hint; + }; + uint8_t bFormatIndex; + uint8_t bFrameIndex; + uint32_t dwFrameInterval; + uint16_t wKeyFrameRate; + uint16_t wPFrameRate; + uint16_t wCompQuality; + uint16_t wCompWindowSize; + uint16_t wDelay; + uint32_t dwMaxVideoFrameSize; + uint32_t dwMaxPayloadTransferSize; + uint32_t dwClockFrequency; + union { + uint8_t bmFramingInfo; + struct TU_ATTR_PACKED { + uint8_t FrameID : 1; + uint8_t EndOfFrame: 1; + uint8_t EndOfSlice: 1; + uint8_t : 0; + } FramingInfo; + }; + uint8_t bPreferedVersion; + uint8_t bMinVersion; + uint8_t bMaxVersion; + uint8_t bUsage; + uint8_t bBitDepthLuma; + uint8_t bmSettings; + uint8_t bMaxNumberOfRefFramesPlus1; + uint16_t bmRateControlModes; + uint64_t bmLayoutPerStream; +} video_probe_and_commit_control_t; + +TU_VERIFY_STATIC( sizeof(video_probe_and_commit_control_t) == 48, "size is not correct"); + +#define TUD_VIDEO_DESC_IAD_LEN 8 +#define TUD_VIDEO_DESC_STD_VC_LEN 9 +#define TUD_VIDEO_DESC_CS_VC_LEN 12 +#define TUD_VIDEO_DESC_INPUT_TERM_LEN 8 +#define TUD_VIDEO_DESC_OUTPUT_TERM_LEN 9 +#define TUD_VIDEO_DESC_CAMERA_TERM_LEN 18 +#define TUD_VIDEO_DESC_STD_VS_LEN 9 +#define TUD_VIDEO_DESC_CS_VS_IN_LEN 13 +#define TUD_VIDEO_DESC_CS_VS_OUT_LEN 9 +#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN 27 +#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN 38 +#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN 26 +#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN 6 + +/* 2.2 compression formats */ +#define TUD_VIDEO_GUID_YUY2 0x59,0x55,0x59,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 +#define TUD_VIDEO_GUID_NV12 0x4E,0x56,0x31,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 +#define TUD_VIDEO_GUID_M420 0x4D,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 +#define TUD_VIDEO_GUID_I420 0x49,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 + +#define TUD_VIDEO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ + TUD_VIDEO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, \ + _firstitfs, _nitfs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_INTERFACE_COLLECTION, \ + VIDEO_ITF_PROTOCOL_UNDEFINED, _stridx + +#define TUD_VIDEO_DESC_STD_VC(_itfnum, _nEPs, _stridx) \ + TUD_VIDEO_DESC_STD_VC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, \ + _nEPs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_CONTROL, VIDEO_ITF_PROTOCOL_15, _stridx + +/* 3.7.2 */ +#define TUD_VIDEO_DESC_CS_VC(_bcdUVC, _totallen, _clkfreq, ...) \ + TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_HEADER, \ + U16_TO_U8S_LE(_bcdUVC), U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__))), \ + U32_TO_U8S_LE(_clkfreq), TU_ARGS_NUM(__VA_ARGS__), __VA_ARGS__ + +/* 3.7.2.1 */ +#define TUD_VIDEO_DESC_INPUT_TERM(_tid, _tt, _at, _stridx) \ + TUD_VIDEO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ + _tid, U16_TO_U8S_LE(_tt), _at, _stridx + +/* 3.7.2.2 */ +#define TUD_VIDEO_DESC_OUTPUT_TERM(_tid, _tt, _at, _srcid, _stridx) \ + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, \ + _tid, U16_TO_U8S_LE(_tt), _at, _srcid, _stridx + +/* 3.7.2.3 */ +#define TUD_VIDEO_DESC_CAMERA_TERM(_tid, _at, _stridx, _focal_min, _focal_max, _focal, _ctls) \ + TUD_VIDEO_DESC_CAMERA_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ + _tid, U16_TO_U8S_LE(VIDEO_ITT_CAMERA), _at, _stridx, \ + U16_TO_U8S_LE(_focal_min), U16_TO_U8S_LE(_focal_max), U16_TO_U8S_LE(_focal), 3, \ + TU_U32_BYTE0(_ctls), TU_U32_BYTE1(_ctls), TU_U32_BYTE2(_ctls) + +/* 3.9.1 */ +#define TUD_VIDEO_DESC_STD_VS(_itfnum, _alt, _epn, _stridx) \ + TUD_VIDEO_DESC_STD_VS_LEN, TUSB_DESC_INTERFACE, _itfnum, _alt, \ + _epn, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_STREAMING, VIDEO_ITF_PROTOCOL_15, _stridx + +/* 3.9.2.1 */ +#define TUD_VIDEO_DESC_CS_VS_INPUT(_numfmt, _totallen, _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, ...) \ + TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ + VIDEO_CS_ITF_VS_INPUT_HEADER, _numfmt, \ + U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ + _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ + +/* 3.9.2.2 */ +#define TUD_VIDEO_DESC_CS_VS_OUTPUT(_numfmt, _totallen, _ep, _inf, _termlnk, ...) \ + TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ + VIDEO_CS_ITF_VS_OUTPUT_HEADER, _numfmt, \ + U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ + _ep, _inf, _termlnk, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ + +/* Uncompressed 3.1.1 */ +#define TUD_VIDEO_GUID(_g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15) _g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15 + +#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfrmdesc, \ + _guid, _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp) \ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, \ + _fmtidx, _numfrmdesc, TUD_VIDEO_GUID(_guid), \ + _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp + +/* Uncompressed 3.1.2 Table 3-3 */ +#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, _minfrminterval, _maxfrminterval, _frmintervalstep) \ + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ + _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ + U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), 0, \ + U32_TO_U8S_LE(_minfrminterval), U32_TO_U8S_LE(_maxfrminterval), U32_TO_U8S_LE(_frmintervalstep) + +/* Uncompressed 3.1.2 Table 3-4 */ +#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \ + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \ + TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ + _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ + U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ + +/* 3.9.2.6 */ +#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(_color, _trns, _mat) \ + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN, \ + TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_COLORFORMAT, \ + _color, _trns, _mat + +/* 3.10.1.1 */ +#define TUD_VIDEO_DESC_EP_ISO(_ep, _epsize, _ep_interval) \ + 7, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS,\ + U16_TO_U8S_LE(_epsize), _ep_interval + +/* 3.10.1.2 */ +#define TUD_VIDEO_DESC_EP_BULK(_ep, _epsize, _ep_interval) \ + 7, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), _ep_interval + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c new file mode 100644 index 000000000..eeb068197 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c @@ -0,0 +1,1149 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Koji KITAYAMA + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VIDEO && CFG_TUD_VIDEO_STREAMING) + +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "video_device.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct { + tusb_desc_interface_t std; + tusb_desc_cs_video_ctl_itf_hdr_t ctl; +} tusb_desc_vc_itf_t; + +typedef struct { + tusb_desc_interface_t std; + tusb_desc_cs_video_stm_itf_hdr_t stm; +} tusb_desc_vs_itf_t; + +typedef union { + tusb_desc_cs_video_ctl_itf_hdr_t ctl; + tusb_desc_cs_video_stm_itf_hdr_t stm; +} tusb_desc_video_itf_hdr_t; + +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bEntityId; +} tusb_desc_cs_video_entity_itf_t; + +/* video streaming interface */ +typedef struct TU_ATTR_PACKED { + uint8_t index_vc; /* index of bound video control interface */ + uint8_t index_vs; /* index from the video control interface */ + struct { + uint16_t beg; /* Offset of the begging of video streaming interface descriptor */ + uint16_t end; /* Offset of the end of video streaming interface descriptor */ + uint16_t cur; /* Offset of the current settings */ + uint16_t ep[2]; /* Offset of endpoint descriptors. 0: streaming, 1: still capture */ + } desc; + uint8_t *buffer; /* frame buffer. assume linear buffer. no support for stride access */ + uint32_t bufsize; /* frame buffer size */ + uint32_t offset; /* offset for the next payload transfer */ + uint32_t max_payload_transfer_size; + uint8_t error_code;/* error code */ + /*------------- From this point, data is not cleared by bus reset -------------*/ + CFG_TUSB_MEM_ALIGN uint8_t ep_buf[CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE]; /* EP transfer buffer for streaming */ +} videod_streaming_interface_t; + +/* video control interface */ +typedef struct TU_ATTR_PACKED { + void const *beg; /* The head of the first video control interface descriptor */ + uint16_t len; /* Byte length of the descriptors */ + uint16_t cur; /* offset for current video control interface */ + uint8_t stm[CFG_TUD_VIDEO_STREAMING]; /* Indices of streaming interface */ + uint8_t error_code; /* error code */ + uint8_t power_mode; + + /*------------- From this point, data is not cleared by bus reset -------------*/ + // CFG_TUSB_MEM_ALIGN uint8_t ctl_buf[64]; /* EP transfer buffer for interrupt transfer */ + +} videod_interface_t; + +#define ITF_STM_MEM_RESET_SIZE offsetof(videod_streaming_interface_t, ep_buf) + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION static videod_interface_t _videod_itf[CFG_TUD_VIDEO]; +CFG_TUSB_MEM_SECTION static videod_streaming_interface_t _videod_streaming_itf[CFG_TUD_VIDEO_STREAMING]; + +static uint8_t const _cap_get = 0x1u; /* support for GET */ +static uint8_t const _cap_get_set = 0x3u; /* support for GET and SET */ + +/** Get interface number from the interface descriptor + * + * @param[in] desc interface descriptor + * + * @return bInterfaceNumber */ +static inline uint8_t _desc_itfnum(void const *desc) +{ + return ((uint8_t const*)desc)[2]; +} + +/** Get endpoint address from the endpoint descriptor + * + * @param[in] desc endpoint descriptor + * + * @return bEndpointAddress */ +static inline uint8_t _desc_ep_addr(void const *desc) +{ + return ((uint8_t const*)desc)[2]; +} + +/** Get instance of streaming interface + * + * @param[in] ctl_idx instance number of video control + * @param[in] stm_idx index number of streaming interface + * + * @return instance */ +static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) +{ + videod_interface_t *ctl = &_videod_itf[ctl_idx]; + if (!ctl->beg) return NULL; + videod_streaming_interface_t *stm = &_videod_streaming_itf[ctl->stm[stm_idx]]; + if (!stm->desc.beg) return NULL; + return stm; +} + +static tusb_desc_vc_itf_t const* _get_desc_vc(videod_interface_t const *self) +{ + return (tusb_desc_vc_itf_t const *)(self->beg + self->cur); +} + +static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const *self) +{ + if (!self->desc.cur) return NULL; + void const *desc = _videod_itf[self->index_vc].beg; + return (tusb_desc_vs_itf_t const*)(desc + self->desc.cur); +} + +/** Find the first descriptor of a given type + * + * @param[in] beg The head of descriptor byte array. + * @param[in] end The tail of descriptor byte array. + * @param[in] desc_type The target descriptor type. + * + * @return The pointer for interface descriptor. + * @retval end did not found interface descriptor */ +static void const* _find_desc(void const *beg, void const *end, uint_fast8_t desc_type) +{ + void const *cur = beg; + while ((cur < end) && (desc_type != tu_desc_type(cur))) { + cur = tu_desc_next(cur); + } + return cur; +} + +/** Find the first descriptor specified by the arguments + * + * @param[in] beg The head of descriptor byte array. + * @param[in] end The tail of descriptor byte array. + * @param[in] desc_type The target descriptor type + * @param[in] element_0 The target element following the desc_type + * @param[in] element_1 The target element following the element_0 + * + * @return The pointer for interface descriptor. + * @retval end did not found interface descriptor */ +static void const* _find_desc_3(void const *beg, void const *end, + uint_fast8_t desc_type, + uint_fast8_t element_0, + uint_fast8_t element_1) +{ + for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, desc_type)) { + uint8_t const *p = (uint8_t const *)cur; + if ((p[2] == element_0) && (p[3] == element_1)) { + return cur; + } + cur = tu_desc_next(cur); + } + return end; +} + +/** Return the next interface descriptor which has another interface number. + * + * @param[in] beg The head of descriptor byte array. + * @param[in] end The tail of descriptor byte array. + * + * @return The pointer for interface descriptor. + * @retval end did not found interface descriptor */ +static void const* _next_desc_itf(void const *beg, void const *end) +{ + void const *cur = beg; + uint_fast8_t itfnum = ((tusb_desc_interface_t const*)cur)->bInterfaceNumber; + while ((cur < end) && + (itfnum == ((tusb_desc_interface_t const*)cur)->bInterfaceNumber)) { + cur = _find_desc(tu_desc_next(cur), end, TUSB_DESC_INTERFACE); + } + return cur; +} + +/** Find the first interface descriptor with the specified interface number and alternate setting number. + * + * @param[in] beg The head of descriptor byte array. + * @param[in] end The tail of descriptor byte array. + * @param[in] itfnum The target interface number. + * @param[in] altnum The target alternate setting number. + * + * @return The pointer for interface descriptor. + * @retval end did not found interface descriptor */ +static inline void const* _find_desc_itf(void const *beg, void const *end, uint_fast8_t itfnum, uint_fast8_t altnum) +{ + return _find_desc_3(beg, end, TUSB_DESC_INTERFACE, itfnum, altnum); +} + +/** Find the first endpoint descriptor belonging to the current interface descriptor. + * + * The search range is from `beg` to `end` or the next interface descriptor. + * + * @param[in] beg The head of descriptor byte array. + * @param[in] end The tail of descriptor byte array. + * + * @return The pointer for endpoint descriptor. + * @retval end did not found endpoint descriptor */ +static void const* _find_desc_ep(void const *beg, void const *end) +{ + for (void const *cur = beg; cur < end; cur = tu_desc_next(cur)) { + uint_fast8_t desc_type = tu_desc_type(cur); + if (TUSB_DESC_ENDPOINT == desc_type) return cur; + if (TUSB_DESC_INTERFACE == desc_type) break; + } + return end; +} + +/** Find the first entity descriptor with the entity ID + * specified by the argument belonging to the current video control descriptor. + * + * @param[in] desc The video control interface descriptor. + * @param[in] entityid The target entity id. + * + * @return The pointer for interface descriptor. + * @retval end did not found interface descriptor */ +static void const* _find_desc_entity(void const *desc, uint_fast8_t entityid) +{ + tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const*)desc; + void const *beg = vc; + void const *end = beg + vc->std.bLength + vc->ctl.wTotalLength; + for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, TUSB_DESC_CS_INTERFACE)) { + tusb_desc_cs_video_entity_itf_t const *itf = (tusb_desc_cs_video_entity_itf_t const *)cur; + if ((VIDEO_CS_ITF_VC_INPUT_TERMINAL <= itf->bDescriptorSubtype + && itf->bDescriptorSubtype < VIDEO_CS_ITF_VC_MAX) + && itf->bEntityId == entityid) { + return itf; + } + cur = tu_desc_next(cur); + } + return end; +} + +/** Return the end of the video streaming descriptor. */ +static inline void const* _end_of_streaming_descriptor(void const *desc) +{ + tusb_desc_vs_itf_t const *vs = (tusb_desc_vs_itf_t const *)desc; + return desc + vs->std.bLength + vs->stm.wTotalLength; +} + +/** Find the first format descriptor with the specified format number. */ +static inline tusb_desc_cs_video_fmt_uncompressed_t const *_find_desc_format(void const *beg, void const *end, uint_fast8_t fmtnum) +{ + return (tusb_desc_cs_video_fmt_uncompressed_t const*) + _find_desc_3(beg, end, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, fmtnum); +} + +/** Find the first frame descriptor with the specified format number. */ +static inline tusb_desc_cs_video_frm_uncompressed_t const *_find_desc_frame(void const *beg, void const *end, uint_fast8_t frmnum) +{ + return (tusb_desc_cs_video_frm_uncompressed_t const*) + _find_desc_3(beg, end, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, frmnum); +} + +/** Set uniquely determined values to variables that have not been set + * + * @param[in,out] param Target */ +static bool _update_streaming_parameters(videod_streaming_interface_t const *stm, + video_probe_and_commit_control_t *param) +{ + tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); + uint_fast8_t fmtnum = param->bFormatIndex; + TU_ASSERT(fmtnum <= vs->stm.bNumFormats); + if (!fmtnum) { + if (1 < vs->stm.bNumFormats) return true; /* Need to negotiate all variables. */ + fmtnum = 1; + param->bFormatIndex = 1; + } + + /* Set the parameters determined by the format */ + param->wKeyFrameRate = 1; + param->wPFrameRate = 0; + param->wCompQuality = 1; /* 1 to 10000 */ + param->wCompWindowSize = 1; /* GOP size? */ + param->wDelay = 0; /* milliseconds */ + param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ + param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ + param->bPreferedVersion = 1; + param->bMinVersion = 1; + param->bMaxVersion = 1; + param->bUsage = 0; + param->bBitDepthLuma = 8; + + void const *end = _end_of_streaming_descriptor(vs); + tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); + TU_ASSERT(fmt != end); + uint_fast8_t frmnum = param->bFrameIndex; + TU_ASSERT(frmnum <= fmt->bNumFrameDescriptors); + if (!frmnum) { + if (1 < fmt->bNumFrameDescriptors) return true; + frmnum = 1; + param->bFrameIndex = 1; + } + tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); + TU_ASSERT(frm != end); + + /* Set the parameters determined by the frame */ + uint_fast32_t frame_size = param->dwMaxVideoFrameSize; + if (!frame_size) { + frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->bBitsPerPixel / 8; + param->dwMaxVideoFrameSize = frame_size; + } + + uint_fast32_t interval = param->dwFrameInterval; + if (!interval) { + if ((1 < frm->bFrameIntervalType) || + ((0 == frm->bFrameIntervalType) && (frm->dwFrameInterval[1] != frm->dwFrameInterval[0]))) { + return true; + } + interval = frm->dwFrameInterval[0]; + param->dwFrameInterval = interval; + } + uint_fast32_t interval_ms = interval / 10000; + TU_ASSERT(interval_ms); + uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; + param->dwMaxPayloadTransferSize = payload_size; + return true; +} + +/** Set the minimum, maximum, default values or resolutions to variables which need to negotiate with the host + * + * @param[in] request GET_MAX, GET_MIN, GET_RES or GET_DEF + * @param[in,out] param Target + */ +static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *stm, uint_fast8_t request, + video_probe_and_commit_control_t *param) +{ + uint_fast8_t const fmtnum = param->bFormatIndex; + if (!fmtnum) { + switch (request) { + case VIDEO_REQUEST_GET_MAX: + param->bFormatIndex = _get_desc_vs(stm)->stm.bNumFormats; + break; + case VIDEO_REQUEST_GET_MIN: + case VIDEO_REQUEST_GET_DEF: + param->bFormatIndex = 1; + break; + default: return false; + } + /* Set the parameters determined by the format */ + param->wKeyFrameRate = 1; + param->wPFrameRate = 0; + param->wCompQuality = 1; /* 1 to 10000 */ + param->wCompWindowSize = 1; /* GOP size? */ + param->wDelay = 0; /* milliseconds */ + param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ + param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ + param->bPreferedVersion = 1; + param->bMinVersion = 1; + param->bMaxVersion = 1; + param->bUsage = 0; + param->bBitDepthLuma = 8; + return true; + } + + uint_fast8_t frmnum = param->bFrameIndex; + if (!frmnum) { + tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); + void const *end = _end_of_streaming_descriptor(vs); + tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); + switch (request) { + case VIDEO_REQUEST_GET_MAX: + frmnum = fmt->bNumFrameDescriptors; + break; + case VIDEO_REQUEST_GET_MIN: + frmnum = 1; + break; + case VIDEO_REQUEST_GET_DEF: + frmnum = fmt->bDefaultFrameIndex; + break; + default: return false; + } + param->bFrameIndex = frmnum; + /* Set the parameters determined by the frame */ + tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); + param->dwMaxVideoFrameSize = frm->wWidth * frm->wHeight * fmt->bBitsPerPixel / 8; + return true; + } + + if (!param->dwFrameInterval) { + tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); + void const *end = _end_of_streaming_descriptor(vs); + tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); + tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); + + uint_fast32_t interval, interval_ms; + switch (request) { + case VIDEO_REQUEST_GET_MAX: + { + uint_fast32_t min_interval, max_interval; + uint_fast8_t num_intervals = frm->bFrameIntervalType; + max_interval = num_intervals ? frm->dwFrameInterval[num_intervals - 1]: frm->dwFrameInterval[1]; + min_interval = frm->dwFrameInterval[0]; + interval = max_interval; + interval_ms = min_interval / 10000; + } + break; + case VIDEO_REQUEST_GET_MIN: + { + uint_fast32_t min_interval, max_interval; + uint_fast8_t num_intervals = frm->bFrameIntervalType; + max_interval = num_intervals ? frm->dwFrameInterval[num_intervals - 1]: frm->dwFrameInterval[1]; + min_interval = frm->dwFrameInterval[0]; + interval = min_interval; + interval_ms = max_interval / 10000; + } + break; + case VIDEO_REQUEST_GET_DEF: + interval = frm->dwDefaultFrameInterval; + interval_ms = interval / 10000; + break; + case VIDEO_REQUEST_GET_RES: + { + uint_fast8_t num_intervals = frm->bFrameIntervalType; + if (num_intervals) { + interval = 0; + } else { + interval = frm->dwFrameInterval[2]; + interval_ms = interval / 10000; + } + } + break; + default: return false; + } + param->dwFrameInterval = interval; + if (!interval) { + param->dwMaxPayloadTransferSize = 0; + } else { + uint_fast32_t frame_size = param->dwMaxVideoFrameSize; + if (!interval_ms) { + param->dwMaxPayloadTransferSize = frame_size + 2; + } else { + param->dwMaxPayloadTransferSize = (frame_size + interval_ms - 1) / interval_ms + 2; + } + } + return true; + } + return true; +} + +/** Close current video control interface. + * + * @param[in,out] self Video control interface context. + * @param[in] altnum The target alternate setting number. */ +static bool _close_vc_itf(uint8_t rhport, videod_interface_t *self) +{ + tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); + /* The next descriptor after the class-specific VC interface header descriptor. */ + void const *cur = (void const*)vc + vc->std.bLength + vc->ctl.bLength; + /* The end of the video control interface descriptor. */ + void const *end = (void const*)vc + vc->std.bLength + vc->ctl.wTotalLength; + if (vc->std.bNumEndpoints) { + /* Find the notification endpoint descriptor. */ + cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); + TU_ASSERT(cur < end); + tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; + usbd_edpt_close(rhport, notif->bEndpointAddress); + } + self->cur = 0; + return true; +} + +/** Set the alternate setting to own video control interface. + * + * @param[in,out] self Video control interface context. + * @param[in] altnum The target alternate setting number. */ +static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t altnum) +{ + TU_LOG2(" open VC %d\n", altnum); + void const *beg = self->beg; + void const *end = beg + self->len; + /* The first descriptor is a video control interface descriptor. */ + void const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); + TU_LOG2(" cur %d\n", cur - beg); + TU_VERIFY(cur < end); + + tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const *)cur; + TU_LOG2(" bInCollection %d\n", vc->ctl.bInCollection); + /* Support for up to 2 streaming interfaces only. */ + TU_ASSERT(vc->ctl.bInCollection <= CFG_TUD_VIDEO_STREAMING); + + /* Update to point the end of the video control interface descriptor. */ + end = cur + vc->std.bLength + vc->ctl.wTotalLength; + /* Advance to the next descriptor after the class-specific VC interface header descriptor. */ + cur += vc->std.bLength + vc->ctl.bLength; + TU_LOG2(" bNumEndpoints %d\n", vc->std.bNumEndpoints); + /* Open the notification endpoint if it exist. */ + if (vc->std.bNumEndpoints) { + /* Support for 1 endpoint only. */ + TU_VERIFY(1 == vc->std.bNumEndpoints); + /* Find the notification endpoint descriptor. */ + cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); + TU_VERIFY(cur < end); + tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; + /* Open the notification endpoint */ + TU_ASSERT(usbd_edpt_open(rhport, notif)); + } + self->cur = (void const*)vc - beg; + return true; +} + +/** Set the alternate setting to own video streaming interface. + * + * @param[in,out] stm Streaming interface context. + * @param[in] altnum The target alternate setting number. */ +static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint_fast8_t altnum) +{ + uint_fast8_t i; + TU_LOG2(" reopen VS %d\n", altnum); + void const *desc = _videod_itf[stm->index_vc].beg; + + /* Close endpoints of previous settings. */ + for (i = 0; i < TU_ARRAY_SIZE(stm->desc.ep); ++i) { + uint_fast16_t ofs_ep = stm->desc.ep[i]; + if (!ofs_ep) break; + uint_fast8_t ep_adr = _desc_ep_addr(desc + ofs_ep); + usbd_edpt_close(rhport, ep_adr); + stm->desc.ep[i] = 0; + TU_LOG2(" close EP%02x\n", ep_adr); + } + /* clear transfer management information */ + stm->buffer = NULL; + stm->bufsize = 0; + stm->offset = 0; + + /* Find a alternate interface */ + void const *beg = desc + stm->desc.beg; + void const *end = desc + stm->desc.end; + void const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); + TU_VERIFY(cur < end); + uint_fast8_t numeps = ((tusb_desc_interface_t const *)cur)->bNumEndpoints; + TU_ASSERT(numeps <= TU_ARRAY_SIZE(stm->desc.ep)); + stm->desc.cur = cur - desc; /* Save the offset of the new settings */ + if (!altnum) { + /* initialize streaming settings */ + stm->max_payload_transfer_size = 0; + video_probe_and_commit_control_t *param = + (video_probe_and_commit_control_t *)&stm->ep_buf; + tu_memclr(param, sizeof(*param)); + return _update_streaming_parameters(stm, param); + } + /* Open endpoints of the new settings. */ + for (i = 0, cur = tu_desc_next(cur); i < numeps; ++i, cur = tu_desc_next(cur)) { + cur = _find_desc_ep(cur, end); + TU_ASSERT(cur < end); + tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)cur; + if (!stm->max_payload_transfer_size) { + video_probe_and_commit_control_t const *param = (video_probe_and_commit_control_t const*)&stm->ep_buf; + uint_fast32_t max_size = param->dwMaxPayloadTransferSize; + if ((TUSB_XFER_ISOCHRONOUS == ep->bmAttributes.xfer) && + (tu_edpt_packet_size(ep) < max_size)) + { + /* FS must be less than or equal to max packet size */ + return false; + } + /* Set the negotiated value */ + stm->max_payload_transfer_size = max_size; + } + TU_ASSERT(usbd_edpt_open(rhport, ep)); + stm->desc.ep[i] = cur - desc; + TU_LOG2(" open EP%02x\n", _desc_ep_addr(cur)); + } + /* initialize payload header */ + tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; + hdr->bHeaderLength = sizeof(*hdr); + hdr->bmHeaderInfo = 0; + + return true; +} + +/** Prepare the next packet payload. */ +static uint_fast16_t _prepare_in_payload(videod_streaming_interface_t *stm) +{ + uint_fast16_t remaining = stm->bufsize - stm->offset; + uint_fast16_t hdr_len = stm->ep_buf[0]; + uint_fast16_t pkt_len = stm->max_payload_transfer_size; + if (hdr_len + remaining < pkt_len) { + pkt_len = hdr_len + remaining; + } + uint_fast16_t data_len = pkt_len - hdr_len; + memcpy(&stm->ep_buf[hdr_len], stm->buffer + stm->offset, data_len); + stm->offset += data_len; + remaining -= data_len; + if (!remaining) { + tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; + hdr->EndOfFrame = 1; + } + return hdr_len + data_len; +} + +/** Handle a standard request to the video control interface. */ +static int handle_video_ctl_std_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t ctl_idx) +{ + switch (request->bRequest) { + case TUSB_REQ_GET_INTERFACE: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + tusb_desc_vc_itf_t const *vc = _get_desc_vc(&_videod_itf[ctl_idx]); + TU_VERIFY(vc, VIDEO_ERROR_UNKNOWN); + + uint8_t alt_num = vc->std.bAlternateSetting; + + TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case TUSB_REQ_SET_INTERFACE: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(0 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(_close_vc_itf(rhport, &_videod_itf[ctl_idx]), VIDEO_ERROR_UNKNOWN); + TU_VERIFY(_open_vc_itf(rhport, &_videod_itf[ctl_idx], request->wValue), VIDEO_ERROR_UNKNOWN); + tud_control_status(rhport, request); + } + return VIDEO_ERROR_NONE; + + default: /* Unknown/Unsupported request */ + TU_BREAKPOINT(); + return VIDEO_ERROR_INVALID_REQUEST; + } +} + +static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t ctl_idx) +{ + videod_interface_t *self = &_videod_itf[ctl_idx]; + + /* 4.2.1 Interface Control Request */ + switch (TU_U16_HIGH(request->wValue)) { + case VIDEO_VC_CTL_VIDEO_POWER_MODE: + switch (request->bRequest) { + case VIDEO_REQUEST_SET_CUR: + if (stage == CONTROL_STAGE_SETUP) { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); + } else if (stage == CONTROL_STAGE_ACK) { + if (tud_video_power_mode_cb) return tud_video_power_mode_cb(ctl_idx, self->power_mode); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_CUR: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_INFO: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + default: break; + } + break; + + case VIDEO_VC_CTL_REQUEST_ERROR_CODE: + switch (request->bRequest) { + case VIDEO_REQUEST_GET_CUR: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_INFO: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + default: break; + } + break; + + default: break; + } + + /* Unknown/Unsupported request */ + TU_BREAKPOINT(); + return VIDEO_ERROR_INVALID_REQUEST; +} + +static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t ctl_idx) +{ + uint_fast8_t entity_id; + switch (request->bmRequestType_bit.type) { + case TUSB_REQ_TYPE_STANDARD: + return handle_video_ctl_std_req(rhport, stage, request, ctl_idx); + + case TUSB_REQ_TYPE_CLASS: + entity_id = TU_U16_HIGH(request->wIndex); + if (!entity_id) { + return handle_video_ctl_cs_req(rhport, stage, request, ctl_idx); + } else { + TU_VERIFY(_find_desc_entity(_get_desc_vc(&_videod_itf[ctl_idx]), entity_id), VIDEO_ERROR_INVALID_REQUEST); + return VIDEO_ERROR_NONE; + } + + default: + return VIDEO_ERROR_INVALID_REQUEST; + } +} + +static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t stm_idx) +{ + videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; + switch (request->bRequest) { + case TUSB_REQ_GET_INTERFACE: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + tusb_desc_vs_itf_t const *vs = _get_desc_vs(self); + TU_VERIFY(vs, VIDEO_ERROR_UNKNOWN); + uint8_t alt_num = vs->std.bAlternateSetting; + + TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case TUSB_REQ_SET_INTERFACE: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(_open_vs_itf(rhport, self, request->wValue), VIDEO_ERROR_UNKNOWN); + tud_control_status(rhport, request); + } + return VIDEO_ERROR_NONE; + + default: /* Unknown/Unsupported request */ + TU_BREAKPOINT(); + return VIDEO_ERROR_INVALID_REQUEST; + } +} + +static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t stm_idx) +{ + (void)rhport; + videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; + + /* 4.2.1 Interface Control Request */ + switch (TU_U16_HIGH(request->wValue)) { + case VIDEO_VS_CTL_STREAM_ERROR_CODE: + switch (request->bRequest) { + case VIDEO_REQUEST_GET_CUR: + if (stage == CONTROL_STAGE_SETUP) + { + /* TODO */ + TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_INFO: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + default: break; + } + break; + + case VIDEO_VS_CTL_PROBE: + switch (request->bRequest) { + case VIDEO_REQUEST_SET_CUR: + if (stage == CONTROL_STAGE_SETUP) { + TU_VERIFY(sizeof(video_probe_and_commit_control_t) == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), + VIDEO_ERROR_UNKNOWN); + } else if (stage == CONTROL_STAGE_ACK) { + TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), + VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_CUR: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_MIN: + case VIDEO_REQUEST_GET_MAX: + case VIDEO_REQUEST_GET_RES: + case VIDEO_REQUEST_GET_DEF: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + video_probe_and_commit_control_t tmp; + tmp = *(video_probe_and_commit_control_t*)&self->ep_buf; + TU_VERIFY(_negotiate_streaming_parameters(self, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); + TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_LEN: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); + uint16_t len = sizeof(video_probe_and_commit_control_t); + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_INFO: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + default: break; + } + break; + + case VIDEO_VS_CTL_COMMIT: + switch (request->bRequest) { + case VIDEO_REQUEST_SET_CUR: + if (stage == CONTROL_STAGE_SETUP) { + TU_VERIFY(sizeof(video_probe_and_commit_control_t) == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); + } else if (stage == CONTROL_STAGE_ACK) { + TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); + if (tud_video_commit_cb) { + return tud_video_commit_cb(self->index_vc, self->index_vs, (video_probe_and_commit_control_t*)self->ep_buf); + } + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_CUR: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_LEN: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); + uint16_t len = sizeof(video_probe_and_commit_control_t); + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + case VIDEO_REQUEST_GET_INFO: + if (stage == CONTROL_STAGE_SETUP) + { + TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); + } + return VIDEO_ERROR_NONE; + + default: break; + } + break; + + case VIDEO_VS_CTL_STILL_PROBE: + case VIDEO_VS_CTL_STILL_COMMIT: + case VIDEO_VS_CTL_STILL_IMAGE_TRIGGER: + case VIDEO_VS_CTL_GENERATE_KEY_FRAME: + case VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT: + case VIDEO_VS_CTL_SYNCH_DELAY_CONTROL: + /* TODO */ + break; + + default: break; + } + + /* Unknown/Unsupported request */ + TU_BREAKPOINT(); + return VIDEO_ERROR_INVALID_REQUEST; +} + +static int handle_video_stm_req(uint8_t rhport, uint8_t stage, + tusb_control_request_t const *request, + uint_fast8_t stm_idx) +{ + switch (request->bmRequestType_bit.type) { + case TUSB_REQ_TYPE_STANDARD: + return handle_video_stm_std_req(rhport, stage, request, stm_idx); + + case TUSB_REQ_TYPE_CLASS: + if (TU_U16_HIGH(request->wIndex)) return VIDEO_ERROR_INVALID_REQUEST; + return handle_video_stm_cs_req(rhport, stage, request, stm_idx); + + default: return VIDEO_ERROR_INVALID_REQUEST; + } + return VIDEO_ERROR_UNKNOWN; +} + +//--------------------------------------------------------------------+ +// APPLICATION API +//--------------------------------------------------------------------+ + +bool tud_video_n_connected(uint_fast8_t ctl_idx) +{ + TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); + videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, 0); + if (stm) return true; + return false; +} + +bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) +{ + TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); + TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); + videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); + if (!stm || !stm->desc.ep[0]) return false; + return true; +} + +bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize) +{ + TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); + TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); + if (!buffer || !bufsize) return false; + videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); + if (!stm || !stm->desc.ep[0] || stm->buffer) return false; + + /* Find EP address */ + void const *desc = _videod_itf[stm->index_vc].beg; + uint_fast8_t ep_addr = 0; + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { + uint_fast16_t ofs_ep = stm->desc.ep[i]; + if (!ofs_ep) continue; + ep_addr = _desc_ep_addr(desc + ofs_ep); + break; + } + if (!ep_addr) return false; + + TU_VERIFY( usbd_edpt_claim(0, ep_addr)); + /* update the packet header */ + tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; + hdr->FrameID ^= 1; + hdr->EndOfFrame = 0; + /* update the packet data */ + stm->buffer = (uint8_t*)buffer; + stm->bufsize = bufsize; + uint_fast16_t pkt_len = _prepare_in_payload(stm); + TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm->ep_buf, pkt_len), 0); + return true; +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void videod_init(void) +{ + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { + videod_interface_t* ctl = &_videod_itf[i]; + tu_memclr(ctl, sizeof(*ctl)); + } + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { + videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; + tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); + } +} + +void videod_reset(uint8_t rhport) +{ + (void) rhport; + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { + videod_interface_t* ctl = &_videod_itf[i]; + tu_memclr(ctl, sizeof(*ctl)); + } + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { + videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; + tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); + } +} + +uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + TU_VERIFY((TUSB_CLASS_VIDEO == itf_desc->bInterfaceClass) && + (VIDEO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass) && + (VIDEO_ITF_PROTOCOL_15 == itf_desc->bInterfaceProtocol), 0); + + /* Find available interface */ + videod_interface_t *self = NULL; + uint_fast8_t ctl_idx; + for (ctl_idx = 0; ctl_idx < CFG_TUD_VIDEO; ++ctl_idx) { + if (_videod_itf[ctl_idx].beg) continue; + self = &_videod_itf[ctl_idx]; + break; + } + TU_ASSERT(ctl_idx < CFG_TUD_VIDEO, 0); + + void const *end = (void const*)itf_desc + max_len; + self->beg = itf_desc; + self->len = max_len; + /*------------- Video Control Interface -------------*/ + TU_VERIFY(_open_vc_itf(rhport, self, 0), 0); + tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); + uint_fast8_t bInCollection = vc->ctl.bInCollection; + /* Find the end of the video interface descriptor */ + void const *cur = _next_desc_itf(itf_desc, end); + for (uint_fast8_t stm_idx = 0; stm_idx < bInCollection; ++stm_idx) { + videod_streaming_interface_t *stm = NULL; + /* find free streaming interface handle */ + for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { + if (_videod_streaming_itf[i].desc.beg) continue; + stm = &_videod_streaming_itf[i]; + self->stm[stm_idx] = i; + break; + } + TU_ASSERT(stm, 0); + stm->index_vc = ctl_idx; + stm->index_vs = stm_idx; + stm->desc.beg = (uintptr_t)cur - (uintptr_t)itf_desc; + cur = _next_desc_itf(cur, end); + stm->desc.end = (uintptr_t)cur - (uintptr_t)itf_desc; + } + self->len = (uintptr_t)cur - (uintptr_t)itf_desc; + return (uintptr_t)cur - (uintptr_t)itf_desc; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + int err; + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + uint_fast8_t itfnum = tu_u16_low(request->wIndex); + + /* Identify which control interface to use */ + uint_fast8_t itf; + for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) { + void const *desc = _videod_itf[itf].beg; + if (!desc) continue; + if (itfnum == _desc_itfnum(desc)) break; + } + + if (itf < CFG_TUD_VIDEO) { + err = handle_video_ctl_req(rhport, stage, request, itf); + _videod_itf[itf].error_code = (uint8_t)err; + if (err) return false; + return true; + } + + /* Identify which streaming interface to use */ + for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { + videod_streaming_interface_t *stm = &_videod_streaming_itf[itf]; + if (!stm->desc.beg) continue; + void const *desc = _videod_itf[stm->index_vc].beg; + if (itfnum == _desc_itfnum(desc + stm->desc.beg)) break; + } + + if (itf < CFG_TUD_VIDEO_STREAMING) { + err = handle_video_stm_req(rhport, stage, request, itf); + _videod_streaming_itf[itf].error_code = (uint8_t)err; + if (err) return false; + return true; + } + return false; +} + +bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void)result; (void)xferred_bytes; + + /* find streaming handle */ + uint_fast8_t itf; + videod_interface_t *ctl; + videod_streaming_interface_t *stm; + for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { + stm = &_videod_streaming_itf[itf]; + uint_fast16_t const ep_ofs = stm->desc.ep[0]; + if (!ep_ofs) continue; + ctl = &_videod_itf[stm->index_vc]; + void const *desc = ctl->beg; + if (ep_addr == _desc_ep_addr(desc + ep_ofs)) break; + } + + TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING); + if (stm->offset < stm->bufsize) { + /* Claim the endpoint */ + TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0); + uint_fast16_t pkt_len = _prepare_in_payload(stm); + TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm->ep_buf, pkt_len), 0); + } else { + stm->buffer = NULL; + stm->bufsize = 0; + stm->offset = 0; + if (tud_video_frame_xfer_complete_cb) { + tud_video_frame_xfer_complete_cb(stm->index_vc, stm->index_vs); + } + } + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h new file mode 100644 index 000000000..ee2fcb9d5 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h @@ -0,0 +1,97 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2021 Koji KITAYAMA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_VIDEO_DEVICE_H_ +#define TUSB_VIDEO_DEVICE_H_ + +#include "common/tusb_common.h" +#include "video.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application API (Multiple Ports) +// CFG_TUD_VIDEO > 1 +//--------------------------------------------------------------------+ + +/** Return true if streaming + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index */ +bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); + +/** Transfer a frame + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index + * @param[in] buffer Frame buffer. The caller must not use this buffer until the operation is completed. + * @param[in] bufsize Byte size of the frame buffer */ +bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize); + +/*------------- Optional callbacks -------------*/ +/** Invoked when compeletion of a frame transfer + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index */ +TU_ATTR_WEAK void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +/** Invoked when SET_POWER_MODE request received + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index + * @return video_error_code_t */ +TU_ATTR_WEAK int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod); + +/** Invoked when VS_COMMIT_CONTROL(SET_CUR) request received + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index + * @param[in] parameters Video streaming parameters + * @return video_error_code_t */ +TU_ATTR_WEAK int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, + video_probe_and_commit_control_t const *parameters); + +//--------------------------------------------------------------------+ +// INTERNAL USBD-CLASS DRIVER API +//--------------------------------------------------------------------+ +void videod_init (void); +void videod_reset (uint8_t rhport); +uint16_t videod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool videod_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h new file mode 100644 index 000000000..9b9e2b007 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h @@ -0,0 +1,406 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_COMMON_H_ +#define _TUSB_COMMON_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Macros Helper +//--------------------------------------------------------------------+ +#define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) +#define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) ) +#define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) ) + +#define TU_U16_HIGH(_u16) ((uint8_t) (((_u16) >> 8) & 0x00ff)) +#define TU_U16_LOW(_u16) ((uint8_t) ((_u16) & 0x00ff)) +#define U16_TO_U8S_BE(_u16) TU_U16_HIGH(_u16), TU_U16_LOW(_u16) +#define U16_TO_U8S_LE(_u16) TU_U16_LOW(_u16), TU_U16_HIGH(_u16) + +#define TU_U32_BYTE3(_u32) ((uint8_t) ((((uint32_t) _u32) >> 24) & 0x000000ff)) // MSB +#define TU_U32_BYTE2(_u32) ((uint8_t) ((((uint32_t) _u32) >> 16) & 0x000000ff)) +#define TU_U32_BYTE1(_u32) ((uint8_t) ((((uint32_t) _u32) >> 8) & 0x000000ff)) +#define TU_U32_BYTE0(_u32) ((uint8_t) (((uint32_t) _u32) & 0x000000ff)) // LSB + +#define U32_TO_U8S_BE(_u32) TU_U32_BYTE3(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE0(_u32) +#define U32_TO_U8S_LE(_u32) TU_U32_BYTE0(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE3(_u32) + +#define TU_BIT(n) (1UL << (n)) +#define TU_GENMASK(h, l) ( (UINT32_MAX << (l)) & (UINT32_MAX >> (31 - (h))) ) + +//--------------------------------------------------------------------+ +// Includes +//--------------------------------------------------------------------+ + +// Standard Headers +#include +#include +#include +#include +#include + +// Tinyusb Common Headers +#include "tusb_option.h" +#include "tusb_compiler.h" +#include "tusb_verify.h" +#include "tusb_types.h" + +#include "tusb_error.h" // TODO remove +#include "tusb_timeout.h" // TODO remove + +//--------------------------------------------------------------------+ +// Internal Helper used by Host and Device Stack +//--------------------------------------------------------------------+ + +// Check if endpoint descriptor is valid per USB specs +bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); + +// Bind all endpoint of a interface descriptor to class driver +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); + +// Calculate total length of n interfaces (depending on IAD) +uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); + +//--------------------------------------------------------------------+ +// Internal Inline Functions +//--------------------------------------------------------------------+ + +//------------- Mem -------------// +#define tu_memclr(buffer, size) memset((buffer), 0, (size)) +#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) + +//------------- Bytes -------------// +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) +{ + return ( ((uint32_t) b3) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b1) << 8) | b0; +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) +{ + return (uint16_t) ((((uint16_t) high) << 8) | low); +} + +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte3(uint32_t ui32) { return TU_U32_BYTE3(ui32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte2(uint32_t ui32) { return TU_U32_BYTE2(ui32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte1(uint32_t ui32) { return TU_U32_BYTE1(ui32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte0(uint32_t ui32) { return TU_U32_BYTE0(ui32); } + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u32_high16(uint32_t ui32) { return (uint16_t) (ui32 >> 16); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u32_low16 (uint32_t ui32) { return (uint16_t) (ui32 & 0x0000ffffu); } + +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t ui16) { return TU_U16_HIGH(ui16); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t ui16) { return TU_U16_LOW(ui16); } + +//------------- Bits -------------// +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_clear(uint32_t value, uint8_t pos) { return value & (~TU_BIT(pos)); } +TU_ATTR_ALWAYS_INLINE static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value & TU_BIT(pos)) ? true : false; } + +//------------- Min -------------// +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_min8 (uint8_t x, uint8_t y ) { return (x < y) ? x : y; } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_min32 (uint32_t x, uint32_t y) { return (x < y) ? x : y; } + +//------------- Max -------------// +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_max8 (uint8_t x, uint8_t y ) { return (x > y) ? x : y; } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_max16 (uint16_t x, uint16_t y) { return (x > y) ? x : y; } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; } + +//------------- Align -------------// +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment) +{ + return value & ((uint32_t) ~(alignment-1)); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } + +//------------- Mathematics -------------// +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return (v + d -1)/d; } + +/// inclusive range checking TODO remove +TU_ATTR_ALWAYS_INLINE static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) +{ + return (lower <= value) && (value <= upper); +} + +// log2 of a value is its MSB's position +// TODO use clz TODO remove +static inline uint8_t tu_log2(uint32_t value) +{ + uint8_t result = 0; + while (value >>= 1) { result++; } + return result; +} + +//------------- Unaligned Access -------------// +#if TUP_ARCH_STRICT_ALIGN + +// Rely on compiler to generate correct code for unaligned access +typedef struct { uint16_t val; } TU_ATTR_PACKED tu_unaligned_uint16_t; +typedef struct { uint32_t val; } TU_ATTR_PACKED tu_unaligned_uint32_t; + +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) +{ + tu_unaligned_uint32_t const* ua32 = (tu_unaligned_uint32_t const*) mem; + return ua32->val; +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) +{ + tu_unaligned_uint32_t* ua32 = (tu_unaligned_uint32_t*) mem; + ua32->val = value; +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) +{ + tu_unaligned_uint16_t const* ua16 = (tu_unaligned_uint16_t const*) mem; + return ua16->val; +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) +{ + tu_unaligned_uint16_t* ua16 = (tu_unaligned_uint16_t*) mem; + ua16->val = value; +} + +#elif TUP_MCU_STRICT_ALIGN + +// MCU such as LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM although it is ARM M4. +// We have to manually pick up bytes since tu_unaligned_uint32_t will still generate unaligned code +// NOTE: volatile cast to memory to prevent compiler to optimize and generate unaligned code +// TODO Big Endian may need minor changes +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) +{ + volatile uint8_t const* buf8 = (uint8_t const*) mem; + return tu_u32(buf8[3], buf8[2], buf8[1], buf8[0]); +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) +{ + volatile uint8_t* buf8 = (uint8_t*) mem; + buf8[0] = tu_u32_byte0(value); + buf8[1] = tu_u32_byte1(value); + buf8[2] = tu_u32_byte2(value); + buf8[3] = tu_u32_byte3(value); +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) +{ + volatile uint8_t const* buf8 = (uint8_t const*) mem; + return tu_u16(buf8[1], buf8[0]); +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) +{ + volatile uint8_t* buf8 = (uint8_t*) mem; + buf8[0] = tu_u16_low(value); + buf8[1] = tu_u16_high(value); +} + + +#else + +// MCU that could access unaligned memory natively +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem) { return *((uint32_t const *) mem); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem) { return *((uint16_t const *) mem); } + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32 (void* mem, uint32_t value ) { *((uint32_t*) mem) = value; } +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, uint16_t value ) { *((uint16_t*) mem) = value; } + +#endif + +// To be removed +//------------- Binary constant -------------// +#if defined(__GNUC__) && !defined(__CC_ARM) + +#define TU_BIN8(x) ((uint8_t) (0b##x)) +#define TU_BIN16(b1, b2) ((uint16_t) (0b##b1##b2)) +#define TU_BIN32(b1, b2, b3, b4) ((uint32_t) (0b##b1##b2##b3##b4)) + +#else + +// internal macro of B8, B16, B32 +#define _B8__(x) (((x&0x0000000FUL)?1:0) \ + +((x&0x000000F0UL)?2:0) \ + +((x&0x00000F00UL)?4:0) \ + +((x&0x0000F000UL)?8:0) \ + +((x&0x000F0000UL)?16:0) \ + +((x&0x00F00000UL)?32:0) \ + +((x&0x0F000000UL)?64:0) \ + +((x&0xF0000000UL)?128:0)) + +#define TU_BIN8(d) ((uint8_t) _B8__(0x##d##UL)) +#define TU_BIN16(dmsb,dlsb) (((uint16_t)TU_BIN8(dmsb)<<8) + TU_BIN8(dlsb)) +#define TU_BIN32(dmsb,db2,db3,dlsb) \ + (((uint32_t)TU_BIN8(dmsb)<<24) \ + + ((uint32_t)TU_BIN8(db2)<<16) \ + + ((uint32_t)TU_BIN8(db3)<<8) \ + + TU_BIN8(dlsb)) +#endif + +//--------------------------------------------------------------------+ +// Debug Function +//--------------------------------------------------------------------+ + +// CFG_TUSB_DEBUG for debugging +// 0 : no debug +// 1 : print error +// 2 : print warning +// 3 : print info +#if CFG_TUSB_DEBUG + +void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); + +#ifdef CFG_TUSB_DEBUG_PRINTF + extern int CFG_TUSB_DEBUG_PRINTF(const char *format, ...); + #define tu_printf CFG_TUSB_DEBUG_PRINTF +#else + #define tu_printf printf +#endif + +static inline +void tu_print_var(uint8_t const* buf, uint32_t bufsize) +{ + for(uint32_t i=0; i= 2 + #define TU_LOG2 TU_LOG1 + #define TU_LOG2_MEM TU_LOG1_MEM + #define TU_LOG2_VAR TU_LOG1_VAR + #define TU_LOG2_INT TU_LOG1_INT + #define TU_LOG2_HEX TU_LOG1_HEX +#endif + +// Log Level 3: Info +#if CFG_TUSB_DEBUG >= 3 + #define TU_LOG3 TU_LOG1 + #define TU_LOG3_MEM TU_LOG1_MEM + #define TU_LOG3_VAR TU_LOG1_VAR + #define TU_LOG3_INT TU_LOG1_INT + #define TU_LOG3_HEX TU_LOG1_HEX +#endif + +typedef struct +{ + uint32_t key; + const char* data; +} tu_lookup_entry_t; + +typedef struct +{ + uint16_t count; + tu_lookup_entry_t const* items; +} tu_lookup_table_t; + +static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) +{ + static char not_found[11]; + + for(uint16_t i=0; icount; i++) + { + if (p_table->items[i].key == key) return p_table->items[i].data; + } + + // not found return the key value in hex + sprintf(not_found, "0x%08lX", (unsigned long) key); + + return not_found; +} + +#endif // CFG_TUSB_DEBUG + +#ifndef TU_LOG +#define TU_LOG(n, ...) +#define TU_LOG_MEM(n, ...) +#define TU_LOG_VAR(n, ...) +#define TU_LOG_INT(n, ...) +#define TU_LOG_HEX(n, ...) +#define TU_LOG_LOCATION() +#define TU_LOG_FAILED() +#endif + +// TODO replace all TU_LOGn with TU_LOG(n) + +#define TU_LOG0(...) +#define TU_LOG0_MEM(...) +#define TU_LOG0_VAR(...) +#define TU_LOG0_INT(...) +#define TU_LOG0_HEX(...) + + +#ifndef TU_LOG1 + #define TU_LOG1(...) + #define TU_LOG1_MEM(...) + #define TU_LOG1_VAR(...) + #define TU_LOG1_INT(...) + #define TU_LOG1_HEX(...) +#endif + +#ifndef TU_LOG2 + #define TU_LOG2(...) + #define TU_LOG2_MEM(...) + #define TU_LOG2_VAR(...) + #define TU_LOG2_INT(...) + #define TU_LOG2_HEX(...) +#endif + +#ifndef TU_LOG3 + #define TU_LOG3(...) + #define TU_LOG3_MEM(...) + #define TU_LOG3_VAR(...) + #define TU_LOG3_INT(...) + #define TU_LOG3_HEX(...) +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_COMMON_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h new file mode 100644 index 000000000..d3284c62a --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h @@ -0,0 +1,258 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup Group_Common + * \defgroup Group_Compiler Compiler + * \brief Group_Compiler brief + * @{ */ + +#ifndef _TUSB_COMPILER_H_ +#define _TUSB_COMPILER_H_ + +#define TU_TOKEN(x) x +#define TU_STRING(x) #x ///< stringify without expand +#define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify + +#define TU_STRCAT(a, b) a##b ///< concat without expand +#define TU_STRCAT3(a, b, c) a##b##c ///< concat without expand + +#define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat +#define TU_XSTRCAT3(a, b, c) TU_STRCAT3(a, b, c) ///< expand then concat 3 tokens + +#define TU_INCLUDE_PATH(_dir,_file) TU_XSTRING( TU_TOKEN(_dir)TU_TOKEN(_file) ) + +#if defined __COUNTER__ && __COUNTER__ != __COUNTER__ + #define _TU_COUNTER_ __COUNTER__ +#else + #define _TU_COUNTER_ __LINE__ +#endif + +// Compile-time Assert +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define TU_VERIFY_STATIC _Static_assert +#elif defined (__cplusplus) && __cplusplus >= 201103L + #define TU_VERIFY_STATIC static_assert +#elif defined(__CCRX__) + #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0]; +#else + #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } +#endif + +// for declaration of reserved field, make use of _TU_COUNTER_ +#define TU_RESERVED TU_XSTRCAT(reserved, _TU_COUNTER_) + +#define TU_LITTLE_ENDIAN (0x12u) +#define TU_BIG_ENDIAN (0x21u) + +/*------------------------------------------------------------------*/ +/* Count number of arguments of __VA_ARGS__ + * - reference https://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments + * - _GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th) + * - _RSEQ_N() is reverse sequential to N to add padding to have + * Nth position is the same as the number of arguments + * - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma) + *------------------------------------------------------------------*/ +#define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N()) + +#define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__) +#define _GET_NTH_ARG( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ + _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ + _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ + _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ + _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ + _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ + _61,_62,_63,N,...) N +#define _RSEQ_N() \ + 62,61,60, \ + 59,58,57,56,55,54,53,52,51,50, \ + 49,48,47,46,45,44,43,42,41,40, \ + 39,38,37,36,35,34,33,32,31,30, \ + 29,28,27,26,25,24,23,22,21,20, \ + 19,18,17,16,15,14,13,12,11,10, \ + 9,8,7,6,5,4,3,2,1,0 + +// Apply an macro X to each of the arguments with an separated of choice +#define TU_ARGS_APPLY(_X, _s, ...) TU_XSTRCAT(_TU_ARGS_APPLY_, TU_ARGS_NUM(__VA_ARGS__))(_X, _s, __VA_ARGS__) + +#define _TU_ARGS_APPLY_1(_X, _s, _a1) _X(_a1) +#define _TU_ARGS_APPLY_2(_X, _s, _a1, _a2) _X(_a1) _s _X(_a2) +#define _TU_ARGS_APPLY_3(_X, _s, _a1, _a2, _a3) _X(_a1) _s _TU_ARGS_APPLY_2(_X, _s, _a2, _a3) +#define _TU_ARGS_APPLY_4(_X, _s, _a1, _a2, _a3, _a4) _X(_a1) _s _TU_ARGS_APPLY_3(_X, _s, _a2, _a3, _a4) +#define _TU_ARGS_APPLY_5(_X, _s, _a1, _a2, _a3, _a4, _a5) _X(_a1) _s _TU_ARGS_APPLY_4(_X, _s, _a2, _a3, _a4, _a5) +#define _TU_ARGS_APPLY_6(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6) _X(_a1) _s _TU_ARGS_APPLY_5(_X, _s, _a2, _a3, _a4, _a5, _a6) +#define _TU_ARGS_APPLY_7(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7) _X(_a1) _s _TU_ARGS_APPLY_6(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7) +#define _TU_ARGS_APPLY_8(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) _X(_a1) _s _TU_ARGS_APPLY_7(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7, _a8) + +//--------------------------------------------------------------------+ +// Compiler porting with Attribute and Endian +//--------------------------------------------------------------------+ + +// TODO refactor since __attribute__ is supported across many compiler +#if defined(__GNUC__) + #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) + #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) + #define TU_ATTR_PACKED __attribute__ ((packed)) + #define TU_ATTR_WEAK __attribute__ ((weak)) + #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used + #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused + #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used + + #define TU_ATTR_PACKED_BEGIN + #define TU_ATTR_PACKED_END + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN + #define TU_ATTR_BIT_FIELD_ORDER_END + + // Endian conversion use well-known host to network (big endian) naming + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #endif + + #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) + #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) + + // List of obsolete callback function that is renamed and should not be defined. + // Put it here since only gcc support this pragma + #pragma GCC poison tud_vendor_control_request_cb + +#elif defined(__TI_COMPILER_VERSION__) + #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) + #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) + #define TU_ATTR_PACKED __attribute__ ((packed)) + #define TU_ATTR_WEAK __attribute__ ((weak)) + #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used + #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused + #define TU_ATTR_USED __attribute__ ((used)) + + #define TU_ATTR_PACKED_BEGIN + #define TU_ATTR_PACKED_END + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN + #define TU_ATTR_BIT_FIELD_ORDER_END + + // __BYTE_ORDER is defined in the TI ARM compiler, but not MSP430 (which is little endian) + #if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) || defined(__MSP430__) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #endif + + #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) + #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) + +#elif defined(__ICCARM__) + #include + #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) + #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) + #define TU_ATTR_PACKED __attribute__ ((packed)) + #define TU_ATTR_WEAK __attribute__ ((weak)) + #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used + #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused + #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used + + #define TU_ATTR_PACKED_BEGIN + #define TU_ATTR_PACKED_END + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN + #define TU_ATTR_BIT_FIELD_ORDER_END + + // Endian conversion use well-known host to network (big endian) naming + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #endif + + #define TU_BSWAP16(u16) (__iar_builtin_REV16(u16)) + #define TU_BSWAP32(u32) (__iar_builtin_REV(u32)) + +#elif defined(__CCRX__) + #define TU_ATTR_ALIGNED(Bytes) + #define TU_ATTR_SECTION(sec_name) + #define TU_ATTR_PACKED + #define TU_ATTR_WEAK + #define TU_ATTR_ALWAYS_INLINE + #define TU_ATTR_DEPRECATED(mess) + #define TU_ATTR_UNUSED + #define TU_ATTR_USED + + #define TU_ATTR_PACKED_BEGIN _Pragma("pack") + #define TU_ATTR_PACKED_END _Pragma("packoption") + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") + #define TU_ATTR_BIT_FIELD_ORDER_END _Pragma("bit_order") + + // Endian conversion use well-known host to network (big endian) naming + #if defined(__LIT) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #endif + + #define TU_BSWAP16(u16) ((unsigned short)_builtin_revw((unsigned long)u16)) + #define TU_BSWAP32(u32) (_builtin_revl(u32)) + +#else + #error "Compiler attribute porting is required" +#endif + +#if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN) + + #define tu_htons(u16) (TU_BSWAP16(u16)) + #define tu_ntohs(u16) (TU_BSWAP16(u16)) + + #define tu_htonl(u32) (TU_BSWAP32(u32)) + #define tu_ntohl(u32) (TU_BSWAP32(u32)) + + #define tu_htole16(u16) (u16) + #define tu_le16toh(u16) (u16) + + #define tu_htole32(u32) (u32) + #define tu_le32toh(u32) (u32) + +#elif (TU_BYTE_ORDER == TU_BIG_ENDIAN) + + #define tu_htons(u16) (u16) + #define tu_ntohs(u16) (u16) + + #define tu_htonl(u32) (u32) + #define tu_ntohl(u32) (u32) + + #define tu_htole16(u16) (TU_BSWAP16(u16)) + #define tu_le16toh(u16) (TU_BSWAP16(u16)) + + #define tu_htole32(u32) (TU_BSWAP32(u32)) + #define tu_le32toh(u32) (TU_BSWAP32(u32)) + +#else + #error Byte order is undefined +#endif + +#endif /* _TUSB_COMPILER_H_ */ + +/// @} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h new file mode 100644 index 000000000..d7ad8c318 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h @@ -0,0 +1,75 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup Group_Common + * \defgroup Group_Error Error Codes + * @{ */ + +#ifndef _TUSB_ERRORS_H_ +#define _TUSB_ERRORS_H_ + +#include "tusb_option.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define ERROR_ENUM(x) x, +#define ERROR_STRING(x) #x, + +#define ERROR_TABLE(ENTRY) \ + ENTRY(TUSB_ERROR_NONE )\ + ENTRY(TUSB_ERROR_INVALID_PARA )\ + ENTRY(TUSB_ERROR_DEVICE_NOT_READY )\ + ENTRY(TUSB_ERROR_INTERFACE_IS_BUSY )\ + ENTRY(TUSB_ERROR_HCD_OPEN_PIPE_FAILED )\ + ENTRY(TUSB_ERROR_OSAL_TIMEOUT )\ + ENTRY(TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED )\ + ENTRY(TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED )\ + ENTRY(TUSB_ERROR_NOT_SUPPORTED )\ + ENTRY(TUSB_ERROR_NOT_ENOUGH_MEMORY )\ + ENTRY(TUSB_ERROR_FAILED )\ + +/// \brief Error Code returned +/// TODO obsolete and to be remove +typedef enum +{ + ERROR_TABLE(ERROR_ENUM) + TUSB_ERROR_COUNT +}tusb_error_t; + +#if CFG_TUSB_DEBUG +/// Enum to String for debugging purposes. Only available if \ref CFG_TUSB_DEBUG > 0 +extern char const* const tusb_strerr[TUSB_ERROR_COUNT]; +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_ERRORS_H_ */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c new file mode 100644 index 000000000..183c9c6fc --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c @@ -0,0 +1,1007 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Reinhard Panhuber - rework to unmasked pointers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "osal/osal.h" +#include "tusb_fifo.h" + +// Supress IAR warning +// Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement +#if defined(__ICCARM__) +#pragma diag_suppress = Pa082 +#endif + +// implement mutex lock and unlock +#if CFG_FIFO_MUTEX + +static inline void _ff_lock(tu_fifo_mutex_t mutex) +{ + if (mutex) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); +} + +static inline void _ff_unlock(tu_fifo_mutex_t mutex) +{ + if (mutex) osal_mutex_unlock(mutex); +} + +#else + +#define _ff_lock(_mutex) +#define _ff_unlock(_mutex) + +#endif + +/** \enum tu_fifo_copy_mode_t + * \brief Write modes intended to allow special read and write functions to be able to + * copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others + */ +typedef enum +{ + TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode + TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO +} tu_fifo_copy_mode_t; + +bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) +{ + if (depth > 0x8000) return false; // Maximum depth is 2^15 items + + _ff_lock(f->mutex_wr); + _ff_lock(f->mutex_rd); + + f->buffer = (uint8_t*) buffer; + f->depth = depth; + f->item_size = item_size; + f->overwritable = overwritable; + + // Limit index space to 2*depth - this allows for a fast "modulo" calculation + // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable + // only if overflow happens once (important for unsupervised DMA applications) + f->max_pointer_idx = 2*depth - 1; + f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; + + f->rd_idx = f->wr_idx = 0; + + _ff_unlock(f->mutex_wr); + _ff_unlock(f->mutex_rd); + + return true; +} + +// Static functions are intended to work on local variables +static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) +{ + while ( idx >= depth) idx -= depth; + return idx; +} + +// Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address +// Code adapted from dcd_synopsis.c +// TODO generalize with configurable 1 byte or 4 byte each read +static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t len) +{ + volatile const uint32_t * rx_fifo = (volatile const uint32_t *) app_buf; + + // Reading full available 32 bit words from const app address + uint16_t full_words = len >> 2; + while(full_words--) + { + tu_unaligned_write32(ff_buf, *rx_fifo); + ff_buf += 4; + } + + // Read the remaining 1-3 bytes from const app address + uint8_t const bytes_rem = len & 0x03; + if ( bytes_rem ) + { + uint32_t tmp32 = *rx_fifo; + memcpy(ff_buf, &tmp32, bytes_rem); + } +} + +// Intended to be used to write to hardware USB FIFO in e.g. STM32 +// where all data is written to a constant address in full word copies +static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t len) +{ + volatile uint32_t * tx_fifo = (volatile uint32_t *) app_buf; + + // Pushing full available 32 bit words to const app address + uint16_t full_words = len >> 2; + while(full_words--) + { + *tx_fifo = tu_unaligned_read32(ff_buf); + ff_buf += 4; + } + + // Write the remaining 1-3 bytes into const app address + uint8_t const bytes_rem = len & 0x03; + if ( bytes_rem ) + { + uint32_t tmp32 = 0; + memcpy(&tmp32, ff_buf, bytes_rem); + + *tx_fifo = tmp32; + } +} + +// send one item to FIFO WITHOUT updating write pointer +static inline void _ff_push(tu_fifo_t* f, void const * app_buf, uint16_t rel) +{ + memcpy(f->buffer + (rel * f->item_size), app_buf, f->item_size); +} + +// send n items to FIFO WITHOUT updating write pointer +static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t rel, tu_fifo_copy_mode_t copy_mode) +{ + uint16_t const nLin = f->depth - rel; + uint16_t const nWrap = n - nLin; + + uint16_t nLin_bytes = nLin * f->item_size; + uint16_t nWrap_bytes = nWrap * f->item_size; + + // current buffer of fifo + uint8_t* ff_buf = f->buffer + (rel * f->item_size); + + switch (copy_mode) + { + case TU_FIFO_COPY_INC: + if(n <= nLin) + { + // Linear only + memcpy(ff_buf, app_buf, n*f->item_size); + } + else + { + // Wrap around + + // Write data to linear part of buffer + memcpy(ff_buf, app_buf, nLin_bytes); + + // Write data wrapped around + memcpy(f->buffer, ((uint8_t const*) app_buf) + nLin_bytes, nWrap_bytes); + } + break; + + case TU_FIFO_COPY_CST_FULL_WORDS: + // Intended for hardware buffers from which it can be read word by word only + if(n <= nLin) + { + // Linear only + _ff_push_const_addr(ff_buf, app_buf, n*f->item_size); + } + else + { + // Wrap around case + + // Write full words to linear part of buffer + uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; + _ff_push_const_addr(ff_buf, app_buf, nLin_4n_bytes); + ff_buf += nLin_4n_bytes; + + // There could be odd 1-3 bytes before the wrap-around boundary + volatile const uint32_t * rx_fifo = (volatile const uint32_t *) app_buf; + uint8_t rem = nLin_bytes & 0x03; + if (rem > 0) + { + uint8_t remrem = tu_min16(nWrap_bytes, 4-rem); + nWrap_bytes -= remrem; + + uint32_t tmp32 = *rx_fifo; + uint8_t * src_u8 = ((uint8_t *) &tmp32); + + // Write 1-3 bytes before wrapped boundary + while(rem--) *ff_buf++ = *src_u8++; + + // Read more bytes to beginning to complete a word + ff_buf = f->buffer; + while(remrem--) *ff_buf++ = *src_u8++; + } + else + { + ff_buf = f->buffer; // wrap around to beginning + } + + // Write data wrapped part + if (nWrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, nWrap_bytes); + } + break; + } +} + +// get one item from FIFO WITHOUT updating read pointer +static inline void _ff_pull(tu_fifo_t* f, void * app_buf, uint16_t rel) +{ + memcpy(app_buf, f->buffer + (rel * f->item_size), f->item_size); +} + +// get n items from FIFO WITHOUT updating read pointer +static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rel, tu_fifo_copy_mode_t copy_mode) +{ + uint16_t const nLin = f->depth - rel; + uint16_t const nWrap = n - nLin; // only used if wrapped + + uint16_t nLin_bytes = nLin * f->item_size; + uint16_t nWrap_bytes = nWrap * f->item_size; + + // current buffer of fifo + uint8_t* ff_buf = f->buffer + (rel * f->item_size); + + switch (copy_mode) + { + case TU_FIFO_COPY_INC: + if ( n <= nLin ) + { + // Linear only + memcpy(app_buf, ff_buf, n*f->item_size); + } + else + { + // Wrap around + + // Read data from linear part of buffer + memcpy(app_buf, ff_buf, nLin_bytes); + + // Read data wrapped part + memcpy((uint8_t*) app_buf + nLin_bytes, f->buffer, nWrap_bytes); + } + break; + + case TU_FIFO_COPY_CST_FULL_WORDS: + if ( n <= nLin ) + { + // Linear only + _ff_pull_const_addr(app_buf, ff_buf, n*f->item_size); + } + else + { + // Wrap around case + + // Read full words from linear part of buffer + uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; + _ff_pull_const_addr(app_buf, ff_buf, nLin_4n_bytes); + ff_buf += nLin_4n_bytes; + + // There could be odd 1-3 bytes before the wrap-around boundary + volatile uint32_t * tx_fifo = (volatile uint32_t *) app_buf; + uint8_t rem = nLin_bytes & 0x03; + if (rem > 0) + { + uint8_t remrem = tu_min16(nWrap_bytes, 4-rem); + nWrap_bytes -= remrem; + + uint32_t tmp32=0; + uint8_t * dst_u8 = (uint8_t *)&tmp32; + + // Read 1-3 bytes before wrapped boundary + while(rem--) *dst_u8++ = *ff_buf++; + + // Read more bytes from beginning to complete a word + ff_buf = f->buffer; + while(remrem--) *dst_u8++ = *ff_buf++; + + *tx_fifo = tmp32; + } + else + { + ff_buf = f->buffer; // wrap around to beginning + } + + // Read data wrapped part + if (nWrap_bytes > 0) _ff_pull_const_addr(app_buf, ff_buf, nWrap_bytes); + } + break; + + default: break; + } +} + +// Advance an absolute pointer +static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) +{ + // We limit the index space of p such that a correct wrap around happens + // Check for a wrap around or if we are in unused index space - This has to be checked first!! + // We are exploiting the wrap around to the correct index + if ((p > (uint16_t)(p + offset)) || ((uint16_t)(p + offset) > f->max_pointer_idx)) + { + p = (p + offset) + f->non_used_index_space; + } + else + { + p += offset; + } + return p; +} + +// Backward an absolute pointer +static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) +{ + // We limit the index space of p such that a correct wrap around happens + // Check for a wrap around or if we are in unused index space - This has to be checked first!! + // We are exploiting the wrap around to the correct index + if ((p < (uint16_t)(p - offset)) || ((uint16_t)(p - offset) > f->max_pointer_idx)) + { + p = (p - offset) - f->non_used_index_space; + } + else + { + p -= offset; + } + return p; +} + +// get relative from absolute pointer +static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p) +{ + return _ff_mod(p, f->depth); +} + +// Works on local copies of w and r - return only the difference and as such can be used to determine an overflow +static inline uint16_t _tu_fifo_count(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) +{ + uint16_t cnt = wAbs-rAbs; + + // In case we have non-power of two depth we need a further modification + if (rAbs > wAbs) cnt -= f->non_used_index_space; + + return cnt; +} + +// Works on local copies of w and r +static inline bool _tu_fifo_empty(uint16_t wAbs, uint16_t rAbs) +{ + return wAbs == rAbs; +} + +// Works on local copies of w and r +static inline bool _tu_fifo_full(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) +{ + return (_tu_fifo_count(f, wAbs, rAbs) == f->depth); +} + +// Works on local copies of w and r +// BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" +// Only one overflow is allowed for this function to work e.g. if depth = 100, you must not +// write more than 2*depth-1 items in one rush without updating write pointer. Otherwise +// write pointer wraps and you pointer states are messed up. This can only happen if you +// use DMAs, write functions do not allow such an error. +static inline bool _tu_fifo_overflowed(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) +{ + return (_tu_fifo_count(f, wAbs, rAbs) > f->depth); +} + +// Works on local copies of w +// For more details see _tu_fifo_overflow()! +static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) +{ + f->rd_idx = backward_pointer(f, wAbs, f->depth); +} + +// Works on local copies of w and r +// Must be protected by mutexes since in case of an overflow read pointer gets modified +static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) +{ + uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); + + // Check overflow and correct if required + if (cnt > f->depth) + { + _tu_fifo_correct_read_pointer(f, wAbs); + cnt = f->depth; + } + + // Skip beginning of buffer + if (cnt == 0) return false; + + uint16_t rRel = get_relative_pointer(f, rAbs); + + // Peek data + _ff_pull(f, p_buffer, rRel); + + return true; +} + +// Works on local copies of w and r +// Must be protected by mutexes since in case of an overflow read pointer gets modified +static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) +{ + uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); + + // Check overflow and correct if required + if (cnt > f->depth) + { + _tu_fifo_correct_read_pointer(f, wAbs); + rAbs = f->rd_idx; + cnt = f->depth; + } + + // Skip beginning of buffer + if (cnt == 0) return 0; + + // Check if we can read something at and after offset - if too less is available we read what remains + if (cnt < n) n = cnt; + + uint16_t rRel = get_relative_pointer(f, rAbs); + + // Peek data + _ff_pull_n(f, p_buffer, n, rRel, copy_mode); + + return n; +} + +// Works on local copies of w and r +static inline uint16_t _tu_fifo_remaining(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) +{ + return f->depth - _tu_fifo_count(f, wAbs, rAbs); +} + +static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu_fifo_copy_mode_t copy_mode) +{ + if ( n == 0 ) return 0; + + _ff_lock(f->mutex_wr); + + uint16_t w = f->wr_idx, r = f->rd_idx; + uint8_t const* buf8 = (uint8_t const*) data; + + if (!f->overwritable) + { + // Not overwritable limit up to full + n = tu_min16(n, _tu_fifo_remaining(f, w, r)); + } + else if (n >= f->depth) + { + // Only copy last part + buf8 = buf8 + (n - f->depth) * f->item_size; + n = f->depth; + + // We start writing at the read pointer's position since we fill the complete + // buffer and we do not want to modify the read pointer within a write function! + // This would end up in a race condition with read functions! + w = r; + } + + uint16_t wRel = get_relative_pointer(f, w); + + // Write data + _ff_push_n(f, buf8, n, wRel, copy_mode); + + // Advance pointer + f->wr_idx = advance_pointer(f, w, n); + + _ff_unlock(f->mutex_wr); + + return n; +} + +static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) +{ + _ff_lock(f->mutex_rd); + + // Peek the data + // f->rd_idx might get modified in case of an overflow so we can not use a local variable + n = _tu_fifo_peek_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); + + // Advance read pointer + f->rd_idx = advance_pointer(f, f->rd_idx, n); + + _ff_unlock(f->mutex_rd); + return n; +} + +/******************************************************************************/ +/*! + @brief Get number of items in FIFO. + + As this function only reads the read and write pointers once, this function is + reentrant and thus thread and ISR save without any mutexes. In case an + overflow occurred, this function return f.depth at maximum. Overflows are + checked and corrected for in the read functions! + + @param[in] f + Pointer to the FIFO buffer to manipulate + + @returns Number of items in FIFO + */ +/******************************************************************************/ +uint16_t tu_fifo_count(tu_fifo_t* f) +{ + return tu_min16(_tu_fifo_count(f, f->wr_idx, f->rd_idx), f->depth); +} + +/******************************************************************************/ +/*! + @brief Check if FIFO is empty. + + As this function only reads the read and write pointers once, this function is + reentrant and thus thread and ISR save without any mutexes. + + @param[in] f + Pointer to the FIFO buffer to manipulate + + @returns Number of items in FIFO + */ +/******************************************************************************/ +bool tu_fifo_empty(tu_fifo_t* f) +{ + return _tu_fifo_empty(f->wr_idx, f->rd_idx); +} + +/******************************************************************************/ +/*! + @brief Check if FIFO is full. + + As this function only reads the read and write pointers once, this function is + reentrant and thus thread and ISR save without any mutexes. + + @param[in] f + Pointer to the FIFO buffer to manipulate + + @returns Number of items in FIFO + */ +/******************************************************************************/ +bool tu_fifo_full(tu_fifo_t* f) +{ + return _tu_fifo_full(f, f->wr_idx, f->rd_idx); +} + +/******************************************************************************/ +/*! + @brief Get remaining space in FIFO. + + As this function only reads the read and write pointers once, this function is + reentrant and thus thread and ISR save without any mutexes. + + @param[in] f + Pointer to the FIFO buffer to manipulate + + @returns Number of items in FIFO + */ +/******************************************************************************/ +uint16_t tu_fifo_remaining(tu_fifo_t* f) +{ + return _tu_fifo_remaining(f, f->wr_idx, f->rd_idx); +} + +/******************************************************************************/ +/*! + @brief Check if overflow happened. + + BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" + Only one overflow is allowed for this function to work e.g. if depth = 100, you must not + write more than 2*depth-1 items in one rush without updating write pointer. Otherwise + write pointer wraps and your pointer states are messed up. This can only happen if you + use DMAs, write functions do not allow such an error. Avoid such nasty things! + + All reading functions (read, peek) check for overflows and correct read pointer on their own such + that latest items are read. + If required (e.g. for DMA use) you can also correct the read pointer by + tu_fifo_correct_read_pointer(). + + @param[in] f + Pointer to the FIFO buffer to manipulate + + @returns True if overflow happened + */ +/******************************************************************************/ +bool tu_fifo_overflowed(tu_fifo_t* f) +{ + return _tu_fifo_overflowed(f, f->wr_idx, f->rd_idx); +} + +// Only use in case tu_fifo_overflow() returned true! +void tu_fifo_correct_read_pointer(tu_fifo_t* f) +{ + _ff_lock(f->mutex_rd); + _tu_fifo_correct_read_pointer(f, f->wr_idx); + _ff_unlock(f->mutex_rd); +} + +/******************************************************************************/ +/*! + @brief Read one element out of the buffer. + + This function will return the element located at the array index of the + read pointer, and then increment the read pointer index. + This function checks for an overflow and corrects read pointer if required. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] buffer + Pointer to the place holder for data read from the buffer + + @returns TRUE if the queue is not empty + */ +/******************************************************************************/ +bool tu_fifo_read(tu_fifo_t* f, void * buffer) +{ + _ff_lock(f->mutex_rd); + + // Peek the data + // f->rd_idx might get modified in case of an overflow so we can not use a local variable + bool ret = _tu_fifo_peek(f, buffer, f->wr_idx, f->rd_idx); + + // Advance pointer + f->rd_idx = advance_pointer(f, f->rd_idx, ret); + + _ff_unlock(f->mutex_rd); + return ret; +} + +/******************************************************************************/ +/*! + @brief This function will read n elements from the array index specified by + the read pointer and increment the read index. + This function checks for an overflow and corrects read pointer if required. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] buffer + The pointer to data location + @param[in] n + Number of element that buffer can afford + + @returns number of items read from the FIFO + */ +/******************************************************************************/ +uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n) +{ + return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_INC); +} + +uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint16_t n) +{ + return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST_FULL_WORDS); +} + +/******************************************************************************/ +/*! + @brief Read one item without removing it from the FIFO. + This function checks for an overflow and corrects read pointer if required. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] offset + Position to read from in the FIFO buffer with respect to read pointer + @param[in] p_buffer + Pointer to the place holder for data read from the buffer + + @returns TRUE if the queue is not empty + */ +/******************************************************************************/ +bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) +{ + _ff_lock(f->mutex_rd); + bool ret = _tu_fifo_peek(f, p_buffer, f->wr_idx, f->rd_idx); + _ff_unlock(f->mutex_rd); + return ret; +} + +/******************************************************************************/ +/*! + @brief Read n items without removing it from the FIFO + This function checks for an overflow and corrects read pointer if required. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] p_buffer + Pointer to the place holder for data read from the buffer + @param[in] n + Number of items to peek + + @returns Number of bytes written to p_buffer + */ +/******************************************************************************/ +uint16_t tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n) +{ + _ff_lock(f->mutex_rd); + uint16_t ret = _tu_fifo_peek_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); + _ff_unlock(f->mutex_rd); + return ret; +} + +/******************************************************************************/ +/*! + @brief Write one element into the buffer. + + This function will write one element into the array index specified by + the write pointer and increment the write index. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] data + The byte to add to the FIFO + + @returns TRUE if the data was written to the FIFO (overwrittable + FIFO will always return TRUE) + */ +/******************************************************************************/ +bool tu_fifo_write(tu_fifo_t* f, const void * data) +{ + _ff_lock(f->mutex_wr); + + bool ret; + uint16_t const w = f->wr_idx; + + if ( _tu_fifo_full(f, w, f->rd_idx) && !f->overwritable ) + { + ret = false; + }else + { + uint16_t wRel = get_relative_pointer(f, w); + + // Write data + _ff_push(f, data, wRel); + + // Advance pointer + f->wr_idx = advance_pointer(f, w, 1); + + ret = true; + } + + _ff_unlock(f->mutex_wr); + + return ret; +} + +/******************************************************************************/ +/*! + @brief This function will write n elements into the array index specified by + the write pointer and increment the write index. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] data + The pointer to data to add to the FIFO + @param[in] count + Number of element + @return Number of written elements + */ +/******************************************************************************/ +uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n) +{ + return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_INC); +} + +/******************************************************************************/ +/*! + @brief This function will write n elements into the array index specified by + the write pointer and increment the write index. The source address will + not be incremented which is useful for reading from registers. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] data + The pointer to data to add to the FIFO + @param[in] count + Number of element + @return Number of written elements + */ +/******************************************************************************/ +uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t* f, const void * data, uint16_t n) +{ + return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_CST_FULL_WORDS); +} + +/******************************************************************************/ +/*! + @brief Clear the fifo read and write pointers + + @param[in] f + Pointer to the FIFO buffer to manipulate + */ +/******************************************************************************/ +bool tu_fifo_clear(tu_fifo_t *f) +{ + _ff_lock(f->mutex_wr); + _ff_lock(f->mutex_rd); + + f->rd_idx = f->wr_idx = 0; + f->max_pointer_idx = 2*f->depth-1; + f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; + + _ff_unlock(f->mutex_wr); + _ff_unlock(f->mutex_rd); + return true; +} + +/******************************************************************************/ +/*! + @brief Change the fifo mode to overwritable or not overwritable + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] overwritable + Overwritable mode the fifo is set to + */ +/******************************************************************************/ +bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) +{ + _ff_lock(f->mutex_wr); + _ff_lock(f->mutex_rd); + + f->overwritable = overwritable; + + _ff_unlock(f->mutex_wr); + _ff_unlock(f->mutex_rd); + + return true; +} + +/******************************************************************************/ +/*! + @brief Advance write pointer - intended to be used in combination with DMA. + It is possible to fill the FIFO by use of a DMA in circular mode. Within + DMA ISRs you may update the write pointer to be able to read from the FIFO. + As long as the DMA is the only process writing into the FIFO this is safe + to use. + + USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] n + Number of items the write pointer moves forward + */ +/******************************************************************************/ +void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) +{ + f->wr_idx = advance_pointer(f, f->wr_idx, n); +} + +/******************************************************************************/ +/*! + @brief Advance read pointer - intended to be used in combination with DMA. + It is possible to read from the FIFO by use of a DMA in linear mode. Within + DMA ISRs you may update the read pointer to be able to again write into the + FIFO. As long as the DMA is the only process reading from the FIFO this is + safe to use. + + USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] n + Number of items the read pointer moves forward + */ +/******************************************************************************/ +void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) +{ + f->rd_idx = advance_pointer(f, f->rd_idx, n); +} + +/******************************************************************************/ +/*! + @brief Get read info + + Returns the length and pointer from which bytes can be read in a linear manner. + This is of major interest for DMA transmissions. If returned length is zero the + corresponding pointer is invalid. + The read pointer does NOT get advanced, use tu_fifo_advance_read_pointer() to + do so! + @param[in] f + Pointer to FIFO + @param[out] *info + Pointer to struct which holds the desired infos + */ +/******************************************************************************/ +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) +{ + // Operate on temporary values in case they change in between + uint16_t w = f->wr_idx, r = f->rd_idx; + + uint16_t cnt = _tu_fifo_count(f, w, r); + + // Check overflow and correct if required - may happen in case a DMA wrote too fast + if (cnt > f->depth) + { + _ff_lock(f->mutex_rd); + _tu_fifo_correct_read_pointer(f, w); + _ff_unlock(f->mutex_rd); + r = f->rd_idx; + cnt = f->depth; + } + + // Check if fifo is empty + if (cnt == 0) + { + info->len_lin = 0; + info->len_wrap = 0; + info->ptr_lin = NULL; + info->ptr_wrap = NULL; + return; + } + + // Get relative pointers + w = get_relative_pointer(f, w); + r = get_relative_pointer(f, r); + + // Copy pointer to buffer to start reading from + info->ptr_lin = &f->buffer[r]; + + // Check if there is a wrap around necessary + if (w > r) { + // Non wrapping case + info->len_lin = cnt; + info->len_wrap = 0; + info->ptr_wrap = NULL; + } + else + { + info->len_lin = f->depth - r; // Also the case if FIFO was full + info->len_wrap = cnt - info->len_lin; + info->ptr_wrap = f->buffer; + } +} + +/******************************************************************************/ +/*! + @brief Get linear write info + + Returns the length and pointer to which bytes can be written into FIFO in a linear manner. + This is of major interest for DMA transmissions not using circular mode. If a returned length is zero the + corresponding pointer is invalid. The returned lengths summed up are the currently free space in the FIFO. + The write pointer does NOT get advanced, use tu_fifo_advance_write_pointer() to do so! + TAKE CARE TO NOT OVERFLOW THE BUFFER MORE THAN TWO TIMES THE FIFO DEPTH - IT CAN NOT RECOVERE OTHERWISE! + @param[in] f + Pointer to FIFO + @param[out] *info + Pointer to struct which holds the desired infos + */ +/******************************************************************************/ +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) +{ + uint16_t w = f->wr_idx, r = f->rd_idx; + uint16_t free = _tu_fifo_remaining(f, w, r); + + if (free == 0) + { + info->len_lin = 0; + info->len_wrap = 0; + info->ptr_lin = NULL; + info->ptr_wrap = NULL; + return; + } + + // Get relative pointers + w = get_relative_pointer(f, w); + r = get_relative_pointer(f, r); + + // Copy pointer to buffer to start writing to + info->ptr_lin = &f->buffer[w]; + + if (w < r) + { + // Non wrapping case + info->len_lin = r-w; + info->len_wrap = 0; + info->ptr_wrap = NULL; + } + else + { + info->len_lin = f->depth - w; + info->len_wrap = free - info->len_lin; // Remaining length - n already was limited to free or FIFO depth + info->ptr_wrap = f->buffer; // Always start of buffer + } +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h new file mode 100644 index 000000000..18db289a1 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h @@ -0,0 +1,151 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Reinhard Panhuber - rework to unmasked pointers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_FIFO_H_ +#define _TUSB_FIFO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// Due to the use of unmasked pointers, this FIFO does not suffer from loosing +// one item slice. Furthermore, write and read operations are completely +// decoupled as write and read functions do not modify a common state. Henceforth, +// writing or reading from the FIFO within an ISR is safe as long as no other +// process (thread or ISR) interferes. +// Also, this FIFO is ready to be used in combination with a DMA as the write and +// read pointers can be updated from within a DMA ISR. Overflows are detectable +// within a certain number (see tu_fifo_overflow()). + +#include "common/tusb_common.h" + +// mutex is only needed for RTOS +// for OS None, we don't get preempted +#define CFG_FIFO_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) + +#if CFG_FIFO_MUTEX +#include "osal/osal.h" +#define tu_fifo_mutex_t osal_mutex_t +#endif + +typedef struct +{ + uint8_t* buffer ; ///< buffer pointer + uint16_t depth ; ///< max items + uint16_t item_size ; ///< size of each item + bool overwritable ; + + uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length + uint16_t max_pointer_idx ; ///< maximum absolute pointer index + + volatile uint16_t wr_idx ; ///< write pointer + volatile uint16_t rd_idx ; ///< read pointer + +#if CFG_FIFO_MUTEX + tu_fifo_mutex_t mutex_wr; + tu_fifo_mutex_t mutex_rd; +#endif + +} tu_fifo_t; + +typedef struct +{ + uint16_t len_lin ; ///< linear length in item size + uint16_t len_wrap ; ///< wrapped length in item size + void * ptr_lin ; ///< linear part start pointer + void * ptr_wrap ; ///< wrapped part start pointer +} tu_fifo_buffer_info_t; + +#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ +{ \ + .buffer = _buffer, \ + .depth = _depth, \ + .item_size = sizeof(_type), \ + .overwritable = _overwritable, \ + .non_used_index_space = UINT16_MAX - (2*(_depth)-1), \ + .max_pointer_idx = 2*(_depth)-1, \ +} + +#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) + + +bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); +bool tu_fifo_clear(tu_fifo_t *f); +bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); + +#if CFG_FIFO_MUTEX +TU_ATTR_ALWAYS_INLINE static inline +void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl) +{ + f->mutex_wr = write_mutex_hdl; + f->mutex_rd = read_mutex_hdl; +} +#endif + +bool tu_fifo_write (tu_fifo_t* f, void const * p_data); +uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t n); +uint16_t tu_fifo_write_n_const_addr_full_words (tu_fifo_t* f, const void * data, uint16_t n); + +bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); +uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); +uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); + +bool tu_fifo_peek (tu_fifo_t* f, void * p_buffer); +uint16_t tu_fifo_peek_n (tu_fifo_t* f, void * p_buffer, uint16_t n); + +uint16_t tu_fifo_count (tu_fifo_t* f); +uint16_t tu_fifo_remaining (tu_fifo_t* f); +bool tu_fifo_empty (tu_fifo_t* f); +bool tu_fifo_full (tu_fifo_t* f); +bool tu_fifo_overflowed (tu_fifo_t* f); +void tu_fifo_correct_read_pointer (tu_fifo_t* f); + +TU_ATTR_ALWAYS_INLINE static inline +uint16_t tu_fifo_depth(tu_fifo_t* f) +{ + return f->depth; +} + +// Pointer modifications intended to be used in combinations with DMAs. +// USE WITH CARE - NO SAFTY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! +void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n); +void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); + +// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies +// to handle a possible wrapping part. These functions deliver a pointer to start +// reading/writing from/to and a valid linear length along which no wrap occurs. +void tu_fifo_get_read_info (tu_fifo_t *f, tu_fifo_buffer_info_t *info); +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); + + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_FIFO_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h new file mode 100644 index 000000000..ce53955f0 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h @@ -0,0 +1,80 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup Group_Common Common Files + * \defgroup Group_TimeoutTimer timeout timer + * @{ */ + +#ifndef _TUSB_TIMEOUT_H_ +#define _TUSB_TIMEOUT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t start; + uint32_t interval; +}tu_timeout_t; + +#if 0 + +extern uint32_t tusb_hal_millis(void); + +static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec) +{ + tt->interval = msec; + tt->start = tusb_hal_millis(); +} + +static inline bool tu_timeout_expired(tu_timeout_t* tt) +{ + return ( tusb_hal_millis() - tt->start ) >= tt->interval; +} + +// For used with periodic event to prevent drift +static inline void tu_timeout_reset(tu_timeout_t* tt) +{ + tt->start += tt->interval; +} + +static inline void tu_timeout_restart(tu_timeout_t* tt) +{ + tt->start = tusb_hal_millis(); +} + +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_TIMEOUT_H_ */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h new file mode 100644 index 000000000..5b26f5aec --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h @@ -0,0 +1,546 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup group_usb_definitions + * \defgroup USBDef_Type USB Types + * @{ */ + +#ifndef _TUSB_TYPES_H_ +#define _TUSB_TYPES_H_ + +#include +#include +#include "tusb_compiler.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/*------------------------------------------------------------------*/ +/* CONSTANTS + *------------------------------------------------------------------*/ + +/// defined base on EHCI specs value for Endpoint Speed +typedef enum +{ + TUSB_SPEED_FULL = 0, + TUSB_SPEED_LOW = 1, + TUSB_SPEED_HIGH = 2, + TUSB_SPEED_INVALID = 0xff, +}tusb_speed_t; + +/// defined base on USB Specs Endpoint's bmAttributes +typedef enum +{ + TUSB_XFER_CONTROL = 0 , + TUSB_XFER_ISOCHRONOUS , + TUSB_XFER_BULK , + TUSB_XFER_INTERRUPT +}tusb_xfer_type_t; + +typedef enum +{ + TUSB_DIR_OUT = 0, + TUSB_DIR_IN = 1, + + TUSB_DIR_IN_MASK = 0x80 +}tusb_dir_t; + +/// Isochronous End Point Attributes +typedef enum +{ + TUSB_ISO_EP_ATT_NO_SYNC = 0x00, + TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, + TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, + TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, + TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point + TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point + TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback +}tusb_iso_ep_attribute_t; + +/// USB Descriptor Types +typedef enum +{ + TUSB_DESC_DEVICE = 0x01, + TUSB_DESC_CONFIGURATION = 0x02, + TUSB_DESC_STRING = 0x03, + TUSB_DESC_INTERFACE = 0x04, + TUSB_DESC_ENDPOINT = 0x05, + TUSB_DESC_DEVICE_QUALIFIER = 0x06, + TUSB_DESC_OTHER_SPEED_CONFIG = 0x07, + TUSB_DESC_INTERFACE_POWER = 0x08, + TUSB_DESC_OTG = 0x09, + TUSB_DESC_DEBUG = 0x0A, + TUSB_DESC_INTERFACE_ASSOCIATION = 0x0B, + + TUSB_DESC_BOS = 0x0F, + TUSB_DESC_DEVICE_CAPABILITY = 0x10, + + TUSB_DESC_FUNCTIONAL = 0x21, + + // Class Specific Descriptor + TUSB_DESC_CS_DEVICE = 0x21, + TUSB_DESC_CS_CONFIGURATION = 0x22, + TUSB_DESC_CS_STRING = 0x23, + TUSB_DESC_CS_INTERFACE = 0x24, + TUSB_DESC_CS_ENDPOINT = 0x25, + + TUSB_DESC_SUPERSPEED_ENDPOINT_COMPANION = 0x30, + TUSB_DESC_SUPERSPEED_ISO_ENDPOINT_COMPANION = 0x31 +}tusb_desc_type_t; + +typedef enum +{ + TUSB_REQ_GET_STATUS = 0 , + TUSB_REQ_CLEAR_FEATURE = 1 , + TUSB_REQ_RESERVED = 2 , + TUSB_REQ_SET_FEATURE = 3 , + TUSB_REQ_RESERVED2 = 4 , + TUSB_REQ_SET_ADDRESS = 5 , + TUSB_REQ_GET_DESCRIPTOR = 6 , + TUSB_REQ_SET_DESCRIPTOR = 7 , + TUSB_REQ_GET_CONFIGURATION = 8 , + TUSB_REQ_SET_CONFIGURATION = 9 , + TUSB_REQ_GET_INTERFACE = 10 , + TUSB_REQ_SET_INTERFACE = 11 , + TUSB_REQ_SYNCH_FRAME = 12 +}tusb_request_code_t; + +typedef enum +{ + TUSB_REQ_FEATURE_EDPT_HALT = 0, + TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1, + TUSB_REQ_FEATURE_TEST_MODE = 2 +}tusb_request_feature_selector_t; + +typedef enum +{ + TUSB_REQ_TYPE_STANDARD = 0, + TUSB_REQ_TYPE_CLASS, + TUSB_REQ_TYPE_VENDOR, + TUSB_REQ_TYPE_INVALID +} tusb_request_type_t; + +typedef enum +{ + TUSB_REQ_RCPT_DEVICE =0, + TUSB_REQ_RCPT_INTERFACE, + TUSB_REQ_RCPT_ENDPOINT, + TUSB_REQ_RCPT_OTHER +} tusb_request_recipient_t; + +// https://www.usb.org/defined-class-codes +typedef enum +{ + TUSB_CLASS_UNSPECIFIED = 0 , + TUSB_CLASS_AUDIO = 1 , + TUSB_CLASS_CDC = 2 , + TUSB_CLASS_HID = 3 , + TUSB_CLASS_RESERVED_4 = 4 , + TUSB_CLASS_PHYSICAL = 5 , + TUSB_CLASS_IMAGE = 6 , + TUSB_CLASS_PRINTER = 7 , + TUSB_CLASS_MSC = 8 , + TUSB_CLASS_HUB = 9 , + TUSB_CLASS_CDC_DATA = 10 , + TUSB_CLASS_SMART_CARD = 11 , + TUSB_CLASS_RESERVED_12 = 12 , + TUSB_CLASS_CONTENT_SECURITY = 13 , + TUSB_CLASS_VIDEO = 14 , + TUSB_CLASS_PERSONAL_HEALTHCARE = 15 , + TUSB_CLASS_AUDIO_VIDEO = 16 , + + TUSB_CLASS_DIAGNOSTIC = 0xDC , + TUSB_CLASS_WIRELESS_CONTROLLER = 0xE0 , + TUSB_CLASS_MISC = 0xEF , + TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE , + TUSB_CLASS_VENDOR_SPECIFIC = 0xFF +}tusb_class_code_t; + +typedef enum +{ + MISC_SUBCLASS_COMMON = 2 +}misc_subclass_type_t; + +typedef enum +{ + MISC_PROTOCOL_IAD = 1 +}misc_protocol_type_t; + +typedef enum +{ + APP_SUBCLASS_USBTMC = 0x03, + APP_SUBCLASS_DFU_RUNTIME = 0x01 +} app_subclass_type_t; + +typedef enum +{ + DEVICE_CAPABILITY_WIRELESS_USB = 0x01, + DEVICE_CAPABILITY_USB20_EXTENSION = 0x02, + DEVICE_CAPABILITY_SUPERSPEED_USB = 0x03, + DEVICE_CAPABILITY_CONTAINER_id = 0x04, + DEVICE_CAPABILITY_PLATFORM = 0x05, + DEVICE_CAPABILITY_POWER_DELIVERY = 0x06, + DEVICE_CAPABILITY_BATTERY_INFO = 0x07, + DEVICE_CAPABILITY_PD_CONSUMER_PORT = 0x08, + DEVICE_CAPABILITY_PD_PROVIDER_PORT = 0x09, + DEVICE_CAPABILITY_SUPERSPEED_PLUS = 0x0A, + DEVICE_CAPABILITY_PRECESION_TIME_MEASUREMENT = 0x0B, + DEVICE_CAPABILITY_WIRELESS_USB_EXT = 0x0C, + DEVICE_CAPABILITY_BILLBOARD = 0x0D, + DEVICE_CAPABILITY_AUTHENTICATION = 0x0E, + DEVICE_CAPABILITY_BILLBOARD_EX = 0x0F, + DEVICE_CAPABILITY_CONFIGURATION_SUMMARY = 0x10 +}device_capability_type_t; + +enum { + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5), + TUSB_DESC_CONFIG_ATT_SELF_POWERED = TU_BIT(6), +}; + +#define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2) + +/// Device State TODO remove +typedef enum +{ + TUSB_DEVICE_STATE_UNPLUG = 0 , + TUSB_DEVICE_STATE_CONFIGURED , + TUSB_DEVICE_STATE_SUSPENDED , +}tusb_device_state_t; + +typedef enum +{ + XFER_RESULT_SUCCESS, + XFER_RESULT_FAILED, + XFER_RESULT_STALLED, +}xfer_result_t; + +enum // TODO remove +{ + DESC_OFFSET_LEN = 0, + DESC_OFFSET_TYPE = 1 +}; + +enum +{ + INTERFACE_INVALID_NUMBER = 0xff +}; + + +typedef enum +{ + MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00, + MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01, + MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02, + MS_OS_20_FEATURE_COMPATBLE_ID = 0x03, + MS_OS_20_FEATURE_REG_PROPERTY = 0x04, + MS_OS_20_FEATURE_MIN_RESUME_TIME = 0x05, + MS_OS_20_FEATURE_MODEL_ID = 0x06, + MS_OS_20_FEATURE_CCGP_DEVICE = 0x07, + MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 +} microsoft_os_20_type_t; + +enum +{ + CONTROL_STAGE_SETUP, + CONTROL_STAGE_DATA, + CONTROL_STAGE_ACK +}; + +//--------------------------------------------------------------------+ +// USB Descriptors +//--------------------------------------------------------------------+ + +// Start of all packed definitions for compiler without per-type packed +TU_ATTR_PACKED_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN + +/// USB Device Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< DEVICE Descriptor Type. + uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant. + + uint8_t bDeviceClass ; ///< Class code (assigned by the USB-IF). \li If this field is reset to zero, each interface within a configuration specifies its own class information and the various interfaces operate independently. \li If this field is set to a value between 1 and FEH, the device supports different class specifications on different interfaces and the interfaces may not operate independently. This value identifies the class definition used for the aggregate interfaces. \li If this field is set to FFH, the device class is vendor-specific. + uint8_t bDeviceSubClass ; ///< Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass field. \li If the bDeviceClass field is reset to zero, this field must also be reset to zero. \li If the bDeviceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. + uint8_t bDeviceProtocol ; ///< Protocol code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass and the bDeviceSubClass fields. If a device supports class-specific protocols on a device basis as opposed to an interface basis, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use class-specific protocols on a device basis. However, it may use classspecific protocols on an interface basis. \li If this field is set to FFH, the device uses a vendor-specific protocol on a device basis. + uint8_t bMaxPacketSize0 ; ///< Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid). For HS devices is fixed to 64. + + uint16_t idVendor ; ///< Vendor ID (assigned by the USB-IF). + uint16_t idProduct ; ///< Product ID (assigned by the manufacturer). + uint16_t bcdDevice ; ///< Device release number in binary-coded decimal. + uint8_t iManufacturer ; ///< Index of string descriptor describing manufacturer. + uint8_t iProduct ; ///< Index of string descriptor describing product. + uint8_t iSerialNumber ; ///< Index of string descriptor describing the device's serial number. + + uint8_t bNumConfigurations ; ///< Number of possible configurations. +} tusb_desc_device_t; + +TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); + +// USB Binary Device Object Store (BOS) Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type + uint16_t wTotalLength ; ///< Total length of data returned for this descriptor + uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS +} tusb_desc_bos_t; + +TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct"); + +/// USB Configuration Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type + uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration. + + uint8_t bNumInterfaces ; ///< Number of interfaces supported by this configuration + uint8_t bConfigurationValue ; ///< Value to use as an argument to the SetConfiguration() request to select this configuration. + uint8_t iConfiguration ; ///< Index of string descriptor describing this configuration + uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. + uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). +} tusb_desc_configuration_t; + +TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); + +/// USB Interface Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type + + uint8_t bInterfaceNumber ; ///< Number of this interface. Zero-based value identifying the index in the array of concurrent interfaces supported by this configuration. + uint8_t bAlternateSetting ; ///< Value used to select this alternate setting for the interface identified in the prior field + uint8_t bNumEndpoints ; ///< Number of endpoints used by this interface (excluding endpoint zero). If this value is zero, this interface only uses the Default Control Pipe. + uint8_t bInterfaceClass ; ///< Class code (assigned by the USB-IF). \li A value of zero is reserved for future standardization. \li If this field is set to FFH, the interface class is vendor-specific. \li All other values are reserved for assignment by the USB-IF. + uint8_t bInterfaceSubClass ; ///< Subclass code (assigned by the USB-IF). \n These codes are qualified by the value of the bInterfaceClass field. \li If the bInterfaceClass field is reset to zero, this field must also be reset to zero. \li If the bInterfaceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. + uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. + uint8_t iInterface ; ///< Index of string descriptor describing this interface +} tusb_desc_interface_t; + +TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); + +/// USB Endpoint Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; // Size of this descriptor in bytes + uint8_t bDescriptorType ; // ENDPOINT Descriptor Type + + uint8_t bEndpointAddress ; // The address of the endpoint + + struct TU_ATTR_PACKED { + uint8_t xfer : 2; // Control, ISO, Bulk, Interrupt + uint8_t sync : 2; // None, Asynchronous, Adaptive, Synchronous + uint8_t usage : 2; // Data, Feedback, Implicit feedback + uint8_t : 2; + } bmAttributes; + + uint16_t wMaxPacketSize ; // Bit 10..0 : max packet size, bit 12..11 additional transaction per highspeed micro-frame + uint8_t bInterval ; // Polling interval, in frames or microframes depending on the operating speed +} tusb_desc_endpoint_t; + +TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct"); + +/// USB Other Speed Configuration Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + uint16_t wTotalLength ; ///< Total length of data returned + + uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration + uint8_t bConfigurationValue ; ///< Value to use to select configuration + uint8_t iConfiguration ; ///< Index of string descriptor + uint8_t bmAttributes ; ///< Same as Configuration descriptor + uint8_t bMaxPower ; ///< Same as Configuration descriptor +} tusb_desc_other_speed_t; + +/// USB Device Qualifier Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Device Qualifier Type + uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) + + uint8_t bDeviceClass ; ///< Class Code + uint8_t bDeviceSubClass ; ///< SubClass Code + uint8_t bDeviceProtocol ; ///< Protocol Code + + uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed + uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations + uint8_t bReserved ; ///< Reserved for future use, must be zero +} tusb_desc_device_qualifier_t; + +TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct"); + +/// USB Interface Association Descriptor (IAD ECN) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + + uint8_t bFirstInterface ; ///< Index of the first associated interface. + uint8_t bInterfaceCount ; ///< Total number of associated interfaces. + + uint8_t bFunctionClass ; ///< Interface class ID. + uint8_t bFunctionSubClass ; ///< Interface subclass ID. + uint8_t bFunctionProtocol ; ///< Interface protocol ID. + + uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. +} tusb_desc_interface_assoc_t; + +// USB String Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< Descriptor Type + uint16_t unicode_string[]; +} tusb_desc_string_t; + +// USB Binary Device Object Store (BOS) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; + uint8_t bDescriptorType ; + uint8_t bDevCapabilityType; + uint8_t bReserved; + uint8_t PlatformCapabilityUUID[16]; + uint8_t CapabilityData[]; +} tusb_desc_bos_platform_t; + +// USB WebuSB URL Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bScheme; + char url[]; +} tusb_desc_webusb_url_t; + +// DFU Functional Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; + uint8_t bDescriptorType; + + union { + struct TU_ATTR_PACKED { + uint8_t bitCanDnload : 1; + uint8_t bitCanUpload : 1; + uint8_t bitManifestationTolerant : 1; + uint8_t bitWillDetach : 1; + uint8_t reserved : 4; + } bmAttributes; + + uint8_t bAttributes; + }; + + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +} tusb_desc_dfu_functional_t; + +/*------------------------------------------------------------------*/ +/* Types + *------------------------------------------------------------------*/ +typedef struct TU_ATTR_PACKED{ + union { + struct TU_ATTR_PACKED { + uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. + uint8_t type : 2; ///< Request type tusb_request_type_t. + uint8_t direction : 1; ///< Direction type. tusb_dir_t + } bmRequestType_bit; + + uint8_t bmRequestType; + }; + + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} tusb_control_request_t; + +TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); + + +TU_ATTR_PACKED_END // End of all packed definitions +TU_ATTR_BIT_FIELD_ORDER_END + +//--------------------------------------------------------------------+ +// Endpoint helper +//--------------------------------------------------------------------+ + +// Get direction from Endpoint address +static inline tusb_dir_t tu_edpt_dir(uint8_t addr) +{ + return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; +} + +// Get Endpoint number from address +static inline uint8_t tu_edpt_number(uint8_t addr) +{ + return (uint8_t)(addr & (~TUSB_DIR_IN_MASK)); +} + +static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) +{ + return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0)); +} + +static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) +{ + return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0); +} + +//--------------------------------------------------------------------+ +// Descriptor helper +//--------------------------------------------------------------------+ +static inline uint8_t const * tu_desc_next(void const* desc) +{ + uint8_t const* desc8 = (uint8_t const*) desc; + return desc8 + desc8[DESC_OFFSET_LEN]; +} + +static inline uint8_t tu_desc_type(void const* desc) +{ + return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; +} + +static inline uint8_t tu_desc_len(void const* desc) +{ + return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_TYPES_H_ */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h new file mode 100644 index 000000000..8fef11dc7 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h @@ -0,0 +1,181 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ +#ifndef TUSB_VERIFY_H_ +#define TUSB_VERIFY_H_ + +#include +#include +#include "tusb_option.h" +#include "tusb_compiler.h" + +/*------------------------------------------------------------------*/ +/* This file use an advanced macro technique to mimic the default parameter + * as C++ for the sake of code simplicity. Beware of a headache macro + * manipulation that you are told to stay away. + * + * This contains macros for both VERIFY and ASSERT: + * + * VERIFY: Used when there is an error condition which is not the + * fault of the MCU. For example, bounds checking on data + * sent to the micro over USB should use this function. + * Another example is checking for buffer overflows, where + * returning from the active function causes a NAK. + * + * ASSERT: Used for error conditions that are caused by MCU firmware + * bugs. This is used to discover bugs in the code more + * quickly. One example would be adding assertions in library + * function calls to confirm a function's (untainted) + * parameters are valid. + * + * The difference in behavior is that ASSERT triggers a breakpoint while + * verify does not. + * + * #define TU_VERIFY(cond) if(cond) return false; + * #define TU_VERIFY(cond,ret) if(cond) return ret; + * + * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;} + * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;} + * + * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} + * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} + * + *------------------------------------------------------------------*/ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// TU_VERIFY Helper +//--------------------------------------------------------------------+ + +#if CFG_TUSB_DEBUG + #include + #define _MESS_ERR(_err) tu_printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) + #define _MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__) +#else + #define _MESS_ERR(_err) do {} while (0) + #define _MESS_FAILED() do {} while (0) +#endif + +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) + #define TU_BREAKPOINT() do \ + { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ + } while(0) + +#elif defined(__riscv) + #define TU_BREAKPOINT() do { __asm("ebreak\n"); } while(0) + +#else + #define TU_BREAKPOINT() do {} while (0) +#endif + +/*------------------------------------------------------------------*/ +/* Macro Generator + *------------------------------------------------------------------*/ + +// Helper to implement optional parameter for TU_VERIFY Macro family +#define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 +#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 + +/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/ +#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do \ +{ \ + if ( !(_cond) ) { _handler; return _ret; } \ +} while(0) + +/*------------------------------------------------------------------*/ +/* TU_VERIFY + * - TU_VERIFY_1ARGS : return false if failed + * - TU_VERIFY_2ARGS : return provided value if failed + *------------------------------------------------------------------*/ +#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false) +#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret) + +#define TU_VERIFY(...) GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__) + + +/*------------------------------------------------------------------*/ +/* TU_VERIFY WITH HANDLER + * - TU_VERIFY_HDLR_2ARGS : execute handler, return false if failed + * - TU_VERIFY_HDLR_3ARGS : execute handler, return provided error if failed + *------------------------------------------------------------------*/ +#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false) +#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret) + +#define TU_VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__) + +/*------------------------------------------------------------------*/ +/* ASSERT + * basically TU_VERIFY with TU_BREAKPOINT() as handler + * - 1 arg : return false if failed + * - 2 arg : return error if failed + *------------------------------------------------------------------*/ +#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false) +#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret) + +#ifndef TU_ASSERT +#define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__) +#endif + +// TODO remove TU_ASSERT_ERR() later + +/*------------- Generator for TU_VERIFY_ERR and TU_VERIFY_ERR_HDLR -------------*/ +#define TU_VERIFY_ERR_DEF2(_error, _handler) do \ +{ \ + uint32_t _err = (uint32_t)(_error); \ + if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _err; } \ +} while(0) + +#define TU_VERIFY_ERR_DEF3(_error, _handler, _ret) do \ +{ \ + uint32_t _err = (uint32_t)(_error); \ + if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _ret; } \ +} while(0) + +/*------------------------------------------------------------------*/ +/* ASSERT Error + * basically TU_VERIFY Error with TU_BREAKPOINT() as handler + *------------------------------------------------------------------*/ +#define ASSERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, TU_BREAKPOINT()) +#define ASSERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, TU_BREAKPOINT(), _ret) + +#ifndef TU_ASSERT_ERR +#define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_ERR_2ARGS, ASSERT_ERR_1ARGS,UNUSED)(__VA_ARGS__) +#endif + +/*------------------------------------------------------------------*/ +/* ASSERT HDLR + *------------------------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif /* TUSB_VERIFY_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h new file mode 100644 index 000000000..c042cc708 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h @@ -0,0 +1,193 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DCD_H_ +#define _TUSB_DCD_H_ + +#include "common/tusb_common.h" +#include "osal/osal.h" +#include "common/tusb_fifo.h" +#include "dcd_attr.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUD_ENDPPOINT_MAX + #define CFG_TUD_ENDPPOINT_MAX DCD_ATTR_ENDPOINT_MAX +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +typedef enum +{ + DCD_EVENT_INVALID = 0, + DCD_EVENT_BUS_RESET, + DCD_EVENT_UNPLUGGED, + DCD_EVENT_SOF, + DCD_EVENT_SUSPEND, // TODO LPM Sleep L1 support + DCD_EVENT_RESUME, + + DCD_EVENT_SETUP_RECEIVED, + DCD_EVENT_XFER_COMPLETE, + + // Not an DCD event, just a convenient way to defer ISR function + USBD_EVENT_FUNC_CALL, + + DCD_EVENT_COUNT +} dcd_eventid_t; + +typedef struct TU_ATTR_ALIGNED(4) +{ + uint8_t rhport; + uint8_t event_id; + + union + { + // BUS RESET + struct { + tusb_speed_t speed; + } bus_reset; + + // SETUP_RECEIVED + tusb_control_request_t setup_received; + + // XFER_COMPLETE + struct { + uint8_t ep_addr; + uint8_t result; + uint32_t len; + }xfer_complete; + + // FUNC_CALL + struct { + void (*func) (void*); + void* param; + }func_call; + }; +} dcd_event_t; + +//TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +// Initialize controller to device mode +void dcd_init (uint8_t rhport); + +// Interrupt Handler +#if __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif +void dcd_int_handler(uint8_t rhport); +#if __GNUC__ +#pragma GCC diagnostic pop +#endif + +// Enable device interrupt +void dcd_int_enable (uint8_t rhport); + +// Disable device interrupt +void dcd_int_disable(uint8_t rhport); + +// Receive Set Address request, mcu port must also include status IN response +void dcd_set_address(uint8_t rhport, uint8_t dev_addr); + +// Wake up host +void dcd_remote_wakeup(uint8_t rhport); + +// Connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; + +// Disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); + +// Close all non-control endpoints, cancel all pending transfers if any. +// Invoked when switching from a non-zero Configuration by SET_CONFIGURE therefore +// required for multiple configuration support. +void dcd_edpt_close_all (uint8_t rhport); + +// Close an endpoint. +// Since it is weak, caller must TU_ASSERT this function's existence before calling it. +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +// Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack +// This API is optional, may be useful for register-based for transferring data. +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; + +// Stall endpoint, any queuing transfer should be removed from endpoint +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); + +// clear stall, data toggle is also reset to DATA0 +// This API never calls with control endpoints, since it is auto cleared when receiving setup packet +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); + +//--------------------------------------------------------------------+ +// Event API (implemented by stack) +//--------------------------------------------------------------------+ + +// Called by DCD to notify device stack +extern void dcd_event_handler(dcd_event_t const * event, bool in_isr); + +// helper to send bus signal event +extern void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr); + +// helper to send bus reset event +extern void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr); + +// helper to send setup received +extern void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr); + +// helper to send transfer complete event +extern void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DCD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h new file mode 100644 index 000000000..b40c2ad07 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h @@ -0,0 +1,221 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_DCD_ATTR_H_ +#define TUSB_DCD_ATTR_H_ + +#include "tusb_option.h" + +// Attribute includes +// - ENDPOINT_MAX: max (logical) number of endpoint +// - ENDPOINT_EXCLUSIVE_NUMBER: endpoint number with different direction IN and OUT aren't allowed, +// e.g EP1 OUT & EP1 IN cannot exist together +// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. + +//------------- NXP -------------// +#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) + #define DCD_ATTR_ENDPOINT_MAX 5 + +#elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) + #define DCD_ATTR_ENDPOINT_MAX 16 + +#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) + // TODO USB0 has 6, USB1 has 4 + #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) + #define DCD_ATTR_ENDPOINT_MAX 5 + +#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) + // TODO USB0 has 5, USB1 has 6 + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) + // TODO USB0 has 5, USB1 has 6 + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX) + #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX, OPT_MCU_K32L2BXX) + #define DCD_ATTR_ENDPOINT_MAX 16 + +#elif TU_CHECK_MCU(OPT_MCU_MM32F327X) + #define DCD_ATTR_ENDPOINT_MAX 16 + +//------------- Nordic -------------// +#elif TU_CHECK_MCU(OPT_MCU_NRF5X) + // 8 CBI + 1 ISO + #define DCD_ATTR_ENDPOINT_MAX 9 + +//------------- Microchip -------------// +#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ + TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_SAMG) + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER + +#elif TU_CHECK_MCU(OPT_MCU_SAMX7X) + #define DCD_ATTR_ENDPOINT_MAX 10 + #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER + +#elif TU_CHECK_MCU(OPT_MCU_PIC32MZ) + #define DCD_ATTR_ENDPOINT_MAX 8 + #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER + +//------------- ST -------------// +#elif TU_CHECK_MCU(OPT_MCU_STM32F0) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32F1) + #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ + defined (STM32F107xB) || defined (STM32F107xC) + #define DCD_ATTR_ENDPOINT_MAX 4 + #define DCD_ATTR_DWC2_STM32 + #else + #define DCD_ATTR_ENDPOINT_MAX 8 + #endif + +#elif TU_CHECK_MCU(OPT_MCU_STM32F2) + // FS has 4 ep, HS has 5 ep + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_DWC2_STM32 + +#elif TU_CHECK_MCU(OPT_MCU_STM32F3) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32F4) + // For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9 + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_DWC2_STM32 + +#elif TU_CHECK_MCU(OPT_MCU_STM32F7) + // FS has 6, HS has 9 + #define DCD_ATTR_ENDPOINT_MAX 9 + #define DCD_ATTR_DWC2_STM32 + +#elif TU_CHECK_MCU(OPT_MCU_STM32H7) + #define DCD_ATTR_ENDPOINT_MAX 9 + #define DCD_ATTR_DWC2_STM32 + +#elif TU_CHECK_MCU(OPT_MCU_STM32G4) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32L4) + #if defined (STM32L475xx) || defined (STM32L476xx) || \ + defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ + defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ + defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_DWC2_STM32 + #else + #define DCD_ATTR_ENDPOINT_MAX 8 + #endif + +//------------- Sony -------------// +#elif TU_CHECK_MCU(OPT_MCU_CXD56) + #define DCD_ATTR_ENDPOINT_MAX 7 + #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER + +//------------- TI -------------// +#elif TU_CHECK_MCU(OPT_MCU_MSP430x5xx) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) + #define DCD_ATTR_ENDPOINT_MAX 8 + +//------------- ValentyUSB -------------// +#elif TU_CHECK_MCU(OPT_MCU_VALENTYUSB_EPTRI) + #define DCD_ATTR_ENDPOINT_MAX 16 + +//------------- Nuvoton -------------// +#elif TU_CHECK_MCU(OPT_MCU_NUC121, OPT_MCU_NUC126) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_NUC120) + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(OPT_MCU_NUC505) + #define DCD_ATTR_ENDPOINT_MAX 12 + +//------------- Espressif -------------// +#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #define DCD_ATTR_ENDPOINT_MAX 6 + +//------------- Dialog -------------// +#elif TU_CHECK_MCU(OPT_MCU_DA1469X) + #define DCD_ATTR_ENDPOINT_MAX 4 + +//------------- Raspberry Pi -------------// +#elif TU_CHECK_MCU(OPT_MCU_RP2040) + #define DCD_ATTR_ENDPOINT_MAX 16 + +//------------- Silabs -------------// +#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) + #define DCD_ATTR_ENDPOINT_MAX 7 + +//------------- Renesas -------------// +#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) + #define DCD_ATTR_ENDPOINT_MAX 10 + +//------------- GigaDevice -------------// +#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) + #define DCD_ATTR_ENDPOINT_MAX 4 + +//------------- Broadcom -------------// +#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) + #define DCD_ATTR_ENDPOINT_MAX 8 + +//------------- Broadcom -------------// +#elif TU_CHECK_MCU(OPT_MCU_XMC4000) + #define DCD_ATTR_ENDPOINT_MAX 8 + +//------------- BridgeTek -------------// +#elif TU_CHECK_MCU(OPT_MCU_FT90X) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_FT93X) + #define DCD_ATTR_ENDPOINT_MAX 16 + +#else + #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" + #define DCD_ATTR_ENDPOINT_MAX 8 +#endif + +// Default to fullspeed if not defined +//#ifndef PORT_HIGHSPEED +// #define DCD_ATTR_PORT_HIGHSPEED 0x00 +//#endif + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c new file mode 100644 index 000000000..6a5210b34 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c @@ -0,0 +1,1419 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED + +#include "tusb.h" +#include "device/usbd.h" +#include "device/usbd_pvt.h" +#include "device/dcd.h" + +//--------------------------------------------------------------------+ +// USBD Configuration +//--------------------------------------------------------------------+ + +// Debug level of USBD +#define USBD_DBG 2 + +#ifndef CFG_TUD_TASK_QUEUE_SZ + #define CFG_TUD_TASK_QUEUE_SZ 16 +#endif + +//--------------------------------------------------------------------+ +// Device Data +//--------------------------------------------------------------------+ + +// Invalid driver ID in itf2drv[] ep2drv[][] mapping +enum { DRVID_INVALID = 0xFFu }; + +typedef struct +{ + struct TU_ATTR_PACKED + { + volatile uint8_t connected : 1; + volatile uint8_t addressed : 1; + volatile uint8_t suspended : 1; + + uint8_t remote_wakeup_en : 1; // enable/disable by host + uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute + uint8_t self_powered : 1; // configuration descriptor's attribute + }; + + volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) + uint8_t speed; + + uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) + uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + + struct TU_ATTR_PACKED + { + volatile bool busy : 1; + volatile bool stalled : 1; + volatile bool claimed : 1; + + // TODO merge ep2drv here, 4-bit should be sufficient + }ep_status[CFG_TUD_ENDPPOINT_MAX][2]; + +}usbd_device_t; + +static usbd_device_t _usbd_dev; + +//--------------------------------------------------------------------+ +// Class Driver +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + #define DRIVER_NAME(_name) .name = _name, +#else + #define DRIVER_NAME(_name) +#endif + +// Built-in class drivers +static usbd_class_driver_t const _usbd_driver[] = +{ + #if CFG_TUD_CDC + { + DRIVER_NAME("CDC") + .init = cdcd_init, + .reset = cdcd_reset, + .open = cdcd_open, + .control_xfer_cb = cdcd_control_xfer_cb, + .xfer_cb = cdcd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_MSC + { + DRIVER_NAME("MSC") + .init = mscd_init, + .reset = mscd_reset, + .open = mscd_open, + .control_xfer_cb = mscd_control_xfer_cb, + .xfer_cb = mscd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_HID + { + DRIVER_NAME("HID") + .init = hidd_init, + .reset = hidd_reset, + .open = hidd_open, + .control_xfer_cb = hidd_control_xfer_cb, + .xfer_cb = hidd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_AUDIO + { + DRIVER_NAME("AUDIO") + .init = audiod_init, + .reset = audiod_reset, + .open = audiod_open, + .control_xfer_cb = audiod_control_xfer_cb, + .xfer_cb = audiod_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_VIDEO + { + DRIVER_NAME("VIDEO") + .init = videod_init, + .reset = videod_reset, + .open = videod_open, + .control_xfer_cb = videod_control_xfer_cb, + .xfer_cb = videod_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_MIDI + { + DRIVER_NAME("MIDI") + .init = midid_init, + .open = midid_open, + .reset = midid_reset, + .control_xfer_cb = midid_control_xfer_cb, + .xfer_cb = midid_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_VENDOR + { + DRIVER_NAME("VENDOR") + .init = vendord_init, + .reset = vendord_reset, + .open = vendord_open, + .control_xfer_cb = tud_vendor_control_xfer_cb, + .xfer_cb = vendord_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_USBTMC + { + DRIVER_NAME("TMC") + .init = usbtmcd_init_cb, + .reset = usbtmcd_reset_cb, + .open = usbtmcd_open_cb, + .control_xfer_cb = usbtmcd_control_xfer_cb, + .xfer_cb = usbtmcd_xfer_cb, + .sof = NULL + }, + #endif + + #if CFG_TUD_DFU_RUNTIME + { + DRIVER_NAME("DFU-RUNTIME") + .init = dfu_rtd_init, + .reset = dfu_rtd_reset, + .open = dfu_rtd_open, + .control_xfer_cb = dfu_rtd_control_xfer_cb, + .xfer_cb = NULL, + .sof = NULL + }, + #endif + + #if CFG_TUD_DFU + { + DRIVER_NAME("DFU") + .init = dfu_moded_init, + .reset = dfu_moded_reset, + .open = dfu_moded_open, + .control_xfer_cb = dfu_moded_control_xfer_cb, + .xfer_cb = NULL, + .sof = NULL + }, + #endif + + #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM + { + DRIVER_NAME("NET") + .init = netd_init, + .reset = netd_reset, + .open = netd_open, + .control_xfer_cb = netd_control_xfer_cb, + .xfer_cb = netd_xfer_cb, + .sof = NULL, + }, + #endif + + #if CFG_TUD_BTH + { + DRIVER_NAME("BTH") + .init = btd_init, + .reset = btd_reset, + .open = btd_open, + .control_xfer_cb = btd_control_xfer_cb, + .xfer_cb = btd_xfer_cb, + .sof = NULL + }, + #endif +}; + +enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; + +// Additional class drivers implemented by application +static usbd_class_driver_t const * _app_driver = NULL; +static uint8_t _app_driver_count = 0; + +// virtually joins built-in and application drivers together. +// Application is positioned first to allow overwriting built-in ones. +static inline usbd_class_driver_t const * get_driver(uint8_t drvid) +{ + // Application drivers + if ( usbd_app_driver_get_cb ) + { + if ( drvid < _app_driver_count ) return &_app_driver[drvid]; + drvid -= _app_driver_count; + } + + // Built-in drivers + if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid]; + + return NULL; +} + +#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) + +//--------------------------------------------------------------------+ +// DCD Event +//--------------------------------------------------------------------+ + +static bool _usbd_initialized = false; + +// Event queue +// OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr) +OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); +static osal_queue_t _usbd_q; + +// Mutex for claiming endpoint, only needed when using with preempted RTOS +#if CFG_TUSB_OS != OPT_OS_NONE +static osal_mutex_def_t _ubsd_mutexdef; +static osal_mutex_t _usbd_mutex; +#endif + + +//--------------------------------------------------------------------+ +// Prototypes +//--------------------------------------------------------------------+ +static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); +static bool process_set_config(uint8_t rhport, uint8_t cfg_num); +static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); + +// from usbd_control.c +void usbd_control_reset(void); +void usbd_control_set_request(tusb_control_request_t const *request); +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); +bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 +static char const* const _usbd_event_str[DCD_EVENT_COUNT] = +{ + "Invalid" , + "Bus Reset" , + "Unplugged" , + "SOF" , + "Suspend" , + "Resume" , + "Setup Received" , + "Xfer Complete" , + "Func Call" +}; + +static char const* const _tusb_std_request_str[] = +{ + "Get Status" , + "Clear Feature" , + "Reserved" , + "Set Feature" , + "Reserved" , + "Set Address" , + "Get Descriptor" , + "Set Descriptor" , + "Get Configuration" , + "Set Configuration" , + "Get Interface" , + "Set Interface" , + "Synch Frame" +}; + +static char const* const _tusb_speed_str[] = { "Full", "Low", "High" }; + +// for usbd_control to print the name of control complete driver +void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) +{ + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) + { + usbd_class_driver_t const * driver = get_driver(i); + if ( driver->control_xfer_cb == callback ) + { + TU_LOG2(" %s control complete\r\n", driver->name); + return; + } + } +} + +#endif + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ +tusb_speed_t tud_speed_get(void) +{ + return (tusb_speed_t) _usbd_dev.speed; +} + +bool tud_connected(void) +{ + return _usbd_dev.connected; +} + +bool tud_mounted(void) +{ + return _usbd_dev.cfg_num ? true : false; +} + +bool tud_suspended(void) +{ + return _usbd_dev.suspended; +} + +bool tud_remote_wakeup(void) +{ + // only wake up host if this feature is supported and enabled and we are suspended + TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en ); + dcd_remote_wakeup(TUD_OPT_RHPORT); + return true; +} + +bool tud_disconnect(void) +{ + TU_VERIFY(dcd_disconnect); + dcd_disconnect(TUD_OPT_RHPORT); + return true; +} + +bool tud_connect(void) +{ + TU_VERIFY(dcd_connect); + dcd_connect(TUD_OPT_RHPORT); + return true; +} + +//--------------------------------------------------------------------+ +// USBD Task +//--------------------------------------------------------------------+ +bool tud_inited(void) +{ + return _usbd_initialized; +} + +bool tud_init (uint8_t rhport) +{ + // skip if already initialized + if (_usbd_initialized) return _usbd_initialized; + + TU_LOG2("USBD init\r\n"); + + tu_varclr(&_usbd_dev); + +#if CFG_TUSB_OS != OPT_OS_NONE + // Init device mutex + _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef); + TU_ASSERT(_usbd_mutex); +#endif + + // Init device queue & task + _usbd_q = osal_queue_create(&_usbd_qdef); + TU_ASSERT(_usbd_q); + + // Get application driver if available + if ( usbd_app_driver_get_cb ) + { + _app_driver = usbd_app_driver_get_cb(&_app_driver_count); + } + + // Init class drivers + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) + { + usbd_class_driver_t const * driver = get_driver(i); + TU_LOG2("%s init\r\n", driver->name); + driver->init(); + } + + // Init device controller driver + dcd_init(rhport); + dcd_int_enable(rhport); + + _usbd_initialized = true; + + return true; +} + +static void configuration_reset(uint8_t rhport) +{ + for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) + { + get_driver(i)->reset(rhport); + } + + tu_varclr(&_usbd_dev); + memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping + memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping +} + +static void usbd_reset(uint8_t rhport) +{ + configuration_reset(rhport); + usbd_control_reset(); +} + +bool tud_task_event_ready(void) +{ + // Skip if stack is not initialized + if ( !tusb_inited() ) return false; + + return !osal_queue_empty(_usbd_q); +} + +/* USB Device Driver task + * This top level thread manages all device controller event and delegates events to class-specific drivers. + * This should be called periodically within the mainloop or rtos thread. + * + @code + int main(void) + { + application_init(); + tusb_init(); + + while(1) // the mainloop + { + application_code(); + tud_task(); // tinyusb device task + } + } + @endcode + */ +void tud_task (void) +{ + // Skip if stack is not initialized + if ( !tusb_inited() ) return; + + // Loop until there is no more events in the queue + while (1) + { + dcd_event_t event; + + if ( !osal_queue_receive(_usbd_q, &event) ) return; + +#if CFG_TUSB_DEBUG >= 2 + if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG2("\r\n"); // extra line for setup + TU_LOG2("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); +#endif + + switch ( event.event_id ) + { + case DCD_EVENT_BUS_RESET: + TU_LOG2(": %s Speed\r\n", _tusb_speed_str[event.bus_reset.speed]); + usbd_reset(event.rhport); + _usbd_dev.speed = event.bus_reset.speed; + break; + + case DCD_EVENT_UNPLUGGED: + TU_LOG2("\r\n"); + usbd_reset(event.rhport); + + // invoke callback + if (tud_umount_cb) tud_umount_cb(); + break; + + case DCD_EVENT_SETUP_RECEIVED: + TU_LOG2_VAR(&event.setup_received); + TU_LOG2("\r\n"); + + // Mark as connected after receiving 1st setup packet. + // But it is easier to set it every time instead of wasting time to check then set + _usbd_dev.connected = 1; + + // mark both in & out control as free + _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = false; + _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0; + _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = false; + _usbd_dev.ep_status[0][TUSB_DIR_IN ].claimed = 0; + + // Process control request + if ( !process_control_request(event.rhport, &event.setup_received) ) + { + TU_LOG2(" Stall EP0\r\n"); + // Failed -> stall both control endpoint IN and OUT + dcd_edpt_stall(event.rhport, 0); + dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK); + } + break; + + case DCD_EVENT_XFER_COMPLETE: + { + // Invoke the class callback associated with the endpoint address + uint8_t const ep_addr = event.xfer_complete.ep_addr; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + + _usbd_dev.ep_status[epnum][ep_dir].busy = false; + _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; + + if ( 0 == epnum ) + { + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); + } + else + { + usbd_class_driver_t const * driver = get_driver( _usbd_dev.ep2drv[epnum][ep_dir] ); + TU_ASSERT(driver, ); + + TU_LOG2(" %s xfer callback\r\n", driver->name); + driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); + } + } + break; + + case DCD_EVENT_SUSPEND: + // NOTE: When plugging/unplugging device, the D+/D- state are unstable and + // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event + // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected + if ( _usbd_dev.connected ) + { + TU_LOG2(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); + if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); + }else + { + TU_LOG2(" Skipped\r\n"); + } + break; + + case DCD_EVENT_RESUME: + if ( _usbd_dev.connected ) + { + TU_LOG2("\r\n"); + if (tud_resume_cb) tud_resume_cb(); + }else + { + TU_LOG2(" Skipped\r\n"); + } + break; + + case DCD_EVENT_SOF: + TU_LOG2("\r\n"); + for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) + { + usbd_class_driver_t const * driver = get_driver(i); + if ( driver->sof ) driver->sof(event.rhport); + } + break; + + case USBD_EVENT_FUNC_CALL: + TU_LOG2("\r\n"); + if ( event.func_call.func ) event.func_call.func(event.func_call.param); + break; + + default: + TU_BREAKPOINT(); + break; + } + } +} + +//--------------------------------------------------------------------+ +// Control Request Parser & Handling +//--------------------------------------------------------------------+ + +// Helper to invoke class driver control request handler +static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) +{ + usbd_control_set_complete_callback(driver->control_xfer_cb); + TU_LOG2(" %s control request\r\n", driver->name); + return driver->control_xfer_cb(rhport, CONTROL_STAGE_SETUP, request); +} + +// This handles the actual request and its response. +// return false will cause its caller to stall control endpoint +static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +{ + usbd_control_set_complete_callback(NULL); + + TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); + + // Vendor request + if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) + { + TU_VERIFY(tud_vendor_control_xfer_cb); + + usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); + return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); + } + +#if CFG_TUSB_DEBUG >= 2 + if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) + { + TU_LOG2(" %s", _tusb_std_request_str[p_request->bRequest]); + if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG2("\r\n"); + } +#endif + + switch ( p_request->bmRequestType_bit.recipient ) + { + //------------- Device Requests e.g in enumeration -------------// + case TUSB_REQ_RCPT_DEVICE: + if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) + { + uint8_t const itf = tu_u16_low(p_request->wIndex); + TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); + + usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]); + TU_VERIFY(driver); + + // forward to class driver: "non-STD request to Interface" + return invoke_class_control(rhport, driver, p_request); + } + + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) + { + // Non standard request is not supported + TU_BREAKPOINT(); + return false; + } + + switch ( p_request->bRequest ) + { + case TUSB_REQ_SET_ADDRESS: + // Depending on mcu, status phase could be sent either before or after changing device address, + // or even require stack to not response with status at all + // Therefore DCD must take full responsibility to response and include zlp status packet if needed. + usbd_control_set_request(p_request); // set request since DCD has no access to tud_control_status() API + dcd_set_address(rhport, (uint8_t) p_request->wValue); + // skip tud_control_status() + _usbd_dev.addressed = 1; + break; + + case TUSB_REQ_GET_CONFIGURATION: + { + uint8_t cfg_num = _usbd_dev.cfg_num; + tud_control_xfer(rhport, p_request, &cfg_num, 1); + } + break; + + case TUSB_REQ_SET_CONFIGURATION: + { + uint8_t const cfg_num = (uint8_t) p_request->wValue; + + // Only process if new configure is different + if (_usbd_dev.cfg_num != cfg_num) + { + if ( _usbd_dev.cfg_num ) + { + // already configured: need to clear all endpoints and driver first + TU_LOG(USBD_DBG, " Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); + + // close all non-control endpoints, cancel all pending transfers if any + dcd_edpt_close_all(rhport); + + // close all drivers and current configured state except bus speed + uint8_t const speed = _usbd_dev.speed; + configuration_reset(rhport); + + _usbd_dev.speed = speed; // restore speed + } + + // switch to new configuration if not zero + if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); + } + + _usbd_dev.cfg_num = cfg_num; + tud_control_status(rhport, p_request); + } + break; + + case TUSB_REQ_GET_DESCRIPTOR: + TU_VERIFY( process_get_descriptor(rhport, p_request) ); + break; + + case TUSB_REQ_SET_FEATURE: + // Only support remote wakeup for device feature + TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); + + TU_LOG(USBD_DBG, " Enable Remote Wakeup\r\n"); + + // Host may enable remote wake up before suspending especially HID device + _usbd_dev.remote_wakeup_en = true; + tud_control_status(rhport, p_request); + break; + + case TUSB_REQ_CLEAR_FEATURE: + // Only support remote wakeup for device feature + TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); + + TU_LOG(USBD_DBG, " Disable Remote Wakeup\r\n"); + + // Host may disable remote wake up after resuming + _usbd_dev.remote_wakeup_en = false; + tud_control_status(rhport, p_request); + break; + + case TUSB_REQ_GET_STATUS: + { + // Device status bit mask + // - Bit 0: Self Powered + // - Bit 1: Remote Wakeup enabled + uint16_t status = (_usbd_dev.self_powered ? 1 : 0) | (_usbd_dev.remote_wakeup_en ? 2 : 0); + tud_control_xfer(rhport, p_request, &status, 2); + } + break; + + // Unknown/Unsupported request + default: TU_BREAKPOINT(); return false; + } + break; + + //------------- Class/Interface Specific Request -------------// + case TUSB_REQ_RCPT_INTERFACE: + { + uint8_t const itf = tu_u16_low(p_request->wIndex); + TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); + + usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]); + TU_VERIFY(driver); + + // all requests to Interface (STD or Class) is forwarded to class driver. + // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE + if ( !invoke_class_control(rhport, driver, p_request) ) + { + // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class + // driver doesn't use alternate settings or implement this + TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); + + switch(p_request->bRequest) + { + case TUSB_REQ_GET_INTERFACE: + case TUSB_REQ_SET_INTERFACE: + // Clear complete callback if driver set since it can also stall the request. + usbd_control_set_complete_callback(NULL); + + if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) + { + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + }else + { + tud_control_status(rhport, p_request); + } + break; + + default: return false; + } + } + } + break; + + //------------- Endpoint Request -------------// + case TUSB_REQ_RCPT_ENDPOINT: + { + uint8_t const ep_addr = tu_u16_low(p_request->wIndex); + uint8_t const ep_num = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); + + usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); + + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) + { + // Forward class request to its driver + TU_VERIFY(driver); + return invoke_class_control(rhport, driver, p_request); + } + else + { + // Handle STD request to endpoint + switch ( p_request->bRequest ) + { + case TUSB_REQ_GET_STATUS: + { + uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000; + tud_control_xfer(rhport, p_request, &status, 2); + } + break; + + case TUSB_REQ_CLEAR_FEATURE: + case TUSB_REQ_SET_FEATURE: + { + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) + { + if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) + { + usbd_edpt_clear_stall(rhport, ep_addr); + }else + { + usbd_edpt_stall(rhport, ep_addr); + } + } + + if (driver) + { + // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request + // We will also forward std request targeted endpoint to class drivers as well + + // STD request must always be ACKed regardless of driver returned value + // Also clear complete callback if driver set since it can also stall the request. + (void) invoke_class_control(rhport, driver, p_request); + usbd_control_set_complete_callback(NULL); + + // skip ZLP status if driver already did that + if ( !_usbd_dev.ep_status[0][TUSB_DIR_IN].busy ) tud_control_status(rhport, p_request); + } + } + break; + + // Unknown/Unsupported request + default: TU_BREAKPOINT(); return false; + } + } + } + break; + + // Unknown recipient + default: TU_BREAKPOINT(); return false; + } + + return true; +} + +// Process Set Configure Request +// This function parse configuration descriptor & open drivers accordingly +static bool process_set_config(uint8_t rhport, uint8_t cfg_num) +{ + // index is cfg_num-1 + tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); + TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION); + + // Parse configuration descriptor + _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0; + _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED ) ? 1 : 0; + + // Parse interface descriptor + uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); + uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); + + while( p_desc < desc_end ) + { + uint8_t assoc_itf_count = 1; + + // Class will always starts with Interface Association (if any) and then Interface descriptor + if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) + { + tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + assoc_itf_count = desc_iad->bInterfaceCount; + + p_desc = tu_desc_next(p_desc); // next to Interface + + // IAD's first interface number and class should match with opened interface + //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); + } + + TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); + tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + + // Find driver for this interface + uint16_t const remaining_len = desc_end-p_desc; + uint8_t drv_id; + for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) + { + usbd_class_driver_t const *driver = get_driver(drv_id); + uint16_t const drv_len = driver->open(rhport, desc_itf, remaining_len); + + if ( (sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len) ) + { + // Open successfully + TU_LOG2(" %s opened\r\n", driver->name); + + // Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or + // BTH (even CDC) with class in device descriptor (single interface) + if ( assoc_itf_count == 1) + { + #if CFG_TUD_CDC + if ( driver->open == cdcd_open ) assoc_itf_count = 2; + #endif + + #if CFG_TUD_MIDI + if ( driver->open == midid_open ) assoc_itf_count = 2; + #endif + + #if CFG_TUD_BTH && CFG_TUD_BTH_ISO_ALT_COUNT + if ( driver->open == btd_open ) assoc_itf_count = 2; + #endif + } + + // bind (associated) interfaces to found driver + for(uint8_t i=0; ibInterfaceNumber+i; + + // Interface number must not be used already + TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[itf_num]); + _usbd_dev.itf2drv[itf_num] = drv_id; + } + + // bind all endpoints to found driver + tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); + + // next Interface + p_desc += drv_len; + + break; // exit driver find loop + } + } + + // Failed if there is no supported drivers + TU_ASSERT(drv_id < TOTAL_DRIVER_COUNT); + } + + // invoke callback + if (tud_mount_cb) tud_mount_cb(); + + return true; +} + +// return descriptor's buffer and update desc_len +static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request) +{ + tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue); + uint8_t const desc_index = tu_u16_low( p_request->wValue ); + + switch(desc_type) + { + case TUSB_DESC_DEVICE: + { + TU_LOG2(" Device\r\n"); + + void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb(); + + // Only response with exactly 1 Packet if: not addressed and host requested more data than device descriptor has. + // This only happens with the very first get device descriptor and EP0 size = 8 or 16. + if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed && + ((tusb_control_request_t const*) p_request)->wLength > sizeof(tusb_desc_device_t)) + { + // Hack here: we modify the request length to prevent usbd_control response with zlp + // since we are responding with 1 packet & less data than wLength. + tusb_control_request_t mod_request = *p_request; + mod_request.wLength = CFG_TUD_ENDPOINT0_SIZE; + + return tud_control_xfer(rhport, &mod_request, desc_device, CFG_TUD_ENDPOINT0_SIZE); + }else + { + return tud_control_xfer(rhport, p_request, desc_device, sizeof(tusb_desc_device_t)); + } + } + break; + + case TUSB_DESC_BOS: + { + TU_LOG2(" BOS\r\n"); + + // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) + if (!tud_descriptor_bos_cb) return false; + + uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb(); + TU_ASSERT(desc_bos); + + // Use offsetof to avoid pointer to the odd/misaligned address + uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) ); + + return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); + } + break; + + case TUSB_DESC_CONFIGURATION: + case TUSB_DESC_OTHER_SPEED_CONFIG: + { + uintptr_t desc_config; + + if ( desc_type == TUSB_DESC_CONFIGURATION ) + { + TU_LOG2(" Configuration[%u]\r\n", desc_index); + desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index); + }else + { + // Host only request this after getting Device Qualifier descriptor + TU_LOG2(" Other Speed Configuration\r\n"); + TU_VERIFY( tud_descriptor_other_speed_configuration_cb ); + desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index); + } + + TU_ASSERT(desc_config); + + // Use offsetof to avoid pointer to the odd/misaligned address + uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))) ); + + return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); + } + break; + + case TUSB_DESC_STRING: + { + TU_LOG2(" String[%u]\r\n", desc_index); + + // String Descriptor always uses the desc set from user + uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, tu_le16toh(p_request->wIndex)); + TU_VERIFY(desc_str); + + // first byte of descriptor is its size + return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_str, tu_desc_len(desc_str)); + } + break; + + case TUSB_DESC_DEVICE_QUALIFIER: + { + TU_LOG2(" Device Qualifier\r\n"); + + TU_VERIFY( tud_descriptor_device_qualifier_cb ); + + uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); + TU_VERIFY(desc_qualifier); + + // first byte of descriptor is its size + return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_qualifier, tu_desc_len(desc_qualifier)); + } + break; + + default: return false; + } +} + +//--------------------------------------------------------------------+ +// DCD Event Handler +//--------------------------------------------------------------------+ +void dcd_event_handler(dcd_event_t const * event, bool in_isr) +{ + switch (event->event_id) + { + case DCD_EVENT_UNPLUGGED: + _usbd_dev.connected = 0; + _usbd_dev.addressed = 0; + _usbd_dev.cfg_num = 0; + _usbd_dev.suspended = 0; + osal_queue_send(_usbd_q, event, in_isr); + break; + + case DCD_EVENT_SUSPEND: + // NOTE: When plugging/unplugging device, the D+/D- state are unstable and + // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). + // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish + // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected + if ( _usbd_dev.connected ) + { + _usbd_dev.suspended = 1; + osal_queue_send(_usbd_q, event, in_isr); + } + break; + + case DCD_EVENT_RESUME: + // skip event if not connected (especially required for SAMD) + if ( _usbd_dev.connected ) + { + _usbd_dev.suspended = 0; + osal_queue_send(_usbd_q, event, in_isr); + } + break; + + case DCD_EVENT_SOF: + // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup + // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational + if ( _usbd_dev.suspended ) + { + _usbd_dev.suspended = 0; + dcd_event_t const event_resume = { .rhport = event->rhport, .event_id = DCD_EVENT_RESUME }; + osal_queue_send(_usbd_q, &event_resume, in_isr); + } + break; + + default: + osal_queue_send(_usbd_q, event, in_isr); + break; + } +} + +void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) +{ + dcd_event_t event = { .rhport = rhport, .event_id = eid }; + dcd_event_handler(&event, in_isr); +} + +void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) +{ + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_BUS_RESET }; + event.bus_reset.speed = speed; + dcd_event_handler(&event, in_isr); +} + +void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) +{ + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED }; + memcpy(&event.setup_received, setup, 8); + + dcd_event_handler(&event, in_isr); +} + +void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) +{ + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE }; + + event.xfer_complete.ep_addr = ep_addr; + event.xfer_complete.len = xferred_bytes; + event.xfer_complete.result = result; + + dcd_event_handler(&event, in_isr); +} + +//--------------------------------------------------------------------+ +// USBD API For Class Driver +//--------------------------------------------------------------------+ + +// Parse consecutive endpoint descriptors (IN & OUT) +bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in) +{ + for(int i=0; ibDescriptorType && xfer_type == desc_ep->bmAttributes.xfer); + TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); + + if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) + { + (*ep_in) = desc_ep->bEndpointAddress; + }else + { + (*ep_out) = desc_ep->bEndpointAddress; + } + + p_desc = tu_desc_next(p_desc); + } + + return true; +} + +// Helper to defer an isr function +void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) +{ + dcd_event_t event = + { + .rhport = 0, + .event_id = USBD_EVENT_FUNC_CALL, + }; + + event.func_call.func = func; + event.func_call.param = param; + + dcd_event_handler(&event, in_isr); +} + +//--------------------------------------------------------------------+ +// USBD Endpoint API +//--------------------------------------------------------------------+ + +bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) +{ + TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); + + return dcd_edpt_open(rhport, desc_ep); +} + +bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + // TODO add this check later, also make sure we don't starve an out endpoint while suspending + // TU_VERIFY(tud_ready()); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + +#if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); + if (ret) + { + _usbd_dev.ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(_usbd_mutex); +#endif + + return ret; +} + +bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); + if (ret) + { + _usbd_dev.ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(_usbd_mutex); +#endif + + return ret; +} + +bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // TODO skip ready() check for now since enumeration also use this API + // TU_VERIFY(tud_ready()); + + TU_LOG2(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() + // could return and USBD task can preempt and clear the busy + _usbd_dev.ep_status[epnum][dir].busy = true; + + if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) + { + return true; + }else + { + // DCD error, mark endpoint as ready to allow next transfer + _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].claimed = 0; + TU_LOG2("FAILED\r\n"); + TU_BREAKPOINT(); + return false; + } +} + +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return + // and usbd task can preempt and clear the busy + _usbd_dev.ep_status[epnum][dir].busy = true; + + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // DCD error, mark endpoint as ready to allow next transfer + _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } +} + +bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + return _usbd_dev.ep_status[epnum][dir].busy; +} + +void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // only stalled if currently cleared + if ( !_usbd_dev.ep_status[epnum][dir].stalled ) + { + TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr); + dcd_edpt_stall(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = true; + _usbd_dev.ep_status[epnum][dir].busy = true; + } +} + +void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // only clear if currently stalled + if ( _usbd_dev.ep_status[epnum][dir].stalled ) + { + TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr); + dcd_edpt_clear_stall(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = false; + _usbd_dev.ep_status[epnum][dir].busy = false; + } +} + +bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + return _usbd_dev.ep_status[epnum][dir].stalled; +} + +/** + * usbd_edpt_close will disable an endpoint. + * + * In progress transfers on this EP may be delivered after this call. + * + */ +void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + TU_ASSERT(dcd_edpt_close, /**/); + TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + dcd_edpt_close(rhport, ep_addr); + _usbd_dev.ep_status[epnum][dir].stalled = false; + _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].claimed = false; + + return; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h new file mode 100644 index 000000000..ec34817fa --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h @@ -0,0 +1,853 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_USBD_H_ +#define _TUSB_USBD_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// Init device stack +bool tud_init (uint8_t rhport); + +// Check if device stack is already initialized +bool tud_inited(void); + +// Task function should be called in main/rtos loop +void tud_task (void); + +// Check if there is pending events need proccessing by tud_task() +bool tud_task_event_ready(void); + +// Interrupt handler, name alias to DCD +extern void dcd_int_handler(uint8_t rhport); +#define tud_int_handler dcd_int_handler + +// Get current bus speed +tusb_speed_t tud_speed_get(void); + +// Check if device is connected (may not mounted/configured yet) +// True if just got out of Bus Reset and received the very first data from host +bool tud_connected(void); + +// Check if device is connected and configured +bool tud_mounted(void); + +// Check if device is suspended +bool tud_suspended(void); + +// Check if device is ready to transfer +TU_ATTR_ALWAYS_INLINE static inline +bool tud_ready(void) +{ + return tud_mounted() && !tud_suspended(); +} + +// Remote wake up host, only if suspended and enabled by host +bool tud_remote_wakeup(void); + +// Enable pull-up resistor on D+ D- +// Return false on unsupported MCUs +bool tud_disconnect(void); + +// Disable pull-up resistor on D+ D- +// Return false on unsupported MCUs +bool tud_connect(void); + +// Carry out Data and Status stage of control transfer +// - If len = 0, it is equivalent to sending status only +// - If len > wLength : it will be truncated +bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len); + +// Send STATUS (zero length) packet +bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request); + +//--------------------------------------------------------------------+ +// Application Callbacks (WEAK is optional) +//--------------------------------------------------------------------+ + +// Invoked when received GET DEVICE DESCRIPTOR request +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void); + +// Invoked when received GET CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index); + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); + +// Invoked when received GET BOS DESCRIPTOR request +// Application return pointer to descriptor +TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index); + +// Invoked when device is mounted (configured) +TU_ATTR_WEAK void tud_mount_cb(void); + +// Invoked when device is unmounted +TU_ATTR_WEAK void tud_umount_cb(void); + +// Invoked when usb bus is suspended +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en); + +// Invoked when usb bus is resumed +TU_ATTR_WEAK void tud_resume_cb(void); + +// Invoked when received control request with VENDOR TYPE +TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + +//--------------------------------------------------------------------+ +// Binary Device Object Store (BOS) Descriptor Templates +//--------------------------------------------------------------------+ + +#define TUD_BOS_DESC_LEN 5 + +// total length, number of device caps +#define TUD_BOS_DESCRIPTOR(_total_len, _caps_num) \ + 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num + +// Device Capability Platform 128-bit UUID + Data +#define TUD_BOS_PLATFORM_DESCRIPTOR(...) \ + 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ + +//------------- WebUSB BOS Platform -------------// + +// Descriptor Length +#define TUD_BOS_WEBUSB_DESC_LEN 24 + +// Vendor Code, iLandingPage +#define TUD_BOS_WEBUSB_DESCRIPTOR(_vendor_code, _ipage) \ + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) + +#define TUD_BOS_WEBUSB_UUID \ + 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ + 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 + +//------------- Microsoft OS 2.0 Platform -------------// +#define TUD_BOS_MICROSOFT_OS_DESC_LEN 28 + +// Total Length of descriptor set, vendor code +#define TUD_BOS_MS_OS_20_DESCRIPTOR(_desc_set_len, _vendor_code) \ + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) + +#define TUD_BOS_MS_OS_20_UUID \ + 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ + 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F + +//--------------------------------------------------------------------+ +// Configuration Descriptor Templates +//--------------------------------------------------------------------+ + +#define TUD_CONFIG_DESC_LEN (9) + +// Config number, interface count, string index, total length, attribute, power in mA +#define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ + 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 + +//--------------------------------------------------------------------+ +// CDC Descriptor Templates +//--------------------------------------------------------------------+ + +// Length of template descriptor: 66 bytes +#define TUD_CDC_DESC_LEN (8+9+5+5+4+5+7+9+7+7) + +// CDC Descriptor Template +// Interface number, string index, EP notification address and size, EP data address (out, in) and size. +#define TUD_CDC_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ + /* Interface Associate */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ + /* CDC Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC Call */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* CDC ACM: support line request */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + +//--------------------------------------------------------------------+ +// MSC Descriptor Templates +//--------------------------------------------------------------------+ + +// Length of template descriptor: 23 bytes +#define TUD_MSC_DESC_LEN (9 + 7 + 7) + +// Interface number, string index, EP Out & EP In address, EP size +#define TUD_MSC_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + + +//--------------------------------------------------------------------+ +// HID Descriptor Templates +//--------------------------------------------------------------------+ + +// Length of template descriptor: 25 bytes +#define TUD_HID_DESC_LEN (9 + 9 + 7) + +// HID Input only descriptor +// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval +#define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + +// Length of template descriptor: 32 bytes +#define TUD_HID_INOUT_DESC_LEN (9 + 9 + 7 + 7) + +// HID Input & Output descriptor +// Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval +#define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + +//--------------------------------------------------------------------+ +// MIDI Descriptor Templates +// Note: MIDI v1.0 is based on Audio v1.0 +//--------------------------------------------------------------------+ + +#define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) +#define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ + /* Audio Control (AC) Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ + /* AC Header */\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ + /* MIDI Streaming (MS) Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ + /* MS Header */\ + 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) + +#define TUD_MIDI_JACKID_IN_EMB(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 1) + +#define TUD_MIDI_JACKID_IN_EXT(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 2) + +#define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 3) + +#define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 4) + +#define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9) +#define TUD_MIDI_DESC_JACK(_cablenum) \ + /* MS In Jack (Embedded) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ + /* MS In Jack (External) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ + /* MS Out Jack (Embedded), connected to In Jack External */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ + /* MS Out Jack (External), connected to In Jack Embedded */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 + +#define TUD_MIDI_DESC_EP_LEN(_numcables) (9 + 4 + (_numcables)) +#define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ + /* Endpoint: Note Audio v1.0's endpoint has 9 bytes instead of 7 */\ + 9, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, 0, 0, \ + /* MS Endpoint (connected to embedded jack) */\ + (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables + +// Length of template descriptor (88 bytes) +#define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2) + +// MIDI simple descriptor +// - 1 Embedded Jack In connected to 1 External Jack Out +// - 1 Embedded Jack out connected to 1 External Jack In +#define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ + TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ + TUD_MIDI_DESC_JACK(1),\ + TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ + TUD_MIDI_JACKID_IN_EMB(1),\ + TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ + TUD_MIDI_JACKID_OUT_EMB(1) + +//--------------------------------------------------------------------+ +// Audio v2.0 Descriptor Templates +//--------------------------------------------------------------------+ + +/* Standard Interface Association Descriptor (IAD) */ +#define TUD_AUDIO_DESC_IAD_LEN 8 +#define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx + +/* Standard AC Interface Descriptor(4.7.1) */ +#define TUD_AUDIO_DESC_STD_AC_LEN 9 +#define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ + TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx + +/* Class-Specific AC Interface Header Descriptor(4.7.2) */ +#define TUD_AUDIO_DESC_CS_AC_LEN 9 +#define TUD_AUDIO_DESC_CS_AC(_bcdADC, _category, _totallen, _ctrl) /* _bcdADC : Audio Device Class Specification Release Number in Binary-Coded Decimal, _category : see audio_function_t, _totallen : Total number of bytes returned for the class-specific AudioControl interface i.e. Clock Source, Unit and Terminal descriptors - Do not include TUD_AUDIO_DESC_CS_AC_LEN, we already do this here*/ \ + TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl + +/* Clock Source Descriptor(4.7.2.1) */ +#define TUD_AUDIO_DESC_CLK_SRC_LEN 8 +#define TUD_AUDIO_DESC_CLK_SRC(_clkid, _attr, _ctrl, _assocTerm, _stridx) \ + TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx + +/* Input Terminal Descriptor(4.7.2.4) */ +#define TUD_AUDIO_DESC_INPUT_TERM_LEN 17 +#define TUD_AUDIO_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _clkid, _nchannelslogical, _channelcfg, _idxchannelnames, _ctrl, _stridx) \ + TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx + +/* Output Terminal Descriptor(4.7.2.5) */ +#define TUD_AUDIO_DESC_OUTPUT_TERM_LEN 12 +#define TUD_AUDIO_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _clkid, _ctrl, _stridx) \ + TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx + +/* Feature Unit Descriptor(4.7.2.8) */ +// 1 - Channel +#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN 6+(1+1)*4 +#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx + +// 2 - Channels +#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN (6+(2+1)*4) +#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), _stridx +// 4 - Channels +#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN (6+(4+1)*4) +#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _ctrlch3, _ctrlch4, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), U32_TO_U8S_LE(_ctrlch3), U32_TO_U8S_LE(_ctrlch4), _stridx + +// For more channels, add definitions here + +/* Standard AS Interface Descriptor(4.9.1) */ +#define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 +#define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ + TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx + +/* Class-Specific AS Interface Descriptor(4.9.2) */ +#define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 +#define TUD_AUDIO_DESC_CS_AS_INT(_termid, _ctrl, _formattype, _formats, _nchannelsphysical, _channelcfg, _stridx) \ + TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx + +/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ +#define TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN 6 +#define TUD_AUDIO_DESC_TYPE_I_FORMAT(_subslotsize, _bitresolution) /* _subslotsize is number of bytes per sample (i.e. subslot) and can be 1,2,3, or 4 */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution + +/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ +#define TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN 7 +#define TUD_AUDIO_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval) \ + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval + +/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ +#define TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN 8 +#define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) + +/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ +#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 +#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval + +// AUDIO simple descriptor (UAC2) for 1 microphone input +// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source + +#define TUD_AUDIO_MIC_ONE_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + +#define TUD_AUDIO_MIC_ONE_CH_DESC_N_AS_INT 1 // Number of AS interfaces + +#define TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + +// AUDIO simple descriptor (UAC2) for 4 microphone input +// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source + +#define TUD_AUDIO_MIC_FOUR_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + +#define TUD_AUDIO_MIC_FOUR_CH_DESC_N_AS_INT 1 // Number of AS interfaces + +#define TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch2*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch3*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch4*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + +// AUDIO simple descriptor (UAC2) for mono speaker +// - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source + +#define TUD_AUDIO_SPEAKER_MONO_FB_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) + +#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ + /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ + +// Calculate wMaxPacketSize of Endpoints +#define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \ + ((((_maxFrequency + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 7999 : 999)) / ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels) + + +//--------------------------------------------------------------------+ +// USBTMC/USB488 Descriptor Templates +//--------------------------------------------------------------------+ + +#define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) +#define TUD_USBTMC_APP_SUBCLASS 0x03u + +#define TUD_USBTMC_PROTOCOL_STD 0x00u +#define TUD_USBTMC_PROTOCOL_USB488 0x01u + +// Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, +// bulk-in endpoint ID +#define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ + /* Interface */ \ + 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx + +#define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u + +#define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \ + /* Endpoint Out */ \ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ + /* Endpoint In */ \ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u + +#define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) + +/* optional interrupt endpoint */ \ +// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? +#define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ + 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 + +#define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) + +//--------------------------------------------------------------------+ +// Vendor Descriptor Templates +//--------------------------------------------------------------------+ + +#define TUD_VENDOR_DESC_LEN (9+7+7) + +// Interface number, string index, EP Out & IN address, EP size +#define TUD_VENDOR_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + +//--------------------------------------------------------------------+ +// DFU Runtime Descriptor Templates +//--------------------------------------------------------------------+ + +#define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) +#define TUD_DFU_APP_SUBCLASS (APP_SUBCLASS_DFU_RUNTIME) + +// Length of template descriptr: 18 bytes +#define TUD_DFU_RT_DESC_LEN (9 + 9) + +// DFU runtime descriptor +// Interface number, string index, attributes, detach timeout, transfer size +#define TUD_DFU_RT_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \ + /* Function */ \ + 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) + +//--------------------------------------------------------------------+ +// DFU Descriptor Templates +//--------------------------------------------------------------------+ + +// Length of template descriptor: 9 bytes + number of alternatives * 9 +#define TUD_DFU_DESC_LEN(_alt_count) (9 + (_alt_count) * 9) + +// Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size +// Note: Alternate count must be numberic or macro, string index is increased by one for each Alt interface +#define TUD_DFU_DESCRIPTOR(_itfnum, _alt_count, _stridx, _attr, _timeout, _xfer_size) \ + TU_XSTRCAT(_TUD_DFU_ALT_,_alt_count)(_itfnum, 0, _stridx), \ + /* Function */ \ + 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) + +#define _TUD_DFU_ALT(_itfnum, _alt, _stridx) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx + +#define _TUD_DFU_ALT_1(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx) + +#define _TUD_DFU_ALT_2(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_1(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_3(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_2(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_4(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_3(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_5(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_4(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_6(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_5(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_7(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_6(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_8(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) + +//--------------------------------------------------------------------+ +// CDC-ECM Descriptor Templates +//--------------------------------------------------------------------+ + +// Length of template descriptor: 71 bytes +#define TUD_CDC_ECM_DESC_LEN (8+9+5+5+13+7+9+9+7+7) + +// CDC-ECM Descriptor Template +// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. +#define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, _desc_stridx,\ + /* CDC-ECM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC-ECM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-ECM Functional Descriptor */\ + 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface (default inactive) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* CDC Data Interface (alternative active) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + +//--------------------------------------------------------------------+ +// RNDIS Descriptor Templates +//--------------------------------------------------------------------+ + +#if 0 +/* Windows XP */ +#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC +#define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL +#define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ +#else +/* Windows 7+ */ +#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER +#define TUD_RNDIS_ITF_SUBCLASS 0x01 +#define TUD_RNDIS_ITF_PROTOCOL 0x03 +#endif + +// Length of template descriptor: 66 bytes +#define TUD_RNDIS_DESC_LEN (8+9+5+5+4+5+7+9+7+7) + +// RNDIS Descriptor Template +// Interface number, string index, EP notification address and size, EP data address (out, in) and size. +#define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ + /* CDC-ACM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC Call Management */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* ACM */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + +//--------------------------------------------------------------------+ +// Bluetooth Radio Descriptor Templates +//--------------------------------------------------------------------+ + +#define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) +#define TUD_BT_APP_SUBCLASS 0x01 +#define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 +#define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02 + +#ifndef CFG_TUD_BTH_ISO_ALT_COUNT +#define CFG_TUD_BTH_ISO_ALT_COUNT 0 +#endif + +// Length of template descriptor: 38 bytes + number of ISO alternatives * 23 +#define TUD_BTH_DESC_LEN (8 + 9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) + +/* Primary Interface */ +#define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, _stridx, \ + /* Endpoint In for events */ \ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ + /* Endpoint In for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ + /* Endpoint Out for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 + +#define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ + /* Interface with 2 endpoints */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Isochronous endpoints */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 + +#define _FIRST(a, ...) a +#define _REST(a, ...) __VA_ARGS__ + +#define TUD_BTH_ISO_ITF_0(_itfnum, ...) +#define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + +#define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ + TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) + +// BT Primary controller descriptor +// Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes +// TODO BTH should also use IAD like CDC for composite device +#define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ + /* Interface Associate */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0,\ + TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) + +//--------------------------------------------------------------------+ +// CDC-NCM Descriptor Templates +//--------------------------------------------------------------------+ + +// Length of template descriptor +#define TUD_CDC_NCM_DESC_LEN (8+9+5+5+13+6+7+9+9+7+7) + +// CDC-ECM Descriptor Template +// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. +#define TUD_CDC_NCM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, _desc_stridx,\ + /* CDC-NCM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC-NCM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-NCM Functional Descriptor */\ + 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0, \ + /* CDC-NCM Functional Descriptor */\ + 6, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_NCM, U16_TO_U8S_LE(0x0100), 0, \ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 50,\ + /* CDC Data Interface (default inactive) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK, 0,\ + /* CDC Data Interface (alternative active) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK, 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_USBD_H_ */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c new file mode 100644 index 000000000..7a8244699 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c @@ -0,0 +1,233 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED + +#include "tusb.h" +#include "device/usbd_pvt.h" +#include "dcd.h" + +#if CFG_TUSB_DEBUG >= 2 +extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); +#endif + +enum +{ + EDPT_CTRL_OUT = 0x00, + EDPT_CTRL_IN = 0x80 +}; + +typedef struct +{ + tusb_control_request_t request; + + uint8_t* buffer; + uint16_t data_len; + uint16_t total_xferred; + + usbd_control_xfer_cb_t complete_cb; +} usbd_control_xfer_t; + +static usbd_control_xfer_t _ctrl_xfer; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// Queue ZLP status transaction +static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) +{ + // Opposite to endpoint in Data Phase + uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); +} + +// Status phase +bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) +{ + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = NULL; + _ctrl_xfer.total_xferred = 0; + _ctrl_xfer.data_len = 0; + + return _status_stage_xact(rhport, request); +} + +// Queue a transaction in Data Stage +// Each transaction has up to Endpoint0's max packet size. +// This function can also transfer an zero-length packet +static bool _data_stage_xact(uint8_t rhport) +{ + uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE); + + uint8_t ep_addr = EDPT_CTRL_OUT; + + if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN ) + { + ep_addr = EDPT_CTRL_IN; + if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); + } + + return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); +} + +// Transmit data to/from the control endpoint. +// If the request's wLength is zero, a status packet is sent instead. +bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) +{ + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = (uint8_t*) buffer; + _ctrl_xfer.total_xferred = 0U; + _ctrl_xfer.data_len = tu_min16(len, request->wLength); + + if (request->wLength > 0U) + { + if(_ctrl_xfer.data_len > 0U) + { + TU_ASSERT(buffer); + } + +// TU_LOG2(" Control total data length is %u bytes\r\n", _ctrl_xfer.data_len); + + // Data stage + TU_ASSERT( _data_stage_xact(rhport) ); + } + else + { + // Status stage + TU_ASSERT( _status_stage_xact(rhport, request) ); + } + + return true; +} + +//--------------------------------------------------------------------+ +// USBD API +//--------------------------------------------------------------------+ + +void usbd_control_reset(void); +void usbd_control_set_request(tusb_control_request_t const *request); +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); +bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + +void usbd_control_reset(void) +{ + tu_varclr(&_ctrl_xfer); +} + +// Set complete callback +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) +{ + _ctrl_xfer.complete_cb = fp; +} + +// for dcd_set_address where DCD is responsible for status response +void usbd_control_set_request(tusb_control_request_t const *request) +{ + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = NULL; + _ctrl_xfer.total_xferred = 0; + _ctrl_xfer.data_len = 0; +} + +// callback when a transaction complete on +// - DATA stage of control endpoint or +// - Status stage +bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) result; + + // Endpoint Address is opposite to direction bit, this is Status Stage complete event + if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) + { + TU_ASSERT(0 == xferred_bytes); + + // invoke optional dcd hook if available + if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); + + if (_ctrl_xfer.complete_cb) + { + // TODO refactor with usbd_driver_print_control_complete_name + _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); + } + + return true; + } + + if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT ) + { + TU_VERIFY(_ctrl_xfer.buffer); + memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); + TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2); + } + + _ctrl_xfer.total_xferred += xferred_bytes; + _ctrl_xfer.buffer += xferred_bytes; + + // Data Stage is complete when all request's length are transferred or + // a short packet is sent including zero-length packet. + if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE) ) + { + // DATA stage is complete + bool is_ok = true; + + // invoke complete callback if set + // callback can still stall control in status phase e.g out data does not make sense + if ( _ctrl_xfer.complete_cb ) + { + #if CFG_TUSB_DEBUG >= 2 + usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); + #endif + + is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request); + } + + if ( is_ok ) + { + // Send status + TU_ASSERT( _status_stage_xact(rhport, &_ctrl_xfer.request) ); + }else + { + // Stall both IN and OUT control endpoint + dcd_edpt_stall(rhport, EDPT_CTRL_OUT); + dcd_edpt_stall(rhport, EDPT_CTRL_IN); + } + } + else + { + // More data to transfer + TU_ASSERT( _data_stage_xact(rhport) ); + } + + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h new file mode 100644 index 000000000..7607b9895 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ +#ifndef USBD_PVT_H_ +#define USBD_PVT_H_ + +#include "osal/osal.h" +#include "common/tusb_fifo.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver API +//--------------------------------------------------------------------+ + +typedef struct +{ + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif + + void (* init ) (void); + void (* reset ) (uint8_t rhport); + uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); + bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* sof ) (uint8_t rhport); /* optional */ +} usbd_class_driver_t; + +// Invoked when initializing device stack to get additional class drivers. +// Can optionally implemented by application to extend/overwrite class driver support. +// Note: The drivers array must be accessible at all time when stack is active +usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; + +typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + +//--------------------------------------------------------------------+ +// USBD Endpoint API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); + +// Close an endpoint +void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); + +// Submit a usb transfer +bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +// Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); + +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. +bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); + +// Release an endpoint without submitting a transfer +bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr); + +// Check if endpoint is busy transferring +bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); + +// Stall endpoint +void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr); + +// Clear stalled endpoint +void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr); + +// Check if endpoint is stalled +bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr); + +// Check if endpoint is ready (not busy and not stalled) +TU_ATTR_ALWAYS_INLINE static inline +bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) +{ + return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); +} + +/*------------------------------------------------------------------*/ +/* Helper + *------------------------------------------------------------------*/ + +bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in); +void usbd_defer_func( osal_task_func_t func, void* param, bool in_isr ); + + +#ifdef __cplusplus + } +#endif + +#endif /* USBD_PVT_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h new file mode 100644 index 000000000..eb53d2e80 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h @@ -0,0 +1,179 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_HCD_H_ +#define _TUSB_HCD_H_ + +#include "common/tusb_common.h" +#include "osal/osal.h" +#include "common/tusb_fifo.h" +#include "hcd_attr.h" + +#ifdef __cplusplus + extern "C" { +#endif + + //--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef enum +{ + HCD_EVENT_DEVICE_ATTACH, + HCD_EVENT_DEVICE_REMOVE, + HCD_EVENT_XFER_COMPLETE, + + // Not an HCD event, just a convenient way to defer ISR function + USBH_EVENT_FUNC_CALL, + + HCD_EVENT_COUNT +} hcd_eventid_t; + +typedef struct +{ + uint8_t rhport; + uint8_t event_id; + uint8_t dev_addr; + + union + { + // Attach, Remove + struct { + uint8_t hub_addr; + uint8_t hub_port; + uint8_t speed; + } connection; + + // XFER_COMPLETE + struct { + uint8_t ep_addr; + uint8_t result; + uint32_t len; + } xfer_complete; + + // FUNC_CALL + struct { + void (*func) (void*); + void* param; + }func_call; + }; + +} hcd_event_t; + +#if TUSB_OPT_HOST_ENABLED +// Max number of endpoints per device +enum { + // TODO better computation + HCD_MAX_ENDPOINT = CFG_TUH_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3), + HCD_MAX_XFER = HCD_MAX_ENDPOINT*2, +}; + +//#define HCD_MAX_ENDPOINT 16 +//#define HCD_MAX_XFER 16 + +typedef struct { + uint8_t rhport; + uint8_t hub_addr; + uint8_t hub_port; + uint8_t speed; +} hcd_devtree_info_t; + +#endif + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +// Initialize controller to host mode +bool hcd_init(uint8_t rhport); + +// Interrupt Handler +void hcd_int_handler(uint8_t rhport); + +// Enable USB interrupt +void hcd_int_enable (uint8_t rhport); + +// Disable USB interrupt +void hcd_int_disable(uint8_t rhport); + +// Get frame number (1ms) +uint32_t hcd_frame_number(uint8_t rhport); + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport); + +// Reset USB bus on the port +void hcd_port_reset(uint8_t rhport); + +// TODO implement later +void hcd_port_reset_end(uint8_t rhport); + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport); + +// HCD closes all opened endpoints belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr); + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); +bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); + +//--------------------------------------------------------------------+ +// USBH implemented API +//--------------------------------------------------------------------+ + +// Get device tree information of a device +// USB device tree can be complicated and manged by USBH, this help HCD to retrieve +// needed topology info to carry out its work +extern void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info); + +//------------- Event API -------------// + +// Called by HCD to notify stack +extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); + +// Helper to send device attach event +extern void hcd_event_device_attach(uint8_t rhport, bool in_isr); + +// Helper to send device removal event +extern void hcd_event_device_remove(uint8_t rhport, bool in_isr); + +// Helper to send USB transfer event +extern void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_HCD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h new file mode 100644 index 000000000..06011c63c --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h @@ -0,0 +1,105 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_HCD_ATTR_H_ +#define TUSB_HCD_ATTR_H_ + +#include "tusb_option.h" + +// Attribute includes +// - ENDPOINT_MAX: max (logical) number of endpoint +// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. + +//------------- NXP -------------// +#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) + #define HCD_ATTR_OHCI + +#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) + #define HCD_ATTR_EHCI_TRANSDIMENSION + +#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) + // #define HCD_ATTR_EHCI_NXP_PTD + +#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) + // #define HCD_ATTR_EHCI_NXP_PTD + +#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX) + #define HCD_ATTR_EHCI_TRANSDIMENSION + +#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX) + +//------------- Microchip -------------// +#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ + TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) + +#elif TU_CHECK_MCU(OPT_MCU_SAMG) + +#elif TU_CHECK_MCU(OPT_MCU_SAMX7X) + +//------------- ST -------------// +#elif TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F1, OPT_MCU_STM32F3) || \ + TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1, OPT_MCU_STM32L4) + +#elif TU_CHECK_MCU(OPT_MCU_STM32F2, OPT_MCU_STM32F3, OPT_MCU_STM32F4) + +#elif TU_CHECK_MCU(OPT_MCU_STM32F7) + +#elif TU_CHECK_MCU(OPT_MCU_STM32H7) + +//------------- Sony -------------// +#elif TU_CHECK_MCU(OPT_MCU_CXD56) + +//------------- Nuvoton -------------// +#elif TU_CHECK_MCU(OPT_MCU_NUC505) + +//------------- Espressif -------------// +#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + +//------------- Raspberry Pi -------------// +#elif TU_CHECK_MCU(OPT_MCU_RP2040) + +//------------- Silabs -------------// +#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) + +//------------- Renesas -------------// +#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) + +//#elif TU_CHECK_MCU(OPT_MCU_MM32F327X) +// #define DCD_ATTR_ENDPOINT_MAX not known yet + +//------------- GigaDevice -------------// +#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) + +#else +// #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" +#endif + +// Default to fullspeed if not defined +//#ifndef PORT_HIGHSPEED +// #define DCD_ATTR_PORT_HIGHSPEED 0x00 +//#endif + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c new file mode 100644 index 000000000..fd4dbd04a --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c @@ -0,0 +1,388 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HUB) + +#include "usbh.h" +#include "usbh_classdriver.h" +#include "hub.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_in; + uint8_t port_count; + uint8_t status_change; // data from status change interrupt endpoint + + hub_port_status_response_t port_status; +} hub_interface_t; + +CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB]; +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)]; + +TU_ATTR_ALWAYS_INLINE +static inline hub_interface_t* get_itf(uint8_t dev_addr) +{ + return &hub_data[dev_addr-1-CFG_TUH_DEVICE_MAX]; +} + +#if CFG_TUSB_DEBUG +static char const* const _hub_feature_str[] = +{ + [HUB_FEATURE_PORT_CONNECTION ] = "PORT_CONNECTION", + [HUB_FEATURE_PORT_ENABLE ] = "PORT_ENABLE", + [HUB_FEATURE_PORT_SUSPEND ] = "PORT_SUSPEND", + [HUB_FEATURE_PORT_OVER_CURRENT ] = "PORT_OVER_CURRENT", + [HUB_FEATURE_PORT_RESET ] = "PORT_RESET", + [HUB_FEATURE_PORT_POWER ] = "PORT_POWER", + [HUB_FEATURE_PORT_LOW_SPEED ] = "PORT_LOW_SPEED", + [HUB_FEATURE_PORT_CONNECTION_CHANGE ] = "PORT_CONNECTION_CHANGE", + [HUB_FEATURE_PORT_ENABLE_CHANGE ] = "PORT_ENABLE_CHANGE", + [HUB_FEATURE_PORT_SUSPEND_CHANGE ] = "PORT_SUSPEND_CHANGE", + [HUB_FEATURE_PORT_OVER_CURRENT_CHANGE ] = "PORT_OVER_CURRENT_CHANGE", + [HUB_FEATURE_PORT_RESET_CHANGE ] = "PORT_RESET_CHANGE", + [HUB_FEATURE_PORT_TEST ] = "PORT_TEST", + [HUB_FEATURE_PORT_INDICATOR ] = "PORT_INDICATOR", +}; +#endif + +//--------------------------------------------------------------------+ +// HUB +//--------------------------------------------------------------------+ +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb) +{ + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HUB_REQUEST_CLEAR_FEATURE, + .wValue = feature, + .wIndex = hub_port, + .wLength = 0 + }; + + TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); + TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); + return true; +} + +bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb) +{ + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HUB_REQUEST_SET_FEATURE, + .wValue = feature, + .wIndex = hub_port, + .wLength = 0 + }; + + TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); + TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); + return true; +} + +bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb) +{ + return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb); +} + +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb) +{ + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HUB_REQUEST_GET_STATUS, + .wValue = 0, + .wIndex = hub_port, + .wLength = 4 + }; + + TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); + TU_ASSERT( tuh_control_xfer( hub_addr, &request, resp, complete_cb) ); + return true; +} + +//--------------------------------------------------------------------+ +// CLASS-USBH API (don't require to verify parameters) +//--------------------------------------------------------------------+ +void hub_init(void) +{ + tu_memclr(hub_data, sizeof(hub_data)); +} + +bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +{ + TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && + 0 == itf_desc->bInterfaceSubClass); + + // hub driver does not support multiple TT yet + TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); + + // msc driver length is fixed + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); + TU_ASSERT(drv_len <= max_len); + + //------------- Interrupt Status endpoint -------------// + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && + TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); + + hub_interface_t* p_hub = get_itf(dev_addr); + + p_hub->itf_num = itf_desc->bInterfaceNumber; + p_hub->ep_in = desc_ep->bEndpointAddress; + + return true; +} + +void hub_close(uint8_t dev_addr) +{ + TU_VERIFY(dev_addr > CFG_TUH_DEVICE_MAX, ); + hub_interface_t* p_hub = get_itf(dev_addr); + + if (p_hub->ep_in) tu_memclr(p_hub, sizeof( hub_interface_t)); +} + +bool hub_status_pipe_queue(uint8_t dev_addr) +{ + hub_interface_t* hub_itf = get_itf(dev_addr); + return usbh_edpt_xfer(dev_addr, hub_itf->ep_in, &hub_itf->status_change, 1); +} + + +//--------------------------------------------------------------------+ +// Set Configure +//--------------------------------------------------------------------+ + +static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + +bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + hub_interface_t* p_hub = get_itf(dev_addr); + TU_ASSERT(itf_num == p_hub->itf_num); + + // Get Hub Descriptor + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HUB_REQUEST_GET_DESCRIPTOR, + .wValue = 0, + .wIndex = 0, + .wLength = sizeof(descriptor_hub_desc_t) + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, _hub_buffer, config_set_port_power) ); + + return true; +} + +static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + hub_interface_t* p_hub = get_itf(dev_addr); + + // only use number of ports in hub descriptor + descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer; + p_hub->port_count = desc_hub->bNbrPorts; + + // May need to GET_STATUS + + // Set Port Power to be able to detect connection, starting with port 1 + uint8_t const hub_port = 1; + return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); +} + +static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(XFER_RESULT_SUCCESS == result); + hub_interface_t* p_hub = get_itf(dev_addr); + + if (request->wIndex == p_hub->port_count) + { + // All ports are power -> queue notification status endpoint and + // complete the SET CONFIGURATION + TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1) ); + + usbh_driver_set_config_complete(dev_addr, p_hub->itf_num); + }else + { + // power next port + uint8_t const hub_port = (uint8_t) (request->wIndex + 1); + return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); + } + + return true; +} + +//--------------------------------------------------------------------+ +// Connection Changes +//--------------------------------------------------------------------+ + +static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + +// callback as response of interrupt endpoint polling +bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports + (void) ep_addr; + TU_ASSERT(result == XFER_RESULT_SUCCESS); + + hub_interface_t* p_hub = get_itf(dev_addr); + + TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change); + + // Hub ignore bit0 in status change + for (uint8_t port=1; port <= p_hub->port_count; port++) + { + if ( tu_bit_test(p_hub->status_change, port) ) + { + hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete); + break; + } + } + + // NOTE: next status transfer is queued by usbh.c after handling this request + + return true; +} + +static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(result == XFER_RESULT_SUCCESS); + + hub_interface_t* p_hub = get_itf(dev_addr); + uint8_t const port_num = (uint8_t) request->wIndex; + + // Connection change + if (p_hub->port_status.change.connection) + { + // Port is powered and enabled + //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); + + // Acknowledge Port Connection Change + hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete); + }else + { + // Other changes are: Enable, Suspend, Over Current, Reset, L1 state + // TODO clear change + + // prepare for next hub status + // TODO continue with status_change, or maybe we can do it again with status + hub_status_pipe_queue(dev_addr); + } + + return true; +} + +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(result == XFER_RESULT_SUCCESS); + + hub_interface_t* p_hub = get_itf(dev_addr); + uint8_t const port_num = (uint8_t) request->wIndex; + + if ( p_hub->port_status.status.connection ) + { + // Reset port if attach event + hub_port_reset(dev_addr, port_num, connection_port_reset_complete); + }else + { + // submit detach event + hcd_event_t event = + { + .rhport = usbh_get_rhport(dev_addr), + .event_id = HCD_EVENT_DEVICE_REMOVE, + .connection = + { + .hub_addr = dev_addr, + .hub_port = port_num + } + }; + + hcd_event_handler(&event, false); + } + + return true; +} + +static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(result == XFER_RESULT_SUCCESS); + + // hub_interface_t* p_hub = get_itf(dev_addr); + uint8_t const port_num = (uint8_t) request->wIndex; + + // submit attach event + hcd_event_t event = + { + .rhport = usbh_get_rhport(dev_addr), + .event_id = HCD_EVENT_DEVICE_ATTACH, + .connection = + { + .hub_addr = dev_addr, + .hub_port = port_num + } + }; + + hcd_event_handler(&event, false); + + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h new file mode 100644 index 000000000..c4d544193 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h @@ -0,0 +1,196 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup group_class + * \defgroup ClassDriver_Hub Hub (Host only) + * \details Like most PC's OS, Hub support is completely hidden from Application. In fact, application cannot determine whether + * a device is mounted directly via roothub or via a hub's port. All Hub-related procedures are performed and managed + * by tinyusb stack. Unless you are trying to develop the stack itself, there are nothing else can be used by Application. + * \note Due to my laziness, only 1-level of Hub is supported. In other way, the stack cannot mount a hub via another hub. + * @{ + */ + +#ifndef _TUSB_HUB_H_ +#define _TUSB_HUB_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//D1...D0: Logical Power Switching Mode +//00: Ganged power switching (all ports’power at +//once) +//01: Individual port power switching +//1X: Reserved. Used only on 1.0 compliant hubs +//that implement no power switching +//D2: Identifies a Compound Device +//0: Hub is not part of a compound device. +//1: Hub is part of a compound device. +//D4...D3: Over-current Protection Mode +//00: Global Over-current Protection. The hub +//reports over-current as a summation of all +//ports’current draw, without a breakdown of +//individual port over-current status. +//01: Individual Port Over-current Protection. The +//hub reports over-current on a per-port basis. +//Each port has an over-current status. +//1X: No Over-current Protection. This option is +//allowed only for bus-powered hubs that do not +//implement over-current protection. +// +//D6...D5: TT Think TIme +//00: TT requires at most 8 FS bit times of inter +//transaction gap on a full-/low-speed +//downstream bus. +//01: TT requires at most 16 FS bit times. +//10: TT requires at most 24 FS bit times. +//11: TT requires at most 32 FS bit times. +//D7: Port Indicators Supported +//0: Port Indicators are not supported on its +//downstream facing ports and the +//PORT_INDICATOR request has no effect. +//1: Port Indicators are supported on its +//downstream facing ports and the +//PORT_INDICATOR request controls the +//indicators. See Section 11.5.3. +//D15...D8: Reserved + +typedef struct TU_ATTR_PACKED{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + uint8_t bNbrPorts; + uint16_t wHubCharacteristics; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; // bitmap each bit for a port (from bit1) + uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff +} descriptor_hub_desc_t; + +TU_VERIFY_STATIC( sizeof(descriptor_hub_desc_t) == 9, "size is not correct"); + +enum { + HUB_REQUEST_GET_STATUS = 0 , + HUB_REQUEST_CLEAR_FEATURE = 1 , + + HUB_REQUEST_SET_FEATURE = 3 , + + HUB_REQUEST_GET_DESCRIPTOR = 6 , + HUB_REQUEST_SET_DESCRIPTOR = 7 , + HUB_REQUEST_CLEAR_TT_BUFFER = 8 , + HUB_REQUEST_RESET_TT = 9 , + HUB_REQUEST_GET_TT_STATE = 10 , + HUB_REQUEST_STOP_TT = 11 +}; + +enum { + HUB_FEATURE_HUB_LOCAL_POWER_CHANGE = 0, + HUB_FEATURE_HUB_OVER_CURRENT_CHANGE +}; + +enum{ + HUB_FEATURE_PORT_CONNECTION = 0, + HUB_FEATURE_PORT_ENABLE = 1, + HUB_FEATURE_PORT_SUSPEND = 2, + HUB_FEATURE_PORT_OVER_CURRENT = 3, + HUB_FEATURE_PORT_RESET = 4, + + HUB_FEATURE_PORT_POWER = 8, + HUB_FEATURE_PORT_LOW_SPEED = 9, + + HUB_FEATURE_PORT_CONNECTION_CHANGE = 16, + HUB_FEATURE_PORT_ENABLE_CHANGE = 17, + HUB_FEATURE_PORT_SUSPEND_CHANGE = 18, + HUB_FEATURE_PORT_OVER_CURRENT_CHANGE = 19, + HUB_FEATURE_PORT_RESET_CHANGE = 20, + HUB_FEATURE_PORT_TEST = 21, + HUB_FEATURE_PORT_INDICATOR = 22 +}; + +// data in response of HUB_REQUEST_GET_STATUS, wIndex = 0 (hub) +typedef struct { + union{ + struct TU_ATTR_PACKED { + uint16_t local_power_source : 1; + uint16_t over_current : 1; + uint16_t : 14; + }; + + uint16_t value; + } status, change; +} hub_status_response_t; + +TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); + +// data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num +typedef struct { + union { + struct TU_ATTR_PACKED { + uint16_t connection : 1; + uint16_t port_enable : 1; + uint16_t suspend : 1; + uint16_t over_current : 1; + uint16_t reset : 1; + + uint16_t : 3; + uint16_t port_power : 1; + uint16_t low_speed : 1; + uint16_t high_speed : 1; + uint16_t port_test_mode : 1; + uint16_t port_indicator_control : 1; + uint16_t TU_RESERVED : 3; + }; + + uint16_t value; + } status, change; +} hub_port_status_response_t; + +TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); + +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); +bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); + +bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb); +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb); +bool hub_status_pipe_queue(uint8_t dev_addr); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void hub_init (void); +bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hub_close (uint8_t dev_addr); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_HUB_H_ */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c new file mode 100644 index 000000000..b8439addc --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c @@ -0,0 +1,1204 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_HOST_ENABLED + +#include "tusb.h" +#include "host/usbh.h" +#include "host/usbh_classdriver.h" +#include "hub.h" + +//--------------------------------------------------------------------+ +// USBH Configuration +//--------------------------------------------------------------------+ + +// TODO remove,update +#ifndef CFG_TUH_EP_MAX +#define CFG_TUH_EP_MAX 9 +#endif + +#ifndef CFG_TUH_TASK_QUEUE_SZ +#define CFG_TUH_TASK_QUEUE_SZ 16 +#endif + +// Debug level of USBD +#define USBH_DBG_LVL 2 + +//--------------------------------------------------------------------+ +// USBH-HCD common data structure +//--------------------------------------------------------------------+ + +// device0 struct must be strictly a subset of normal device struct +typedef struct +{ + // port + uint8_t rhport; + uint8_t hub_addr; + uint8_t hub_port; + uint8_t speed; + + volatile struct TU_ATTR_PACKED + { + uint8_t connected : 1; + uint8_t addressed : 1; + uint8_t configured : 1; + uint8_t suspended : 1; + }; +} usbh_dev0_t; + +typedef struct { + // port + uint8_t rhport; + uint8_t hub_addr; + uint8_t hub_port; + uint8_t speed; + + volatile struct TU_ATTR_PACKED + { + uint8_t connected : 1; + uint8_t addressed : 1; + uint8_t configured : 1; + uint8_t suspended : 1; + }; + + //------------- device descriptor -------------// + uint16_t vid; + uint16_t pid; + + uint8_t ep0_size; + uint8_t i_manufacturer; + uint8_t i_product; + uint8_t i_serial; + + //------------- configuration descriptor -------------// + // uint8_t interface_count; // bNumInterfaces alias + + //------------- device -------------// + volatile uint8_t state; // device state, value from enum tusbh_device_state_t + + uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) + uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + + struct TU_ATTR_PACKED + { + volatile bool busy : 1; + volatile bool stalled : 1; + volatile bool claimed : 1; + + // TODO merge ep2drv here, 4-bit should be sufficient + }ep_status[CFG_TUH_EP_MAX][2]; + + // Mutex for claiming endpoint, only needed when using with preempted RTOS +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_def_t mutexdef; + osal_mutex_t mutex; +#endif + +} usbh_device_t; + + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +// Invalid driver ID in itf2drv[] ep2drv[][] mapping +enum { DRVID_INVALID = 0xFFu }; +enum { ADDR_INVALID = 0xFFu }; + +#if CFG_TUSB_DEBUG >= 2 + #define DRIVER_NAME(_name) .name = _name, +#else + #define DRIVER_NAME(_name) +#endif + +static usbh_class_driver_t const usbh_class_drivers[] = +{ + #if CFG_TUH_CDC + { + DRIVER_NAME("CDC") + .init = cdch_init, + .open = cdch_open, + .set_config = cdch_set_config, + .xfer_cb = cdch_xfer_cb, + .close = cdch_close + }, + #endif + + #if CFG_TUH_MSC + { + DRIVER_NAME("MSC") + .init = msch_init, + .open = msch_open, + .set_config = msch_set_config, + .xfer_cb = msch_xfer_cb, + .close = msch_close + }, + #endif + + #if CFG_TUH_HID + { + DRIVER_NAME("HID") + .init = hidh_init, + .open = hidh_open, + .set_config = hidh_set_config, + .xfer_cb = hidh_xfer_cb, + .close = hidh_close + }, + #endif + + #if CFG_TUH_HUB + { + DRIVER_NAME("HUB") + .init = hub_init, + .open = hub_open, + .set_config = hub_set_config, + .xfer_cb = hub_xfer_cb, + .close = hub_close + }, + #endif + + #if CFG_TUH_VENDOR + { + DRIVER_NAME("VENDOR") + .init = cush_init, + .open = cush_open_subtask, + .xfer_cb = cush_isr, + .close = cush_close + } + #endif +}; + +enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; + +enum { RESET_DELAY = 500 }; // 200 USB specs say only 50ms but many devices require much longer + +enum { CONFIG_NUM = 1 }; // default to use configuration 1 + + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ + +static bool _usbh_initialized = false; + +// Device with address = 0 for enumeration +static usbh_dev0_t _dev0; + +// all devices excluding zero-address +// hub address start from CFG_TUH_DEVICE_MAX+1 +CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUH_DEVICE_MAX + CFG_TUH_HUB]; + +// Event queue +// role device/host is used by OS NONE for mutex (disable usb isr) +OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); +static osal_queue_t _usbh_q; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; + +//------------- Helper Function -------------// + +TU_ATTR_ALWAYS_INLINE +static inline usbh_device_t* get_device(uint8_t dev_addr) +{ + TU_ASSERT(dev_addr, NULL); + return &_usbh_devices[dev_addr-1]; +} + +static bool enum_new_device(hcd_event_t* event); +static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); +static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); + +// from usbh_control.c +extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + +//--------------------------------------------------------------------+ +// PUBLIC API (Parameter Verification is required) +//--------------------------------------------------------------------+ +bool tuh_mounted(uint8_t dev_addr) +{ + return get_device(dev_addr)->configured; +} + +bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) +{ + *vid = *pid = 0; + + TU_VERIFY(tuh_mounted(dev_addr)); + + usbh_device_t const* dev = get_device(dev_addr); + + *vid = dev->vid; + *pid = dev->pid; + + return true; +} + +tusb_speed_t tuh_speed_get (uint8_t dev_addr) +{ + return (tusb_speed_t) (dev_addr ? get_device(dev_addr)->speed : _dev0.speed); +} + +#if CFG_TUSB_OS == OPT_OS_NONE +void osal_task_delay(uint32_t msec) +{ + (void) msec; + + const uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); + while ( ( hcd_frame_number(TUH_OPT_RHPORT) - start ) < msec ) {} +} +#endif + +//--------------------------------------------------------------------+ +// CLASS-USBD API (don't require to verify parameters) +//--------------------------------------------------------------------+ + +bool tuh_inited(void) +{ + return _usbh_initialized; +} + +bool tuh_init(uint8_t rhport) +{ + // skip if already initialized + if (_usbh_initialized) return _usbh_initialized; + + TU_LOG2("USBH init\r\n"); + + tu_memclr(_usbh_devices, sizeof(_usbh_devices)); + tu_memclr(&_dev0, sizeof(_dev0)); + + //------------- Enumeration & Reporter Task init -------------// + _usbh_q = osal_queue_create( &_usbh_qdef ); + TU_ASSERT(_usbh_q != NULL); + + //------------- Semaphore, Mutex for Control Pipe -------------// + for(uint8_t i=0; imutex = osal_mutex_create(&dev->mutexdef); + TU_ASSERT(dev->mutex); +#endif + + memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping + memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping + } + + // Class drivers init + for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + { + TU_LOG2("%s init\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].init(); + } + + TU_ASSERT(hcd_init(rhport)); + hcd_int_enable(rhport); + + _usbh_initialized = true; + return true; +} + +/* USB Host Driver task + * This top level thread manages all host controller event and delegates events to class-specific drivers. + * This should be called periodically within the mainloop or rtos thread. + * + @code + int main(void) + { + application_init(); + tusb_init(); + + while(1) // the mainloop + { + application_code(); + tuh_task(); // tinyusb host task + } + } + @endcode + */ +void tuh_task(void) +{ + // Skip if stack is not initialized + if ( !tusb_inited() ) return; + + // Loop until there is no more events in the queue + while (1) + { + hcd_event_t event; + if ( !osal_queue_receive(_usbh_q, &event) ) return; + + switch (event.event_id) + { + case HCD_EVENT_DEVICE_ATTACH: + // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating + // one device before enumerating another one. + TU_LOG2("USBH DEVICE ATTACH\r\n"); + enum_new_device(&event); + break; + + case HCD_EVENT_DEVICE_REMOVE: + TU_LOG2("USBH DEVICE REMOVED\r\n"); + process_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); + + #if CFG_TUH_HUB + // TODO remove + if ( event.connection.hub_addr != 0) + { + // done with hub, waiting for next data on status pipe + (void) hub_status_pipe_queue( event.connection.hub_addr ); + } + #endif + break; + + case HCD_EVENT_XFER_COMPLETE: + { + uint8_t const ep_addr = event.xfer_complete.ep_addr; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + + if (event.dev_addr == 0) + { + // device 0 only has control endpoint + TU_ASSERT(epnum == 0, ); + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + } + else + { + usbh_device_t* dev = get_device(event.dev_addr); + dev->ep_status[epnum][ep_dir].busy = false; + dev->ep_status[epnum][ep_dir].claimed = 0; + + if ( 0 == epnum ) + { + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + }else + { + uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; + TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); + + TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + } + } + } + break; + + case USBH_EVENT_FUNC_CALL: + if ( event.func_call.func ) event.func_call.func(event.func_call.param); + break; + + default: break; + } + } +} + +//--------------------------------------------------------------------+ +// USBH API For Class Driver +//--------------------------------------------------------------------+ + +uint8_t usbh_get_rhport(uint8_t dev_addr) +{ + return (dev_addr == 0) ? _dev0.rhport : get_device(dev_addr)->rhport; +} + +uint8_t* usbh_get_enum_buf(void) +{ + return _usbh_ctrl_buf; +} + +//--------------------------------------------------------------------+ +// HCD Event Handler +//--------------------------------------------------------------------+ + +void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info) +{ + if (dev_addr) + { + usbh_device_t const* dev = get_device(dev_addr); + + devtree_info->rhport = dev->rhport; + devtree_info->hub_addr = dev->hub_addr; + devtree_info->hub_port = dev->hub_port; + devtree_info->speed = dev->speed; + }else + { + devtree_info->rhport = _dev0.rhport; + devtree_info->hub_addr = _dev0.hub_addr; + devtree_info->hub_port = _dev0.hub_port; + devtree_info->speed = _dev0.speed; + } +} + +void hcd_event_handler(hcd_event_t const* event, bool in_isr) +{ + switch (event->event_id) + { + default: + osal_queue_send(_usbh_q, event, in_isr); + break; + } +} + +void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) +{ + hcd_event_t event = + { + .rhport = 0, // TODO correct rhport + .event_id = HCD_EVENT_XFER_COMPLETE, + .dev_addr = dev_addr, + .xfer_complete = + { + .ep_addr = ep_addr, + .result = result, + .len = xferred_bytes + } + }; + + hcd_event_handler(&event, in_isr); +} + +void hcd_event_device_attach(uint8_t rhport, bool in_isr) +{ + hcd_event_t event = + { + .rhport = rhport, + .event_id = HCD_EVENT_DEVICE_ATTACH + }; + + event.connection.hub_addr = 0; + event.connection.hub_port = 0; + + hcd_event_handler(&event, in_isr); +} + +void hcd_event_device_remove(uint8_t hostid, bool in_isr) +{ + hcd_event_t event = + { + .rhport = hostid, + .event_id = HCD_EVENT_DEVICE_REMOVE + }; + + event.connection.hub_addr = 0; + event.connection.hub_port = 0; + + hcd_event_handler(&event, in_isr); +} + + +// a device unplugged on hostid, hub_addr, hub_port +// return true if found and unmounted device, false if cannot find +void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) +{ + //------------- find the all devices (star-network) under port that is unplugged -------------// + // TODO mark as disconnected in ISR, also handle dev0 + for ( uint8_t dev_id = 0; dev_id < TU_ARRAY_SIZE(_usbh_devices); dev_id++ ) + { + usbh_device_t* dev = &_usbh_devices[dev_id]; + uint8_t const dev_addr = dev_id+1; + + // TODO Hub multiple level + if (dev->rhport == rhport && + (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub + (hub_port == 0 || dev->hub_port == hub_port) && + dev->state != TUSB_DEVICE_STATE_UNPLUG) + { + // Invoke callback before close driver + if (tuh_umount_cb) tuh_umount_cb(dev_addr); + + // Close class driver + for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + { + TU_LOG2("%s close\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].close(dev_addr); + } + + hcd_device_close(rhport, dev_addr); + + // release all endpoints associated with the device + memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping + memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping + tu_memclr(dev->ep_status, sizeof(dev->ep_status)); + + dev->state = TUSB_DEVICE_STATE_UNPLUG; + } + } +} + +//--------------------------------------------------------------------+ +// INTERNAL HELPER +//--------------------------------------------------------------------+ +static uint8_t get_new_address(bool is_hub) +{ + uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; + uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); + + for (uint8_t i=0; i < count; i++) + { + uint8_t const addr = start + i; + if (get_device(addr)->state == TUSB_DEVICE_STATE_UNPLUG) return addr; + } + return ADDR_INVALID; +} + +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) +{ + usbh_device_t* dev = get_device(dev_addr); + + for(itf_num++; itf_num < sizeof(dev->itf2drv); itf_num++) + { + // continue with next valid interface + // TODO skip IAD binding interface such as CDCs + uint8_t const drv_id = dev->itf2drv[itf_num]; + if (drv_id != DRVID_INVALID) + { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; + TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num); + driver->set_config(dev_addr, itf_num); + break; + } + } + + // all interface are configured + if (itf_num == sizeof(dev->itf2drv)) + { + // Invoke callback if available + if (tuh_mount_cb) tuh_mount_cb(dev_addr); + } +} + +//--------------------------------------------------------------------+ +// Enumeration Process +// is a lengthy process with a seires of control transfer to configure +// newly attached device. Each step is handled by a function in this +// section +// TODO due to the shared _usbh_ctrl_buf, we must complete enumerating +// one device before enumerating another one. +//--------------------------------------------------------------------+ + +static bool enum_request_addr0_device_desc(void); +static bool enum_request_set_addr(void); + +static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_set_address_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_get_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_get_9byte_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_get_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_set_config_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); + +#if CFG_TUH_HUB +static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + enum_request_addr0_device_desc(); + return true; +} + +static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + enum_request_set_addr(); + + // done with hub, waiting for next data on status pipe + (void) hub_status_pipe_queue( _dev0.hub_addr ); + + return true; +} + +static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + hub_port_status_response_t port_status; + memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); + + // Acknowledge Port Reset Change if Reset Successful + if (port_status.change.reset) + { + TU_ASSERT( hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); + } + + return true; +} + +static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + hub_port_status_response_t port_status; + memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); + + if ( !port_status.status.connection ) + { + // device unplugged while delaying, nothing else to do, queue hub status + return hub_status_pipe_queue(dev_addr); + } + + _dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : + (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; + + // Acknowledge Port Reset Change + if (port_status.change.reset) + { + hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset0_complete); + } + + return true; +} +#endif + +static bool enum_new_device(hcd_event_t* event) +{ + _dev0.rhport = event->rhport; // TODO refractor integrate to device_pool + _dev0.hub_addr = event->connection.hub_addr; + _dev0.hub_port = event->connection.hub_port; + + //------------- connected/disconnected directly with roothub -------------// + if (_dev0.hub_addr == 0) + { + // wait until device is stable TODO non blocking + osal_task_delay(RESET_DELAY); + + // device unplugged while delaying + if ( !hcd_port_connect_status(_dev0.rhport) ) return true; + + _dev0.speed = hcd_port_speed_get(_dev0.rhport ); + + enum_request_addr0_device_desc(); + } +#if CFG_TUH_HUB + //------------- connected/disconnected via hub -------------// + else + { + // wait until device is stable + osal_task_delay(RESET_DELAY); + TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete) ); + } +#endif // CFG_TUH_HUB + + return true; +} + +static bool enum_request_addr0_device_desc(void) +{ + // TODO probably doesn't need to open/close each enumeration + uint8_t const addr0 = 0; + TU_ASSERT( usbh_edpt_control_open(addr0, 8) ); + + //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// + TU_LOG2("Get 8 byte of Device Descriptor\r\n"); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = TUSB_DESC_DEVICE << 8, + .wIndex = 0, + .wLength = 8 + }; + TU_ASSERT( tuh_control_xfer(addr0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete) ); + + return true; +} + +// After Get Device Descriptor of Address 0 +static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + TU_ASSERT(0 == dev_addr); + + if (XFER_RESULT_SUCCESS != result) + { +#if CFG_TUH_HUB + // TODO remove, waiting for next data on status pipe + if (_dev0.hub_addr != 0) hub_status_pipe_queue(_dev0.hub_addr); +#endif + + return false; + } + + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + TU_ASSERT( tu_desc_type(desc_device) == TUSB_DESC_DEVICE ); + + // Reset device again before Set Address + TU_LOG2("Port reset \r\n"); + + if (_dev0.hub_addr == 0) + { + // connected directly to roothub + hcd_port_reset( _dev0.rhport ); // reset port after 8 byte descriptor + osal_task_delay(RESET_DELAY); + + enum_request_set_addr(); + } +#if CFG_TUH_HUB + else + { + // after RESET_DELAY the hub_port_reset() already complete + TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, NULL) ); + osal_task_delay(RESET_DELAY); + + tuh_task(); // FIXME temporarily to clean up port_reset control transfer + + TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) ); + } +#endif + + return true; +} + +static bool enum_request_set_addr(void) +{ + uint8_t const addr0 = 0; + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + + // Get new address + uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); + TU_ASSERT(new_addr != ADDR_INVALID); + + TU_LOG2("Set Address = %d\r\n", new_addr); + + usbh_device_t* new_dev = get_device(new_addr); + + new_dev->rhport = _dev0.rhport; + new_dev->hub_addr = _dev0.hub_addr; + new_dev->hub_port = _dev0.hub_port; + new_dev->speed = _dev0.speed; + new_dev->connected = 1; + new_dev->ep0_size = desc_device->bMaxPacketSize0; + + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = new_addr, + .wIndex = 0, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(addr0, &new_request, NULL, enum_set_address_complete) ); + + return true; +} + +// After SET_ADDRESS is complete +static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(0 == dev_addr); + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + uint8_t const new_addr = (uint8_t const) request->wValue; + + usbh_device_t* new_dev = get_device(new_addr); + new_dev->addressed = 1; + + // TODO close device 0, may not be needed + hcd_device_close(_dev0.rhport, 0); + + // open control pipe for new address + TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size) ); + + // Get full device descriptor + TU_LOG2("Get Device Descriptor\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = TUSB_DESC_DEVICE << 8, + .wIndex = 0, + .wLength = sizeof(tusb_desc_device_t) + }; + + TU_ASSERT(tuh_control_xfer(new_addr, &new_request, _usbh_ctrl_buf, enum_get_device_desc_complete)); + + return true; +} + +static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + usbh_device_t* dev = get_device(dev_addr); + + dev->vid = desc_device->idVendor; + dev->pid = desc_device->idProduct; + dev->i_manufacturer = desc_device->iManufacturer; + dev->i_product = desc_device->iProduct; + dev->i_serial = desc_device->iSerialNumber; + +// if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); + + TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), + .wIndex = 0, + .wLength = 9 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_9byte_config_desc_complete) ); + + return true; +} + +static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + // TODO not enough buffer to hold configuration descriptor + uint8_t const * desc_config = _usbh_ctrl_buf; + + // Use offsetof to avoid pointer to the odd/misaligned address + uint16_t const total_len = tu_le16toh( tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); + + TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); + + // Get full configuration descriptor + TU_LOG2("Get Configuration Descriptor\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), + .wIndex = 0, + .wLength = total_len + + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); + + return true; +} + +static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + // Parse configuration & set up drivers + // Driver open aren't allowed to make any usb transfer yet + TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); + + TU_LOG2("Set Configuration = %d\r\n", CONFIG_NUM); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_CONFIGURATION, + .wValue = CONFIG_NUM, + .wIndex = 0, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, enum_set_config_complete) ); + + return true; +} + +static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + TU_LOG2("Device configured\r\n"); + usbh_device_t* dev = get_device(dev_addr); + dev->configured = 1; + dev->state = TUSB_DEVICE_STATE_CONFIGURED; + + // Start the Set Configuration process for interfaces (itf = DRVID_INVALID) + // Since driver can perform control transfer within its set_config, this is done asynchronously. + // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() + // TODO use separated API instead of using DRVID_INVALID + usbh_driver_set_config_complete(dev_addr, DRVID_INVALID); + + return true; +} + +static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) +{ + usbh_device_t* dev = get_device(dev_addr); + + uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); + uint8_t const* p_desc = tu_desc_next(desc_cfg); + + // parse each interfaces + while( p_desc < desc_end ) + { + uint8_t assoc_itf_count = 1; + + // Class will always starts with Interface Association (if any) and then Interface descriptor + if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) + { + tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + assoc_itf_count = desc_iad->bInterfaceCount; + + p_desc = tu_desc_next(p_desc); // next to Interface + + // IAD's first interface number and class should match with opened interface + //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); + } + + TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); + tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + +#if CFG_TUH_MIDI + // MIDI has 2 interfaces (Audio Control v1 + MIDIStreaming) but does not have IAD + // manually increase the associated count + if (1 == assoc_itf_count && + TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) + { + assoc_itf_count = 2; + } +#endif + + uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, assoc_itf_count, desc_end-p_desc); + TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t)); + + if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) + { + // TODO Attach hub to Hub is not currently supported + // skip this interface + TU_LOG(USBH_DBG_LVL, "Only 1 level of HUB is supported\r\n"); + } + else + { + // Find driver for this interface + uint8_t drv_id; + for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; + + if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) + { + // open successfully + TU_LOG2(" %s opened\r\n", driver->name); + + // bind (associated) interfaces to found driver + for(uint8_t i=0; ibInterfaceNumber+i; + + // Interface number must not be used already + TU_ASSERT( DRVID_INVALID == dev->itf2drv[itf_num] ); + dev->itf2drv[itf_num] = drv_id; + } + + // bind all endpoints to found driver + tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); + + break; // exit driver find loop + } + } + + if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + { + TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", + desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); + } + } + + // next Interface or IAD descriptor + p_desc += drv_len; + } + + return true; +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = get_device(dev_addr); + +#if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = get_device(dev_addr); + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = get_device(dev_addr); + + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() + // could return and USBH task can preempt and clear the busy + dev->ep_status[epnum][dir].busy = true; + + if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // HCD error, mark endpoint as ready to allow next transfer + dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } +} + +static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) +{ + TU_LOG2("Open EP0 with Size = %u (addr = %u)\r\n", max_packet_size, dev_addr); + + tusb_desc_endpoint_t ep0_desc = + { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = max_packet_size, + .bInterval = 0 + }; + + return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc); +} + +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) +{ + usbh_device_t* dev = get_device(dev_addr); + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed)); + + return hcd_edpt_open(rhport, dev_addr, desc_ep); +} + +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = get_device(dev_addr); + + return dev->ep_status[epnum][dir].busy; +} + + + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h new file mode 100644 index 000000000..8411cad28 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h @@ -0,0 +1,99 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_USBH_H_ +#define _TUSB_USBH_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "common/tusb_common.h" +#include "hcd.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + +//--------------------------------------------------------------------+ +// APPLICATION API +//--------------------------------------------------------------------+ + +// Init host stack +bool tuh_init(uint8_t rhport); + +// Check if host stack is already initialized +bool tuh_inited(void); + +// Task function should be called in main/rtos loop +void tuh_task(void); + +// Interrupt handler, name alias to HCD +extern void hcd_int_handler(uint8_t rhport); +#define tuh_int_handler hcd_int_handler + +bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid); +tusb_speed_t tuh_speed_get(uint8_t dev_addr); + +// Check if device is connected and configured +bool tuh_mounted(uint8_t dev_addr); + +// Check if device is suspended +static inline bool tuh_suspended(uint8_t dev_addr) +{ + // TODO implement suspend & resume on host + (void) dev_addr; + return false; +} + +// Check if device is ready to communicate with +TU_ATTR_ALWAYS_INLINE +static inline bool tuh_ready(uint8_t dev_addr) +{ + return tuh_mounted(dev_addr) && !tuh_suspended(dev_addr); +} + +// Carry out control transfer +bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); + +//--------------------------------------------------------------------+ +// APPLICATION CALLBACK +//--------------------------------------------------------------------+ +//TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); + +// Invoked when device is mounted (configured) +TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); + +/// Invoked when device is unmounted (bus reset/unplugged) +TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h new file mode 100644 index 000000000..8bc2622aa --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h @@ -0,0 +1,83 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_USBH_CLASSDRIVER_H_ +#define _TUSB_USBH_CLASSDRIVER_H_ + +#include "osal/osal.h" +#include "common/tusb_fifo.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver API +//--------------------------------------------------------------------+ + +typedef struct { + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif + + void (* const init )(void); + bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); +} usbh_class_driver_t; + +// Call by class driver to tell USBH that it has complete the enumeration +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + +uint8_t usbh_get_rhport(uint8_t dev_addr); + +uint8_t* usbh_get_enum_buf(void); + +//--------------------------------------------------------------------+ +// USBH Endpoint API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); + +// Submit a usb transfer +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); + +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr); + +// Check if endpoint transferring is complete +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c new file mode 100644 index 000000000..9204576ac --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c @@ -0,0 +1,138 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_HOST_ENABLED + +#include "tusb.h" +#include "usbh_classdriver.h" + +enum +{ + STAGE_SETUP, + STAGE_DATA, + STAGE_ACK +}; + +typedef struct +{ + tusb_control_request_t request TU_ATTR_ALIGNED(4); + + uint8_t stage; + uint8_t* buffer; + tuh_control_complete_cb_t complete_cb; +} usbh_control_xfer_t; + +static usbh_control_xfer_t _ctrl_xfer; + +//CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) +{ + // TODO need to claim the endpoint first + const uint8_t rhport = usbh_get_rhport(dev_addr); + + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = buffer; + _ctrl_xfer.stage = STAGE_SETUP; + _ctrl_xfer.complete_cb = complete_cb; + + TU_LOG2("Control Setup (addr = %u): ", dev_addr); + TU_LOG2_VAR(request); + TU_LOG2("\r\n"); + + // Send setup packet + TU_ASSERT( hcd_setup_send(rhport, dev_addr, (uint8_t const*) &_ctrl_xfer.request) ); + + return true; +} + +static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) +{ + TU_LOG2("\r\n"); + if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); +} + +bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) ep_addr; + (void) xferred_bytes; + + const uint8_t rhport = usbh_get_rhport(dev_addr); + + tusb_control_request_t const * request = &_ctrl_xfer.request; + + if (XFER_RESULT_SUCCESS != result) + { + TU_LOG2("Control failed: result = %d\r\n", result); + + // terminate transfer if any stage failed + _xfer_complete(dev_addr, result); + }else + { + switch(_ctrl_xfer.stage) + { + case STAGE_SETUP: + _ctrl_xfer.stage = STAGE_DATA; + if (request->wLength) + { + // DATA stage: initial data toggle is always 1 + hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); + return true; + } + __attribute__((fallthrough)); + + case STAGE_DATA: + _ctrl_xfer.stage = STAGE_ACK; + + if (request->wLength) + { + TU_LOG2("Control data (addr = %u):\r\n", dev_addr); + TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); + } + + // ACK stage: toggle is always 1 + hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); + break; + + case STAGE_ACK: + _xfer_complete(dev_addr, result); + break; + + default: return false; + } + } + + return true; +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h new file mode 100644 index 000000000..c8131d19d --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h @@ -0,0 +1,111 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_OSAL_H_ +#define _TUSB_OSAL_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +/** \addtogroup group_osal + * @{ */ + +#include "common/tusb_common.h" + +// Return immediately +#define OSAL_TIMEOUT_NOTIMEOUT (0) +// Default timeout +#define OSAL_TIMEOUT_NORMAL (10) +// Wait forever +#define OSAL_TIMEOUT_WAIT_FOREVER (UINT32_MAX) + +#define OSAL_TIMEOUT_CONTROL_XFER OSAL_TIMEOUT_WAIT_FOREVER + +typedef void (*osal_task_func_t)( void * ); + +#if CFG_TUSB_OS == OPT_OS_NONE + #include "osal_none.h" +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + #include "osal_freertos.h" +#elif CFG_TUSB_OS == OPT_OS_MYNEWT + #include "osal_mynewt.h" +#elif CFG_TUSB_OS == OPT_OS_PICO + #include "osal_pico.h" +#elif CFG_TUSB_OS == OPT_OS_RTTHREAD + #include "osal_rtthread.h" +#elif CFG_TUSB_OS == OPT_OS_CUSTOM + #include "tusb_os_custom.h" // implemented by application +#else + #error OS is not supported yet +#endif + +//--------------------------------------------------------------------+ +// OSAL Porting API +//--------------------------------------------------------------------+ + +#if __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif +//------------- Semaphore -------------// +static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); +static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec); + +static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed + +//------------- Mutex -------------// +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef); +static inline bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec); +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl); + +//------------- Queue -------------// +static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef); +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data); +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); +static inline bool osal_queue_empty(osal_queue_t qhdl); +#if __GNUC__ +#pragma GCC diagnostic pop +#endif + +#if 0 // TODO remove subtask related macros later +// Sub Task +#define OSAL_SUBTASK_BEGIN +#define OSAL_SUBTASK_END return TUSB_ERROR_NONE; + +#define STASK_RETURN(_error) return _error; +#define STASK_INVOKE(_subtask, _status) (_status) = _subtask +#define STASK_ASSERT(_cond) TU_VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED) +#endif + +#ifdef __cplusplus + } +#endif + +/** @} */ + +#endif /* _TUSB_OSAL_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h new file mode 100644 index 000000000..4573e01f5 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h @@ -0,0 +1,172 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_OSAL_FREERTOS_H_ +#define _TUSB_OSAL_FREERTOS_H_ + +// FreeRTOS Headers +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,FreeRTOS.h) +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,semphr.h) +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,queue.h) +#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,task.h) + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// TASK API +//--------------------------------------------------------------------+ +static inline void osal_task_delay(uint32_t msec) +{ + vTaskDelay( pdMS_TO_TICKS(msec) ); +} + +//--------------------------------------------------------------------+ +// Semaphore API +//--------------------------------------------------------------------+ +typedef StaticSemaphore_t osal_semaphore_def_t; +typedef SemaphoreHandle_t osal_semaphore_t; + +static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +{ + return xSemaphoreCreateBinaryStatic(semdef); +} + +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +{ + if ( !in_isr ) + { + return xSemaphoreGive(sem_hdl) != 0; + } + else + { + BaseType_t xHigherPriorityTaskWoken; + BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); + +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 + if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); +#else + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +#endif + + return res != 0; + } +} + +static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) +{ + uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(msec); + return xSemaphoreTake(sem_hdl, ticks); +} + +static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) +{ + xQueueReset(sem_hdl); +} + +//--------------------------------------------------------------------+ +// MUTEX API (priority inheritance) +//--------------------------------------------------------------------+ +typedef StaticSemaphore_t osal_mutex_def_t; +typedef SemaphoreHandle_t osal_mutex_t; + +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +{ + return xSemaphoreCreateMutexStatic(mdef); +} + +static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) +{ + return osal_semaphore_wait(mutex_hdl, msec); +} + +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +{ + return xSemaphoreGive(mutex_hdl); +} + +//--------------------------------------------------------------------+ +// QUEUE API +//--------------------------------------------------------------------+ + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + static _type _name##_##buf[_depth];\ + osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; + +typedef struct +{ + uint16_t depth; + uint16_t item_sz; + void* buf; + + StaticQueue_t sq; +}osal_queue_def_t; + +typedef QueueHandle_t osal_queue_t; + +static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +{ + return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); +} + +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +{ + return xQueueReceive(qhdl, data, portMAX_DELAY); +} + +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + if ( !in_isr ) + { + return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0; + } + else + { + BaseType_t xHigherPriorityTaskWoken; + BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); + +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 + if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); +#else + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +#endif + + return res != 0; + } +} + +static inline bool osal_queue_empty(osal_queue_t qhdl) +{ + return uxQueueMessagesWaiting(qhdl) == 0; +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_OSAL_FREERTOS_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h new file mode 100644 index 000000000..6882329c1 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h @@ -0,0 +1,174 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef OSAL_MYNEWT_H_ +#define OSAL_MYNEWT_H_ + +#include "os/os.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// TASK API +//--------------------------------------------------------------------+ +static inline void osal_task_delay(uint32_t msec) +{ + os_time_delay( os_time_ms_to_ticks32(msec) ); +} + +//--------------------------------------------------------------------+ +// Semaphore API +//--------------------------------------------------------------------+ +typedef struct os_sem osal_semaphore_def_t; +typedef struct os_sem* osal_semaphore_t; + +static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +{ + return (os_sem_init(semdef, 0) == OS_OK) ? (osal_semaphore_t) semdef : NULL; +} + +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +{ + (void) in_isr; + return os_sem_release(sem_hdl) == OS_OK; +} + +static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) +{ + uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); + return os_sem_pend(sem_hdl, ticks) == OS_OK; +} + +static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) +{ + // TODO implement later +} + +//--------------------------------------------------------------------+ +// MUTEX API (priority inheritance) +//--------------------------------------------------------------------+ +typedef struct os_mutex osal_mutex_def_t; +typedef struct os_mutex* osal_mutex_t; + +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +{ + return (os_mutex_init(mdef) == OS_OK) ? (osal_mutex_t) mdef : NULL; +} + +static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) +{ + uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); + return os_mutex_pend(mutex_hdl, ticks) == OS_OK; +} + +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +{ + return os_mutex_release(mutex_hdl) == OS_OK; +} + +//--------------------------------------------------------------------+ +// QUEUE API +//--------------------------------------------------------------------+ + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + static _type _name##_##buf[_depth];\ + static struct os_event _name##_##evbuf[_depth];\ + osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, .evbuf = _name##_##evbuf};\ + +typedef struct +{ + uint16_t depth; + uint16_t item_sz; + void* buf; + void* evbuf; + + struct os_mempool mpool; + struct os_mempool epool; + + struct os_eventq evq; +}osal_queue_def_t; + +typedef osal_queue_def_t* osal_queue_t; + +static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +{ + if ( OS_OK != os_mempool_init(&qdef->mpool, qdef->depth, qdef->item_sz, qdef->buf, "usbd queue") ) return NULL; + if ( OS_OK != os_mempool_init(&qdef->epool, qdef->depth, sizeof(struct os_event), qdef->evbuf, "usbd evqueue") ) return NULL; + + os_eventq_init(&qdef->evq); + return (osal_queue_t) qdef; +} + +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +{ + struct os_event* ev; + ev = os_eventq_get(&qhdl->evq); + + memcpy(data, ev->ev_arg, qhdl->item_sz); // copy message + os_memblock_put(&qhdl->mpool, ev->ev_arg); // put back mem block + os_memblock_put(&qhdl->epool, ev); // put back ev block + + return true; +} + +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + (void) in_isr; + + // get a block from mem pool for data + void* ptr = os_memblock_get(&qhdl->mpool); + if (!ptr) return false; + memcpy(ptr, data, qhdl->item_sz); + + // get a block from event pool to put into queue + struct os_event* ev = (struct os_event*) os_memblock_get(&qhdl->epool); + if (!ev) + { + os_memblock_put(&qhdl->mpool, ptr); + return false; + } + tu_memclr(ev, sizeof(struct os_event)); + ev->ev_arg = ptr; + + os_eventq_put(&qhdl->evq, ev); + + return true; +} + +static inline bool osal_queue_empty(osal_queue_t qhdl) +{ + return STAILQ_EMPTY(&qhdl->evq.evq_list); +} + + +#ifdef __cplusplus + } +#endif + +#endif /* OSAL_MYNEWT_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h new file mode 100644 index 000000000..a1f997cf2 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h @@ -0,0 +1,204 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_OSAL_NONE_H_ +#define _TUSB_OSAL_NONE_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// TASK API +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// Binary Semaphore API +//--------------------------------------------------------------------+ +typedef struct +{ + volatile uint16_t count; +}osal_semaphore_def_t; + +typedef osal_semaphore_def_t* osal_semaphore_t; + +static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +{ + semdef->count = 0; + return semdef; +} + +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +{ + (void) in_isr; + sem_hdl->count++; + return true; +} + +// TODO blocking for now +static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) +{ + (void) msec; + + while (sem_hdl->count == 0) { } + sem_hdl->count--; + + return true; +} + +static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) +{ + sem_hdl->count = 0; +} + +//--------------------------------------------------------------------+ +// MUTEX API +// Within tinyusb, mutex is never used in ISR context +//--------------------------------------------------------------------+ +typedef osal_semaphore_def_t osal_mutex_def_t; +typedef osal_semaphore_t osal_mutex_t; + +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +{ + mdef->count = 1; + return mdef; +} + +static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) +{ + return osal_semaphore_wait(mutex_hdl, msec); +} + +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +{ + return osal_semaphore_post(mutex_hdl, false); +} + +//--------------------------------------------------------------------+ +// QUEUE API +//--------------------------------------------------------------------+ +#include "common/tusb_fifo.h" + +// extern to avoid including dcd.h and hcd.h +#if TUSB_OPT_DEVICE_ENABLED +extern void dcd_int_disable(uint8_t rhport); +extern void dcd_int_enable(uint8_t rhport); +#endif + +#if TUSB_OPT_HOST_ENABLED +extern void hcd_int_disable(uint8_t rhport); +extern void hcd_int_enable(uint8_t rhport); +#endif + +typedef struct +{ + uint8_t role; // device or host + tu_fifo_t ff; +}osal_queue_def_t; + +typedef osal_queue_def_t* osal_queue_t; + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + osal_queue_def_t _name = { \ + .role = _role, \ + .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ + } + +// lock queue by disable USB interrupt +static inline void _osal_q_lock(osal_queue_t qhdl) +{ + (void) qhdl; + +#if TUSB_OPT_DEVICE_ENABLED + if (qhdl->role == OPT_MODE_DEVICE) dcd_int_disable(TUD_OPT_RHPORT); +#endif + +#if TUSB_OPT_HOST_ENABLED + if (qhdl->role == OPT_MODE_HOST) hcd_int_disable(TUH_OPT_RHPORT); +#endif +} + +// unlock queue +static inline void _osal_q_unlock(osal_queue_t qhdl) +{ + (void) qhdl; + +#if TUSB_OPT_DEVICE_ENABLED + if (qhdl->role == OPT_MODE_DEVICE) dcd_int_enable(TUD_OPT_RHPORT); +#endif + +#if TUSB_OPT_HOST_ENABLED + if (qhdl->role == OPT_MODE_HOST) hcd_int_enable(TUH_OPT_RHPORT); +#endif +} + +static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +{ + tu_fifo_clear(&qdef->ff); + return (osal_queue_t) qdef; +} + +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +{ + _osal_q_lock(qhdl); + bool success = tu_fifo_read(&qhdl->ff, data); + _osal_q_unlock(qhdl); + + return success; +} + +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + if (!in_isr) { + _osal_q_lock(qhdl); + } + + bool success = tu_fifo_write(&qhdl->ff, data); + + if (!in_isr) { + _osal_q_unlock(qhdl); + } + + TU_ASSERT(success); + + return success; +} + +static inline bool osal_queue_empty(osal_queue_t qhdl) +{ + // Skip queue lock/unlock since this function is primarily called + // with interrupt disabled before going into low power mode + return tu_fifo_empty(&qhdl->ff); +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_OSAL_NONE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h new file mode 100644 index 000000000..1c3366e01 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h @@ -0,0 +1,187 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_OSAL_PICO_H_ +#define _TUSB_OSAL_PICO_H_ + +#include "pico/time.h" +#include "pico/sem.h" +#include "pico/mutex.h" +#include "pico/critical_section.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// TASK API +//--------------------------------------------------------------------+ +static inline void osal_task_delay(uint32_t msec) +{ + sleep_ms(msec); +} + +//--------------------------------------------------------------------+ +// Binary Semaphore API +//--------------------------------------------------------------------+ +typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; + +static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +{ + sem_init(semdef, 0, 255); + return semdef; +} + +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +{ + (void) in_isr; + sem_release(sem_hdl); + return true; +} + +static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) +{ + return sem_acquire_timeout_ms(sem_hdl, msec); +} + +static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) +{ + sem_reset(sem_hdl, 0); +} + +//--------------------------------------------------------------------+ +// MUTEX API +// Within tinyusb, mutex is never used in ISR context +//--------------------------------------------------------------------+ +typedef struct mutex osal_mutex_def_t, *osal_mutex_t; + +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +{ + mutex_init(mdef); + return mdef; +} + +static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) +{ + return mutex_enter_timeout_ms(mutex_hdl, msec); +} + +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +{ + mutex_exit(mutex_hdl); + return true; +} + +//--------------------------------------------------------------------+ +// QUEUE API +//--------------------------------------------------------------------+ +#include "common/tusb_fifo.h" + +#if TUSB_OPT_HOST_ENABLED +extern void hcd_int_disable(uint8_t rhport); +extern void hcd_int_enable(uint8_t rhport); +#endif + +typedef struct +{ + tu_fifo_t ff; + struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section +} osal_queue_def_t; + +typedef osal_queue_def_t* osal_queue_t; + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + osal_queue_def_t _name = { \ + .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ + } + +// lock queue by disable USB interrupt +static inline void _osal_q_lock(osal_queue_t qhdl) +{ + critical_section_enter_blocking(&qhdl->critsec); +} + +// unlock queue +static inline void _osal_q_unlock(osal_queue_t qhdl) +{ + critical_section_exit(&qhdl->critsec); +} + +static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +{ + critical_section_init(&qdef->critsec); + tu_fifo_clear(&qdef->ff); + return (osal_queue_t) qdef; +} + +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +{ + // TODO: revisit... docs say that mutexes are never used from IRQ context, + // however osal_queue_recieve may be. therefore my assumption is that + // the fifo mutex is not populated for queues used from an IRQ context + //assert(!qhdl->ff.mutex); + + _osal_q_lock(qhdl); + bool success = tu_fifo_read(&qhdl->ff, data); + _osal_q_unlock(qhdl); + + return success; +} + +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + // TODO: revisit... docs say that mutexes are never used from IRQ context, + // however osal_queue_recieve may be. therefore my assumption is that + // the fifo mutex is not populated for queues used from an IRQ context + //assert(!qhdl->ff.mutex); + (void) in_isr; + + _osal_q_lock(qhdl); + bool success = tu_fifo_write(&qhdl->ff, data); + _osal_q_unlock(qhdl); + + TU_ASSERT(success); + + return success; +} + +static inline bool osal_queue_empty(osal_queue_t qhdl) +{ + // TODO: revisit; whether this is true or not currently, tu_fifo_empty is a single + // volatile read. + + // Skip queue lock/unlock since this function is primarily called + // with interrupt disabled before going into low power mode + return tu_fifo_empty(&qhdl->ff); +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_OSAL_PICO_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h new file mode 100644 index 000000000..d5c062ac1 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h @@ -0,0 +1,130 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 tfx2001 (2479727366@qq.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_OSAL_RTTHREAD_H_ +#define _TUSB_OSAL_RTTHREAD_H_ + +// RT-Thread Headers +#include "rtthread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// TASK API +//--------------------------------------------------------------------+ +static inline void osal_task_delay(uint32_t msec) { + rt_thread_mdelay(msec); +} + +//--------------------------------------------------------------------+ +// Semaphore API +//--------------------------------------------------------------------+ +typedef struct rt_semaphore osal_semaphore_def_t; +typedef rt_sem_t osal_semaphore_t; + +static inline osal_semaphore_t +osal_semaphore_create(osal_semaphore_def_t *semdef) { + rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_FIFO); + return semdef; +} + +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { + (void) in_isr; + return rt_sem_release(sem_hdl) == RT_EOK; +} + +static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { + return rt_sem_take(sem_hdl, rt_tick_from_millisecond(msec)) == RT_EOK; +} + +static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { + // TODO: implement +} + +//--------------------------------------------------------------------+ +// MUTEX API (priority inheritance) +//--------------------------------------------------------------------+ +typedef struct rt_mutex osal_mutex_def_t; +typedef rt_mutex_t osal_mutex_t; + +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { + rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_FIFO); + return mdef; +} + +static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) { + return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond(msec)) == RT_EOK; +} + +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { + return rt_mutex_release(mutex_hdl) == RT_EOK; +} + +//--------------------------------------------------------------------+ +// QUEUE API +//--------------------------------------------------------------------+ + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + static _type _name##_##buf[_depth]; \ + osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; + +typedef struct { + uint16_t depth; + uint16_t item_sz; + void *buf; + + struct rt_messagequeue sq; +} osal_queue_def_t; + +typedef rt_mq_t osal_queue_t; + +static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { + rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz, + qdef->item_sz * qdef->depth, RT_IPC_FLAG_FIFO); + return &(qdef->sq); +} + +static inline bool osal_queue_receive(osal_queue_t qhdl, void *data) { + return rt_mq_recv(qhdl, data, qhdl->msg_size, RT_WAITING_FOREVER) == RT_EOK; +} + +static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) { + (void) in_isr; + return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK; +} + +static inline bool osal_queue_empty(osal_queue_t qhdl) { + return (qhdl->entry) == 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_OSAL_RTTHREAD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c new file mode 100644 index 000000000..a9c311324 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c @@ -0,0 +1,854 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Additions Copyright (c) 2020, Espressif Systems (Shanghai) Co. Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && TUSB_OPT_DEVICE_ENABLED) + +// Espressif +#include "freertos/xtensa_api.h" +#include "esp_intr_alloc.h" +#include "esp_log.h" +#include "driver/gpio.h" +#include "soc/dport_reg.h" +#include "soc/gpio_sig_map.h" +#include "soc/usb_periph.h" +#include "soc/periph_defs.h" // for interrupt source + +#include "device/dcd.h" + +// Max number of bi-directional endpoints including EP0 +// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0 +// We should probably prohibit enabling Endpoint IN > 4 (not done yet) +#define EP_MAX USB_OUT_EP_NUM + +// FIFO size in bytes +#define EP_FIFO_SIZE 1024 + +// Max number of IN EP FIFOs +#define EP_FIFO_NUM 5 + +typedef struct { + uint8_t *buffer; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API + uint16_t total_len; + uint16_t queued_len; + uint16_t max_size; + bool short_packet; +} xfer_ctl_t; + +static const char *TAG = "TUSB:DCD"; +static intr_handle_t usb_ih; + + +static uint32_t _setup_packet[2]; + +#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] +static xfer_ctl_t xfer_status[EP_MAX][2]; + +// Keep count of how many FIFOs are in use +static uint8_t _allocated_fifos = 1; //FIFO0 is always in use + +// Will either return an unused FIFO number, or 0 if all are used. +static uint8_t get_free_fifo(void) +{ + if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; + return 0; +} + +// Setup the control endpoint 0. +static void bus_reset(void) +{ + for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { + USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK + } + + // clear device address + USB0.dcfg &= ~USB_DEVADDR_M; + + USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; + USB0.doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK; + USB0.diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; + + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | + // --------------- y + x + 16 + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + 16 + GRXFSIZ + // | IN FIFO 1 | + // --------------- 16 + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): + // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN + // + // - All EP OUT shared a unique OUT FIFO which uses + // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). + // * 2 locations for OUT endpoint control words. + // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) + // * 1 location for global NAK (not required/used here). + // * It is recommended to allocate 2 times the largest packet size, therefore + // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 + USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, + USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo + USB0.grxfsiz = 52; + + // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); + + // Ready to receive SETUP packet + USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; + + USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; +} + +static void enum_done_processing(void) +{ + ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); + // On current silicon on the Full Speed core, speed is fixed to Full Speed. + // However, keep for debugging and in case Low Speed is ever supported. + uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); + + // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL + if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) + USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes + USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall + xfer_status[0][TUSB_DIR_OUT].max_size = 64; + xfer_status[0][TUSB_DIR_IN].max_size = 64; + } else { + USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes + USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall + xfer_status[0][TUSB_DIR_OUT].max_size = 8; + xfer_status[0][TUSB_DIR_IN].max_size = 8; + } +} + + +/*------------------------------------------------------------------*/ +/* Controller API + *------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + ESP_LOGV(TAG, "DCD init - Start"); + + // A. Disconnect + ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); + USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect + + // B. Programming DCFG + /* If USB host misbehaves during status portion of control xfer + (non zero-length packet), send STALL back and discard. Full speed. */ + USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL + (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) + + USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON + USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode + USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides + + // C. Setting SNAKs, then connect + for (int n = 0; n < USB_OUT_EP_NUM; n++) { + USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK + } + + // D. Interruption masking + USB0.gintmsk = 0; //mask all + USB0.gotgint = ~0U; //clear OTG ints + USB0.gintsts = ~0U; //clear pending ints + USB0.gintmsk = USB_OTGINTMSK_M | + USB_MODEMISMSK_M | + USB_RXFLVIMSK_M | + USB_ERLYSUSPMSK_M | + USB_USBSUSPMSK_M | + USB_USBRSTMSK_M | + USB_ENUMDONEMSK_M | + USB_RESETDETMSK_M | + USB_DISCONNINTMSK_M; // host most only + + dcd_connect(rhport); +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); + USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); + // Response with status after changing device address + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void)rhport; + + // set remote wakeup + USB0.dctl |= USB_RMTWKUPSIG_M; + + // enable SOF to detect bus resume + USB0.gintsts = USB_SOF_M; + USB0.gintmsk |= USB_SOFMSK_M; + + // Per specs: remote wakeup signal bit must be clear within 1-15ms + vTaskDelay(pdMS_TO_TICKS(1)); + + USB0.dctl &= ~USB_RMTWKUPSIG_M; +} + +// connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + USB0.dctl &= ~USB_SFTDISCON_M; +} + +// disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB0.dctl |= USB_SFTDISCON_M; +} + +/*------------------------------------------------------------------*/ +/* DCD Endpoint port + *------------------------------------------------------------------*/ + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) +{ + ESP_LOGV(TAG, "DCD endpoint opened"); + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + + TU_ASSERT(epnum < EP_MAX); + + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = tu_edpt_packet_size(desc_edpt); + + if (dir == TUSB_DIR_OUT) { + out_ep[epnum].doepctl |= USB_USBACTEP1_M | + desc_edpt->bmAttributes.xfer << USB_EPTYPE1_S | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0) | + xfer->max_size << USB_MPS1_S; + USB0.daintmsk |= (1 << (16 + epnum)); + } else { + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | + // --------------- y + x + 16 + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + 16 + GRXFSIZ + // | IN FIFO 1 | + // --------------- 16 + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints + // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) + // - Offset: GRXFSIZ + 16 + Size*(epnum-1) + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + + uint8_t fifo_num = get_free_fifo(); + TU_ASSERT(fifo_num != 0); + + in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M); + in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | + fifo_num << USB_D_TXFNUM1_S | + desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | + xfer->max_size << 0; + + USB0.daintmsk |= (1 << (0 + epnum)); + + // Both TXFD and TXSA are in unit of 32-bit words. + // IN FIFO 0 was configured during enumeration, hence the "+ 16". + uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; + uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); + uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); + + // DIEPTXF starts at FIFO #1. + USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; + } + return true; +} + +void dcd_edpt_close_all(uint8_t rhport) +{ + (void) rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + // Disable non-control interrupt + USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; + + for(uint8_t n = 1; n < EP_MAX; n++) + { + // disable OUT endpoint + out_ep[n].doepctl = 0; + xfer_status[n][TUSB_DIR_OUT].max_size = 0; + + // disable IN endpoint + in_ep[n].diepctl = 0; + xfer_status[n][TUSB_DIR_IN].max_size = 0; + } + + _allocated_fifos = 1; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void)rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if (short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", + epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), + num_packets, total_bytes); + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them + // here. + if (dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; + USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK + + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + USB0.dtknqr4_fifoemptymsk |= (1 << epnum); + } + } else { + // Each complete packet for OUT xfers triggers XFRC. + USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + return true; +} + +#if 0 // TODO support dcd_edpt_xfer_fifo API +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void)rhport; +} +#endif + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_IN) { + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); + } else { + // Stop transmitting packets and NAK IN xfers. + in_ep[epnum].diepctl |= USB_DI_SNAK1_M; + while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) ; + + // Disable the endpoint. Note that both SNAK and STALL are set here. + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | USB_D_EPDIS1_M); + while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) ; + in_ep[epnum].diepint = USB_D_EPDISBLD0_M; + } + + // Flush the FIFO, and wait until we have confirmed it cleared. + uint8_t const fifo_num = ((in_ep[epnum].diepctl >> USB_D_TXFNUM1_S) & USB_D_TXFNUM1_V); + USB0.grstctl |= (fifo_num << USB_TXFNUM_S); + USB0.grstctl |= USB_TXFFLSH_M; + while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ; + } else { + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { + out_ep[epnum].doepctl |= USB_STALL0_M; + } else { + // Asserting GONAK is required to STALL an OUT endpoint. + // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt + // anyway, and it can't be cleared by user code. If this while loop never + // finishes, we have bigger problems than just the stack. + USB0.dctl |= USB_SGOUTNAK_M; + while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) ; + + // Ditto here- disable the endpoint. Note that only STALL and not SNAK + // is set here. + out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); + while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) ; + out_ep[epnum].doepint = USB_EPDISBLD0_M; + + // Allow other OUT endpoints to keep receiving. + USB0.dctl |= USB_CGOUTNAK_M; + } + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_IN) { + in_ep[epnum].diepctl &= ~USB_D_STALL1_M; + + uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + if (eptype == 2 || eptype == 3) { + in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; + } + } else { + out_ep[epnum].doepctl &= ~USB_STALL1_M; + + uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + if (eptype == 2 || eptype == 3) { + out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; + } + } +} + +/*------------------------------------------------------------------*/ + +static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) +{ + ESP_EARLY_LOGV(TAG, "USB - receive_packet"); + volatile uint32_t *rx_fifo = USB0.fifo[0]; + + // See above TODO + // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; + // xfer->queued_len = xfer->total_len - remaining; + + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t to_recv_size; + + if (remaining <= xfer->max_size) { + // Avoid buffer overflow. + to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; + } else { + // Room for full packet, choose recv_size based on what the microcontroller + // claims. + to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; + } + + // Common buffer read +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + // Ring buffer + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); + } + else +#endif + { + uint8_t to_recv_rem = to_recv_size % 4; + uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; + + // Do not assume xfer buffer is aligned. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to collect. + if (to_recv_size >= 4) { + for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { + uint32_t tmp = (*rx_fifo); + base[i] = tmp & 0x000000FF; + base[i + 1] = (tmp & 0x0000FF00) >> 8; + base[i + 2] = (tmp & 0x00FF0000) >> 16; + base[i + 3] = (tmp & 0xFF000000) >> 24; + } + } + + // Do not read invalid bytes from RX FIFO. + if (to_recv_rem != 0) { + uint32_t tmp = (*rx_fifo); + uint8_t *last_32b_bound = base + to_recv_size_aligned; + + last_32b_bound[0] = tmp & 0x000000FF; + if (to_recv_rem > 1) { + last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; + } + if (to_recv_rem > 2) { + last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + } + } + } + + xfer->queued_len += xfer_size; + + // Per USB spec, a short OUT packet (including length 0) is always + // indicative of the end of a transfer (at least for ctl, bulk, int). + xfer->short_packet = (xfer_size < xfer->max_size); +} + +static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) +{ + ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); + volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; + + uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; + xfer->queued_len = xfer->total_len - remaining; + + uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; + +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); + } + else +#endif + { + uint8_t to_xfer_rem = to_xfer_size % 4; + uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; + + // Buffer might not be aligned to 32b, so we need to force alignment + // by copying to a temp var. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to send off. + if (to_xfer_size >= 4) { + for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { + uint32_t tmp = base[i] | (base[i + 1] << 8) | + (base[i + 2] << 16) | (base[i + 3] << 24); + (*tx_fifo) = tmp; + } + } + + // Do not read beyond end of buffer if not divisible by 4. + if (to_xfer_rem != 0) { + uint32_t tmp = 0; + uint8_t *last_32b_bound = base + to_xfer_size_aligned; + + tmp |= last_32b_bound[0]; + if (to_xfer_rem > 1) { + tmp |= (last_32b_bound[1] << 8); + } + if (to_xfer_rem > 2) { + tmp |= (last_32b_bound[2] << 16); + } + + (*tx_fifo) = tmp; + } + } +} + +static void read_rx_fifo(void) +{ + // Pop control word off FIFO (completed xfers will have 2 control words, + // we only pop one ctl word each interrupt). + uint32_t const ctl_word = USB0.grxstsp; + uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; + uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; + uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; + + switch (pktsts) { + case 0x01: // Global OUT NAK (Interrupt) + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); + break; + + case 0x02: { // Out packet recvd + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + receive_packet(xfer, bcnt); + } + break; + + case 0x03: // Out packet done (Interrupt) + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); + break; + + case 0x04: // Step 2: Setup transaction completed (Interrupt) + // After this event, OEPINT interrupt will occur with SETUP bit set + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); + USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; + break; + + case 0x06: { // Step1: Setup data packet received + volatile uint32_t *rx_fifo = USB0.fifo[0]; + + // We can receive up to three setup packets in succession, but + // only the last one is valid. Therefore we just overwrite it + _setup_packet[0] = (*rx_fifo); + _setup_packet[1] = (*rx_fifo); + + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); + } + break; + + default: // Invalid, do something here, like breakpoint? + TU_BREAKPOINT(); + break; + } +} + +static void handle_epout_ints(void) +{ + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DOEPINTx is cleared. + // DOEPINT will be cleared when DAINT's out bits are cleared. + for (int n = 0; n < USB_OUT_EP_NUM; n++) { + xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + + if (USB0.daint & (1 << (16 + n))) { + // SETUP packet Setup Phase done. + if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { + USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear + dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); + } + + // OUT XFER complete (single packet).q + if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { + + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); + USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; + + // Transfer complete if short packet or total len is transferred + if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { + xfer->short_packet = false; + dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } else { + // Schedule another packet to be received. + USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + } + } + } +} + +static void handle_epin_ints(void) +{ + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DIEPINTx is cleared. + // IEPINT will be cleared when DAINT's out bits are cleared. + for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { + xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; + + if (USB0.daint & (1 << (0 + n))) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); + // IN XFER complete (entire xfer). + if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); + USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; + dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + + // XFER FIFO empty + if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); + USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; + transmit_packet(xfer, &USB0.in_ep_reg[n], n); + + // Turn off TXFE if all bytes are written. + if (xfer->queued_len == xfer->total_len) + { + USB0.dtknqr4_fifoemptymsk &= ~(1 << n); + } + } + + // XFER Timeout + if (USB0.in_ep_reg[n].diepint & USB_D_TIMEOUT0_M) { + // Clear interrupt or enpoint will hang. + USB0.in_ep_reg[n].diepint = USB_D_TIMEOUT0_M; + // Maybe retry? + } + } + } +} + + +static void _dcd_int_handler(void* arg) +{ + (void) arg; + uint8_t const rhport = 0; + + const uint32_t int_msk = USB0.gintmsk; + const uint32_t int_status = USB0.gintsts & int_msk; + + if (int_status & USB_USBRST_M) { + // start of reset + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); + USB0.gintsts = USB_USBRST_M; + // FIFOs will be reassigned when the endpoints are reopen + _allocated_fifos = 1; + bus_reset(); + } + + if (int_status & USB_RESETDET_M) { + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); + USB0.gintsts = USB_RESETDET_M; + bus_reset(); + } + + if (int_status & USB_ENUMDONE_M) { + // ENUMDNE detects speed of the link. For full-speed, we + // always expect the same value. This interrupt is considered + // the end of reset. + USB0.gintsts = USB_ENUMDONE_M; + enum_done_processing(); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); + } + + if(int_status & USB_USBSUSP_M) + { + USB0.gintsts = USB_USBSUSP_M; + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + } + + if(int_status & USB_WKUPINT_M) + { + USB0.gintsts = USB_WKUPINT_M; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + } + + if (int_status & USB_OTGINT_M) + { + // OTG INT bit is read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); + + uint32_t const otg_int = USB0.gotgint; + + if (otg_int & USB_SESENDDET_M) + { + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); + } + + USB0.gotgint = otg_int; + } + + if (int_status & USB_SOF_M) { + USB0.gintsts = USB_SOF_M; + + // Disable SOF interrupt since currently only used for remote wakeup detection + USB0.gintmsk &= ~USB_SOFMSK_M; + + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + } + + + if (int_status & USB_RXFLVI_M) { + // RXFLVL bit is read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); + + // Mask out RXFLVL while reading data from FIFO + USB0.gintmsk &= ~USB_RXFLVIMSK_M; + read_rx_fifo(); + USB0.gintmsk |= USB_RXFLVIMSK_M; + } + + // OUT endpoint interrupt handling. + if (int_status & USB_OEPINT_M) { + // OEPINT is read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); + handle_epout_ints(); + } + + // IN endpoint interrupt handling. + if (int_status & USB_IEPINT_M) { + // IEPINT bit read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); + handle_epin_ints(); + } + + // Without handling + USB0.gintsts |= USB_CURMOD_INT_M | + USB_MODEMIS_M | + USB_OTGINT_M | + USB_NPTXFEMP_M | + USB_GINNAKEFF_M | + USB_GOUTNAKEFF | + USB_ERLYSUSP_M | + USB_USBSUSP_M | + USB_ISOOUTDROP_M | + USB_EOPF_M | + USB_EPMIS_M | + USB_INCOMPISOIN_M | + USB_INCOMPIP_M | + USB_FETSUSP_M | + USB_PTXFEMP_M; +} + +void dcd_int_enable (uint8_t rhport) +{ + (void) rhport; + esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) _dcd_int_handler, NULL, &usb_ih); +} + +void dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + esp_intr_free(usb_ih); +} + +#endif // #if OPT_MCU_ESP32S2 || OPT_MCU_ESP32S3 + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c new file mode 100644 index 000000000..9583f509d --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c @@ -0,0 +1,245 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_HOST_ENABLED || TUSB_OPT_DEVICE_ENABLED + +#include "tusb.h" + +// TODO clean up +#if TUSB_OPT_DEVICE_ENABLED +#include "device/usbd_pvt.h" +#endif + +bool tusb_init(void) +{ +#if TUSB_OPT_DEVICE_ENABLED + TU_ASSERT ( tud_init(TUD_OPT_RHPORT) ); // init device stack +#endif + +#if TUSB_OPT_HOST_ENABLED + TU_ASSERT( tuh_init(TUH_OPT_RHPORT) ); // init host stack +#endif + + return true; +} + +bool tusb_inited(void) +{ + bool ret = false; + +#if TUSB_OPT_DEVICE_ENABLED + ret = ret || tud_inited(); +#endif + +#if TUSB_OPT_HOST_ENABLED + ret = ret || tuh_inited(); +#endif + + return ret; +} + +//--------------------------------------------------------------------+ +// Internal Helper for both Host and Device stack +//--------------------------------------------------------------------+ + +bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) +{ + uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); + + switch (desc_ep->bmAttributes.xfer) + { + case TUSB_XFER_ISOCHRONOUS: + { + uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023); + TU_ASSERT(max_packet_size <= spec_size); + } + break; + + case TUSB_XFER_BULK: + if (speed == TUSB_SPEED_HIGH) + { + // Bulk highspeed must be EXACTLY 512 + TU_ASSERT(max_packet_size == 512); + }else + { + // TODO Bulk fullspeed can only be 8, 16, 32, 64 + TU_ASSERT(max_packet_size <= 64); + } + break; + + case TUSB_XFER_INTERRUPT: + { + uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64); + TU_ASSERT(max_packet_size <= spec_size); + } + break; + + default: return false; + } + + return true; +} + +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint8_t const* desc_end = p_desc + desc_len; + + while( p_desc < desc_end ) + { + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; + + TU_LOG(2, " Bind EP %02x to driver id %u\r\n", ep_addr, driver_id); + ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; + } + + p_desc = tu_desc_next(p_desc); + } +} + +uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while (itf_count--) + { + // Next on interface desc + len += tu_desc_len(desc_itf); + p_desc = tu_desc_next(p_desc); + + while (len < max_len) + { + // return on IAD regardless of itf count + if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; + + if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) + { + break; + } + + len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + } + + return len; +} + +/*------------------------------------------------------------------*/ +/* Debug + *------------------------------------------------------------------*/ +#if CFG_TUSB_DEBUG +#include + +char const* const tusb_strerr[TUSB_ERROR_COUNT] = { ERROR_TABLE(ERROR_STRING) }; + +static void dump_str_line(uint8_t const* buf, uint16_t count) +{ + tu_printf(" |"); + + // each line is 16 bytes + for(uint16_t i=0; i= 0 ) + +// Which roothub port is configured as device +#define TUD_OPT_RHPORT ( ((CFG_TUSB_RHPORT0_MODE) & OPT_MODE_DEVICE) ? 0 : (((CFG_TUSB_RHPORT1_MODE) & OPT_MODE_DEVICE) ? 1 : -1) ) + +#if TUD_OPT_RHPORT == 0 +#define TUD_OPT_HIGH_SPEED ( (CFG_TUSB_RHPORT0_MODE) & OPT_MODE_HIGH_SPEED ) +#else +#define TUD_OPT_HIGH_SPEED ( (CFG_TUSB_RHPORT1_MODE) & OPT_MODE_HIGH_SPEED ) +#endif + +#define TUSB_OPT_DEVICE_ENABLED ( TUD_OPT_RHPORT >= 0 ) + +//--------------------------------------------------------------------+ +// COMMON OPTIONS +//--------------------------------------------------------------------+ + +// Debug enable to print out error message +#ifndef CFG_TUSB_DEBUG + #define CFG_TUSB_DEBUG 0 +#endif + +// place data in accessible RAM for usb controller +#ifndef CFG_TUSB_MEM_SECTION + #define CFG_TUSB_MEM_SECTION +#endif + +// alignment requirement of buffer used for endpoint transferring +#ifndef CFG_TUSB_MEM_ALIGN + #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) +#endif + +// OS selection +#ifndef CFG_TUSB_OS + #define CFG_TUSB_OS OPT_OS_NONE +#endif + +#ifndef CFG_TUSB_OS_INC_PATH + #define CFG_TUSB_OS_INC_PATH +#endif + +//-------------------------------------------------------------------- +// DEVICE OPTIONS +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE + #define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +#ifndef CFG_TUD_CDC + #define CFG_TUD_CDC 0 +#endif + +#ifndef CFG_TUD_MSC + #define CFG_TUD_MSC 0 +#endif + +#ifndef CFG_TUD_HID + #define CFG_TUD_HID 0 +#endif + +#ifndef CFG_TUD_AUDIO + #define CFG_TUD_AUDIO 0 +#endif + +#ifndef CFG_TUD_VIDEO + #define CFG_TUD_VIDEO 0 +#endif + +#ifndef CFG_TUD_MIDI + #define CFG_TUD_MIDI 0 +#endif + +#ifndef CFG_TUD_VENDOR + #define CFG_TUD_VENDOR 0 +#endif + +#ifndef CFG_TUD_USBTMC + #define CFG_TUD_USBTMC 0 +#endif + +#ifndef CFG_TUD_DFU_RUNTIME + #define CFG_TUD_DFU_RUNTIME 0 +#endif + +#ifndef CFG_TUD_DFU + #define CFG_TUD_DFU 0 +#endif + +#ifndef CFG_TUD_BTH + #define CFG_TUD_BTH 0 +#endif + +#ifndef CFG_TUD_ECM_RNDIS + #ifdef CFG_TUD_NET + #warning "CFG_TUD_NET is renamed to CFG_TUD_ECM_RNDIS" + #define CFG_TUD_ECM_RNDIS CFG_TUD_NET + #else + #define CFG_TUD_ECM_RNDIS 0 + #endif +#endif + +#ifndef CFG_TUD_NCM + #define CFG_TUD_NCM 0 +#endif + +//-------------------------------------------------------------------- +// HOST OPTIONS +//-------------------------------------------------------------------- +#if TUSB_OPT_HOST_ENABLED + #ifndef CFG_TUH_DEVICE_MAX + #define CFG_TUH_DEVICE_MAX 1 + #endif + + #ifndef CFG_TUH_ENUMERATION_BUFSIZE + #define CFG_TUH_ENUMERATION_BUFSIZE 256 + #endif +#endif // TUSB_OPT_HOST_ENABLED + +//------------- CLASS -------------// + +#ifndef CFG_TUH_HUB +#define CFG_TUH_HUB 0 +#endif + +#ifndef CFG_TUH_CDC +#define CFG_TUH_CDC 0 +#endif + +#ifndef CFG_TUH_HID +#define CFG_TUH_HID 0 +#endif + +#ifndef CFG_TUH_MIDI +#define CFG_TUH_MIDI 0 +#endif + +#ifndef CFG_TUH_MSC +#define CFG_TUH_MSC 0 +#endif + +#ifndef CFG_TUH_VENDOR +#define CFG_TUH_VENDOR 0 +#endif + +//--------------------------------------------------------------------+ +// Port Specific +// TUP stand for TinyUSB Port (can be renamed) +//--------------------------------------------------------------------+ + +//------------- Unaligned Memory -------------// + +// ARMv7+ (M3-M7, M23-M33) can access unaligned memory +#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) + #define TUP_ARCH_STRICT_ALIGN 0 +#else + #define TUP_ARCH_STRICT_ALIGN 1 +#endif + +// TUP_MCU_STRICT_ALIGN will overwrite TUP_ARCH_STRICT_ALIGN. +// In case TUP_MCU_STRICT_ALIGN = 1 and TUP_ARCH_STRICT_ALIGN =0, we will not reply on compiler +// to generate unaligned access code. +// LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM +#if TUD_OPT_HIGH_SPEED && (CFG_TUSB_MCU == OPT_MCU_LPC54XXX || CFG_TUSB_MCU == OPT_MCU_LPC55XX) + #define TUP_MCU_STRICT_ALIGN 1 +#else + #define TUP_MCU_STRICT_ALIGN 0 +#endif + + +//------------------------------------------------------------------ +// Configuration Validation +//------------------------------------------------------------------ +#if CFG_TUD_ENDPOINT0_SIZE > 64 + #error Control Endpoint Max Packet Size cannot be larger than 64 +#endif + +#endif /* _TUSB_OPTION_H_ */ + +/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py new file mode 100644 index 000000000..b2a80c680 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py @@ -0,0 +1,100 @@ +import os +import glob +import sys +import subprocess +import time + +import build_utils + +SUCCEEDED = "\033[32msucceeded\033[0m" +FAILED = "\033[31mfailed\033[0m" +SKIPPED = "\033[33mskipped\033[0m" + +success_count = 0 +fail_count = 0 +skip_count = 0 +exit_status = 0 + +total_time = time.monotonic() + +build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |' +build_separator = '-' * 106 + +def filter_with_input(mylist): + if len(sys.argv) > 1: + input_args = list(set(mylist).intersection(sys.argv)) + if len(input_args) > 0: + mylist[:] = input_args + +# If examples are not specified in arguments, build all +all_examples = [] +for entry in os.scandir("examples/device"): + if entry.is_dir(): + all_examples.append("device/" + entry.name) +for entry in os.scandir("examples/host"): + if entry.is_dir(): + all_examples.append("host/" + entry.name) +filter_with_input(all_examples) +all_examples.sort() + +# If boards are not specified in arguments, build all +all_boards = [] +for entry in os.scandir("hw/bsp"): + if entry.is_dir() and os.path.exists(entry.path + "/board.mk"): + all_boards.append(entry.name) +filter_with_input(all_boards) +all_boards.sort() + +def build_board(example, board): + global success_count, fail_count, skip_count, exit_status + start_time = time.monotonic() + flash_size = "-" + sram_size = "-" + + # Check if board is skipped + if build_utils.skip_example(example, board): + success = SKIPPED + skip_count += 1 + print(build_format.format(example, board, success, '-', flash_size, sram_size)) + else: + subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + + if build_result.returncode == 0: + success = SUCCEEDED + success_count += 1 + (flash_size, sram_size) = build_size(example, board) + else: + exit_status = build_result.returncode + success = FAILED + fail_count += 1 + + build_duration = time.monotonic() - start_time + print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) + + if build_result.returncode != 0: + print(build_result.stdout.decode("utf-8")) + +def build_size(example, board): + #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) + elf_file = 'examples/{}/_build/{}/*.elf'.format(example, board) + size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") + size_list = size_output.split('\n')[1].split('\t') + flash_size = int(size_list[0]) + sram_size = int(size_list[1]) + int(size_list[2]) + return (flash_size, sram_size) + +print(build_separator) +print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) + +for example in all_examples: + print(build_separator) + for board in all_boards: + build_board(example, board) + +total_time = time.monotonic() - total_time +print(build_separator) +print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) +print(build_separator) + +sys.exit(exit_status) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py new file mode 100644 index 000000000..2947a0a6b --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py @@ -0,0 +1,101 @@ +import os +import glob +import sys +import subprocess +import time + +import build_utils + +SUCCEEDED = "\033[32msucceeded\033[0m" +FAILED = "\033[31mfailed\033[0m" +SKIPPED = "\033[33mskipped\033[0m" + +success_count = 0 +fail_count = 0 +skip_count = 0 +exit_status = 0 + +total_time = time.monotonic() + +build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |' +build_separator = '-' * 100 + +def filter_with_input(mylist): + if len(sys.argv) > 1: + input_args = list(set(mylist).intersection(sys.argv)) + if len(input_args) > 0: + mylist[:] = input_args + +# Build all examples if not specified +all_examples = [] +for entry in os.scandir("examples/device"): + # Only includes example with CMakeLists.txt for esp32s, and skip board_test to speed up ci + if entry.is_dir() and os.path.exists(entry.path + "/sdkconfig.defaults") and entry.name != 'board_test': + all_examples.append(entry.name) +filter_with_input(all_examples) +all_examples.sort() + +# Build all boards if not specified +all_boards = [] +for entry in os.scandir("hw/bsp/esp32s2/boards"): + if entry.is_dir(): + all_boards.append(entry.name) +for entry in os.scandir("hw/bsp/esp32s3/boards"): + if entry.is_dir(): + all_boards.append(entry.name) +filter_with_input(all_boards) +all_boards.sort() + +def build_board(example, board): + global success_count, fail_count, skip_count, exit_status + start_time = time.monotonic() + flash_size = "-" + sram_size = "-" + + # Check if board is skipped + if build_utils.skip_example(example, board): + success = SKIPPED + skip_count += 1 + print(build_format.format(example, board, success, '-', flash_size, sram_size)) + else: + subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + build_result = subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + + if build_result.returncode == 0: + success = SUCCEEDED + success_count += 1 + (flash_size, sram_size) = build_size(example, board) + else: + exit_status = build_result.returncode + success = FAILED + fail_count += 1 + + build_duration = time.monotonic() - start_time + print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) + + if build_result.returncode != 0: + print(build_result.stdout.decode("utf-8")) + +def build_size(example, board): + #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) + elf_file = 'examples/device/{}/_build/{}/*.elf'.format(example, board) + size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") + size_list = size_output.split('\n')[1].split('\t') + flash_size = int(size_list[0]) + sram_size = int(size_list[1]) + int(size_list[2]) + return (flash_size, sram_size) + +print(build_separator) +print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) +print(build_separator) + +for example in all_examples: + for board in all_boards: + build_board(example, board) + +total_time = time.monotonic() - total_time +print(build_separator) +print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) +print(build_separator) + +sys.exit(exit_status) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py new file mode 100644 index 000000000..4094d07db --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py @@ -0,0 +1,113 @@ +import os +import glob +import sys +import subprocess +import time + +import build_utils + +SUCCEEDED = "\033[32msucceeded\033[0m" +FAILED = "\033[31mfailed\033[0m" +SKIPPED = "\033[33mskipped\033[0m" + +success_count = 0 +fail_count = 0 +skip_count = 0 +exit_status = 0 + +total_time = time.monotonic() + +build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |' +build_separator = '-' * 106 + +def filter_with_input(mylist): + if len(sys.argv) > 1: + input_args = list(set(mylist).intersection(sys.argv)) + if len(input_args) > 0: + mylist[:] = input_args + +# If examples are not specified in arguments, build all +all_examples = [] +for entry in os.scandir("examples/device"): + if entry.is_dir(): + all_examples.append("device/" + entry.name) +for entry in os.scandir("examples/host"): + if entry.is_dir(): + all_examples.append("host/" + entry.name) +filter_with_input(all_examples) +all_examples.sort() + +# If family are not specified in arguments, build all +all_families = [] +for entry in os.scandir("hw/bsp"): + if entry.is_dir() and os.path.isdir(entry.path + "/boards") and entry.name not in ("esp32s2", "esp32s3"): + all_families.append(entry.name) + +filter_with_input(all_families) +all_families.sort() + +def build_family(example, family): + all_boards = [] + for entry in os.scandir("hw/bsp/{}/boards".format(family)): + if entry.is_dir(): + all_boards.append(entry.name) + filter_with_input(all_boards) + all_boards.sort() + + for board in all_boards: + build_board(example, board) + +def build_board(example, board): + global success_count, fail_count, skip_count, exit_status + start_time = time.monotonic() + flash_size = "-" + sram_size = "-" + + # Check if board is skipped + if build_utils.skip_example(example, board): + success = SKIPPED + skip_count += 1 + print(build_format.format(example, board, success, '-', flash_size, sram_size)) + else: + #subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + + if build_result.returncode == 0: + success = SUCCEEDED + success_count += 1 + (flash_size, sram_size) = build_size(example, board) + subprocess.run("make -j -C examples/{} BOARD={} copy-artifact".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + else: + exit_status = build_result.returncode + success = FAILED + fail_count += 1 + + build_duration = time.monotonic() - start_time + print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) + + if build_result.returncode != 0: + print(build_result.stdout.decode("utf-8")) + +def build_size(example, board): + #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) + elf_file = 'examples/{}/_build/{}/*.elf'.format(example, board) + size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") + size_list = size_output.split('\n')[1].split('\t') + flash_size = int(size_list[0]) + sram_size = int(size_list[1]) + int(size_list[2]) + return (flash_size, sram_size) + +print(build_separator) +print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) + +for example in all_examples: + print(build_separator) + for family in all_families: + build_family(example, family) + +total_time = time.monotonic() - total_time +print(build_separator) +print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) +print(build_separator) + +sys.exit(exit_status) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py new file mode 100644 index 000000000..299fffa4d --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py @@ -0,0 +1,61 @@ +import pathlib + +def skip_example(example, board): + ex_dir = pathlib.Path('examples/') / example + bsp = pathlib.Path("hw/bsp") + + board_dir = list(bsp.glob("*/boards/" + board)) + if not board_dir: + # Skip unknown boards + return True + + board_dir = list(board_dir)[0] + + family_dir = board_dir.parent.parent + family = family_dir.name + + # family CMake + family_mk = family_dir / "family.cmake" + + # family.mk + if not family_mk.exists(): + family_mk = family_dir / "family.mk" + + mk_contents = family_mk.read_text() + + # Find the mcu + if "CFG_TUSB_MCU=OPT_MCU_" not in mk_contents: + board_mk = board_dir / "board.cmake" + if not board_mk.exists(): + board_mk = board_dir / "board.mk" + + mk_contents = board_mk.read_text() + + for token in mk_contents.split(): + if "CFG_TUSB_MCU=OPT_MCU_" in token: + # Strip " because cmake files has them. + token = token.strip("\"") + _, opt_mcu = token.split("=") + mcu = opt_mcu[len("OPT_MCU_"):] + + # Skip all OPT_MCU_NONE these are WIP port + if mcu == "NONE": + return True + + skip_file = ex_dir / "skip.txt" + only_file = ex_dir / "only.txt" + + if skip_file.exists() and only_file.exists(): + raise RuntimeError("Only have a skip or only file. Not both.") + elif skip_file.exists(): + skips = skip_file.read_text().split() + return ("mcu:" + mcu in skips or + "board:" + board in skips or + "family:" + family in skips) + elif only_file.exists(): + onlys = only_file.read_text().split() + return not ("mcu:" + mcu in onlys or + "board:" + board in onlys or + "family:" + family in onlys) + + return False diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py new file mode 100644 index 000000000..73c8b29fc --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py @@ -0,0 +1,51 @@ +#!/usr/bin/python3 + +import os +import xml.dom.minidom as XML + +# Read base configuration +base = "" +with open("iar_template.ipcf") as f: + base = f.read() + +# Enumerate all device/host examples +dir_1 = os.listdir("../examples") +for dir_2 in dir_1: + if os.path.isdir("../examples/{}".format(dir_2)): + print(dir_2) + examples = os.listdir("../examples/{}".format(dir_2)) + for example in examples: + if os.path.isdir("../examples/{}/{}".format(dir_2, example)): + print("../examples/{}/{}".format(dir_2, example)) + conf = XML.parseString(base) + files = conf.getElementsByTagName("files")[0] + inc = conf.getElementsByTagName("includePath")[0] + # Add bsp inc + path = conf.createElement('path') + path_txt = conf.createTextNode("$TUSB_DIR$/hw") + path.appendChild(path_txt) + inc.appendChild(path) + # Add board.c/.h + grp = conf.createElement('group') + grp.setAttribute("name", "bsp") + path = conf.createElement('path') + path_txt = conf.createTextNode("$TUSB_DIR$/hw/bsp/board.c") + path.appendChild(path_txt) + grp.appendChild(path) + files.appendChild(grp) + # Add example's .c/.h + grp = conf.createElement('group') + grp.setAttribute("name", "example") + for file in os.listdir("../examples/{}/{}/src".format(dir_2, example)): + if file.endswith(".c") or file.endswith(".h"): + path = conf.createElement('path') + path.setAttribute("copyTo", "$PROJ_DIR$/{}".format(file)) + path_txt = conf.createTextNode("$TUSB_DIR$/examples/{0}/{1}/src/{2}".format(dir_2, example, file)) + path.appendChild(path_txt) + grp.appendChild(path) + files.appendChild(grp) + cfg_str = conf.toprettyxml() + cfg_str = '\n'.join([s for s in cfg_str.splitlines() if s.strip()]) + #print(cfg_str) + with open("../examples/{0}/{1}/iar_{1}.ipcf".format(dir_2, example), 'w') as f: + f.write(cfg_str) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf new file mode 100644 index 000000000..ba54fe057 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf @@ -0,0 +1,145 @@ + + + + + $TUSB_DIR$/src + $TUSB_DIR$/lib/SEGGER_RTT/RTT + $PROJ_DIR$ + + + + $TUSB_DIR$/src/device/usbd.c + $TUSB_DIR$/src/device/usbd_control.c + + + $TUSB_DIR$/src/common/tusb_fifo.c + + + $TUSB_DIR$/src/class/audio/audio_device.c + + + $TUSB_DIR$/src/class/bth/bth_device.c + + + $TUSB_DIR$/src/class/cdc/cdc_device.c + $TUSB_DIR$/src/class/cdc/cdc_host.c + $TUSB_DIR$/src/class/cdc/cdc_rndis_host.c + + + $TUSB_DIR$/src/class/dfu/dfu_device.c + $TUSB_DIR$/src/class/dfu/dfu_rt_device.c + + + $TUSB_DIR$/src/class/hid/hid_device.c + $TUSB_DIR$/src/class/hid/hid_host.c + + + $TUSB_DIR$/src/class/midi/midi_device.c + + + $TUSB_DIR$/src/class/msc/msc_device.c + $TUSB_DIR$/src/class/msc/msc_host.c + + + $TUSB_DIR$/src/class/net/ecm_rndis_device.c + $TUSB_DIR$/src/class/net/ncm_device.c + + + $TUSB_DIR$/src/class/usbtmc/usbtmc_device.c + + + $TUSB_DIR$/src/class/vendor/vendor_device.c + $TUSB_DIR$/src/class/vendor/vendor_host.c + + + $TUSB_DIR$/src/tusb.c + + + $TUSB_DIR$/src/host/hub.c + $TUSB_DIR$/src/host/usbh.c + $TUSB_DIR$/src/host/usbh_control.c + + + $TUSB_DIR$/src/portable/synopsys/dwc2/dcd_dwc2.c + + + $TUSB_DIR$/src/portable/dialog/da146xx/dcd_da146xx.c + + + $TUSB_DIR$/src/portable/ehci/ehci.c + + + $TUSB_DIR$/src/portable/espressif/esp32sx/dcd_esp32sx.c + + + $TUSB_DIR$/src/portable/mentor/musb/dcd_musb.c + + + $TUSB_DIR$/src/portable/microchip/samd/dcd_samd.c + + + $TUSB_DIR$/src/portable/microchip/samg/dcd_samg.c + + + $TUSB_DIR$/src/portable/microchip/samx7x/dcd_samx7x.c + + + $TUSB_DIR$/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c + + + $TUSB_DIR$/src/portable/nordic/nrf5x/dcd_nrf5x.c + + + $TUSB_DIR$/src/portable/nuvoton/nuc120/dcd_nuc120.c + + + $TUSB_DIR$/src/portable/nuvoton/nuc121/dcd_nuc121.c + + + $TUSB_DIR$/src/portable/nuvoton/nuc505/dcd_nuc505.c + + + $TUSB_DIR$/src/portable/nxp/khci/dcd_khci.c + + + $TUSB_DIR$/src/portable/nxp/lpc17_40/dcd_lpc17_40.c + $TUSB_DIR$/src/portable/nxp/lpc17_40/hcd_lpc17_40.c + + + $TUSB_DIR$/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c + + + $TUSB_DIR$/src/portable/nxp/transdimension/dcd_transdimension.c + $TUSB_DIR$/src/portable/nxp/transdimension/hcd_transdimension.c + + + $TUSB_DIR$/src/portable/ohci/ohci.c + + + $TUSB_DIR$/src/portable/raspberrypi/rp2040/dcd_rp2040.c + $TUSB_DIR$/src/portable/raspberrypi/rp2040/hcd_rp2040.c + $TUSB_DIR$/src/portable/raspberrypi/rp2040/rp2040_usb.c + + + $TUSB_DIR$/src/portable/renesas/usba/dcd_usba.c + + + $TUSB_DIR$/src/portable/sony/cxd56/dcd_cxd56.c + + + $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + + + $TUSB_DIR$/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c + + + $TUSB_DIR$/src/portable/valentyusb/eptri/dcd_eptri.c + + + $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT.c + $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c + $TUSB_DIR$/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c + + + + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk new file mode 100644 index 000000000..84523a557 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk @@ -0,0 +1,30 @@ +ifneq ($(lastword a b),b) +$(error This Makefile require make 3.81 or newer) +endif + +# Detect whether shell style is windows or not +# https://stackoverflow.com/questions/714100/os-detecting-makefile/52062069#52062069 +ifeq '$(findstring ;,$(PATH))' ';' +CMDEXE := 1 +endif + +# Set TOP to be the path to get from the current directory (where make was +# invoked) to the top of the tree. $(lastword $(MAKEFILE_LIST)) returns +# the name of this makefile relative to where make was invoked. + +THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) +TOP := $(patsubst %/tools/top.mk,%,$(THIS_MAKEFILE)) + +ifeq ($(CMDEXE),1) +TOP := $(subst \,/,$(shell for %%i in ( $(TOP) ) do echo %%~fi)) +else +TOP := $(shell realpath $(TOP)) +endif +#$(info Top directory is $(TOP)) + +ifeq ($(CMDEXE),1) +CURRENT_PATH := $(subst $(TOP)/,,$(subst \,/,$(shell echo %CD%))) +else +CURRENT_PATH := $(shell realpath --relative-to=$(TOP) `pwd`) +endif +#$(info Path from top is $(CURRENT_PATH)) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf new file mode 100644 index 000000000..e7f7a9b22 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf @@ -0,0 +1,108 @@ +;************************************************************ +; Windows USB CDC ACM Setup File +; Copyright (c) 2000 Microsoft Corporation + + +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} +Provider=%MFGNAME% +LayoutFile=layout.inf +CatalogFile=%MFGFILENAME%.cat +DriverVer=11/15/2007,5.1.2600.0 +DriverPackageDisplayName=%DESCRIPTION% + +[Manufacturer] +%MFGNAME%=DeviceList, NTamd64 + +[DestinationDirs] +DefaultDestDir=12 + + +;------------------------------------------------------------------------------ +; Windows 2000/XP/Vista-32bit Sections +;------------------------------------------------------------------------------ + +[DriverInstall.nt] +include=mdmcpq.inf +CopyFiles=DriverCopyFiles.nt +AddReg=DriverInstall.nt.AddReg + +[DriverCopyFiles.nt] +usbser.sys,,,0x20 + +[DriverInstall.nt.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,%DRIVERFILENAME%.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[DriverInstall.nt.Services] +AddService=usbser, 0x00000002, DriverService.nt + +[DriverService.nt] +DisplayName=%SERVICE% +ServiceType=1 +StartType=3 +ErrorControl=1 +ServiceBinary=%12%\%DRIVERFILENAME%.sys + +;------------------------------------------------------------------------------ +; Vista-64bit Sections +;------------------------------------------------------------------------------ + +[DriverInstall.NTamd64] +include=mdmcpq.inf +CopyFiles=DriverCopyFiles.NTamd64 +AddReg=DriverInstall.NTamd64.AddReg + +[DriverCopyFiles.NTamd64] +%DRIVERFILENAME%.sys,,,0x20 + +[DriverInstall.NTamd64.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,%DRIVERFILENAME%.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[DriverInstall.NTamd64.Services] +AddService=usbser, 0x00000002, DriverService.NTamd64 + +[DriverService.NTamd64] +DisplayName=%SERVICE% +ServiceType=1 +StartType=3 +ErrorControl=1 +ServiceBinary=%12%\%DRIVERFILENAME%.sys + + +;------------------------------------------------------------------------------ +; Vendor and Product ID Definitions +;------------------------------------------------------------------------------ +; When developing your USB device, the VID and PID used in the PC side +; application program and the firmware on the microcontroller must match. +; Modify the below line to use your VID and PID. Use the format as shown below. +; Note: One INF file can be used for multiple devices with different VID and PIDs. +; For each supported device, append ",USB\VID_xxxx&PID_yyyy" to the end of the line. +;------------------------------------------------------------------------------ +[SourceDisksFiles] +[SourceDisksNames] +[DeviceList] + +%DESCRIPTION%=DriverInstall, USB\VID_CAFE&PID_4001&MI_00, USB\VID_CAFE&PID_4003&MI_00, USB\VID_CAFE&PID_4005&MI_00, USB\VID_CAFE&PID_4007&MI_00, USB\VID_CAFE&PID_4009&MI_00, USB\VID_CAFE&PID_400b&MI_00, USB\VID_CAFE&PID_400d&MI_00, USB\VID_CAFE&PID_400f&MI_00, USB\VID_CAFE&PID_4011&MI_00, USB\VID_CAFE&PID_4013&MI_00, USB\VID_CAFE&PID_4015&MI_00, USB\VID_CAFE&PID_4017&MI_00, USB\VID_CAFE&PID_4019&MI_00, USB\VID_CAFE&PID_401b&MI_00, USB\VID_CAFE&PID_401d&MI_00, USB\VID_CAFE&PID_401f&MI_00, USB\VID_CAFE&PID_4021&MI_00, USB\VID_CAFE&PID_4023&MI_00, USB\VID_CAFE&PID_4025&MI_00, USB\VID_CAFE&PID_4027&MI_00, USB\VID_CAFE&PID_4029&MI_00, USB\VID_CAFE&PID_402b&MI_00, USB\VID_CAFE&PID_402d&MI_00, USB\VID_CAFE&PID_402f&MI_00, USB\VID_CAFE&PID_4031&MI_00, USB\VID_CAFE&PID_4033&MI_00, USB\VID_CAFE&PID_4035&MI_00, USB\VID_CAFE&PID_4037&MI_00, USB\VID_CAFE&PID_4039&MI_00, USB\VID_CAFE&PID_403b&MI_00, USB\VID_CAFE&PID_403d&MI_00, USB\VID_CAFE&PID_403f&MI_00 + + +[DeviceList.NTamd64] +%DESCRIPTION%=DriverInstall, USB\VID_CAFE&PID_4001&MI_00, USB\VID_CAFE&PID_4003&MI_00, USB\VID_CAFE&PID_4005&MI_00, USB\VID_CAFE&PID_4007&MI_00, USB\VID_CAFE&PID_4009&MI_00, USB\VID_CAFE&PID_400b&MI_00, USB\VID_CAFE&PID_400d&MI_00, USB\VID_CAFE&PID_400f&MI_00, USB\VID_CAFE&PID_4011&MI_00, USB\VID_CAFE&PID_4013&MI_00, USB\VID_CAFE&PID_4015&MI_00, USB\VID_CAFE&PID_4017&MI_00, USB\VID_CAFE&PID_4019&MI_00, USB\VID_CAFE&PID_401b&MI_00, USB\VID_CAFE&PID_401d&MI_00, USB\VID_CAFE&PID_401f&MI_00, USB\VID_CAFE&PID_4021&MI_00, USB\VID_CAFE&PID_4023&MI_00, USB\VID_CAFE&PID_4025&MI_00, USB\VID_CAFE&PID_4027&MI_00, USB\VID_CAFE&PID_4029&MI_00, USB\VID_CAFE&PID_402b&MI_00, USB\VID_CAFE&PID_402d&MI_00, USB\VID_CAFE&PID_402f&MI_00, USB\VID_CAFE&PID_4031&MI_00, USB\VID_CAFE&PID_4033&MI_00, USB\VID_CAFE&PID_4035&MI_00, USB\VID_CAFE&PID_4037&MI_00, USB\VID_CAFE&PID_4039&MI_00, USB\VID_CAFE&PID_403b&MI_00, USB\VID_CAFE&PID_403d&MI_00, USB\VID_CAFE&PID_403f&MI_00 + +;------------------------------------------------------------------------------ +; String Definitions +;------------------------------------------------------------------------------ +;Modify these strings to customize your device +;------------------------------------------------------------------------------ +[Strings] +MFGFILENAME="tinyusb_usbser" +DRIVERFILENAME ="usbser" +MFGNAME="tinyusb.org" +INSTDISK="tinyusb CDC Driver" +DESCRIPTION="tinyusb Serial" +SERVICE="USB RS-232 Emulation Driver" \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml new file mode 100644 index 000000000..db103d80e --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml @@ -0,0 +1,3 @@ +# Newt uses this file to determine the version of a checked out repo. +# This should always be 0.0.0 in the master branch. +repo.version: 0.0.0 diff --git a/examples/espidf-peripherals-usb/platformio.ini b/examples/espidf-peripherals-usb/platformio.ini index 8591d4b45..438ef31be 100644 --- a/examples/espidf-peripherals-usb/platformio.ini +++ b/examples/espidf-peripherals-usb/platformio.ini @@ -5,7 +5,7 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env] platform = espressif32 diff --git a/examples/espidf-peripherals-usb/sdkconfig.defaults b/examples/espidf-peripherals-usb/sdkconfig.defaults index 4d3be6399..afec5843f 100644 --- a/examples/espidf-peripherals-usb/sdkconfig.defaults +++ b/examples/espidf-peripherals-usb/sdkconfig.defaults @@ -1,6 +1 @@ -CONFIG_IDF_TARGET="esp32s2" -CONFIG_USB_ENABLED=y -CONFIG_USB_DESC_USE_ESPRESSIF_VID=n -CONFIG_USB_DESC_CUSTOM_VID=0x303A -CONFIG_USB_DESC_USE_DEFAULT_PID=n -CONFIG_USB_DESC_CUSTOM_PID=0x3000 +CONFIG_TINYUSB_CDC_ENABLED=y diff --git a/examples/espidf-peripherals-usb/src/CMakeLists.txt b/examples/espidf-peripherals-usb/src/CMakeLists.txt index 649d1f761..a3d8eb603 100644 --- a/examples/espidf-peripherals-usb/src/CMakeLists.txt +++ b/examples/espidf-peripherals-usb/src/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "tusb_sample_descriptor.c" - INCLUDE_DIRS . ${COMPONENT_DIR}) +idf_component_register(SRCS "tusb_serial_device_main.c" + INCLUDE_DIRS .) diff --git a/examples/espidf-peripherals-usb/src/Kconfig.projbuild b/examples/espidf-peripherals-usb/src/Kconfig.projbuild deleted file mode 100644 index 49a79fe59..000000000 --- a/examples/espidf-peripherals-usb/src/Kconfig.projbuild +++ /dev/null @@ -1,10 +0,0 @@ -menu "Example Configuration" - - config EXAMPLE_MANUAL_DESC - bool "Set up a USB descriptor manually in code" - default y - help - You can set up a descriptor using Menuconfig or independently of - your project configuration - manually in code - -endmenu diff --git a/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c b/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c deleted file mode 100644 index 2da369c2c..000000000 --- a/examples/espidf-peripherals-usb/src/tusb_sample_descriptor.c +++ /dev/null @@ -1,84 +0,0 @@ -/* USB Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "driver/gpio.h" -#include "sdkconfig.h" -#include "tinyusb.h" - -static const char *TAG = "example"; - -// USB Device Driver task -// This top level thread processes all usb events and invokes callbacks -static void usb_device_task(void *param) { - (void)param; - ESP_LOGI(TAG, "USB task started"); - while (1) { - tud_task(); // RTOS forever loop - } -} - -void app_main(void) { - - ESP_LOGI(TAG, "USB initialization"); - -#if CONFIG_EXAMPLE_MANUAL_DESC - // Setting of descriptor. You can use descriptor_tinyusb and - // descriptor_str_tinyusb as a reference - tusb_desc_device_t my_descriptor = { - .bLength = sizeof(my_descriptor), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, // USB version. 0x0200 means version 2.0 - .bDeviceClass = TUSB_CLASS_UNSPECIFIED, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = 0x303A, - .idProduct = 0x3000, - .bcdDevice = 0x0101, // Device FW version - - .iManufacturer = 0x01, // see string_descriptor[1] bellow - .iProduct = 0x02, // see string_descriptor[2] bellow - .iSerialNumber = 0x03, // see string_descriptor[3] bellow - - .bNumConfigurations = 0x01}; - - tusb_desc_strarray_device_t my_string_descriptor = { - // array of pointer to string descriptors - (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) - "I", // 1: Manufacturer - "My Custom Device", // 2: Product - "012-345", // 3: Serials, should use chip ID - }; - - tinyusb_config_t tusb_cfg = { - .descriptor = &my_descriptor, - .string_descriptor = my_string_descriptor, - .external_phy = false // In the most cases you need to use a `false` value - }; - -#else - - tinyusb_config_t tusb_cfg = { - .descriptor = NULL, - .string_descriptor = NULL, - .external_phy = false // In the most cases you need to use a `false` value - }; - -#endif - - ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg)); - ESP_LOGI(TAG, "USB initialization DONE"); - - // Create a task for tinyusb device stack: - xTaskCreate(usb_device_task, "usbd", 4096, NULL, 5, NULL); - return; -} diff --git a/examples/espidf-peripherals-usb/src/tusb_serial_device_main.c b/examples/espidf-peripherals-usb/src/tusb_serial_device_main.c new file mode 100644 index 000000000..0a2cc3a2c --- /dev/null +++ b/examples/espidf-peripherals-usb/src/tusb_serial_device_main.c @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "tinyusb.h" +#include "tusb_cdc_acm.h" +#include "sdkconfig.h" + +static const char *TAG = "example"; +static uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE + 1]; + +void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event) +{ + /* initialization */ + size_t rx_size = 0; + + /* read */ + esp_err_t ret = tinyusb_cdcacm_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size); + if (ret == ESP_OK) { + ESP_LOGI(TAG, "Data from channel %d:", itf); + ESP_LOG_BUFFER_HEXDUMP(TAG, buf, rx_size, ESP_LOG_INFO); + } else { + ESP_LOGE(TAG, "Read error"); + } + + /* write back */ + tinyusb_cdcacm_write_queue(itf, buf, rx_size); + tinyusb_cdcacm_write_flush(itf, 0); +} + +void tinyusb_cdc_line_state_changed_callback(int itf, cdcacm_event_t *event) +{ + int dtr = event->line_state_changed_data.dtr; + int rts = event->line_state_changed_data.rts; + ESP_LOGI(TAG, "Line state changed on channel %d: DTR:%d, RTS:%d", itf, dtr, rts); +} + +void app_main(void) +{ + ESP_LOGI(TAG, "USB initialization"); + const tinyusb_config_t tusb_cfg = { + .device_descriptor = NULL, + .string_descriptor = NULL, + .external_phy = false, + .configuration_descriptor = NULL, + }; + + ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg)); + + tinyusb_config_cdcacm_t acm_cfg = { + .usb_dev = TINYUSB_USBDEV_0, + .cdc_port = TINYUSB_CDC_ACM_0, + .rx_unread_buf_sz = 64, + .callback_rx = &tinyusb_cdc_rx_callback, // the first way to register a callback + .callback_rx_wanted_char = NULL, + .callback_line_state_changed = NULL, + .callback_line_coding_changed = NULL + }; + + ESP_ERROR_CHECK(tusb_cdc_acm_init(&acm_cfg)); + /* the second way to register a callback */ + ESP_ERROR_CHECK(tinyusb_cdcacm_register_callback( + TINYUSB_CDC_ACM_0, + CDC_EVENT_LINE_STATE_CHANGED, + &tinyusb_cdc_line_state_changed_callback)); + +#if (CONFIG_TINYUSB_CDC_COUNT > 1) + acm_cfg.cdc_port = TINYUSB_CDC_ACM_1; + ESP_ERROR_CHECK(tusb_cdc_acm_init(&acm_cfg)); + ESP_ERROR_CHECK(tinyusb_cdcacm_register_callback( + TINYUSB_CDC_ACM_1, + CDC_EVENT_LINE_STATE_CHANGED, + &tinyusb_cdc_line_state_changed_callback)); +#endif + + ESP_LOGI(TAG, "USB initialization DONE"); +} diff --git a/examples/espidf-storage-sdcard/.travis.yml b/examples/espidf-storage-sdcard/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/examples/espidf-storage-sdcard/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-storage-sdcard/README.md b/examples/espidf-storage-sdcard/README.md index e2f47657d..bc56cddc2 100644 --- a/examples/espidf-storage-sdcard/README.md +++ b/examples/espidf-storage-sdcard/README.md @@ -1,7 +1,7 @@ How to build PlatformIO based project ===================================== -1. [Install PlatformIO Core](http://docs.platformio.org/page/core.html) +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) 2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) 3. Extract ZIP archive 4. Run these commands: diff --git a/examples/espidf-storage-sdcard/platformio.ini b/examples/espidf-storage-sdcard/platformio.ini index 182e8e8f7..112293123 100644 --- a/examples/espidf-storage-sdcard/platformio.ini +++ b/examples/espidf-storage-sdcard/platformio.ini @@ -5,7 +5,7 @@ ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/page/projectconf.html [env] platform = espressif32 diff --git a/examples/espidf-storage-sdcard/src/CMakeLists.txt b/examples/espidf-storage-sdcard/src/CMakeLists.txt index 439aa9002..39630ccc5 100644 --- a/examples/espidf-storage-sdcard/src/CMakeLists.txt +++ b/examples/espidf-storage-sdcard/src/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRCS "sd_card_example_main.c" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS ".") diff --git a/examples/espidf-storage-sdcard/src/Kconfig.projbuild b/examples/espidf-storage-sdcard/src/Kconfig.projbuild new file mode 100644 index 000000000..2b2a81aff --- /dev/null +++ b/examples/espidf-storage-sdcard/src/Kconfig.projbuild @@ -0,0 +1,57 @@ +menu "SD/MMC Example Configuration" + + config EXAMPLE_FORMAT_IF_MOUNT_FAILED + bool "Format the card if mount failed" + default n + help + If this config item is set, format_if_mount_failed will be set to true and the card will be formatted if + the mount has failed. + + choice EXAMPLE_SDMMC_BUS_WIDTH + prompt "SD/MMC bus width" + default EXAMPLE_SDMMC_BUS_WIDTH_4 + help + Select the bus width of SD or MMC interface. + Note that even if 1 line mode is used, D3 pin of the SD card must have a pull-up resistor connected. + Otherwise the card may enter SPI mode, the only way to recover from which is to cycle power to the card. + + config EXAMPLE_SDMMC_BUS_WIDTH_4 + bool "4 lines (D0 - D3)" + + config EXAMPLE_SDMMC_BUS_WIDTH_1 + bool "1 line (D0)" + endchoice + + if SOC_SDMMC_USE_GPIO_MATRIX + + config EXAMPLE_PIN_CMD + int "CMD GPIO number" + default 35 if IDF_TARGET_ESP32S3 + + config EXAMPLE_PIN_CLK + int "CLK GPIO number" + default 36 if IDF_TARGET_ESP32S3 + + config EXAMPLE_PIN_D0 + int "D0 GPIO number" + default 37 if IDF_TARGET_ESP32S3 + + if EXAMPLE_SDMMC_BUS_WIDTH_4 + + config EXAMPLE_PIN_D1 + int "D1 GPIO number" + default 38 if IDF_TARGET_ESP32S3 + + config EXAMPLE_PIN_D2 + int "D2 GPIO number" + default 33 if IDF_TARGET_ESP32S3 + + config EXAMPLE_PIN_D3 + int "D3 GPIO number" + default 34 if IDF_TARGET_ESP32S3 + + endif # EXAMPLE_SDMMC_BUS_WIDTH_4 + + endif # SOC_SDMMC_USE_GPIO_MATRIX + +endmenu diff --git a/examples/espidf-storage-sdcard/src/sd_card_example_main.c b/examples/espidf-storage-sdcard/src/sd_card_example_main.c index e3ff6639e..9f7ef71c7 100644 --- a/examples/espidf-storage-sdcard/src/sd_card_example_main.c +++ b/examples/espidf-storage-sdcard/src/sd_card_example_main.c @@ -6,63 +6,24 @@ CONDITIONS OF ANY KIND, either express or implied. */ -#include +// This example uses SDMMC peripheral to communicate with SD card. + #include #include #include -#include "esp_err.h" -#include "esp_log.h" #include "esp_vfs_fat.h" -#include "driver/sdspi_host.h" -#include "driver/spi_common.h" #include "sdmmc_cmd.h" -#include "sdkconfig.h" - -#ifdef CONFIG_IDF_TARGET_ESP32 #include "driver/sdmmc_host.h" -#endif static const char *TAG = "example"; #define MOUNT_POINT "/sdcard" -// This example can use SDMMC and SPI peripherals to communicate with SD card. -// By default, SDMMC peripheral is used. -// To enable SPI mode, uncomment the following line: - -// #define USE_SPI_MODE - -// ESP32-S2 doesn't have an SD Host peripheral, always use SPI: -#ifdef CONFIG_IDF_TARGET_ESP32S2 -#ifndef USE_SPI_MODE -#define USE_SPI_MODE -#endif // USE_SPI_MODE -// on ESP32-S2, DMA channel must be the same as host id -#define SPI_DMA_CHAN host.slot -#endif //CONFIG_IDF_TARGET_ESP32S2 - -// DMA channel to be used by the SPI peripheral -#ifndef SPI_DMA_CHAN -#define SPI_DMA_CHAN 1 -#endif //SPI_DMA_CHAN - -// When testing SD and SPI modes, keep in mind that once the card has been -// initialized in SPI mode, it can not be reinitialized in SD mode without -// toggling power to the card. - -#ifdef USE_SPI_MODE -// Pin mapping when using SPI mode. -// With this mapping, SD card can be used both in SPI and 1-line SD mode. -// Note that a pull-up on CS line is required in SD mode. -#define PIN_NUM_MISO 2 -#define PIN_NUM_MOSI 15 -#define PIN_NUM_CLK 14 -#define PIN_NUM_CS 13 -#endif //USE_SPI_MODE void app_main(void) { esp_err_t ret; + // Options for mounting the filesystem. // If format_if_mount_failed is set to true, SD card will be partitioned and // formatted in case when mounting fails. @@ -75,7 +36,7 @@ void app_main(void) .max_files = 5, .allocation_unit_size = 16 * 1024 }; - sdmmc_card_t* card; + sdmmc_card_t *card; const char mount_point[] = MOUNT_POINT; ESP_LOGI(TAG, "Initializing SD card"); @@ -83,7 +44,7 @@ void app_main(void) // Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions. // Please check its source code and implement error recovery when developing // production applications. -#ifndef USE_SPI_MODE + ESP_LOGI(TAG, "Using SDMMC peripheral"); sdmmc_host_t host = SDMMC_HOST_DEFAULT(); @@ -91,64 +52,56 @@ void app_main(void) // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - // To use 1-line SD mode, uncomment the following line: - // slot_config.width = 1; - - // GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups. - // Internal pull-ups are not sufficient. However, enabling internal pull-ups - // does make a difference some boards, so we do that here. - gpio_set_pull_mode(15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes - gpio_set_pull_mode(2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes - gpio_set_pull_mode(4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only - gpio_set_pull_mode(12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only - gpio_set_pull_mode(13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes - - ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card); + // Set bus width to use: +#ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 + slot_config.width = 4; #else - ESP_LOGI(TAG, "Using SPI peripheral"); - - sdmmc_host_t host = SDSPI_HOST_DEFAULT(); - spi_bus_config_t bus_cfg = { - .mosi_io_num = PIN_NUM_MOSI, - .miso_io_num = PIN_NUM_MISO, - .sclk_io_num = PIN_NUM_CLK, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = 4000, - }; - ret = spi_bus_initialize(host.slot, &bus_cfg, SPI_DMA_CHAN); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize bus."); - return; - } - - // This initializes the slot without card detect (CD) and write protect (WP) signals. - // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals. - sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT(); - slot_config.gpio_cs = PIN_NUM_CS; - slot_config.host_id = host.slot; + slot_config.width = 1; +#endif - ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card); -#endif //USE_SPI_MODE + // On chips where the GPIOs used for SD card can be configured, set them in + // the slot_config structure: +#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX + slot_config.clk = CONFIG_EXAMPLE_PIN_CLK; + slot_config.cmd = CONFIG_EXAMPLE_PIN_CMD; + slot_config.d0 = CONFIG_EXAMPLE_PIN_D0; +#ifdef CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 + slot_config.d1 = CONFIG_EXAMPLE_PIN_D1; + slot_config.d2 = CONFIG_EXAMPLE_PIN_D2; + slot_config.d3 = CONFIG_EXAMPLE_PIN_D3; +#endif // CONFIG_EXAMPLE_SDMMC_BUS_WIDTH_4 +#endif // CONFIG_SOC_SDMMC_USE_GPIO_MATRIX + + // Enable internal pullups on enabled pins. The internal pullups + // are insufficient however, please make sure 10k external pullups are + // connected on the bus. This is for debug / example purpose only. + slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP; + + ESP_LOGI(TAG, "Mounting filesystem"); + ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card); if (ret != ESP_OK) { if (ret == ESP_FAIL) { ESP_LOGE(TAG, "Failed to mount filesystem. " - "If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option."); + "If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option."); } else { ESP_LOGE(TAG, "Failed to initialize the card (%s). " - "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); + "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); } return; } + ESP_LOGI(TAG, "Filesystem mounted"); // Card has been initialized, print its properties sdmmc_card_print_info(stdout, card); - // Use POSIX and C standard library functions to work with files. + // Use POSIX and C standard library functions to work with files: + // First create a file. - ESP_LOGI(TAG, "Opening file"); - FILE* f = fopen(MOUNT_POINT"/hello.txt", "w"); + const char *file_hello = MOUNT_POINT"/hello.txt"; + + ESP_LOGI(TAG, "Opening file %s", file_hello); + FILE *f = fopen(file_hello, "w"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file for writing"); return; @@ -157,42 +110,43 @@ void app_main(void) fclose(f); ESP_LOGI(TAG, "File written"); + const char *file_foo = MOUNT_POINT"/foo.txt"; + // Check if destination file exists before renaming struct stat st; - if (stat(MOUNT_POINT"/foo.txt", &st) == 0) { + if (stat(file_foo, &st) == 0) { // Delete it if it exists - unlink(MOUNT_POINT"/foo.txt"); + unlink(file_foo); } // Rename original file - ESP_LOGI(TAG, "Renaming file"); - if (rename(MOUNT_POINT"/hello.txt", MOUNT_POINT"/foo.txt") != 0) { + ESP_LOGI(TAG, "Renaming file %s to %s", file_hello, file_foo); + if (rename(file_hello, file_foo) != 0) { ESP_LOGE(TAG, "Rename failed"); return; } // Open renamed file for reading - ESP_LOGI(TAG, "Reading file"); - f = fopen(MOUNT_POINT"/foo.txt", "r"); + ESP_LOGI(TAG, "Reading file %s", file_foo); + f = fopen(file_foo, "r"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file for reading"); return; } + + // Read a line from file char line[64]; fgets(line, sizeof(line), f); fclose(f); - // strip newline - char* pos = strchr(line, '\n'); + + // Strip newline + char *pos = strchr(line, '\n'); if (pos) { *pos = '\0'; } ESP_LOGI(TAG, "Read from file: '%s'", line); - // All done, unmount partition and disable SDMMC or SPI peripheral + // All done, unmount partition and disable SDMMC peripheral esp_vfs_fat_sdcard_unmount(mount_point, card); ESP_LOGI(TAG, "Card unmounted"); -#ifdef USE_SPI_MODE - //deinitialize the bus after all devices are removed - spi_bus_free(host.slot); -#endif } diff --git a/examples/espidf-storage-spiffs/.gitignore b/examples/espidf-storage-spiffs/.gitignore new file mode 100644 index 000000000..03f4a3c19 --- /dev/null +++ b/examples/espidf-storage-spiffs/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/examples/espidf-storage-spiffs/CMakeLists.txt b/examples/espidf-storage-spiffs/CMakeLists.txt new file mode 100644 index 000000000..1894b31ca --- /dev/null +++ b/examples/espidf-storage-spiffs/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(spiffs) diff --git a/examples/espidf-storage-spiffs/README.md b/examples/espidf-storage-spiffs/README.md new file mode 100644 index 000000000..214f9ba67 --- /dev/null +++ b/examples/espidf-storage-spiffs/README.md @@ -0,0 +1,24 @@ +How to build PlatformIO based project +===================================== + +1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) +2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) +3. Extract ZIP archive +4. Run these commands: + +```shell +# Change directory to example +$ cd platform-espressif32/examples/espidf-storage-spiffs + +# Build project +$ pio run + +# Upload firmware +$ pio run --target upload + +# Upload SPIFFS image +$ pio run --target uploadfs + +# Clean build files +$ pio run --target clean +``` diff --git a/examples/espidf-storage-spiffs/data/hello.txt b/examples/espidf-storage-spiffs/data/hello.txt new file mode 100644 index 000000000..5a8367719 --- /dev/null +++ b/examples/espidf-storage-spiffs/data/hello.txt @@ -0,0 +1 @@ +Hello World from SPIFFS. diff --git a/examples/espidf-storage-spiffs/include/README b/examples/espidf-storage-spiffs/include/README new file mode 100644 index 000000000..194dcd432 --- /dev/null +++ b/examples/espidf-storage-spiffs/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-storage-spiffs/lib/README b/examples/espidf-storage-spiffs/lib/README new file mode 100644 index 000000000..6debab1e8 --- /dev/null +++ b/examples/espidf-storage-spiffs/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-storage-spiffs/partitions_example.csv b/examples/espidf-storage-spiffs/partitions_example.csv new file mode 100644 index 000000000..92db904e0 --- /dev/null +++ b/examples/espidf-storage-spiffs/partitions_example.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +spiffs, data, spiffs, , 0xF0000, diff --git a/examples/espidf-storage-spiffs/platformio.ini b/examples/espidf-storage-spiffs/platformio.ini new file mode 100644 index 000000000..9185e89ba --- /dev/null +++ b/examples/espidf-storage-spiffs/platformio.ini @@ -0,0 +1,15 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +framework = espidf +board = esp32dev +monitor_speed = 115200 +board_build.partitions = partitions_example.csv diff --git a/examples/espidf-storage-spiffs/sdkconfig.defaults b/examples/espidf-storage-spiffs/sdkconfig.defaults new file mode 100644 index 000000000..b9bb0c0a5 --- /dev/null +++ b/examples/espidf-storage-spiffs/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv" diff --git a/examples/espidf-storage-spiffs/src/CMakeLists.txt b/examples/espidf-storage-spiffs/src/CMakeLists.txt new file mode 100644 index 000000000..c480915ab --- /dev/null +++ b/examples/espidf-storage-spiffs/src/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "spiffs_example_main.c" + INCLUDE_DIRS ".") diff --git a/examples/espidf-storage-spiffs/src/Kconfig.projbuild b/examples/espidf-storage-spiffs/src/Kconfig.projbuild new file mode 100644 index 000000000..eadd67909 --- /dev/null +++ b/examples/espidf-storage-spiffs/src/Kconfig.projbuild @@ -0,0 +1,9 @@ +menu "SPIFFS Example menu" + + config EXAMPLE_SPIFFS_CHECK_ON_START + bool "Run SPIFFS_check on every start-up" + default y + help + If this config item is set, esp_spiffs_check() will be run on every start-up. + Slow on large flash sizes. +endmenu diff --git a/examples/espidf-storage-spiffs/src/spiffs_example_main.c b/examples/espidf-storage-spiffs/src/spiffs_example_main.c new file mode 100644 index 000000000..32cc17686 --- /dev/null +++ b/examples/espidf-storage-spiffs/src/spiffs_example_main.c @@ -0,0 +1,127 @@ +/* SPIFFS filesystem example. + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include +#include "esp_err.h" +#include "esp_log.h" +#include "esp_spiffs.h" + +static const char *TAG = "example"; + +void app_main(void) +{ + ESP_LOGI(TAG, "Initializing SPIFFS"); + + esp_vfs_spiffs_conf_t conf = { + .base_path = "/spiffs", + .partition_label = NULL, + .max_files = 5, + .format_if_mount_failed = true + }; + + // Use settings defined above to initialize and mount SPIFFS filesystem. + // Note: esp_vfs_spiffs_register is an all-in-one convenience function. + esp_err_t ret = esp_vfs_spiffs_register(&conf); + + if (ret != ESP_OK) { + if (ret == ESP_FAIL) { + ESP_LOGE(TAG, "Failed to mount or format filesystem"); + } else if (ret == ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Failed to find SPIFFS partition"); + } else { + ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); + } + return; + } + +#ifdef CONFIG_EXAMPLE_SPIFFS_CHECK_ON_START + ESP_LOGI(TAG, "Performing SPIFFS_check()."); + ret = esp_spiffs_check(conf.partition_label); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "SPIFFS_check() failed (%s)", esp_err_to_name(ret)); + return; + } else { + ESP_LOGI(TAG, "SPIFFS_check() successful"); + } +#endif + + size_t total = 0, used = 0; + ret = esp_spiffs_info(conf.partition_label, &total, &used); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s). Formatting...", esp_err_to_name(ret)); + esp_spiffs_format(conf.partition_label); + return; + } else { + ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); + } + +# + // Check consistency of reported partiton size info. + if (used > total) { + ESP_LOGW(TAG, "Number of used bytes cannot be larger than total. Performing SPIFFS_check()."); + ret = esp_spiffs_check(conf.partition_label); + // Could be also used to mend broken files, to clean unreferenced pages, etc. + // More info at https://github.com/pellepl/spiffs/wiki/FAQ#powerlosses-contd-when-should-i-run-spiffs_check + if (ret != ESP_OK) { + ESP_LOGE(TAG, "SPIFFS_check() failed (%s)", esp_err_to_name(ret)); + return; + } else { + ESP_LOGI(TAG, "SPIFFS_check() successful"); + } + } + + // Use POSIX and C standard library functions to work with files. + // First create a file. + ESP_LOGI(TAG, "Opening file"); + FILE* f = fopen("/spiffs/hello.txt", "w"); + if (f == NULL) { + ESP_LOGE(TAG, "Failed to open file for writing"); + return; + } + fprintf(f, "Hello World!\n"); + fclose(f); + ESP_LOGI(TAG, "File written"); + + // Check if destination file exists before renaming + struct stat st; + if (stat("/spiffs/foo.txt", &st) == 0) { + // Delete it if it exists + unlink("/spiffs/foo.txt"); + } + + // Rename original file + ESP_LOGI(TAG, "Renaming file"); + if (rename("/spiffs/hello.txt", "/spiffs/foo.txt") != 0) { + ESP_LOGE(TAG, "Rename failed"); + return; + } + + // Open renamed file for reading + ESP_LOGI(TAG, "Reading file"); + f = fopen("/spiffs/foo.txt", "r"); + if (f == NULL) { + ESP_LOGE(TAG, "Failed to open file for reading"); + return; + } + char line[64]; + fgets(line, sizeof(line), f); + fclose(f); + // strip newline + char* pos = strchr(line, '\n'); + if (pos) { + *pos = '\0'; + } + ESP_LOGI(TAG, "Read from file: '%s'", line); + + // All done, unmount partition and disable SPIFFS + esp_vfs_spiffs_unregister(conf.partition_label); + ESP_LOGI(TAG, "SPIFFS unmounted"); +} diff --git a/examples/espidf-storage-spiffs/test/README b/examples/espidf-storage-spiffs/test/README new file mode 100644 index 000000000..df5066e64 --- /dev/null +++ b/examples/espidf-storage-spiffs/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c b/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c index de9c20e3b..ba5c5845f 100644 --- a/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c +++ b/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c @@ -1,4 +1,4 @@ -/* ULP riscv DS18B20 1wire temperature sensor example +/* ULP riscv example This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -12,14 +12,19 @@ #include "soc/rtc_cntl_reg.h" #include "soc/sens_reg.h" #include "soc/rtc_periph.h" +#include "hal/rtc_io_ll.h" #include "driver/gpio.h" #include "driver/rtc_io.h" -#include "esp32s2/ulp.h" -#include "esp32s2/ulp_riscv.h" +#include "ulp_riscv.h" #include "ulp_main.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +/* We alternate between start conversion and read result every other ULP wakeup, + Conversion time is 750 ms for 12 bit resolution +*/ +#define WAKEUP_PERIOD_US (750000) + extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end"); @@ -27,28 +32,18 @@ static void init_ulp_program(void); void app_main(void) { - /* Initialize selected GPIO as RTC IO, enable input, disable pullup and pulldown */ - rtc_gpio_init(GPIO_NUM_0); - rtc_gpio_set_direction(GPIO_NUM_0, RTC_GPIO_MODE_INPUT_ONLY); - rtc_gpio_pulldown_dis(GPIO_NUM_0); - rtc_gpio_pullup_dis(GPIO_NUM_0); - rtc_gpio_hold_en(GPIO_NUM_0); - esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); /* not a wakeup from ULP, load the firmware */ if (cause != ESP_SLEEP_WAKEUP_ULP) { - printf("Not a ULP-RISC-V wakeup, initializing it! \n"); + printf("Not a ULP-RISC-V wakeup (cause = %d), initializing it! \n", cause); init_ulp_program(); } - /* ULP Risc-V read and detected a change in GPIO_0, prints */ + /* ULP Risc-V read and detected a temperature above the limit */ if (cause == ESP_SLEEP_WAKEUP_ULP) { - printf("ULP-RISC-V woke up the main CPU! \n"); - printf("ULP-RISC-V read changes in GPIO_0 current is: %s \n", - (bool)(ulp_gpio_level_previous == 0) ? "Low" : "High" ); - + printf("ULP-RISC-V woke up the main CPU, temperature is above set limit! \n"); + printf("ULP-RISC-V read temperature is %f\n", ulp_temp_reg_val / 16.0); } - /* Go back to sleep, only the ULP Risc-V will run */ printf("Entering in deep sleep\n\n"); @@ -56,6 +51,7 @@ void app_main(void) vTaskDelay(100); ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup()); + esp_deep_sleep_start(); } @@ -65,9 +61,9 @@ static void init_ulp_program(void) ESP_ERROR_CHECK(err); /* The first argument is the period index, which is not used by the ULP-RISC-V timer - * The second argument is the period in microseconds, which gives a wakeup time period of: 20ms + * The second argument is the period in microseconds, which gives a wakeup time period of: 750ms */ - ulp_set_wakeup_period(0, 20000); + ulp_set_wakeup_period(0, WAKEUP_PERIOD_US); /* Start the program */ err = ulp_riscv_run(); diff --git a/examples/espidf-ulp-riscv/sdkconfig.defaults b/examples/espidf-ulp-riscv/sdkconfig.defaults index 302c87aa9..a28f71162 100644 --- a/examples/espidf-ulp-riscv/sdkconfig.defaults +++ b/examples/espidf-ulp-riscv/sdkconfig.defaults @@ -1,3 +1,7 @@ +# Enable ULP +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_RISCV=y +CONFIG_ULP_COPROC_RESERVE_MEM=4096 # Set log level to Warning to produce clean output CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y CONFIG_BOOTLOADER_LOG_LEVEL=2 diff --git a/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 b/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 deleted file mode 100644 index f86c0eff1..000000000 --- a/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 +++ /dev/null @@ -1,4 +0,0 @@ -# Enable ULP -CONFIG_ESP32S2_ULP_COPROC_ENABLED=y -CONFIG_ESP32S2_ULP_COPROC_RISCV=y -CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=4096 diff --git a/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 b/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 deleted file mode 100644 index 165e30dd5..000000000 --- a/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 +++ /dev/null @@ -1,4 +0,0 @@ -# Enable ULP -CONFIG_ESP32S3_ULP_COPROC_ENABLED=y -CONFIG_ESP32S3_ULP_COPROC_RISCV=y -CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=4096 diff --git a/examples/espidf-ulp-riscv/ulp/main.c b/examples/espidf-ulp-riscv/ulp/main.c index 2f24ba377..dfabfd192 100644 --- a/examples/espidf-ulp-riscv/ulp/main.c +++ b/examples/espidf-ulp-riscv/ulp/main.c @@ -12,30 +12,145 @@ #include #include #include -#include "ulp_riscv/ulp_riscv.h" -#include "ulp_riscv/ulp_riscv_utils.h" -#include "ulp_riscv/ulp_riscv_gpio.h" +#include "ulp_riscv.h" +#include "ulp_riscv_utils.h" +#include "ulp_riscv_gpio.h" -static bool gpio_level = false; +#define EXAMPLE_1WIRE_GPIO GPIO_NUM_4 -/* this variable will be exported as a public symbol, visible from main CPU: */ -bool gpio_level_previous = false; +#define WAKEUP_TEMP_C 32.5 +#define TEMP_ALARM_LIMIT ( (int)(WAKEUP_TEMP_C*16) ) + +typedef enum { + SENSOR_CONVERSION_INIT, + SENSOR_CONVERSION_READ, +} sensor_state_t; + +sensor_state_t state = SENSOR_CONVERSION_INIT; +int32_t temp_reg_val = INT32_MIN; + +static void ds18b20_write_bit(bool bit) +{ + ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0); + if (bit) { + /* Must pull high within 15 us, without delay this takes 5 us */ + ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1); + } + + /* Write slot duration at least 60 us */ + ulp_riscv_delay_cycles(60 * ULP_RISCV_CYCLES_PER_US); + ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1); +} + +static bool ds18b20_read_bit(void) +{ + bool bit; + + /* Pull low minimum 1 us */ + ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0); + ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1); + + /* Must sample within 15 us of the failing edge */ + ulp_riscv_delay_cycles(5 * ULP_RISCV_CYCLES_PER_US); + bit = ulp_riscv_gpio_get_level(EXAMPLE_1WIRE_GPIO); + + /* Read slot duration at least 60 us */ + ulp_riscv_delay_cycles(55 * ULP_RISCV_CYCLES_PER_US); + + return bit; +} + +static void ds18b20_write_byte(uint8_t data) +{ + for (int i = 0; i < 8; i++) { + ds18b20_write_bit((data >> i) & 0x1); + } +} + +static uint8_t ds18b20_read_byte(void) +{ + uint8_t data = 0; + for (int i = 0; i < 8; i++) { + data |= ds18b20_read_bit() << i; + } + return data; +} + +bool ds18b20_reset_pulse(void) +{ + bool presence_pulse; + /* min 480 us reset pulse + 480 us reply time is specified by datasheet */ + ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0); + ulp_riscv_delay_cycles(480 * ULP_RISCV_CYCLES_PER_US); + + ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1); + + /* Wait for ds18b20 to pull low before sampling */ + ulp_riscv_delay_cycles(60 * ULP_RISCV_CYCLES_PER_US); + presence_pulse = ulp_riscv_gpio_get_level(EXAMPLE_1WIRE_GPIO) == 0; + + ulp_riscv_delay_cycles(420 * ULP_RISCV_CYCLES_PER_US); + + return presence_pulse; +} int main (void) { - gpio_level = (bool)ulp_riscv_gpio_get_level(GPIO_NUM_0); - gpio_level_previous = gpio_level; + uint8_t temp_high_byte; + uint8_t temp_low_byte; - while(1) { - gpio_level = (bool)ulp_riscv_gpio_get_level(GPIO_NUM_0); + /* Setup GPIO used for 1wire */ + ulp_riscv_gpio_init(EXAMPLE_1WIRE_GPIO); + ulp_riscv_gpio_input_enable(EXAMPLE_1WIRE_GPIO); + ulp_riscv_gpio_output_enable(EXAMPLE_1WIRE_GPIO); + ulp_riscv_gpio_set_output_mode(EXAMPLE_1WIRE_GPIO, RTCIO_MODE_OUTPUT_OD); + ulp_riscv_gpio_pullup(EXAMPLE_1WIRE_GPIO); + ulp_riscv_gpio_pulldown_disable(EXAMPLE_1WIRE_GPIO); - /* Wakes up the main CPU if pin changed its state */ - if(gpio_level != gpio_level_previous) { - gpio_level_previous = gpio_level; - ulp_riscv_wakeup_main_processor(); + + switch (state) { + case SENSOR_CONVERSION_INIT: + if (!ds18b20_reset_pulse()) { + temp_reg_val = INT32_MIN; break; } + /* Start conversion */ + ds18b20_write_byte(0xCC); + ds18b20_write_byte(0x44); + + /* shutdown and wait for next period (750ms) where the data is ready for reading */ + state = SENSOR_CONVERSION_READ; + break; + + case SENSOR_CONVERSION_READ: + if (!ds18b20_reset_pulse()) { + temp_reg_val = INT32_MIN; + state = SENSOR_CONVERSION_INIT; + break; + } + + /* Read scratchpad */ + ds18b20_write_byte(0xCC); + ds18b20_write_byte(0xBE); + + temp_low_byte = ds18b20_read_byte(); + temp_high_byte = ds18b20_read_byte(); + + temp_reg_val = temp_high_byte << 8; + temp_reg_val |= temp_low_byte; + state = SENSOR_CONVERSION_INIT; + + /* Wakes up the main CPU if the temperature exceeds the limit */ + if (temp_reg_val > TEMP_ALARM_LIMIT) { + ulp_riscv_wakeup_main_processor(); + } + + break; } - /* ulp_riscv_shutdown() is called automatically when main exits */ + + /* ulp_riscv_halt() is called automatically when main exits, + main will be executed again at the next timeout period, + according to ulp_set_wakeup_period() + */ return 0; } diff --git a/examples/espidf-ulp/main/CMakeLists.txt b/examples/espidf-ulp/main/CMakeLists.txt index a79852fbe..51dd8d369 100644 --- a/examples/espidf-ulp/main/CMakeLists.txt +++ b/examples/espidf-ulp/main/CMakeLists.txt @@ -1,6 +1,6 @@ idf_component_register(SRCS "ulp_example_main.c" INCLUDE_DIRS "" - REQUIRES soc nvs_flash ulp) + REQUIRES driver soc nvs_flash ulp) # # ULP support additions to component CMakeLists.txt. # diff --git a/examples/espidf-ulp/main/ulp_example_main.c b/examples/espidf-ulp/main/ulp_example_main.c index b7593bc4d..1607e7b07 100644 --- a/examples/espidf-ulp/main/ulp_example_main.c +++ b/examples/espidf-ulp/main/ulp_example_main.c @@ -8,6 +8,7 @@ */ #include +#include #include "esp_sleep.h" #include "nvs.h" #include "nvs_flash.h" @@ -16,15 +17,7 @@ #include "soc/rtc_periph.h" #include "driver/gpio.h" #include "driver/rtc_io.h" - -#if CONFIG_IDF_TARGET_ESP32 -#include "esp32/ulp.h" -#elif CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/ulp.h" -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/ulp.h" -#endif - +#include "ulp.h" #include "ulp_main.h" extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); @@ -36,7 +29,6 @@ static void update_pulse_count(void); void app_main(void) { esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); - printf("cause %d\n", cause); if (cause != ESP_SLEEP_WAKEUP_ULP) { printf("Not ULP wakeup, initializing ULP\n"); init_ulp_program(); @@ -115,18 +107,18 @@ static void update_pulse_count(void) uint32_t pulse_count = 0; esp_err_t err = nvs_get_u32(handle, count_key, &pulse_count); assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND); - printf("Read pulse count from NVS: %5d\n", pulse_count); + printf("Read pulse count from NVS: %5"PRIu32"\n", pulse_count); /* ULP program counts signal edges, convert that to the number of pulses */ uint32_t pulse_count_from_ulp = (ulp_edge_count & UINT16_MAX) / 2; /* In case of an odd number of edges, keep one until next time */ ulp_edge_count = ulp_edge_count % 2; - printf("Pulse count from ULP: %5d\n", pulse_count_from_ulp); + printf("Pulse count from ULP: %5"PRIu32"\n", pulse_count_from_ulp); /* Save the new pulse count to NVS */ pulse_count += pulse_count_from_ulp; ESP_ERROR_CHECK(nvs_set_u32(handle, count_key, pulse_count)); ESP_ERROR_CHECK(nvs_commit(handle)); nvs_close(handle); - printf("Wrote updated pulse count to NVS: %5d\n", pulse_count); + printf("Wrote updated pulse count to NVS: %5"PRIu32"\n", pulse_count); } diff --git a/examples/espidf-ulp/sdkconfig.defaults b/examples/espidf-ulp/sdkconfig.defaults index c7e68b3c8..1dffd2c78 100644 --- a/examples/espidf-ulp/sdkconfig.defaults +++ b/examples/espidf-ulp/sdkconfig.defaults @@ -1,3 +1,7 @@ +# Enable ULP +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_TYPE_FSM=y +CONFIG_ULP_COPROC_RESERVE_MEM=1024 # Set log level to Warning to produce clean output CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y CONFIG_BOOTLOADER_LOG_LEVEL=2 diff --git a/platform.json b/platform.json index 5bb7f82df..a11cb6cb6 100644 --- a/platform.json +++ b/platform.json @@ -12,13 +12,13 @@ "RISC-V" ], "engines": { - "platformio": ">=6.1.0" + "platformio": ">=6.1.5" }, "repository": { "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2022.12.2", + "version": "2023.01.0", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -53,32 +53,37 @@ "framework-espidf": { "type": "framework", "optional": true, - "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20221227/esp-idf-v4.4.3.zip" + "owner": "platformio", + "version": "~3.50000.0", + "optionalVersions": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20221227/esp-idf-v4.4.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch5" + "version": "8.4.0+2021r2-patch5", + "optionalVersions": ["11.2.0+2022r1"] }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch5" + "version": "8.4.0+2021r2-patch5", + "optionalVersions": ["11.2.0+2022r1"] }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch5" + "version": "8.4.0+2021r2-patch5", + "optionalVersions": ["11.2.0+2022r1"] }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch5" + "version": "8.4.0+2021r2-patch5", + "optionalVersions": ["11.2.0+2022r1"] }, "toolchain-esp32ulp": { "type": "toolchain", diff --git a/platform.py b/platform.py index 3226e326b..a47d3e1b5 100644 --- a/platform.py +++ b/platform.py @@ -66,6 +66,19 @@ def configure_default_packages(self, variables, targets): elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: self.packages[p]["optional"] = False + if "arduino" in frameworks: + # Downgrade the IDF version for mixed Arduino+IDF projects + self.packages["framework-espidf"]["version"] = "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20221227/esp-idf-v4.4.3.zip" + else: + # Use the latest toolchains available for IDF v5.0 + for target in ( + "xtensa-esp32", + "xtensa-esp32s2", + "xtensa-esp32s3", + "riscv32-esp" + ): + self.packages["toolchain-%s" % target]["version"] = "11.2.0+2022r1" + for available_mcu in ("esp32", "esp32s2", "esp32s3"): if available_mcu == mcu: self.packages["toolchain-xtensa-%s" % mcu]["optional"] = False From 160b39516cff775e883e8953327127d482b5c587 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 7 Jan 2023 16:21:58 +0100 Subject: [PATCH 257/666] disable-pip-version-check --- builder/frameworks/arduino.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index ebbc269b5..3690ecb22 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -57,7 +57,14 @@ def _get_installed_pip_packages(): result = {} packages = {} pip_output = subprocess.check_output( - [env.subst("$PYTHONEXE"), "-m", "pip", "list", "--format=json"] + [ + env.subst("$PYTHONEXE"), + "-m", + "pip", + "list", + "--format=json", + "--disable-pip-version-check", + ] ) try: packages = json.loads(pip_output) From a54fad92575228067701c6f96c2730df7bb49360 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 8 Jan 2023 14:59:09 +0100 Subject: [PATCH 258/666] Platform 2022.12.2 --- boards/bpi_leaf_s3.json | 48 ++++++++++++++++++++ boards/cytron_maker_feather_aiot_s3.json | 56 ++++++++++++++++++++++++ boards/deneyapkart1Av2.json | 46 +++++++++++++++++++ boards/deneyapmini.json | 7 ++- boards/deneyapminiv2.json | 48 ++++++++++++++++++++ boards/esp32-c3-m1i-kit.json | 37 ++++++++++++++++ boards/redpill_esp32s3.json | 55 +++++++++++++++++++++++ builder/frameworks/arduino.py | 9 +++- builder/frameworks/espidf.py | 11 ++++- builder/frameworks/ulp.py | 6 +-- builder/main.py | 2 +- platform.json | 6 +-- 12 files changed, 318 insertions(+), 13 deletions(-) create mode 100644 boards/bpi_leaf_s3.json create mode 100644 boards/cytron_maker_feather_aiot_s3.json create mode 100644 boards/deneyapkart1Av2.json create mode 100644 boards/deneyapminiv2.json create mode 100644 boards/esp32-c3-m1i-kit.json create mode 100644 boards/redpill_esp32s3.json diff --git a/boards/bpi_leaf_s3.json b/boards/bpi_leaf_s3.json new file mode 100644 index 000000000..c1d8a154c --- /dev/null +++ b/boards/bpi_leaf_s3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_BPI_LEAF_S3", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80DF" + ] + ], + "mcu": "esp32s3", + "variant": "bpi_leaf_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "BPI-Leaf-S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.banana-pi.org/BPI-Leaf-S3", + "vendor": "BPI Tech" +} diff --git a/boards/cytron_maker_feather_aiot_s3.json b/boards/cytron_maker_feather_aiot_s3.json new file mode 100644 index 000000000..4b7a2704c --- /dev/null +++ b/boards/cytron_maker_feather_aiot_s3.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "partitions-8MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_CYTRON_MAKER_FEATHER_AIOT_S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80F8" + ] + ], + "mcu": "esp32s3", + "variant": "cytron_maker_feather_aiot_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Cytron Maker Feather AIoT S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/cytron_maker_feather_aiot_s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://sg.cytron.io/c-development-tools/c-maker-series/p-v-maker-feather-aiot-s3-simplifying-aiot-with-esp32", + "vendor": "Cytron Technologies" +} diff --git a/boards/deneyapkart1Av2.json b/boards/deneyapkart1Av2.json new file mode 100644 index 000000000..b287551aa --- /dev/null +++ b/boards/deneyapkart1Av2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYDK1Av2", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8147" + ] + ], + "mcu": "esp32s3", + "variant": "deneyapkart1Av2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart 1A v2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.banana-pi.org/BPI-Leaf-S3", + "vendor": "Deneyap" +} diff --git a/boards/deneyapmini.json b/boards/deneyapmini.json index 02509684b..046fcba0b 100644 --- a/boards/deneyapmini.json +++ b/boards/deneyapmini.json @@ -4,14 +4,17 @@ "ldscript": "esp32s2_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_DYM", + "extra_flags": [ + "-DARDUINO_DYM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "qio", "hwids": [ [ "0x303A", - "0x0002" + "0x8141" ] ], "mcu": "esp32s2", diff --git a/boards/deneyapminiv2.json b/boards/deneyapminiv2.json new file mode 100644 index 000000000..b0c6cfdeb --- /dev/null +++ b/boards/deneyapminiv2.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_DYMv2", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8144" + ] + ], + "mcu": "esp32s2", + "variant": "deneyapminiv2" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Mini v2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://deneyapkart.org/magaza/urun-deneyap-kart-mini.html", + "vendor": "Deneyap" +} diff --git a/boards/esp32-c3-m1i-kit.json b/boards/esp32-c3-m1i-kit.json new file mode 100644 index 000000000..8e7d7cb08 --- /dev/null +++ b/boards/esp32-c3-m1i-kit.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": [ + "-DARDUINO_ESP32C3_M1_I_KIT", + "-DARDUINO_USB_MODE=1" + ], + "mcu": "esp32c3", + "variant": "esp_c3_m1_i_kit" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Ai-Thinker ESP-C3-M1-I-Kit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.ai-thinker.com/en/esp32c3", + "vendor": "Ai-Thinker" +} diff --git a/boards/redpill_esp32s3.json b/boards/redpill_esp32s3.json new file mode 100644 index 000000000..8dff2ff49 --- /dev/null +++ b/boards/redpill_esp32s3.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_REDPILL_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80F8" + ] + ], + "mcu": "esp32s3", + "variant": "redpill_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Munich Labs RedPill ESP32-S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/redpill_esp32s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://munich-labs.com/index.php/redpill-esp32-s3/", + "vendor": "Munich Labs" +} diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index ebbc269b5..3690ecb22 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -57,7 +57,14 @@ def _get_installed_pip_packages(): result = {} packages = {} pip_output = subprocess.check_output( - [env.subst("$PYTHONEXE"), "-m", "pip", "list", "--format=json"] + [ + env.subst("$PYTHONEXE"), + "-m", + "pip", + "list", + "--format=json", + "--disable-pip-version-check", + ] ) try: packages = json.loads(pip_output) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 9477160cd..c75d96c69 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -222,7 +222,7 @@ def populate_idf_env_vars(idf_env): os.path.dirname(env.subst("$PYTHONEXE")), ] - if mcu not in ("esp32c3"): + if mcu != "esp32c3": additional_packages.append( os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), ) @@ -1028,7 +1028,14 @@ def _get_installed_pip_packages(): result = {} packages = {} pip_output = subprocess.check_output( - [env.subst("$PYTHONEXE"), "-m", "pip", "list", "--format=json"] + [ + env.subst("$PYTHONEXE"), + "-m", + "pip", + "list", + "--format=json", + "--disable-pip-version-check", + ] ) try: packages = json.loads(pip_output) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index c99dceebf..c66d1baa6 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -36,9 +36,7 @@ def prepare_ulp_env_vars(env): additional_packages = [ os.path.join( - platform.get_package_dir( - "toolchain-xtensa-%s" % (idf_variant) - ), + platform.get_package_dir("toolchain-xtensa-%s" % idf_variant), "bin", ), os.path.join( @@ -99,7 +97,7 @@ def generate_ulp_config(target_config): "-DULP_APP_NAME=ulp_main", "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), '-DCOMPONENT_INCLUDES="%s"' % ";".join(get_component_includes(target_config)), - "-DIDF_TARGET=" + idf_variant, + "-DIDF_TARGET=%s" % idf_variant, "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), "-DPYTHON=" + env.subst("$PYTHONEXE"), diff --git a/builder/main.py b/builder/main.py index 2265e7018..36354b6e9 100644 --- a/builder/main.py +++ b/builder/main.py @@ -273,7 +273,7 @@ def __fetch_fs_size(target, source, env): '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", "--dont-append-digest", - "--flash_mode", "$BOARD_FLASH_MODE", + "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" diff --git a/platform.json b/platform.json index dd013abc4..5bb7f82df 100644 --- a/platform.json +++ b/platform.json @@ -83,13 +83,13 @@ "toolchain-esp32ulp": { "type": "toolchain", "optional": true, - "owner": "espressif", - "version": "~2" + "owner": "platformio", + "version": "~1.23500.0" }, "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4.1/esptool-4.4.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4.2/esptool-4.4.2.zip" }, "tool-openocd-esp32": { "type": "debugger", From d6ca6947198fc05ef2e3a72a4c1e45696c0b8556 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 10 Jan 2023 11:28:34 +0100 Subject: [PATCH 259/666] esptool.py v4.4.3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index a11cb6cb6..af36495b1 100644 --- a/platform.json +++ b/platform.json @@ -94,7 +94,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4.2/esptool-4.4.2.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4.3/esptool-4.4.3.zip" }, "tool-openocd-esp32": { "type": "debugger", From 37d2266f67aa8500e58aeb84cb4582dd09f876a9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 10 Jan 2023 11:31:27 +0100 Subject: [PATCH 260/666] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fe1e4d98f..812d6b1d6 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -### Stable Release supporting Arduino and IDF -based on Arduino Core 2.0.5 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C3, ESP32S2 and ESP32S3 +### Stable Release supporting Arduino and IDF 5.0 +based on Arduino Core 2.0.6 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C3, ESP32S2 and ESP32S3 ``` [platformio] -platform = https://github.com/tasmota/platform-espressif32/releases/download/v.2.0.5/platform-espressif32-v.2.0.5.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.01.00/platform-espressif32.zip framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env From 769b6791328dd65cd3f02abb562eb79bc5900698 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 17 Jan 2023 10:14:29 +0100 Subject: [PATCH 261/666] Changes from Upstream for IDF5 --- builder/frameworks/espidf.py | 44 +++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 354ca3a0c..52ad882ce 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -25,6 +25,7 @@ import subprocess import sys import os +import pkg_resources import click import semantic_version @@ -49,6 +50,9 @@ mcu = board.get("build.mcu", "esp32") idf_variant = mcu.lower() +# Required until Arduino switches to v5 +IDF5 = platform.get_package_version( + "framework-espidf").split(".")[1].startswith("5") FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( "toolchain-%s" % ("riscv32-esp" if mcu == "esp32c3" else ("xtensa-%s" % mcu)) @@ -584,6 +588,7 @@ def _fix_component_relative_include(config, build_flags, source_index): build_flags = build_flags.replace("..", os.path.dirname(source_file_path) + "/..") return build_flags + def prepare_build_envs(config, default_env, debug_allowed=True): build_envs = [] target_compile_groups = config.get("compileGroups") @@ -1073,21 +1078,21 @@ def _get_installed_pip_packages(): "wheel": ">=0.35.1", "cryptography": ">=2.1.4,<35.0.0", "future": ">=0.15.2", - "pyparsing": ">=3" - if platform.get_package_version("framework-espidf") - .split(".")[1] - .startswith("5") - else ">=2.0.3,<2.4.0", + "pyparsing": ">=2.0.3,<2.4.0", "kconfiglib": "==13.7.1", "idf-component-manager": "~=1.0", } + if IDF5: + # Remove specific versions for IDF5 as not required + deps = {dep: "" for dep in deps} + installed_packages = _get_installed_pip_packages() packages_to_install = [] for package, spec in deps.items(): if package not in installed_packages: packages_to_install.append(package) - else: + elif spec: version_spec = semantic_version.Spec(spec) if not version_spec.match(installed_packages[package]): packages_to_install.append(package) @@ -1096,21 +1101,34 @@ def _get_installed_pip_packages(): env.Execute( env.VerboseAction( ( - '"$PYTHONEXE" -m pip install -U --force-reinstall ' - + " ".join(['"%s%s"' % (p, deps[p]) for p in packages_to_install]) + '"$PYTHONEXE" -m pip install -U ' + + " ".join( + [ + '"%s%s"' % (p, deps[p]) + for p in packages_to_install + ] + ) ), "Installing ESP-IDF's Python dependencies", ) ) - # a special "esp-windows-curses" python package is required on Windows for Menuconfig - if "windows" in get_systype(): - import pkg_resources + if "windows" in get_systype() and "windows-curses" not in installed_packages: + env.Execute( + env.VerboseAction( + "$PYTHONEXE -m pip install windows-curses", + "Installing windows-curses package", + ) + ) - if "esp-windows-curses" not in {pkg.key for pkg in pkg_resources.working_set}: + # A special "esp-windows-curses" python package is required on Windows + # for Menuconfig on IDF <5 + if not IDF5 and "esp-windows-curses" not in { + pkg.key for pkg in pkg_resources.working_set + }: env.Execute( env.VerboseAction( - '$PYTHONEXE -m pip install "file://%s/tools/kconfig_new/esp-windows-curses" windows-curses' + '$PYTHONEXE -m pip install "file://%s/tools/kconfig_new/esp-windows-curses"' % FRAMEWORK_DIR, "Installing windows-curses package", ) From 64ad7e504dc77ddc2cfdfecc63501ebdfa11afa7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 17 Jan 2023 10:21:25 +0100 Subject: [PATCH 262/666] no `pip install --force-reinstall` --- builder/frameworks/arduino.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 3690ecb22..4a0bfbcfc 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -94,8 +94,13 @@ def _get_installed_pip_packages(): env.Execute( env.VerboseAction( ( - '"$PYTHONEXE" -m pip install -U --force-reinstall ' - + " ".join(['"%s%s"' % (p, deps[p]) for p in packages_to_install]) + '"$PYTHONEXE" -m pip install -U ' + + " ".join( + [ + '"%s%s"' % (p, deps[p]) + for p in packages_to_install + ] + ) ), "Installing Python dependencies", ) From eeea60783ec62fa6d3321b3dd9f6111da57f14cb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 23 Jan 2023 22:05:56 +0100 Subject: [PATCH 263/666] Use latest pio v6.1.6 fixes `extends` --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index af36495b1..0ab5c0084 100644 --- a/platform.json +++ b/platform.json @@ -12,7 +12,7 @@ "RISC-V" ], "engines": { - "platformio": ">=6.1.5" + "platformio": ">=6.1.6" }, "repository": { "type": "git", From c04f7b762bffbb26578439e2e5037f8a4ce42a41 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 24 Jan 2023 15:51:11 +0100 Subject: [PATCH 264/666] rm IDF downgrade to 4.4.3 --- platform.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platform.py b/platform.py index a47d3e1b5..14244a586 100644 --- a/platform.py +++ b/platform.py @@ -66,10 +66,6 @@ def configure_default_packages(self, variables, targets): elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: self.packages[p]["optional"] = False - if "arduino" in frameworks: - # Downgrade the IDF version for mixed Arduino+IDF projects - self.packages["framework-espidf"]["version"] = "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20221227/esp-idf-v4.4.3.zip" - else: # Use the latest toolchains available for IDF v5.0 for target in ( "xtensa-esp32", From 3abdc79ad9150c31fb211c0ccb6801a354f84a40 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 24 Jan 2023 15:55:44 +0100 Subject: [PATCH 265/666] use IDF 5.x toolchains only --- platform.json | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/platform.json b/platform.json index 0ab5c0084..879371c32 100644 --- a/platform.json +++ b/platform.json @@ -36,7 +36,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.6/framework-arduinoespressif32.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1138/framework-arduinoespressif32-master-49551cc48c.zip" }, "framework-arduino-solo1": { "type": "framework", @@ -54,36 +54,31 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.50000.0", - "optionalVersions": "https://github.com/tasmota/esp-idf/releases/download/v4.4.3.20221227/esp-idf-v4.4.3.zip" + "version": "~3.50000.0" }, "toolchain-xtensa-esp32": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["11.2.0+2022r1"] + "version": "11.2.0+2022r1" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["11.2.0+2022r1"] + "version": "11.2.0+2022r1" }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["11.2.0+2022r1"] + "version": "11.2.0+2022r1" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["11.2.0+2022r1"] + "version": "11.2.0+2022r1" }, "toolchain-esp32ulp": { "type": "toolchain", From ee41ab374774671b0ddba4b5eb1d430f0628ee25 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 25 Jan 2023 10:57:10 +0100 Subject: [PATCH 266/666] pyparsing >=3.0.9 --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 52ad882ce..8e7e8b283 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1078,7 +1078,7 @@ def _get_installed_pip_packages(): "wheel": ">=0.35.1", "cryptography": ">=2.1.4,<35.0.0", "future": ">=0.15.2", - "pyparsing": ">=2.0.3,<2.4.0", + "pyparsing": ">=3.0.9", "kconfiglib": "==13.7.1", "idf-component-manager": "~=1.0", } From 975fec170395dfded9e5f6ff73b300567b74eac8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 25 Jan 2023 14:53:34 +0100 Subject: [PATCH 267/666] Use pre IDF 5.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 879371c32..2f6f46315 100644 --- a/platform.json +++ b/platform.json @@ -54,7 +54,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.50000.0" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1-pre/esp-idf-v5.1-pre.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 5e9c6ea30b5decb7aed61dec8e92fdc697cdfed8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 25 Jan 2023 15:00:33 +0100 Subject: [PATCH 268/666] revert to "pyparsing": ">=2.0.3,<2.4.0" --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 8e7e8b283..52ad882ce 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1078,7 +1078,7 @@ def _get_installed_pip_packages(): "wheel": ">=0.35.1", "cryptography": ">=2.1.4,<35.0.0", "future": ">=0.15.2", - "pyparsing": ">=3.0.9", + "pyparsing": ">=2.0.3,<2.4.0", "kconfiglib": "==13.7.1", "idf-component-manager": "~=1.0", } From a897d2f3950e141b6184678a4d54be0da62c9348 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 25 Jan 2023 15:45:03 +0100 Subject: [PATCH 269/666] Use release IDF 5.0 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 2f6f46315..879371c32 100644 --- a/platform.json +++ b/platform.json @@ -54,7 +54,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1-pre/esp-idf-v5.1-pre.zip" + "version": "~3.50000.0" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 4204a8de3455c0368c2272f95c5995716ba64223 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 25 Jan 2023 21:31:55 +0100 Subject: [PATCH 270/666] try own IDF 5.0 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 879371c32..3aa7b7272 100644 --- a/platform.json +++ b/platform.json @@ -54,7 +54,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.50000.0" + "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.0.0/esp-idf-v5.0.0.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 1563202a8ea0dd2a9b924569ef296f0a53034251 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 25 Jan 2023 22:04:30 +0100 Subject: [PATCH 271/666] Update platform.json --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 3aa7b7272..bc3f6225b 100644 --- a/platform.json +++ b/platform.json @@ -36,24 +36,24 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1138/framework-arduinoespressif32-master-49551cc48c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1156/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.6/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1156/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/2.0.6/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1156/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" }, "framework-espidf": { "type": "framework", "optional": true, - "owner": "platformio", + "owner": "tasmota", "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.0.0/esp-idf-v5.0.0.zip" }, "toolchain-xtensa-esp32": { From 6e5be9dfd4b38e1b242b5a8e7996696734b5a94c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 25 Jan 2023 22:17:59 +0100 Subject: [PATCH 272/666] Update examples.yml --- .github/workflows/examples.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 16914ac72..3b787537e 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -22,7 +22,6 @@ jobs: - "examples/espidf-arduino-blink" - "examples/espidf-arduino-wifiscan" - "examples/espidf-blink" - - "examples/espidf-aws-iot" - "examples/espidf-ble-eddystone" - "examples/espidf-coap-server" - "examples/espidf-exceptions" From b25343196a02d3da7a1fa6a9e121f25344078462 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 26 Jan 2023 12:14:53 +0100 Subject: [PATCH 273/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index bc3f6225b..7970adbb6 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1156/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1157/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1156/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1157/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1156/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1157/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" }, "framework-espidf": { "type": "framework", From eaabf49fb4965638edac5c1fdb18fcf971366316 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 26 Jan 2023 14:26:23 +0100 Subject: [PATCH 274/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 7970adbb6..47877d1c1 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1157/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1158/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1157/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1158/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1157/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1158/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" }, "framework-espidf": { "type": "framework", From 26afcf809cce06a3619af6df8db3301bdcc663e1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 29 Jan 2023 15:48:48 +0100 Subject: [PATCH 275/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 47877d1c1..126ee6df7 100644 --- a/platform.json +++ b/platform.json @@ -54,7 +54,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.0.0/esp-idf-v5.0.0.zip" + "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.0/esp-idf-v5.0.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 361081b5a6258a8897bafd34ebfd79e3fe899354 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 29 Jan 2023 15:54:05 +0100 Subject: [PATCH 276/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 126ee6df7..b1207a763 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1158/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1171/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1158/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1171/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1158/framework-arduinoespressif32-Tasmota_v5-450b6a3f3c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1171/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" }, "framework-espidf": { "type": "framework", From 63360b975513566e6d5855b552201838fb39d2b1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 29 Jan 2023 17:35:01 +0100 Subject: [PATCH 277/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index b1207a763..425324a3f 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1171/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1176/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1171/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1176/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1171/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1176/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" }, "framework-espidf": { "type": "framework", From 54c205a17269ef3baf59701006694f837d7c319e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 29 Jan 2023 17:45:38 +0100 Subject: [PATCH 278/666] Update Blink.cpp --- examples/espidf-arduino-blink/src/Blink.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/espidf-arduino-blink/src/Blink.cpp b/examples/espidf-arduino-blink/src/Blink.cpp index c69fd30f5..b584a2c73 100644 --- a/examples/espidf-arduino-blink/src/Blink.cpp +++ b/examples/espidf-arduino-blink/src/Blink.cpp @@ -29,7 +29,7 @@ void blink_task(void *pvParameter) Technical Reference for a list of pads and their default functions.) */ - gpio_pad_select_gpio(BLINK_GPIO); + esp_rom_gpio_pad_select_gpio(BLINK_GPIO); /* Set the GPIO as a push/pull output */ gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); while(1) { From 46610926f53c48ee04d18aa0c2613a8e4dd83bf4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 29 Jan 2023 17:50:05 +0100 Subject: [PATCH 279/666] rm outdated example --- .github/workflows/examples.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 3b787537e..934aace02 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -20,7 +20,6 @@ jobs: - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/espidf-arduino-blink" - - "examples/espidf-arduino-wifiscan" - "examples/espidf-blink" - "examples/espidf-ble-eddystone" - "examples/espidf-coap-server" From 4db5bfa53a328c90a4d6b836b66e9a8abeeb4f74 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 29 Jan 2023 17:55:40 +0100 Subject: [PATCH 280/666] rm arduino/IDF example --- .github/workflows/examples.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 934aace02..13f6eef7d 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -19,7 +19,6 @@ jobs: - "examples/arduino-rmt-blink" - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - - "examples/espidf-arduino-blink" - "examples/espidf-blink" - "examples/espidf-ble-eddystone" - "examples/espidf-coap-server" From be66e95d915ed2c4d44f4c10371fa47fbc8305b8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 1 Feb 2023 12:25:53 +0100 Subject: [PATCH 281/666] Better handling of ESP IDF Python dependencies --- builder/frameworks/espidf.py | 101 +++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 27 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 52ad882ce..bd6997fb9 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -37,11 +37,17 @@ ) from platformio import fs +from platformio.compat import IS_WINDOWS from platformio.proc import exec_command -from platformio.util import get_systype from platformio.builder.tools.piolib import ProjectAsLibBuilder from platformio.package.version import get_original_version, pepver_to_semver +# Added to avoid conflicts between installed Python packages from +# the IDF virtual environment and PlatformIO Core +# Note: This workaround can be safely deleted when PlatformIO 6.1.7 is released +if os.environ.get("PYTHONPATH"): + del os.environ["PYTHONPATH"] + env = DefaultEnvironment() env.SConscript("_embed_files.py", exports="env") @@ -51,8 +57,7 @@ idf_variant = mcu.lower() # Required until Arduino switches to v5 -IDF5 = platform.get_package_version( - "framework-espidf").split(".")[1].startswith("5") +IDF5 = platform.get_package_version("framework-espidf").split(".")[1].startswith("5") FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( "toolchain-%s" % ("riscv32-esp" if mcu == "esp32c3" else ("xtensa-%s" % mcu)) @@ -62,6 +67,7 @@ assert os.path.isdir(FRAMEWORK_DIR) assert os.path.isdir(TOOLCHAIN_DIR) +# Arduino framework as a component is not compatible with ESP-IDF >=4.1 if "arduino" in env.subst("$PIOFRAMEWORK"): ARDUINO_FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") # Possible package names in 'package@version' format is not compatible with CMake @@ -223,7 +229,7 @@ def populate_idf_env_vars(idf_env): os.path.join(TOOLCHAIN_DIR, "bin"), platform.get_package_dir("tool-ninja"), os.path.join(platform.get_package_dir("tool-cmake"), "bin"), - os.path.dirname(env.subst("$PYTHONEXE")), + os.path.dirname(get_python_exe()), ] if mcu != "esp32c3": @@ -231,7 +237,7 @@ def populate_idf_env_vars(idf_env): os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), ) - if "windows" in get_systype(): + if IS_WINDOWS: additional_packages.append(platform.get_package_dir("tool-mconf")) idf_env["PATH"] = os.pathsep.join(additional_packages + [idf_env["PATH"]]) @@ -558,7 +564,7 @@ def generate_project_ld_script(sdk_config, ignore_targets=None): } cmd = ( - '"$PYTHONEXE" "{script}" --input $SOURCE ' + '"$ESPIDF_PYTHONEXE" "{script}" --input $SOURCE ' '--config "{config}" --fragments {fragments} --output $TARGET ' '--kconfig "{kconfig}" --env-file "{env_file}" ' '--libraries-file "{libraries_list}" ' @@ -762,7 +768,7 @@ def build_bootloader(sdk_config): [ "-DIDF_TARGET=" + idf_variant, "-DPYTHON_DEPS_CHECKED=1", - "-DPYTHON=" + env.subst("$PYTHONEXE"), + "-DPYTHON=" + get_python_exe(), "-DIDF_PATH=" + FRAMEWORK_DIR, "-DSDKCONFIG=" + SDKCONFIG_PATH, "-DLEGACY_INCLUDE_COMMON_HEADERS=", @@ -917,7 +923,7 @@ def generate_empty_partition_image(binary_path, image_size): binary_path, None, env.VerboseAction( - '"$PYTHONEXE" "%s" %s $TARGET' + '"$ESPIDF_PYTHONEXE" "%s" %s $TARGET' % ( os.path.join( FRAMEWORK_DIR, @@ -942,7 +948,7 @@ def get_partition_info(pt_path, pt_offset, pt_params): env.Exit(1) cmd = [ - env.subst("$PYTHONEXE"), + get_python_exe(), os.path.join(FRAMEWORK_DIR, "components", "partition_table", "parttool.py"), "-q", "--partition-table-offset", @@ -999,7 +1005,7 @@ def generate_mbedtls_bundle(sdk_config): FRAMEWORK_DIR, "components", "mbedtls", "esp_crt_bundle" ) - cmd = [env.subst("$PYTHONEXE"), os.path.join(default_crt_dir, "gen_crt_bundle.py")] + cmd = [get_python_exe(), os.path.join(default_crt_dir, "gen_crt_bundle.py")] crt_args = ["--input"] if sdk_config.get("MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL", False): @@ -1050,12 +1056,12 @@ def generate_mbedtls_bundle(sdk_config): def install_python_deps(): - def _get_installed_pip_packages(): + def _get_installed_pip_packages(python_exe_path): result = {} packages = {} pip_output = subprocess.check_output( [ - env.subst("$PYTHONEXE"), + python_exe_path, "-m", "pip", "list", @@ -1087,7 +1093,8 @@ def _get_installed_pip_packages(): # Remove specific versions for IDF5 as not required deps = {dep: "" for dep in deps} - installed_packages = _get_installed_pip_packages() + python_exe_path = get_python_exe() + installed_packages = _get_installed_pip_packages(python_exe_path) packages_to_install = [] for package, spec in deps.items(): if package not in installed_packages: @@ -1101,22 +1108,17 @@ def _get_installed_pip_packages(): env.Execute( env.VerboseAction( ( - '"$PYTHONEXE" -m pip install -U ' - + " ".join( - [ - '"%s%s"' % (p, deps[p]) - for p in packages_to_install - ] - ) + '"%s" -m pip install -U ' % python_exe_path + + " ".join(['"%s%s"' % (p, deps[p]) for p in packages_to_install]) ), "Installing ESP-IDF's Python dependencies", ) ) - if "windows" in get_systype() and "windows-curses" not in installed_packages: + if IS_WINDOWS and "windows-curses" not in installed_packages: env.Execute( env.VerboseAction( - "$PYTHONEXE -m pip install windows-curses", + '"%s" -m pip install windows-curses' % python_exe_path, "Installing windows-curses package", ) ) @@ -1128,15 +1130,59 @@ def _get_installed_pip_packages(): }: env.Execute( env.VerboseAction( - '$PYTHONEXE -m pip install "file://%s/tools/kconfig_new/esp-windows-curses"' - % FRAMEWORK_DIR, + '"%s" -m pip install "file://%s/tools/kconfig_new/esp-windows-curses"' + % (python_exe_path, FRAMEWORK_DIR), "Installing windows-curses package", ) ) +def get_python_exe(): + def _create_venv(venv_dir): + pip_path = os.path.join( + venv_dir, + "Scripts" if IS_WINDOWS else "bin", + "pip" + (".exe" if IS_WINDOWS else ""), + ) + if not os.path.isfile(pip_path): + # Use the built-in PlatformIO Python to create a standalone IDF virtual env + env.Execute( + env.VerboseAction( + '"$PYTHONEXE" -m venv --clear "%s"' % venv_dir, + "Creating a virtual environment for IDF Python dependencies", + ) + ) + + assert os.path.isfile( + pip_path + ), "Error: Failed to create a proper virtual environment. Missing the pip binary!" + + # The name of the IDF venv contains the IDF version to avoid possible conflicts and + # unnecessary reinstallation of Python dependencies in cases when Arduino + # as an IDF component requires a different version of the IDF package and + # hence a different set of Python deps or their versions + idf_version = get_original_version(platform.get_package_version("framework-espidf")) + venv_dir = os.path.join( + env.subst("$PROJECT_CORE_DIR"), "penv", ".espidf-" + idf_version) + + if not os.path.isdir(venv_dir): + _create_venv(venv_dir) + + python_exe_path = os.path.join( + venv_dir, + "Scripts" if IS_WINDOWS else "bin", + "python" + (".exe" if IS_WINDOWS else ""), + ) + + assert os.path.isfile(python_exe_path), ( + "Error: Missing Python executable file `%s`" % python_exe_path + ) + + return python_exe_path + + # -# ESP-IDF requires Python packages with specific versions +# ESP-IDF requires Python packages with specific versions in a virtual environment # install_python_deps() @@ -1235,7 +1281,7 @@ def _get_installed_pip_packages(): "-DIDF_TARGET=" + idf_variant, "-DPYTHON_DEPS_CHECKED=1", "-DEXTRA_COMPONENT_DIRS:PATH=" + ";".join(extra_components), - "-DPYTHON=" + env.subst("$PYTHONEXE"), + "-DPYTHON=" + get_python_exe(), "-DSDKCONFIG=" + SDKCONFIG_PATH, ] + click.parser.split_arg_string(board.get("build.cmake_extra_args", "")), @@ -1373,7 +1419,7 @@ def _skip_prj_source_files(node): os.path.join("$BUILD_DIR", "partitions.bin"), "$PARTITIONS_TABLE_CSV", env.VerboseAction( - '"$PYTHONEXE" "%s" -q --offset "%s" --flash-size "%s" $SOURCE $TARGET' + '"$ESPIDF_PYTHONEXE" "%s" -q --offset "%s" --flash-size "%s" $SOURCE $TARGET' % ( os.path.join( FRAMEWORK_DIR, "components", "partition_table", "gen_esp32part.py" @@ -1396,6 +1442,7 @@ def _skip_prj_source_files(node): env.Prepend( CPPPATH=app_includes["plain_includes"], CPPDEFINES=project_defines, + ESPIDF_PYTHONEXE=get_python_exe(), LINKFLAGS=extra_flags, LIBS=libs, FLASH_EXTRA_IMAGES=[ From 912820a578f5faa3f2f5050bc8c132783aeb8b4a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 1 Feb 2023 12:28:26 +0100 Subject: [PATCH 282/666] Update platform.json --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 425324a3f..d611a78b3 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1176/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1179/framework-arduinoespressif32-Tasmota_v5-d6ffee9234.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1176/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1179/framework-arduinoespressif32-Tasmota_v5-d6ffee9234.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1176/framework-arduinoespressif32-Tasmota_v5-a1f7e3c87c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1179/framework-arduinoespressif32-Tasmota_v5-d6ffee9234.zip" }, "framework-espidf": { "type": "framework", @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4.3/esptool-4.4.3.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4.4/esptool-4.4.4.zip" }, "tool-openocd-esp32": { "type": "debugger", From 037ab30af458e9f5747b6d6839e6fb7d56bfb833 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 3 Feb 2023 12:52:17 +0100 Subject: [PATCH 283/666] esptool v4.4.5 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index d611a78b3..b65c8a46f 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4.4/esptool-4.4.4.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.4.5/esptool-4.4.5.zip" }, "tool-openocd-esp32": { "type": "debugger", From 6768c1edd66cf961789f6096ddc6ff189fde888c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 3 Feb 2023 13:04:53 +0100 Subject: [PATCH 284/666] Delete examples/espidf-aws-iot directory --- examples/espidf-aws-iot/.gitignore | 1 - examples/espidf-aws-iot/.travis.yml | 67 -- examples/espidf-aws-iot/CMakeLists.txt | 6 - examples/espidf-aws-iot/README.md | 22 - .../components/esp-aws-iot/.gitignore | 9 - .../components/esp-aws-iot/.gitlab-ci.yml | 42 - .../components/esp-aws-iot/.gitmodules | 3 - .../components/esp-aws-iot/CMakeLists.txt | 26 - .../components/esp-aws-iot/Kconfig | 146 --- .../components/esp-aws-iot/LICENSE | 201 ---- .../components/esp-aws-iot/README.md | 14 - .../aws-iot-device-sdk-embedded-C/.gitignore | 22 - .../aws-iot-device-sdk-embedded-C/.travis.yml | 44 - .../CHANGELOG.md | 233 ----- .../CODE_OF_CONDUCT.md | 4 - .../CONTRIBUTING.md | 61 -- .../CppUTestMakefileWorker.mk | 575 ----------- .../aws-iot-device-sdk-embedded-C/LICENSE.txt | 120 --- .../aws-iot-device-sdk-embedded-C/Makefile | 131 --- .../aws-iot-device-sdk-embedded-C/NOTICE.txt | 16 - .../PortingGuide.md | 145 --- .../aws-iot-device-sdk-embedded-C/README.md | 270 ----- .../certs/README.txt | 4 - .../doc/architecture.png | Bin 82526 -> 0 bytes .../doc/architecture.txt | 32 - .../doc/config/common | 95 -- .../doc/config/html/footer.html | 35 - .../doc/config/html/header.html | 88 -- .../doc/config/html/style.css | 128 --- .../doc/config/layout_library.xml | 197 ---- .../doc/config/layout_main.xml | 200 ---- .../doc/config/main | 30 - .../doc/config/mqtt | 21 - .../doc/lib/mqtt.txt | 61 -- .../external_libs/CppUTest/README.txt | 2 - .../external_libs/jsmn/jsmn.c | 344 ------- .../external_libs/jsmn/jsmn.h | 106 -- .../external_libs/mbedTLS/README.txt | 10 - .../filterGcov.sh | 63 -- .../include/aws_iot_error.h | 166 --- .../include/aws_iot_jobs_interface.h | 267 ----- .../include/aws_iot_jobs_json.h | 108 -- .../include/aws_iot_jobs_topics.h | 88 -- .../include/aws_iot_jobs_types.h | 109 -- .../include/aws_iot_json_utils.h | 212 ---- .../include/aws_iot_log.h | 138 --- .../include/aws_iot_mqtt_client.h | 491 --------- .../aws_iot_mqtt_client_common_internal.h | 134 --- .../include/aws_iot_mqtt_client_interface.h | 305 ------ .../include/aws_iot_shadow_actions.h | 33 - .../include/aws_iot_shadow_interface.h | 305 ------ .../include/aws_iot_shadow_json.h | 51 - .../include/aws_iot_shadow_json_data.h | 150 --- .../include/aws_iot_shadow_key.h | 22 - .../include/aws_iot_shadow_records.h | 55 - .../include/aws_iot_version.h | 48 - .../include/network_interface.h | 167 ---- .../include/threads_interface.h | 108 -- .../include/timer_interface.h | 105 -- .../platform/linux/common/timer.c | 82 -- .../platform/linux/common/timer_platform.h | 48 - .../linux/mbedtls/network_mbedtls_wrapper.c | 440 -------- .../platform/linux/mbedtls/network_platform.h | 59 -- .../platform/linux/pthread/threads_platform.h | 43 - .../linux/pthread/threads_pthread_wrapper.c | 112 --- .../samples/README.md | 44 - .../samples/linux/jobs_sample/Makefile | 71 -- .../linux/jobs_sample/aws_iot_config.h | 78 -- .../samples/linux/jobs_sample/jobs_sample.c | 374 ------- .../samples/linux/shadow_sample/Makefile | 72 -- .../linux/shadow_sample/aws_iot_config.h | 63 -- .../linux/shadow_sample/shadow_sample.c | 274 ----- .../linux/shadow_sample_console_echo/Makefile | 75 -- .../aws_iot_config.h | 63 -- .../shadow_console_echo.c | 271 ----- .../subscribe_publish_library_sample/Makefile | 76 -- .../aws_iot_config.h | 63 -- .../subscribe_publish_library_sample.c | 264 ----- .../linux/subscribe_publish_sample/Makefile | 70 -- .../subscribe_publish_sample/aws_iot_config.h | 63 -- .../subscribe_publish_sample.c | 270 ----- .../src/aws_iot_jobs_interface.c | 215 ---- .../src/aws_iot_jobs_json.c | 197 ---- .../src/aws_iot_jobs_topics.c | 129 --- .../src/aws_iot_jobs_types.c | 73 -- .../src/aws_iot_json_utils.c | 227 ----- .../src/aws_iot_mqtt_client.c | 397 -------- .../src/aws_iot_mqtt_client_common_internal.c | 793 --------------- .../src/aws_iot_mqtt_client_connect.c | 560 ----------- .../src/aws_iot_mqtt_client_publish.c | 411 -------- .../src/aws_iot_mqtt_client_subscribe.c | 435 -------- .../src/aws_iot_mqtt_client_unsubscribe.c | 234 ----- .../src/aws_iot_mqtt_client_yield.c | 325 ------ .../src/aws_iot_shadow.c | 250 ----- .../src/aws_iot_shadow_actions.c | 80 -- .../src/aws_iot_shadow_json.c | 559 ----------- .../src/aws_iot_shadow_records.c | 529 ---------- .../tests/README.md | 9 - .../tests/integration/Makefile | 108 -- .../tests/integration/README.md | 44 - .../integration/include/aws_iot_config.h | 73 -- .../include/aws_iot_integ_tests_config.h | 46 - .../include/aws_iot_test_integration_common.h | 43 - .../aws_iot_test_multithreading_validation.c | 362 ------- .../src/aws_iot_test_auto_reconnect.c | 236 ----- .../src/aws_iot_test_basic_connectivity.c | 281 ------ .../src/aws_iot_test_integration_runner.c | 91 -- .../integration/src/aws_iot_test_jobs_api.c | 284 ------ .../src/aws_iot_test_multiple_clients.c | 286 ------ .../tests/unit/README.md | 12 - .../tests/unit/include/aws_iot_config.h | 73 -- .../aws_iot_tests_unit_helper_functions.h | 104 -- .../aws_iot_tests_unit_shadow_helper.h | 43 - .../src/aws_iot_tests_unit_common_tests.cpp | 34 - .../aws_iot_tests_unit_common_tests_helper.c | 186 ---- .../unit/src/aws_iot_tests_unit_connect.cpp | 86 -- .../src/aws_iot_tests_unit_connect_helper.c | 792 --------------- .../src/aws_iot_tests_unit_disconnect.cpp | 42 - .../aws_iot_tests_unit_disconnect_helper.c | 244 ----- .../src/aws_iot_tests_unit_helper_functions.c | 571 ----------- .../unit/src/aws_iot_tests_unit_jobs.cpp | 60 -- .../src/aws_iot_tests_unit_jobs_interface.c | 337 ------- .../unit/src/aws_iot_tests_unit_jobs_json.c | 244 ----- .../unit/src/aws_iot_tests_unit_jobs_topics.c | 161 --- .../unit/src/aws_iot_tests_unit_jobs_types.c | 70 -- .../src/aws_iot_tests_unit_json_utils.cpp | 91 -- .../aws_iot_tests_unit_json_utils_helper.c | 834 ---------------- .../unit/src/aws_iot_tests_unit_publish.cpp | 48 - .../src/aws_iot_tests_unit_publish_helper.c | 205 ---- .../unit/src/aws_iot_tests_unit_runner.cpp | 25 - .../src/aws_iot_tests_unit_shadow_action.cpp | 51 - .../aws_iot_tests_unit_shadow_action_helper.c | 944 ------------------ .../src/aws_iot_tests_unit_shadow_delta.cpp | 33 - .../aws_iot_tests_unit_shadow_delta_helper.c | 324 ------ ...aws_iot_tests_unit_shadow_json_builder.cpp | 31 - ...ot_tests_unit_shadow_json_builder_helper.c | 131 --- .../aws_iot_tests_unit_shadow_null_fields.cpp | 40 - ...iot_tests_unit_shadow_null_fields_helper.c | 151 --- .../unit/src/aws_iot_tests_unit_subscribe.cpp | 79 -- .../src/aws_iot_tests_unit_subscribe_helper.c | 606 ----------- .../src/aws_iot_tests_unit_unsubscribe.cpp | 55 - .../aws_iot_tests_unit_unsubscribe_helper.c | 343 ------- .../unit/src/aws_iot_tests_unit_yield.cpp | 57 -- .../src/aws_iot_tests_unit_yield_helper.c | 493 --------- .../tls_mock/aws_iot_tests_unit_mock_tls.c | 223 ----- .../aws_iot_tests_unit_mock_tls_params.c | 47 - .../aws_iot_tests_unit_mock_tls_params.h | 72 -- .../tests/unit/tls_mock/network_platform.h | 19 - .../components/esp-aws-iot/component.mk | 10 - .../components/esp-aws-iot/examples/README.md | 141 --- .../examples/subscribe_publish/CMakeLists.txt | 7 - .../examples/subscribe_publish/Makefile | 11 - .../examples/subscribe_publish/README.md | 36 - .../subscribe_publish/main/CMakeLists.txt | 11 - .../subscribe_publish/main/Kconfig.projbuild | 60 -- .../subscribe_publish/main/certs/README.md | 3 - .../main/certs/aws-root-ca.pem | 20 - .../subscribe_publish/main/component.mk | 14 - .../main/subscribe_publish_sample.c | 332 ------ .../examples/subscribe_publish/sdkconfig.ci | 2 - .../subscribe_publish/sdkconfig.defaults | 9 - .../examples/thing_shadow/CMakeLists.txt | 7 - .../examples/thing_shadow/Makefile | 11 - .../examples/thing_shadow/README.md | 38 - .../examples/thing_shadow/main/CMakeLists.txt | 11 - .../thing_shadow/main/Kconfig.projbuild | 66 -- .../thing_shadow/main/certs/README.md | 3 - .../thing_shadow/main/certs/aws-root-ca.pem | 20 - .../examples/thing_shadow/main/component.mk | 14 - .../thing_shadow/main/thing_shadow_sample.c | 370 ------- .../examples/thing_shadow/sdkconfig.ci | 2 - .../examples/thing_shadow/sdkconfig.defaults | 8 - .../esp-aws-iot/port/include/aws_iot_config.h | 65 -- .../esp-aws-iot/port/include/aws_iot_log.h | 50 - .../port/include/network_platform.h | 64 -- .../port/include/threads_platform.h | 45 - .../esp-aws-iot/port/include/timer_platform.h | 40 - .../port/network_mbedtls_wrapper.c | 419 -------- .../esp-aws-iot/port/threads_freertos.c | 104 -- .../components/esp-aws-iot/port/timer.c | 83 -- examples/espidf-aws-iot/include/README | 39 - examples/espidf-aws-iot/lib/README | 46 - examples/espidf-aws-iot/platformio.ini | 26 - examples/espidf-aws-iot/sdkconfig.defaults | 13 - examples/espidf-aws-iot/src/CMakeLists.txt | 11 - examples/espidf-aws-iot/src/Kconfig.projbuild | 60 -- examples/espidf-aws-iot/src/certs/README.md | 3 - .../espidf-aws-iot/src/certs/aws-root-ca.pem | 20 - .../src/certs/certificate.pem.crt | 3 - .../espidf-aws-iot/src/certs/private.pem.key | 3 - .../src/subscribe_publish_sample.c | 358 ------- examples/espidf-aws-iot/test/README | 11 - 192 files changed, 27518 deletions(-) delete mode 100644 examples/espidf-aws-iot/.gitignore delete mode 100644 examples/espidf-aws-iot/.travis.yml delete mode 100644 examples/espidf-aws-iot/CMakeLists.txt delete mode 100644 examples/espidf-aws-iot/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/.gitignore delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/.gitlab-ci.yml delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/.gitmodules delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/CMakeLists.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/Kconfig delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/LICENSE delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.gitignore delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.travis.yml delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CHANGELOG.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CODE_OF_CONDUCT.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CONTRIBUTING.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CppUTestMakefileWorker.mk delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/LICENSE.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/Makefile delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/NOTICE.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/PortingGuide.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/certs/README.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/architecture.png delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/architecture.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/common delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/footer.html delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/header.html delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/style.css delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_library.xml delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_main.xml delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/main delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/mqtt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/lib/mqtt.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/CppUTest/README.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/mbedTLS/README.txt delete mode 100755 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/filterGcov.sh delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_error.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_interface.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_json.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_topics.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_types.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_json_utils.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_log.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_common_internal.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_interface.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_actions.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_interface.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json_data.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_key.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_records.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_version.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/network_interface.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/threads_interface.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/timer_interface.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer_platform.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_mbedtls_wrapper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_platform.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_platform.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_pthread_wrapper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/Makefile delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/aws_iot_config.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/jobs_sample.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/Makefile delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/aws_iot_config.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/shadow_sample.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/Makefile delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/aws_iot_config.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/shadow_console_echo.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/Makefile delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/aws_iot_config.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/Makefile delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/aws_iot_config.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/subscribe_publish_sample.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_interface.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_json.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_topics.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_types.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_json_utils.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_common_internal.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_connect.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_publish.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_subscribe.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_unsubscribe.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_yield.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_actions.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_json.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_records.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/Makefile delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_config.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_integ_tests_config.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_test_integration_common.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/multithreadingTest/aws_iot_test_multithreading_validation.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_auto_reconnect.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_basic_connectivity.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_integration_runner.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_jobs_api.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_multiple_clients.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_config.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_helper_functions.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_shadow_helper.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_helper_functions.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_interface.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_json.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_topics.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_types.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_runner.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield.cpp delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield_helper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/network_platform.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/component.mk delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/CMakeLists.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/Makefile delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/CMakeLists.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/Kconfig.projbuild delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/aws-root-ca.pem delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/component.mk delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/subscribe_publish_sample.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.ci delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.defaults delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/CMakeLists.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/Makefile delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/CMakeLists.txt delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/Kconfig.projbuild delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/README.md delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/aws-root-ca.pem delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/component.mk delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/thing_shadow_sample.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.ci delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.defaults delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_config.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_log.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/port/include/network_platform.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/port/include/threads_platform.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/port/include/timer_platform.h delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/port/network_mbedtls_wrapper.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/port/threads_freertos.c delete mode 100644 examples/espidf-aws-iot/components/esp-aws-iot/port/timer.c delete mode 100644 examples/espidf-aws-iot/include/README delete mode 100644 examples/espidf-aws-iot/lib/README delete mode 100644 examples/espidf-aws-iot/platformio.ini delete mode 100644 examples/espidf-aws-iot/sdkconfig.defaults delete mode 100644 examples/espidf-aws-iot/src/CMakeLists.txt delete mode 100644 examples/espidf-aws-iot/src/Kconfig.projbuild delete mode 100644 examples/espidf-aws-iot/src/certs/README.md delete mode 100644 examples/espidf-aws-iot/src/certs/aws-root-ca.pem delete mode 100644 examples/espidf-aws-iot/src/certs/certificate.pem.crt delete mode 100644 examples/espidf-aws-iot/src/certs/private.pem.key delete mode 100644 examples/espidf-aws-iot/src/subscribe_publish_sample.c delete mode 100644 examples/espidf-aws-iot/test/README diff --git a/examples/espidf-aws-iot/.gitignore b/examples/espidf-aws-iot/.gitignore deleted file mode 100644 index 03f4a3c19..000000000 --- a/examples/espidf-aws-iot/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/espidf-aws-iot/.travis.yml b/examples/espidf-aws-iot/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-aws-iot/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-aws-iot/CMakeLists.txt b/examples/espidf-aws-iot/CMakeLists.txt deleted file mode 100644 index 61f45be84..000000000 --- a/examples/espidf-aws-iot/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(subscribe_publish) diff --git a/examples/espidf-aws-iot/README.md b/examples/espidf-aws-iot/README.md deleted file mode 100644 index da21cb256..000000000 --- a/examples/espidf-aws-iot/README.md +++ /dev/null @@ -1,22 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell - -# Change directory to example -$ cd platform-espressif32/examples/espidf-aws-iot - -# Build project -$ pio run - -# Upload firmware -$ pio run --target upload - -# Clean build files -$ pio run --target clean -``` \ No newline at end of file diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/.gitignore b/examples/espidf-aws-iot/components/esp-aws-iot/.gitignore deleted file mode 100644 index bf8e14f7e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.o - -# Example project files -examples/**/sdkconfig -examples/**/sdkconfig.old -examples/**/build - -# AWS IoT Examples require device-specific certs/keys -examples/*/main/certs/*.pem.* diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/.gitlab-ci.yml b/examples/espidf-aws-iot/components/esp-aws-iot/.gitlab-ci.yml deleted file mode 100644 index 5536211db..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/.gitlab-ci.yml +++ /dev/null @@ -1,42 +0,0 @@ -stages: - - build - -variables: - BATCH_BUILD: "1" - V: "0" - MAKEFLAGS: "-j5 --no-keep-going" - IDF_PATH: "$CI_PROJECT_DIR/esp-idf" - -build_demo: - stage: build - image: $CI_DOCKER_REGISTRY/esp32-ci-env - tags: - - build - script: - # add gitlab ssh key - - export PATH="$IDF_PATH/tools:$PATH" - - mkdir -p ~/.ssh - - chmod 700 ~/.ssh - - echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64 - - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa - - chmod 600 ~/.ssh/id_rsa - - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config - - git --version - - git submodule update --init --recursive - - git clone --recursive --depth 1 $GITLAB_SSH_SERVER/idf/esp-idf.git - - export PATH="$IDF_PATH/tools:$PATH" - - cd esp-idf - - ./install.sh - - . export.sh - - cd .. - - cd examples/thing_shadow - - cat sdkconfig.ci >> sdkconfig.defaults - - make defconfig && make -j4 - - make clean && rm -rf build - - idf.py build - - cd ../.. - - cd examples/subscribe_publish - - cat sdkconfig.ci >> sdkconfig.defaults - - make defconfig && make -j4 - - make clean && rm -rf build - - idf.py build diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/.gitmodules b/examples/espidf-aws-iot/components/esp-aws-iot/.gitmodules deleted file mode 100644 index f75792f69..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "aws-iot-device-sdk-embedded-C"] - path = aws-iot-device-sdk-embedded-C - url = https://github.com/espressif/aws-iot-device-sdk-embedded-C.git diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/CMakeLists.txt b/examples/espidf-aws-iot/components/esp-aws-iot/CMakeLists.txt deleted file mode 100644 index 653fd191b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -set(COMPONENT_ADD_INCLUDEDIRS "port/include aws-iot-device-sdk-embedded-C/include") -set(aws_sdk_dir aws-iot-device-sdk-embedded-C/src) -set(COMPONENT_SRCS "${aws_sdk_dir}/aws_iot_jobs_interface.c" - "${aws_sdk_dir}/aws_iot_jobs_json.c" - "${aws_sdk_dir}/aws_iot_jobs_topics.c" - "${aws_sdk_dir}/aws_iot_jobs_types.c" - "${aws_sdk_dir}/aws_iot_json_utils.c" - "${aws_sdk_dir}/aws_iot_mqtt_client.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_common_internal.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_connect.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_publish.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_subscribe.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_unsubscribe.c" - "${aws_sdk_dir}/aws_iot_mqtt_client_yield.c" - "${aws_sdk_dir}/aws_iot_shadow.c" - "${aws_sdk_dir}/aws_iot_shadow_actions.c" - "${aws_sdk_dir}/aws_iot_shadow_json.c" - "${aws_sdk_dir}/aws_iot_shadow_records.c" - "port/network_mbedtls_wrapper.c" - "port/threads_freertos.c" - "port/timer.c") - -set(COMPONENT_REQUIRES "mbedtls") -set(COMPONENT_PRIV_REQUIRES "jsmn") - -register_component() diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/Kconfig b/examples/espidf-aws-iot/components/esp-aws-iot/Kconfig deleted file mode 100644 index 0e41d9689..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/Kconfig +++ /dev/null @@ -1,146 +0,0 @@ -menu "Amazon Web Services IoT Platform" - -config AWS_IOT_MQTT_HOST - string "AWS IoT Endpoint Hostname" - default "" - help - Default endpoint host name to connect to AWS IoT MQTT/S gateway - - This is the custom endpoint hostname and is specific to an AWS - IoT account. You can find it by logging into your AWS IoT - Console and clicking the Settings button. The endpoint hostname - is shown under the "Custom Endpoint" heading on this page. - - If you need per-device hostnames for different regions or - accounts, you can override the default hostname in your app. - -config AWS_IOT_MQTT_PORT - int "AWS IoT MQTT Port" - default 8883 - range 0 65535 - help - Default port number to connect to AWS IoT MQTT/S gateway - - If you need per-device port numbers for different regions, you can - override the default port number in your app. - - -config AWS_IOT_MQTT_TX_BUF_LEN - int "MQTT TX Buffer Length" - default 512 - range 32 131072 - help - Maximum MQTT transmit buffer size. This is the maximum MQTT - message length (including protocol overhead) which can be sent. - - Sending longer messages will fail. - -config AWS_IOT_MQTT_RX_BUF_LEN - int "MQTT RX Buffer Length" - default 512 - range 32 131072 - help - Maximum MQTT receive buffer size. This is the maximum MQTT - message length (including protocol overhead) which can be - received. - - Longer messages are dropped. - - - -config AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS - int "Maximum MQTT Topic Filters" - default 5 - range 1 100 - help - Maximum number of concurrent MQTT topic filters. - - -config AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - int "Auto reconnect initial interval (ms)" - default 1000 - range 10 3600000 - help - Initial delay before making first reconnect attempt, if the AWS IoT connection fails. - Client will perform exponential backoff, starting from this value. - -config AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - int "Auto reconnect maximum interval (ms)" - default 128000 - range 10 3600000 - help - Maximum delay between reconnection attempts. If the exponentially increased delay - interval reaches this value, the client will stop automatically attempting to reconnect. - -menu "Thing Shadow" - - config AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER - bool "Override Shadow RX buffer size" - default n - help - Allows setting a different Thing Shadow RX buffer - size. This is the maximum size of a Thing Shadow - message in bytes, plus one. - - If not overridden, the default value is the MQTT RX Buffer length plus one. If overriden, do not set - higher than the default value. - - config AWS_IOT_SHADOW_MAX_SIZE_OF_RX_BUFFER - int "Maximum RX Buffer (bytes)" - depends on AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER - default 513 - range 32 65536 - help - Allows setting a different Thing Shadow RX buffer size. - This is the maximum size of a Thing Shadow message in bytes, - plus one. - - - config AWS_IOT_SHADOW_MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES - int "Maximum unique client ID size (bytes)" - default 80 - range 4 1000 - help - Maximum size of the Unique Client Id. - - config AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS - int "Maximum simultaneous responses" - default 10 - range 1 100 - help - At any given time we will wait for this many responses. This will correlate to the rate at which the - shadow actions are requested - - config AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES - int "Maximum simultaneous Thing Name operations" - default 10 - range 1 100 - help - We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any - given time - - config AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED - int "Maximum expected JSON tokens" - default 120 - help - These are the max tokens that is expected to be in the Shadow JSON document. Includes the metadata which - is published - - config AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME - int "Maximum topic length (not including Thing Name)" - default 60 - range 10 1000 - help - All shadow actions have to be published or subscribed to a topic which is of the format - $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing - Name - - config AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME - int "Maximum Thing Name length" - default 20 - range 4 1000 - help - Maximum length of a Thing Name. - -endmenu # Thing Shadow -endmenu # AWS IoT diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/LICENSE b/examples/espidf-aws-iot/components/esp-aws-iot/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/README.md deleted file mode 100644 index 57b5b1619..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# ESP-AWS-IoT - -This framework enables AWS IoT cloud connectivity with ESP32 based platforms using [AWS IoT Device Embedded SDK](https://github.com/aws/aws-iot-device-sdk-embedded-C). - -## Getting Started - -- Please clone this repository using, - ``` - git clone --recursive https://github.com/espressif/esp-aws-iot - ``` -- Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html for setting ESP-IDF - - ESP-IDF can be downloaded from https://github.com/espressif/esp-idf/ - - ESP-IDF v3.1 and above is recommended version -- Please refer to [example README](examples/README.md) for more information on setting up examples diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.gitignore b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.gitignore deleted file mode 100644 index 32361d47b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -# Ignore executables -*.o -IotSdkC_tests -samples/linux/jobs_sample/jobs_sample -samples/linux/shadow_sample/shadow_sample -samples/linux/shadow_sample_console_echo/shadow_console_echo -samples/linux/subscribe_publish_library_sample/libAwsIotSdk.a -samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample -samples/linux/subscribe_publish_sample/subscribe_publish_sample -tests/integration/integration_tests_mbedtls -tests/integration/integration_tests_mbedtls_mt - -# Ignore test artifacts -objs/* -testLibs/* - -# Ignore CppUTest and mbed TLS -external_libs/CppUTest/* -external_libs/mbedTLS/* - -# Ignore credentials -certs/* diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.travis.yml b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.travis.yml deleted file mode 100644 index 509ccf78e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/.travis.yml +++ /dev/null @@ -1,44 +0,0 @@ -language: c - -install: - # Remove placeholders. - - rm external_libs/CppUTest/* - - rm external_libs/mbedTLS/* - - # Get mbedtls. - - wget -qO- https://github.com/ARMmbed/mbedtls/archive/mbedtls-2.16.5.tar.gz | tar xvz -C external_libs/mbedTLS --strip-components=1 - - # Get CppUTest. - - wget -qO- https://github.com/cpputest/cpputest/archive/v3.6.tar.gz | tar xvz -C external_libs/CppUTest --strip-components=1 - -script: - # Verify that the samples build. - - cd samples/linux/jobs_sample - - make -j2 - - cd ../shadow_sample - - make -j2 - - cd ../shadow_sample_console_echo - - make -j2 - - cd ../subscribe_publish_library_sample - - make -j2 - - cd ../subscribe_publish_sample - - make -j2 - - # Build and run unit tests. - - cd ../../../ - - make build-cpputest -j2 - - make all_no_tests -j2 - - ./IotSdkC_tests -v - - # Set up integration tests if not a pull request. - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then cd tests/integration; fi - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then sed -i 's/^.*#define AWS_IOT_MQTT_HOST.*$/#define AWS_IOT_MQTT_HOST "'"$AWS_IOT_ENDPOINT"'"/' include/aws_iot_config.h; fi - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then make app -j2; fi - - # Import credentials for integration tests. - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -O ../../certs/rootCA.crt; fi - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then echo -e $AWS_IOT_CLIENT_CERT > ../../certs/cert.pem; fi - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then echo -e $AWS_IOT_PRIVATE_KEY > ../../certs/privkey.pem; fi - - # Run integration tests. - - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then ./integration_tests_mbedtls; fi diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CHANGELOG.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CHANGELOG.md deleted file mode 100644 index 497128753..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CHANGELOG.md +++ /dev/null @@ -1,233 +0,0 @@ -# Change Log - -## [3.0.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v3.0.1) (May 10, 2018) - -Bugfixes: - - - [#167](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/167), [#168](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/168) Fixed issues reported by Coverity Scan. - - [#177](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/177) Fixes a memory corruption bug and handling of timeouts. - -Other: - - - Add .travis.yml for Travis CI. - - Removed C++ sample. - - Removed includes of `inttypes.h`, which doesn't exist on some systems. - - [#175](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/175) Added comments on static allocation of MQTT topics. - -## [3.0.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v3.0.0) (Apr 17, 2018) - -Bugfixes: - - - [#152](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/152) Fixes potential buffer overflows in `parseStringValue` by requiring a size parameter in `jsonStruct_t`. - - [#155](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/155) Fixes other memory corruption bugs; also improves stability. - -The two bug fixes above are not backwards compatible with v2.3.0. Please see [README.md](README.md#migrating-from-2x-to-3x) for details on migrating to v3.0.0. - -## [2.3.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.3.0) (Mar 21, 2018) - -New Features: - - - Add [AWS IoT Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) support. - - Use AWS IoT Core support for MQTT over port 443. MQTT connection now defaults to port 443. - -Pull requests: - - - [#124](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/124) - Thing Shadow: Fix potential shadow buffer overflow - - [#135](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/135) - mbedtls_wrap: Fix unintialized variable usage - - Fix bugs in long-running integration tests. - -## [2.2.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.2.1) (Dec 26, 2017) - -Bugfixes: - - - [#115](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/115) - Issue with new client metrics - -Pull requests: - - - [#112](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/112) - Initialize msqParams.isRetained to 0 in publishToShadowAction() - - [#118](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/118) - mqttInitParams.mqttPacketTimeout_ms initialized - -## [2.2.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.2.0) (Nov 22, 2017) - -New Features: - - - Added SDK metrics string into connect packet - -Bugfixes: - - - [#49](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/49) - Add support for SHADOW_JSON_STRING as supported value - - [#57](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/57) - remove unistd.h - - [#58](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/58) - Fix return type of aws_iot_mqtt_internal_is_topic_matched - - [#59](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/95) - Fix extraneous assignment - - [#62](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/62) - Clearing SubscriptionList entries in shadowActionAcks after subscription failure - - [#63](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/63) - Stack overflow when IOT_DEBUG is enabled - - [#66](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/66) - Bug in send packet function - - [#69](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/69) - Fix for broken deleteActionHandler in shadow API - - [#71](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/71) - Prevent messages on /update/accepted from incrementing shadowJsonVersionNum in delta - - [#73](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/73) - wait for all messages to be received in subscribe publish sample - - [#96](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/96) - destroy TLS instance even if disconnect send fails - - Fix for aws_iot_mqtt_resubscribe not properly resubscribing to all topics - - Update MbedTLS Network layer Readme to remove specific version link - - Fix for not Passing througheError code on aws_iot_shadow_connect failure - - Allow sending of SHADOW_JSON_OBJECT to the shadow - - Ignore delta token callback for metadata - - Fix infinite publish exiting early in subscribe publish sample - -Improvements: - - - Updated jsmn to latest commit - - Change default keepalive interval to 600 seconds - -Pull requests: - - - [#29](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/29) - three small fixes - - [#59](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/59) - Fixed MQTT header constructing and parsing - - [#88](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/88) - Fix username and password are confused - - [#78](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/78) - Fixed compilation warnings - - [#102](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/102) - Corrected markdown headers - - [#105](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/105) - Fixed warnings when compiling - -## [2.1.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.1.1) (Sep 5, 2016) - -Bugfixes/Improvements: - - - Network layer interface improvements to address reported issues - - Incorporated GitHub pull request [#41](https://github.com/aws/aws-iot-device-sdk-embedded-c/pull/41) - - Bugfixes for issues [#36](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/36) and [#33](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/33) - -## [2.1.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.1.0) (Jun 15, 2016) - -New features: - - - Added unit tests, further details can be found in the testing readme [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/README.md/) - - Added sample to demonstrate building the SDK as library - - Added sample to demonstrate building the SDK in C++ - -Bugfixes/Improvements: - - - Increased default value of Maximum Reconnect Wait interval to 128 secs - - Increased default value of MQTT Command Timeout in Shadow Connect to 20 secs - - Shadow null/length checks - - Client Id Length not passed correctly in shadow connect - - Add extern C to headers and source files, added sample to demonstrate usage with C++ - - Delete/Accepted not being reported, callback added for delete/accepted - - Append IOT_ to all Debug macros (eg. DEBUG is now IOT_DEBUG) - - Fixed exit on error for subscribe_publish_sample - -## [2.0.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v2.0.0) (April 28, 2016) - -New features: - - - Refactored API to make it instance specific. This is a breaking change in the API from 1.x releases because a Client Instance parameter had to be added to all APIs - - Added Threading library porting layer wrapper - - Added support for multiple connections from one application - - Shadows and connections de-linked, connection needs to be set up separately, can be used independently of shadow - - Added integration tests for testing SDK functionality - -Bugfixes/Improvements: - - - Yield cannot be called again while waiting for application callback to return - - Fixed issue with TLS layer handles not being cleaned up properly on connection failure reported [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/16) - - Renamed timer_linux.h to timer_platform.h as requested [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/5) - - Adds support for disconnect handler to shadow. A similar pull request can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/9) - - New SDK folder structure, cleaned and simplified code structure - - Removed Paho Wrapper, Merge MQTT into SDK code, added specific error codes - - Refactored Network and Timer layer wrappers, added specific error codes - - Refactored samples and makefiles - -## [1.1.2](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.1.2) (April 22, 2016) - -Bugfixes/Improvements: - - - Signature mismatch in MQTT library file fixed - - Makefiles have a protective target on the top to prevent accidental execution - -## [1.1.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.1.1) (April 1, 2016) - -Bugfixes/Improvements: - - - Removing the Executable bit from all the files in the repository. Fixing [this](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues/14) issue - - Refactoring MQTT client to remove declaration after statement warnings - - Fixing [this](https://forums.aws.amazon.com/thread.jspa?threadID=222467&tstart=0) bug - - -## [1.1.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.1.0) (February 10, 2016) -Features: - - - Auto Reconnect and Resubscribe - -Bugfixes/Improvements: - - - MQTT buffer handling incase of bigger message - - Large timeout values converted to seconds and milliseconds - - Dynamic loading of Shadow parameters. Client ID and Thing Name are not hard-coded - - MQTT Library refactored - - -## [1.0.1](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.0.1) (October 21, 2015) - -Bugfixes/Improvements: - - - Paho name changed to Eclipse Paho - - Renamed the Makefiles in the samples directory - - Device Shadow - Delete functionality macro fixed - - `subscribe_publish_sample` updated - -## [1.0.0](https://github.com/aws/aws-iot-device-sdk-embedded-C/releases/tag/v1.0.0) (October 8, 2015) - -Features: - - - Release to github - - SDK tarballs made available for public download - -Bugfixes/Improvements: - - Updated API documentation - -## 0.4.0 (October 5, 2015) - -Features: - - - Thing Shadow Actions - Update, Delete, Get for any Thing Name - - aws_iot_config.h file for easy configuration of parameters - - Sample app for talking with console's Interactive guide - - disconnect handler for the MQTT client library - -Bugfixes/Improvements: - - - mbedTLS read times out every 10 ms instead of hanging for ever - - mbedTLS handshake failure handled - -## 0.3.0 (September 14, 2015) - -Features: - - - Testing with mbedTLS, prepping for relase - -Bugfixes/Improvements: - - - Refactored to break out timer and network interfaces - -## 0.2.0 (September 2, 2015) - -Features: - - - Added initial Shadow implementation + example - - Added hostname verification to OpenSSL example - - Added iot_log interface - - Initial API Docs (Doxygen) - -Bugfixes/Improvements: - - - Fixed yield timeout - - Refactored APIs to pass by reference vs value - -## 0.1.0 (August 12, 2015) - -Features: - - - Initial beta release - - MQTT Publish and Subscribe - - TLS mutual auth on linux with OpenSSL - -Bugfixes/Improvements: - - N/A diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CODE_OF_CONDUCT.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CODE_OF_CONDUCT.md deleted file mode 100644 index 3b6446687..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,4 +0,0 @@ -## Code of Conduct -This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). -For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact -opensource-codeofconduct@amazon.com with any additional questions or comments. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CONTRIBUTING.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CONTRIBUTING.md deleted file mode 100644 index eb63eaed2..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CONTRIBUTING.md +++ /dev/null @@ -1,61 +0,0 @@ -# Contributing Guidelines - -Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional -documentation, we greatly value feedback and contributions from our community. - -Please read through this document before submitting any issues or pull requests to ensure we have all the necessary -information to effectively respond to your bug report or contribution. - - -## Reporting Bugs/Feature Requests - -We welcome you to use the GitHub issue tracker to report bugs or suggest features. - -When filing an issue, please check [existing open](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues), or [recently closed](https://github.com/aws/aws-iot-device-sdk-embedded-C/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already -reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: - -* A reproducible test case or series of steps -* The version of our code being used -* Any modifications you've made relevant to the bug -* Anything unusual about your environment or deployment - - -## Contributing via Pull Requests -Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: - -1. You are working against the latest source on the *master* branch. -2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. -3. You open an issue to discuss any significant work - we would hate for your time to be wasted. - -To send us a pull request, please: - -1. Fork the repository. -2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. -3. Ensure local tests pass. -4. Commit to your fork using clear commit messages. -5. Send us a pull request, answering any default questions in the pull request interface. -6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. - -GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and -[creating a pull request](https://help.github.com/articles/creating-a-pull-request/). - - -## Finding contributions to work on -Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws/aws-iot-device-sdk-embedded-C/labels/help%20wanted) issues is a great place to start. - - -## Code of Conduct -This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). -For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact -opensource-codeofconduct@amazon.com with any additional questions or comments. - - -## Security issue notifications -If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. - - -## Licensing - -See the [LICENSE](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. - -We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CppUTestMakefileWorker.mk b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CppUTestMakefileWorker.mk deleted file mode 100644 index 9f3c3054f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/CppUTestMakefileWorker.mk +++ /dev/null @@ -1,575 +0,0 @@ -#--------- -# -# MakefileWorker.mk -# -# Include this helper file in your makefile -# It makes -# A static library -# A test executable -# -# See this example for parameter settings -# examples/Makefile -# -#---------- -# Inputs - these variables describe what to build -# -# INCLUDE_DIRS - Directories used to search for include files. -# This generates a -I for each directory -# SRC_DIRS - Directories containing source file to built into the library -# SRC_FILES - Specific source files to build into library. Helpful when not all code -# in a directory can be built for test (hopefully a temporary situation) -# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner -# These do not go in a library. They are explicitly included in the test runner -# TEST_SRC_FILES - Specific source files to build into the unit test runner -# These do not go in a library. They are explicitly included in the test runner -# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner -# These do not go in a library. They are explicitly included in the test runner -#---------- -# You can adjust these variables to influence how to build the test target -# and where to put and name outputs -# See below to determine defaults -# COMPONENT_NAME - the name of the thing being built -# TEST_TARGET - name the test executable. By default it is -# $(COMPONENT_NAME)_tests -# Helpful if you want 1 > make files in the same directory with different -# executables as output. -# CPPUTEST_HOME - where CppUTest home dir found -# TARGET_PLATFORM - Influences how the outputs are generated by modifying the -# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the -# normal objs and lib directories. Also modifies where to search for the -# CPPUTEST_LIB to link against. -# CPPUTEST_OBJS_DIR - a directory where o and d files go -# CPPUTEST_LIB_DIR - a directory where libs go -# CPPUTEST_ENABLE_DEBUG - build for debug -# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete -# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out -# of the test harness -# CPPUTEST_USE_GCOV - Turn on coverage analysis -# Clean then build with this flag set to Y, then 'make gcov' -# CPPUTEST_MAPFILE - generate a map file -# CPPUTEST_WARNINGFLAGS - overly picky by default -# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make -# other targets. Like CSlim, which is part of fitnesse -# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user -# specification of source files and directories that aren't below -# the user's Makefile in the directory tree, like: -# SRC_DIRS += ../../lib/foo -# It defaults to N, and shouldn't be necessary except in the above case. -#---------- -# -# Other flags users can initialize to sneak in their settings -# CPPUTEST_CXXFLAGS - flags for the C++ compiler -# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor -# CPPUTEST_CFLAGS - flags for the C complier -# CPPUTEST_LDFLAGS - Linker flags -#---------- - -# Some behavior is weird on some platforms. Need to discover the platform. - -# Platforms -UNAME_OUTPUT = "$(shell uname -a)" -MACOSX_STR = Darwin -MINGW_STR = MINGW -CYGWIN_STR = CYGWIN -LINUX_STR = Linux -SUNOS_STR = SunOS -UNKNWOWN_OS_STR = Unknown - -# Compilers -CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)" -CLANG_STR = clang -SUNSTUDIO_CXX_STR = SunStudio - -UNAME_OS = $(UNKNWOWN_OS_STR) - -ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR)) - UNAME_OS = $(MINGW_STR) -endif - -ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR)) - UNAME_OS = $(CYGWIN_STR) -endif - -ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR)) - UNAME_OS = $(LINUX_STR) -endif - -ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR)) - UNAME_OS = $(MACOSX_STR) -#lion has a problem with the 'v' part of -a - UNAME_OUTPUT = "$(shell uname -pmnrs)" -endif - -ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR)) - UNAME_OS = $(SUNOS_STR) - - SUNSTUDIO_CXX_ERR_STR = CC -flags -ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR)) - CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)" - COMPILER_NAME = $(SUNSTUDIO_CXX_STR) -endif -endif - -ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR)) - COMPILER_NAME = $(CLANG_STR) -endif - -#Kludge for mingw, it does not have cc.exe, but gcc.exe will do -ifeq ($(UNAME_OS),$(MINGW_STR)) - CC := gcc -endif -# RHEL5 is always going to use GCC, CC is going for the old verison -CC := gcc -#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the -# Standard C++ library as a shared library. Unbelievable. -ifeq ($(UNAME_OS),$(MINGW_STR)) - CPPUTEST_LDFLAGS += -static -endif -ifeq ($(UNAME_OS),$(CYGWIN_STR)) - CPPUTEST_LDFLAGS += -static -endif - - -#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic -ifeq ($(UNAME_OS),$(MACOSX_STR)) -ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9) - CPPUTEST_PEDANTIC_ERRORS = N -endif -endif - -ifndef COMPONENT_NAME - COMPONENT_NAME = name_this_in_the_makefile -endif - -# Debug on by default -ifndef CPPUTEST_ENABLE_DEBUG - CPPUTEST_ENABLE_DEBUG = Y -endif - -# new and delete for memory leak detection on by default -ifndef CPPUTEST_USE_MEM_LEAK_DETECTION - CPPUTEST_USE_MEM_LEAK_DETECTION = Y -endif - -# Use the standard C library -ifndef CPPUTEST_USE_STD_C_LIB - CPPUTEST_USE_STD_C_LIB = Y -endif - -# Use the standard C++ library -ifndef CPPUTEST_USE_STD_CPP_LIB - CPPUTEST_USE_STD_CPP_LIB = Y -endif - -# Use gcov, off by default -ifndef CPPUTEST_USE_GCOV - CPPUTEST_USE_GCOV = N -endif - -ifndef CPPUTEST_PEDANTIC_ERRORS - CPPUTEST_PEDANTIC_ERRORS = Y -endif - -# Default warnings -ifndef CPPUTEST_WARNINGFLAGS - CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wswitch-default -Wswitch-enum -Wconversion -ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y) - CPPUTEST_WARNINGFLAGS += -pedantic-errors -endif -ifeq ($(UNAME_OS),$(LINUX_STR)) -# CPPUTEST_WARNINGFLAGS += -Wsign-conversion -endif - CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual - CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes -endif - -#Wonderful extra compiler warnings with clang -ifeq ($(COMPILER_NAME),$(CLANG_STR)) -# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that. -# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit) -# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor -# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled. - CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables - CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded -endif - -# Uhm. Maybe put some warning flags for SunStudio here? -ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR)) - CPPUTEST_CXX_WARNINGFLAGS = - CPPUTEST_C_WARNINGFLAGS = -endif - -# Default dir for temporary files (d, o) -ifndef CPPUTEST_OBJS_DIR -ifndef TARGET_PLATFORM - CPPUTEST_OBJS_DIR = objs -else - CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM) -endif -endif - -# Default dir for the output library -ifndef CPPUTEST_LIB_DIR -ifndef TARGET_PLATFORM - CPPUTEST_LIB_DIR = testLibs -else - CPPUTEST_LIB_DIR = testLibs/$(TARGET_PLATFORM) -endif -endif - -# No map by default -ifndef CPPUTEST_MAP_FILE - CPPUTEST_MAP_FILE = N -endif - -# No extentions is default -ifndef CPPUTEST_USE_EXTENSIONS - CPPUTEST_USE_EXTENSIONS = N -endif - -# No VPATH is default -ifndef CPPUTEST_USE_VPATH - CPPUTEST_USE_VPATH := N -endif -# Make empty, instead of 'N', for usage in $(if ) conditionals -ifneq ($(CPPUTEST_USE_VPATH), Y) - CPPUTEST_USE_VPATH := -endif - -ifndef TARGET_PLATFORM -CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_BUILD_LIB) -else -CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_BUILD_LIB)/$(TARGET_PLATFORM) -endif - -# -------------------------------------- -# derived flags in the following area -# -------------------------------------- - -# Without the C library, we'll need to disable the C++ library and ... -ifeq ($(CPPUTEST_USE_STD_C_LIB), N) - CPPUTEST_USE_STD_CPP_LIB = N - CPPUTEST_USE_MEM_LEAK_DETECTION = N - CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED - CPPUTEST_CPPFLAGS += -nostdinc -endif - -CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION - -ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N) - CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED -else - ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE - CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_INCLUDE)/CppUTest/MemoryLeakDetectorNewMacros.h - endif - ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE - CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_INCLUDE)/CppUTest/MemoryLeakDetectorMallocMacros.h - endif -endif - -ifeq ($(CPPUTEST_ENABLE_DEBUG), Y) - CPPUTEST_CXXFLAGS += -g - CPPUTEST_CFLAGS += -g - CPPUTEST_LDFLAGS += -g -endif - -ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N) - CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED -ifeq ($(CPPUTEST_USE_STD_C_LIB), Y) - CPPUTEST_CXXFLAGS += -nostdinc++ -endif -endif - -ifdef $(GMOCK_HOME) - GTEST_HOME = $(GMOCK_HOME)/gtest - CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include - GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a - LD_LIBRARIES += $(GMOCK_LIBRARY) - CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS - CPPUTEST_WARNINGFLAGS = - CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME) - GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a - LD_LIBRARIES += $(GTEST_LIBRARY) -endif - - -ifeq ($(CPPUTEST_USE_GCOV), Y) - CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage - CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage -endif - -CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS) -CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS) -CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE) -CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE) -CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS) - -TARGET_MAP = $(COMPONENT_NAME).map.txt -ifeq ($(CPPUTEST_MAP_FILE), Y) - CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP) -endif - -# Link with CppUTest lib -CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a - -ifeq ($(CPPUTEST_USE_EXTENSIONS), Y) -CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a -endif - -ifdef CPPUTEST_STATIC_REALTIME - LD_LIBRARIES += -lrt -endif - -TARGET_LIB = \ - $(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a - -ifndef TEST_TARGET - ifndef TARGET_PLATFORM - TEST_TARGET = $(COMPONENT_NAME)_tests - else - TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests - endif -endif - -#Helper Functions -get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c) -get_dirs_from_dirspec = $(wildcard $1) -get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir))) -__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2)))) -src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2)) -src_to_o = $(call src_to,.o,$1) -src_to_d = $(call src_to,.d,$1) -src_to_gcda = $(call src_to,.gcda,$1) -src_to_gcno = $(call src_to,.gcno,$1) -time = $(shell date +%s) -delta_t = $(eval minus, $1, $2) -debug_print_list = $(foreach word,$1,echo " $(word)";) echo; - -#Derived -STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP) - -SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES) -OBJ = $(call src_to_o,$(SRC)) - -STUFF_TO_CLEAN += $(OBJ) - -TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES) -TEST_OBJS = $(call src_to_o,$(TEST_SRC)) -STUFF_TO_CLEAN += $(TEST_OBJS) - - -MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS)) -MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC)) -STUFF_TO_CLEAN += $(MOCKS_OBJS) - -ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC) - -# If we're using VPATH -ifeq ($(CPPUTEST_USE_VPATH), Y) -# gather all the source directories and add them - VPATH += $(sort $(dir $(ALL_SRC))) -# Add the component name to the objs dir path, to differentiate between same-name objects - CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR)) -endif - -#LCOV html generation -BUILD_OUTPUT_DIR=build_output -COVERAGE_DIR=$(BUILD_OUTPUT_DIR)/generated-coverage -LCOV_INFO_FILE=$(TEST_TARGET).info -LCOV_SUMMARY_FILE=$(TEST_TARGET)_summary.info - -#Test coverage with gcov -GCOV_OUTPUT = gcov_output.txt -GCOV_REPORT = gcov_report.txt -GCOV_ERROR = gcov_error.txt -GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC)) -GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC)) -TEST_OUTPUT = $(TEST_TARGET).txt -STUFF_TO_CLEAN += \ - $(GCOV_OUTPUT)\ - $(GCOV_REPORT)\ - $(GCOV_REPORT).html\ - $(GCOV_ERROR)\ - $(GCOV_GCDA_FILES)\ - $(GCOV_GCNO_FILES)\ - $(TEST_OUTPUT) - -#The gcda files for gcov need to be deleted before each run -#To avoid annoying messages. -GCOV_CLEAN = $(SILENCE)$(RM) -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR) -RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) - -ifeq ($(CPPUTEST_USE_GCOV), Y) - - ifeq ($(COMPILER_NAME),$(CLANG_STR)) - LD_LIBRARIES += --coverage - else - LD_LIBRARIES += -lgcov - endif -endif - - -INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS)) -INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir)) -MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS)) -INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir)) - -CPPUTEST_CPPFLAGS += $(INCLUDES) - -DEP_FILES = $(call src_to_d, $(ALL_SRC)) -STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END) -STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output - -# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags -CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS) -CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS) -CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS) -LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS) - -# Don't consider creating the archive a warning condition that does STDERR output -ARFLAGS := $(ARFLAGS)c - -DEP_FLAGS=-MMD -MP - -# Some macros for programs to be overridden. For some reason, these are not in Make defaults -RANLIB = ranlib - -# Targets - -ALL_TARGETS += cpputest_all -ALL_TARGETS_CLEAN += cpputest_clean -.PHONY: cpputest_all -cpputest_all: start $(TEST_TARGET) gcov - $(RUN_TEST_TARGET) - -.PHONY: start -start: $(TEST_TARGET) - $(SILENCE)START_TIME=$(call time) - -.PHONY: all_no_tests -all_no_tests: $(TEST_TARGET) - -.PHONY: flags -flags: - @echo - @echo "OS ${UNAME_OS}" - @echo "Compile C and C++ source with CPPFLAGS:" - @$(call debug_print_list,$(CPPFLAGS)) - @echo "Compile C++ source with CXXFLAGS:" - @$(call debug_print_list,$(CXXFLAGS)) - @echo "Compile C source with CFLAGS:" - @$(call debug_print_list,$(CFLAGS)) - @echo "Link with LDFLAGS:" - @$(call debug_print_list,$(LDFLAGS)) - @echo "Link with LD_LIBRARIES:" - @$(call debug_print_list,$(LD_LIBRARIES)) - @echo "Create libraries with ARFLAGS:" - @$(call debug_print_list,$(ARFLAGS)) - -TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START) -test-deps: $(TEST_DEPS) - -$(TEST_TARGET): $(TEST_DEPS) - @echo Linking $@ - $(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS) - -$(TARGET_LIB): $(OBJ) - @echo Building archive $@ - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(AR) $(ARFLAGS) $@ $^ - $(SILENCE)$(RANLIB) $@ - -test: $(TEST_TARGET) - $(RUN_TEST_TARGET) $(COMMAND_LINE_ARGUMENTS) | tee $(TEST_OUTPUT) -vtest: $(TEST_TARGET) - $(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT) - -$(CPPUTEST_OBJS_DIR)/%.o: %.cc - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -$(CPPUTEST_OBJS_DIR)/%.o: %.cpp - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -$(CPPUTEST_OBJS_DIR)/%.o: %.c - @echo compiling $(notdir $<) - $(SILENCE)mkdir -p $(dir $@) - $(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $< - -ifneq "$(MAKECMDGOALS)" "clean" --include $(DEP_FILES) -endif - -.PHONY: cpputest_clean -cpputest_clean: - @echo Making clean - $(SILENCE)$(RM) $(STUFF_TO_CLEAN) - $(SILENCE)$(RM) -rf gcov $(CPPUTEST_OBJS_DIR) - $(SILENCE)find . -name "*.gcno" | xargs $(RM) -f - $(SILENCE)find . -name "*.gcda" | xargs $(RM) -f - -#realclean gets rid of all gcov, o and d files in the directory tree -#not just the ones made by this makefile -.PHONY: realclean -realclean: clean - $(SILENCE)$(RM) -rf gcov - $(SILENCE)$(RM) -rf $(BUILD_OUTPUT_DIR) - $(SILENCE)find . -name "*.gdcno" | xargs $(RM) -f - $(SILENCE)find . -name "*.[do]" | xargs $(RM) -f - -gcov: test - $(SILENCE)mkdir -p $(BUILD_OUTPUT_DIR) -ifeq ($(CPPUTEST_USE_VPATH), Y) - $(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR) -else - $(SILENCE)for d in $(SRC_DIRS) ; do \ - FILES=`ls $$d/*.c $$d/*.cc $$d/*.cpp 2> /dev/null` ; \ - gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$FILES >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ - done - $(SILENCE)for f in $(SRC_FILES) ; do \ - gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \ - done -endif - $(SILENCE)./filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT) - $(SILENCE)mkdir -p gcov - $(SILENCE)mv *.gcov gcov - $(SILENCE)mv gcov_* gcov - $(SILENCE)mkdir -p $(COVERAGE_DIR) - $(SILENCE)lcov -d $(CPPUTEST_OBJS_DIR) -c -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE) -q --rc lcov_branch_coverage=1 - $(SILENCE)lcov --remove $(COVERAGE_DIR)/$(LCOV_INFO_FILE) $(LCOV_EXCLUDE_PATTERN) -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE) - $(SILENCE)lcov --remove $(COVERAGE_DIR)/$(LCOV_INFO_FILE) "*CppUTest*" -o $(COVERAGE_DIR)/$(LCOV_INFO_FILE) - $(SILENCE)lcov --summary ./$(COVERAGE_DIR)/$(LCOV_INFO_FILE) &> $(COVERAGE_DIR)/$(LCOV_SUMMARY_FILE) - $(SILENCE)echo ansic:line:`grep -E -o "([0-9]*\.[0-9]+|[0-9]+)" $(COVERAGE_DIR)/$(LCOV_SUMMARY_FILE) | head -1` >> $(COVERAGE_DIR)/coverage-data.txt - $(SILENCE)genhtml -o $(COVERAGE_DIR) $(COVERAGE_DIR)/$(LCOV_INFO_FILE) -q --rc lcov_branch_coverage=1 - @echo "See gcov directory for details" - -.PHONEY: format -format: - $(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR) - -.PHONEY: debug -debug: - @echo - @echo "Target Source files:" - @$(call debug_print_list,$(SRC)) - @echo "Target Object files:" - @$(call debug_print_list,$(OBJ)) - @echo "Test Source files:" - @$(call debug_print_list,$(TEST_SRC)) - @echo "Test Object files:" - @$(call debug_print_list,$(TEST_OBJS)) - @echo "Mock Source files:" - @$(call debug_print_list,$(MOCKS_SRC)) - @echo "Mock Object files:" - @$(call debug_print_list,$(MOCKS_OBJS)) - @echo "All Input Dependency files:" - @$(call debug_print_list,$(DEP_FILES)) - @echo Stuff to clean: - @$(call debug_print_list,$(STUFF_TO_CLEAN)) - @echo Includes: - @$(call debug_print_list,$(INCLUDES)) - --include $(OTHER_MAKEFILE_TO_INCLUDE) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/LICENSE.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/LICENSE.txt deleted file mode 100644 index 1b6cbea0c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/LICENSE.txt +++ /dev/null @@ -1,120 +0,0 @@ -############################################################################################################################# - - -Apache License -Version 2.0, January 2004 - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. -"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. -"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. -"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. -"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. -"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. -"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. -"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). -"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. -"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. -2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. -3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. -4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: - 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and - 2. You must cause any modified files to carry prominent notices stating that You changed the files; and - 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and - 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. -You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. -5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. -6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. -7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. -8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. -9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - - -############################################################################################################################# - - -Components are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - - -############################################################################################################################# - - -Copyright (C) 2012, iSEC Partners. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -############################################################################################################################# - - _ _ ____ _ - Project ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - -Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - -This software is licensed as described in the file COPYING, which -you should have received as part of this distribution. The terms -are also available at http://curl.haxx.se/docs/copyright.html. - -You may opt to use, copy, modify, merge, publish, distribute and/or sell -copies of the Software, and permit persons to whom the Software is -furnished to do so, under the terms of the COPYING file. - -This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -KIND, either express or implied. - - -############################################################################################################################# - - -Copyright (c) 2010 Serge A. Zaitsev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -############################################################################################################################# - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/Makefile deleted file mode 100644 index 4f37f9219..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/Makefile +++ /dev/null @@ -1,131 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -#Set this to @ to keep the makefile quiet -ifndef SILENCE - SILENCE = @ -endif - -CC = gcc -RM = rm - -DEBUG = - -#--- Inputs ----# -COMPONENT_NAME = IotSdkC - -ALL_TARGETS := build-cpputest -ALL_TARGETS_CLEAN := - -CPPUTEST_USE_EXTENSIONS = Y -CPP_PLATFORM = Gcc -CPPUTEST_CFLAGS += -std=gnu99 -CPPUTEST_LDFLAGS += -lpthread -CPPUTEST_CFLAGS += -D__USE_BSD -CPPUTEST_USE_GCOV = Y - -#IoT client directory -IOT_CLIENT_DIR = . - -APP_DIR = $(IOT_CLIENT_DIR)/tests/unit -APP_NAME = aws_iot_sdk_unit_tests -APP_SRC_FILES = $(shell find $(APP_DIR)/src -name '*.cpp') -APP_SRC_FILES += $(shell find $(APP_DIR)/src -name '*.c') -APP_INCLUDE_DIRS = -I $(APP_DIR)/include - -CPPUTEST_DIR = $(IOT_CLIENT_DIR)/external_libs/CppUTest - -# Provide paths for CppUTest to run Unit Tests otherwise build will fail -ifndef CPPUTEST_INCLUDE - CPPUTEST_INCLUDE = $(CPPUTEST_DIR)/include -endif - -ifndef CPPUTEST_BUILD_LIB - CPPUTEST_BUILD_LIB = $(CPPUTEST_DIR) -endif - -CPPUTEST_LDFLAGS += -ldl $(CPPUTEST_BUILD_LIB)/libCppUTest.a - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux - -#MbedTLS directory -TEMP_MBEDTLS_SRC_DIR = $(APP_DIR)/tls_mock -TLS_LIB_DIR = $(TEMP_MBEDTLS_SRC_DIR) -TLS_INCLUDE_DIR = -I $(TEMP_MBEDTLS_SRC_DIR) - -# Logging level control -#LOG_FLAGS += -DENABLE_IOT_DEBUG -#LOG_FLAGS += -DENABLE_IOT_TRACE -#LOG_FLAGS += -DENABLE_IOT_INFO -#LOG_FLAGS += -DENABLE_IOT_WARN -#LOG_FLAGS += -DENABLE_IOT_ERROR -COMPILER_FLAGS += $(LOG_FLAGS) - -EXTERNAL_LIBS += -L$(CPPUTEST_BUILD_LIB) - -#IoT client directory -PLATFORM_COMMON_DIR = $(PLATFORM_DIR)/common - -IOT_INCLUDE_DIRS = -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn - -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn/ -name '*.c') - -#Aggregate all include and src directories -INCLUDE_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_DIRS += $(APP_INCLUDE_DIRS) -INCLUDE_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_DIRS += $(CPPUTEST_INCLUDE) - -TEST_SRC_DIRS = $(APP_DIR)/src - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) -PRE_MAKE_CMDS = cd $(CPPUTEST_DIR) && -PRE_MAKE_CMDS += cmake CMakeLists.txt && -PRE_MAKE_CMDS += make && -PRE_MAKE_CMDS += cd - && -PRE_MAKE_CMDS += pwd && -PRE_MAKE_CMDS += cp -f $(CPPUTEST_DIR)/src/CppUTest/libCppUTest.a $(CPPUTEST_DIR)/libCppUTest.a && -PRE_MAKE_CMDS += cp -f $(CPPUTEST_DIR)/src/CppUTestExt/libCppUTestExt.a $(CPPUTEST_DIR)/libCppUTestExt.a - -# Using TLS Mock for running Unit Tests -MOCKS_SRC += $(APP_DIR)/tls_mock/aws_iot_tests_unit_mock_tls_params.c -MOCKS_SRC += $(APP_DIR)/tls_mock/aws_iot_tests_unit_mock_tls.c - -ISYSTEM_HEADERS += $(IOT_ISYSTEM_HEADERS) -CPPUTEST_CPPFLAGS += $(ISYSTEM_HEADERS) -CPPUTEST_CPPFLAGS += $(LOG_FLAGS) - -LCOV_EXCLUDE_PATTERN = "tests/unit/*" -LCOV_EXCLUDE_PATTERN += "tests/integration/*" -LCOV_EXCLUDE_PATTERN += "external_libs/*" - -#use this section for running a specific group of tests, comment this to run all -#ONLY FOR TESTING PURPOSE -#COMMAND_LINE_ARGUMENTS += -g CommonTests -#COMMAND_LINE_ARGUMENTS += -v - -build-cpputest: - $(PRE_MAKE_CMDS) - -include CppUTestMakefileWorker.mk - -.PHONY: run-unit-tests -run-unit-tests: $(ALL_TARGETS) - @echo $(ALL_TARGETS) - -.PHONY: clean -clean: - $(MAKE) -C $(CPPUTEST_DIR) clean - $(RM) -rf build_output - $(RM) -rf gcov - $(RM) -rf objs - $(RM) -rf testLibs diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/NOTICE.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/NOTICE.txt deleted file mode 100644 index c3f856f11..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/NOTICE.txt +++ /dev/null @@ -1,16 +0,0 @@ -AWS C SDK for Internet of Things Service -Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - -This product includes software developed by -Amazon Inc (http://www.amazon.com/). - -********************** -THIRD PARTY COMPONENTS -********************** -This software includes third party software subject to the following licensing: -- Embedded C MQTT Client - From the Eclipse Paho Project - EPL v1.0 -- mbedTLS (external library, included in tarball or downloaded separately) - Apache 2.0 -- jsmn (JSON Parsing) - MIT -- cURL (hostname verification) - MIT - -The licenses for these third party components are included in LICENSE.txt diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/PortingGuide.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/PortingGuide.md deleted file mode 100644 index 2ca5f8d8c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/PortingGuide.md +++ /dev/null @@ -1,145 +0,0 @@ -# Porting Guide - -## Scope -The scope of this document is to provide instructions to modify the provided source files and functions in this SDK to run in a variety of embedded C–based environments (e.g. real-time OS, embedded Linux) and to be adjusted to use a specific TLS implementation as available with specific hardware platforms. - -## Contents of the SDK - -The C-code files of this SDK are delivered via the following directory structure (see comment behind folder name for an explanation of its content). - -Current SDK Directory Layout (mbedTLS) - -|--`certs` (Private key, device certificate and Root CA)
-|--`docs` (Developer guide & API documentation)
-|--`external_libs` (external libraries - jsmn, mbedTLS)
-|--`include` (Header files of the AWS IoT device SDK)
-|--`src` (Source files of the AWS IoT device SDK)
-|--`platform` (Platform specific files)
-|--`samples` (Samples including makefiles for building on mbedTLS)
-|--`tests` (Tests for verifying SDK is functioning as expected)
- -All makefiles in this SDK were configured using the documented folder structure above, so moving or renaming folders will require modifications to makefiles. - -## Explanation of folders and their content - - * `certs` : This directory is initially empty and will need to contain the private key, the client certificate and the root CA. The client certificate and private key can be downloaded from the AWS IoT console or be created using the AWS CLI commands. The root CA can be downloaded from [Symantec](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem). - - * `docs` : SDK API and file documentation. - - * `external_libs` : The mbedTLS and jsmn source files. The jsmn source files are always present. The mbedTLS source files are only included when downloading the tarball version of the SDK. - - * `include` : This directory contains the header files that an application using the SDK needs to include. - - * `src` : This directory contains the SDK source code including the MQTT library, device shadow code and utilities. - - * `platform` : Platform specific files for timer, TLS and threading layers. Includes a reference implementation for the linux using mbedTLS and pthread. - - * `samples` : This directory contains sample applications as well as their makefiles. The samples include a simple MQTT example which publishes and subscribes to the AWS IoT service as well as a device shadow example that shows example usage of the device shadow functionality. - - * `tests` : Contains tests for verifying SDK functionality. For further details please check the readme file included with the tests [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/tests/README.md/). - -## Integrating the SDK into your environment - -This section explains the API calls that need to be implemented in order for the Device SDK to run on your platform. The SDK interfaces follow the driver model where only prototypes are defined by the Device SDK itself while the implementation is delegated to the user of the SDK to adjust it to the platform in use. The following sections list the needed functionality for the device SDK to run successfully on any given platform. - -### Timer Functions - -A timer implementation is necessary to handle request timeouts (sending MQTT connect, subscribe, etc. commands) as well as connection maintenance (MQTT keep-alive pings). Timers need millisecond resolution and are polled for expiration so these can be implemented using a "milliseconds since startup" free-running counter if desired. In the synchronous sample provided with this SDK only one command will be "in flight" at one point in time plus the client's ping timer. - -Define the `Timer` Struct as in `timer_platform.h` - -`void init_timer(Timer *);` -init_timer - A timer structure is initialized to a clean state. - -`bool has_timer_expired(Timer *);` -has_timer_expired - a polling function to determine if the timer has expired. - -`void countdown_ms(Timer *, uint32_t);` -countdown_ms - set the timer to expire in x milliseconds and start the timer. - -`void countdown_sec(Timer *, uint32_t);` -countdown_sec - set the timer to expire in x seconds and start the timer. - -`uint32_t left_ms(Timer *);` -left_ms - query time in milliseconds left on the timer. - -`void delay(unsigned milliseconds)` -delay - sleep for the specified number of milliseconds. - - -### Network Functions - -In order for the MQTT client stack to be able to communicate via the TCP/IP network protocol stack using a mutually authenticated TLS connection, the following API calls need to be implemented for your platform. - -For additional details about API parameters refer to the [API documentation](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html). - -Define the `TLSDataParams` Struct as in `network_platform.h` -This is used for data specific to the TLS library being used. - -`IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t DestinationPort, uint32_t timeout_ms, bool ServerVerificationFlag);` -Initialize the network client / structure. - -`IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *TLSParams);` -Create a TLS TCP socket to the configure address using the credentials provided via the NewNetwork API call. This will include setting up certificate locations / arrays. - - -`IoT_Error_t iot_tls_write(Network*, unsigned char*, size_t, Timer *, size_t *);` -Write to the TLS network buffer. - -`IoT_Error_t iot_tls_read(Network*, unsigned char*, size_t, Timer *, size_t *);` -Read from the TLS network buffer. - -`IoT_Error_t iot_tls_disconnect(Network *pNetwork);` -Disconnect API - -`IoT_Error_t iot_tls_destroy(Network *pNetwork);` -Clean up the connection - -`IoT_Error_t iot_tls_is_connected(Network *pNetwork);` -Check if the TLS layer is still connected - -The TLS library generally provides the API for the underlying TCP socket. - - -### Threading Functions - -The MQTT client uses a state machine to control operations in multi-threaded situations. However it requires a mutex implementation to guarantee thread safety. This is not required in situations where thread safety is not important and it is disabled by default. The _ENABLE_THREAD_SUPPORT_ macro needs to be defined in aws_iot_config.h to enable this layer. You will also need to add the -lpthread linker flag for the compiler if you are using the provided reference implementation. - -For additional details about API parameters refer to the [API documentation](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html). - -Define the `IoT_Mutex_t` Struct as in `threads_platform.h` -This is used for data specific to the TLS library being used. - -`IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *);` -Initialize the mutex provided as argument. - -`IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *);` -Lock the mutex provided as argument - -`IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *);` -Unlock the mutex provided as argument. - -`IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *);` -Destroy the mutex provided as argument. - -The threading layer provides the implementation of mutexes used for thread-safe operations. - -## Time source for certificate validation - -As part of the TLS handshake the device (client) needs to validate the server certificate which includes validation of the certificate lifetime requiring that the device is aware of the actual time. Devices should be equipped with a real time clock or should be able to obtain the current time via NTP. Bypassing validation of the lifetime of a certificate is not recommended as it exposes the device to a security vulnerability, as it will still accept server certificates even when they have already has_timer_expired. - -## Integration into operating system -### Single-Threaded implementation - -The single threaded implementation implies that the sample application code (SDK + MQTT client) is called periodically by the firmware application running on the main thread. This is done by calling the function `aws_iot_mqtt_yield` (in the simple pub-sub example) and by calling `aws_iot_shadow_yield()` (in the device shadow example). In both cases the keep-alive time is set to 10 seconds. This means that the yield functions need to be called at a minimum frequency of once every 10 seconds. Note however that the `iot_mqtt_yield()` function takes care of reading incoming MQTT messages from the IoT service as well and hence should be called more frequently depending on the timing requirements of an application. All incoming messages can only be processed at the frequency at which `yield` is called. - -### Multi-Threaded implementation - -In the simple multi-threaded case the `yield` function can be moved to a background thread. Ensure this task runs at the frequency described above. In this case, depending on the OS mechanism, a message queue or mailbox could be used to proxy incoming MQTT messages from the callback to the worker task responsible for responding to or dispatching messages. A similar mechanism could be employed to queue publish messages from threads into a publish queue that are processed by a publishing task. Ensure the threading layer is enabled as the library is not thread safe otherwise. -There is a validation test for the multi-threaded implementation that can be found with the integration tests. You can find further details in the Readme for the integration tests [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/tests/integration/README.md/). We have run the validation test with 10 threads sending 500 messages each and verified to be working fine. It can be used as a reference testing application to validate whether your use case will work with multi-threading enabled. - -## Sample applications - -The sample apps in this SDK provide a working implementation for mbedTLS. They use a reference implementation for linux provided with the SDK. Threading layer is enabled in the subscribe publish sample. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/README.md deleted file mode 100644 index 2686ad6a9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/README.md +++ /dev/null @@ -1,270 +0,0 @@ -# AWS IoT Device SDK for Embedded C - -This tag [3.1.5](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/v3.1.5) contains the v3 version of AWS IoT Device SDK for Embedded C. No new features will be added to this tag; instead, only bug fixes will be made and minimally tested. - - -## Overview - -The AWS IoT device SDK for embedded C is a collection of C source files which can be used in embedded applications to securely connect to the [AWS IoT platform](http://docs.aws.amazon.com/iot/latest/developerguide/what-is-aws-iot.html). It includes transport clients **MQTT**, **TLS** implementations and examples for their use. It also supports AWS IoT specific features such as **Thing Shadow**. It is distributed in source form and intended to be built into customer firmware along with application code, other libraries and RTOS. For additional information about porting the Device SDK for embedded C onto additional platforms please refer to the [PortingGuide](./PortingGuide.md). - -## Features -The Device SDK simplifies access to the Pub/Sub functionality of the AWS IoT broker via MQTT and provide APIs to interact with Thing Shadows. The SDK has been tested to work with the AWS IoT platform to ensure best interoperability of a device with the AWS IoT platform. - -### MQTT Connection -The Device SDK provides functionality to create and maintain a mutually authenticated TLS connection over which it runs MQTT. This connection is used for any further publish operations and allow for subscribing to MQTT topics which will call a configurable callback function when these topics are received. - -### Thing Shadow -The Device SDK implements the specific protocol for Thing Shadows to retrieve, update and delete Thing Shadows adhering to the protocol that is implemented to ensure correct versioning and support for client tokens. It abstracts the necessary MQTT topic subscriptions by automatically subscribing to and unsubscribing from the reserved topics as needed for each API call. Inbound state change requests are automatically signalled via a configurable callback. - -### Jobs -The Device SDK implements features to facilitate use of the AWS Jobs service. The Jobs service can be used for device management tasks such as updating program files, rotating device certificates, or running other maintenance tasks such are restoring device settings or restarting devices. - -## Design Goals of this SDK -The embedded C SDK was specifically designed for resource constrained devices (running on micro-controllers and RTOS). - -Primary aspects are: - * Flexibility in picking and choosing functionality (reduce memory footprint) - * Static memory only (no malloc’s) - * Configurable resource usage(JSON tokens, MQTT subscription handlers, etc…) - * Can be ported to a different RTOS, uses wrappers for OS specific functions - -For more information on the Architecture of the SDK refer [here](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html) - -## Collection of Metrics -Beginning with Release v2.2.0 of the SDK, AWS collects usage metrics indicating which language and version of the SDK is being used. This allows us to prioritize our resources towards addressing issues faster in SDKs that see the most and is an important data point. However, we do understand that not all customers would want to report this data by default. In that case, the sending of usage metrics can be easily disabled by the user by setting the `DISABLE_METRICS` flag to true in the -`aws_iot_config.h` for each application. - -## How to get started ? -Ensure you understand the AWS IoT platform and create the necessary certificates and policies. For more information on the AWS IoT platform please visit the [AWS IoT developer guide](http://docs.aws.amazon.com/iot/latest/developerguide/iot-security-identity.html). - -In order to quickly get started with the AWS IoT platform, we have ported the SDK for POSIX type Operating Systems like Ubuntu, OS X and RHEL. The SDK is configured for the mbedTLS library and can be built out of the box with *GCC* using *make utility*. You'll need to download mbedTLS from the official ARMmbed repository. We recommend that you pick the latest version of 2.16 LTS release in order to have up-to-date security fixes. - -## Installation -This section explains the individual steps to retrieve the necessary files and be able to build your first application using the AWS IoT device SDK for embedded C. - -Steps: - - * Create a directory to hold your application e.g. (/home/*user*/aws_iot/my_app) - * Change directory to this new directory - * Download the SDK to device and place in the newly created directory - * Expand the tarball (tar -xf ). This will create the below directories: - * `certs` - TLS certificates directory - * `docs` - SDK API and file documentation. This folder is not present on GitHub. You can access the documentation [here](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html) - * `external_libs` - The mbedTLS and jsmn source files - * `include` - The AWS IoT SDK header files - * `platform` - Platform specific files for timer, TLS and threading layers - * `samples` - The sample applications - * `src` - The AWS IoT SDK source files - * `tests` - Contains tests for verifying that the SDK is functioning as expected. More information can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/README.md/) - * View further information on how to use the SDK in the README file for samples that can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/samples/README.md/) - -Also, for a guided example on getting started with the Thing Shadow, visit the AWS IoT Console's [Interactive Guide](https://console.aws.amazon.com/iot). - -## Porting to different platforms -As Embedded devices run on different real-time operating systems and TCP/IP stacks, it is one of the important design goals for the Device SDK to keep it portable. Please refer to the [porting guide](https://github.com/aws/aws-iot-device-sdk-embedded-C/blob/master/PortingGuide.md/) to get more information on how to make this SDK run on your devices (i.e. microcontrollers). - -## Migrating from 1.x to 2.x -The 2.x branch makes several changes to the SDK. This section provides information on what changes will be required in the client application for migrating from v1.x to 2.x. - - * The first change is in the folder structure. Client applications using the SDK now need to keep only the certs, external_libs, include, src and platform folder in their application. The folder descriptions can be found above - * All the SDK headers are in the `include` folder. These need to be added to the makefile as include directories - * The source files are in the `src` folder. These need to be added to the makefile as one of the source directories - * Similar to 1.x, the platform folder contains the platform specific headers and source files. These need to be added to the makefile as well - * The `platform/threading` folder only needs to be added if multi-threading is required, and the `_ENABLE_THREAD_SUPPORT_` macro is defined in config - * The list below provides a mapping for migrating from the major APIs used in 1.x to the new APIs: - - | Description | 1.x | 2.x | - | :---------- | :-- | :-- | - | Initializing the client | ```void aws_iot_mqtt_init(MQTTClient_t *pClient);``` | ```IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *pInitParams);``` | - | Connect | ```IoT_Error_t aws_iot_mqtt_connect(MQTTConnectParams *pParams);``` | ```IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams);``` | - | Subscribe | ```IoT_Error_t aws_iot_mqtt_subscribe(MQTTSubscribeParams *pParams);``` | ```IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData);``` | - | Unsubscribe | ```IoT_Error_t aws_iot_mqtt_unsubscribe(char *pTopic);``` | ```IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen);``` | - | Yield | ```IoT_Error_t aws_iot_mqtt_yield(int timeout);``` | ```IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms);``` | - | Publish | ```IoT_Error_t aws_iot_mqtt_publish(MQTTPublishParams *pParams);``` | ```IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, IoT_Publish_Message_Params *pParams);``` | - | Disconnect | ```IoT_Error_t aws_iot_mqtt_disconnect(void);``` | ```IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient);``` | - -You can find more information on how to use the new APIs in the README file for samples that can be found [here](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/samples/README.md/) - -## Migrating from 2.x to 3.x -AWS IoT Device SDK for Embedded C v3.0.0 fixes two bugs (see #152 and #155) that create a potential buffer overflows. This version is not backward compatible with previous versions, so users will need to recompile their applications with the new version. - -Users of AWS IoT Device Shadows or Json utility functions such as `extractClientToken`, `emptyJsonWithClientToken`, `isJsonValidAndParse` and `isReceivedJsonValid` are encouraged to upgrade to version v3.0.0. For users who cannot upgrade, review all parts of your solution where user input can be sent to the device, and ensure sufficient authorization of these operations is enforced. - -Details of the required changes to public functions and data structures are shown below: - -### Changes in the `jsonStruct` data structure: -The member `dataLength` has been added to struct `jsonStruct`, which is declared in [include/aws_iot_shadow_json_data.h](include/aws_iot_shadow_json_data.h#L60). - -```c -struct jsonStruct { - const char * pKey; - void * pData; - size_t dataLength; - JsonPrimitiveType type; - JsonStructCallback_t cb; -}; -``` - -The size of the buffer `pData` must now be specified by `dataLength`. **Failure to do so may result in undefined behavior**. Below are examples of the code changes required to use the new jsonStruct. - -With a primitive data type, such as `int32_t`: - -```c -… -jsonStruct_t exampleJsonStruct; -int32_t value = 0L; - -/* Set the members of exampleJsonStruct. */ -exampleJsonStruct.pKey = “exampleKey”; -exampleJsonStruct.pData = &value; -exampleJsonStruct.type = SHADOW_JSON_INT32; -exampleJsonStruct.cb = exampleCallback; - -/* Register a delta callback using example JsonStruct. */ -aws_iot_shadow_register_delta(&mqttClient, &exampleJsonStruct); -… -``` - -Version 3.0.0 will require the following code: - -```c -… -jsonStruct_t exampleJsonStruct; -int32_t value = 0L; - -/* Set the members of exampleJsonStruct. */ -exampleJsonStruct.pKey = “exampleKey”; -exampleJsonStruct.pData = &value; -exampleJsonStruct.dataLength = sizeof(int32_t); /* sizeof(value) also OK.*/ -exampleJsonStruct.type = SHADOW_JSON_INT32; -exampleJsonStruct.cb = exampleCallback; - -/* Register a delta callback using example JsonStruct. */ -aws_iot_shadow_register_delta(&mqttClient, &exampleJsonStruct); -… -``` - -With a string, versions up to v2.3.0 would require the following code: - -```c -… -jsonStruct_t exampleJsonStruct; -char stringBuffer[SIZE_OF_BUFFER]; -/* Set the members of exampleJsonStruct. */ -exampleJsonStruct.pKey = “exampleKey”; -exampleJsonStruct.pData = stringBuffer; -exampleJsonStruct.type = SHADOW_JSON_STRING; -exampleJsonStruct.cb = exampleCallback; -/* Register a delta callback using example JsonStruct. */ -aws_iot_shadow_register_delta(&mqttClient, &exampleJsonStruct); -… -``` - -Version 3.0.0 will require the following code: - -```c -… -jsonStruct_t exampleJsonStruct; -char stringBuffer[SIZE_OF_BUFFER]; -/* Set the members of exampleJsonStruct. */ -exampleJsonStruct.pKey = “exampleKey”; -exampleJsonStruct.pData = stringBuffer; -exampleJsonStruct.dataLength = SIZE_OF_BUFFER; -exampleJsonStruct.type = SHADOW_JSON_STRING; -exampleJsonStruct.cb = exampleCallback; -/* Register a delta callback using example JsonStruct. */ -aws_iot_shadow_register_delta(&mqttClient, &exampleJsonStruct); -… -``` - -### Changes in parseStringValue: -The function `parseStringValue`, declared in [include/aws_iot_json_utils.h](include/aws_iot_json_utils.h#L179) and implemented in [src/aws_iot_json_utils.c](src/aws_iot_json_utils.c#L184), now requires the inclusion of a buffer length. Its new function signature is: - -```c -IoT_Error_t parseStringValue(char *buf, size_t bufLen, const char *jsonString, jsmntok_t *token); -``` - -Below is an example of code changes required to use the new parseStringValue. - -With up to version v2.3.0: - -```c -… -char* jsonString = “…”; -jsmntok_t jsmnTokens[NUMBER_OF_JSMN_TOKENS]; -char stringBuffer[SIZE_OF_BUFFER]; -parseStringValue(stringBuffer, jsonString, jsmnTokens); -… -``` - -Version 3.0.0 will require the following code: - -```c -… -char* jsonString = “…”; -jsmntok_t jsmnTokens[NUMBER_OF_JSMN_TOKENS]; -char stringBuffer[SIZE_OF_BUFFER]; -parseStringValue(stringBuffer, SIZE_OF_BUFFER, jsonString, jsmnTokens); -… -``` - -### Changes to functions intended for internal usage: -Version 3.0.0 changes the signature of four functions intended for internal usage. The new signatures explicitly carry the information for the size of the buffer or JSON document passed as a parameter to the functions. Users of the SDK may need to change their code and recompile to ingest the changes. We report the old and new signatures below. - -#### Old signatures: - -```c -bool extractClientToken(const char *pJsonDocument, char *pExtractedClientToken); - -static void emptyJsonWithClientToken(char *pBuffer); - -bool isJsonValidAndParse(const char *pJsonDocument, void *pJsonHandler, int32_t *pTokenCount); - -bool isReceivedJsonValid(const char *pJsonDocument); -``` - -#### New signatures: - -```c -bool extractClientToken(const char *pJsonDocument, size_t jsonSize, char *pExtractedClientToken, size_t clientTokenSize); - -static void emptyJsonWithClientToken(char *pBuffer, size_t bufferSize); - -bool isJsonValidAndParse(const char *pJsonDocument, size_t jsonSize, void *pJsonHandler, int32_t *pTokenCount); - -bool isReceivedJsonValid(const char *pJsonDocument, size_t jsonSize); -``` - -## Resources -[API Documentation](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/index.html) - -[MQTT 3.1.1 Spec](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/csprd02/mqtt-v3.1.1-csprd02.html) - -## Support -If you have any technical questions about AWS IoT Device SDK, use the [AWS IoT forum](https://forums.aws.amazon.com/forum.jspa?forumID=210). -For any other questions on AWS IoT, contact [AWS Support](https://aws.amazon.com/contact-us/). - -## Sample APIs -Connecting to the AWS IoT MQTT platform - -``` -AWS_IoT_Client client; -rc = aws_iot_mqtt_init(&client, &iotInitParams); -rc = aws_iot_mqtt_connect(&client, &iotConnectParams); -``` - - -Subscribe to a topic - -``` -AWS_IoT_Client client; -rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); -``` - - -Update Thing Shadow from a device - -``` -rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, pJsonDocumentBuffer, ShadowUpdateStatusCallback, - pCallbackContext, TIMEOUT_4SEC, persistenSubscription); -``` diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/certs/README.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/certs/README.txt deleted file mode 100644 index 8df3d0208..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/certs/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Copy certificates for running the samples and tests provided with the SDK into this directory -# Certificates can be created and downloaded from the AWS IoT Console -# The IoT Client takes the full path of the certificates as an input parameter while initializing -# This is the default folder for the certificates only for samples and tests. A different path can be specified if required. \ No newline at end of file diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/architecture.png b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/architecture.png deleted file mode 100644 index d010a47e3fdc6bf75bfe61fe53084f724ed94e5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82526 zcmd43g;QM3);-J&g9mpAZowf02_D=%=-?0t?ky?R2G6eLlRiI8DnU{Ix{#8hBlfMd|lOGJ3+oh9#N zRp=jpql%;mOzFtW9q2zuc2Zi7Ffb_C&mRCxN*VzSj4+I}*gG{hz5v;~^>un*s2u zV*YwZ6b#%OU)aBEqmF_D;*4oQx{LqkF4VlG|0##`|10w_l5s(Wg@s!EBTfHfb`&FG zU{KJ_fYx|JY|Fl$nP+MUBE}~eqkjShpzPO{UB{q2 z{eP%_brX#s1ZW>k`1nI;-5H>63K+39|O1|8+DN8faT9v7@Db7cohPM&wlT3F2Ro z>&Gt#0rH|}dby`*9o=h?6}`- z`tSa!RDhblH{=HTyErK=)TUrX!A6C@A|=Wh7_B7~_{XKTagd6tYUE;@?LW4-#|Ud` zYG!P6!#QQ}4DVATnFs+wHoLmSZgvORUmv7OpRPrIF&S)4-8fzmozW+hrT*g=qBd}R zoL!|!OuGJd_p?f^p7F=orf@NFap_lIJ|b^tJ-n?nq{e6hk!K`6)@hR7>nqZO>q6d` z{{nlQH|T%HWBwNK!ReSQjhX6Cb$u?t(9mGhxgRB!cI~dGGso?xHmw?YM|-gA--{Rn zi$lIaMlLfkQKnxtTQuswHb$hE@hrKLkv zs$2vbCECVL`^)VuLQ4r8C{uvEtdFxZW>`D`AOX3duFrDIT;Awene0quqIB+UU3X89 zv{SXDaBy%?M*Ip$=>+3BF8droDk=iN+vAl^=+N}3zh0HysG!r2TfDl8LW6t{gfqyOdwj2X*HR#K zu}CLKSb2(c_QP#8u+tb|SrHm#;oyN}6Co*b2#9T)!el{F7GHM5vS?p_pk_lxOzC2WX#iL}Z-I78ZR=6ib3dd` zV)BNz-tvR#P&cC?H*}JblF#E^c##rf30sO80vB!xUrJK22&j0um?& zQg27SM@b({!@{-bH7~->q)d)kY4xY^WkLLhFQZ+a?FMRl^N7F$;GFu>WLyG4K+!e< z2gd~17oTxP{S1dyo(Ca$9OAVe>pW+duBwBl5Pg>89ihpcG&usIdEDsBf}r>Rphw_q zKc$8QCE?&x)_89!zkO;9k;uhLY?MLDKT&@iARMAA`YP*zXKP60ukk7jjDUfwrfPTn z3#|ZH#{tlrWKl^$f58m|^b&wCy9)zZ{4tTwu5YyOdbw#+NN3dQNU<-vsPOG&L5l6-Q}F z6!3JJtM3o>u%C7Ko`LZYTCPJO1;rweB15Ctvm10WFd|5@hlg{u8k-}@EJv+(4NcQW z@3q)`OR4E-lFj+XE4?F8aNljZd2?Ja-k2Q2%+x!2{$L*nna*TP97HYI>z~*9Nlj0$ z%w+?nL%%wtX??7Gqq8gS>!oiFYx9-M8k|{jaeWz{DNW9e1;yKNvjfmvS}uMo%@_Q> z$A>$GauBHmkQ!qEltyrWvqhHovD0FrP}K3pe5~#)(qa_6UnU{Eew?G7RS@5DkWJ_K=F2P^{35Q|^9oemZ#i8YGc{~E z*mPv3Baq7d#2m@*mUv%rKMk4s(ji3rSkZJgH3%pR#)ZaO8V?{O&(|5e{i`JzY2#gh zWPiwbtjRgPs%e%_L`X=~gGKVEAR>2faZ16vmN8^6ZooHpU7w~-hufcuLQ<`@ddeuf z@Yp^!t&CI;_ASj0?ynhya;ynSQnhYM_lGX?Sy8-`k2eUS%h~F;p{O)ypR-=B2W#IX zTPo)}m!KsW7kV3IfFV6`W_J_6v3>_PnD;JcbMb6t*U{T<$sT-L8Qpu(yCupnBt&@M z682;i=dI9QuOJ`ISjyl#?*Y~-=%vwcx%D_n4+S}J_*rF&)vZP@tw+q+#Khkw6`p@I zJ&)F}yuUjVa`^$n60;K2bZwEXKB4>NWMHU z(Q3YBEmW!bH2LKrmM$WeQ(NK&IX+J&J_QTYeO(3Nq}8a~_VrQY%%9m~_d7Bd{HMKP zz=YlfbH?$;)qtH9#?2vqk z`4Aa$eBO?v*c8B5Jf<4wdBBT$;gK{-6;%`I_PN~P(ba`YEoal&Va8NLCMf~6XqAh{Q9SXe_qzgu1Z zr=!3VQrR|IZzmq_Ssd(@a<;aVX1$VJ{hdb<5A3llLk@bC>Lk8ji-t5Ag)I1t8cfse zyDtiri%M~rwdYe2s&b-7_?|=v3w=J;c^-{bd~x-?Mb{4_q?n$xWt#jx9UV+s*LgT% zUo2bN%&c7#8*Wjb#A_;&vhlTL%C}+gLscaeC6$vB6J2b}t;keSJSiR(+X&OIaleN< z>#Q&GqIrw3L_K^E%{0&vO?WK$G@r=eq7D zQ=XP(ZFQA~g++mqO5iJ|5h^QUcIT}~ha2KM;=-q6LL+v1c4e{$ve$cu=D592p2yN3 z=d0tzih>+lBbW(tPN;Y1&sgHNGTb#YydP1koQ&^-HZE@jBMY()Ue#VTjrNqvr*icz zxH?5|Io$>CN&su&sts5Ck8*W`Q#We3muhc4oLZGLJXU>GiWIyX;e!edSECV*;@%y# z(xmgc#+o;m7Hd8>e!i#MSbP$ol~1kt@d!mgJ@T)_TsGP2`zgRBBWeQfMH04OHq=J( zL1lK`K3>6`o*juf&S04__NE_;h+?whHDZe6ds7e1nNhDy5v~wyleMQIex3UsHKv2D z6QY@dBJ*hX=DF02eCK<2M<1l`&}z4_ry5HlB87+ySbVsv_oz42&Km=7)8Ssu*(n$( zKi+KR(PlKxdj!wtK75LI-5_htkIyWaPNj9YYDSlp0~fam7@u~Xc!-|FwN3c6ARkh6 z_DCm=Sf5L`zjaYnDp#T~jv%JiKnJU-m)xq3_ILVZ7IASq#c8N@SypW%=X(qaI# zgx{dxyqP9vOnZtJW}&n@eZ&z=?}h~M&3t*kPs-@cw#@8)SCSYp0Q9?9e)1SlCsB)H zGt73WVZ6YcP|_-j+`8qz$kH~KEZ})r6gk+Vok797c5}e3AD5ZHQgLL5Ti>$b3``99 z$N(es^0y+-7|&&;3*s zBp)W$;6@4J!xQW*NtukHBW=`wxJrP6@DlTdrN*y*Vp(0hn{{LB*vpdmTOxFoC)*cO z$$7089WcJ@cow>CYa*KdUJ3R%C(+O?b8EpVRxrn>5TnZEI`uZq57^7Z?VJJ*_feVr3Z zcSSPg)xr+)3;QyiGYjvRd-d6Gr|O}s*VDqAQ+n8 zxDBo%Kr_u)Dj4=pzB*1Xf?hFdmY3HHEbkDIR;fYN0U)v&dI5Le~(8= zWJ89r;%GL?7JvliF?b)L98HLgZMlkN+SWlrmT91F71mpxv^bxazgSIIpqv9qv+tSN zH5!xCW%*Eu>zN;)UhJHfClNdME1dP6?f0{d(XvD0>7>*?sz|}2LsGcnc}oTjRnZ|l zXX)RD)(}$yXYQ#JywX>0@5}7d7pcXxZ|aaBA>s}7vgq~KF|s9I1jb`5OMxvNM(6?J z&YTd<^w}leX-+JHz-51b7ZDRW2K3xHHJr5`z$b`Go?`6ot~R^=83~Wwa)Hk~ek%0a zsqgZhd@es4I;j2maLlzUi4&?Fqr-^tt%bsv%!yxc7$oTvcEsm>7lcEcKGW1G=`UyK z?WG|=ac$OX^$AZmV{0EqxL+8zP3uHF;Jfu(-zDVxP#5axJNkZ9?@GtlPF1}|+qyB? z9}`90t2z-%Jc<3Rs)UUp5L=BJBIl~0_HE@%89*}!$=$|_yPTfo7rvbQ7Dc%MMpvZ= zCfjEE?j@N8I5w2!O$zBPeU{OmOtY8f%6=OFxseik!bn+S^G9lX9m->b%`aQZg1va} zWeYV6Ki>uqCvq|GCe_^bq&CbNvbG-Q)~w7W%UYFp<+e@@@AXwF3Qsld^FCjYq<86RmvcSNCCEBhw()`|e66?ejbS_noQ&Vg&ZOqE*qZM=b&$qPtzG z`Bwt219^gR7Z-#L$ZlV(Tvgq=l&Q;F1$-KwEc2+}MEaTUPE$pntPCM5W` zhJBf}P?qUeG)=$S?VnStyQTgn4=O8Rk2z2hmzNYo3{M$|*%dybOkdJI;@|9Yz~K4X z^KxcOi%{9a+I||l+B5T(8~x#2^z2

dzMMi~>1=(ROqokqGf23C3t$yPuoO7U9Km z&&LHK0S%gaA&ojh2$|Y3@AC?3cyKje)f;u@ z?`~FzCt<%-7Tzq2RJyG+J-r0lBcFr?zAO58#`W5Bs#X%o={ilQcnY6ea}|?xVu*0* z_ua{3C(P}^uTYEV!ZqjUw&j_FAB_iN6T6w)*9Ndmo5%6rB@oS@6IcVIu*tGnLVq(h11OHSPIlVF7NMy|lUayqhAzUw!V+ zG^2Bv(YwfETvHSprDz9 zYDd?_H{i0yuq&*?uGjH3{Ee`&>5_x0?2eZ)O8r%-&Vh$tf4C>75fa!K?9T_sbi9qN zSN@A?MFPgu<1X)zW!u*&jE)S5Eu_KyGveazp*&QA)1C`D+b{h2^TS=olN5O( zW*-+o7c5Tl*tcAiLQ<%@b?BemnQmiMT8hJI5~INTR$U|z;RQ<){Xr@lTRekv3Xm zV6iU8GXi&O!oF)Z?9?VkV3!0TNkqh%jQWH<@HwHqhzYgFl__5~0$b)NqLKNY(hNrS zyO(o`W>Fl>RrU5Lc?pX4a%zfm+i2Tfh%n{&$V~(&=Y=$oW~C>bqXK7U(I!)W%peJB zDmT0TRNEpnOQQ)1!7N!5+U31VI~!v2%hw4)#^)5Wb`1;dsXi6JCA}fD?x->RF7XpG z*mE6PWjaucva$CO#k6C+{&XzIn~7=X+%`Yysa&@munYim1N;>XZLpYqFqeR3+0kIOurCS8&pV$=(d9 zsuvoJ$((X4nRuL9@k+ld7zBBFoHVqU>NZMIP-7kLN5+HMy!o;C)Pa#exXAQgk|QRb zWUXPdLYl^f3)I|ly}k^!FFdOql>CP3sxE1a_n(rUu|E=~>lN*-b6w$=2CX!kGgJ)J zwbU}Y6n*B+Y_LXE(?WIUFtEcmkcG(q?W-lZbm|3LYcro71@aE5<44c3)NVo}_npWu zLwzdWod_Ex;-*}w>+(y$H^K5T5=q>3j{M(GcJOy%d6=;L-*P0?E$nO_Viji3lUoVw zY_qo^EmfyWw(htAEG<->sr-~THt;jbQ$Z%PKb*gW5ef{^Dt3JT&M+Av&~Q%Gy>bhm z1E3YQo%lbyxgE3v8$RY&Km=WFgyz0Uh@nXP z<$XqSqBG`^!)wYXsPL@(cLjQ_$o#)sa#*F>1GCo=5hH{XPu4SE)?O%wHZ8s83Pu5hhj`sY_DLiT=P~ftC74nLZWyK$k z;?N6z;c{pZ^F7FhupHxt)-$e%7^4@*S#UwJll1+i9G<+?8N1UB2QRlxrYHJ&y~D*Z zbVIGp7l`ofPf>B3i>Mc@xMuvbFIfy+l^BG+Fl6SdVye~njuluva+P<}kM zJetM+mO9HFf9uR>vEAsm`2n(r(&HA!9>Noti0$PTY~D5Knu;jf5GQQ)gLi)sdaggt` zB5v&!G1fxf-VE34*1G4?lW>{k{u`}_4CwS4Qb=q8I_g@$T> zh=|JpiNC`35pzjJlD_Ry7ZiziGYJmlNwA|4)(bhB^euUV8SYI0iB^IyMmj$0$f;-1 z^_(3DM$`$GCV4XFp%wcL`EBj(Ey=fO^0?!&$O0CkM=|O@J9VB)}tbH?apM!ykEhJ z2(ZxTWw;-5)?4n0(tG*%UaeXrUb> zgg9|F(kex#{A8l8PuIus^=i4(dtDGUI8k4BfK3CmU#wSiOiN8YXgqKPKs6249APme zmEF>@neHP`9Ul0yhfj-ZL^|}2vsk#JQ)K?(veEjK+bgpjZ~VX82N;5Dr~2I1iIJ?Q7MJ z@Ns+(n_8PWqinhH$Fq^<S;>DBZ;!oj2sigT!m8HkU(2pgvPEkjjBW#A3U*QcU-AFX`FkP4_4lg^V}emDiY0s*7L2cwTsWL(;ORLhn3<3R{e%@p#byOYGO}-3H5&IaZL) z_TQU#5u*g>^AJnEpO00&K_71_3a1y)wTtEB9_(yKKl_z)oj0xd92veMvldcM$;Crt z!hoPC-3I#M#PVUZjMjf7M>qOxw2FWi^^O$$ihSD}oA!5h>oOwa)y(b^x5+h+?Tf8* zZ^b7PQ-RZKN4!2VidzFyKU}1Mx3__H#pPbER?}T>hH#xajY}VkKG(aLxY$fMz8!ZA z@)*OLcF|yc-hETZfa!X%sq(w=vj`%OW*WPoNR#1yI||YvTAxmV5+-)bb*fm4RG1%w zm0@A`Rh1gS8b?Ggh&Qr^Qv@#iGq?nON)geF?(rBcT9{SfL z^KP-=WQg2krIO%}odO$fSj5y%UR==%-SoTusfhPgvIX75)@?qBR*rdNE;C}>#Ac6t z2|0=wks*;U1}hnfH^{TS3$QzW)mJ51h8&76A@A7Roe2x39-G_XuDFzl&Lk-z(Q2-Y zgYql8?91;Nl&~jCy$Mj-iM-nI5BxEaO?AlPvup4lekP`Ccn6dBb}$GtXBp_273nC`n!qUo4gRdrjpMzn1qOTb7!->z-aO9%OLD&5p>O3Gkkmbb9x!vBgDek?xCX(pF;*W=s{@$KM1PV`2p&cjZdCVmg{G z&Qw*&W87E_fOUp8qu`qrN8#LmUI{$7YLJe=6|a|5=9QtK%)7CW2bGX*E8e!`3UMdf zzm0YbTB3sY0#hde6=7N>150L`EfeD!SD9`MXS6*#R+w!3Yyp;iAA#46UGBlcPKt08 zQt8Vgo=l3fKKnoY#!^C0#==9(v8W{8V0C33o&5e}zan)WOeKQcYpTu~A-W(%fB<%w z^V+KwG#8q%b=)v+HCu|7!rqCr_qM-SCUN)LJF^Zx@;UAllas>}17R^y`zJlsv8)i# zkt*Yr2HPdJ5eSJeU%6pH*hh@)_ZlrFZ!hznB5svQci}zvGBe1q%RX8w`s#7U*7Q!U zMD)IGtG^JK8j$6i?x8^0Lhfz2TwRFY*cG2k772zKvA3yn5$@a{?;nbcxR-~&YUr?W z$o?2{)yUt1EEwt-$~SLJqse{Z(67O7Obkz0JCHuOc6a!}|IVhthgh>Idi=)vw~n!diPHq(8@JE6PkezA0rR@vNN)vjI&zU=Kw=M|TY#$L9L zKNI~bFz~e!rvSUA6Iui{rYZ(Tw+UWurAE=^+=5AK$-KyoD%=L> zM0;l@X6s7ZCcf~OvYg{8>L2Yr)M-5!&PbAK1P=zEdJCDIlR(MFuFL*UGRLN~%?L>? zsh!9xs|zb3JlSA*hXVZdpdQdcI@E$0u!SNf%=mYGD@6Mx~&YymPH-|cHGFuAlr=M%VW)6Qp?Pu z-b{YFm}wHI*L??26;Z(biwwuZ8zOxtKP|S1Nj0Ww;57U{l0Ls>3WHTmx_2E1!}aC4 z`1#jphNy{X)Gq_@v7y3>W9U9R+M=T|b0_&O@djnpCM7>M^!~Hv!VVL{?ke^g5<&@V5~W>=X6R0q*bF(Gebul3|e zkt<@hS(qd(JI!op^h3AX$!hwnhEusES(@)<8vjw00D09$sPEnZ z0hG&>u;fGPHM=#Y1M92;vT*q&B2G9)6J5I-7UHgK`d`qVzcp5(ie!d{gr*yJ`a~MbeB2VKtFVO~aGRYO| z?fN~CWZNVlHT%Pc9J-10PS(kWFWHLq*(p#6q>5iL`Hez@^GCV>_{a&%9#fZtkYAQk zuaL~OvtZAuj4G%xWT09faj^n8UM}^R*qB`CUYN;ozVSwVK3PIEm0!3`b$$j5jm-)~gJV%@G)?TNV-ll!^@H1I)fG}?NYrupaa1MS%P+l!^NBGr zObBQ%qf*|p)_xeeJv0mbNt|kzzTFQM#w?Qou3Xg`Z{t7UBnf&JLKO>J5yuCf#$P9TwlZ#T9_Uqo8h|2`B5#`AJYxA zKioCPclGwjwgiH3$CRsuJqwSa<}0*a9lhe`m&@D@3EGiU^3~OpXaB)&>L*OZx@0L@ zz>y0X={O3|f>Nsp+GY5`oZ3?za-`qkpY`Ub-muilUcV&76$czZph;HeDg1I#~EvP7W_^09~||2Nxh6a=CsoHZnwUb z0eO4g7i|Xi--p=L7~cjJsq$2WGs)YV+zH^E7Wt3%Isbqd6qX@ac3)gLkP&>*v?!qZ zQe5q!e;tn6L*l7LZQ?_5lKCuSe*13g)-hF;1ggoRpC}Igx6QT@3j!~zLs#E!kI1ue zhX8q#M$zV=3ax*{;226k!xd6MddvXN7yypMC`eT}_&1WN>%V^A(=E@xt&95nG?b(o z2ux`O{%bhDY#Y+H+J)bT|95L?2%|t%eChKrF3@*E?EVi8|4drgi0Efh6kUE2IA{{9 zh=*smOeHxGv;>ZJm;alKpmIe1=k!W!CGBk6(J>s_Q#bn+2mkFUIhaG@m5)H)Aj5ry zBx61PD5&Z)!}&7#KVG+qwrOS6$8q~&YLR0k2Q{T|zQ@??ZcbbCo*FQ)`Qw5gHqG+I z_<2o2-i`Gs=6R^fhP`_<*lZYV{l*X(-7JYZWf{yT9KNY_$s-zX*)DIxP4j1OW=UA2WhK}nZaoBgZ+RFlxqP+pec{-2YV(k3Rkfx$oT zsJeV*_DP}jU|_W^XT-%Z&ACtyoO27HdX>w3#bHh>Fm^;{y?^I6@;i5#Iw~oNn$MMH zfH^bNYM$QV3^!C|Wk4)6LcMjndJ-w1YQyTi3l_v&K}IGfe~Z?wx->J0OhdS_vD~D_ zjU2lB*Ve@WSDhJ{9RA#jmC+C+bCO8(eW7J$+{~+PG1*-0tc9e5g?@BsHxOb;sf}0b zbB235`5tFIk{m42g-VAmh6WLm_Jvc3FNdH=`ty|Rjq-Sa0paaLaP7NcYFWa7X1_5=)72Kn@L)wpEh-o57P=)&0*Gg`;wS=ui5x4A8Yd;a??i& zBsiv06YiAR#1b?He}lM)T`NGBKp@h!AFLyeLrgWvjL(lkfVbECBJ>DMV_c((aMeE> z9?v6dH6N9XNdFyEQPj&~v5Tp%qajOB#`qx79rka`XN!Ain09#P_~BIRynSeJflz(BaCxQDzZK65LkFvgc9vu34sr^YiZH@(p@HbX zgWMqn3SUWCgJQr(DA&A9#5sfR82mF9191Q$TjkYByEtPM&K9tXgvi?vst<7gn$<4T z7Niyo`4)mURfXeq@D+mA;@E-rZ}D{uK&?5lca|ffTZoz{fP|7RX5pD${ki&h{n%U) zy|YM=TJGLKfV1dQ|JCARq<}gm5)KrkSExJ2_&fb}aN(Q`>MGU#^$0B7MjQlH@H)0b zJ)-@8c%&1`7H^;BNaS5w8VTjFnSxvy|AB{P6GS)WF$>5CoQPP8?TWE9WUjz}ALk=&8!f8SFps^J7j&JL1f(~PlIbY^2a)Zt zK=U$z^kE(LSU6{k+0ereM`=~P|F-u>P)7ulxD+k*GB-2=T9w(U{*8bFOhlA3sqA%= zTjAi@dQ=nNS6Q&qiKhP^#sDz`6mifL&s3agM4&WwRu$I?6^gqJsvYqE?Jpd^<2NWy z7N5=NZ9i|PQD!#oK}FyTTahLI9;)CW1b!48!x^E2Wj`X31*Bh%y!Dj(kM&U!&|V3! z-@i`n148FtrZyw>e|v0{;y-Wa_0KIv# ziD(aLd=!NMZ-u0u&lW&H{*f^1(wa!zpCEo{mhUp# z?-g9ncDww#f`G-t0+<_Xc5d&^9uWL|t_tb7r!m$+1~i@Gg0EkzG`Lu?!Xd9G z=C$7MT66y2yBqp|i*nCG$S8Ket+3fpkWM5tPrFTWtBZa1T0sC1veFkK6&m>^K8EJ= z;P8R%wPH>=>Rl9qJAKwuKnSrExhQZ1Aw|*VbysJ2G6s}0fL?I_flD?_h_9oZTo{g; ztYhkj@b!I;(PJ+3%!)sSpEJLEs2Sc(Gm4PELRzLI%R3}QIyq6P zv!mFVJosSCcS1NnvB~_}5A>R5`B7n>k9jQl>uSUcM6nO$;i=C>p`8>3`XcC{W!`Q2|Xu27JF48(C|`My1iU*O%`D=4oM;ItxmCJCSH z2i!NcO4vojoxtEU92PaD!-JV&v|cl-PC@Dn$b+nR7+_!TvlVgtHLIjpR)D=%QAQrhIgG-`8TM(l>+2>uY;YxkOO9e17k#=@6rB zAMp`t9BVLY!u56C%RA=IQxd#QcL!LMH_(^KLSLq@G9(G4kbt4II$C^ixWtXmQ*Gor z6+7~@2B299r6myreg8JiKVtkucS^;N~0!) zh7+;6KW}D*DC9`MI@#Raq)l8xd8o>LaoTgbkKG@Poi`I+`+H(Ea?v+2bPGDghEu#; z(GBSonC0gzF)4utYqku`l@CF%K~T@I{@2B7^uwnH{-@cwTd{q#WPXbRF-ggdkPx(d zI9@g14}b%F=)81NX@`ZV0IV~YzyFY;opse;&<-od*1Jbt{aaHvkV*y4X%>!#M`u(W z+6RHifI4|<8k)iO0E7)liyg<(=H{G}R|*R=(Im%ouJF|)A@V$Sy6|-GsVMZ2hLd@k z2#3Y#0l0<%>%^h1%Al09UVXORdS$5AWQ*oo%t(C9yd1kFofJl~0{8nY1 zuQLW@HQ!whhFfb7^i{0oNk8x|<{SF$=MtZ(OqRDjPmIeV439BJf>?-{P}8Aoq`!kk zNM@KJo<^Z$1kn$#3K%~j4}EsnSrI7!Y8KY_rj6ewB+R-k+_d^VsLE&L5sr)K@l+}|iz z$f$k8UNCou_^?svp=JN}aMx}loB8+V53?z*#HFPx;kX^!g(25nr1dU0+=Qv&w1T}~ z*rq6zUtpNWX2fGQp4Up2#S~a995T!qMo`oP!Bsv1#oCRB1=G9Ed!`RP@($a_h9Bqh z^1Y7x%U_V$cUoLc@7BEDYrJU?nqf4rLLr|GDK|DpQIEQFoFuXg)*-C0o*tS@nB>Z0 zopafbL#`nn9BpN-O={O-4!Ch-^-Ckl?>Lu!8B^u9rDtU2u7H&V$4mFIisgA$>I;Nm ze=BQxC~Z19Y%GYIigg2FKfH1keJ79;zmPy;lpr3_Q|Cv){k2=5Px@fJ)E8c+#;Fr!Rrs-MFN zmU~|AM{h7b#g*vP%2rNA_8!bkW)}Yly%CLVi{=^2o)NlaV1p7u*v|O8=an(x1SE3g zwg*?IL>=DwtS>SzW3qF4`pU=GOji38nRwq>S%ook`SpP`>zS1`V#C6YU#yJ;0V!** z76jHWb!<*G3#bHaaCb`FTUhXZZ(TOJ)-Hvkd;6<-gC;#`M|qm#loN&C#Pm_Dtu-%fa2X%L%p|3(#_DsJ#yx}Y6ZOA; zQQMD|Zs^b%?+9Y{%?83T34w0>X@vTI?Nq&|rjy28AR{HE4WF#^YOmi)>I=k>hbBK8 zjE@tS)Jbj5z6^K6u>9CD(2vJg_)ecb`H*-&#iu zHoU#U@fRoPfkC;c0Id3GVM*2XW;S&Cu({FnzN>8V^+O^#j&T*d^F}epNVyjo8i`>q z*!`o{U5iVn#La3^|HR&uj@3u=YTJf{=BGBmN9|S?=2;2)$fraXbmw(-#>g{+s|QM9 zGV@k8_J8O@0t{2O-FS#9qhpH~QjC5OJ;*WXQ8q*aPy)menPn>X$b0(G!&Lv!5^Qqt z33d1M#IJhimu~lk;n`Z+Ti2GRyA`?*6+v)U2UkLI2pQW{={Bu83qld=!9vboKd(mX zd(oHJG`zng`CZoG8P9)m&q(|2X{MNBYcD=gpOVk@ASQ8X-!^rv##%E3VFiQP zbe5|o$x>Ib`8?&^eFIgefw01d@1jm}@n%_cF8BdiX{P?8X9}8oE zt6rM*_zcpC%{%Vnli|wLffu!;Q@00*qiC_SZ`LS#J?)D!qkD$*@c;%HnMHJqo`=(pNh!geT5g8-=8l8b%$MqKR4#9sYQRv6 zQeP{{y_4_5a~&-5pWgzQdgc&(HV4IJI=>u9t-(=3RX=py9_tL6O;`nz4yG`KXM9cBuG9#a4H06r&(R!k=<-u39aYl zlU6jS+Q$NMyW`A|>dqotasMo*F^~P3!Jfel06a88dxF0gJ++a&3oCK9RIkCEGe~Fg z9KY$KCFZh@>DhJ1qn<_EKW=o zl$OZsW<1VGgcXZ!g^)--1|eDsBO`-&%Yi{pGH-@PmjiaPZCu}y82k*c-@9y>=^wI# z;D`>1FwXIH?K1es@AL{iw zyi@D>aJs1p{~yAwKmwq<9-0(=h@hI77bq6D5DqXO*?#9Fal>4;NtTa&>ajH0Sv-l6 zhtXqJcpNwvQiQ&-#xXB#G`UMmN@|!{q+V+NUbMJ_1eSI?Y*)ky?V3#Jq@!q}LCd)Q z?y^*!4E%<6uS=pD&hR9P%j#B=rT&_-=qO8q${xvG&dE~FD#ZO)!1Q;{y}s^lVgRe!9-fOF0n$ADXZCb|1m6cT_7v39)XYxA!(4J;YS}yaD7r#;RZdO*zL)O>> z4ZmV$rBYERc^VW29eavTWD-ExzC4ue+p7KZ+Y@g^+o-}YB2uqo^M#_&?Et`hy8k}Etp5>oJUoJTq>wKIl&v2UBerX0)SLStU6xHUm zd{w*nYmsSeT)PLCsH0SFN2Sv8iWGbB_^wnp=X2;O(JmEgtGyWiJI|z3F2J3q^xa*% zD%R)irU%bHnWIi8CH_r;MAQ@u&fkTRTMbYZ0_+@arJW4HtLH4#0Ur>FD5Ii3z2Go~ z8*g$@38$j;Adh+BXGG~XLLrXEYfmX}e-ykvv-H^-&$7>h+fVDkgRo3B;kMh<*n)SO3PL5-p@->w zu0{VJS7+JKRu^sS7MJ1$io3hJ6nBcd7K#*i4_4fr;ts*x-Jxi42<}dBzv+AK`Ec(a zNV2om-h0kxj5(IS9YsI1wmlYK;-MHD@F(c7r4mF8dY|z-D)} zg1G@@5k*0Ft*9LNeC{rV*6k;5ET!Py`=6M_-E zaN0u{J86fC$QQCRQ2SKO@Yt`xhEEa*ADhnv+)6K8I@%&Wt71gAtYk~-oRYq|k0I{f zJiw$D2zlR+$=lzgHj6yS*jcaY7Ss#U!*ZHY0tiZ84&uI}^ho@y@L2KPRl-|4L82>k zd|+!Ly7(=Fo%y{a4EtZ3>koiob&xKL44}Dlju9wV^>Zutf!cwz{EcIcJAIUCxfe6Nxb7wT}c?Qtv{RvHl# z5#mLd?`%#!G4_|D^$|hQ7PQ6K=_N@{(pJsz3gS3T6^e)HKT!6o#!T65VOuy3!=ju? z3!&dQz|-a9@+SrO^1`jgGa5EUd~blqv8sf^=h~{u^H~{aF4#4hn&d zVH#mZVS@T|WSCi8lydi;Ab#V71(?N7a=^< zBUpPWb0U_ht2+yI>gITegmGC2Jql_tPYPX?Ar*oEt{aJm|8iTv2p_|~9ndG_`~6|= zMT+)4-)p+gf)R`NzYZAMHTYL?^Z;_4AH6C6FHX)>g{nzw)sjNF8qVKmY=xAU>;Mz( z0wHEh>6a?sajEpQ#x6aJ%4fB%i`pZR_NE*KK3<$Y3s6XO)7*V{(y#A#Ka)@;?s?;P z{@zD!IOBf2=gFlJap%gc6e@yrN6K`5nvn2}I4wlc(#I}Bc%zR8?Hld_kja(c9eMk^ z)Nak{#;LBy+KYQ^hFCg!13c}?=O5AKQSMqH>+gVmmZ3WmI1A;Yyu^x+4aRNxu#>iq#TW9pH?WyjUIz^QF z20D}G!|G0_?w10X?2(bEt&?s(C&3C&3*LL~bXZ8UK$bp;eEdJsEP}WRh0=R>Z9i^4 z11WZmS8wirL`p}tG@$o;g#L2B?$+ZPy8im;*K4ZR$nrW!S2>XP`C-wH|9?7PAwP>w#cXFW#Z~C=bBa-8( z&2C5PQ8V?-?psMnW+jH?Ld6EDv+qh~X%`3?pbhkWUTwLU`7(2j`(DbH=k7VkZAXa7 zWyd{caI>TO6M7Qk-~YxqeSV+L<27NJ%?R0diBuyy|J^ajFb?tALiPbZ9N(LKuI9}e zN$=~aN<{FkTA7vVbgFEp*Kj29IL(56x*clQ9yh<&In7(^LB=ty+9NxpgNsKpE_^NX zy)SFx!Pea$*%b%PQVs9RJwS!>&h{!FJG9+SS3Kt&X%B*wLzWYkEQiSql3*CnyB6M| zJx@Bn;$Y$TxlYGz)txqPxXyRCyM9a(pFPW7*L*8~UFYfT631P#UTh3yRM}eH0ica% zJ|gcWH$Rt88!%&aWmALB-*SlD-*LYUh`g^^@J|o&5^^Sa#d?CsHt*?wU$0)re z^pIXBW5wm%jtBnpjLw6}!FGjRz76mVCrzfu2%>WTZ@<7R3xytsUae)|R+hx9(}(l$ z@OZxm>5iSil@TLl96w|S%d0u#`K2Y@ew8z)zO=1uR*!4R3_5B3PF`w8ME9Vx<_q~i z%y%d6xgFrWyN}9K>grlj)qqR$uZUe~vdNFk|IB@L48vG4@yo^Y)My^NU=2Gp!((8Z zqVwXIuG#I}SaXRN#YC&oNwPkwKcPcW3vK{e-fF{lwep8f_ASV#wRmm*Uj=$JQqLgv*J?6`W;Y^yVNZ0x#7M%t^I zo%X`s>u{b-*~*FK(4@5ow)q-2_Q|t!$((m}mg{>iQ?*4s;5qqTQ+wH{2<_uvn@eRh z+bq))@Vqh!wY#MZzqvPuf7kBYVnI0(s+chTh!O3UM?&Pv)t1oKMz$tR$YQkrLg)o! z8Gzd9{2NOs-+vNutRmBw`Yla}j#oxIh+P_x&J~jHSyXtABvzh}D zhY$>0c6%W#`S(1%{M0iEn|v9Tt4HXU(6A5&*e()J5u4%uIylEe9IPvBq}!9Zq;>cE zq~UD9AY*OVeN-5s_94tU-Zd^${FIAhGQI|V#+TvQO-qW|y#CNxFN!8kp5r0#x?@`( ziQR`Twed%{M)Jin6^*AZ4pDk7T8pzA;zAOImy$*j(*?;6DFISoKNk{0Q@<-rIZ@M` z2ByIJv>aR~Xt82Ln-SJ?+VBPqizM~srrzgnFjcydPvO3|DvUdDSQ0mr!B&qe(T_!> zgok;rl4vRPsdfnooXg1S(6`bIdLhJzahNo40^l;Ea^5|jyFWr?)GnAWLzAg+|K*TD zTvwa! z?v~Ia@FMyLNO>1;*hx}P)$$W~_=~o?;ZzcQSkE#VsVqc}o9P`B4n-LI(k~U8EHZDw zZv+WTGmCt!$p3s6&@_@GlGCc(!v%w5hOlrw#kV>ZL_U$q@|C`P&u1Xbu_qqpBy>j9AEp`JgT zUB%G%4)M19O<(wn;9SMI@=ceP{SV<3CoMzjE&AUe6qsN>wL{FFjUI3^V5K9l{00%u zFG%M60?ST*b*}TEO?RH-1r)-JcgM&8({}^!yvxlPL{UqC#oz|y%9DRLXRk3JBhtQJ zHBSBNW(UbjLNJB8yRS%TG-!7l*U?f>XdK6p=?#QcXlaR*LFW-! zBe(|`-4?f5kXgZq^m)YMFg{^COn)glD}d`flvIyi(@u4pKu=Pi=u&Ece+&BquS6XJX-nGS90GQ zsp{}Hj9br}kF8ba-Wgam`z4QUnZ6j$wtJsGE;!L67%MClBsR6juF(Z~8<71%!mhj8 z@mQ45%~c*;HqD|$hk?0l!50glJ3ufNjfuKs%rU4aMeX)t3*GyRXiBqriFy^D_6NO} zjsAD7ZLZSGvpiD;vw_Q-r_;|8RQjh1+Kb2FLuYd_7v&5t>DO|L_I`yzk@pAjefy~B zQsl?07?>+WHhc@e@nge0O}nIUZczscGM1;HI}?H~@dxr=_NWeKlZ|GMgOSC*KYk0q zHtk4l4bqU@Mc8S%D?~{TYnl#8Y~q6?(RYEZtZuE@sp8^+rAJ5&@24QLHj)Y{`5`LeF~vxWc;#F353XCqDl@2s#*gGUuB|)ze)rj3 z!Z!C4C&JJB*K=8p8SxuD)dK7D2hTCS!z&jVsX6tjAE+I0nDuFmU#=QHGArlAzROA8 zAa#b{(wePhzO`CMgY-dvcQmgD?_WF3>{)bl?f&H#{*Mh+hcdUWhgo5-x~)&Fpm#9| zvh0~*to@RN`5ath-_!4W?iu^fsJqN5?>cY+jniHd<KO7W4i9NZtL+5Q$5N9!4@>j6$~Rv32^5X{u@S#h zVIi7HK%B=E^lMU3WC}gRujR1CO;YS(k&*H6#DE3jay1F~d)eV%8#~PedE1NE{3#x8 zosPqg#3xgZ=MSeIXd&EY(jwYYn+P5Q&Jmm^4v|WiQK>8Q=vIR}rb$_i+s$Dad=F>1 z(+Di?ZWpEit*RJQi1e3kK4$rH3)5*LnS_gEIUI5!{m=aI8@@YUbOfsgIZSvqR1%z} zm7N$X9hD$uYoAZWzdI!;AOqDa+oO|x;d?^|!Byctm-`Id!jff0yy#FkJaJ#%k*v)! z%9*>>@eQOv+=V{e`E8DF$9C(M@3-zKZd(1v4__ zZ+ZEpJvOen+1r=R<`%hJ_!P`ltBETyXw2s01#2%Z6G7xTQgZ)GlXshSay3r=@gC(+ zy_ZYA#9?cXudXVyxGy)*WVtHT18i$tNLF8zAH=58o4<6}GIlo#5>5~Wn!jZ=%O07u8~|MK$!L@`81 zdbjZ{9`OyDUhND5u<~{`vx6o5eO_as_YC30#XcIa9#;GvUm_RKGSpm1X$f`wxMP-k zjPiL(G?gGMBVDwaFK$mw6h47@oH~G%%3nIIrltp~9#W@!9=!IlyZ4GMmmycMa=XN3 zb8<(*h(&#{o2?Dpdl*$a!!`vWho5ii1`L{2mFpM~x16{|Dv6Pu@ijs$N>^AGG%}DN zQC5Vim!FLdhf5j|j9*xt;R0J6*u)xA-_dekkvd87pC0NAr4+mc0!>r!OGQ;NhhI7_ zrC=dOmTb}yY7Pw)4$5Sa1Qx9sJUiv1^coKD1DZ#|Ai}WzLef|HYd`d z@%vt#FD3d1DD)xip(eQ?9Ps4$lo!r&4RSd1Y+j^o;h~(J!hb@ACDc~i7!?kCfB?J% z2hJxs*+0uy@Z|W2t|io7+ez?k8?9w8P_Rg8@q2;JQ}Jy~tD}DqbH*WMLEM2PC#;Lz z6Lx(iWgH45*we((^ET^#H%8Asg`W$UJ_ygy@~cS4ckaWE4go*G@plZ*NPll@M@HoJ zT5yYR%x`nLnqeRScHn^#M}PmGAl; zduoo%fhkjTc4=>%XFN#FUH#$VZk2~ci=Xrbggxr34S2xd$9#X`L6L8o5F5SX2i&uP zLWy+Y1MkPv{(DAzY2oN_{7Ni~ON7L57^S2SjGn9R=MAG}RGhy*GDdXaYGXzHwis_Z zYpPCTrntECzAGAAe|_GKO$NxSfZP}GN>+DVl7e2}k1?nI`MGbn#nvvU4(&a<&x1&B z6_-N!<&tTux^L48js-j}bDuWt;_IgbK~3#V55yPGc(x8l9-anWQR^y72@wghM#_m6 zM!sryr>iut&%zhsz7>gwX)>f~2tDk8hiQ}7)iryvce}&c{wgw0p+6+BF08L|%Q*k^ z5jr~h-1*-%zQam%YHfu`vAp5Yk&T0}q)19qUv@>WbtL03S&dY0DLU(Pg_g?$FCn5! zGO>YxXQetd{_W^+s#;gP-g(QSrubUJ3w-#341&xFq*Lf5_E1kv&7rw+bgWZmSxD=c zYo5ZIt&@euo+z6=42glXdTpN&=YVdNL>XI3podX!d%2V1XoVIE<+?U{#V5BAm(FXy zIQPQW$*n!^#0&95LY0W!wO6J(VpdeqXy=}qIO&zI7)pQ8w5PVW_$;F?Py>J0l;x5toKfJiA;`}xHf(T<&% zflk-n7RO49$zSUB@Jg-rw!0l4gGc5Z#Low@k>5e%$r&m_RaM{5oQEMGt4^-x6^;zY zv9gB?dJ**{1Y|$?3Rkb|W;dn$zb|hZ(H?_BP{OpQ>j%M)E`pTMP%Uw$+ecgd;Z4nk zXZW-Bo5SqlpkVy@awZjexI_)n_lLhz;J?+~*bP|$LOb-Ba5{1e_~ ziaQ3$0904Ag*$|$IC(x+x))g&AtkUFb?nDBNRKvAc1ryeCEW06gxhJ3a_iB;Qr3zy zy$Ou{#cn)v7tIjm+Y;_lJBdc3R0l~DetU@wzd+J5qRWZRp>4lEO-@lHI7I1%1wWH8 zm_Hn{IF$OZn>Hk=r^Zd5Rj2mp3I{(9lx>Xlk@&GMChnu0EGvFkX&JYJk&-KMv)v7f z4F%GorWT_dkCadh>*_#Mwv=wo%4EB?uo;#yGjKD<1j>F#{ZtZxy(JZ_y7tZm7NFk2 z1n+SW=I745mOj1hZ!R|C!+W7M(pu2nU}SfJTlE%%PHx8DY*$? zvMcPLK24#Q5m>(T27+P1c^|C~#1no# z56o6(T7$Uj?z@afqyK80#^rNS>c06P(sy7fDC}%s*x?A}Z(KKjVDrE8tz_7~g-G63 z9kwnv--^nJ18kh?hs8aHinW|uYU3F+`T3&n)jIR-plg4@r&D?A5gJQ{ zo#SY|QHZBO;ZOBOjY_u18@AQzo}2S~8i#$?qd|L}@w{R29@ESV0$r>1nXYZYhycl_ zloTGfMzGMr#k^{noto#*9@6N=E_p+bGa^q(8t1JLld}*-)lLgt{Aclsh_Yp6zQ$P4R6|4+E zP8oE~A(~mfxgt*IG#5TaURh ztWsDJOa@MVN#Zk%nTREZn_@>{Ks2aTa@UP3{iMsqIG9w_#;|Ig=C4n;zDo3ExuIWd zXPXjz-u5VwcU-mZncH@+p<1i8+);L1^Cn2rgr5aY77JB!R@kRO{O)n*?)ND?>#w5g zfE_Bn+;cJ+No3rV)Ev)0!Gc{Ii}e|Qp6s&Mmd|inkHPXx#}iSA1(g>bf`%%dE=R82 zHcJo9Nvd!xrL@f2tld#x=8Txey`b|J&WNn7hIgw{U2mt^k29W{LJB3USKHF(Y}b{B z6kl{#nyh~)e^`qSGT#JHIwZh&pqLOICcYqEIsA`9Rk|mf6JhgMgT5S_ulti)bEvoX zI(@$giG>|nGDAvg`tiyZW<~d%DlR&Ly+k0JV+9nOzDPSV*9)_O(=FlSd3Zy>1>TwS zBfGaWQMTttI;Wwdl5~%dRcSMc!d6q!4hoZa6iSKfuz6fe#`&7x{RXhHEi<@bPY|;T z=f~_)9t4?xYMLGTrX5r&nndT!29XW`kP3xH z!5`-kOKKSUf5uwa$~cpBB*W7wR;BdM(eqGx__#GuY=wy7gF zs(VXVKY)UjXnxF|{P z`tO$>O>(^NbdJ4L`x)LG6*7^)FUJW`$O15S4N|P4VmcnSYCoNZSI;?{1a(q8ebsM$%!a{_wUc7*^WMPz>-r{s>tzQ2U!g7?bmKQF;CxEDh@q`G+DG+<3&jk z9578tOY0Q=v#9mM)Ch9Ga7uvYk2eIgB{};VlW7g-`ixCPFeQj3_7!bc)68$B8ha+c z<(M+sfjirzT+ThKEB?xQbhd5SEEpxP`l-0)&sYEHN}nBIju8Qa&3f+1@sZH1nv}fO z8og5${VR-0Qgr>@$EIh#D^`d#nC7J=^YfusF^07T1ZRYNS~d6E9L1Tn4^={K2nX;V zIa%r^p>iS)o3ihD+*%p7z$D_{ml@qj9F<_9#N#hk7t9D0pO_7cOfCSa#Q_|| zA!bO-5kE+)zdV&h^`E~jo8p5bavp9TOU6>kf+j*M_XIvcWK-qujMBT)>jyq>uoR*u z6XBH!Aj5Jo&zq&SMvTj9t;t!}Xa5V{so$-`Ko2_)Z(y6YH^_goTI)(vEBE@qDxHzd&U5^_m`Jj)&b3eurJ08Zivsd@? zWW-$KSSFI7-2=x*wjA2lp$k+xb*%K0VomJwb%;P$4kOD_yIz){ERRKkfK9{(6uZ=p z;H)Jn{@B?1$j$dU3kJ7H-L+`%*cMb~-M|%^Cx$p(6Wv2T^<+#E`{$A$<3he92SkX4 z@fS@~%H}N&{p?2ZXIiPV|9lpZ{>es5=Dp_H+qV~Lni@wI;tePL2jgOk+|O2+EDTg+ z7nt>OIi8UVb;dl3P|)uLRTy8q?vL2l!lXaFo3xnr%$wY23+*pP*0{jltb9~yQ)VjA z#%T#tauK)W4~|I^>7&=)G>aS(kTOI#?Ov!zKH!3a?dwD#Su#4FE45C%Mju1z zYw}Nt4EID&c0|)p_uZwe)?5u;vc%u|6LSZA}VpC?|>18VR5yTE@ObyOFf2K_=nFkdAis zjqc0;q?!A9XD?%{{qKnlM+l-{#6RIOK#kYv=5hJx19kJrY%n76wsuL);xRehIKZZX z#1#XRCAj(6rfm+rfz%<6GZ0;ayC&z4UW@klUCTF8C)kQc^uey}FB>X6)TcTR{0~GW zI$pjRkv^dpP7k%B)>P#H(ocF;;02gb*whw!_;LjngvQa!Pi;ePzl(Mk$yQ5$NP4z)q zn0gYnm5)u%zT<6qP}qE80_KS=H1Aiz_Ac!JNCuM(=_&$@g6Pf+=(zC&b}QVW`Fu7+ z5wLo!>LIb8!3xQg0M>w$>{n_W6Ls*>F^}F)v*2@M=Lv>MyzLb!CCenrB;q@HBvr@8 z7DUC>8{{8(Mr7FOGop~psVF2V9$Ql*BLyb6+yUM9LeJil&)FBA zlg`;e-_xxJfn3~)EDrs*+|Otz7k>3gL+l0$3MBE=Km7BZWYC!xDfIe@j_Q{w=1kl< z8mjXAN}eZ_Ze`WFlH+r3gbb#?JjXse)%ggzq(!|mE?Hs{$E!8SX>}`y+<6;;55^&p zgas$uS=se1XT-KXW0%h^;m(7=`L=M{cDxr6jZFZLZHj9f^lQX8OX6CqlN8)w#orX$ z)l>ZEx=dc2u?=iTgtj8j3Cqjd_d_4{_MO1WPM$S!>JC!Gh4Xe$$cb7>7;)N zfKO#CE%DEr<;M-A?};>c&wsT~gW(_H;Cs*~f6*w+77oh-N^_90ely?qT{xrIyWfgr z0W67MP+7!1UZ!7O?PL9=H`g$DuM}O+k0gsPM-M29jIW$#f&KOI_Yb|Ja<<7XzuKaK z^~v2bvYy4OKl7Ru?axEVOOp_a4V;bt`SCcFVyUf&8 z!_U4hf91k0MO2C~G#(bc{LnR~zkvEv4xdl}L$o#u(0R!B8Ti++lSJwU-R2CMzl9B4 zOqARKw=1`Og|z&kXR}X=x}!yl*a->q=gB_J*r}>=D}0`eYh)lRP;LD$s|QN~P?VY` zvCWJy`_lI*VUlI3R0H=&eP?+#tF=4X0Ef`F%cf!Ov@u0^I;*YVSgc2XN zai7@es({L*wdQ|G7I8BO+rYp24$fOIzIAgv`nEkx=3F?q(|2Fiysc1dV({|7OcDgV zL2O>FiniWLnJ>{8CR%^Mkol<)VxtI`rBD#eaBadod8Br_{#B+VMw>og8PaH@Tb#p}asv-yP) z1BD2S$o(9m3Fb3wIXd>SAZhtRMdGqibaK`SAW;LkTPvfgdAUq?>w%Q*V6M(njb`Ln z(%B5O?Wvk~BNX4;)1f=)6mtJ$v_CF=aa*I-ZpWY@J7Fm4ivXQqkKhyE*F54(6q9&0 zBJqj_S%1<=ip_A7OnY)8(OA)Z@y(7>2hyt@%bA=XK2(DY^C^zj?cls8SClm*bGfld z`wqyjGob#3j8o&yF<-n7a$h%*&acw%)C3!344*r%on$p{SPSHnnJ{kQb{5n;=IJ^b zRa)N(6a!?wgB#MD#vkFh-h(`;xV=bcjIWVmTs(E!Pt=Oe43D==?hen7V?~IVD>FC~ z*s!`1sK)&g*{RN(Ks&}99!s?4SWU_*dWfzv`6>s-p&rR#^Ie?AJpALXO#X>e{~v!R zIJwHz4NQGR0{hawY_bd1eAfr< zn#!ovWFkSk&xzKt!<1=ZEe z4nKo!wnG=j-|rASU`%6rJmW>t2sjKQ*4)aEhBT}74dbK)v`TxTi`4{e_ifzee*h)g zTtCEmrCS|#vJWc3nz@qCFs*Q5Ee(}C^X*Brnt6UWC}j|1Gj zpf_lW*M|UM7pe)Y`fuN?PX<`>%1{ISeL_R_ zc<%k4eT&i^krn?A9ta33S++Qc{5h%A@0?use33fb2D@5e4ksUl5qoUE80hM=7&P_G zI^5?!{rDC0%F{?}LtRQ^>Niz{{aZ`jQT!FH46!Qowg<1Pf2ZByZ58qq3G;=SL=JfK zx#2CtB_pbWc%8FXI5$2`s`-TJcp9XG<>H6jhnLM0-7-S8bh|LVubG}da+ zR%X8mZ!f=*Z9h`D6~r}p22MG)*y+j;Fp^?8%3|MlKAOE^dwo+t!fuiE@Y_3!dXrx)^A`i|& zg}H?<7yWPCtl7-MC0Vtt4xuZ)u6D~28%5Xh_9Lq+3tC3WkUC?uwDL7-I8}gPmg~3RW)t?>MXQO#@ z^?JijuY?Ni^nMqhW6lU|wgK5~H6Poncly1Vr|&7gtu|dGd5SPMIGRVwIhIUimxmU1 z6mXX;9?O9UvAp7pZp`^9Pq<(3(wQmUglK5oj%_a7#>UG6uKn~2Rkw+LU#JM_T-hVP zk3$?`cWWen;9SeL-H(9l0Ei@_oWf(ibG^9nKIS9ji7rn$P^2G)_rMpmJPtX@qXLx~ zV(?MUXAynB)A4{2C0)?q_0xTc?A$z-$Q0J7GIQiW645W3Rc`W}`&M0A*dp5=Lv6k* zGZ)AMG9Fhxlx{wrULILj@Qtrsi_LLv-cbFP;&UHOj4YtP?$g{%`YVgyEzLL@GQpOL znt?(vC#2-0!_1&k5yq(9qOHrtr*V4tia%FLS9CiV+An3%;$8T)6OyV%MatCqIP~I% zhK)%mb)7YyabT^X(mG)vx94QO8}07B%=NUnT=xT8oi|gyl3OnIh!VQlcx#IKs(Y)= z$1Qq3p^XbDfq8jL@K)Db?A9o^Ka~@Dyz!IrFVpjc=Fv-|r&Gq<8f@Pe5wp*(@g%O( zV({sspJL{NAy;)6n0*tCA0hutIb~@lSe%%-GEYCgN^+B2Recv1Zk@h+5-(119Yv2% zNz6rvs^)P1)UgO`jAht0NETDOQ}-hO?f!4S{QCOAiASF1RfI{`G;wuwV=^w&>k=L& zJ@F+%qk?RFechpC5-jZXu8(|W(na^|HJd?DxXX=J?#X&78KYUy*QH zzM>JV(otP7{{Vhjz1d`gk=8PFY;Ew^wlev1@^qX*-QjW4xgO|`fGwo?x+F10#zttM z)V5KIUS_@%dYUzFp!Jal-}GXML)qjoYF9W-Z@iTb!Bb*wSvY~|C=n?t?G}^pe+^Ps5ZDNe_x|*0Q3VNHT=UdLC0nvQQIiQM4UiU0x+k(SU;cV5gd_SJjC8%Hy?8d zG_)YaLX0*i4j%x42o(f;KALtxyftb9aQ4U_8(^ zrDjaEJ6k6t0tmcdugI!6M^zFmyTZyrm-jIqIZKtZww(pBK5GhwpD+7DExyBUba5ix zuWqji_Ju8(=fkqT{lh+F2ClH@TX6SfHy)wCQ53&FiyqGdt@o7>FN8yrwaK$8b!#g) zE3{S>qJ#?=9HP}7{8^1tfWshz8&prx4M&B#`;)SuB(|I?OKhzzq~Ra+ZNFT;V0lfp zva9Sv25#)ly4Bh>XK(W0cZYLQY15??uT-&&a|4H^e$3s)(C6h;GkD3A>GAk#!%`M0 zh6QZ~D^5lMq#Iud*Xy)ppG#S&ty`pY*V|Mz@4a)85L2`%(%Ef`vzBC9NkM6VqECeP z(ci-U64I5p69+6w`TGqnZ5c4i=klRC?zV*A1)8emI+t41IL7S>Qr0Z_|8U-H2Ie3I z_#GtUGSX&{)~xk@B1{fmG&(&^;62Kyv8maiUHIFo&sSAL%Ai#_zoQtt`q8k~NrRG4 z&;TE|FDKg5MTut5m?L+Ua>Sk8*E4^6^F@3-xYD}tbKX__9q&O*ra}7~+Nh_wKYWIk z7?I~%KFj-}kq7sU+paxWyZtCXdmpZ>77fFiYnw)%yS=Oc93n z+wQ9$$?D8J)dl^JeRe)o{6^&UGuwH)mlBGhFJxwQs|Q(&yOAssbt1Fj4=-M*c4N0X6V&K=-5!Ihsdvc{g1dJ? zNte7|?XyyMstX}}FyT(kSdcG(Tdm#+k*-^I<7bwU7ib-M%Xc}fC_x>82L^xpSc$gd zbs;c?hG5KAIp&As9(HOv@znvp=H9p4NJ-!r+u^lJd`)mFVqm6v>>agYD)Xa5E>1>G zJmY)qmi^KFXbIRZCsrXM=7t$oI<1_Nk2V#kYl*sCXU>K!UFx@K&7kv^GX!bq%kPAx zonqvqH}TcBg@)GvTC`~9-z@?LPz{VfhUAbH%!ZEQc1snNC`r_<{rc8XDh6bjA zc5y5T23{r=v(j+C#PWbi5cx&@7Mj!OJ_aF6=^fK=1n$fNC&C&>(Rq?3&afbl@6ul9 zXd=szNvS*D_AWf2mg$F1_)iJ$>ZzZ+2TPo^uxU-(eDh35cP_dg>pDm5Tk4Zuz^^<& zHJ?V<0GoX4o*@Ckmf|VTtf;>~)ip*EQ78|Yze}Np4m9N0(Mq`E!_)a~x7q=(naQ{l{h1Rq_dK??d*fA@FU>}N>$3$43aq5- zQ{4;V!gJ8lysD|VE{5~r!~$miM|5?c5v!7*HGYS*-Gsx0V120_B}x|Wh71X|9nYTG zs7;X(CkF7e3%U1Me{c*1N*u#ZY%IG-k+dH$ut-&5)?g&{LWe$f|D5L}&QK6&uyPDs z?!9a(c{gRFEJI~a>y$r@L6L>n0cvGOd}A9pUDKcVJp*knRc|0`#f(5YBdPn6qvWQ7 zC|(rX1>0*TPC7-g6Dq4gmM!<>VL`O;TsnW%B_E&3E2~f!MRH6~XkvBZ9j@qH=4u3O zmh26${u-G4d0alWX8+Yo;#Mq*%2Tro5ISE4ItV-mWBK`XFkfnGZ@LCW~pAHGd>Mo4-Q)sN(Wi>L1yFwMtYE=jGu zWElmYmKBgZQ2C&;8axg0aAiX8&oH7B`JAN&DM|$}o%_BS65c9SS~;NnfFQ6*?2k`m zuQ(j76D#iO6fi-yXzEWcN0lTwKc8>~gx4&ZyWoGLZID5)ex5sEsP9Zw;vpWQ4=6^z z+dPqHTATSG<0sDJ>^Lz__d<41G$_yYB5YM>HkBYeey#G@?&G<<>Cqd){|An&H|9Ld zeoR(q1m?wX=^~1b>#I z=Z1P~hZ7wW#tBJ>C1dAbf4Jt%AM@>VR$M!nEA}o$k|?Sx(m-oX8yqGvFzre_ZU+^G z%fT|_+TgpyxIZu$WY4mG3~%7Y==LOWoOs4$kG>?AFIH&6i`(fVoBlkrcbf^!$ABO9 z{+k@ms^2cC-xg<+nH<|zMxj_`-~o2z|C0p!DTe-$tJP3~uXkXOD$3xepG@XxqPLq7 zbSpc$aQe357clt0Z8%+`BSc(`4=uEQ!H{$NE($Kk2v)%3SRoE}h;e21G^l9lfM@0p z=+aKUfAoSdPBv+OT=IlEA#1~*spn)5l4wsRh(uZ5Jda_X*20C5o_!O7O(@M^NJme< zdtDvT+~(GwOc;L+`E;acPV2IbW5mX*2jyEwEafBFllot;jRDnhsjXy@o~jtE4Ah;@ zY6e+LXC0_yEZe0ENQFO&5(j9DeURl!(1YWk>~5i?uQk7Po1H6lVP?vfGY#*DL60Qj zRc{K!R!Tft>AVzSW_FBQAg^h(Pln!^Y*N^IeE1nF>Lclojju%gW_f8*3^j&_m1>v( z8j1@R&7LYU5DXB;z46hH6%~~Hkl>G1?8c|e9J>u$mrA~ z!e31mfwm?=r!rJc++jmSV`8wMg}n+$L4X$%fFE>np|ZC%8>7GzVjcm^e9M+56(-xv zhUZ>%15_n;6dZ8Oss0_{pow9>jeby1y;jjw&Ygk>3M)c5r_={A|H2DsE)GpiH2&lD z)`Bw4--bo9TX6%Ppi$nn;4Vu@?*rk#9Tc0?u{JB_ze+M)TSij1f z5;H(9<-%av0s=7f5H3~Cf)*dDOU6#7+?!C!wHqCayS6p0e60kb{^z4i$$O3|;ow;* zA_t30vH_CWCrj(x&)!hJY{#GJj=^uCz z>&Qjf;<$#OEbnz0 z`MillWID|laEe%sL2?j8Z zbtt5Vl=;6|05BT^U4g^_SQtH=sm>jrg*@FXAO7L=f4emdHQ@4!+=VfmSxKzxf(L_o zcj4Cc8bKmR)HDTO0$Mh+n`q^S-z?Ta#yIXYMO-chf-ecxVMKPmQ?_Uh6ye1lg=95&bq)e`8)t z_X#aN+Wxg431~r{AOPH;0`waskk-;Rl%OK%l|1nO9Ct~g2!ITD5T`G*IElDX2|3Dod&jG$|1dRO~0;_zGLg7 zW6sV1074&Lo>q}OOW!(w$BdY8CEx7LL7uNi_HN)cNLnu4;CYLIa-x8W^lGyCagzpJPD^@44kq=@BkaOf6iX9n1a z#(hnfwl1m)H7GPXNsMQMviUf)t{ogSl>-ssxwS}qcfUryuU?cF`eebeH(Wf2Snx6< z0{b7w{_Q^E0NxmXnrX+50G}(!Ui|nG0aVPSSEw?6=d|g+0u8#)Y4|xKk#JI+5ai{w z6$%Z9_n0AUQdqcFuS{to&Z47@_b3Z5+}8?AK`T=Ye+A z@zz{6j3V#g@->(K+myHRiw+k1?w3GL@6ujG%HI$0>iDa$ z0%jpz@73;rN8elg>ymTtWEYFEv>6#;o)h)z{6auFBzcEmJ621AGo~D%s<-fNTz0Y=QyBW!tif3 z6jg^qo<5{KAO1!D;0gI9V01uMj)h`K5uLKYTGnXvf-G_6j^ri%<@!R3s(_Da?JHGA z{r;b3c3%PKCc&8}6^gYq;gx!e*gwyXd7LfHDK8~Mk0L~TnmCNQjL_bl6wRfaDOu|$ z3-)o8Prf%xDvA_3W+2k;=lctuaIQj^8OZehYdfE6*NspDxmX19S5UP?{RNG9(THvH z7@7!Eo%n|ugNWzv{YI*tz5PxaF@)@n55}W;((`?bwC`9`owR72_6*m>F{unJ-TJ~O z?*XUt?5a7nkm5JhyMqD3R@J~jA@$Q-azwW;MEo9yg{%s+v*lT~eJ#CTK9TnE#wdxD zUZq9xhJJo-(z8q1yS9*9X|UQ&TL|UuxtiD|m2^VbSLt8D;7%3Z5(7x@DStT+ef~8> z@oDmxnoM5@C{nw6QpN~PFfqLG~XuHj5-wenQXKvlm_4zCZ=z<^(F8q z+sUWaZAt?&h2G)ytXf}F#8k_z2en7mFr2wg4|!4QYJ< zsV^|KFB=bG{>^Fdn)IkW2+Dwa%s~c{anP-NfGbN+nHQ;F(;S8cP*#)B`vX~u&oPd{mnbXH`9VwdgKSD1-BK-CIEwf|0OROxg!!VrqSf-`xd*Q`NCZN zUY&YFaFbp(8VBcEQu$*di-n^*hXL?5@U~r*z%c1j^6n-gx(WW)u;qMtxI{ThhqG_UFSX6ij3Mt}Bdq z-22GSM1OA(hj+JoanAP2a1CP^uUnI%Idzy0=K;Bls*Mzv2gD@DU4~jr)*?%PPIt~% zI#*w&sJhbzsO(v-*P4RXyp&<-^nnTLZPj_(Te*+9m#{+5%l{g~)6?K(DTSqCN7tSW*H{x{$XKGSnx`xET@k36lVz zV8>fuy(&c20(YZ{B*YsjaJoho%6+nDaH%(w$uaCw3wM59;ZmR%fY5Ty;vtli@kIU_ zvD5QP6%F{5@AT=}7OKmuNM(jK3H?5c`?ViSQh|XTV11h8wqhem7jVIzeu6aPz!zNU#Gj>?A9a!Ur?07+1lH=R zm8gkV*1RPDpgx1&mGpihf7pqb_2vOB?srWGv+g%a>!{G(Naq+4 z&J`Nmp*S{(mm5J-bMI9u&!yis^T0-<`whYM2T467QN8Rt2MozIBiOmSfqEA){*G8m zZf|fD3Z53|G%){Q()osL*m|APMkTUyzU+h0u=iv<&ea1+vHsjW{9l?9=|1Q;61)n^so}QQHPCaXh=l#1nO)H2VN&6e@Do^62jrF@O2*p_sk-J1bb}Ab`a^Y`ebC7uj+07j*(>tH3Ew z@x}UH2CjEY_4&ylj@AeDjKW1E!MR|g$xLt}7Z+2$*ZNODLg0ISnG5lETR|DhQ5A=QN#_S4+?KAR~jg z)&|`eGr;X}X>`bCs(CrlEo99y0+LS|UuR@aE3{da7`a*{Y~KXlR`tFB^OMx=5#bzMIX$QgUtHxK;=dGd955AsoQ`*z%I7u+2oc6aeh-hY zltGU#CWE6W*)EZAo!XVrC>hU|M)yBXb7dE!-kIO zZ9LMMVCC8*Nr5GuDEm{Y(~j@J2m;l`**|*5m#@6 zw@9Q<0|aYfKDI<&0{;F!fS5m-+p}E9^@LsO%85#JfX(@P@1$9#mw-}zp#XpJ`??a< z`hP+7fP5zMzw*p1=5gR3@V{)N*937%L3&uAk|b% zk_l1Q_%OJmm4U1;Khc^xSm$0o>-l4Qh;~Y*t}xd&%2fID)4*T_l$ie(zzU;En0&kd&za$$%#&2< zw58|{ga0}2Xg0bPz494!QutHZW}p~}M|$x0$gv5mHWZ$=vBYY?MyXWr;GNb z@WYpfC)b_~NdHO0dw7SVOf|zN(WkD15g>OrG0TTY>jc~7>E~kdd*B)iug`~?55D!C zWVe;FK1HNZDOo3}fkzupWjw7zLre^6K5!IuUV9;uP=Et!n#TIAwsVMjp~|~%4t-}0 z#jf@Jxg4o-^D%vco9Kw=9DmMP){jnP>)?ttpGzwDa#7DIJKF~pJX+0bJHL~&D6`m&(m6xh6HKRq_H>VzuFb@L6&7X-?6+Ak^HynPk62EjYWLnM~l>iFiD4& zr3*azUWzi#8UHi(5Tb=y_Zv!Meyd)S%T#GN|nAmoBxU{_RfrE0HLp_wr!`c zLgRlDv#~r*YQMymSG3Y5nvBu4#4&kak2w7{@mrAc6N{Lf!4CPD>FRMEKhu01aSGj< zm7nh|v(JWIOvD3^AcTjnlN(m7HOA+`VV&mVgroU9Lq+uA%_%2jXvn$`;>AF7kPnCK zj4c-?LuT6^xu^JUS@a^(u~zxwJj_yzWH;(YGT)H3^U6QygRLA35=zv#$x_J$pr zHkm|Jkye?zKZM~!@%s)XQl^V!c-}=9=(-foB;)BF8B+dB_|BP3hw&MwmKAEXmCsNg z7R|4%mdpc9V6$5rsLWoKUF4&M3qqZO$PgAb zKHU`e04Zncg3b1unGHPIUeW=Ks6eEFV3{ z&Ww;It=V_YuyD_<1d0baB=dtRy(UYa23{ahNN&hZ->ud3X(KzEC^|`DAR3J(MWssQ z+M)yd7i;PZe*};|O(rM;CRCnbD;99(11&!^^T8>srZS94x;;vWbeOIynqqmzQ?iTo zT2w*c_tF+_A)J%a)C)EW4GFu-s~ofd-6-0O=Ufi|;STu&hlmxzhIm_!+Kg2GX=lFp z@Hkmju}*!h6j4pm+o*9a@C+#tAiGn!z&rewhH1A@&o7dBcl)OuM>ON*bKqJU1w(md zl$KMyBCl{AnR>)$v@uz_TrH7YVhx$3*WZ&sT4d_+u+Qx zZTl5_#mEX`E`FvUioKCsK3oJv&6?6ZNidjA#@W54CBNT@0)g3jQQK@lG?+8}j@oox zB;BT5Nu$%OQKwCAaoLet)`q_DsoNzUJ8<+7Os?zFhYu*e1ubQjf@{z<8Fr zAA==T|At5?tE#j|4}O?KjzmzY+H}O)Bq_WOih!Qr>f9kTnM+$XLVt!tPi%RY1hKUk zl7G0Kgu-)|jm%p=DkT<_l4Om>lR**O^Nyy(;@v&?bssjuEmsv=!lkU02M{gqg7)G= z^+M_D$^^i3iVZ334nO0$K{ma-KOn>eAtZJyI_gGrzZ(VFJ@;W&=y{ah9ThLcF5+oA z_j}6PQf;ot?T;Ds^IG@l`z%Qqt2s|rjtM{1ep~PAYYF%PKpw~qHqa4(bsF#nKE#hm z*L<0`?O}nMO_36+Q3$S>93)iNv-N0N8%eDg8cz;4z@zmlDS`;G*lP@F6x3&H<^&hM z9m*&K(}d2BxI|eXOa)yZ(khCL^e^`n7wzH%DHEBG}e{EhvB22e@nm-@(eW9Vv z^M)2^^oovo&CuvWGrFeE1ADVIa8mM{%AaFGV1A;7Edt^Idx!&!`8Sj*M7 zjpk_W(R(F&WQAJPSIWn&TIa_hWEttry^Bvvg6_G+tD-e*#!7h%{z4XcHFLaBJ>QEM zGjbWt{_Vrj6j+slt0WKWYQcCmQj@_D&bqIjLH1Cl^~_0ib1K?c<}D&Ns%GHTMv|{? z3V#c~mDjJmQAE#u?rZLR)HvMZiZRbJAzydAMgieZ*id4~#G`kPD>>vsse zgURAY-DdiDB(&V0-`0{v-0SB|dfX#?Gec8mh2w*xV-Iub6XTiFP^ZRdZbnyHuG~?kTScfjKLB&;`0IWm>1%n_mT+Qx}uf*bV zCffZ`Cc1uu)X!Q%ri^l2X6|5J%mcL(Q-V?$Fnt`(!l#E&Lz*e`QTTPrFds{rtHB-f z>mTSVNFsxC2}CsWyzrMy!0sB~cLcTr{9N}#n7_j}%U=G0;hy9hEt&En!v~Lk%!O0J zkLoDA(5-VR3qnqqqGkOIzy4#@GP$=gn}H9Xhw~K_BXCfY)8-Us^PwOYVGsk7N^QY$PZt(fL_gQ}KW zt+7(h`W&i1$5b0WIm&33dTHs|=cjk#^s$1yKv{8#)&7i=PDpm+du%S_)>=L5h#S_7 ze%{nmJlX0I7&xB?;azg!#^{gv+N-j$`-E$^fQWyq7E=!WS2ZN7rtV_1pfK%EKM2EdVl4 zgM*c@bRrcq8m9G(AB>-*S}B#vtxl1nXimXZIUFM8lo(lJZWKX^Vq?9Pou=}>%ES*L zdy6WuPdhd>VqWN<^)lQ!Li$ss)GeOJ%*A^5*uD6^YLe32nx>>wEb-R161@W3pOG@{ z>S(sm2tFxX_vX+J!D_H~{e%#XAOLfSlwO}xk=4M?XIy>e({AyX>rr*j_&**1D?>U&;!A5A7!^M+Gm+- zdu0R^>U=vZnX#d&YA}E-^duxDAV{Ffas4e8>>6P3w789^J+C3Kkx@q$o)u9U1xAu? zu05!=%WW|AOgO!>AAvrmF9r{VH#QWPpK`6thpf`lA?|A;9)wj2$BzU?@g9B;Lk4Z_ z>-Xj%)z&GaAWsICeukN3vSt$x_eZk<=QgRI=M$*d2+QY8k3g?*o!TeJK+s2*&vL9Y zTBx^Gw6=BSAs?l~XxQ$w?#S;Gqus>?k`&;dVlM16FEH>07N@01lQO+HmO+$VhhPQo z!9nM!(Z9E))$48`(exb>#j~sCu{SfsQ$4e6YUNtS*edk9xpL`$`fGkjS4D39CidML zlgx(Y?Eg~6`B{3N*nA5_?ViA>+nv!BLZ_`%{!Dw#jUX68?HqYt>yj-n{iAYvXeN>= z+rq(jf@vl99Y^7OmYicveb)%*c0=fJaxGSF>Z5H_lhDrx9N?7A9C^Gi8bY$1qgC-C z(3g`r|11Oq=XZC~_q8^c!31<_Q`=kFJvKAn2mX+*?1zOZyLkqR-3a0!!BU5jVuSO% z*k3aR-$Xl+YO%Gi$f~jwn{QX{(+6^uP>JdHSV(gScnmK%dHRb!1*2~gQu_6Vn4Y)% zST%(I0rNgbwc3pt|8@cCvO}~Cmg}1x{RD@tg1pDS13Ql&afC72>UoPqi*>bYa)Xej ztl(`T)c!7E5PdfJ#xCZE1n-g}4`HD!IAk&lC4}7NI7Ac}jWRdgP@18KG>;JD9vsP# zU(zEWdMA#F4VOF7R(pvl}9m@ zz+z?tzlJtVm)fcn)q1)0_k{$bcafAr$;w*4%4Y>1p@OE^e;5>_i{<6vrNdgTNazO_ zenK62993sDI^eC6T0P`7)8apu_bBPI4XJ2QgW!?V3Q6?3kpvC;u6)Mg_iy7hSjgC9 zL>KuxsrQW^)jDAx%lL#z-p-X1k;I}Ge^Fj9uiniRT&ufSyiBJ6CH1=Ya(8xL+bxdC z{w&ll+*$;2YT@0}#5kU2i#R0Oo{Gs9h@2qg4~>PPS~BLMeChqwTK<@e5|OCq7}|RO z$T}&`Y0^Hur5oG3s$XDc@6OPdPEYTMDDEc|GxO@uVuzHZ+aii|Eb7P? z%xje13!>M!cE4P~xL$Dt?{8VV{Wj#md3s2y$8u9llsnOe5ZDMFtMt_hI$JM^|!Ra|&v$P|&>_Eo~=da{Hx?cd$^BDc9<$;r?S)Ps5{qaRl@oo$>PA z2b&NU;v~f5phci2-g+>8Tx+vz6?#>XsmW6K{GMo<_f-JmO=d7wgI)<x1RBh<$Rdz>9GEgo zDziHLI}rTBs@+HLpe#qJs;MeY1wP_hfM=at$wQ10!$a`WC2~1iDBD>vlzuRy8$)#0$^GHXo0VL<5U}gg+Z@@Zg&p zZu&sBBq3k4GZ#GcYupP8hDwy*X&!zJHo3|<+?ERZvFplT7I$>gdeE$+Z<~1hacsWt zypy0k6w=?yN|cV%AqzAk6fsXX9;IcaL$1ZQk#16;p0GrKif-ji*PD}vG^5;BM^Db6 zl~y0XzY~<%JDKpVv0L-LEa2aFO=c}((|w3arS!vpLb*o0$HT$%HVzNC5VBkt?%x$3 zj9g{JAv}b4k$F!W9IrpcPv(7Fm){2xKYVK@qvcA$KI2qL<9{{1sPaI2P0pwmxj(gy zeDLdMP{Stpj`SwZbu0s#fMEC)u1E6$6l>_@#|>e%`BXX!Xk;_67EyE^CPkn8YH8ry zqd_)sReg%YgCp!GgY2exZT(hzUu-H&ATs$m^?xwg~%m*69wSbBP~%ruyl21 zh#*3?Y{P!EOUEk|ju=9-9se#38qm&jxX}7-m<~w@AgFS#i@qnd&TRvnH7Tl*oId(C zMG8tc_Wo{Xc5n}6=4$b>z}8jdRO*%<8$@oJWh>)LLC5w})zae}peFRjl>Z#*T{Aoc zy)Y%+PVs_ZhKN)P#RWLzuhz(8Zuha?_l`2I) zFo1$DgE1-o{31qe&Lzsli%a#4`^+Tz0ia8LACY<_l8Zy8FTyKgUJ#x{`h#iNqp=i( zrkBcLQ`M~G?G&SXU(2rKQ65dYNrPzdDy_mey#<)dnj=>NQ?$r3<%V?e3^o>;>ovD< zyO>I;G_-&HbQ~kAg})Y(*ua4#CyDEk-4U|+Je86f3j=<8~vObF#|P$ ziS9~&-*3?!KMv{Six8}#^V^NNTuFRbYn4omBVn(>-K%_m9_pGaBx!G9w?UFpct0vc zTulOsP&pj1a#Q_n*j@ItRAsyZj|}OAT#n3L7k88p;@FRsspd(&0RQRF$FpXmk#;vS zF?e4(+47>DQnU8OR_biV(R&SJ9L#LquYbz*1U(`DJo$BUxESU!u09@%h@s=F3_rSv z5Qov)D4&VcH$;9Xh>Q*+pM|3nd;iWI-Utz<|BukjOfRKIF3O+Cb?gMQX`Bd`WjL0w zA0I8hlaLw0b%dOI1>Q0@O5T^~n>1r}jj$qZk{{lLX1GcIsX=;lh!*LQh|_D+NoHu& z6O|+T_1-*Vu|}`bz6vdZI`5m2Bi5>+dtfj!t(-|awK!Q!3nYLvy8ryva-%fk(Afy8 z+ZytdBKDn;HlK!Y0E%~$)uzNFded9tG#*4@A${lZN<|5g=+XGk?vXKRHHo#+AhAKp zYN;@a2jA6#q}wf0P(DFK17s40-sqMayH4Iv*R4$$TJ+VhH^-xMg6FguEV9CKkm4>SI&^efpV)bJMKa% zkC$*CaNkrNBj;q}By-ezsP6PpY$mfm_Ixz*(ZBV(ojS;M4MaBJt90Q zR>@PT$4Q)X+S$bpW{R#B_Bf!95|B*LX=S~02|yYZ^KLAh-1=y`mva$0%2-_4cZmwd zaS-hx`yH^PlrjGB1p`lDnX%aFR9wBGuse7U%j3iwhmo)R@>hjKVkXK~d(YJRA{L}O z;GxA+xKX)buIR$v+bcLB{%D*}UNu9xPElqMPu0iKombFRwyB%QTUbExCj0#Sna7Z9 z9oebdQeGb*|Ng{c;uoe8V|Iv`?xnQ$!szk+NFR>qzgdJZeycZ^ltA)5?Xx<1ss`zT zlk_=rxDRMUF7T%4ag;Lhys|**M#X#MAnlZgV~R&t?>1A~n>n0d%D&+9*})`t{7c}! zAH`n^=tNaEwvPBg6LM{!_F1y}!4qUBYqEo>zev3l@NNrx%@G>w;fPeEW z4dtl(sp0>z`2^rK{CcINj?mLjvQiUU_;8!f$ef13*8Kn;Ft4>d$2mdqM)D8ad+NX8 z#LN0&2^F>+-+2WW^lV!NGHuYMhZ%pP%m{ysOSAl$S*k-b4HXD|3-jWY?kVk0#!;SF zra}9J0Hu4)u-9}Dm;CEuUHbUFF1q)a&rk0Evd0X9`BR0sl#)exxUOyY&zUD{brCf? zHsot+qiFp8#=j~qU$^%-n4P@_r#jpxCgX-AH?#f;-~H1o6VvD4G64Lkan;8_Nzx69 zPHBvXBEo;2WaRU+HVe7Y06VDnl=@%dX5c;yp>;Q{S)h~()6j<>W^(m7r(9Xxue+}G zWla0Axe?dIngH*+X98ZGKZ5$^5ucUzdpt04jo+eop#<-9Ep3=*7 zbH0?{xL_pT7*~fI=bXG3=1<1hQ$aCG%fk3*4Bz>olv`~{R*lPymn&}L7=tp@0mchZ z^}YIeSilE%jJGiV~T&dF?Ta%N2U`=`Gx z^97iJMOyf^DAnEhZxL6!x_g<7!BWHRHl^U4zS@#Ogxe~Q0shEer&MA10RnMAEJTfC z+B0^&$D$+Zi*PtDOBBdFb20N3%!T(@Yk%SiMdsMZm5bL>hnw^q7`;PSE67|2xN_|} zrc?QH#$$=PAXo?~>C`;{ovpsH?SJG)V!!{- z?`yg@W;n4mdhQQj3qU4*UFE!R9^SpuXB}|;DCH2fHA=SLU#q?m@=bONW&6Kc z$b|xpP!Q1P`C3V0zsq0%{Oi#{?Ar`smk!(k$NTWBykxSrnxR>`4PAs6OH5`t=1jd0$`m=EK#_&Fd8dEQEsN zeGc3RNTeg0X_X_7vGFz1`d>+B(d>;C<-irDD<)Ta==f09mR!kg%>O!ViUR1@1Lg~| z|2kTzl;VxM3;g{&vk$gmDcmv674U2T8OH*eevG0~zyhdCCxty7d>YaIuhn;bMFtnI zt@*!}0IF++txx)2bxETrA?NP|4yndN^9G>&{{_VNSExOg4Ei5}a2xEqB<40OowcRE zb%*`hETNxX``7vM0hns}VDWHZ3gAwt#_?)!y;lD#Vtp9v9R7Zo`I7m+s&;Zybdu3Q zVh|*Y;LVOlxgnYVi!*?3OA62D*DfUVVEw;$;sTn+DXZ zi%?TPJwMJb_;O?i_ z-<|h=Q{ORa)ZG5WMuO$j|EyM)V0Oa0;7VgC5U&qg)L!vNTnHEyKi)KtO}>s=FC?L` z#4q|}B;I@)h<61hTe~BhPFWZv0`zumbJ{@>A1N{;2q}Ui3IAdr^v;QUg^yvwAYE+q zNWO9lwl62Pa&-&7IPQ;c^iSW8@IL|`1}oh`*vI|8&%u)Gs6eaVqjp{h1JMHLQx`}( z4MrrotQ_^J#O)aAfkQQvx|gY0ir9~4U-@Fk_kcgcPN$#0-aDeuh?fm4E_PUntVqIy zV%#CfEPb+RSI%!1mr3>L=+}~p)c_-f=^pRzpMZNE>Vam0*7x7J{V%XkvAA+#c7TkV zRJF-~$#QOmDUd1Beg`b3#n?5Xul^D-FU_sq_JX21Q2WR?lswMGag(hRa0q`|pa^2$ zH@yY#?L|?x^2VaaZ%Ow48{2O(BL6p08hw9L{E2WWoyGKB)9E4~KtB|x7y!i7mHXNa zHi;@cw}SWQ{yd!pG4E+(B#T{pDWN2PD58?E*6*Y;_?mL1l9en~%1Q68@RzEcwJ9kd zcl7{DJp-y?`n`$?=}QlVebDQ>1o_^r|Lwn!%+5; zff@CkxT}LnsjzL@$2UH(JkQ+}nEbF&8zz?6EH;a^G0esY7E{O3v9RAT1iLY3arR?L zFE~drUq?PB6Up-bLJ$ph-b*f-JkLZ07W#W95fY1dBngTIQrp5e+{*bsV|bh`{j48g z1h9!;>!tB*M8MAFR0_5aQ-ADUqB14TDhx zKa+uv+sY8L_<)&WrHQL_NWp;r%}`#VNh0dOB<+CQ2I6fE%v>L28i{E`rrZ-HiV5KM zDr#|9n3&*q58It?NPZOLmYvq6nx)I+n^n3%e)W@i4JTSGgLS#=`^1Ad8gs=TZzAiy zg4zIoPs>7EGc%%fefAz zRTLNytUW`)ubZWA%yZtwo;TbhRB&8MRWkT2`_&f=%}od5>=p4;N}RF##8Xqg9}(M( zMTWgvGG2m2pOD#UK!qa&?3Ji@Cn~=hHr!1RRK>wvssd~i@bA# zMBj&3G${O8WcSN0gyTrg_0)Y23rvq>FtUL?qtEElXXEIzlA=^(Op&5VEe@QOgL4Sw;)^K~JVKoWWnl6_L68uv8q?G%tmn#zY5 zr+$lB!Y*nE!>1sHX2Az`P8dsNsj3>hJU?Azdh-Y_$Q=qi7Pj7xK46VW>A#dx7Jj&i z=f;Jd;Kzu~my1n_A1Z0qs#X?{RQCpU042K@f!9bngz!m;V`D_x;WqU5j*PmGUn;6Jg|2|L2nuxr@(x{>{RNFrU)L{ z?8F7Q&IJd7QW;zN;a;KquvI_alrZt(3^*%=>e^)_OIMptK+Fbl)GUlR)iYBhNo~p3 zGlJu2l?P1|^~ix4w}Clek35^JqB~kaYjO^lqKL7CEbX_!m6~+%?U>5BT;=r+#5L>| z;$EsKFs#%z4l&90rRS0jgnQEl-92K?L`0x39p_xz8-tj-%jaBp7mFKN_VXZ>%8(yB zd_ospC?HJ(edEXJA>=q4AFp4oZ#RV5Z?jOM5I-L353iR za=iLw#V|u;KqrN*NS+SS9kXu-lEQ4EkC$;Ht_>uyQ``B;B-v0WbnwYffS#{)6bxx%((B(Os8?Cq0oZ!@$8sGL}e>1YaXvTyiyc5YlM7`6=mr13~{C7q*;6&=cJFZLg@^B_t zbg96)qN6+;LG=8vChL+yA(q4x7Y|2D8e2HJ&v55DWj5e>G865FIa(@2qqo#>7KK}) zwv=E0{jDt%zca$ko}Nd~B%NY8TzmDUDAM}xr0V)+ibo=IoG{saz`GoG>f&<2# zYoi37K=Z?wbm+rB$lhti(m;YHi+PO2mZa3h)xjneR<>OBsfYk?_Fcx1UC3zuh_>n4 z^Gm5uK)!h9aACf+J27CELSZVkY?Dg)%M(F#>(4*C%0KtWW3qt8$mr3!g@Y%NB^F_9 zC179;e8ag~A8MbOQ9(d_${l%f4+^;2+`7ahIt8|h!9P3BfHgAB*O$OauF*Z?3u&gl z+?@om#bvGzU_O$}cc?s&!d??IZbDbYM=Cy~p6IH7266^ezy}gipT)o4Eq5YeaRJAh zda-WtHr*GeIqI%jQBb9RL0!vsfY29vE>jbdJoan_=NnF%uQ0(aJc$lG8FT z%aRgqD%`?A!5fPF@nPsi?+DcK{I6wU9+X+Av*xOo=ucN=d!vG<*rx4) z&$6EcLTZlyEN*anQ;4wsVBrnGAc>;e8KTXW@_`LS5626`y%BvPy^#rNPiEE*`uULo zy6P@U!%2r3@XOk(g-z!o$pQIi9sPBcT&%1zo1-(}U!aHSuZHTiQ!C zZzSVr=gPGpDSR6GpV({|VuLUyWR1jS2HnV*^V9gu^#ST?3P8N$cz&+Ql}_cTj+9Wf z-yAP!Prq(!$8dzK@-IjyI7r}utC+dVkGO}Nf{nxZ6RV8qaPC}m+8@n{JoYAME-K+!54@RN6ANO)Q!5WHz zNKUsAdxp*B#kK~P*q>f1ZL3ic_I>#c(=x07Mmlc#Z0|d4j&ubeKo z4C`E865gG4JXLFjN{1sv_6OT_fPMoRTW|2=A1L?2pv!sIE^ZZ_5Vz~;B9(mGc^I43 zm2a(QZ55=fKqixFfDPT5!Q-JU;g48+0(UAC81_Ysvz?bk|WByiWW7VdYe2oaix^rWS4Z-JCuQ6VsQdU^}T4W8#hfZC+poU zcAGptu4B;P`@g9VG9m|pT$B?<%6au`iaVi*PeJWV2X~3v&phlq0LAM>)1D4t!yT(H z5BIRo?tTr>)-fzO%@lYYU_16W-&u?Q+>7zj(NR~wkzF3IZ6v`FlpcQxRenW33Q~IT z{s0?kB=I+!$`xwt2bX^hnmSz2l#LDSjgkcN*B%Aj_OoIR{aGvq8>;R9Dp46EtI%ml zTXK`=yJSCZy0Kaz6=01ircFxGe48EeU@C;F=lioKn zcc6VedY;dMzp=8Idcdu zjjmIZ{UnYa2e8=O25+V|sV0jDdN{C>{yq_w>7(&xqreXC2`&1Yoxl@L7KKUuv(~iP zvH{oT`l`N-V3vrAypgKjnj_|QlX7*{5vr5hdo%Of^B_g$6zM9eH7 zA~S||9Hn;tk=dnnIqAh?p~kfWa$aLLko!-^>WEf1*(5M#FM124u{=M&Ip#%ali zTrze%gOtsNs|WgZ#cg9JsZPUcHBbA)a93ZrkzvmL2+b96KY@rmRoa3=k)fgSK~5Gk zUZ#WZUBJVM_rv@bLQqIq^R?h}tJw4X0|{*@PB+#Ti0*Ec0%Nv>LVahLY;81+0T4z} zzpYC@JoNK+e|P@mk|Q&dawlG?Dx90uPauKBdBN@UBv}lBUmOMo?73k$;*_k zs1;_(bw?f+&o$K3#W7fYD9Y}u*&Bey&p-?0b_JiE8n6F)XQIwL#!A(NnVR&UGbh}{ zS=5+}EDBn~O23eB(z?l;C|=j_%+L*7H($Jk?BR}un1>zF$;R+bf7 z%)43uUnvqXMbFotj%(_99O<_3YRsZ$|nsV;Ix}v8&WAVihXPc zI2gx^DL!*?6hMQge7(XNASfG7_@#u=$T zsvo{73bx;W^CJLvGDZd&6+Ndbp9gG={n74yetj46)0lMJ*N&Bv%tN7yD&)8D@Pf}| z7Gv>SQUpoqDswC$n;1!~WOwIVWRt3@B3iC)YR^j5_khZ2vQk{T%o^h*Iy8%)Y_A*=clrjG!v#U%Li>Nq>p~H-brdRWGpm>awORwVElH^DNha0 zQjqtDJgn~o2{;#}I=Ai2fqjanRJ=#H41)y#mgE5}k;!anS8XCPoz#f*Yi{>BFr`>b zeR1K_e>jTI`rZCtVG`vd!O*mnZ#m~`!>$z zl4%;}Z6SH0gtA-R#IDTA*n>}6_@s4Kb9R+n>N?)ZSf(LA9+D(`GYd}x??tPlRc;RM zg0SK&uL&SCVW!SaZFvV?6b#b=svbVcQoGM}JMQ@;aX)H%(xb7dD7=hYoTsy%n+>66 z6=na=3xKu6i}MW8B8TUoWVRe9*ArlFReFvcPRwv_4_OWHt(>S@Wn!#)EPw?k>#Et0 zhQ#8J0r$9B%7D-673}F}TB>v@l(ERj31CpssOOlv9+Sm2Onm)VI^XJJS2K7+8|_T+ zi$7dyD7UvH}U4v!C!9@i{;9U9e+CH*y=IF zt9oREKUW98Y(9KtgHL!C;okRmUDcZ(RIOVTr3=p}Jd~B)jxU!Vipd+w)hXJn#}3Ga zHp_YR`S6Rk6EgR5P;**McOp5>1)Tk1dX97~WHT-XRx|e?( zt-4_U4M!5rOJ?@f)?+)auftGuf$O!|y!-o~R8-6EAAjjNPNB`E-Xke_PAdSWhKc;V zXKjD6A=3Q(f9tHn@99P|=&vo04l1zD5HGKMHsN102cc%?fv+%gHx`p^!6Q0B4*gpn z4$IQksgjD;Gn~&S)o7u} zdnu|idTRO9>$da{oUYIE#WeYq}Cow4@V364Kfol{kd;6e2hcU0KrK|Cq<{RCAY~ac|x};t(`_by(6BA7{ zvhpd$c9Joex#ROW7>popUi`8R8+O>)DPCos$X%6G;UtPriKolv1(`BDva9Ro4Xy1^ zwqfHH7;Pq86(ODkP7`(4TmP1#5Ve}CXlT?{y+8{!q=IpTcLxz6kzh{+{_u$&(XRjW z7ehrRCMoxQOoTWdeS;ewEBrEL4>b5sj?ek=M%4U;p(#ybdH%BE?T4dCb;}N6=K`bT zn0#~*p4z9~GHshYgOTRzX1ZGO`mdhZmVQg634)|0d@XakO^X?^TFr*h1DQn;``-e2 zASw|oRn6VOj^ly~K3SPLVSdFJhQoYD0k-W2Csu31fg$Fe_paYc<;nkwvs>MrmHhOj zVCZ9qo_q5K#v`+Q=HuJrQpx3Vh-~*<$Xjr}HjZtVR2%ripl!X`ruo3|nd$PHQhi!f z0Y|i2{+8fU-~9WVRp!%$Y{6e)y)~Cd7r6H=)w4ZE=LGW(`;mZEL?N@6B7m;?#bOzB z`a8K;&Piz%@d&qR&4gpJeq3%#9uy92gxjh7={1h8#R3*l`lNorNm*-;3PXJ|FU`JEhszSoHnvum zWyRmn@%`PjJ;ieUv{2DwFtEN|3tdE>(%-qeo+6FUmY+?eFWa4;w2S%vG+D2Vo#9 zna93uh@^MDtlyHf9eC$w>ZvsDzD|qTa;RkxTB4 z2A$CyK6YF2s~~!Pe+A?7T_eM=t~dFsAjr-@rXLL>11AIKQ3JA6u4a>js)R7Pu@dAi z&4J}#!3A&cy8&@uDF@OwFgN` zwMrz$kPYvDzHIY2@rX5{aCcN&qwu%6 zNc+2P9OO5tL!;oyHG9Gk(VgGZJMvw+Y4^mrz~C&xf8V@dPZOdROX`;&l-Gg_La(Wg z1iX9ex<08AbQL3Qg#L)bxb&^H83#$V$C2**R5&YA%=^Bqy6uvx5=HH?Q{?nrn74^V z!|y3mL%8$aKVR$tAQ+~DLA+l%-6WC&G?PM*QBS;*i#OLvL%}}|D6R|_!_41xm+1B` zE`c0mq}ctZ>PVhwstIMD!NCFKY0_}g3|EL3COGua>%R#jKMQe45Z(8-E^@79qG&(E z&+*?J%V)_A0WukZFh&3Sg$MYWD2WF23SvUFErcT_ zBQ9*&Ci{lTo)Ek+|3|2Q-5>3M1do9kGLgV1Drx{n0;i|Qp7|#$JojoZuOmeZ ze5XY9vr#mM%mk++qquqUn~YL#P^bLNJv>jl-}}#%E?9BAMp1LaWXWERhY0N%6)rWp z&w%9$3%O7DVwNfC^FwAhD9{m()}j%Q)e?0Y#@s^Et+MnXR*PRFiwfe zMYV{>Hs3aPIoDmpOz~USr$IoNjK(2b^a+KaslG6Pk+eb~8Rs(pdu~w!yNrUc)1ab* z@KYcMQEt*kjHPbWKUI2VsXsp4zd6iuu$hdG;Sb6ZwB~6v8x>%d&O@F#q|dI#6$!BuU4Ui~fF*;c@)hwL@_zt1#y7z7%yz9m&T*n(6Bkc;3~)8DT{o#~xi zW~ju9k+39+d389cap@F=-{CSc0$$*BC9`EU!fb(GYB+4&I*KfobDmLSP`~aAiu7_6 zp@YO?P0f#~0J{}%g6hz+@-pS`eeQb8<$e_`01T{s-&pdK&Eh6Ec}}z-nT53LPo7k0 z91g7$Da2og_06wSzoyax5<6p$DQicmk^rJ7$$lm^ZgP0Vd^4d1d(<3*^~s?Os*;sg zxv$F1$oKeD8=C7B_|&%xn40BkP+E=Fw8bWRbh)mZa4=K2z_9tg6=(^G)6( zH(e966RDN{w3%J5IHUld4)~i|DX$qgW+!V4klDz((|WqB@M+~s@YAY339zRpDpL7d z$b<)kzE7=Za{p)W!^Kf~V$uxettv(YozKn8X@ado-B*Q16RM_P)~a>?ho-OKYOCwI zMGF*%7I$}wyHhk2X>l*^F2P+MJh;2NyHnh?xVyUqx#|0j`v)?Tm2=jfvi4lrLewg= zW>7C8Y~p?oxz#BR^Dl;?B&~|wgEKz89OYQ5sMvQOIX23vvi>6Vlq>vw*$>5b-S5B6 zl8E=J{^P3L#9>jDtyBUuIx{PryA{Z;l@J+H+%7qScvRM>9W|aCFH`k8UoeYuFG^EB z=B6AaW>mPJ2mYH#UvC>egxvUtSuq0+S_x0{LXzSs&~JDam^x|n$I|Oc^Y!N0e7meB zI1h}bI&wmVRO7evhsMsE*R1z*FEl(_uqVAsUIi4&;OQ&)VdvGzdL8VPB|$X*1vozT1ADxi|Zjt{)2XTJVL4DvpNWHX&aKXAqca$$XU z1(T|D&zCNcRHDgQ(-`AtdlIU)MZ&FccO64bY!mQux16tZY8R%pE67>2&7`4QoP+JM zvDWUSnBx4-RWrYj#_BDI$z=CV+$=M|EWLxLQ4;scw=~C4w zdk=?Y7UrvH6&z-yg#3Z}B_sT79rSv2PE}uxQnVMCE z>zaHf7UP>J!Jsj;&T>UKlIR^jQfOB5g7PX%hq8iLVMsXI-s(d3H5?;+v|sQJoNP!z z3oN?~>=?uInt2r`1$Oy25)gTeQ~(SX zS(+b+U)`IIo9}4v8dAw_1UaCKtIy{j5eQKOh4D(L_)vI-;ztMW?w_2k`m$%{oXJV4CfA*O@9*4B_yOS)IOCAZf`K-TAuN)BKSWZ z+uCd%^t%oBaKqp0W-JFGb=3dZ7ep5R%D*uMq5Umeh*z`hNY1mrib#4J33(L)N(0wx zjjUBZ7l?j|?R^WwT5$#jKx0`b9r?v`QdG)2_fTZX$G8{G=3L5NT=%&Z2ykYMCHrUg zW6FrkXLk@S7j<}%S&e`Sxp#1YinoD&TWFSiyuV<;fBxn(myfmc_JP#?1N^Y#l!>`X z{Tdf08yH+jl|;&)G-O>Kw0?<4wb@wU?v} z(28)n}g=1q26wd*4X!P;XiaFS2`2m3I=5H&54Sd(S zz7D|$X~Gz3G}lpdryQbf4Fbj_;*##O1J~(DU!zr%bBO2_G!SP{FA&m`F>zLIEBEWV z$}F(58zk6rnD!KW%>p9p?O$x62uERsW4$)`G@XARot(bXA!7r=_#J>rS59vmSogj= zDF4`QYS9(^Ka4{JgF@ofr~8czeyk|hM>!Zh$_`e0)}WU8)yJKmpCxNgr%RS{mQ2)~ zAHw;KFM>CViFl>wXQBpwkzg@G!nEB793JtV!!IwE(cdIyFS^=?xVGc^T+Z*@YdlJz zb@fA2t}ZjcHAc&8C9>ixkJCR|%@)NnNHeHl|5urzo^3 z7}g7~pbCG=p1R#|dh7Uj)Wdz;So56P?u2Y`>gLG0eXG0#`b+^yK5TOM4NSmy7u`QI z%*U3RE)CpQrC2`RxTkD8U2I6SlWkFyflpXoUF!(eCleNppf{<-IY3i6T|Jb@9j9v0w%w7?LH6mHgLbU z6kH#&6L>CQO}-F@Bl7P8M~BA`lW$?Ppu%~f*TgbzSo;ohRbL{-aGOWD-fi2F6cDd; zZt?7-}EAP_}K(PI$gftY<8?E}@ zI?ARf`0e%ym1oZ;MB&}U+9!wEfmgy|mE6pNTRFPr^!46tRS`_y(~O`Xgzi5|?Ou>Qry zGYoq~Nh7$vK)jopJ)>|&*Ksdt0h>qofa#=eP5hG(wZTwm1}5TIqYI@F9+xU03 zo5&9@d+Sve_BJ1==FZUMvwU~LpVMK*cHcPY{!K2QJ+~8=FG+3wqthgZ;NQFA z*H3n|lqjL1-t8U3VvxEF_b%V>Kv!x@T#qiZ|;3> z>&yBgah(yZ&!YFCj=8r|h*jb97%{acj(&>!$L;c}h|TgBmG+Fw46vty0qwWz#afqj z?h}eF0B_z!trJK9(tfsspwPKFt0dt8Al_VZ?;%btO*!mwSdLF5KGHG7a|qT+fK=y1 zL1VXrj$jb=Pbt(l;#GI-9G0%~YmRh=!m0bEYAJBS;uFOIwD- zHC}hUS)~47`Gai_u9ONa?-&^mS;%?%QM<9!-4)t6yjHr~F!8f^5)T;pVVHlu>z~P{ z%fD;&VwZofTO^$RlSDFah=s8JJyzFxkBx9V`OiM&0WDwMuAk@>R< zFT3k-@|_%vPP$m)Ko7vc9sd@_i%2gOU6IOhibUa)aY8V0+Do2+mTz?+BJQ{AHTtAT!fl)9Y`rS?-xnsbdrNhmYC*{<*-4YU zkMm_WQAg9UvcruFA@KOKQ?~>Bp%bm!!x}KZREV4p5cFeh!U1&~dG~Mi5VcW=^U2t% zC-GK9TNlzw;FKwiZvt(}%=IoUmGhgcgV`MiRO8=jms67f4yxFp zu_U!-RXCGp+f&!$Sx>+5EI~Ca1bE*Xy7a^5SF13``{K0G1JwwHlv7}x<+%rHhyB$w zrp0aW>U#K1Rm33aHtec=K~6{r0QYUnzk_86YS8Qsey1h%S~VCPb8UraKua zN>5VPaR$$I{ciQaMSpmQ>CtSq=AZ>DaG?E5Bc`8{xT$)DCZi{+7>Sv9nTT?JSq58B zny5HyvzK1kyp?g76Spp>JQ+p6>Q**zNU`1cdRLiND!z(XKW=IBf*FXC`hEe~)mI{> zYw-f`cG5+g|F#8Z#Q@fj#Wrkc;cIS}*$#L%-o@2VJuT=C7uJwLXTX$76?`D%mYXe> zrQA$A_1FMokGmu=x-%(*kA|#|iT$IOhc=@&AWzFTL{T~5UtKPJOVv_3)ro!riW#v^Shddir}NM9H5jG#fW1OOUP+wcTZSh z9Hg}WjMD4lyBMl+mn&|Hna5g|XYnJyIf{#Y#ubR2mhRKLR(RwObw~w=>lCc6XU+0V zGS19#FusID8^`nU&5pk<6=N~Tta>r0wqx<(JG~BBcEib4Q5wNLKEL<|DTmHf{QG63 z+D_ymjtclk_65Nggx`^40_iDt;%h*G0YY3rxD@IMwpX+Z2V4sX>4&6J{NcoNhxzg6 zDDjnzmMB3R&Yg*shGhPQ@)Goi+RM9S>p| zLEZmwnSYOG2*;tyA0j+kcbU>8NEB%17o)_nn2G}r6T&Zj$$~dWikDicU+z!m6D$ur zyeMi5&({NC;Gg^CwXN9qW}Y6F~an z;*SKJIwRJ(uRyLe0=Qd}Ta1A({)pa!XTWK!&n=G6>~-(A6F18TtR{CkU6xn@2MZoe zTML(B5(&T_6?EqMDTIoWCY<^>&Qg`scbJ$(kmAWLLyG#^FrY!K!DfDF4aSb7AwqUE z%E(pTl?hJl8~8K>+CHQEuAfqOXJlN@XgVjZ&2Z*!F#^L zRKMAw{^8j?F7%iAS$3sYWH8$eA+Vx3t|#BART&j}l6Vpyz;Y+Z-JKdKZlAgrC;de! z-e$v<3UoJE5XO&$J-GC3TY4P$rvM~~Ww@{i}0W0z`jySjUm!S0^8qI*nOO?*Ny?0u+FR#!-WLJuJGwBfWRaFdQy zK0yT)&}H@^Hj+u%9-Vj!gEi&i^>?^?1&}2BhlHh~;Jpj%b;Di&IG#JjLtOQqOevej z!Q?o1Z_EQ@?_=1*@sAR-)7JchiyMenu^cg4-Z_R^J+PcjKm&=-?CIwIDb9Dt44(s_md!0W3fxl$Be5)%mVX}7LNCAPtLDE)XNrtb ze*Zky`S?uH_>2fsz|)k#<}!t+z1>SWH0(#ByT9qljCr-J&+fX9e}H~-jnTwzwZ|@j zH{8915r90%k{0^gYB==bH6|JVXYAQ*orOfI^`N*& zDvGj*{ZZIThRVlNcsxJ!a5hh~pmJwfR}$?S?;dRWw6mCDQ>hgaLSOm^%Xe%z-lo@G zqJuWEh_Tk(aO55;wC0e4MWajP(n{AGQ*=1qOg4Ov((gZ=Dor?Dybtd#ggj9&xpP}4 z?!_C#J*%t&56}DueguktjJ(&1GV8r9Sb%kk@jkJeZUj)_u;dPKUWF0IR#cpoA zg{o*NabgiuOQ~(`lj2ZX#N7yWKF=Q>#ZSfjwUt{QI0`t*HEZ5&DR!}rOT?+VrL@0}X|`&uv+8+Wr&lB+V_apK)5k8ZJC zkjs*?dv6ahwhDaeab4KHMt~rjtg4U`$dVpEVZxC-T~7qQ7NRK>IFzeLwhr)@s#eww ze!%iQb)g^sf>S~vB3mgp7L?_>j1Uj8ide^)LcjCANeKK4PTTMmy3ij7qNVmk~Cq)F@tUp``Yo{)AAXYR#FAm#%uyyIrgOc3y!@ zoDONonNgvLYmfU_4yw-(TN>o@-H`bX*=O@?nU7be<+JV*g61G3tTZ356*HV?3*vqq zO;MTl8V$P-wJ|Ayl&EQ8Fp$nl4ar5=ymN7o~2E zLEVy#b6=@Rtlsqk2lwJ-34}|k^@B8+WB2 zG@Ox!Ow)2cOjAv256XcZ#v7%D_KI|INNLzj<-)P4=WCy?1{ zcr(ln`9afz(Zu?pMcoq`HalWHu)G$af)}!89yQKE(BERzd?xhoSl~+CT4pP*!LGNZ z)1z|hpILBX)bz)k=qENJ?^HrB=nI<|u-=-sGVn#j=m(?tI$8X85<&|U@rEFEk_WMG zuS24(2Ka$5OHC-fQBK)*f?e!O;2h%gV*PQ_VYvPpn^fA^^+N4xFE4Z!H;K}t>wY~- zS3)7FuQznONwGSlm{H|JNrKe}DI;Hwg*kE?hCcKp#L3HIXRQtbqiQlsloywzm{RM_ zYsWQfQj)2Ak&<05V~9zNJ+{ZtE-1rZ4Hyg+IL-=`*2hyB!+CyWRA287{S2762gb08 z>PP!ySox9K?{UA>daU3yr4+D?;F!`_qvYC&`M z{?18QLpeQj=GV5(3rF!8+V+V)$~Ejem$_lSb{)ElK$R#uFG-pIjZNls)5A827XE6} zd9gtk!hV10?me{4>GiZ!IqLF3?wLYU7thp3yUnUd_U6Wm*Q1rNQsP#}^h#rJ$N6f< zQHzj?muLR|>)V~h$Zwtc?~elx_n1?JvWDhE>E28Qlnxi71+p{(Pl8mWSdrdBdQ4=$ z_Z&8EAA*IwA7;9I8Wrj{1;PtDc$Tv_d@3>;PN_Wrwh#el%yRXC)$I0sadgnGYgPFC z{ix%Q3;9&!5x1#yPX4Xt>EHndA}!pnTMOHl@1Jph>GwWKMTOJXkw85_kD>Cr3N{!n z%^dVj1-`qQw61$BQ6s)G=dGZwt*&Q+pOft783#=3y?KXeuhyBbGv$Y_(Z{G}R^vbT zVEOJ3o`)}0sYjQp@asS4zbzQQ1PJDjm{1&7?!H}|GgfTcHFtHN`M&|uf>Mji4#DRzC`o*k zJY(oS1L4=EAu0pvOH2o(78kROsjBF!?MY?CqQ*7zb{8y!Vq;aas9x<(rv+eF024V;mH_n!) zbQznY%BI$OeJMt$W)-L|q2^^uEUQDcP_uugU*8nUop20*j$|;%``Ybkh%nJ=Pa$CF z9#gcvFMt$h7Lr+@E~i#S+5UJQpGZ@e83wGwoydC}xJV&+F>$4Z_+e0AmEixM~+c_|5-sF0aGQ>+~ z{HJRLQNpa5SG{>^R_VORSG_ukv1AA`c=Gttnfb0$tF!8V9?H`BiRNDtELs8Hk*h;# zrIsEsqcUW`R=DhX8dO;EzNx;>eY@O`IB08SFpGYr>pp*1nIw6WeQ&j2WD1M$xgg75 zRCbyT;emO?FLvaj-|6tS z1BI>b*Z(0+JB(l)beLkQ`tTWxXG~>t>7%7hU&JK1OFE{1JHkh7%;L?}lW>c7y?79H zX#5QWW8a5-$U0n`KV-Z#se5yet1q8qty$oc{{rH(GDS5H?BuXx-W}qJqrL2Z%VAZT zTMt1eFmE`-=AoMJ;W13SEP`8Mw^vgEv0(ifiZzqY>Hl2Ic!&`ujA)<#>^j!W?sNh; zo-L1{lFN`$*VJ#Z?}cm^n&VM=l;VFOvgZNCVj|uQ25VQjBkjnR-V`QaJRYw|hiz#z zx-Jl&-1xnlZ%EfUoJ*DJM(O4UuhLYLgvdr>2&kBuYc@_tW_B*>S_?b<7#ynmKl_ z(lYs??Q<%zsw;u%)}b@D9q7k*$+zTkbEt`%T;2%t0a~i6h-oGg^9Qg-@l)E_g<$7gD^KeV01lbE^&qPqOQhsQ3(xH|R zEg#8nF7~l|P%l?6${Fgc#bn+`>z0%|F?53il{dWg8P~L6v24852~P#_bP5 zL!Sl|D1`=!whLk>8CpPL0EAi3M*v~)jl$nvV~1ugJW z%zxbwUF$#TiIFpmFiFUX7_;O|Me;sr%7KOMcgiqIW*`gaI#sYPa+y@dRmM>2Cs>~} zY*mM8^63E11u+O3+Vh=5cF!vmpkAq|>a+1&f41C6yJC?`?2pzjyZs+8+;4uE_XyZl z<+eRY|Amv<+RP!NFC0w-@m`~**3c+QNgRSC$l54-Zv98{R=`71#a1v$teRDDD-6bY zu%9k0qtT>iqI$_OkPsz{3H7OZ_S?d85$!W;a$Nmi|~o z7L|;?HFf;^Hr!L@qq2CWnJ7BIO&(1QY(i|c0f_qDX5Nx0I8W;Eaox}$&s>IBadupx z*Aup1olH0GLVgx6oVbJ^Va10+Qu?*8f~YM`a^iAQJ$rp4_^d^O5ZR>UeK}a3smmHGXyVvKVbJ?e39!x!bPW`pG#kEcr-(n zLA{)*bgpPI|8}>D)a3M0d;i!h8;62dtFrEK+8>tc6|!up?k>M@whj`T=(S%*^l{(f z)%3t2n?=#eGAtWQ){B~^c0#_pq5m+tr0>Oye>p`LlL!Qi+|~H^?+rtC%9&jgQEy`X z2=Q#;HXc9MYKrfGzm=PU7BZO&QE)ujE8Rk%c66v9i;LY~13Jm~_QAWTzBiFJy^-P= z_O6il`c~+fgZq5n?WJfy)YD0#?lHCC3yd&XMA4j9v=;8O`(AGL%WcfyX3A;I;0mjy ze>fK#W(}YkZ{AR_Y5gqK=61p|6ipI;hd+C&kaRf$qK&WWY?mu6ON6@#`?N&k`SYL| z#N|}~K=Tl)HrPG|UfTQ#f$xFNjW;n#E}faz0&G$g+5e1o=h{_tKm%OQpIm%Qdx0VD?6yM>N8(Pc`8~8Da)@5=tkUspks#N&U7p?>E{!qk1jAW za^IRwB+DAnS_pI^JSOqqpU8A*2xCQ$n`e?gRd+p=tq|m)zCXpsd_{k-XqSR5*dTxJ zjE*O!L|v_2Wd^>x*G*j%GcODi+OWryo)MaL@JOJY3FMfZL5K}#pw||?e5sTLcykcP z#klxNigV}2QIYNauE};uL3ctJk5JCQRTfmXyd)QQHME0`q}$2@0hnme38*vFd@#hi z(FKH|5@i2TKy8bTc|2_yTC8?d8V{$49WbR*rq&xTViNPYOKzN96*-?ztJaxKRcQgN zW<{Y-AnKzhh84x{-1{0ZSu6$zXHi0}>DL5*jTQ9sqoIU3*GS-}ee#fq17;BMs_XF8 zb^m_c@0b$VKV3rL1m0P6V~4+fhALON0R(+XqA+)@@A3C#76WC^<4Kxi9*K2p#^3yb`k!}`8V*1xlFs;sQwBGo_33#!tB1+d0w2Cl=#B-Es+`D zR2)T8v?=2qtnqxwn9N0fRVetXsU`kFFL%bDedat)GDMCWN-tfBL8H~g+hK2+eT6l#&cot`KdgR3cQhC37pq^1DPwIib z%B#uzvHZHfl;2&pED0)*-K(vOk!?C#{?(7X{Bn3B;`qJ>T&{5qJcB^3*+RwQBGg#t zHAb<$uC=>DP+Q0I&1lgS_lW-+LV;*6j7l9qHqoCQ{mJP9%n(4a7{bS z7PK8S3js_A8Wpk;;XH%w?7WJb=X z_8OU9tD1SP3q;;{M)eo-IcN~29Lv? zWN*ja8B`Tf&?Xf24k1$iMYd|4b z{g8m`Ju|2<4^PFbc{;lujbTIzCQ7H_OsrH=D*~kCt>_LKakZIW_EtMRPC}MsZ*ESL zp1%X%6)hgc1*l&nkwcB%D!iZ^?;;D>(0rStQH*EnAEaX|e*L>`RCs{RRe0Ew z#ji%gCjmxHT%I$NKd4CEUt4wpQJ8$TNgsiB4@9O)3XXoIF$7yTzCSSgU0i|l?SzKst{?_{!fnBh|qFa9rkN zm0!F^Gw5f1-F;JUuZd*Sm`YJdIdxcc+X@DVD`_KeYHjpt9R0^rL?q;rSm;Rs&!X=y zr>tDSk~d?Ug~8uTYXy4PsUn_TSTfYjQfM+3ha{Pe)wt;$be(Mvplsh4&Bn@M%g!Gq z)6nmJu#VFtO|y{8s!0Q~QRnuM@fE6!1S(A|diC0jH22r%!)&=0@+M>vof6j_hyja6 z6PIMIf*!?5L!L4?uE8roz->dvD6B`m>3yGRndNrAMxDQj&upV_Rc^`1NAq%n z1(lQLPZHHY&7yjSxddsa?E7QG&HCQuK}0tZOObL53>LbhM(L5u&=2E(VYS6Wq#7YG z9wZ2Kv?&J!v&)4jzPqY$l_6nMCtzYr4WF*-spG#q9sj9lOc3AK5u;^d1RHiLInJGY< zUGXG2^n6I_I|}+PU*K_m@?W+{_&(2WAQ7!X+Al2HA54lo-dgE@YzgL~635iaG(RI> zbEX)FqV|9+jO`cB~H2=4iA?y*Wl61G_L)r|}xi>M{Lx;ON6 zwf+d?=l`^KuefnNqn|c!;mq#eE@Us@2r<5RmddrJLa|Z(5|=}ZvhG%^yGutt5qMqE zh#ftXlqfRWNBEkDa`%$vz58lRWmg>{Nv@EVUxBu9zPtV*hTvVi|NJPY+3tGU4F%vX zKEaU*y#{iM5nb0tCgFo3m@Bb#jbNbT)?2-cLCTHQsO%P^1|JTroQ>6QN|xxZ*`8xa(tdI6(BPJ zV$JH{*-q~(x?Htb=U(c{)G%&(SFE(WaM{FlC=yKFb!|b+bspOXB!!?%HsoqH%Xd~7 z#jsMjIHW`1Oqcq^y}gI@{w?+Lk=3W)Zk2X-TL3#uG92p|FO^p`Qd*IqQp>tsBgQC} zMVFr#d$%cq+#;|55+X?L8elLox& zK7<88#0m@;o-!UHrvH14K$w07V*g!TcYqJqPxhg!aZ-du8J@fBFT{0^mU0YXvmZEQ zMqb9M^c#pCCQ~S^H`{b|yQu-OO5vn5LiYu1uPK*O=*^WsWK2v@*k74MSw2$?;@VpA^xYktzr1- zh>NE;nCFquT|KWgeE;b(@@e_`=9YEgJE86Vs5(ov@haBrBW+i;@NAbk`7V$nqVtk9kPT3*a@ZMZh_5-H2J42fNZS9DU8M0x2u-P?=!LMNHG9*1O;q_fa?ShTEdx=FCeG+DQ(Zf_D zcI}~ZwOk#u;Zl+|=&#XjB$Er_yy`Q;9T8b|*LB&qWikSazq_b#;G2`ivavmfcoX~V z-kTdM*7C=w+_%uOa#0%cS4vG_T%s{o=icfyTwj2rJ8Q4iXA%_+86fN;O$myIlc0Ft zXK~@{_3*Y5$A_I|{=w_~!PDQvz_Ej44QVv|(xz)r$Qu>`$YdgW8 z`uq-{E>#qMD-e9#ak8`&(;emvLe@4Gw2RfS|Jz{l(*_nM;uB857{VMh=h*e`^DBNi zeK7qkAl~d(7Leo6g3vsycIrdMvWU7;)Ht%FV2b$Lc+EbMn1zs zry|71NAG6*Rh5&r$3omzviLQIrhgFSCkM``|67;?rLn=K|7@Nz^4FO6+r6=T+h=oD z`3I(1Gka1Y;RJub!289^CQJP?2lTW+GRAlWm9?kAb$yJ~B83$SCV>%BWC{V{g(vz{ zcF3jKbQj`Ne#ON&b^gvgqrE5?7I24#g^`%=bW^qx zeYWMBT^wq~HCU#&&bi##(8jSpfB;W4mec8^yx<_-yuy&HI`r8G>vgk*NxW)Y461Q< zI&_EnN7}uEufk1}L2$*w#+biR918RwjFS9A(M}AL<)Lr@(&jPzDGmm<{s3zW*on$f zW9vjDD+PfR52a6bBtfL=jdJ%d=lVNlgG1*57pT{=W^v=GrEB2 zj=wNas51t4;eFy~zA%mq@b<(CJ~&CxEE5v$lmAWOtl9KA^O0ZEc$M~~3M;UQ*-UCs zPWD*3Xr*y5n)kO_`2Se|@Nx3Dt4X=6GPvQ6O{_jcZKeQ5z!ip!R@r=MzFj?N;R=xm9A5=3zA!2Syde`s3U{!wQMim*mJ83s8Mv#sn3zt8jP0X|WJ#mFZdk|+ z$Dppe_L2UzzELSY;`&r~KinXqfJz&9!$KSU2$VeolyFDdS#E1mJ^Z8iCh`po&(Xh* z*5~f8wW2i9$VhcQu!~Y?d!ZFZ{MZC)L;^2O-i}^xzD~k5q-#3=C=aAF1oqqu+@H_8 zy8PcU#!C*Bt2}GOiyAba&V)~aJ_|cTSsPqXi&|Cf>E$~dDEf>|ZReRJx@zgaVz}9; zu{3ZbV^eDoAQjSdNZZ_uK58yf)RqYs8#;)kz^f--QyX%m`FqR<>-=fV{5Cw`NP#@D zFtSi#GA<>gE5df*TyJ!F!e*^ceR4ft ztl}pwYZ@@qGRV)7t=f4Q-Rj@S?@8%I3Yx@6he+Lw4Zg~#B_ICpWa@y-!=Hce_jddD zV0gfhrT$I8VNv1z`-PIK&!rjtQ|k=xE&2Ba2gy&9XywDAe2y<$HUS^$Xl@tMXb)A% zR}wv!@CHv@XIlSPS4@8>bghQzzq55wC+K>6&Dmi+jQouj4*#7D2~xy_Qy1$6Sb{0h z>vJI~y{TavTKNB%aN*}<&}H|to{2ciWvHXt5AC7$&5w3ppmu0*W5WH#WAseYZIg7C z@8@5W+C!_MZx@>(VB$^;dxE1Q7r}LNA{fm7pdQ-XzqJs8D3#s%mF?N##J9TJq{wVV z-k##E-(1TD@6Uenk2EYHfv>V|E(9*+b`J@y8UPyylCA+^JNHmL!S3?p=IB{2+*PY3 z7x0=_|5XZz`F#FLUl4D6vsk4`*s;kn!1Yt{Yc|{O#qYqbU3k;YF7LYCP~tk@OP~8R z3Fm2;;LlGRPbm(Rp^5ODXCmiMvX7Vx^+);NKS3SET&(IX z3{_Kedd!kl)0+d3zp#)Ib}i=!Pti{erFV39?yZPq^KS^+5qdQjtZ9b``s{MNm9ut% zHhta{7*xv(2Cz{%2hz-wr<#5AZV{I@AW8=QU#A=tpj%iZ&@Pg7pq+dQfE7l^_fK9* zqD*g78wjQ{BAImy8&74E&bJjWTTpLh+tq+59~gG$c`dT`Kl};1Sh6h<>XGT3zUNubSQTSg&`}x>$a@| zYp?q!-8=EzyR{>G#tuB$XtVb=LwxbImuyRoRv)J7pA#I8Cn41KWs=RAnHMgP3+5pt zDx|Qt9(8XYhgE*P_~axI`8?@=bPgRFajaU}C-FGG*y__#WTy`W0p-ge0M>>ci32Gt zTj5D0w4_R}R%=v9@5h_9gjV;;P2yspjxR)VUQoehQc;piV!-ccxsR#$9loI+D^yvK z1F^fv5o3FAcV{#!GabE|JhI;OH;W)@>3P*tqWgRP6J@`a|4Nv*_-RGrZ;kY_} zn4INmpD*tt(^*wAlNQBEIrAj?weZzDlE->hnU1zx9)GU>E)tDs83mQx}z3>zHuEz|aPEVCy!YN;;xdZo^C zj$y>zSIQge55||ZZ^SU<6i}&rEgw1aRT|p-uIDAyU@rDu7ZRM`>sKq#+dC3<+N<2% zUpe z&>^E&DVnY&5pw*c=W#*J_Xf6Da8)D_kVOKwJPsZ21;T>>i#_3Wl8PpR<{STb24hl1 zET~ZaRP5Th^3p^1VGacDN2znx zz^_mdy0Dm%?MNMCT*dtw|3oGd`*j$Q{$Nw^t5ro9#-<9tDzlwj>|$Cpo-7sP2O=KO zoNZ?MfpkOv@zJ}z8bHFMnFb+qLFbq9zE;AL$u(DxX}*z!by5Pc7Bq8H+@5NtfYjWT zMUhGT%Epr(XLmFMvNh?iEdf#r*A34JqMxU(vnfq%vf?y1ReIM35LbOC@>A-7 z``{1!a^6avHWeup0&?%R`#2v7uciVPa9Mm($sX9#KI5H9RzGu z2{c=X&Kv9B`Dt{X?`I$cBti~0xe12ZuAiQnfDDMcgX7bpwBlx4{b)vm_czt4L+7&y zWY8T=gh^K(&EGr%3LTx~OOXD7zh>8O;KD^DF`L>T3SmCajk$n3&$rMX1q@Mapl=em zP=1Q#MrkHAAiPXH0vJz2;nfV%&0nC_T(WhIP-{?aS0jKS!NzDv`b$=Ckm8VwN>i#C zM&74xq`SaP25cC^$y=$>l+dhqjJms=(Vrk1{Y6I!5tgoivpHR@ZcN%803;)b0h4$J z3_nTE_ND)4X-(j?EQuaP;4qf;h9KVl5ZN$39~&`aGW(IKoR`k)@H_L0GM>8IJO`Va z&G1~|1)RqQ%LYco-So7#qi!}2-Sl{4PQBhh!RK;FFrJ809dqBGYYJElgyVx^J9}xH zsKwo7RQJaI60weKqo)+bBT48*K8;Gi72Ai7tEP#J!&34e5{?HupRyC7(fiF>#8jy) z%4d`pGvd(zblfAVAWwGh-%@i;655q9MMQOxgIPvT?)yUvzu@ZA+K;{NNQO#Y)-jJt zJoYly(EMej{1DL4xk!H9noh;j?-t9P(^|=w)b;uwCF4L$D&#+8gnNN zcr;@OtmM4^W70yKXQg{i!$;&EQ+}_8F>kBan{YPA<#ruqb`@lPO~fnJn$1O=R?7gi zGm)H?MU-XSa4V!;0R|^J~hQmrf)9Z#f%h4bW53qUU z^tE2-<4&n9+bvd~Q@UH_vZnxt2J^%b1&j_zqsTFBtZ_9+oWT1n}Yl$LI!LAo2HHl=hoNOy;nba#U^BHi8H&1S=I z_I2N0f5G$Od2#cS&kTFbV$V5i9q0ErhO&|Db~_UK;Eg2vh6;cOh;R=WtXibRKIR!T zvRT<&AY#PU?(I!agPzwaOSHzUaEUrp3MosUy2GV}!oFx1GSW59L7aId29ROv%`|4j zV2|l~W-YZD&o4>PugPqto=*->xPL(npa+80=HD`hX^3DANHTn`d&Bn_aIBqiCGb8Oudcn9zwI5rDSf?WcHG%TC~LHQc$oac_ic%) z3jW|O-Wm_H{X~yIiXZ#hfC8_93&)9SFJ8yooQLDOu9I05Yu`0v5-x2k4%sb9r`E+{c<#s>ngB7_kg z5(dBo?f$(Mw4&C(LlqpuuVEdzzdGa-E*%6xs4~Ma7ix+;PBh{Xs1g4q#dE%hOl6m> zoGmBdzEiq$8C<>SJy))^nFnnpWhoP zaQGT$!JNrH^yZ3W*<@5(hTi)Q`KDLAxziCu0tHoa_5Fw<;pj(8=sWEvkYDC5MZwg` z0#(?%4OoZS;=Wbo_jbrdr)k@ZRaJF&3&^1mP{T_7hv80+)j@2UX=7wPq2!S0PUPe{RdXHQ-DG_*g1_uZ=Pe@SrM(|s-oSP}Fa5tIE? z%+FE1MvcZ;JY6|cs;oSMuEwB;Y5mGCJ=!{UmWt50JE+kjtl%Igve!qK=iBG*5Nh0! zud{l(Z{bh0qrJK_HVGmJBkR8`l`3?4Y}bFUrfe-gnL6_rh(8 zFva$!pKeVC^=6zdn2lA9alY>F8zI7G%b~y`4MHd%(KB~iPS8^%TA)1Nfpzvs9q*1p`(`o_PqyY#8x8(C3@CI=Pl^>bo^}NOH#J{Ihc1olr79!_rxcenDI1n@OQ2m# zF>Zu0M8io9K%djBvJY(cs}p|Jc-{h#w);qDr2$84yU8yMu8XJR6gnPN2HyoR=2T!K zkvY{iexPu9*+J%tL9e$@0l)QKh(s!u`ZKRqxfRZmAxS!eI4i1W1ZRd2*_LrL>^&t0 zGRmtWFwhB|K7D6U$=xydfUg z$rets=)h;Mh`2$5FI9m|L9vT98p$YVGhW4_=dD8_ni>6|_-^EW>c2W2Q%>FP7fHtf zXM(-4F?%qyq>2l9Hl_wMqQl#Cn)@_%t;%r;I~Tr#d!~ZZLD9kHb0Jfq9KfL@XT^eu zwv*amh#|3udLUtgB{ANE3FU07H3n5APB}pQqLo>0#r$$^QI`e~BnM3$lEAI8@T z*$@!ZS4$h7iw=C@6u++b;;CpNZ-Vs*9{0EC9=05p>EM^vcQg;e0z-jf+0ld%d|mQ) z@|qgVPM z)(Iw0Ma21{UyXOcvdHDsinswsHIALJ?K-bWpzBAHce?b@^`j3J%#H7F)J5>v_j-6| z_^(JyX~ivwQ)5;+%27dhWZojCj`v6C@%`FOvhw91dl}3+{4>U z@8#VSJtm2_TRSZNM9vP0WO}DHAP>V^37uFU(mu@# zZ9^{M6RJRSj0^JY`S&P0NqnxCv{j;;2l}(I!rD<~-ri37lJ_eR!!92uT4%<@alSNf z&ii4r%eFRtk(3uQyVh8o;6pUv7ih1#T9b8Rl|U)25M&%7pG~dyOh> z>pgN;P`hi6g&<9>A;K^d)`FP83-qSRFz%5)qJG;lK5_eo)T4nAZ;hWM16@gbytuGX zLD-z>Rh06RFG5pBw{g}PX8CI|)i_BaW&3Q}IJa=su~ zh@3Qv2H=BZ0(Gr`#okTiu+lRp#afNe5qEnPz5az*vWA-v5n7pur5VjX=pue>}XWlB%m@8z9r7K_3Pph(Rd&)UM9z)*0r!feq`g!Y;o!B6Gyl(H3JLH)!O z%o0xTg3*X#9ZTeNu~{N81`#|eiC+~uw@58=Z7#LASFo2(DoQ92GbR+PHJ5$$tG`1a z=szCXJ%G{^EQA0UWPEe(oa>AvMhAx>$o}2j2^lMz*VabY6Rpa3Z4I0N1Jgl#ud3&9 z-)nGzlOjUipWt0FFqBWv@%Z6~tvyAZ!=N<2pk?cnOHL4TcUskPYsOZuj}P$fhb<+e zPw@=^bR)U&%|bOUOkYRGx$XRh@Z#v}=!y?Ef;W_t%y>FQu<|(P81`e-`5HsIOhrsj zw$GXum*xGa$y0w!3%)%`0yL)*cjg0;v7f(Faws3ScbH4unREiyWpJOX#e@jC?ehS> zZXIzH!61NS*_4Dij!WND8Tl&!kDC6u;%2oRpw)aHc`z7-Z}5*P^H(EW?W6Q~aL`G{ zTYAOv^3)%UK9tiG7O+NgV9Yh(?|a-20%!mLL@Og-18{EgogrwrM?)Y?9?EesmDsb+ z(INOWz0?3N^Xm=3nQX027WSz!S~0TzDMrUf=GFa>_gtL+YLZq{TcepH~D1 zYwooM{@aKpgBCQT&PHo!`}+~o=T6vM(j52R1-k%6(B}DbuB~dJjxh3VB69<644q=5 z4-|ie+7aITM~y66kUV&{zd_e*H)(3$P)J$84Trg?GwUUw>I@8flc?|XOfKjF_J=ZE z6b{1aA=LG5_m)K(`8k$m7GZ9H7&}ufCim+n-Qdvo$8dkKc_<=zlI1M3{NU)hgF*c~ zYur)HEipo4SzMo5ZElVGN4L;qE=ZeNVUZ&dEm{=I%Y@AJt`js>8sh<;Zm72SMNQRj zZ`?o4ilOJn9UYC1WsTjF(uuJpiin&a&gr@q;v37WU<1O%M%M{LB@xttTo=U97D$@VqZya;sf@3sM)@J1FAp0GS)WX1TcSs{iv?*L8Wi~AhNDmXPsdEY}oRKQBS2Bh*&9LNbWkiGYn2`Rw>o` z3~(0?{`I=_&4T~n9G&RE{SSe$7liUJA>u+(G5daH5F7Wc+h8^U6*%paa|eg}1=AD( z*JdnT_PSs+VkHM|qcbFn*{Y1zsV6F`P6*vF=ns-|4%pbD%9v4$=sLS-6r zO1VsxVGG3o(qnqcgeXL7(v8&dt&-*17$T6s7Wd~3F)hThn`Vx~sTn@or&h~$gWN4L z8VD;|?E$5BR=qtpVoX1S7!7I=yZh2M-FY9M$;btVr4{OY0YfzzGl&GxCvgo==IcHY zyPUytdmhwY9j+*7wN8mZ>V~e+v^fwtXa1hfcf12gpX>ykr(Pnat%*4u$oIntUA%? zbgea*z?&4yCxRO{<5?{~$eo9U6%1j7rHXHT;4lv*4}&4Q@JRHmm0b)nhjCr zPsW=3ulANiGu|vL zBMKT9ofH!(|Se`ciOOpw{lkKz4DLncv@8vDZ&DntB&JfQ1f1?!}UHh8fSdJn(z!m{sdepji~gyncxMgxLL!eSC|bu^)z z>3N~4dpFbQYD~4`yQNr7DApLGuRNB>vN`X6PC?OwU&i`TF$%cjrRWeG0bHkf4WnhB zQYuz*5e?*-w{7b}H|xK6tiqAC_+xn92%Jz0==~IlILW7+K9Q&3nfq zxvVD?Ii{2UtlvqM7-{q@+ICTyk*0} z5%%Nn$2@WrG3=8U0so&^VfN4vSaz6{$J~PlyKaYEKm#$y6+p-zbv8*H>22JF%RkMzy{c2wD@myv{|0 zjWZRsYUD`x6ozrFChJ&KN^^sKO{2-IcscmAU8P`8d! zYKjf{-R=qv%(}ZfFm%^mpswFl^lvYvd_6Ein+1(%bEr=QtKF+%pKL{wOd{9b>xmE) zmZ5m-MH_#L+84_gPs6!bDZSl#Vz@mN>(-v#7(5@iG$7ues0j;q_fFsXouCYO9huBG z&+odb22&YJh+BH3u;`x#l_=v>ijK3TR5>+*e2mQs4=y_;Nm?0DP1fQAbZN%QK^`TR{_k6S!Y>0kv4e|9zTuBo zkjp<=jt-qB-SV_>*Sf7L_7?L6`LW6m!FJS=cAmmHWya?wIWU8D0kzs$HWRg8%JYp* zxl^7QvhZwDpI(4Hy`*SBN_4mR&nB8-r&>asG$ES{s7MovBhLT0!@~iQuEb8&hF^# zs#gWx{MTW6f534Bg_9WIbskg83_Ik%>An!<(xp$X!>PD!rKFd z)hyB{Df}m4zp+}Z@BmJiw}Q2&in@GAn10cQnVlP=e*SCqXtPeBw1xyS&!B-Z=U~f} zd=f@gcVoXap-R%`CoxN?gleLt9PSs0QXGVLd|WL)tP&Q1%A~bvMD=~JIKN~{7B-5k zR;o>CFp^7e$)%VqIQifX&lm&8_u$3QkH zt=_14E6r~45)KtPsP=L>>!Wht#-JF&B=XUaCZ6lTtum|4)<^zKQ~LO6PAh&*nOyFi z?FztWY>+tt#2|9SbnUWVs8;CeMrn_h^XD5kL}GEt>p(K-9O*13+vU#Yx+29>E55mj zLyQ&hdBq9%S0xWP3+cap8JXUcej_FcRuFv3qvi?E2!&e_k(9w@N&rZ3+V%c-2+DB; zj#fy?wg3_niL1br&ddbe=%M)nFQ!M}VgI%y0G;+FOrIsgmtjrtBxz@>Ee7{+R5pp} zN^1H|gmT46VmX>rKSl!gguC@mADWvbt!A=Quyk_%{D7DW1|Z>@nj7`Y5&k4lV+Z2l zITMg`X$qHFGYO(!F6y%B|l0^`gx^bu9w|(ak?=f84ei)CU_YQ_DFCwMdMF-#D@$RuG_nVW( zMD2Lz=}8uTZ+M;auDUZ?{M%Kq6oSiq)Xy-&c0U>dN9uRbmehjzE0f_EIXCo!GN!{$ zbU8s=c+#0h;-0I5G0{LM*y8rOlUrtn;lgRPVLCx~vpJ%U1j%{Sm%pyu69uN~lkx9G zUtPhISmaarXruh^MKm~PMEu`s-5}Ypk&Jr$S92*+7*7?$0(xqAf>|e!W|aP*!X)EQ z;nM=+tqrGBdK?=DfGPDK=LaefZ-Yu5pHv_Kg15=DyT5!)22GU2xR!mvahrRo@z)1F z^~pyY0pUf1ZSTd~I6yi?zB#Zf5rYSjR*a8h)cCxfFdHPGOa{NYsY;d-Ix^29C7XLK z+FaGttBmM6;J=Spab|%VK@NKMx^S-JFVOuBvq2T|vj;`}8!oe+$}ycuxKpKn-${!5 z!p4iRX^++LDbQH~#Ngoz!&=#TJ1X(+XomXlqAw#KKQzElM6y7tdu9Elkme?7i~}k+ zdC>09G)Jn8UkAK+sa~ma6cJ@+2d8Y3Z;OM(sJhzI z`r#%M!&BHS1sv7~0|m}H4RMRfjWy11jSyC9U5^G>423s`BIpyMDYzV;UZ-{ID3{BO)nD!WHhkae94|vH@i5ftxG+zV25YceBBy>)GM8w{dptTa{z0cAOx3HNwBkzxylVFC~X=py4H znsp%`jkC#G)4C7!+jOkzg=EzyO1TC0_I5ucbXG+)hY$(eSTUvf*Mq%VFxBFM;SnAg zuMy^XCP@ZMrVDfqrixVM`@}`eB*{BOYhq@)GX?7f*+)EX7Z@g~JFxquOCh+T@H$K!iR4hV}dMf=9q@dY6aDAfT=&% z!uQoG5PjI1n?y8a>{}c4lJzo23FLKzj~saiZxUEJ$<#y4eXL3c!=b8=7<>zuToKSi z3F*sq!Zs;Z>vdY^&g0F;&FtLSC2FSFAo~iJ%QHXZYOBpZkW@T0LVaISA1>y_GzYX> zHO}J$v{LFA-B`sw596^S-cLMc^M&A*pS8Ni2X?-{XXB0bHEB3%Sas}|ds0lSf3(j5 zUYdLpYPLF5frrmsgw8o2w!yV6Dic4>f|su0BjtH;7R9poAUzgg-F!9?PeFoO*(-aP z%oj;xYBAhF)F-ZA&*1RhX~%9MG-!sSXMxyw@ufp-Vbo66jnvU@Yo+G`-vY|;U0sag z6DfTt#^rxz;)_C70+77%auqiRg?Kg#Yur@K<{eZs(v9$mO(lJiMa7qB7a(rO9CML) zJBluo7R@&F;~J_i#L}^6>0wEd#DDg)j9*tXOFK>IdTtrQU{^a8kU45~O@wj3?0(=^ zbYE$9dIlg=#+%kVmk#&Cz?)^_evR33^bd->;bC48Oqywz%)d^@hVGJn#t3Q5vuLG2 z4q1?^s~0@=nhL*Mf(RRGOtB0nq1MK+Ux7yofa9{~BSNG8$#RYQ>Xn_RYeiHcTHiIV zz6wcb+$waD?SQn0I=!Uwi+=vbCJ^Z}4kL>hS@Ks6&=*P8WqA^^y0`Q9m}Kr63$H6! zf2?mG`=9#8G8*5`uR2*>+B#c->r(AKB8?q3GQKU_ES6`Ak`|M7x{lsIPw!Mrtv0tY z9XVo6_iZv)P>el=G_C@ZB@`~=lg3T(g+mI7H86yU>kiM6^fb2X;65NUMCwpbvm)#x zk#D;US|m1w66RX#7tG7lw^n%~39ke$%P^=LV(2tJI_@BS`v|+A3iSfy0NY?zRSE2>!rz)hw#LLyOz2#?QF{OTUx#~Vw+p*Hai{_c&S2ynF>`- zi~V!QZdqEL6D1GzyGJ|$37Jf7PMh~pi7qM>eixh)kV$tP9f_C8-5ElkUMfD7urQ=H zNJ6zWpe6N+wi{^BZ>R8#nw!+2u3AUe>6axaG`t*z^l2;^YpOG?ef}cijO>wti|V(iHNc^B zyB?X`-}h&M>TS5AFTac?={rFjM4uL>t+p2{+S|x%cOx^P;Q?K)KL*7HmRxIgEcSHN zG@=MtrEgA`Npze~ncYoiz%?ob6&;T}AD_+iBZ>H_wFOqm0fP=|)n2lp@z#Z4(srBX zsZ<}B4KZmrn#Dgni&L-eX;UI{(qoGcz%K^%KX_M;s`&Bojjx5Sxt)ZGlKw`*tKq)#6tDe5X@6v+HR0e8h4i8*N6wlrSlKIAq zk=1~v`~E@_GXm=cKI7-&09nXcb4q{sdp7peNdS*TAY3nb)=T(FC|H(PX8|d&oJ^zA z#=!>!$2ab!8fPqq1(zq4&Iv;8;FXqC@BIlXs2h0jn>V#)orS91yl~sg!4CDO1OUvA zPaFL9IJ-HKFN!-482Wx^3TPu`5egc5xc(SHVTH8qvu5|hxaRdx(9L%0!EdKfk4moo z@bm}2+8^#m5l|zkO(<4kb8%$8ligT!2U&4Vv_obi+J&DdHL)ca86nfS?OJ)0}D1R6&>r{4m{Ees2_!CzU4Q1lWE@GA#=nk4oE(roR^lwtL)HTf&Sn=s$pC zv#A6CmnJkVgJW>+rL$X0+ze`oEXl~Tq<|JA1{wge{ju`Y2io_zBAAkqVvAsW91Gt~ zkS}(mRlDG6nvHyXf<_D!Db;)r!n|3`7fe|u0@T7m>1@c>GT>srw+BacwSZ9%Y06S- zCjt|$38#~0jx zg2C&x=5q-mgpXP00|9U`4YA_HjO3duBsBYMdFqitO^9*A0(@MLxd9RxF+ofg z0hs3OeM=u&L(}}Z5=u1wfR$h2zAx=y`ErJ}cZEM$f{Opr7rkOgqjaFeWPt6x^UBhN zSrpecprXyLKDxFJZ5|ZC#YJpHy-fmI2<4nzyk2u;hl0Ay5m~kjK&yX79X%SPq+#lo zyGSUVS@a9J`Y6}b^3vaFsi2sn4FbY8)CtY)z7CSvl_1&43uj-$+RE}I`?N3Yt9rU`kvu%8 zEjn!z!F_%UTmEt-e4{z?GZIgDwt)Ua=FSG`N#>p{DKEK`LR6eL|AX5W|s z$pm6A5U#il7^2q*)4`NDX~xw(U;RRQjkr;bwVHLx zQdmsn@mvNAZ8niBtnhWE&Q}g06x|lUgV75^rPklIOZhAZ-z-KB@7&ws0y!kLF9*@z zvrKN9Y$ZrZBI~f44B7ocP6P7FJoCG)#Hn%N-Ov_bghZ#pp z-MhrcJu2m<+?F7rs|ke7NOTHVH4=|CpTAbRFp#XB-7TYP;sVb#v1F3t!ns;zaVIZ8ekAd_8)+PkQzp-kA4zn}eADLMT3EP=2KGh~k zl+=yfXC~qc)~)$K)pYZH+{-p6S^Rpww2eo?PZdNnt9#eRwX-J#-!pe5zrB0A%fDNl z3EoKo7K{Bm;{7b(sC_|-vBn4AGgQE_F;%E6x_#kRbA~$w=2bmVdH8-5eCib)G(v!Q z+MT>CXxLZf@?@kdn*>B0aa>Er&;=57DrB+h`j^iIx;v9&I|((~t|M$r>u5|CT&Hba zo&Nl_MFbzb<+9P)@^Zn^wwr{VV9%EV(ULO{;2sB`1 zVhOWO`rBI~JC0H&2LXN75fFk@kG}%M{x5b)G@T4YN2rKoxr>sL&gGsdOC+dz=x!_G zQnohToxET4I zsSxsI#ADzE3TBB-VrqjW(;N$z?VL^<$y(diMqpSs`S5LD8;vZ&5FlKnX|}sG$)Etu%m0D$k^tmF#E1b!RFj}|j zT|M_V3vNgGKVNP9P?DBGC+5T91HZgeXQv%WOcm`h_nbu2t(W3FBpkc)MC?8=Te02s zT-hErF}rbTc^bJsIj5mn<(_Bqa;Va6^!U+Y*0f5)x4C-0TfWa|gBNc1PNC@|WM%*4 z9K_|_IDd@OKW2N*ZQpjfDM;cBzCF#l-;;G7xoEon3ei3$?VqYx?zri-SG&DoZfNPB zE%R<%kuS|K|FSB$c(T&82+^!qwY}gdZ)m?gZ1c>5@HKhsxM6X<=%a|W0n$))AMTV| z-1aSRX*=)y;v2Lb2V*u_p;RydRRCFBn(m^ zpU!kR6y`rOPnZ3<%k-PG_PM`Y_-ufMYPP4R=@h?{O@ksKeb3YRKwV>ukz3fICxwOr z;?~^ldf%@TS-VFmdK=l)(&LJX^mei;{T6S|Z%Yh#i{Ct3ar@tlGKAMu#Az=r;hxF` zLp1x}SoLmd-YnGD*DvG-M``I;R(U*?r!Gr-45+xwrYjOMK6EU*??*pJ#3yy|L4OoNbT%=yWp?7 z1Q#;TCEMI}Khihd2PWfES?=%gia-h+6Q|uV*56TX0V7J!vi$dW zASCl!m9JIOKbHWEf|Q0-X!lX&->Z59d|()=PRoD3Nx)Iuu&_M4KU4o6pPlRjqiemk zK=t>M27nQ93r_!g{Qsulf8T=t-3Y+#^8dk&U~mEh0i63Y&u?lb{;f%!&tlo5HRn91 z^&f4!)CHf|y zNRP<0pKzP`^1%PMR>JtsijZD_(j7B*UxlS4*2EEBg%d??#I~cAI{aIWk>W8hvSq?GXVJnA zgoTkE99xU__Y5Iq;33eH%pvu+sDFs}f#HwObNuJw4jqX!64Dq|U#ZmJEAjmSeCQ9# zGSR8Jp&7P4urB;#s0l816o*ExBur;@dOu#yA&_A SkI)JO{78w*iPossible values: " -ALIASES += configrecommended="Recommended values: " -ALIASES += configdefault="Default value (if undefined): " - -# Alias for starting a constants page. -ALIASES += constantspage{2}="@page \1_constants Constants^^@brief Defined constants of the \2.^^^^Libraries may @c #`define` constants in their headers with special meanings. This page describes the meanings and uses of any constants defined by the \2. Related constants are shown in a single section on this page.^^" - -# Alias for starting a functions page. -ALIASES += functionspage{2}="@page \1_functions Functions^^@brief Functions of the \2.^^^^The \2 consists of the following functions." -ALIASES += functionspage{3}="@page \1_functions \3^^@brief Functions of the \2.^^^^The \2 consists of the following functions." - -# Alias for listing a single function on a functions page. -ALIASES += functionname{1}="@subpage \1
^^ @copybrief \1^^" - -# Alias for creating a page for a single function. -ALIASES += functionpage{3}="@page \2_function_\3 \1^^^^@snippet this declare_\2_\3^^@copydoc \1" - -# Alias for starting a handles group. -ALIASES += handles{2}="@defgroup \1_datatypes_handles Handles^^@brief Opaque handles of the \2." - -# Alias for starting an enum group. -ALIASES += enums{2}="@defgroup \1_datatypes_enums Enumerated types^^@brief Enumerated types of the \2." - -# Alias for starting a function pointers group. -ALIASES += functionpointers{2}="@defgroup \1_datatypes_functionpointers Function pointers types^^@brief Function pointers types of the \2." - -# Alias for starting a structs group. -ALIASES += structs{2}="@defgroup \1_datatypes_structs Structured types^^@brief Structured types of the \2." - -# Alias for starting a parameter structures group. -ALIASES += paramstructs{2}="@defgroup \1_datatypes_paramstructs Parameter structures^^@brief Structures passed as parameters to [\2 functions](@ref \1_functions)^^^^These structures are passed as parameters to library functions. Documentation for these structures will state the functions associated with each parameter structure and the purpose of each member." - -# Alias for "Parameter for". -ALIASES += paramfor="Parameter for: " - -# Alias for parameter structure initializers. -ALIASES += initializer{2}="All instances of #\1 should be initialized with #\2.^^" diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/footer.html b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/footer.html deleted file mode 100644 index 18c84eb78..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/footer.html +++ /dev/null @@ -1,35 +0,0 @@ - - - -

- - - - - - - - - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/header.html b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/header.html deleted file mode 100644 index a60bb68d3..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/header.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - $projectname: $title - - - - - $title - - - - - - $search - $mathjax - - $extrastylesheet - - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - -
-
- AWS IoT Device SDK C: - $projectname -
- -
- $projectbrief -
- -
-
- $projectbrief -
-
- $searchbox -
- Return to main page ↑ -
-
- -$treeview - - - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/style.css b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/style.css deleted file mode 100644 index 433d4cd4b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/html/style.css +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Stylesheet for Doxygen HTML output. - * - * This file defines styles for custom elements in the header/footer and - * overrides some of the default Doxygen styles. - * - * Styles in this file do not affect the treeview sidebar. - */ - -/* Set the margins to place a small amount of whitespace on the left and right - * side of the page. */ -div.contents { - margin-left:4em; - margin-right:4em; -} - -/* Justify text in paragraphs. */ -p { - text-align: justify; -} - -/* Style of section headings. */ -h1 { - border-bottom: 1px solid #879ECB; - color: #354C7B; - font-size: 160%; - font-weight: normal; - padding-bottom: 4px; - padding-top: 8px; -} - -/* Style of subsection headings. */ -h2:not(.memtitle):not(.groupheader) { - font-size: 125%; - margin-bottom: 0px; - margin-top: 16px; - padding: 0px; -} - -/* Style of paragraphs immediately after subsection headings. */ -h2 + p { - margin: 0px; - padding: 0px; -} - -/* Style of subsubsection headings. */ -h3 { - font-size: 100%; - margin-bottom: 0px; -} - -/* Style of paragraphs immediately after subsubsection headings. */ -h3 + p { - margin-top: 0px; -} - -/* Style of the prefix "AWS IoT Device SDK C" that appears in the header. */ -#csdkprefix { - color: #757575; -} - -/* Style of the "Return to main page" link that appears in the header. */ -#returntomain { - padding: 0.5em; -} - -/* Style of the dividers on Configuration Settings pages. */ -div.configpagedivider { - margin-left: 0px !important; - margin-right: 0px !important; - margin-top: 20px !important; -} - -/* Style of configuration setting names. */ -dl.section.user ~ h1 { - border-bottom: none; - color: #000000; - font-family: monospace, fixed; - font-size: 16px; - margin-bottom: 0px; - margin-left: 2em; - margin-top: 1.5em; -} - -/* Style of paragraphs on a configuration settings page. */ -dl.section.user ~ * { - margin-bottom: 10px; - margin-left: 4em; - margin-right: 4em; - margin-top: 0px; -} - -/* Hide the configuration setting marker. */ -dl.section.user { - display: none; -} - -/* Overrides for code fragments and lines. */ -div.fragment { - background: #ffffff; - border: none; - padding: 5px; -} - -div.line { - color: #3a3a3a; -} - -/* Overrides for code syntax highlighting colors. */ -span.comment { - color: #008000; -} - -span.keyword, span.keywordtype, span.keywordflow { - color: #0000ff; -} - -span.preprocessor { - color: #50015a; -} - -span.stringliteral, span.charliteral { - color: #800c0c; -} - -a.code, a.code:visited, a.line, a.line:visited { - color: #496194; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_library.xml b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_library.xml deleted file mode 100644 index 7aebbfee9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_library.xml +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_main.xml b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_main.xml deleted file mode 100644 index 7d9fc5e16..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/layout_main.xml +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/main b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/main deleted file mode 100644 index 8ef18d1ef..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/main +++ /dev/null @@ -1,30 +0,0 @@ -# Include common configuration options. -@INCLUDE_PATH = doc/config -@INCLUDE = common - -# Basic project information. -PROJECT_NAME = "Main" - -# Library documentation output directory. -HTML_OUTPUT = main - -# Generate Doxygen tag file for this library. -GENERATE_TAGFILE = doc/tag/main.tag - -# Files to show on the main page. -INPUT = README.md \ - CHANGELOG.md \ - PortingGuide.md \ - doc/architecture.txt - -# Path to architecture image. -IMAGE_PATH += doc/ - -# Use repository README as main page. -USE_MDFILE_AS_MAINPAGE = README.md - -# Don't automatically link to library symbols. -AUTOLINK_SUPPORT = NO - -# Use the Main page layout file -LAYOUT_FILE = doc/config/layout_main.xml diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/mqtt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/mqtt deleted file mode 100644 index 38da6f2f0..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/config/mqtt +++ /dev/null @@ -1,21 +0,0 @@ -# Include common configuration options. -@INCLUDE_PATH = doc/config -@INCLUDE = common - -# Basic project information. -PROJECT_NAME = "MQTT" -PROJECT_BRIEF = "MQTT v3.1.1 client library" - -# Library documentation output directory. -HTML_OUTPUT = mqtt - -# Generate Doxygen tag file for this library. -GENERATE_TAGFILE = doc/tag/mqtt.tag - -# Directories containing library source code. -INPUT = doc/lib \ - include/ \ - src/ - -# Library file names. -FILE_PATTERNS = *mqtt*.c *mqtt*.h *mqtt*.txt diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/lib/mqtt.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/lib/mqtt.txt deleted file mode 100644 index 03a77d30f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/doc/lib/mqtt.txt +++ /dev/null @@ -1,61 +0,0 @@ -/** -@mainpage -@anchor mqtt -@brief MQTT v3.1.1 client library. - -MQTT is a standardized publish subscribe protocol popular on embedded devices. The MQTT library provided with this SDK implements a subset of the MQTT v3.1.1 protocol. The sample application for Linux `subscribe_publish_sample.c` is provided as a starting point for using this library. - -The interface for communication over MQTT is provided in the file `aws_iot_mqtt_interface.h`. -- MQTT client context management: @ref mqtt_function_init and @ref mqtt_function_free -- Connection management: @ref mqtt_function_connect and @ref mqtt_function_disconnect -- Publishing messages to the server: @ref mqtt_function_publish -- Managing subscriptions: @ref mqtt_function_subscribe and @ref mqtt_function_unsubscribe -- Process incoming messages, reconnections, and keep-alive: @ref mqtt_function_yield - -@note In a multithreaded environment, always ensure that calls to this library's functions are serialized, such as with a lock or a queue. This library is not thread safe. - -@note This library does not support QoS 2 or retained messages. - -@section mqtt_configuration Configuration -@brief The following configuration settings are associated with this MQTT library. -- `AWS_IOT_MQTT_TX_BUF_LEN`
-Size of buffer for outgoing messages. -- `AWS_IOT_MQTT_RX_BUF_LEN`
-Size of buffer for incoming messages. Messages longer than this will be dropped. -- `AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS`
-Number of subscriptions that may be registered simultaneously. -- `AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL`
-The initial wait time before the first reconnect attempt. See @ref mqtt_autoreconnect. -- `AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL`
-The maximum wait time between reconnect attempts. See @ref mqtt_autoreconnect. -*/ - -/** -@page mqtt_autoreconnect Auto-reconnect -@brief This page describes the auto-reconnect mechanism of the MQTT library. - -The auto-reconnect mechanism can be enabled through the following methods: -- Set #IoT_Client_Init_Params.enableAutoReconnect to `true` when calling @ref mqtt_function_init. -- Call @ref mqtt_function_autoreconnect_set_status with `newStatus` set to `true`. @ref mqtt_function_autoreconnect_set_status must only be called after @ref mqtt_function_connect. - -Once enabled, this feature will attempt to reconnect to the server if the library detects a disconnection. The reconnections are handled through @ref mqtt_function_yield. In addition to re-establishing the network connection and MQTT session, all the previous subscriptions will be re-established. This restores the client-side subscriptions for both clean and persistent MQTT sessions. - -The following events are considered disconnects: -- Fatal errors returned from the TLS layer. -- Failure to send a ping request. -- Failure to receive a timely ping response. - -On all disconnect events, the #iot_disconnect_handler for an MQTT client will be called. - -Reconnect attempts are made with an exponential backoff strategy. -- `AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL`
-The initial wait time before the first reconnect attempt. -- `AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL`
-The maximum wait time between reconnect attempts. - -If a reconnect attempt after `AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL` fails, @ref mqtt_function_yield will return `NETWORK_RECONNECT_TIMED_OUT`. There will be no more reconnect attempts. If an application still wants to re-connect, it should call @ref mqtt_function_attempt_reconnect. - -Calling @ref mqtt_function_attempt_reconnect performs a single reconnect and resubscribe attempt. It is equivalent to a manual reconnect attempt. - -@note Since reconnects are handled by @ref mqtt_function_yield and a new TLS handshake for reconnection may take a significant amount of time, calls to @ref mqtt_function_yield that handle reconnections may block for longer than usual. -*/ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/CppUTest/README.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/CppUTest/README.txt deleted file mode 100644 index 5b2e09255..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/CppUTest/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Copy source code for CppUTest into this directory -# The SDK was tested internally with CppUTest v3.6 which can be found here - https://github.com/cpputest/cpputest/releases/tag/v3.6 \ No newline at end of file diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.c deleted file mode 100644 index e920e8620..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2010 Serge A. Zaitsev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/** - * @file jsmn.c - * @brief Implementation of the JSMN (Jasmine) JSON parser. - * - * For more information on JSMN: - * @see http://zserge.com/jsmn.html - */ - -#include "jsmn.h" - -/** - * Allocates a fresh unused token from the token pull. - */ -static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, - jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *tok; - if (parser->toknext >= num_tokens) { - return NULL; - } - tok = &tokens[parser->toknext++]; - tok->start = tok->end = -1; - tok->size = 0; -#ifdef JSMN_PARENT_LINKS - tok->parent = -1; -#endif - return tok; -} - -/** - * Fills token type and boundaries. - */ -static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, - int start, int end) { - token->type = type; - token->start = start; - token->end = end; - token->size = 0; -} - -/** - * Fills next available token with JSON primitive. - */ -static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - int start; - - start = parser->pos; - - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - switch (js[parser->pos]) { -#ifndef JSMN_STRICT - /* In strict mode primitive must be followed by "," or "}" or "]" */ - case ':': -#endif - case '\t' : case '\r' : case '\n' : case ' ' : - case ',' : case ']' : case '}' : - goto found; - } - if (js[parser->pos] < 32 || js[parser->pos] >= 127) { - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } -#ifdef JSMN_STRICT - /* In strict mode primitive must be followed by a comma/object/array */ - parser->pos = start; - return JSMN_ERROR_PART; -#endif - -found: - if (tokens == NULL) { - parser->pos--; - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - parser->pos--; - return 0; -} - -/** - * Fills next token with JSON string. - */ -static int jsmn_parse_string(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - - int start = parser->pos; - - parser->pos++; - - /* Skip starting quote */ - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c = js[parser->pos]; - - /* Quote: end of string */ - if (c == '\"') { - if (tokens == NULL) { - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - return 0; - } - - /* Backslash: Quoted symbol expected */ - if (c == '\\' && parser->pos + 1 < len) { - int i; - parser->pos++; - switch (js[parser->pos]) { - /* Allowed escaped symbols */ - case '\"': case '/' : case '\\' : case 'b' : - case 'f' : case 'r' : case 'n' : case 't' : - break; - /* Allows escaped symbol \uXXXX */ - case 'u': - parser->pos++; - for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { - /* If it isn't a hex character we have an error */ - if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ - (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ - (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ - parser->pos = start; - return JSMN_ERROR_INVAL; - } - parser->pos++; - } - parser->pos--; - break; - /* Unexpected symbol */ - default: - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } - } - parser->pos = start; - return JSMN_ERROR_PART; -} - -/** - * Parse JSON string and fill tokens. - */ -int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens) { - int r; - int i; - jsmntok_t *token; - int count = parser->toknext; - - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c; - jsmntype_t type; - - c = js[parser->pos]; - switch (c) { - case '{': case '[': - count++; - if (tokens == NULL) { - break; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) - return JSMN_ERROR_NOMEM; - if (parser->toksuper != -1) { - tokens[parser->toksuper].size++; -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - } - token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); - token->start = parser->pos; - parser->toksuper = parser->toknext - 1; - break; - case '}': case ']': - if (tokens == NULL) - break; - type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); -#ifdef JSMN_PARENT_LINKS - if (parser->toknext < 1) { - return JSMN_ERROR_INVAL; - } - token = &tokens[parser->toknext - 1]; - for (;;) { - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - token->end = parser->pos + 1; - parser->toksuper = token->parent; - break; - } - if (token->parent == -1) { - if(token->type != type || parser->toksuper == -1) { - return JSMN_ERROR_INVAL; - } - break; - } - token = &tokens[token->parent]; - } -#else - for (i = parser->toknext - 1; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - parser->toksuper = -1; - token->end = parser->pos + 1; - break; - } - } - /* Error if unmatched closing bracket */ - if (i == -1) return JSMN_ERROR_INVAL; - for (; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - parser->toksuper = i; - break; - } - } -#endif - break; - case '\"': - r = jsmn_parse_string(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - case '\t' : case '\r' : case '\n' : case ' ': - break; - case ':': - parser->toksuper = parser->toknext - 1; - break; - case ',': - if (tokens != NULL && parser->toksuper != -1 && - tokens[parser->toksuper].type != JSMN_ARRAY && - tokens[parser->toksuper].type != JSMN_OBJECT) { -#ifdef JSMN_PARENT_LINKS - parser->toksuper = tokens[parser->toksuper].parent; -#else - for (i = parser->toknext - 1; i >= 0; i--) { - if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { - if (tokens[i].start != -1 && tokens[i].end == -1) { - parser->toksuper = i; - break; - } - } - } -#endif - } - break; -#ifdef JSMN_STRICT - /* In strict mode primitives are: numbers and booleans */ - case '-': case '0': case '1' : case '2': case '3' : case '4': - case '5': case '6': case '7' : case '8': case '9': - case 't': case 'f': case 'n' : - /* And they must not be keys of the object */ - if (tokens != NULL && parser->toksuper != -1) { - jsmntok_t *t = &tokens[parser->toksuper]; - if (t->type == JSMN_OBJECT || - (t->type == JSMN_STRING && t->size != 0)) { - return JSMN_ERROR_INVAL; - } - } -#else - /* In non-strict mode every unquoted value is a primitive */ - default: -#endif - r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - -#ifdef JSMN_STRICT - /* Unexpected char in strict mode */ - default: - return JSMN_ERROR_INVAL; -#endif - } - } - - if (tokens != NULL) { - for (i = parser->toknext - 1; i >= 0; i--) { - /* Unmatched opened object or array */ - if (tokens[i].start != -1 && tokens[i].end == -1) { - return JSMN_ERROR_PART; - } - } - } - - return count; -} - -/** - * Creates a new parser based over a given buffer with an array of tokens - * available. - */ -void jsmn_init(jsmn_parser *parser) { - parser->pos = 0; - parser->toknext = 0; - parser->toksuper = -1; -} - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.h deleted file mode 100644 index e0ffb1bc4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/jsmn/jsmn.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2010 Serge A. Zaitsev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/** - * @file jsmn.h - * @brief Definition of the JSMN (Jasmine) JSON parser. - * - * For more information on JSMN: - * @see http://zserge.com/jsmn.html - */ - -#ifndef __JSMN_H_ -#define __JSMN_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * JSON type identifier. Basic types are: - * o Object - * o Array - * o String - * o Other primitive: number, boolean (true/false) or null - */ -typedef enum { - JSMN_UNDEFINED = 0, - JSMN_OBJECT = 1, - JSMN_ARRAY = 2, - JSMN_STRING = 3, - JSMN_PRIMITIVE = 4 -} jsmntype_t; - -enum jsmnerr { - /* Not enough tokens were provided */ - JSMN_ERROR_NOMEM = -1, - /* Invalid character inside JSON string */ - JSMN_ERROR_INVAL = -2, - /* The string is not a full JSON packet, more bytes expected */ - JSMN_ERROR_PART = -3 -}; - -/** - * JSON token description. - * type type (object, array, string etc.) - * start start position in JSON data string - * end end position in JSON data string - */ -typedef struct { - jsmntype_t type; - int start; - int end; - int size; -#ifdef JSMN_PARENT_LINKS - int parent; -#endif -} jsmntok_t; - -/** - * JSON parser. Contains an array of token blocks available. Also stores - * the string being parsed now and current position in that string - */ -typedef struct { - unsigned int pos; /* offset in the JSON string */ - unsigned int toknext; /* next token to allocate */ - int toksuper; /* superior token node, e.g parent object or array */ -} jsmn_parser; - -/** - * Create JSON parser over an array of tokens - */ -void jsmn_init(jsmn_parser *parser); - -/** - * Run JSON parser. It parses a JSON data string into and array of tokens, each describing - * a single JSON object. - */ -int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens); - -#ifdef __cplusplus -} -#endif - -#endif /* __JSMN_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/mbedTLS/README.txt b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/mbedTLS/README.txt deleted file mode 100644 index b6b428d36..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/external_libs/mbedTLS/README.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Copy source code for mbedTLS into this directory -# -# You'll need to download mbedTLS from the official ARMmbed repository and -# place the files here. We recommend that you pick the latest version of 2.16 -# LTS release in order to have up-to-date security fixes. - -# Note that this SDK will not negotiate the TLS Maximum Fragment Length even if -# it is enabled in mbedTLS' configuration. Therefore, you should ensure content -# buffers used by mbedTLS are at least 16384 bytes in length to use the largest -# maximum record length supported by TLS. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/filterGcov.sh b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/filterGcov.sh deleted file mode 100755 index fee4a0327..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/filterGcov.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -INPUT_FILE=$1 -TEMP_FILE1=${INPUT_FILE}1.tmp -TEMP_FILE2=${INPUT_FILE}2.tmp -TEMP_FILE3=${INPUT_FILE}3.tmp -ERROR_FILE=$2 -OUTPUT_FILE=$3 -HTML_OUTPUT_FILE=$3.html -TEST_RESULTS=$4 - -flattenGcovOutput() { -while read line1 -do - read line2 - echo $line2 " " $line1 - read junk - read junk -done < ${INPUT_FILE} -} - -getRidOfCruft() { -sed '-e s/^Lines.*://g' \ - '-e s/^[0-9]\./ &/g' \ - '-e s/^[0-9][0-9]\./ &/g' \ - '-e s/of.*File/ /g' \ - "-e s/'//g" \ - '-e s/^.*\/usr\/.*$//g' \ - '-e s/^.*\.$//g' -} - -flattenPaths() { -sed \ - -e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \ - -e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \ - -e 's/\/[^/][^/]*\/[^/][^/]*\/\.\.\/\.\.\//\//g' \ - -e 's/\/[^/][^/]*\/\.\.\//\//g' -} - -getFileNameRootFromErrorFile() { -sed '-e s/gc..:cannot open .* file//g' ${ERROR_FILE} -} - -writeEachNoTestCoverageFile() { -while read line -do - echo " 0.00% " ${line} -done -} - -createHtmlOutput() { - echo "" - echo "" - sed "-e s/.*% /
CoverageFile
&<\/td>/" \ - "-e s/[a-zA-Z0-9_]*\.[ch][a-z]*/&<\/a><\/td><\/tr>/" - echo "
" - sed "-e s/.*/&
/g" < ${TEST_RESULTS} -} - -flattenGcovOutput | getRidOfCruft | flattenPaths > ${TEMP_FILE1} -getFileNameRootFromErrorFile | writeEachNoTestCoverageFile | flattenPaths > ${TEMP_FILE2} -cat ${TEMP_FILE1} ${TEMP_FILE2} | sort | uniq > ${OUTPUT_FILE} -createHtmlOutput < ${OUTPUT_FILE} > ${HTML_OUTPUT_FILE} -rm -f ${TEMP_FILE1} ${TEMP_FILE2} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_error.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_error.h deleted file mode 100644 index f0ccc3963..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_error.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_error.h - * @brief Definition of error types for the SDK. - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_ERROR_H_ -#define AWS_IOT_SDK_SRC_IOT_ERROR_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Used to avoid warnings in case of unused parameters in function pointers */ -#define IOT_UNUSED(x) (void)(x) - -/*! \public - * @brief IoT Error enum - * - * Enumeration of return values from the IoT_* functions within the SDK. - * Values less than -1 are specific error codes - * Value of -1 is a generic failure response - * Value of 0 is a generic success response - * Values greater than 0 are specific non-error return codes - */ -typedef enum { - /** Returned when the Network physical layer is connected */ - NETWORK_PHYSICAL_LAYER_CONNECTED = 6, - /** Returned when the Network is manually disconnected */ - NETWORK_MANUALLY_DISCONNECTED = 5, - /** Returned when the Network is disconnected and the reconnect attempt is in progress */ - NETWORK_ATTEMPTING_RECONNECT = 4, - /** Return value of yield function to indicate auto-reconnect was successful */ - NETWORK_RECONNECTED = 3, - /** Returned when a read attempt is made on the TLS buffer and it is empty */ - MQTT_NOTHING_TO_READ = 2, - /** Returned when a connection request is successful and packet response is connection accepted */ - MQTT_CONNACK_CONNECTION_ACCEPTED = 1, - /** Success return value - no error occurred */ - SUCCESS = 0, - /** A generic error. Not enough information for a specific error code */ - FAILURE = -1, - /** A required parameter was passed as null */ - NULL_VALUE_ERROR = -2, - /** The TCP socket could not be established */ - TCP_CONNECTION_ERROR = -3, - /** The TLS handshake failed */ - SSL_CONNECTION_ERROR = -4, - /** Error associated with setting up the parameters of a Socket */ - TCP_SETUP_ERROR = -5, - /** A timeout occurred while waiting for the TLS handshake to complete. */ - NETWORK_SSL_CONNECT_TIMEOUT_ERROR = -6, - /** A Generic write error based on the platform used */ - NETWORK_SSL_WRITE_ERROR = -7, - /** SSL initialization error at the TLS layer */ - NETWORK_SSL_INIT_ERROR = -8, - /** An error occurred when loading the certificates. The certificates could not be located or are incorrectly formatted. */ - NETWORK_SSL_CERT_ERROR = -9, - /** SSL Write times out */ - NETWORK_SSL_WRITE_TIMEOUT_ERROR = -10, - /** SSL Read times out */ - NETWORK_SSL_READ_TIMEOUT_ERROR = -11, - /** A Generic error based on the platform used */ - NETWORK_SSL_READ_ERROR = -12, - /** Returned when the Network is disconnected and reconnect is either disabled or physical layer is disconnected */ - NETWORK_DISCONNECTED_ERROR = -13, - /** Returned when the Network is disconnected and the reconnect attempt has timed out */ - NETWORK_RECONNECT_TIMED_OUT_ERROR = -14, - /** Returned when the Network is already connected and a connection attempt is made */ - NETWORK_ALREADY_CONNECTED_ERROR = -15, - /** Network layer Error Codes */ - /** Network layer Random number generator seeding failed */ - NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED = -16, - /** A generic error code for Network layer errors */ - NETWORK_SSL_UNKNOWN_ERROR = -17, - /** Returned when the physical layer is disconnected */ - NETWORK_PHYSICAL_LAYER_DISCONNECTED = -18, - /** Returned when the root certificate is invalid */ - NETWORK_X509_ROOT_CRT_PARSE_ERROR = -19, - /** Returned when the device certificate is invalid */ - NETWORK_X509_DEVICE_CRT_PARSE_ERROR = -20, - /** Returned when the private key failed to parse */ - NETWORK_PK_PRIVATE_KEY_PARSE_ERROR = -21, - /** Returned when the network layer failed to open a socket */ - NETWORK_ERR_NET_SOCKET_FAILED = -22, - /** Returned when the server is unknown */ - NETWORK_ERR_NET_UNKNOWN_HOST = -23, - /** Returned when connect request failed */ - NETWORK_ERR_NET_CONNECT_FAILED = -24, - /** Returned when there is nothing to read in the TLS read buffer */ - NETWORK_SSL_NOTHING_TO_READ = -25, - /** A connection could not be established. */ - MQTT_CONNECTION_ERROR = -26, - /** A timeout occurred while waiting for the TLS handshake to complete */ - MQTT_CONNECT_TIMEOUT_ERROR = -27, - /** A timeout occurred while waiting for the TLS request complete */ - MQTT_REQUEST_TIMEOUT_ERROR = -28, - /** The current client state does not match the expected value */ - MQTT_UNEXPECTED_CLIENT_STATE_ERROR = -29, - /** The client state is not idle when request is being made */ - MQTT_CLIENT_NOT_IDLE_ERROR = -30, - /** The MQTT RX buffer received corrupt or unexpected message */ - MQTT_RX_MESSAGE_PACKET_TYPE_INVALID_ERROR = -31, - /** The MQTT RX buffer received a bigger message. The message will be dropped */ - MQTT_RX_BUFFER_TOO_SHORT_ERROR = -32, - /** The MQTT TX buffer is too short for the outgoing message. Request will fail */ - MQTT_TX_BUFFER_TOO_SHORT_ERROR = -33, - /** The client is subscribed to the maximum possible number of subscriptions */ - MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR = -34, - /** Failed to decode the remaining packet length on incoming packet */ - MQTT_DECODE_REMAINING_LENGTH_ERROR = -35, - /** Connect request failed with the server returning an unknown error */ - MQTT_CONNACK_UNKNOWN_ERROR = -36, - /** Connect request failed with the server returning an unacceptable protocol version error */ - MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = -37, - /** Connect request failed with the server returning an identifier rejected error */ - MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR = -38, - /** Connect request failed with the server returning an unavailable error */ - MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR = -39, - /** Connect request failed with the server returning a bad userdata error */ - MQTT_CONNACK_BAD_USERDATA_ERROR = -40, - /** Connect request failed with the server failing to authenticate the request */ - MQTT_CONNACK_NOT_AUTHORIZED_ERROR = -41, - /** An error occurred while parsing the JSON string. Usually malformed JSON. */ - JSON_PARSE_ERROR = -42, - /** Shadow: The response Ack table is currently full waiting for previously published updates */ - SHADOW_WAIT_FOR_PUBLISH = -43, - /** Any time an snprintf writes more than size value, this error will be returned */ - SHADOW_JSON_BUFFER_TRUNCATED = -44, - /** Any time an snprintf encounters an encoding error or not enough space in the given buffer */ - SHADOW_JSON_ERROR = -45, - /** Mutex initialization failed */ - MUTEX_INIT_ERROR = -46, - /** Mutex lock request failed */ - MUTEX_LOCK_ERROR = -47, - /** Mutex unlock request failed */ - MUTEX_UNLOCK_ERROR = -48, - /** Mutex destroy failed */ - MUTEX_DESTROY_ERROR = -49, - /** Input argument exceeded the allowed maximum size */ - MAX_SIZE_ERROR = -50, - /** Some limit has been exceeded, e.g. the maximum number of subscriptions has been reached */ - LIMIT_EXCEEDED_ERROR = -51, - /** Invalid input topic type */ - INVALID_TOPIC_TYPE_ERROR = -52 -} IoT_Error_t; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_SDK_SRC_IOT_ERROR_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_interface.h deleted file mode 100644 index 4f033d9d6..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_interface.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_jobs_interface.h - * @brief An interface for interacting with the AWS IoT Jobs system. - * - * This file defines utility functions for interacting with the AWS IoT jobs - * APIs over MQTT. It provides functions for managing subscriptions to job - * related topics and for sending queries and updates requests for jobs. - * Callers are responsible for managing the subscriptions and associating - * responses with the queries and update messages. - */ -#ifndef AWS_IOT_JOBS_INTERFACE_H_ -#define AWS_IOT_JOBS_INTERFACE_H_ - -#ifdef DISABLE_IOT_JOBS -#error "Jobs API is disabled" -#endif - -/** - * @file aws_iot_jobs_interface.h - * @brief Functions for interacting with the AWS IoT Jobs system. - */ -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_jobs_topics.h" -#include "aws_iot_jobs_types.h" -#include "aws_iot_error.h" -#include "aws_iot_json_utils.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Subscribe to jobs messages for the given thing and/or jobs. - * - * The function can be used to subscribe to all job related messages. To subscribe - * to messages not related to a job the jobId passed should be null. The jobId - * can also be "+" to subscribe to messages related to any job, or "$next" to - * indicate the next pending job. - * - * See also #aws_iot_jobs_subscribe_to_all_job_messages to subscribe to all possible - * messages in one operation. - * - * \note Subscribing with the same thing, job and topic type more than - * once is undefined. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the name of the thing to subscribe to - * \param jobId the job id to subscribe to. To subscribe to messages not related to - * a job the jobId passed should be null. The jobId can also be "+" to subscribe to - * messages related to any job, or "$next" to indicate the next pending job. - * \param topicType the topic type to subscribe to - * \param replyType the reply topic type to subscribe to - * \param pApplicationHandler the callback handler - * \param pApplicationHandlerData the callback context data. This must remain valid at least until - * aws_iot_jobs_unsubscribe_from_job_messages is called. - * \param topicBuffer. A buffer to use to hold the topic name for the subscription. This buffer - * must remain valid at least until aws_iot_jobs_unsubscribe_from_job_messages is called. - * \param topicBufferSize the size of the topic buffer. The function will fail - * with LIMIT_EXCEEDED_ERROR if this is too small. - * \return the result of subscribing to the topic (see aws_iot_mqtt_subscribe) - */ -IoT_Error_t aws_iot_jobs_subscribe_to_job_messages( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - AwsIotJobExecutionTopicType topicType, - AwsIotJobExecutionTopicReplyType replyType, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData, - char *topicBuffer, - uint16_t topicBufferSize); - -/** - * @brief Subscribe to all job messages. - * - * Subscribe to all job messages for the given thing. - * - * \note Subscribing with the same thing more than once is undefined. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the name of the thing to subscribe to - * \param pApplicationHandler the callback handler - * \param pApplicationHandlerData the callback context data. This must remain valid at least until - * aws_iot_jobs_unsubscribe_from_job_messages is called. - * \param topicBuffer. A buffer to use to hold the topic name for the subscription. This buffer - * must remain valid at least until aws_iot_jobs_unsubscribe_from_job_messages is called. - * \param topicBufferSize the size of the topic buffer. The function will fail - * with LIMIT_EXCEEDED_ERROR if this is too small. - * \return the result of subscribing to the topic (see aws_iot_mqtt_subscribe) - */ -IoT_Error_t aws_iot_jobs_subscribe_to_all_job_messages( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData, - char *topicBuffer, - uint16_t topicBufferSize); - -/** - * @brief Unsubscribe from a job subscription - * - * Remove the subscription created using #aws_iot_jobs_subscribe_to_job_messages or - * #aws_iot_jobs_subscribe_to_all_job_messages. - * - * \param pClient the client to use - * \param topicBuffer the topic buffer passed to #aws_iot_jobs_subscribe_to_job_messages or - * #aws_iot_jobs_subscribe_to_all_job_messages when the subscription was created. - * \return #SUCCESS or the first error encountered. - */ -IoT_Error_t aws_iot_jobs_unsubscribe_from_job_messages( - AWS_IoT_Client *pClient, - char *topicBuffer); - -/** - * @brief Send a query to one of the job query APIs. - * - * Send a query to one of the job query APIs. If jobId is null this - * requests a list of pending jobs for the thing. If jobId is - * not null then it sends a query for the details of that job. - * If jobId is $next then it sends a query for the details for - * the next pending job. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the thing name to query for - * \param jobId the id of the job to query for. If null a list - * of all pending jobs for the thing is requested. - * \param clientToken the client token to use for the query. - * If null no clientToken is sent resulting in an empty message. - * \param topicBuffer the topic buffer to use. This may be discarded - * as soon as this function returns - * \param topicBufferSize the size of topicBuffer - * \param messageBuffer the message buffer to use. May be NULL - * if clientToken is NULL - * \param messageBufferSize the size of messageBuffer - * \param topicType the topic type to publish query to - * \return LIMIT_EXCEEDED_ERROR if the topic buffer or - * message buffer is too small, NULL_VALUE_ERROR if the any of - * the required inputs are NULL, otherwise the result - * of the mqtt publish - */ -IoT_Error_t aws_iot_jobs_send_query( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const char *clientToken, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize, - AwsIotJobExecutionTopicType topicType); - -/** - * @brief Send a start next command to the job start-next API. - * - * Send a start next command to the job start-next API. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the thing name to query for - * \param startNextRequest the start-next request to send - * \param topicBuffer the topic buffer to use. This may be discarded - * as soon as this function returns - * \param topicBufferSize the size of topicBuffer - * \param messageBuffer the message buffer to use. May be NULL - * if clientToken is NULL - * \param messageBufferSize the size of messageBuffer - * \return LIMIT_EXCEEDED_ERROR if the topic buffer or - * message buffer is too small, NULL_VALUE_ERROR if the any of - * the required inputs are NULL, otherwise the result - * of the mqtt publish - */ -IoT_Error_t aws_iot_jobs_start_next( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const AwsIotStartNextPendingJobExecutionRequest *startNextRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize); - -/** - * @brief Send a describe job query to the job query API. - * - * Send a describe job query to the job query API. If jobId is null this - * requests a list of pending jobs for the thing. If jobId is - * not null then it sends a query for the details of that job. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the thing name to query for - * \param jobId the id of the job to query for. If null a list - * of all pending jobs for the thing is requested. - * \param describeRequest the describe request to send - * \param topicBuffer the topic buffer to use. This may be discarded - * as soon as this function returns - * \param topicBufferSize the size of topicBuffer - * \param messageBuffer the message buffer to use. May be NULL - * if clientToken is NULL - * \param messageBufferSize the size of messageBuffer - * \return LIMIT_EXCEEDED_ERROR if the topic buffer or - * message buffer is too small, NULL_VALUE_ERROR if the any of - * the required inputs are NULL, otherwise the result - * of the mqtt publish - */ -IoT_Error_t aws_iot_jobs_describe( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const AwsIotDescribeJobExecutionRequest *describeRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize); - -/** - * @brief Send an update about a job execution. - * - * Send an update about a job execution. - * - * \param pClient the client to use - * \param qos the qos to use - * \param thingName the thing name to send the update for - * \param jobId the id of the job to send the update for - * \param updateRequest the update request to send - * \param topicBuffer the topic buffer to use. This may be discarded - * as soon as this function returns - * \param topicBufferSize the size of topicBuffer - * \param messageBuffer the message buffer to use. - * \param messageBufferSize the size of messageBuffer - * \return LIMIT_EXCEEDED_ERROR if the topic buffer or - * message buffer is too small, NULL_VALUE_ERROR if the any of - * the required inputs are NULL, otherwise the result - * of the mqtt publish - */ -IoT_Error_t aws_iot_jobs_send_update( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const AwsIotJobExecutionUpdateRequest *updateRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize); - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_JOBS_INTERFACE_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_json.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_json.h deleted file mode 100644 index 55e45142b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_json.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_jobs_json.h - * @brief Functions for mapping between json and the AWS Iot Job data structures. - */ - -#ifdef DISABLE_IOT_JOBS -#error "Jobs API is disabled" -#endif - -#ifndef AWS_IOT_JOBS_JSON_H_ -#define AWS_IOT_JOBS_JSON_H_ - -#include -#include "jsmn.h" -#include "aws_iot_jobs_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Serialize a job execution update request into a json string. - * - * \param requestBuffer buffer to contain the serialized request. If null - * this function will return the size of the buffer required - * \param bufferSize the size of the buffer. If this is smaller than the required - * length the string will be truncated to fit. - * \request the request to serialize. - * \return The size of the json string to store the serialized request or -1 - * if the request is invalid. Note that the return value should be checked against - * the size of the buffer and if its larger handle the fact that the string has - * been truncated. - */ -int aws_iot_jobs_json_serialize_update_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotJobExecutionUpdateRequest *request); - -/** - * Serialize a job API request that contains only a client token. - * - * \param requestBuffer buffer to contain the serialized request. If null - * this function will return the size of the buffer required - * \param bufferSize the size of the buffer. If this is smaller than the required - * length the string will be truncated to fit. - * \param clientToken the client token to use for the request. - * \return The size of the json string to store the serialized request or -1 - * if the request is invalid. Note that the return value should be checked against - * the size of the buffer and if its larger handle the fact that the string has - * been truncated. - */ -int aws_iot_jobs_json_serialize_client_token_only_request( - char *requestBuffer, size_t bufferSize, - const char *clientToken); - -/** - * Serialize describe job execution request into json string. - * - * \param requestBuffer buffer to contain the serialized request. If null - * this function will return the size of the buffer required - * \param bufferSize the size of the buffer. If this is smaller than the required - * length the string will be truncated to fit. - * \param request the request to serialize. - * \return The size of the json string to store the serialized request or -1 - * if the request is invalid. Note that the return value should be checked against - * the size of the buffer and if its larger handle the fact that the string has - * been truncated. - */ -int aws_iot_jobs_json_serialize_describe_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotDescribeJobExecutionRequest *request); - -/** - * Serialize start next job execution request into json string. - * - * \param requestBuffer buffer to contain the serialized request. If null - * this function will return the size of the buffer required - * \param bufferSize the size of the buffer. If this is smaller than the required - * length the string will be truncated to fit. - * \param request the start-next request to serialize. - * \return The size of the json string to store the serialized request or -1 - * if the request is invalid. Note that the return value should be checked against - * the size of the buffer and if its larger handle the fact that the string has - * been truncated. - */ -int aws_iot_jobs_json_serialize_start_next_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotStartNextPendingJobExecutionRequest *request); - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_JOBS_JSON_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_topics.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_topics.h deleted file mode 100644 index 3e291878b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_topics.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_job_topics.h - * @brief Functions for parsing and creating MQTT topics used by the AWS IoT Jobs system. - */ - -#ifdef DISABLE_IOT_JOBS -#error "Jobs API is disabled" -#endif - -#ifndef AWS_IOT_JOBS_TOPICS_H_ -#define AWS_IOT_JOBS_TOPICS_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define JOB_ID_NEXT "$next" -#define JOB_ID_WILDCARD "+" - -/** - * The type of job topic. - */ -typedef enum { - JOB_UNRECOGNIZED_TOPIC = 0, - JOB_GET_PENDING_TOPIC, - JOB_START_NEXT_TOPIC, - JOB_DESCRIBE_TOPIC, - JOB_UPDATE_TOPIC, - JOB_NOTIFY_TOPIC, - JOB_NOTIFY_NEXT_TOPIC, - JOB_WILDCARD_TOPIC -} AwsIotJobExecutionTopicType; - -/** - * The type of reply topic, or #JOB_REQUEST_TYPE for - * topics that are not replies. - */ -typedef enum { - JOB_UNRECOGNIZED_TOPIC_TYPE = 0, - JOB_REQUEST_TYPE, - JOB_ACCEPTED_REPLY_TYPE, - JOB_REJECTED_REPLY_TYPE, - JOB_WILDCARD_REPLY_TYPE -} AwsIotJobExecutionTopicReplyType; - -/** - * @brief Get the topic matching the provided details and put into the provided buffer. - * - * If the buffer is not large enough to store the full topic the topic will be truncated - * to fit, with the last character always being a null terminator. - * - * \param buffer the buffer to put the results into - * \param bufferSize the size of the buffer - * \param topicType the type of the topic - * \param replyType the reply type of the topic - * \param thingName the name of the thing in the topic - * \param jobId the name of the job id in the topic - * \return the number of characters in the topic excluding the null terminator. A return - * value of bufferSize or more means that the topic string was truncated. - */ -int aws_iot_jobs_get_api_topic(char *buffer, size_t bufferSize, - AwsIotJobExecutionTopicType topicType, AwsIotJobExecutionTopicReplyType replyType, - const char* thingName, const char* jobId); - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_JOBS_TOPICS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_types.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_types.h deleted file mode 100644 index b96ac02b7..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_jobs_types.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_jobs_types.h - * @brief Structures defining the interface with the AWS IoT Jobs system - * - * This file defines the structures returned by and sent to the AWS IoT Jobs system. - * - */ - -#ifdef DISABLE_IOT_JOBS -#error "Jobs API is disabled" -#endif - -#ifndef AWS_IOT_JOBS_TYPES_H_ -#define AWS_IOT_JOBS_TYPES_H_ - -#include -#include -#include "jsmn.h" -#include "timer_interface.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - JOB_EXECUTION_STATUS_NOT_SET = 0, - JOB_EXECUTION_QUEUED, - JOB_EXECUTION_IN_PROGRESS, - JOB_EXECUTION_FAILED, - JOB_EXECUTION_SUCCEEDED, - JOB_EXECUTION_CANCELED, - JOB_EXECUTION_REJECTED, - /*** - * Used for any status not in the supported list of statuses - */ - JOB_EXECUTION_UNKNOWN_STATUS = 99 -} JobExecutionStatus; - -extern const char *JOB_EXECUTION_QUEUED_STR; -extern const char *JOB_EXECUTION_IN_PROGRESS_STR; -extern const char *JOB_EXECUTION_FAILED_STR; -extern const char *JOB_EXECUTION_SUCCEEDED_STR; -extern const char *JOB_EXECUTION_CANCELED_STR; -extern const char *JOB_EXECUTION_REJECTED_STR; - -/** - * Convert a string to its matching status. - * - * \return the matching status, or JOB_EXECUTION_UNKNOWN_STATUS if the string was not recognized. - */ -JobExecutionStatus aws_iot_jobs_map_string_to_job_status(const char *str); - -/** - * Convert a status to its string. - * - * \return a string representing the status, or null if the status is not recognized. - */ -const char *aws_iot_jobs_map_status_to_string(JobExecutionStatus status); - -/** - * A request to update the status of a job execution. - */ -typedef struct { - int64_t expectedVersion; // set to 0 to ignore - int64_t executionNumber; // set to 0 to ignore - JobExecutionStatus status; - const char *statusDetails; - bool includeJobExecutionState; - bool includeJobDocument; - const char *clientToken; -} AwsIotJobExecutionUpdateRequest; - -/** - * A request to get the status of a job execution. - */ -typedef struct { - int64_t executionNumber; // set to 0 to ignore - bool includeJobDocument; - const char *clientToken; -} AwsIotDescribeJobExecutionRequest; - -/** - * A request to get and start the next pending (not in a terminal state) job execution for a Thing. - */ -typedef struct { - const char *statusDetails; - const char *clientToken; -} AwsIotStartNextPendingJobExecutionRequest; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_JOBS_TYPES_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_json_utils.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_json_utils.h deleted file mode 100644 index af762d8a9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_json_utils.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_json_utils.h - * @brief Utilities for manipulating JSON - * - * json_utils provides JSON parsing utilities for use with the IoT SDK. - * Underlying JSON parsing relies on the Jasmine JSON parser. - * - */ - -#ifndef AWS_IOT_SDK_SRC_JSON_UTILS_H_ -#define AWS_IOT_SDK_SRC_JSON_UTILS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "aws_iot_error.h" -#include "jsmn.h" - -// utility functions -/** - * @brief JSON Equality Check - * - * Given a token pointing to a particular JSON node and an - * input string, check to see if the key is equal to the string. - * - * @param json json string - * @param tok json token - pointer to key to test for equality - * @param s input string for key to test equality - * - * @return 0 if equal, 1 otherwise - */ -int8_t jsoneq(const char *json, jsmntok_t *tok, const char *s); - -/** - * @brief Parse a signed 32-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of int32_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseInteger32Value(int32_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a signed 16-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of int16_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseInteger16Value(int16_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a signed 8-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of int8_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseInteger8Value(int8_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse an unsigned 32-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of uint32_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseUnsignedInteger32Value(uint32_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse an unsigned 16-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of uint16_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseUnsignedInteger16Value(uint16_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse an unsigned 8-bit integer value from a JSON node. - * - * Given a JSON node parse the integer value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param i address of uint8_t to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseUnsignedInteger8Value(uint8_t *i, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a float value from a JSON node. - * - * Given a JSON node parse the float value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param f address of float to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseFloatValue(float *f, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a double value from a JSON node. - * - * Given a JSON node parse the double value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param d address of double to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseDoubleValue(double *d, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a boolean value from a JSON node. - * - * Given a JSON node parse the boolean value from the value. - * - * @param jsonString json string - * @param tok json token - pointer to JSON node - * @param b address of boolean to be updated - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token); - -/** - * @brief Parse a string value from a JSON node. - * - * Given a JSON node parse the string value from the value. - * - * @param buf address of string to be updated - * @param bufLen length of buf in bytes - * @param jsonString json string - * @param token json token - pointer to JSON node - * - * @return SUCCESS - success - * @return JSON_PARSE_ERROR - error parsing value - */ -IoT_Error_t parseStringValue(char *buf, size_t bufLen, const char *jsonString, jsmntok_t *token); - -/** - * @brief Find the JSON node associated with the given key in the given object. - * - * Given a JSON node parse the string value from the value. - * - * @param key json key - * @param token json token - pointer to JSON node - * @param jsonString json string - * - * @return pointer to found property value - * @return NULL - not found - */ -jsmntok_t *findToken(const char *key, const char *jsonString, jsmntok_t *token); - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_SDK_SRC_JSON_UTILS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_log.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_log.h deleted file mode 100644 index 2eeac5954..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_log.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_log.h - * @brief Logging macros for the SDK. - * This file defines common logging macros with log levels to be used within the SDK. - * These macros can also be used in the IoT application code as a common way to output - * logs. The log levels can be tuned by modifying the makefile. Removing (commenting - * out) the IOT_* statement in the makefile disables that log level. - * - * It is expected that the macros below will be modified or replaced when porting to - * specific hardware platforms as printf may not be the desired behavior. - */ - -#ifndef _IOT_LOG_H -#define _IOT_LOG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** - * @brief Debug level logging macro. - * - * Macro to expose function, line number as well as desired log message. - */ -#ifdef ENABLE_IOT_DEBUG -#define IOT_DEBUG(...) \ - {\ - printf("DEBUG: %s L#%d ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#undef IOT_DEBUG -#define IOT_DEBUG(...) -#endif - -/** - * @brief Debug level trace logging macro. - * - * Macro to print message function entry and exit - */ -#ifdef ENABLE_IOT_TRACE -#define FUNC_ENTRY \ - {\ - printf("FUNC_ENTRY: %s L#%d \n", __func__, __LINE__); \ - } -#define FUNC_EXIT \ - {\ - printf("FUNC_EXIT: %s L#%d \n", __func__, __LINE__); \ - } -#define FUNC_EXIT_RC(x) \ - {\ - printf("FUNC_EXIT: %s L#%d Return Code : %d \n", __func__, __LINE__, x); \ - return x; \ - } -#else -#undef FUNC_ENTRY -#define FUNC_ENTRY - -#undef FUNC_EXIT -#define FUNC_EXIT -#undef FUNC_EXIT_RC -#define FUNC_EXIT_RC(x) { return x; } -#endif - -/** - * @brief Info level logging macro. - * - * Macro to expose desired log message. Info messages do not include automatic function names and line numbers. - */ -#ifdef ENABLE_IOT_INFO -#define IOT_INFO(...) \ - {\ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#undef IOT_INFO -#define IOT_INFO(...) -#endif - -/** - * @brief Warn level logging macro. - * - * Macro to expose function, line number as well as desired log message. - */ -#ifdef ENABLE_IOT_WARN -#define IOT_WARN(...) \ - { \ - printf("WARN: %s L#%d ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#undef IOT_WARN -#define IOT_WARN(...) -#endif - -/** - * @brief Error level logging macro. - * - * Macro to expose function, line number as well as desired log message. - */ -#ifdef ENABLE_IOT_ERROR -#define IOT_ERROR(...) \ - { \ - printf("ERROR: %s L#%d ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\n"); \ - } -#else -#undef IOT_ERROR -#define IOT_ERROR(...) -#endif - -#ifdef __cplusplus -} -#endif - -#endif // _IOT_LOG_H diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client.h deleted file mode 100644 index 9ba98c8ba..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client.h +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client.h - * @brief Client definition for MQTT - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_MQTT_CLIENT_H -#define AWS_IOT_SDK_SRC_IOT_MQTT_CLIENT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Library Header files */ -#include "stdio.h" -#include "stdbool.h" -#include "stdint.h" -#include "stddef.h" - -/* AWS Specific header files */ -#include "aws_iot_error.h" -#include "aws_iot_config.h" - -/* Platform specific implementation header files */ -#include "network_interface.h" -#include "timer_interface.h" - -#ifdef _ENABLE_THREAD_SUPPORT_ -#include "threads_interface.h" -#endif - -/** Greatest packet identifier, per MQTT spec */ -#define MAX_PACKET_ID 65535 - -typedef struct _Client AWS_IoT_Client; - -/** - * @brief Quality of Service Type - * - * Defining a QoS type. - * @note QoS 2 is \b NOT supported by the AWS IoT Service at the time of this SDK release. - * - */ -typedef enum QoS { - QOS0 = 0, - QOS1 = 1 -} QoS; - -/** - * @brief Publish Message Parameters Type - * - * Defines a type for MQTT Publish messages. Used for both incoming and out going messages - * - */ -typedef struct { - QoS qos; ///< Message Quality of Service - uint8_t isRetained; ///< Retained messages are \b NOT supported by the AWS IoT Service at the time of this SDK release. - uint8_t isDup; ///< Is this message a duplicate QoS > 0 message? Handled automatically by the MQTT client. - uint16_t id; ///< Message sequence identifier. Handled automatically by the MQTT client. - void *payload; ///< Pointer to MQTT message payload (bytes). - size_t payloadLen; ///< Length of MQTT payload. -} IoT_Publish_Message_Params; - -/** - * @brief MQTT Version Type - * - * Defining an MQTT version type. Only 3.1.1 is supported at this time - * - */ -typedef enum { - MQTT_3_1_1 = 4 ///< MQTT 3.1.1 (protocol message byte = 4) -} MQTT_Ver_t; - -/** - * @brief Last Will and Testament Definition - * - * Defining a type for the MQTT "Last Will and Testament" (LWT) parameters. - * @note Retained messages are \b NOT supported by the AWS IoT Service at the time of this SDK release. - * - */ -typedef struct { - char struct_id[4]; ///< The eyecatcher for this structure. must be MQTW - char *pTopicName; ///< The LWT topic to which the LWT message will be published - uint16_t topicNameLen; ///< The length of the LWT topic, 16 bit unsinged integer - char *pMessage; ///< Message to be delivered as LWT - uint16_t msgLen; ///< The length of the Message, 16 bit unsinged integer - bool isRetained; ///< NOT supported. The retained flag for the LWT message (see MQTTAsync_message.retained) - QoS qos; ///< QoS of LWT message -} IoT_MQTT_Will_Options; -/** Default initializer for will */ -extern const IoT_MQTT_Will_Options iotMqttWillOptionsDefault; - -/** Default initializer for will */ -#define IoT_MQTT_Will_Options_Initializer { {'M', 'Q', 'T', 'W'}, NULL, 0, NULL, 0, false, QOS0 } - -/** - * @brief MQTT Connection Parameters - * - * Defining a type for MQTT connection parameters. Passed into client when establishing a connection. - * - */ -typedef struct { - char struct_id[4]; ///< The eyecatcher for this structure. must be MQTC - MQTT_Ver_t MQTTVersion; ///< Desired MQTT version used during connection - char *pClientID; ///< Pointer to a string defining the MQTT client ID (this needs to be unique \b per \b device across your AWS account) - uint16_t clientIDLen; ///< Client Id Length. 16 bit unsigned integer - uint16_t keepAliveIntervalInSec; ///< MQTT keep alive interval in seconds. Defines inactivity time allowed before determining the connection has been lost. - bool isCleanSession; ///< MQTT clean session. True = this session is to be treated as clean. Previous server state is cleared and no stated is retained from this connection. - bool isWillMsgPresent; ///< Is there a LWT associated with this connection? - IoT_MQTT_Will_Options will; ///< MQTT LWT parameters. - char *pUsername; ///< Not used in the AWS IoT Service, will need to be cstring if used - uint16_t usernameLen; ///< Username Length. 16 bit unsigned integer - char *pPassword; ///< Not used in the AWS IoT Service, will need to be cstring if used - uint16_t passwordLen; ///< Password Length. 16 bit unsigned integer -} IoT_Client_Connect_Params; -/** Default initializer for connect */ -extern const IoT_Client_Connect_Params iotClientConnectParamsDefault; - -/** Default initializer for connect */ -#define IoT_Client_Connect_Params_initializer { {'M', 'Q', 'T', 'C'}, MQTT_3_1_1, NULL, 0, 60, true, false, \ - IoT_MQTT_Will_Options_Initializer, NULL, 0, NULL, 0 } - -/** - * @brief Disconnect Callback Handler Type - * - * Defining a TYPE for definition of disconnect callback function pointers. - * - */ -typedef void (*iot_disconnect_handler)(AWS_IoT_Client *, void *); - -/** - * @brief MQTT Initialization Parameters - * - * Defining a type for MQTT initialization parameters. - * Passed into client when to initialize the client - * - */ -typedef struct { - bool enableAutoReconnect; ///< Set to true to enable auto reconnect - char *pHostURL; ///< Pointer to a string defining the endpoint for the MQTT service - uint16_t port; ///< MQTT service listening port - char *pRootCALocation; ///< Pointer to a string defining the Root CA file (full file, not path) - char *pDeviceCertLocation; ///< Pointer to a string defining the device identity certificate file (full file, not path) - char *pDevicePrivateKeyLocation; ///< Pointer to a string defining the device private key file (full file, not path) - uint32_t mqttPacketTimeout_ms; ///< Timeout for reading a complete MQTT packet. In milliseconds - uint32_t mqttCommandTimeout_ms; ///< Timeout for MQTT blocking calls. In milliseconds - uint32_t tlsHandshakeTimeout_ms; ///< TLS handshake timeout. In milliseconds - bool isSSLHostnameVerify; ///< Client should perform server certificate hostname validation - iot_disconnect_handler disconnectHandler; ///< Callback to be invoked upon connection loss - void *disconnectHandlerData; ///< Data to pass as argument when disconnect handler is called -#ifdef _ENABLE_THREAD_SUPPORT_ - bool isBlockOnThreadLockEnabled; ///< Timeout for Thread blocking calls. Set to 0 to block until lock is obtained. In milliseconds -#endif -} IoT_Client_Init_Params; -/** Default initializer for client */ -extern const IoT_Client_Init_Params iotClientInitParamsDefault; - -/** Default initializer for client */ -#ifdef _ENABLE_THREAD_SUPPORT_ -#define IoT_Client_Init_Params_initializer { true, NULL, 0, NULL, NULL, NULL, 2000, 20000, 5000, true, NULL, NULL, false } -#else -#define IoT_Client_Init_Params_initializer { true, NULL, 0, NULL, NULL, NULL, 2000, 20000, 5000, true, NULL, NULL } -#endif - -/** - * @brief MQTT Client State Type - * - * Defining a type for MQTT Client State - * - */ -typedef enum _ClientState { - CLIENT_STATE_INVALID = 0, - CLIENT_STATE_INITIALIZED = 1, - CLIENT_STATE_CONNECTING = 2, - CLIENT_STATE_CONNECTED_IDLE = 3, - CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS = 4, - CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS = 5, - CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS = 6, - CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS = 7, - CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS = 8, - CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN = 9, - CLIENT_STATE_DISCONNECTING = 10, - CLIENT_STATE_DISCONNECTED_ERROR = 11, - CLIENT_STATE_DISCONNECTED_MANUALLY = 12, - CLIENT_STATE_PENDING_RECONNECT = 13 -} ClientState; - -/** - * @brief Application Callback Handler Type - * - * Defining a TYPE for definition of application callback function pointers. - * Used to send incoming data to the application - * - */ -typedef void (*pApplicationHandler_t)(AWS_IoT_Client *pClient, char *pTopicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *pParams, void *pClientData); - -/** - * @brief MQTT Message Handler - * - * Defining a type for MQTT Message Handlers. - * Used to pass incoming data back to the application - * - */ -typedef struct _MessageHandlers { - const char *topicName; ///< Topic name of subscription - uint16_t topicNameLen; ///< Length of topic name - char resubscribed; ///< Whether this handler was successfully resubscribed in the reconnect workflow - QoS qos; ///< QoS of subscription - pApplicationHandler_t pApplicationHandler; ///< Application function to invoke - void *pApplicationHandlerData; ///< Context to pass to application handler -} MessageHandlers; /* Message handlers are indexed by subscription topic */ - -/** - * @brief MQTT Client Status - * - * Defining a type for MQTT Client Status - * Contains information about the state of the MQTT Client - * - */ -typedef struct _ClientStatus { - ClientState clientState; ///< The current state of the client's state machine - bool isPingOutstanding; ///< Whether this client is waiting for a ping response - bool isAutoReconnectEnabled; ///< Whether auto-reconnect is enabled for this client -} ClientStatus; - -/** - * @brief MQTT Client Data - * - * Defining a type for MQTT Client Data - * Contains data used by the MQTT Client - * - */ -typedef struct _ClientData { - uint16_t nextPacketId; ///< Packet ID to use for the next generated packet - - /* Packet timeout is unused. See https://github.com/aws/aws-iot-device-sdk-embedded-C/pull/1475 */ - uint32_t packetTimeoutMs; ///< Timeout for reading incoming packets from the network - uint32_t commandTimeoutMs; ///< Timeout for processing outgoing MQTT packets - uint16_t keepAliveInterval; ///< Maximum interval between control packets - uint32_t currentReconnectWaitInterval; ///< Current backoff period for reconnect - uint32_t counterNetworkDisconnected; ///< How many times this client detected a disconnection - - /* The below values are initialized with the - * lengths of the TX/RX buffers and never modified - * afterwards */ - size_t writeBufSize; ///< Size of this client's outgoing data buffer - size_t readBufSize; ///< Size of this client's incoming data buffer - size_t readBufIndex; ///< Current offset into the incoming data buffer - unsigned char writeBuf[AWS_IOT_MQTT_TX_BUF_LEN]; ///< Buffer for outgoing data - unsigned char readBuf[AWS_IOT_MQTT_RX_BUF_LEN]; ///< Buffer for incoming data - -#ifdef _ENABLE_THREAD_SUPPORT_ - bool isBlockOnThreadLockEnabled; ///< Whether to use nonblocking or blocking mutex APIs - IoT_Mutex_t state_change_mutex; ///< Mutex protecting the client's state machine - IoT_Mutex_t tls_read_mutex; ///< Mutex protecting incoming data - IoT_Mutex_t tls_write_mutex; ///< Mutex protecting outgoing data -#endif - - IoT_Client_Connect_Params options; ///< Options passed when the client was initialized - - MessageHandlers messageHandlers[AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS]; ///< Callbacks for incoming messages - iot_disconnect_handler disconnectHandler; ///< Callback when a disconnection is detected - void *disconnectHandlerData; ///< Context for disconnect handler -} ClientData; - -/** - * @brief MQTT Client - * - * Defining a type for MQTT Client - * - */ -struct _Client { - Timer pingReqTimer; ///< Timer to keep track of when to send next PINGREQ - Timer pingRespTimer; ///< Timer to ensure that PINGRESP is received timely - Timer reconnectDelayTimer; ///< Timer for backoff on reconnect - - ClientStatus clientStatus; ///< Client state information - ClientData clientData; ///< Client context - Network networkStack; ///< Table of network function pointers -}; - -/** - * @functionpage{aws_iot_mqtt_get_next_packet_id,mqtt,get_next_packet_id} - * @functionpage{aws_iot_mqtt_set_connect_params,mqtt,set_connect_params} - * @functionpage{aws_iot_mqtt_is_client_connected,mqtt,is_client_connected} - * @functionpage{aws_iot_mqtt_get_client_state,mqtt,get_client_state} - * @functionpage{aws_iot_is_autoreconnect_enabled,mqtt,is_autoreconnect_enabled} - * @functionpage{aws_iot_mqtt_set_disconnect_handler,mqtt,set_disconnect_handler} - * @functionpage{aws_iot_mqtt_autoreconnect_set_status,mqtt,autoreconnect_set_status} - * @functionpage{aws_iot_mqtt_get_network_disconnected_count,mqtt,get_network_disconnected_count} - * @functionpage{aws_iot_mqtt_reset_network_disconnected_count,mqtt,reset_network_disconnected_count} - */ - -/** - * @brief Retrieve and increment the next packet identifier for an MQTT client context. - * - * This function generates a two-byte packet identifier for an outgoing MQTT packet and - * modifies the internal state of the MQTT client context so that the next call generates - * a different packet identifier. Per the MQTT specification, MQTT packet identifiers are - * nonzero, two-byte integers that identify certain MQTT packets. MQTT packet identifiers - * must be unique at any given time: no two concurrent packets may use the same identifier, - * but packet identifiers from previously processed packets may be reused. - * - * @param[in] pClient MQTT client context - * - * @return A two-byte MQTT packet identifier that will be unique for the given MQTT client - * context. - * - * @warning This function is not thread safe. Do not call it concurrently from different - * threads. - */ -/* @[declare_mqtt_get_next_packet_id] */ -uint16_t aws_iot_mqtt_get_next_packet_id(AWS_IoT_Client *pClient); -/* @[declare_mqtt_get_next_packet_id] */ - -/** - * @brief Reset the connection parameters of an initialized MQTT client context. - * - * This function replaces the current connection parameters of an MQTT client - * context with a new set of parameters. Its primary use is to modify the connection - * parameters for the next reconnect attempt if the existing parameters are no longer - * valid. Therefore, it should be called just before a reconnect attempt, i.e. just - * before @ref mqtt_function_attempt_reconnect or @ref mqtt_function_yield. - * - * The new connection parameters take effect at the next connection attempt. - * - * @param[in] pClient MQTT client context - * @param[in] pNewConnectParams The new connection parameters - * - * @return Returns NULL_VALUE_ERROR if provided a bad parameter; otherwise, always - * returns SUCCESS. - * - * @warning Do not call this function if a connection attempt is in progress. Connection - * attempts happen in the context of @ref mqtt_function_connect, @ref mqtt_function_attempt_reconnect, - * or @ref mqtt_function_yield. - */ -/* @[declare_mqtt_set_connect_params] */ -IoT_Error_t aws_iot_mqtt_set_connect_params(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pNewConnectParams); -/* @[declare_mqtt_set_connect_params] */ - -/** - * @brief Determine if the MQTT client context currently connected to a server. - * - * This function checks the internal state of the MQTT client context to determine - * if it is currently connected to the server. - * - * @param[in] pClient MQTT client context - * - * @return true if connected; false otherwise. - * - * @warning Application code should not rely on this function's return value. - * The returned value only represents the internal state of the client and - * does not check the network connection status. - */ -/* @[declare_mqtt_is_client_connected] */ -bool aws_iot_mqtt_is_client_connected(AWS_IoT_Client *pClient); -/* @[declare_mqtt_is_client_connected] */ - -/** - * @brief Get the current state of the MQTT client context. - * - * @param[in] pClient MQTT client context - * - * @return The state of the MQTT client context at the time of the function call. - * - * @note The client's state is internal and generally not useful to application code. - * Applications should not make assumptions about the status of the client based on - * its state. - */ -/* @[declare_mqtt_get_client_state] */ -ClientState aws_iot_mqtt_get_client_state(AWS_IoT_Client *pClient); -/* @[declare_mqtt_get_client_state] */ - -/** - * @brief Determine if auto-reconnect is enabled for an MQTT client context. - * - * @param[in] pClient MQTT client context - * - * @return true if auto-reconnect is enabled; false otherwise. - */ -/* @[declare_mqtt_is_autoreconnect_enabled] */ -bool aws_iot_is_autoreconnect_enabled(AWS_IoT_Client *pClient); -/* @[declare_mqtt_is_autoreconnect_enabled] */ - -/** - * @brief Reset the disconnect handler of an initialized MQTT client context. - * - * This function replaces the current disconnect handler of an MQTT client - * context with a new disconnect handler. - * - * The new disconnect handler will be invoked when the next disconnect is detected. - * - * @param[in] pClient MQTT client context - * @param[in] pDisconnectHandler New disconnect handler - * @param[in] pDisconnectHandlerData Context to be passed to new disconnect handler - * - * @return Returns NULL_VALUE_ERROR if provided a bad parameter; otherwise, always - * returns SUCCESS. - * - * @warning Do not call this function if @ref mqtt_function_yield is in progress. - */ -/* @[declare_mqtt_set_disconnect_handler] */ -IoT_Error_t aws_iot_mqtt_set_disconnect_handler(AWS_IoT_Client *pClient, iot_disconnect_handler pDisconnectHandler, - void *pDisconnectHandlerData); -/* @[declare_mqtt_set_disconnect_handler] */ - -/** - * @brief Enable or disable auto-reconnect for an initialized MQTT client context. - * - * This function replaces the current auto-reconnect setting with the provided setting. - * - * @note This function should only be called after @ref mqtt_function_connect has been - * called for the provided client. - * - * @param[in] pClient MQTT client context - * @param[in] newStatus New setting for auto-reconnect - * - * @return Returns NULL_VALUE_ERROR if provided a bad parameter; otherwise, always - * returns SUCCESS. - * - * @warning Do not call this function if a connection attempt is in progress. Connection - * attempts happen in the context of @ref mqtt_function_connect, @ref mqtt_function_attempt_reconnect, - * or @ref mqtt_function_yield. - */ -/* @[declare_mqtt_autoreconnect_set_status] */ -IoT_Error_t aws_iot_mqtt_autoreconnect_set_status(AWS_IoT_Client *pClient, bool newStatus); -/* @[declare_mqtt_autoreconnect_set_status] */ - -/** - * @brief Get the current number of disconnects detected by an MQTT client context. - * - * @param[in] pClient MQTT client context - * - * @return The number of disconnects detected since the client was created - * (or since the last call to @ref mqtt_function_reset_network_disconnected_count). - * - * @warning Do not call this function if @ref mqtt_function_yield is in progress. - */ -/* @[declare_mqtt_get_network_disconnected_count] */ -uint32_t aws_iot_mqtt_get_network_disconnected_count(AWS_IoT_Client *pClient); -/* @[declare_mqtt_get_network_disconnected_count] */ - -/** - * @brief Reset the number of disconnects detected by an MQTT client context to zero. - * - * @param[in] pClient MQTT client context - * - * @warning Do not call this function if @ref mqtt_function_yield is in progress. - */ -/* @[declare_mqtt_reset_network_disconnected_count] */ -void aws_iot_mqtt_reset_network_disconnected_count(AWS_IoT_Client *pClient); -/* @[declare_mqtt_reset_network_disconnected_count] */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_common_internal.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_common_internal.h deleted file mode 100644 index ee8ca023e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_common_internal.h +++ /dev/null @@ -1,134 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_common_internal.h - * @brief Internal MQTT functions not exposed to application - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H -#define AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include "aws_iot_log.h" -#include "aws_iot_mqtt_client_interface.h" - -/** Types of MQTT messages */ -typedef enum msgTypes { - UNKNOWN = -1, - CONNECT = 1, - CONNACK = 2, - PUBLISH = 3, - PUBACK = 4, - PUBREC = 5, - PUBREL = 6, - PUBCOMP = 7, - SUBSCRIBE = 8, - SUBACK = 9, - UNSUBSCRIBE = 10, - UNSUBACK = 11, - PINGREQ = 12, - PINGRESP = 13, - DISCONNECT = 14 -} MessageTypes; - -/* Macros for parsing header fields from incoming MQTT frame. */ -#define MQTT_HEADER_FIELD_TYPE(_byte) ((_byte >> 4) & 0x0F) /**< Message type */ -#define MQTT_HEADER_FIELD_DUP(_byte) ((_byte & (1 << 3)) >> 3) /**< DUP flag */ -#define MQTT_HEADER_FIELD_QOS(_byte) ((_byte & (3 << 1)) >> 1) /**< QoS */ -#define MQTT_HEADER_FIELD_RETAIN(_byte) ((_byte & (1 << 0)) >> 0) /**< Retain flag */ - -/** - * Bitfields for the MQTT header byte. - */ -typedef union { - unsigned char byte; /**< the whole byte */ -} MQTTHeader; - -IoT_Error_t aws_iot_mqtt_internal_init_header(MQTTHeader *pHeader, MessageTypes message_type, - QoS qos, uint8_t dup, uint8_t retained); - -IoT_Error_t aws_iot_mqtt_internal_serialize_ack(unsigned char *pTxBuf, size_t txBufLen, - MessageTypes msgType, uint8_t dup, uint16_t packetId, - uint32_t *pSerializedLen); -IoT_Error_t aws_iot_mqtt_internal_deserialize_ack(unsigned char *, unsigned char *, - uint16_t *, unsigned char *, size_t); - -uint32_t aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(uint32_t rem_len); - -size_t aws_iot_mqtt_internal_write_len_to_buffer(unsigned char *buf, uint32_t length); -IoT_Error_t aws_iot_mqtt_internal_decode_remaining_length_from_buffer(unsigned char *buf, uint32_t *decodedLen, - uint32_t *readBytesLen); - -uint16_t aws_iot_mqtt_internal_read_uint16_t(unsigned char **pptr); -void aws_iot_mqtt_internal_write_uint_16(unsigned char **pptr, uint16_t anInt); - -unsigned char aws_iot_mqtt_internal_read_char(unsigned char **pptr); -void aws_iot_mqtt_internal_write_char(unsigned char **pptr, unsigned char c); -void aws_iot_mqtt_internal_write_utf8_string(unsigned char **pptr, const char *string, uint16_t stringLen); - -IoT_Error_t aws_iot_mqtt_internal_flushBuffers( AWS_IoT_Client *pClient ); -IoT_Error_t aws_iot_mqtt_internal_send_packet(AWS_IoT_Client *pClient, size_t length, Timer *pTimer); -IoT_Error_t aws_iot_mqtt_internal_cycle_read(AWS_IoT_Client *pClient, Timer *pTimer, uint8_t *pPacketType); -IoT_Error_t aws_iot_mqtt_internal_wait_for_read(AWS_IoT_Client *pClient, uint8_t packetType, Timer *pTimer); -IoT_Error_t aws_iot_mqtt_internal_serialize_zero(unsigned char *pTxBuf, size_t txBufLen, - MessageTypes packetType, size_t *pSerializedLength); -IoT_Error_t aws_iot_mqtt_internal_deserialize_publish(uint8_t *dup, QoS *qos, - uint8_t *retained, uint16_t *pPacketId, - char **pTopicName, uint16_t *topicNameLen, - unsigned char **payload, size_t *payloadLen, - unsigned char *pRxBuf, size_t rxBufLen); - -IoT_Error_t aws_iot_mqtt_set_client_state(AWS_IoT_Client *pClient, ClientState expectedCurrentState, - ClientState newState); - -#ifdef _ENABLE_THREAD_SUPPORT_ - -IoT_Error_t aws_iot_mqtt_client_lock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex); - -IoT_Error_t aws_iot_mqtt_client_unlock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_SDK_SRC_IOT_COMMON_INTERNAL_H */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_interface.h deleted file mode 100644 index 65e101951..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_mqtt_client_interface.h +++ /dev/null @@ -1,305 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_interface.h - * @brief Interface definition for MQTT client. - */ - -#ifndef AWS_IOT_SDK_SRC_IOT_MQTT_INTERFACE_H -#define AWS_IOT_SDK_SRC_IOT_MQTT_INTERFACE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Library Header files */ -#include "stdio.h" -#include "stdbool.h" -#include "stdint.h" -#include "stddef.h" - -/* AWS Specific header files */ -#include "aws_iot_error.h" -#include "aws_iot_config.h" -#include "aws_iot_mqtt_client.h" - -/* Platform specific implementation header files */ -#include "network_interface.h" -#include "timer_interface.h" - -/** - * @functionspage{mqtt,MQTT library} - * - * API functions - * - @functionname{mqtt_function_init} - * - @functionname{mqtt_function_free} - * - @functionname{mqtt_function_connect} - * - @functionname{mqtt_function_publish} - * - @functionname{mqtt_function_subscribe} - * - @functionname{mqtt_function_resubscribe} - * - @functionname{mqtt_function_unsubscribe} - * - @functionname{mqtt_function_disconnect} - * - @functionname{mqtt_function_yield} - * - @functionname{mqtt_function_attempt_reconnect} - * - @functionname{mqtt_function_get_next_packet_id} - * - @functionname{mqtt_function_set_connect_params} - * - @functionname{mqtt_function_is_client_connected} - * - @functionname{mqtt_function_get_client_state} - * - @functionname{mqtt_function_is_autoreconnect_enabled} - * - @functionname{mqtt_function_set_disconnect_handler} - * - @functionname{mqtt_function_autoreconnect_set_status} - * - @functionname{mqtt_function_get_network_disconnected_count} - * - @functionname{mqtt_function_reset_network_disconnected_count} - */ - -/** - * @functionpage{aws_iot_mqtt_init,mqtt,init} - * @functionpage{aws_iot_mqtt_free,mqtt,free} - * @functionpage{aws_iot_mqtt_connect,mqtt,connect} - * @functionpage{aws_iot_mqtt_publish,mqtt,publish} - * @functionpage{aws_iot_mqtt_subscribe,mqtt,subscribe} - * @functionpage{aws_iot_mqtt_resubscribe,mqtt,resubscribe} - * @functionpage{aws_iot_mqtt_unsubscribe,mqtt,unsubscribe} - * @functionpage{aws_iot_mqtt_disconnect,mqtt,disconnect} - * @functionpage{aws_iot_mqtt_yield,mqtt,yield} - * @functionpage{aws_iot_mqtt_attempt_reconnect,mqtt,attempt_reconnect} - */ - -/** - * @brief Initialize a new MQTT client context. - * - * This function should be called before any other MQTT function to initialize - * a new MQTT client context. Once the client context is no longer needed, - * @ref mqtt_function_free should be called. - * - * @param[in] pClient MQTT client context to initialize - * @param[in] pInitParams The MQTT connection parameters - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_init] */ -IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *pInitParams); -/* @[declare_mqtt_init] */ - -/** - * @brief Clean up an MQTT client context that is no longer needed. - * - * This function will free up resources used by an MQTT client context. It should - * only be called when that context is no longer needed. - * - * @param[in] pClient MQTT client context that was previously initialized by - * @ref mqtt_function_init - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_free] */ -IoT_Error_t aws_iot_mqtt_free( AWS_IoT_Client *pClient ); -/* @[declare_mqtt_free] */ - -/** - * @brief Establish a connection with an MQTT server. - * - * This function should be called once and after @ref mqtt_function_init. It sends - * the MQTT CONNECT packet to the server, which establishes an MQTT session. Once - * the session is no longer needed, it can be closed with @ref mqtt_function_disconnect. - * - * @param[in] pClient MQTT client context - * @param[in] pConnectParams MQTT connection parameters - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_connect] */ -IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams); -/* @[declare_mqtt_connect] */ - -/** - * @brief Publish an MQTT message to a topic. - * - * This function sends an MQTT message to the server. The server will then - * forward this message to any clients with subscriptions to topic filters - * that match the message's topic. - * - * For a QoS 0 message, this function returns after the message is successfully - * passed to the TLS layer. For a QoS 1 message, this function returns after the - * receipt of the PUBACK for the transmitted message. - * - * @param pClient MQTT client context - * @param pTopicName Topic name to publish to - * @param topicNameLen Length of the topic name - * @param pParams Publish message parameters - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_publish] */ -IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *pParams); -/* @[declare_mqtt_publish] */ - -/** - * @brief Subscribe to an MQTT topic. - * - * This function sends an MQTT subscribe packet to the server. It registers - * a subscription that will cause the provided callback function to be invoked - * when the server sends a message on a matching topic to the client. - * - * @note Incoming messages are handled by @ref mqtt_function_yield. Therefore, - * @ref mqtt_function_yield must always be called regularly if any subscriptions - * are active. - * - * @param[in] pClient MQTT client context - * @param[in] pTopicName Topic for subscription - * @param[in] topicNameLen Length of topic - * @param[in] qos Quality of service for subscription - * @param[in] pApplicationHandler Callback function for incoming messages that arrive - * on this subscription - * @param[in] pApplicationHandlerData Data passed to the callback - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - * - * @attention The `pTopicName` parameter is not copied. It must remain valid for the duration - * of the subscription (until @ref mqtt_function_unsubscribe) is called. - */ -/* @[declare_mqtt_subscribe] */ -IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData); -/* @[declare_mqtt_subscribe] */ - -/** - * @brief Resubscribe to topic filter subscriptions in a previous MQTT session. - * - * This function restores subscriptions that were previously present in an - * MQTT session. Its primary use is to restore subscriptions after a session - * is manually disconnected and reopened. - * - * @note This function does not need to be called after @ref mqtt_function_attempt_reconnect - * or if auto-reconnect is enabled. - * - * @param[in] pClient MQTT client context - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_resubscribe] */ -IoT_Error_t aws_iot_mqtt_resubscribe(AWS_IoT_Client *pClient); -/* @[declare_mqtt_resubscribe] */ - -/** - * @brief Unsubscribe from an MQTT topic filter. - * - * This function removes an MQTT subscription previously set by @ref mqtt_function_subscribe. - * It sends an MQTT UNSUBSCRIBE packet to the server and removes the topic's message - * handler stored by the client. - * - * @param[in] pClient MQTT client context - * @param[in] pTopicFilter Topic filter of the subscription to remove - * @param[in] topicFilterLen Length of topic filter to remove - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_unsubscribe] */ -IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen); -/* @[declare_mqtt_unsubscribe] */ - -/** - * @brief Disconnect an MQTT session. - * - * This function sends the MQTT DISCONNECT packet, which closes the MQTT session - * between the client and server. After this function returns, the MQTT client - * context should be either freed with @ref mqtt_function_free or reopened with - * @ref mqtt_function_connect. - * - * @param[in] pClient MQTT client context - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - */ -/* @[declare_mqtt_disconnect] */ -IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient); -/* @[declare_mqtt_disconnect] */ - -/** - * @brief Provide time for the MQTT client to process events. - * - * This function processes the following events: - * - Incoming messages from the server
- * Whenever a client publishes a message on a topic, the server sends that - * message to all the clients whose subscriptions match the message's - * topic. The messages sent by the server are received by this function, - * which in turn calls the corresponding message handler. This function - * must be called at a rate faster than the incoming messages, as it is the - * only way the client receives processing time to manage incoming messages. - * - MQTT keep-alive (sending ping requests and processing ping responses)
- * The MQTT keep-alive mechanism involves sending pings to the server if the connection - * is idle. Therefore, in the absence of any other messages, this function must be called - * at least once every keep-alive period to send the ping request. - * - @ref mqtt_autoreconnect (if enabled)
- * If the client detects a disconnect, the reconnection will be performed in this function. - * - * @param[in] pClient MQTT client context - * @param[in] timeout_ms Amount of time to yield. This function will return to the caller - * after AT LEAST this amount of thime has passed. - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - * @return If this call results a negative value, assume the MQTT connection has dropped. - * @ref mqtt_function_is_client_connected can be called to confirm. If a reconnection is - * needed, @ref mqtt_function_attempt_reconnect should be called. - */ -/* @[declare_mqtt_yield] */ -IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms); -/* @[declare_mqtt_yield] */ - -/** - * @brief Attempt to reconnect with the MQTT server. - * - * This function makes a single reconnect attempt with the server. If the - * reconnection is successful, subscriptions from the client's previous - * session are restored as well. - * - * If this function fails, the client's state is set to `CLIENT_STATE_PENDING_RECONNECT`. - * - * @param[in] pClient MQTT client context - * - * @return `IoT_Error_t`: See `aws_iot_error.h` - * - * @note Generally, it is not necessary to call this function if @ref mqtt_autoreconnect - * is enabled. This function may still be called to initiate a reconnect attempt when - * auto-reconnect has exhausted all attempts. - */ -/* @[declare_mqtt_attempt_reconnect] */ -IoT_Error_t aws_iot_mqtt_attempt_reconnect(AWS_IoT_Client *pClient); -/* @[declare_mqtt_attempt_reconnect] */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_actions.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_actions.h deleted file mode 100644 index 279c0cbec..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_actions.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_interface.h" - -IoT_Error_t aws_iot_shadow_internal_action(const char *pThingName, ShadowActions_t action, - const char *pJsonDocumentToBeSent, size_t jsonSize, fpActionCallback_t callback, - void *pCallbackContext, uint32_t timeout_seconds, bool isSticky); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_ACTIONS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_interface.h deleted file mode 100644 index 241edba70..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_interface.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ -#ifndef AWS_IOT_SDK_SRC_IOT_SHADOW_H_ -#define AWS_IOT_SDK_SRC_IOT_SHADOW_H_ - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @file aws_iot_shadow_interface.h - * @brief Interface for thing shadow - * - * These are the functions and structs to manage/interact the Thing Shadow(in the cloud). - * This SDK will let you interact with your own thing shadow or any other shadow using its Thing Name. - * There are totally 3 actions a device can perform on the shadow - Get, Update and Delete. - * - * Currently the device should use MQTT/S underneath. In the future this will also support other protocols. As it supports MQTT, the shadow needs to connect and disconnect. - * It will also work on the pub/sub model. On performing any action, the acknowledgment will be received in either accepted or rejected. For Example: - * If we want to perform a GET on the thing shadow the following messages will be sent and received: - * 1. A MQTT Publish on the topic - $aws/things/{thingName}/shadow/get - * 2. Subscribe to MQTT topics - $aws/things/{thingName}/shadow/get/accepted and $aws/things/{thingName}/shadow/get/rejected. - * If the request was successful we will receive the things json document in the accepted topic. - * - * - */ -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_json_data.h" - -/*! - * @brief Shadow Initialization parameters - * - * As the Shadow SDK uses MQTT underneath, it could be connected and disconnected on events to save some battery. - * @note Always use the \c ShadowIniTParametersDefault to initialize this struct - * - * - * - */ -typedef struct { - char *pHost; ///< This will be unique to a customer and can be retrieved from the console - uint16_t port; ///< Network port for TCP/IP socket - char *pRootCA; ///< Location with the Filename of the Root CA - char *pClientCRT; ///< Location of Device certs signed by AWS IoT service - char *pClientKey; ///< Location of Device private key - bool enableAutoReconnect; ///< Set to true to enable auto reconnect - iot_disconnect_handler disconnectHandler; ///< Callback to be invoked upon connection loss. -} ShadowInitParameters_t; - -/*! - * @brief Shadow Connect parameters - * - * As the Shadow SDK uses MQTT underneath, it could be connected and disconnected on events to save some battery. - * @note Always use the \c ShadowConnectParametersDefault to initialize this struct - * - *d - * - */ -typedef struct { - char *pMyThingName; ///< Every device has a Thing Shadow and this is the placeholder for name - char *pMqttClientId; ///< Currently the Shadow uses MQTT to connect and it is important to ensure we have unique client id - uint16_t mqttClientIdLen; ///< Currently the Shadow uses MQTT to connect and it is important to ensure we have unique client id - pApplicationHandler_t deleteActionHandler; ///< Callback to be invoked when Thing shadow for this device is deleted -} ShadowConnectParameters_t; - -/*! - * @brief This is set to defaults from the configuration file - * The certs are set to NULL because they need the path to the file. shadow_sample.c file demonstrates on how to get the relative path - * - * \relates ShadowInitParameters_t - */ -extern const ShadowInitParameters_t ShadowInitParametersDefault; - -/*! - * @brief This is set to defaults from the configuration file - * The length of the client id is initialized as 0. This is due to C language limitations of using constant literals - * only for creating const variables. The client id will be assigned using the value from aws_iot_config.h but the - * length needs to be assigned in code. shadow_sample.c file demonstrates this. - * - * \relates ShadowConnectParameters_t - */ -extern const ShadowConnectParameters_t ShadowConnectParametersDefault; - -/** -* @brief Clean shadow client from all dynamic memory allocate -* -* This function will free up memory that was dynamically allocated for the client. -* -* @param pClient MQTT Client that was previously created by calling aws_iot_shadow_init -* @return An IoT Error Type defining successful/failed freeing -*/ -IoT_Error_t aws_iot_shadow_free(AWS_IoT_Client *pClient); - -/** - * @brief Initialize the Thing Shadow before use - * - * This function takes care of initializing the internal book-keeping data structures and initializing the IoT client. - * - * @param pClient A new MQTT Client to be used as the protocol layer. Will be initialized with pParams. - * @return An IoT Error Type defining successful/failed Initialization - */ -IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, ShadowInitParameters_t *pParams); - -/** - * @brief Connect to the AWS IoT Thing Shadow service over MQTT - * - * This function does the TLSv1.2 handshake and establishes the MQTT connection - * - * @param pClient MQTT Client used as the protocol layer - * @param pParams Shadow Conenction parameters like TLS cert location - * @return An IoT Error Type defining successful/failed Connection - */ -IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, ShadowConnectParameters_t *pParams); - -/** - * @brief Yield function to let the background tasks of MQTT and Shadow - * - * This function could be use in a separate thread waiting for the incoming messages, ensuring the connection is kept alive with the AWS Service. - * It also ensures the expired requests of Shadow actions are cleared and Timeout callback is executed. - * @note All callbacks ever used in the SDK will be executed in the context of this function. - * - * @param pClient MQTT Client used as the protocol layer - * @param timeout in milliseconds, This is the maximum time the yield function will wait for a message and/or read the messages from the TLS buffer - * @return An IoT Error Type defining successful/failed Yield - */ -IoT_Error_t aws_iot_shadow_yield(AWS_IoT_Client *pClient, uint32_t timeout); - -/** - * @brief Disconnect from the AWS IoT Thing Shadow service over MQTT - * - * This will close the underlying TCP connection, MQTT connection will also be closed - * - * @param pClient MQTT Client used as the protocol layer - * @return An IoT Error Type defining successful/failed disconnect status - */ -IoT_Error_t aws_iot_shadow_disconnect(AWS_IoT_Client *pClient); - -/** - * @brief Thing Shadow Acknowledgment enum - * - * This enum type is use in the callback for the action response - * - */ -typedef enum { - SHADOW_ACK_TIMEOUT, SHADOW_ACK_REJECTED, SHADOW_ACK_ACCEPTED -} Shadow_Ack_Status_t; - -/** - * @brief Thing Shadow Action type enum - * - * This enum type is use in the callback for the action response - * - */ -typedef enum { - SHADOW_GET, SHADOW_UPDATE, SHADOW_DELETE -} ShadowActions_t; - - -/** - * @brief Function Pointer typedef used as the callback for every action - * - * This function will be called from the context of \c aws_iot_shadow_yield() context - * - * @param pThingName Thing Name of the response received - * @param action The response of the action - * @param status Informs if the action was Accepted/Rejected or Timed out - * @param pReceivedJsonDocument Received JSON document - * @param pContextData the void* data passed in during the action call(update, get or delete) - * - */ -typedef void (*fpActionCallback_t)(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData); - -/** - * @brief This function is the one used to perform an Update action to a Thing Name's Shadow. - * - * update is one of the most frequently used functionality by a device. In most cases the device may be just reporting few params to update the thing shadow in the cloud - * Update Action if no callback or if the JSON document does not have a client token then will just publish the update and not track it. - * - * @note The update has to subscribe to two topics update/accepted and update/rejected. This function waits 2 seconds to ensure the subscriptions are registered before publishing the update message. - * The following steps are performed on using this function: - * 1. Subscribe to Shadow topics - $aws/things/{thingName}/shadow/update/accepted and $aws/things/{thingName}/shadow/update/rejected - * 2. wait for 2 seconds for the subscription to take effect - * 3. Publish on the update topic - $aws/things/{thingName}/shadow/update - * 4. In the \c aws_iot_shadow_yield() function the response will be handled. In case of timeout or if the response is received, the subscription to shadow response topics are un-subscribed from. - * On the contrary if the persistent subscription is set to true then the un-subscribe will not be done. The topics will always be listened to. - * - * @param pClient MQTT Client used as the protocol layer - * @param pThingName Thing Name of the shadow that needs to be Updated - * @param pJsonString The update action expects a JSON document to send. The JSON String should be a null terminated string. This JSON document should adhere to the AWS IoT Thing Shadow specification. To help in the process of creating this document- SDK provides apis in \c aws_iot_shadow_json_data.h - * @param callback This is the callback that will be used to inform the caller of the response from the AWS IoT Shadow service.Callback could be set to NULL if response is not important - * @param pContextData This is an extra parameter that could be passed along with the callback. It should be set to NULL if not used - * @param timeout_seconds It is the time the SDK will wait for the response on either accepted/rejected before declaring timeout on the action - * @param isPersistentSubscribe As mentioned above, every time if a device updates the same shadow then this should be set to true to avoid repeated subscription and unsubscription. If the Thing Name is one off update then this should be set to false - * @return An IoT Error Type defining successful/failed update action - */ -IoT_Error_t aws_iot_shadow_update(AWS_IoT_Client *pClient, const char *pThingName, char *pJsonString, - fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds, - bool isPersistentSubscribe); - -/** - * @brief This function is the one used to perform an Get action to a Thing Name's Shadow. - * - * One use of this function is usually to get the config of a device at boot up. - * It is similar to the Update function internally except it does not take a JSON document as the input. The entire JSON document will be sent over the accepted topic - * - * @param pClient MQTT Client used as the protocol layer - * @param pThingName Thing Name of the JSON document that is needed - * @param callback This is the callback that will be used to inform the caller of the response from the AWS IoT Shadow service.Callback could be set to NULL if response is not important - * @param pContextData This is an extra parameter that could be passed along with the callback. It should be set to NULL if not used - * @param timeout_seconds It is the time the SDK will wait for the response on either accepted/rejected before declaring timeout on the action - * @param isPersistentSubscribe As mentioned above, every time if a device gets the same Sahdow (JSON document) then this should be set to true to avoid repeated subscription and un-subscription. If the Thing Name is one off get then this should be set to false - * @return An IoT Error Type defining successful/failed get action - */ -IoT_Error_t aws_iot_shadow_get(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe); - -/** - * @brief This function is the one used to perform an Delete action to a Thing Name's Shadow. - * - * This is not a very common use case for device. It is generally the responsibility of the accompanying app to do the delete. - * It is similar to the Update function internally except it does not take a JSON document as the input. The Thing Shadow referred by the ThingName will be deleted. - * - * @param pClient MQTT Client used as the protocol layer - * @param pThingName Thing Name of the Shadow that should be deleted - * @param callback This is the callback that will be used to inform the caller of the response from the AWS IoT Shadow service.Callback could be set to NULL if response is not important - * @param pContextData This is an extra parameter that could be passed along with the callback. It should be set to NULL if not used - * @param timeout_seconds It is the time the SDK will wait for the response on either accepted/rejected before declaring timeout on the action - * @param isPersistentSubscribe As mentioned above, every time if a device deletes the same Shadow (JSON document) then this should be set to true to avoid repeated subscription and un-subscription. If the Thing Name is one off delete then this should be set to false - * @return An IoT Error Type defining successful/failed delete action - */ -IoT_Error_t aws_iot_shadow_delete(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscriptions); - -/** - * @brief This function is used to listen on the delta topic of #AWS_IOT_MY_THING_NAME mentioned in the aws_iot_config.h file. - * - * Any time a delta is published the Json document will be delivered to the pStruct->cb. If you don't want the parsing done by the SDK then use the jsonStruct_t key set to "state". A good example of this is displayed in the sample_apps/shadow_console_echo.c - * - * @param pClient MQTT Client used as the protocol layer - * @param pStruct The struct used to parse JSON value - * @return An IoT Error Type defining successful/failed delta registering - */ -IoT_Error_t aws_iot_shadow_register_delta(AWS_IoT_Client *pClient, jsonStruct_t *pStruct); - -/** - * @brief Reset the last received version number to zero. - * This will be useful if the Thing Shadow is deleted and would like to to reset the local version - * @return no return values - * - */ -void aws_iot_shadow_reset_last_received_version(void); - -/** - * @brief Version of a document is received with every accepted/rejected and the SDK keeps track of the last received version of the JSON document of #AWS_IOT_MY_THING_NAME shadow - * - * One exception to this version tracking is that, the SDK will ignore the version from update/accepted topic. Rest of the responses will be scanned to update the version number. - * Accepting version change for update/accepted may cause version conflicts for delta message if the update message is received before the delta. - * - * @return version number of the last received response - * - */ -uint32_t aws_iot_shadow_get_last_received_version(void); - -/** - * @brief Enable the ignoring of delta messages with old version number - * - * As we use MQTT underneath, there could be more than 1 of the same message if we use QoS 0. To avoid getting called for the same message, this functionality should be enabled. All the old message will be ignored - */ -void aws_iot_shadow_enable_discard_old_delta_msgs(void); - -/** - * @brief Disable the ignoring of delta messages with old version number - */ -void aws_iot_shadow_disable_discard_old_delta_msgs(void); - -/** - * @brief This function is used to enable or disable autoreconnect - * - * Any time a disconnect happens the underlying MQTT client attempts to reconnect if this is set to true - * - * @param pClient MQTT Client used as the protocol layer - * @param newStatus The new status to set the autoreconnect option to - * - * @return An IoT Error Type defining successful/failed operation - */ -IoT_Error_t aws_iot_shadow_set_autoreconnect_status(AWS_IoT_Client *pClient, bool newStatus); - -#ifdef __cplusplus -} -#endif - -#endif //AWS_IOT_SDK_SRC_IOT_SHADOW_H_ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json.h deleted file mode 100644 index 748ff0884..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ -#ifndef AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_ -#define AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#include "aws_iot_error.h" -#include "aws_iot_shadow_json_data.h" - -bool isJsonValidAndParse(const char *pJsonDocument, size_t jsonSize, void *pJsonHandler, int32_t *pTokenCount); - -bool isJsonKeyMatchingAndUpdateValue(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, - jsonStruct_t *pDataStruct, uint32_t *pDataLength, int32_t *pDataPosition); - -IoT_Error_t aws_iot_shadow_internal_get_request_json(char *pBuffer, size_t bufferSize); - -IoT_Error_t aws_iot_shadow_internal_delete_request_json(char *pBuffer, size_t bufferSize); - -void resetClientTokenSequenceNum(void); - - -bool isReceivedJsonValid(const char *pJsonDocument, size_t jsonSize); - -bool extractClientToken(const char *pJsonDocument, size_t jsonSize, char *pExtractedClientToken, size_t clientTokenSize); - -bool extractVersionNumber(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, uint32_t *pVersionNumber); - -#ifdef __cplusplus -} -#endif - -#endif // AWS_IOT_SDK_SRC_IOT_SHADOW_JSON_H_ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json_data.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json_data.h deleted file mode 100644 index e2c61ac51..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_json_data.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file aws_iot_shadow_json_data.h - * @brief This file is the interface for all the Shadow related JSON functions. - */ - -#include - -/** - * @brief This is a static JSON object that could be used in code - * - */ -typedef struct jsonStruct jsonStruct_t; - -/** - * @brief Every JSON name value can have a callback. The callback should follow this signature - */ -typedef void (*jsonStructCallback_t)(const char *pJsonValueBuffer, uint32_t valueLength, jsonStruct_t *pJsonStruct_t); - -/** - * @brief All the JSON object types enum - * - * JSON number types need to be split into proper integer / floating point data types and sizes on embedded platforms. - */ -typedef enum { - SHADOW_JSON_INT32, - SHADOW_JSON_INT16, - SHADOW_JSON_INT8, - SHADOW_JSON_UINT32, - SHADOW_JSON_UINT16, - SHADOW_JSON_UINT8, - SHADOW_JSON_FLOAT, - SHADOW_JSON_DOUBLE, - SHADOW_JSON_BOOL, - SHADOW_JSON_STRING, - SHADOW_JSON_OBJECT -} JsonPrimitiveType; - -/** - * @brief This is the struct form of a JSON Key value pair - */ -struct jsonStruct { - const char *pKey; ///< JSON key - void *pData; ///< pointer to the data (JSON value) - size_t dataLength; ///< Length (in bytes) of pData - JsonPrimitiveType type; ///< type of JSON - jsonStructCallback_t cb; ///< callback to be executed on receiving the Key value pair -}; - -/** - * @brief Initialize the JSON document with Shadow expected name/value - * - * This Function will fill the JSON Buffer with a null terminated string. Internally it uses snprintf - * This function should always be used First, followed by iot_shadow_add_reported and/or iot_shadow_add_desired. - * Always finish the call sequence with iot_finalize_json_document - * - * @note Ensure the size of the Buffer is enough to hold the entire JSON Document. - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_shadow_init_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument); - -/** - * @brief Add the reported section of the JSON document of jsonStruct_t - * - * This is a variadic function and please be careful with the usage. count is the number of jsonStruct_t types that you would like to add in the reported section - * This function will add "reported":{} - * - * @note Ensure the size of the Buffer is enough to hold the reported section + the init section. Always use the same JSON document buffer used in the iot_shadow_init_json_document function. This function will accommodate the size of previous null terminated string, so pass teh max size of the buffer - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @param count total number of arguments(jsonStruct_t object) passed in the arguments - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_shadow_add_reported(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...); - -/** - * @brief Add the desired section of the JSON document of jsonStruct_t - * - * This is a variadic function and please be careful with the usage. count is the number of jsonStruct_t types that you would like to add in the reported section - * This function will add "desired":{} - * - * @note Ensure the size of the Buffer is enough to hold the reported section + the init section. Always use the same JSON document buffer used in the iot_shadow_init_json_document function. This function will accommodate the size of previous null terminated string, so pass the max size of the buffer - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @param count total number of arguments(jsonStruct_t object) passed in the arguments - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_shadow_add_desired(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...); - -/** - * @brief Finalize the JSON document with Shadow expected client Token. - * - * This function will automatically increment the client token every time this function is called. - * - * @note Ensure the size of the Buffer is enough to hold the entire JSON Document. If the finalized section is not invoked then the JSON doucment will not be valid - * - * - * @param pJsonDocument The JSON Document filled in this char buffer - * @param maxSizeOfJsonDocument maximum size of the pJsonDocument that can be used to fill the JSON document - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ -IoT_Error_t aws_iot_finalize_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument); - -/** - * @brief Fill the given buffer with client token for tracking the Repsonse. - * - * This function will add the AWS_IOT_MQTT_CLIENT_ID with a sequence number. Every time this function is used the sequence number gets incremented - * - * - * @param pBufferToBeUpdatedWithClientToken buffer to be updated with the client token string - * @param maxSizeOfJsonDocument maximum size of the pBufferToBeUpdatedWithClientToken that can be used - * @return An IoT Error Type defining if the buffer was null or the entire string was not filled up - */ - -IoT_Error_t aws_iot_fill_with_client_token(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_JSON_DATA_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_key.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_key.h deleted file mode 100644 index 075a726da..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_key.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_KEY_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_KEY_H_ - -#define SHADOW_CLIENT_TOKEN_STRING "clientToken" -#define SHADOW_VERSION_STRING "version" - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_KEY_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_records.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_records.h deleted file mode 100644 index fc2de0322..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_shadow_records.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifndef SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_ -#define SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "aws_iot_shadow_interface.h" -#include "aws_iot_config.h" - - -extern uint32_t shadowJsonVersionNum; -extern bool shadowDiscardOldDeltaFlag; - -extern char myThingName[MAX_SIZE_OF_THING_NAME]; -extern uint16_t myThingNameLen; -extern char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES]; -extern uint16_t mqttClientIDLen; - -void initializeRecords(AWS_IoT_Client *pClient); -bool isSubscriptionPresent(const char *pThingName, ShadowActions_t action); -IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t action, bool isSticky); -void incrementSubscriptionCnt(const char *pThingName, ShadowActions_t action, bool isSticky); - -IoT_Error_t publishToShadowAction(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent); -void addToAckWaitList(uint8_t indexAckWaitList, const char *pThingName, ShadowActions_t action, - const char *pExtractedClientToken, fpActionCallback_t callback, void *pCallbackContext, - uint32_t timeout_seconds); -bool getNextFreeIndexOfAckWaitList(uint8_t *pIndex); -void HandleExpiredResponseCallbacks(void); -void initDeltaTokens(void); -IoT_Error_t registerJsonTokenOnDelta(jsonStruct_t *pStruct); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_SHADOW_AWS_IOT_SHADOW_RECORDS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_version.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_version.h deleted file mode 100644 index 873949b07..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/aws_iot_version.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_version.h - * @brief Constants defining the release version of the SDK. - * - * This file contains constants defining the release version of the SDK. - * This file is modified by AWS upon release of the SDK and should not be - * modified by the consumer of the SDK. The provided samples show example - * usage of these constants. - * - * Versioning of the SDK follows the MAJOR.MINOR.PATCH Semantic Versioning guidelines. - * @see http://semver.org/ - */ -#ifndef SRC_UTILS_AWS_IOT_VERSION_H_ -#define SRC_UTILS_AWS_IOT_VERSION_H_ - -/** - * @brief MAJOR version, incremented when incompatible API changes are made. - */ -#define VERSION_MAJOR 3 -/** - * @brief MINOR version when functionality is added in a backwards-compatible manner. - */ -#define VERSION_MINOR 0 -/** - * @brief PATCH version when backwards-compatible bug fixes are made. - */ -#define VERSION_PATCH 1 -/** - * @brief TAG is an (optional) tag appended to the version if a more descriptive verion is needed. - */ -#define VERSION_TAG "" - -#endif /* SRC_UTILS_AWS_IOT_VERSION_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/network_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/network_interface.h deleted file mode 100644 index cf2834106..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/network_interface.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file network_interface.h - * @brief Network interface definition for MQTT client. - * - * Defines an interface to the TLS layer to be used by the MQTT client. - * Starting point for porting the SDK to the networking layer of a new platform. - */ - -#ifndef __NETWORK_INTERFACE_H_ -#define __NETWORK_INTERFACE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include "timer_interface.h" -#include "network_platform.h" - -/** - * @brief Network Type - * - * Defines a type for the network struct. See structure definition below. - */ -typedef struct Network Network; - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct { - char *pRootCALocation; ///< Pointer to string containing the filename (including path) of the root CA file. - char *pDeviceCertLocation; ///< Pointer to string containing the filename (including path) of the device certificate. - char *pDevicePrivateKeyLocation; ///< Pointer to string containing the filename (including path) of the device private key file. - char *pDestinationURL; ///< Pointer to string containing the endpoint of the MQTT service. - uint16_t DestinationPort; ///< Integer defining the connection port of the MQTT service. - uint32_t timeout_ms; ///< Unsigned integer defining the TLS handshake timeout value in milliseconds. - bool ServerVerificationFlag; ///< Boolean. True = perform server certificate hostname validation. False = skip validation \b NOT recommended. -} TLSConnectParams; - -/** - * @brief Network Structure - * - * Structure for defining a network connection. - */ -struct Network { - IoT_Error_t (*connect)(Network *, TLSConnectParams *); - - IoT_Error_t (*read)(Network *, unsigned char *, size_t, Timer *, size_t *); ///< Function pointer pointing to the network function to read from the network - IoT_Error_t (*write)(Network *, unsigned char *, size_t, Timer *, size_t *); ///< Function pointer pointing to the network function to write to the network - IoT_Error_t (*disconnect)(Network *); ///< Function pointer pointing to the network function to disconnect from the network - IoT_Error_t (*isConnected)(Network *); ///< Function pointer pointing to the network function to check if TLS is connected - IoT_Error_t (*destroy)(Network *); ///< Function pointer pointing to the network function to destroy the network object - - TLSConnectParams tlsConnectParams; ///< TLSConnect params structure containing the common connection parameters - TLSDataParams tlsDataParams; ///< TLSData params structure containing the connection data parameters that are specific to the library being used -}; - -/** - * @brief Initialize the TLS implementation - * - * Perform any initialization required by the TLS layer. - * Connects the interface to implementation by setting up - * the network layer function pointers to platform implementations. - * - * @param pNetwork - Pointer to a Network struct defining the network interface. - * @param pRootCALocation - Path of the location of the Root CA - * @param pDeviceCertLocation - Path to the location of the Device Cert - * @param pDevicyPrivateKeyLocation - Path to the location of the device private key file - * @param pDestinationURL - The target endpoint to connect to - * @param DestinationPort - The port on the target to connect to - * @param timeout_ms - The value to use for timeout of operation - * @param ServerVerificationFlag - used to decide whether server verification is needed or not - * - * @return IoT_Error_t - successful initialization or TLS error - */ -IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t DestinationPort, uint32_t timeout_ms, bool ServerVerificationFlag); - -/** - * @brief Create a TLS socket and open the connection - * - * Creates an open socket connection including TLS handshake. - * - * @param pNetwork - Pointer to a Network struct defining the network interface. - * @param TLSParams - TLSConnectParams defines the properties of the TLS connection. - * @return IoT_Error_t - successful connection or TLS error - */ -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *TLSParams); - -/** - * @brief Write bytes to the network socket - * - * @param Network - Pointer to a Network struct defining the network interface. - * @param unsigned char pointer - buffer to write to socket - * @param integer - number of bytes to write - * @param Timer * - operation timer - * @return integer - number of bytes written or TLS error - * @return IoT_Error_t - successful write or TLS error code - */ -IoT_Error_t iot_tls_write(Network *, unsigned char *, size_t, Timer *, size_t *); - -/** - * @brief Read bytes from the network socket - * - * @param Network - Pointer to a Network struct defining the network interface. - * @param unsigned char pointer - pointer to buffer where read bytes should be copied - * @param size_t - number of bytes to read - * @param Timer * - operation timer - * @param size_t - pointer to store number of bytes read - * @return IoT_Error_t - successful read or TLS error code - */ -IoT_Error_t iot_tls_read(Network *, unsigned char *, size_t, Timer *, size_t *); - -/** - * @brief Disconnect from network socket - * - * @param Network - Pointer to a Network struct defining the network interface. - * @return IoT_Error_t - successful read or TLS error code - */ -IoT_Error_t iot_tls_disconnect(Network *pNetwork); - -/** - * @brief Perform any tear-down or cleanup of TLS layer - * - * Called to cleanup any resources required for the TLS layer. - * - * @param Network - Pointer to a Network struct defining the network interface - * @return IoT_Error_t - successful cleanup or TLS error code - */ -IoT_Error_t iot_tls_destroy(Network *pNetwork); - -/** - * @brief Check if TLS layer is still connected - * - * Called to check if the TLS layer is still connected or not. - * - * @param Network - Pointer to a Network struct defining the network interface - * @return IoT_Error_t - TLS error code indicating status of network physical layer connection - */ -IoT_Error_t iot_tls_is_connected(Network *pNetwork); - -#ifdef __cplusplus -} -#endif - -#endif //__NETWORK_INTERFACE_H_ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/threads_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/threads_interface.h deleted file mode 100644 index b4bc3705d..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/threads_interface.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file threads_interface.h - * @brief Thread interface definition for MQTT client. - * - * Defines an interface that can be used by system components for multithreaded situations. - * Starting point for porting the SDK to the threading hardware layer of a new platform. - */ - -#include "aws_iot_config.h" - -#ifdef _ENABLE_THREAD_SUPPORT_ -#ifndef __THREADS_INTERFACE_H_ -#define __THREADS_INTERFACE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The platform specific timer header that defines the Timer struct - */ -#include "threads_platform.h" - -#include - -/** - * @brief Mutex Type - * - * Forward declaration of a mutex struct. The definition of this struct is - * platform dependent. When porting to a new platform add this definition - * in "threads_platform.h". - * - */ -typedef struct _IoT_Mutex_t IoT_Mutex_t; - -/** - * @brief Initialize the provided mutex - * - * Call this function to initialize the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be initialized - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *); - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change - * This is a blocking call. - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *); - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change. - * This is not a blocking call. - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *); - -/** - * @brief Unlock the provided mutex - * - * Call this function to unlock the mutex before performing a state change - * - * @param IoT_Mutex_t - pointer to the mutex to be unlocked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *); - -/** - * @brief Destroy the provided mutex - * - * Call this function to destroy the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be destroyed - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *); - -#ifdef __cplusplus -} -#endif - -#endif /*__THREADS_INTERFACE_H_*/ -#endif /*_ENABLE_THREAD_SUPPORT_*/ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/timer_interface.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/timer_interface.h deleted file mode 100644 index 0bef0fc94..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/include/timer_interface.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Allan Stockdill-Mander - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file timer_interface.h - * @brief Timer interface definition for MQTT client. - * - * Defines an interface to timers that can be used by other system - * components. MQTT client requires timers to handle timeouts and - * MQTT keep alive. - * Starting point for porting the SDK to the timer hardware layer of a new platform. - */ - -#ifndef __TIMER_INTERFACE_H_ -#define __TIMER_INTERFACE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The platform specific timer header that defines the Timer struct - */ -#include "timer_platform.h" - -#include -#include - -/** - * @brief Timer Type - * - * Forward declaration of a timer struct. The definition of this struct is - * platform dependent. When porting to a new platform add this definition - * in "timer_.h" and include that file above. - * - */ -typedef struct Timer Timer; - -/** - * @brief Check if a timer is expired - * - * Call this function passing in a timer to check if that timer has expired. - * - * @param Timer - pointer to the timer to be checked for expiration - * @return bool - true = timer expired, false = timer not expired - */ -bool has_timer_expired(Timer *); - -/** - * @brief Create a timer (milliseconds) - * - * Sets the timer to expire in a specified number of milliseconds. - * - * @param Timer - pointer to the timer to be set to expire in milliseconds - * @param uint32_t - set the timer to expire in this number of milliseconds - */ -void countdown_ms(Timer *, uint32_t); - -/** - * @brief Create a timer (seconds) - * - * Sets the timer to expire in a specified number of seconds. - * - * @param Timer - pointer to the timer to be set to expire in seconds - * @param uint32_t - set the timer to expire in this number of seconds - */ -void countdown_sec(Timer *, uint32_t); - -/** - * @brief Check the time remaining on a given timer - * - * Checks the input timer and returns the number of milliseconds remaining on the timer. - * - * @param Timer - pointer to the timer to be set to checked - * @return int - milliseconds left on the countdown timer - */ -uint32_t left_ms(Timer *); - -/** - * @brief Initialize a timer - * - * Performs any initialization required to the timer passed in. - * - * @param Timer - pointer to the timer to be initialized - */ -void init_timer(Timer *); - -#ifdef __cplusplus -} -#endif - -#endif //__TIMER_INTERFACE_H_ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer.c deleted file mode 100644 index d7cc204bd..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file timer.c - * @brief Linux implementation of the timer interface. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include - -#include "timer_platform.h" - -bool has_timer_expired(Timer *timer) { - struct timeval now, res; - gettimeofday(&now, NULL); - timersub(&timer->end_time, &now, &res); - return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0); -} - -void countdown_ms(Timer *timer, uint32_t timeout) { - struct timeval now; -#ifdef __cplusplus - struct timeval interval = {timeout / 1000, static_cast((timeout % 1000) * 1000)}; -#else - struct timeval interval = {timeout / 1000, (int)((timeout % 1000) * 1000)}; -#endif - gettimeofday(&now, NULL); - timeradd(&now, &interval, &timer->end_time); -} - -uint32_t left_ms(Timer *timer) { - struct timeval now, res; - uint32_t result_ms = 0; - gettimeofday(&now, NULL); - timersub(&timer->end_time, &now, &res); - if(res.tv_sec >= 0) { - result_ms = (uint32_t) (res.tv_sec * 1000 + res.tv_usec / 1000); - } - return result_ms; -} - -void countdown_sec(Timer *timer, uint32_t timeout) { - struct timeval now; - struct timeval interval = {timeout, 0}; - gettimeofday(&now, NULL); - timeradd(&now, &interval, &timer->end_time); -} - -void init_timer(Timer *timer) { - timer->end_time = (struct timeval) {0, 0}; -} - -void delay(unsigned milliseconds) -{ - useconds_t sleepTime = (useconds_t)(milliseconds * 1000); - - usleep(sleepTime); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer_platform.h deleted file mode 100644 index d381447e0..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/common/timer_platform.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifndef SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_ -#define SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file timer_platform.h - */ -#include -#include -#include "timer_interface.h" - -/** - * definition of the Timer struct. Platform specific - */ -struct Timer { - struct timeval end_time; -}; - -/** - * @brief Delay (sleep) for the specified number of milliseconds. - * - * @param milliseconds The number of milliseconds to sleep. - */ -void delay(unsigned milliseconds); - -#ifdef __cplusplus -} -#endif - -#endif /* SRC_PROTOCOL_MQTT_AWS_IOT_EMBEDDED_CLIENT_WRAPPER_PLATFORM_LINUX_COMMON_TIMER_PLATFORM_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_mbedtls_wrapper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_mbedtls_wrapper.c deleted file mode 100644 index a91d4aa61..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_mbedtls_wrapper.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "aws_iot_config.h" - -#include -#include - -#include "aws_iot_error.h" -#include "aws_iot_log.h" -#include "network_interface.h" -#include "network_platform.h" - - -/* This is the value used for ssl read timeout */ -#ifndef IOT_SSL_READ_TIMEOUT_MS - #define IOT_SSL_READ_TIMEOUT_MS 3 -#endif - -/* When this much time has elapsed after receiving MBEDTLS_ERR_SSL_WANT_READ - * or MBEDTLS_ERR_SSL_WANT_WRITE, then iot_tls_write will return - * NETWORK_SSL_WRITE_TIMEOUT_ERROR. */ -#ifndef IOT_SSL_WRITE_RETRY_TIMEOUT_MS - #define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 -#endif - -/* When this much time has elapsed after receiving MBEDTLS_ERR_SSL_WANT_READ, - * MBEDTLS_ERR_SSL_WANT_WRITE, or MBEDTLS_ERR_SSL_TIMEOUT, then iot_tls_read - * will return NETWORK_SSL_READ_TIMEOUT_ERROR. */ -#ifndef IOT_SSL_READ_RETRY_TIMEOUT_MS - #define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 -#endif - -/* This defines the value of the debug buffer that gets allocated. - * The value can be altered based on memory constraints - */ -#ifdef ENABLE_IOT_DEBUG -#define MBEDTLS_DEBUG_BUFFER_SIZE 2048 -#endif - -/* - * This is a function to do further verification if needed on the cert received - */ - -static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { - char buf[1024]; - ((void) data); - - IOT_DEBUG("\nVerify requested for (Depth %d):\n", depth); - mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); - IOT_DEBUG("%s", buf); - - if((*flags) == 0) { - IOT_DEBUG(" This certificate has no flags\n"); - } else { - IOT_DEBUG(buf, sizeof(buf), " ! ", *flags); - IOT_DEBUG("%s\n", buf); - } - - return 0; -} - -void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - pNetwork->tlsConnectParams.DestinationPort = destinationPort; - pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL; - pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation; - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation; - pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation; - pNetwork->tlsConnectParams.timeout_ms = timeout_ms; - pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag; -} - -IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation, - pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag); - - pNetwork->connect = iot_tls_connect; - pNetwork->read = iot_tls_read; - pNetwork->write = iot_tls_write; - pNetwork->disconnect = iot_tls_disconnect; - pNetwork->isConnected = iot_tls_is_connected; - pNetwork->destroy = iot_tls_destroy; - - pNetwork->tlsDataParams.flags = 0; - - return SUCCESS; -} - -IoT_Error_t iot_tls_is_connected(Network *pNetwork) { - /* Use this to add implementation which can check for physical layer disconnect */ - return NETWORK_PHYSICAL_LAYER_CONNECTED; -} - -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { - int ret = 0; - const char *pers = "aws_iot_tls_wrapper"; - TLSDataParams *tlsDataParams = NULL; - char portBuffer[6]; - char vrfy_buf[512]; - const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; - -#ifdef ENABLE_IOT_DEBUG - unsigned char buf[MBEDTLS_DEBUG_BUFFER_SIZE]; -#endif - - if(NULL == pNetwork) { - return NULL_VALUE_ERROR; - } - - if(NULL != params) { - _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, - params->pDevicePrivateKeyLocation, params->pDestinationURL, - params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag); - } - - tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_init(&(tlsDataParams->server_fd)); - mbedtls_ssl_init(&(tlsDataParams->ssl)); - mbedtls_ssl_config_init(&(tlsDataParams->conf)); - mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); - mbedtls_x509_crt_init(&(tlsDataParams->cacert)); - mbedtls_x509_crt_init(&(tlsDataParams->clicert)); - mbedtls_pk_init(&(tlsDataParams->pkey)); - - IOT_DEBUG("\n . Seeding the random number generator..."); - mbedtls_entropy_init(&(tlsDataParams->entropy)); - if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), - (const unsigned char *) pers, strlen(pers))) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); - return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; - } - - IOT_DEBUG(" . Loading the CA root certificate ..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation); - if(ret < 0) { - IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n", -ret); - return NETWORK_X509_ROOT_CRT_PARSE_ERROR; - } - IOT_DEBUG(" ok (%d skipped)\n", ret); - - IOT_DEBUG(" . Loading the client cert. and key..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), pNetwork->tlsConnectParams.pDeviceCertLocation); - if(ret != 0) { - IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n", -ret); - return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; - } - - ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, ""); - if(ret != 0) { - IOT_ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret); - IOT_DEBUG(" path : %s ", pNetwork->tlsConnectParams.pDevicePrivateKeyLocation); - return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; - } - IOT_DEBUG(" ok\n"); - snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); - IOT_DEBUG(" . Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); - if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, - portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret); - switch(ret) { - case MBEDTLS_ERR_NET_SOCKET_FAILED: - return NETWORK_ERR_NET_SOCKET_FAILED; - case MBEDTLS_ERR_NET_UNKNOWN_HOST: - return NETWORK_ERR_NET_UNKNOWN_HOST; - case MBEDTLS_ERR_NET_CONNECT_FAILED: - default: - return NETWORK_ERR_NET_CONNECT_FAILED; - }; - } - - ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); - if(ret != 0) { - IOT_ERROR(" failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } IOT_DEBUG(" ok\n"); - - IOT_DEBUG(" . Setting up the SSL/TLS structure..."); - if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); - } else { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); - } - mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); - - mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); - if((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey))) != - 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); - - /* Use the AWS IoT ALPN extension for MQTT if port 443 is requested. */ - if(443 == pNetwork->tlsConnectParams.DestinationPort) { - if((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_conf_alpn_protocols returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } - } - - /* Assign the resulting configuration to the SSL context. */ - if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret); - return SSL_CONNECTION_ERROR; - } - if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { - IOT_ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); - return SSL_CONNECTION_ERROR; - } - IOT_DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state); - mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, - mbedtls_net_recv_timeout); - IOT_DEBUG(" ok\n"); - - IOT_DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state); - IOT_DEBUG(" . Performing the SSL/TLS handshake..."); - while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - IOT_ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret); - if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - IOT_ERROR(" Unable to verify the server's certificate. " - "Either it is invalid,\n" - " or you didn't set ca_file or ca_path " - "to an appropriate value.\n" - " Alternatively, you may want to use " - "auth_mode=optional for testing purposes.\n"); - } - return SSL_CONNECTION_ERROR; - } - } - - IOT_DEBUG(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), - mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); - if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { - IOT_DEBUG(" [ Record expansion is %d ]\n", ret); - } else { - IOT_DEBUG(" [ Record expansion is unknown (compression) ]\n"); - } - - IOT_DEBUG(" . Verifying peer X.509 certificate..."); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { - IOT_ERROR(" failed\n"); - mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", tlsDataParams->flags); - IOT_ERROR("%s\n", vrfy_buf); - ret = SSL_CONNECTION_ERROR; - } else { - IOT_DEBUG(" ok\n"); - ret = SUCCESS; - } - } else { - IOT_DEBUG(" Server Verification skipped\n"); - ret = SUCCESS; - } - -#ifdef ENABLE_IOT_DEBUG - if(mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { - IOT_DEBUG(" . Peer certificate information ...\n"); - mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); - IOT_DEBUG("%s\n", buf); - } -#endif - - mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), IOT_SSL_READ_TIMEOUT_MS); - -#ifdef IOT_SSL_SOCKET_NON_BLOCKING - mbedtls_net_set_nonblock(&(tlsDataParams->server_fd)); -#endif - - return (IoT_Error_t) ret; -} - -IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) { - mbedtls_ssl_context *pSsl = &(pNetwork->tlsDataParams.ssl); - size_t txLen = 0U; - int ret = 0; - /* This timer checks for a timeout whenever MBEDTLS_ERR_SSL_WANT_READ - * or MBEDTLS_ERR_SSL_WANT_WRITE are returned by mbedtls_ssl_write. - * Timeout is specified by IOT_SSL_WRITE_RETRY_TIMEOUT_MS. */ - Timer writeTimer; - - /* This variable is unused */ - (void) timer; - - /* The timer must be started in case no bytes are written on the first try */ - init_timer(&writeTimer); - countdown_ms(&writeTimer, IOT_SSL_WRITE_RETRY_TIMEOUT_MS); - - while(len > 0U) { - ret = mbedtls_ssl_write(pSsl, pMsg, len); - - if(ret > 0) { - if((size_t) ret > len) { - IOT_ERROR("More bytes written than requested\n\n"); - return NETWORK_SSL_WRITE_ERROR; - } - - /* Successfully sent data, so reset the timeout */ - init_timer(&writeTimer); - countdown_ms(&writeTimer, IOT_SSL_WRITE_RETRY_TIMEOUT_MS); - - txLen += ret; - pMsg += ret; - len -= ret; - } else if(ret == MBEDTLS_ERR_SSL_WANT_READ || - ret == MBEDTLS_ERR_SSL_WANT_WRITE) { - if(has_timer_expired(&writeTimer)) { - *written_len = txLen; - return NETWORK_SSL_WRITE_TIMEOUT_ERROR; - } - } else { - IOT_ERROR(" failed\n ! mbedtls_ssl_write returned -0x%x\n\n", (unsigned int) -ret); - /* All other negative return values indicate connection needs to be reset. - * Will be caught in ping request so ignored here */ - return NETWORK_SSL_WRITE_ERROR; - } - } - - *written_len = txLen; - return SUCCESS; -} - -IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *read_len) { - mbedtls_ssl_context *pSsl = &(pNetwork->tlsDataParams.ssl); - size_t rxLen = 0U; - int ret; - /* This timer checks for a timeout whenever MBEDTLS_ERR_SSL_WANT_READ, - * MBEDTLS_ERR_SSL_WANT_WRITE, or MBEDTLS_ERR_SSL_TIMEOUT are returned by - * mbedtls_ssl_read. Timeout is specified by IOT_SSL_READ_RETRY_TIMEOUT_MS. */ - Timer readTimer; - - /* This variable is unused */ - (void) timer; - - /* The timer must be started in case no bytes are read on the first try */ - init_timer(&readTimer); - countdown_ms(&readTimer, IOT_SSL_READ_RETRY_TIMEOUT_MS); - - while(len > 0U) { - /* This read will timeout after IOT_SSL_READ_TIMEOUT_MS if there's no data to be read */ - ret = mbedtls_ssl_read(pSsl, pMsg, len); - - if(ret > 0) { - if((size_t) ret > len) { - IOT_ERROR("More bytes read than requested\n\n"); - return NETWORK_SSL_WRITE_ERROR; - } - - /* Successfully received data, so reset the timeout */ - init_timer(&readTimer); - countdown_ms(&readTimer, IOT_SSL_READ_RETRY_TIMEOUT_MS); - - rxLen += ret; - pMsg += ret; - len -= ret; - } else if(ret == MBEDTLS_ERR_SSL_WANT_READ || - ret == MBEDTLS_ERR_SSL_WANT_WRITE || - ret == MBEDTLS_ERR_SSL_TIMEOUT) { - if(has_timer_expired(&readTimer)) { - *read_len = rxLen; - if(rxLen == 0U) { - return NETWORK_SSL_NOTHING_TO_READ; - } else { - return NETWORK_SSL_READ_TIMEOUT_ERROR; - } - } - } else { - IOT_ERROR("Failed\n ! mbedtls_ssl_read returned -0x%x\n\n", (unsigned int) -ret); - return NETWORK_SSL_READ_ERROR; - } - } - - *read_len = rxLen; - return SUCCESS; -} - -IoT_Error_t iot_tls_disconnect(Network *pNetwork) { - mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl); - int ret = 0; - do { - ret = mbedtls_ssl_close_notify(ssl); - } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE); - - /* All other negative return values indicate connection needs to be reset. - * No further action required since this is disconnect call */ - - return SUCCESS; -} - -IoT_Error_t iot_tls_destroy(Network *pNetwork) { - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_free(&(tlsDataParams->server_fd)); - - mbedtls_x509_crt_free(&(tlsDataParams->clicert)); - mbedtls_x509_crt_free(&(tlsDataParams->cacert)); - mbedtls_pk_free(&(tlsDataParams->pkey)); - mbedtls_ssl_free(&(tlsDataParams->ssl)); - mbedtls_ssl_config_free(&(tlsDataParams->conf)); - mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg)); - mbedtls_entropy_free(&(tlsDataParams->entropy)); - - return SUCCESS; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_platform.h deleted file mode 100644 index c2810a1c8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/mbedtls/network_platform.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#include "mbedtls/config.h" - -#include "mbedtls/platform.h" -#include "mbedtls/net.h" -#include "mbedtls/ssl.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/certs.h" -#include "mbedtls/x509.h" -#include "mbedtls/error.h" -#include "mbedtls/debug.h" -#include "mbedtls/timing.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct _TLSDataParams { - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_context ssl; - mbedtls_ssl_config conf; - uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; - mbedtls_pk_context pkey; - mbedtls_net_context server_fd; -}TLSDataParams; - -#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#ifdef __cplusplus -} -#endif - -#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_platform.h deleted file mode 100644 index 8a520c637..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_platform.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#include "threads_interface.h" -#ifdef _ENABLE_THREAD_SUPPORT_ -#ifndef IOTSDKC_THREADS_PLATFORM_H_H -#define IOTSDKC_THREADS_PLATFORM_H_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** - * @brief Mutex Type - * - * definition of the Mutex struct. Platform specific - * - */ -struct _IoT_Mutex_t { - pthread_mutex_t lock; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* IOTSDKC_THREADS_PLATFORM_H_H */ -#endif /* _ENABLE_THREAD_SUPPORT_ */ - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_pthread_wrapper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_pthread_wrapper.c deleted file mode 100644 index 65a310fb0..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/platform/linux/pthread/threads_pthread_wrapper.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#include "threads_platform.h" -#ifdef _ENABLE_THREAD_SUPPORT_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize the provided mutex - * - * Call this function to initialize the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be initialized - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *pMutex) { - if(0 != pthread_mutex_init(&(pMutex->lock), NULL)) { - return MUTEX_INIT_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change - * Blocking, thread will block until lock request fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *pMutex) { -int rc = pthread_mutex_lock(&(pMutex->lock)); - if(0 != rc) { - return MUTEX_LOCK_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Try to lock the provided mutex - * - * Call this function to attempt to lock the mutex before performing a state change - * Non-Blocking, immediately returns with failure if lock attempt fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *pMutex) { -int rc = pthread_mutex_trylock(&(pMutex->lock)); - if(0 != rc) { - return MUTEX_LOCK_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Unlock the provided mutex - * - * Call this function to unlock the mutex before performing a state change - * - * @param IoT_Mutex_t - pointer to the mutex to be unlocked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *pMutex) { - if(0 != pthread_mutex_unlock(&(pMutex->lock))) { - return MUTEX_UNLOCK_ERROR; - } - - return SUCCESS; -} - -/** - * @brief Destroy the provided mutex - * - * Call this function to destroy the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be destroyed - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *pMutex) { - if(0 != pthread_mutex_destroy(&(pMutex->lock))) { - return MUTEX_DESTROY_ERROR; - } - - return SUCCESS; -} - -#ifdef __cplusplus -} -#endif - -#endif /* _ENABLE_THREAD_SUPPORT_ */ - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/README.md deleted file mode 100644 index a0017f08a..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Sample apps for the AWS IoT Device SDK for Embedded C - -All samples are written in C unless otherwise mentioned. The these sample apps are included in the SDK and described below. - * [`subscribe_publish_sample`](#subscribe-publish-sample) - demonstrates how to publish and subscribe to MQTT messages. - * [`subscribe_publish_library_sample`](#subscribe-publish-library-sample) - demonstrates how to create a library that provides support to publish and subscribe to MQTT messages. - - These sample apps are also provided in this SDK. - * [`shadow_sample`](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/master/samples/linux/shadow_sample) - demonstrates how to use a simple device shadow in a connected window example. - * [`shadow_sample_console_echo`](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/master/samples/linux/shadow_sample_console_echo) - demonstrates how to work with the AWS IoT Console interactive guide. - * [`jobs_sample`](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/master/samples/linux/jobs_sample) - demonstrates how to connect to the AWS IoT MQTT platform and perform several operations that use the basic capabilities of the AWS IoT Jobs platform. - -## Overview -This folder contains several samples that demonstrate various SDK functions. The Readme file also includes a walk-through of the subscribe publish sample to explain how the SDK is used. The samples are currently provided with Makefiles for building them on linux. For each sample: - - * Explore the makefile. The makefile for each sample provides a reference on how to set up makefiles for client applications - * Explore the example. It connects to AWS IoT platform using MQTT and demonstrates few actions that can be performed by the SDK - * Download certificate authority CA file from [Symantec](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem) and place in location referenced in the example (certs/) - * Ensure you have [created a thing](https://docs.aws.amazon.com/iot/latest/developerguide/create-thing.html) through your AWS IoT Console with name matching the definition AWS_IOT_MY_THING_NAME in the `aws_iot_config.h` file - * Place device identity cert and private key in locations referenced in the example (certs/) - * Ensure the names of the cert files are the same as in the `aws_iot_config.h` file - * Ensure the certificate has an attached policy which allows the proper permissions for AWS IoT - * Build the example using make (`make`) - * Run sample application (./subscribe_publish_sample or ./shadow_sample). The sample will print status messages to stdout - -## Subscribe Publish Sample -This is a simple pub/sub MQTT example. It connects a single MQTT client to the server and subscribes to a test topic. Then it proceeds to publish messages on this topic and yields after each publish to ensure that the message was received. - - * The sample first creates an instance of the AWS_IoT_Client - * The next step is to initialize the client. The aws_iot_mqtt_init API is called for this purpose. The API takes the client instance and an IoT_Client_Init_Params variable to set the initial values for the client. The Init params include values like host URL, port, certificates, disconnect handler etc. - * If the call to the init API was successful, we can proceed to call connect. The API is called aws_iot_mqtt_connect. It takes the client instance and IoT_Client_Connect_Params variable as arguments. The IoT_Client_Connect_Params is optional after the first call to connect as the client retains the original values that were provided to support reconnect. The Connect params include values like Client Id, MQTT Version etc. - * If the connect API call was successful, we can proceed to subscribe and publish on this connect. The connect API call will return an error code, specific to the type of error that occurred, in case the call fails. - * It is important to remember here that there is no dynamic memory allocation in the SDK. Any values that are passed as a pointer to the APIs should not be freed unless they are not required any further. For example, if the variable that stores the certificate path is freed after the init call is made, the connect call will fail. Similarly, if it is freed after the connect API returns success, any future connect calls (including reconnects) will fail. - * The next step for this sample is to subscribe to the test topic. The API to be called for subscribe is aws_iot_mqtt_subscribe. It takes as arguments, the IoT Client instance, topic name, the length of the topic name, QoS, the subscribe callback handler and an optional pointer to some data to be returned to the subscribe handler - * The next step it to call the publish API to send a message on the test topic. The sample sends two different messages, one QoS0 and one QoS1. The - * The publish API takes the client instance, topic name to publish to, topic name length and a variable of type IoT_Publish_Message_Params. The IoT_Publish_Message_Params contains the payload, length of the payload and QoS. - * If the publish API calls are successful, the sample proceeds to call the yield API. The yield API takes the client instance and a timeout value in milliseconds as arguments. - * The yield API is called to let the SDK process any incoming messages. It also periodically sends out the PING request to prevent disconnect and, if enabled, it also performs auto-reconnect and resubscribe. - * The yield API should be called periodically to process the PING request as well as read any messages in the receive buffer. It should be called once at least every TTL/2 time periods to ensure disconnect does not happen. There can only be one yield in progress at a time. Therefore, in multi-threaded scenarios one thread can be a dedicated yield thread while other threads handle other operations. - * The sample sends out messages equal to the value set in publish count unless infinite publishing flag is set - -For further information on each API please read the API documentation. - -## Subscribe Publish Library Sample -This is also the same code as the Subscribe Publish sample. In this case, the SDK is built as a separate library and then used in the sample program. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/Makefile deleted file mode 100644 index 4f74593b8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = jobs_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/sdk_config -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -CRYPTO_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/aws_iot_config.h deleted file mode 100644 index 7bff6c89e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/aws_iot_config.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_JOBS_IOT_JOB_CONFIG_H_ -#define SRC_JOBS_IOT_JOB_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename - -// MQTT PubSub -#ifndef DISABLE_IOT_JOBS -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#else -#define AWS_IOT_MQTT_RX_BUF_LEN 2048 -#endif -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Shadow and Job common configs -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_SIZE_OF_THING_NAME 30 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER 512 ///< Maximum size of the SHADOW buffer to store the received Shadow message -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Job specific configs -#ifndef DISABLE_IOT_JOBS -#define MAX_SIZE_OF_JOB_ID 64 -#define MAX_JOB_JSON_TOKEN_EXPECTED 120 -#define MAX_SIZE_OF_JOB_REQUEST AWS_IOT_MQTT_TX_BUF_LEN - -#define MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME 40 -#define MAX_JOB_TOPIC_LENGTH_BYTES MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME + MAX_SIZE_OF_THING_NAME + MAX_SIZE_OF_JOB_ID + 2 -#endif - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_JOBS_IOT_JOB_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/jobs_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/jobs_sample.c deleted file mode 100644 index e79f25f7e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/jobs_sample/jobs_sample.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * - * This example takes the parameters from the aws_iot_config.h file and establishes - * a connection to the AWS IoT MQTT Platform. It performs several operations to - * demonstrate the basic capabilities of the AWS IoT Jobs platform. - * - * If all the certs are correct, you should see the list of pending Job Executions - * printed out by the iot_get_pending_callback_handler. If there are any existing pending - * job executions each will be processed one at a time in the iot_next_job_callback_handler. - * After all of the pending jobs have been processed the program will wait for - * notifications for new pending jobs and process them one at a time as they come in. - * - * In the main body you can see how each callback is registered for each corresponding - * Jobs topic. - * - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_json_utils.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_jobs_interface.h" - -/** - * @brief Default cert location - */ -static char certDirectory[PATH_MAX + 1] = "../../../certs"; - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -static char HostAddress[255] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -static uint32_t port = AWS_IOT_MQTT_PORT; - -static jsmn_parser jsonParser; -static jsmntok_t jsonTokenStruct[MAX_JSON_TOKEN_EXPECTED]; -static int32_t tokenCount; - -static void iot_get_pending_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_GET_PENDING_TOPIC callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); - - jsmn_init(&jsonParser); - - tokenCount = jsmn_parse(&jsonParser, params->payload, (int) params->payloadLen, jsonTokenStruct, MAX_JSON_TOKEN_EXPECTED); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d", tokenCount); - return; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object"); - return; - } - - jsmntok_t *jobs; - - jobs = findToken("inProgressJobs", params->payload, jsonTokenStruct); - - if (jobs) { - IOT_INFO("inProgressJobs: %.*s", jobs->end - jobs->start, (char *)params->payload + jobs->start); - } - - jobs = findToken("queuedJobs", params->payload, jsonTokenStruct); - - if (jobs) { - IOT_INFO("queuedJobs: %.*s", jobs->end - jobs->start, (char *)params->payload + jobs->start); - } -} - -static void iot_next_job_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char topicToPublishUpdate[MAX_JOB_TOPIC_LENGTH_BYTES]; - char messageBuffer[200]; - - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_NOTIFY_NEXT_TOPIC / JOB_DESCRIBE_TOPIC($next) callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); - - jsmn_init(&jsonParser); - - tokenCount = jsmn_parse(&jsonParser, params->payload, (int) params->payloadLen, jsonTokenStruct, MAX_JSON_TOKEN_EXPECTED); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d", tokenCount); - return; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object"); - return; - } - - jsmntok_t *tokExecution; - - tokExecution = findToken("execution", params->payload, jsonTokenStruct); - - if (tokExecution) { - IOT_INFO("execution: %.*s", tokExecution->end - tokExecution->start, (char *)params->payload + tokExecution->start); - - jsmntok_t *tok; - - tok = findToken("jobId", params->payload, tokExecution); - - if (tok) { - IoT_Error_t rc; - char jobId[MAX_SIZE_OF_JOB_ID + 1]; - AwsIotJobExecutionUpdateRequest updateRequest; - - rc = parseStringValue(jobId, MAX_SIZE_OF_JOB_ID + 1, params->payload, tok); - if(SUCCESS != rc) { - IOT_ERROR("parseStringValue returned error : %d ", rc); - return; - } - - IOT_INFO("jobId: %s", jobId); - - tok = findToken("jobDocument", params->payload, tokExecution); - - /* - * Do your job processing here. - */ - - if (tok) { - IOT_INFO("jobDocument: %.*s", tok->end - tok->start, (char *)params->payload + tok->start); - /* Alternatively if the job still has more steps the status can be set to JOB_EXECUTION_IN_PROGRESS instead */ - updateRequest.status = JOB_EXECUTION_SUCCEEDED; - updateRequest.statusDetails = "{\"exampleDetail\":\"a value appropriate for your successful job\"}"; - } else { - updateRequest.status = JOB_EXECUTION_FAILED; - updateRequest.statusDetails = "{\"failureDetail\":\"Unable to process job document\"}"; - } - - updateRequest.expectedVersion = 0; - updateRequest.executionNumber = 0; - updateRequest.includeJobExecutionState = false; - updateRequest.includeJobDocument = false; - updateRequest.clientToken = NULL; - - rc = aws_iot_jobs_send_update(pClient, QOS0, AWS_IOT_MY_THING_NAME, jobId, &updateRequest, - topicToPublishUpdate, sizeof(topicToPublishUpdate), messageBuffer, sizeof(messageBuffer)); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_jobs_send_update returned error : %d ", rc); - return; - } - } - } else { - IOT_INFO("execution property not found, nothing to do"); - } -} - -static void iot_update_accepted_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_UPDATE_TOPIC / accepted callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); -} - -static void iot_update_rejected_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_UPDATE_TOPIC / rejected callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); - - /* Do error handling here for when the update was rejected */ -} - -static void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - IOT_WARN("MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - IOT_UNUSED(data); - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - IOT_WARN("Manual Reconnect Successful"); - } else { - IOT_WARN("Manual Reconnect Failed - %d", rc); - } - } -} - -int main(int argc, char **argv) { - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char cPayload[100]; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - mqttInitParams.pRootCALocation = rootCA; - mqttInitParams.pDeviceCertLocation = clientCRT; - mqttInitParams.pDevicePrivateKeyLocation = clientKey; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc); - return rc; - } - - connectParams.keepAliveIntervalInSec = 600; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - IOT_INFO("Connecting..."); - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - return rc; - } - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - char topicToSubscribeGetPending[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeNotifyNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeGetNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeUpdateAccepted[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeUpdateRejected[MAX_JOB_TOPIC_LENGTH_BYTES]; - - char topicToPublishGetPending[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToPublishGetNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, NULL, JOB_GET_PENDING_TOPIC, JOB_WILDCARD_REPLY_TYPE, - iot_get_pending_callback_handler, NULL, topicToSubscribeGetPending, sizeof(topicToSubscribeGetPending)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_GET_PENDING_TOPIC: %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, NULL, JOB_NOTIFY_NEXT_TOPIC, JOB_REQUEST_TYPE, - iot_next_job_callback_handler, NULL, topicToSubscribeNotifyNext, sizeof(topicToSubscribeNotifyNext)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_NOTIFY_NEXT_TOPIC: %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_NEXT, JOB_DESCRIBE_TOPIC, JOB_WILDCARD_REPLY_TYPE, - iot_next_job_callback_handler, NULL, topicToSubscribeGetNext, sizeof(topicToSubscribeGetNext)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_DESCRIBE_TOPIC ($next): %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_WILDCARD, JOB_UPDATE_TOPIC, JOB_ACCEPTED_REPLY_TYPE, - iot_update_accepted_callback_handler, NULL, topicToSubscribeUpdateAccepted, sizeof(topicToSubscribeUpdateAccepted)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_UPDATE_TOPIC/accepted: %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_WILDCARD, JOB_UPDATE_TOPIC, JOB_REJECTED_REPLY_TYPE, - iot_update_rejected_callback_handler, NULL, topicToSubscribeUpdateRejected, sizeof(topicToSubscribeUpdateRejected)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_UPDATE_TOPIC/rejected: %d ", rc); - return rc; - } - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - paramsQOS0.payloadLen = strlen(cPayload); - - rc = aws_iot_jobs_send_query(&client, QOS0, AWS_IOT_MY_THING_NAME, NULL, NULL, topicToPublishGetPending, sizeof(topicToPublishGetPending), NULL, 0, JOB_GET_PENDING_TOPIC); - if(SUCCESS != rc) { - IOT_ERROR("Error calling aws_iot_jobs_send_query: %d ", rc); - return rc; - } - - AwsIotDescribeJobExecutionRequest describeRequest; - describeRequest.executionNumber = 0; - describeRequest.includeJobDocument = true; - describeRequest.clientToken = NULL; - - rc = aws_iot_jobs_describe(&client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_NEXT, &describeRequest, topicToPublishGetNext, sizeof(topicToPublishGetNext), NULL, 0); - - while(SUCCESS == rc) { - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 50000); - } - - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/Makefile deleted file mode 100644 index 9483299fc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/Makefile +++ /dev/null @@ -1,72 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = shadow_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -CRYPTO_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a - - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/aws_iot_config.h deleted file mode 100644 index 81f9e39e8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/aws_iot_config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/shadow_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/shadow_sample.c deleted file mode 100644 index 2a692c70c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample/shadow_sample.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file shadow_sample.c - * @brief A simple connected window example demonstrating the use of Thing Shadow - */ - -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" - -/*! - * The goal of this sample application is to demonstrate the capabilities of shadow. - * This device(say Connected Window) will open the window of a room based on temperature - * It can report to the Shadow the following parameters: - * 1. temperature of the room (double) - * 2. status of the window (open or close) - * It can act on commands from the cloud. In this case it will open or close the window based on the json object "windowOpen" data[open/close] - * - * The two variables from a device's perspective are double temperature and bool windowOpen - * The device needs to act on only on windowOpen variable, so we will create a primitiveJson_t object with callback - The Json Document in the cloud will be - { - "reported": { - "temperature": 0, - "windowOpen": false - }, - "desired": { - "windowOpen": false - } - } - */ - -#define ROOMTEMPERATURE_UPPERLIMIT 32.0f -#define ROOMTEMPERATURE_LOWERLIMIT 25.0f -#define STARTING_ROOMTEMPERATURE ROOMTEMPERATURE_LOWERLIMIT - -#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 - -static char certDirectory[PATH_MAX + 1] = "../../../certs"; -#define HOST_ADDRESS_SIZE 255 -static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST; -static uint32_t port = AWS_IOT_MQTT_PORT; -static uint8_t numPubs = 5; - -static void simulateRoomTemperature(float *pRoomTemperature) { - static float deltaChange; - - if(*pRoomTemperature >= ROOMTEMPERATURE_UPPERLIMIT) { - deltaChange = -0.5f; - } else if(*pRoomTemperature <= ROOMTEMPERATURE_LOWERLIMIT) { - deltaChange = 0.5f; - } - - *pRoomTemperature += deltaChange; -} - -static void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(action); - IOT_UNUSED(pReceivedJsonDocument); - IOT_UNUSED(pContextData); - - if(SHADOW_ACK_TIMEOUT == status) { - IOT_INFO("Update Timeout--"); - } else if(SHADOW_ACK_REJECTED == status) { - IOT_INFO("Update RejectedXX"); - } else if(SHADOW_ACK_ACCEPTED == status) { - IOT_INFO("Update Accepted !!"); - } -} - -static void windowActuate_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - IOT_UNUSED(pJsonString); - IOT_UNUSED(JsonStringDataLen); - - if(pContext != NULL) { - IOT_INFO("Delta - Window state changed to %d", *(bool *) (pContext->pData)); - } -} - -static void parseInputArgsForConnectParams(int argc, char **argv) { - int opt; - - while(-1 != (opt = getopt(argc, argv, "h:p:c:n:"))) { - switch(opt) { - case 'h': - strncpy(HostAddress, optarg, HOST_ADDRESS_SIZE); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("port %s", optarg); - break; - case 'c': - strncpy(certDirectory, optarg, PATH_MAX + 1); - IOT_DEBUG("cert root directory %s", optarg); - break; - case 'n': - numPubs = atoi(optarg); - IOT_DEBUG("num pubs %s", optarg); - break; - case '?': - if(optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if(isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("ERROR in command line argument parsing"); - break; - } - } - -} - -int main(int argc, char **argv) { - IoT_Error_t rc = FAILURE; - - char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER]; - size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]); - float temperature = 0.0; - - bool windowOpen = false; - jsonStruct_t windowActuator; - windowActuator.cb = windowActuate_Callback; - windowActuator.pData = &windowOpen; - windowActuator.dataLength = sizeof(bool); - windowActuator.pKey = "windowOpen"; - windowActuator.type = SHADOW_JSON_BOOL; - - jsonStruct_t temperatureHandler; - temperatureHandler.cb = NULL; - temperatureHandler.pKey = "temperature"; - temperatureHandler.pData = &temperature; - temperatureHandler.dataLength = sizeof(float); - temperatureHandler.type = SHADOW_JSON_FLOAT; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - - parseInputArgsForConnectParams(argc, argv); - - // generate the paths of the credentials - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - // initialize the mqtt client - AWS_IoT_Client mqttClient; - - ShadowInitParameters_t sp = ShadowInitParametersDefault; - sp.pHost = HostAddress; - sp.port = port; - sp.pClientCRT = clientCRT; - sp.pClientKey = clientKey; - sp.pRootCA = rootCA; - sp.enableAutoReconnect = false; - sp.disconnectHandler = NULL; - - IOT_INFO("Shadow Init"); - rc = aws_iot_shadow_init(&mqttClient, &sp); - if(SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - ShadowConnectParameters_t scp = ShadowConnectParametersDefault; - scp.pMyThingName = AWS_IOT_MY_THING_NAME; - scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - - IOT_INFO("Shadow Connect"); - rc = aws_iot_shadow_connect(&mqttClient, &scp); - if(SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - rc = aws_iot_shadow_register_delta(&mqttClient, &windowActuator); - - if(SUCCESS != rc) { - IOT_ERROR("Shadow Register Delta Error"); - } - temperature = STARTING_ROOMTEMPERATURE; - - // loop and publish a change in temperature - while(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) { - rc = aws_iot_shadow_yield(&mqttClient, 200); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - sleep(1); - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - IOT_INFO("\n=======================================================================================\n"); - IOT_INFO("On Device: window state %s", windowOpen ? "true" : "false"); - simulateRoomTemperature(&temperature); - - rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); - if(SUCCESS == rc) { - rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 2, &temperatureHandler, - &windowActuator); - if(SUCCESS == rc) { - rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); - if(SUCCESS == rc) { - IOT_INFO("Update Shadow: %s", JsonDocumentBuffer); - rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, JsonDocumentBuffer, - ShadowUpdateStatusCallback, NULL, 4, true); - } - } - } - IOT_INFO("*****************************************************************************************\n"); - sleep(1); - } - - if(SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop %d", rc); - } - - IOT_INFO("Disconnecting"); - rc = aws_iot_shadow_disconnect(&mqttClient); - - if(SUCCESS != rc) { - IOT_ERROR("Disconnect error %d", rc); - } - - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/Makefile deleted file mode 100644 index ebb173636..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = shadow_console_echo -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -CRYPTO_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a - - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(MQTT_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(MQTT_SRC_FILES) -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) - -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/aws_iot_config.h deleted file mode 100644 index 81f9e39e8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/aws_iot_config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/shadow_console_echo.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/shadow_console_echo.c deleted file mode 100644 index 181c8d77a..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/shadow_sample_console_echo/shadow_console_echo.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" - -/** - * @file shadow_console_echo.c - * @brief Echo received Delta message - * - * This application will echo the message received in delta, as reported. - * for example: - * Received Delta message - * { - * "state": { - * "switch": "on" - * } - * } - * This delta message means the desired switch position has changed to "on" - * - * This application will take this delta message and publish it back as the reported message from the device. - * { - * "state": { - * "reported": { - * "switch": "on" - * } - * } - * } - * - * This update message will remove the delta that was created. If this message was not removed then the AWS IoT Thing Shadow is going to always have a delta and keep sending delta any time an update is applied to the Shadow - * This example will not use any of the json builder/helper functions provided in the aws_iot_shadow_json_data.h. - * @note Ensure the buffer sizes in aws_iot_config.h are big enough to receive the delta message. The delta message will also contain the metadata with the timestamps - */ - -static char certDirectory[PATH_MAX + 1] = "../../../certs"; -#define HOST_ADDRESS_SIZE 255 -static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST; -static uint32_t port = AWS_IOT_MQTT_PORT; -static bool messageArrivedOnDelta = false; - -/* - * @note The delta message is always sent on the "state" key in the json - * @note Any time messages are bigger than AWS_IOT_MQTT_RX_BUF_LEN the underlying MQTT library will ignore it. The maximum size of the message that can be received is limited to the AWS_IOT_MQTT_RX_BUF_LEN - */ -static char stringToEchoDelta[SHADOW_MAX_SIZE_OF_RX_BUFFER]; - - -/** - * @brief This function builds a full Shadow expected JSON document by putting the data in the reported section - * - * @param pJsonDocument Buffer to be filled up with the JSON data - * @param maxSizeOfJsonDocument maximum size of the buffer that could be used to fill - * @param pReceivedDeltaData This is the data that will be embedded in the reported section of the JSON document - * @param lengthDelta Length of the data - */ -static bool buildJSONForReported(char *pJsonDocument, size_t maxSizeOfJsonDocument, const char *pReceivedDeltaData, uint32_t lengthDelta) { - int32_t ret; - - if (NULL == pJsonDocument) { - return false; - } - - char tempClientTokenBuffer[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - - if(aws_iot_fill_with_client_token(tempClientTokenBuffer, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE) != SUCCESS){ - return false; - } - - ret = snprintf(pJsonDocument, maxSizeOfJsonDocument, "{\"state\":{\"reported\":%.*s}, \"clientToken\":\"%s\"}", lengthDelta, pReceivedDeltaData, tempClientTokenBuffer); - - if (ret >= maxSizeOfJsonDocument || ret < 0) { - return false; - } - - return true; -} - -// Helper functions -static void parseInputArgsForConnectParams(int argc, char** argv) { - int opt; - - while (-1 != (opt = getopt(argc, argv, "h:p:c:"))) { - switch (opt) { - case 'h': - strncpy(HostAddress, optarg, HOST_ADDRESS_SIZE); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strncpy(certDirectory, optarg, PATH_MAX + 1); - IOT_DEBUG("cert root directory %s", optarg); - break; - case '?': - if (optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if (isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("ERROR in command line argument parsing"); - break; - } - } - -} - -// Shadow Callback for receiving the delta -static void DeltaCallback(const char *pJsonValueBuffer, uint32_t valueLength, jsonStruct_t *pJsonStruct_t) { - IOT_UNUSED(pJsonStruct_t); - - IOT_DEBUG("Received Delta message %.*s", valueLength, pJsonValueBuffer); - - if (buildJSONForReported(stringToEchoDelta, SHADOW_MAX_SIZE_OF_RX_BUFFER, pJsonValueBuffer, valueLength)) { - messageArrivedOnDelta = true; - } -} - -static void UpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(action); - IOT_UNUSED(pReceivedJsonDocument); - IOT_UNUSED(pContextData); - - if(SHADOW_ACK_TIMEOUT == status) { - IOT_INFO("Update Timeout--"); - } else if(SHADOW_ACK_REJECTED == status) { - IOT_INFO("Update RejectedXX"); - } else if(SHADOW_ACK_ACCEPTED == status) { - IOT_INFO("Update Accepted !!"); - } -} - -int main(int argc, char** argv) { - IoT_Error_t rc = SUCCESS; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - - parseInputArgsForConnectParams(argc, argv); - - // initialize the mqtt client - AWS_IoT_Client mqttClient; - - ShadowInitParameters_t sp = ShadowInitParametersDefault; - sp.pHost = AWS_IOT_MQTT_HOST; - sp.port = AWS_IOT_MQTT_PORT; - sp.pClientCRT = clientCRT; - sp.pClientKey = clientKey; - sp.pRootCA = rootCA; - sp.enableAutoReconnect = false; - sp.disconnectHandler = NULL; - - IOT_INFO("Shadow Init"); - rc = aws_iot_shadow_init(&mqttClient, &sp); - if (SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - ShadowConnectParameters_t scp = ShadowConnectParametersDefault; - scp.pMyThingName = AWS_IOT_MY_THING_NAME; - scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - - IOT_INFO("Shadow Connect"); - rc = aws_iot_shadow_connect(&mqttClient, &scp); - if (SUCCESS != rc) { - IOT_ERROR("Shadow Connection Error"); - return rc; - } - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true); - if(SUCCESS != rc){ - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - jsonStruct_t deltaObject; - deltaObject.pData = stringToEchoDelta; - deltaObject.dataLength = SHADOW_MAX_SIZE_OF_RX_BUFFER; - deltaObject.pKey = "state"; - deltaObject.type = SHADOW_JSON_OBJECT; - deltaObject.cb = DeltaCallback; - - /* - * Register the jsonStruct object - */ - rc = aws_iot_shadow_register_delta(&mqttClient, &deltaObject); - - // Now wait in the loop to receive any message sent from the console - while (NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) { - /* - * Lets check for the incoming messages for 200 ms. - */ - rc = aws_iot_shadow_yield(&mqttClient, 200); - - if (NETWORK_ATTEMPTING_RECONNECT == rc) { - sleep(1); - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - if (messageArrivedOnDelta) { - IOT_INFO("\nSending delta message back %s\n", stringToEchoDelta); - rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, stringToEchoDelta, UpdateStatusCallback, NULL, 2, true); - messageArrivedOnDelta = false; - } - - // sleep for some time in seconds - sleep(1); - } - - if (SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop %d", rc); - } - - IOT_INFO("Disconnecting"); - rc = aws_iot_shadow_disconnect(&mqttClient); - - if (SUCCESS != rc) { - IOT_ERROR("Disconnect error %d", rc); - } - - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/Makefile deleted file mode 100644 index 232260464..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/Makefile +++ /dev/null @@ -1,76 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = subscribe_publish_library_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -CRYPTO_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(APP_NAME).c $(COMPILER_FLAGS) -o $(APP_NAME) -L. -lAwsIotSdk $(LD_FLAG) $(INCLUDE_ALL_DIRS) - -all: libAwsIotSdk.a - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -libAwsIotSdk.a: $(SRC_FILES:.c=.o) - ar rcs $@ $^ - -%.o : %.c - $(CC) -c $< -o $@ $(COMPILER_FLAGS) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - rm -f $(APP_DIR)/libAwsIotSdk.a - $(MBED_TLS_MAKE_CMD) clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/aws_iot_config.h deleted file mode 100644 index 81f9e39e8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/aws_iot_config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample.c deleted file mode 100644 index 0c3e775e9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_library_sample/subscribe_publish_library_sample.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file subscribe_publish_library_sample.c - * @brief simple MQTT publish and subscribe on the same topic using the SDK as a library - * - * This example takes the parameters from the aws_iot_config.h file and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "sdkTest/sub" - * - * If all the certs are correct, you should see the messages received by the application in a loop. - * - * The application takes in the certificate path, host name , port and the number of times the publish should happen. - * - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -#define HOST_ADDRESS_SIZE 255 - -/** - * @brief Default cert location - */ -static char certDirectory[PATH_MAX + 1] = "../../../certs"; - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -static uint32_t port = AWS_IOT_MQTT_PORT; - -/** - * @brief This parameter will avoid infinite loop of publish and exit the program after certain number of publishes - */ -uint32_t publishCount = 0; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("Subscribe callback"); - IOT_INFO("%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, (char *) params->payload); -} - -static void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - IOT_WARN("MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - IOT_UNUSED(data); - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - IOT_WARN("Manual Reconnect Successful"); - } else { - IOT_WARN("Manual Reconnect Failed - %d", rc); - } - } -} - -static void parseInputArgsForConnectParams(int argc, char **argv) { - int opt; - - while(-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) { - switch(opt) { - case 'h': - strncpy(HostAddress, optarg, HOST_ADDRESS_SIZE); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strncpy(certDirectory, optarg, PATH_MAX + 1); - IOT_DEBUG("cert root directory %s", optarg); - break; - case 'x': - publishCount = atoi(optarg); - IOT_DEBUG("publish %s times\n", optarg); - break; - case '?': - if(optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if(isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("Error in command line argument parsing"); - break; - } - } - -} - -int main(int argc, char **argv) { - bool infinitePublishFlag = true; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - parseInputArgsForConnectParams(argc, argv); - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - mqttInitParams.pRootCALocation = rootCA; - mqttInitParams.pDeviceCertLocation = clientCRT; - mqttInitParams.pDevicePrivateKeyLocation = clientKey; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc); - return rc; - } - - connectParams.keepAliveIntervalInSec = 600; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - IOT_INFO("Connecting..."); - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - return rc; - } - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - IOT_INFO("Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing : %d ", rc); - return rc; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - if(publishCount != 0) { - infinitePublishFlag = false; - } - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) - && (publishCount > 0 || infinitePublishFlag)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - IOT_INFO("-->sleep"); - sleep(1); - sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS0); - if(publishCount > 0) { - publishCount--; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - IOT_WARN("QOS1 publish ack not received.\n"); - rc = SUCCESS; - } - if(publishCount > 0) { - publishCount--; - } - } - - if(SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop.\n"); - } else { - IOT_INFO("Publish done\n"); - } - - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/Makefile deleted file mode 100644 index 1a665a3ae..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc - -#remove @ for no make command prints -DEBUG = @ - -APP_DIR = . -APP_INCLUDE_DIRS += -I $(APP_DIR) -APP_NAME = subscribe_publish_sample -APP_SRC_FILES = $(APP_NAME).c - -#IoT client directory -IOT_CLIENT_DIR = ../../.. - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux/mbedtls -PLATFORM_COMMON_DIR = $(IOT_CLIENT_DIR)/platform/linux/common - -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn -IOT_INCLUDE_DIRS += -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_DIR) - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') - -#TLS - mbedtls -MBEDTLS_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(MBEDTLS_DIR)/library -CRYPTO_LIB_DIR = $(MBEDTLS_DIR)/library -TLS_INCLUDE_DIR = -I $(MBEDTLS_DIR)/include -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -# Logging level control -LOG_FLAGS += -DENABLE_IOT_DEBUG -LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR - -COMPILER_FLAGS += $(LOG_FLAGS) -#If the processor is big endian uncomment the compiler flag -#COMPILER_FLAGS += -DREVERSED - -MBED_TLS_MAKE_CMD = $(MAKE) -C $(MBEDTLS_DIR) - -PRE_MAKE_CMD = $(MBED_TLS_MAKE_CMD) -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -o $(APP_NAME) $(LD_FLAG) $(EXTERNAL_LIBS) $(INCLUDE_ALL_DIRS) - -all: - $(PRE_MAKE_CMD) - $(DEBUG)$(MAKE_CMD) - $(POST_MAKE_CMD) - -clean: - rm -f $(APP_DIR)/$(APP_NAME) - $(MBED_TLS_MAKE_CMD) clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/aws_iot_config.h deleted file mode 100644 index 81f9e39e8..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/aws_iot_config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename -// ================================================= - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN+1) ///< Maximum size of the SHADOW buffer to store the received Shadow message, including terminating NULL byte. -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/subscribe_publish_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/subscribe_publish_sample.c deleted file mode 100644 index ce7a28f9c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/samples/linux/subscribe_publish_sample/subscribe_publish_sample.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file subscribe_publish_sample.c - * @brief simple MQTT publish and subscribe on the same topic - * - * This example takes the parameters from the aws_iot_config.h file and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "sdkTest/sub" - * - * If all the certs are correct, you should see the messages received by the application in a loop. - * - * The application takes in the certificate path, host name , port and the number of times the publish should happen. - * - */ -#include -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -#define HOST_ADDRESS_SIZE 255 -/** - * @brief Default cert location - */ -static char certDirectory[PATH_MAX + 1] = "../../../certs"; - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -static uint32_t port = AWS_IOT_MQTT_PORT; - -/** - * @brief This parameter will avoid infinite loop of publish and exit the program after certain number of publishes - */ -static uint32_t publishCount = 0; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("Subscribe callback"); - IOT_INFO("%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, (char *) params->payload); -} - -static void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - IOT_WARN("MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - IOT_UNUSED(data); - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - IOT_WARN("Manual Reconnect Successful"); - } else { - IOT_WARN("Manual Reconnect Failed - %d", rc); - } - } -} - -static void parseInputArgsForConnectParams(int argc, char **argv) { - int opt; - - while(-1 != (opt = getopt(argc, argv, "h:p:c:x:"))) { - switch(opt) { - case 'h': - strncpy(HostAddress, optarg, HOST_ADDRESS_SIZE); - IOT_DEBUG("Host %s", optarg); - break; - case 'p': - port = atoi(optarg); - IOT_DEBUG("arg %s", optarg); - break; - case 'c': - strncpy(certDirectory, optarg, PATH_MAX + 1); - IOT_DEBUG("cert root directory %s", optarg); - break; - case 'x': - publishCount = atoi(optarg); - IOT_DEBUG("publish %s times\n", optarg); - break; - case '?': - if(optopt == 'c') { - IOT_ERROR("Option -%c requires an argument.", optopt); - } else if(isprint(optopt)) { - IOT_WARN("Unknown option `-%c'.", optopt); - } else { - IOT_WARN("Unknown option character `\\x%x'.", optopt); - } - break; - default: - IOT_ERROR("Error in command line argument parsing"); - break; - } - } - -} - -int main(int argc, char **argv) { - bool infinitePublishFlag = true; - - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - parseInputArgsForConnectParams(argc, argv); - - IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - IOT_DEBUG("rootCA %s", rootCA); - IOT_DEBUG("clientCRT %s", clientCRT); - IOT_DEBUG("clientKey %s", clientKey); - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - mqttInitParams.pRootCALocation = rootCA; - mqttInitParams.pDeviceCertLocation = clientCRT; - mqttInitParams.pDevicePrivateKeyLocation = clientKey; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc); - return rc; - } - - connectParams.keepAliveIntervalInSec = 600; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - IOT_INFO("Connecting..."); - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - return rc; - } - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); - return rc; - } - - IOT_INFO("Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing : %d ", rc); - return rc; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - if(publishCount != 0) { - infinitePublishFlag = false; - } - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) - && (publishCount > 0 || infinitePublishFlag)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - IOT_INFO("-->sleep"); - sleep(1); - sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS0); - if(publishCount > 0) { - publishCount--; - } - - if(publishCount == 0 && !infinitePublishFlag) { - break; - } - - sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - IOT_WARN("QOS1 publish ack not received.\n"); - rc = SUCCESS; - } - if(publishCount > 0) { - publishCount--; - } - } - - // Wait for all the messages to be received - aws_iot_mqtt_yield(&client, 100); - - if(SUCCESS != rc) { - IOT_ERROR("An error occurred in the loop.\n"); - } else { - IOT_INFO("Publish done\n"); - } - - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_interface.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_interface.c deleted file mode 100644 index 0452d6786..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_interface.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -#include "aws_iot_jobs_interface.h" -#include "aws_iot_log.h" -#include "aws_iot_jobs_json.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define CHECK_GENERATE_STRING_RESULT(result, bufferSize) \ - if (result < 0) { \ - return FAILURE; \ - } else if ((unsigned) result >= bufferSize) { \ - return LIMIT_EXCEEDED_ERROR; \ - } - - -IoT_Error_t aws_iot_jobs_subscribe_to_job_messages( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - AwsIotJobExecutionTopicType topicType, - AwsIotJobExecutionTopicReplyType replyType, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData, - char *topicBuffer, - uint16_t topicBufferSize) -{ - int requiredSize = aws_iot_jobs_get_api_topic(topicBuffer, topicBufferSize, topicType, replyType, thingName, jobId); - CHECK_GENERATE_STRING_RESULT(requiredSize, topicBufferSize); - - return aws_iot_mqtt_subscribe(pClient, topicBuffer, (uint16_t)strlen(topicBuffer), qos, pApplicationHandler, pApplicationHandlerData); -} - -IoT_Error_t aws_iot_jobs_subscribe_to_all_job_messages( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData, - char *topicBuffer, - uint16_t topicBufferSize) -{ - return aws_iot_jobs_subscribe_to_job_messages(pClient, qos, thingName, NULL, JOB_WILDCARD_TOPIC, JOB_WILDCARD_REPLY_TYPE, - pApplicationHandler, pApplicationHandlerData, topicBuffer, topicBufferSize); -} - -IoT_Error_t aws_iot_jobs_unsubscribe_from_job_messages( - AWS_IoT_Client *pClient, - char *topicBuffer) -{ - return aws_iot_mqtt_unsubscribe(pClient, topicBuffer, (uint16_t)strlen(topicBuffer)); -} - -IoT_Error_t aws_iot_jobs_send_query( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const char *clientToken, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize, - AwsIotJobExecutionTopicType topicType) -{ - if (thingName == NULL || topicBuffer == NULL || (clientToken != NULL && messageBuffer == NULL)) { - return NULL_VALUE_ERROR; - } - - int neededSize = aws_iot_jobs_get_api_topic(topicBuffer, topicBufferSize, topicType, JOB_REQUEST_TYPE, thingName, jobId); - CHECK_GENERATE_STRING_RESULT(neededSize, topicBufferSize); - uint16_t topicSize = (uint16_t) neededSize; - - char emptyBuffer[1]; - size_t messageLength; - if (clientToken == NULL) { - messageLength = 0; - messageBuffer = emptyBuffer; - } else { - int serializeResult = aws_iot_jobs_json_serialize_client_token_only_request(messageBuffer, messageBufferSize, clientToken); - CHECK_GENERATE_STRING_RESULT(serializeResult, messageBufferSize); - messageLength = (size_t)serializeResult; - } - - IoT_Publish_Message_Params publishParams; - publishParams.qos = qos; - publishParams.isRetained = 0; - publishParams.isDup = 0; - publishParams.id = 0; - publishParams.payload = messageBuffer; - publishParams.payloadLen = messageLength; - - return aws_iot_mqtt_publish(pClient, topicBuffer, topicSize, &publishParams); -} - -IoT_Error_t aws_iot_jobs_start_next( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const AwsIotStartNextPendingJobExecutionRequest *startNextRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize) -{ - if (thingName == NULL || topicBuffer == NULL || startNextRequest == NULL) { - return NULL_VALUE_ERROR; - } - - int neededSize = aws_iot_jobs_get_api_topic(topicBuffer, topicBufferSize, JOB_START_NEXT_TOPIC, JOB_REQUEST_TYPE, thingName, NULL); - CHECK_GENERATE_STRING_RESULT(neededSize, topicBufferSize); - uint16_t topicSize = (uint16_t) neededSize; - - int serializeResult = aws_iot_jobs_json_serialize_start_next_job_execution_request(messageBuffer, messageBufferSize, startNextRequest); - CHECK_GENERATE_STRING_RESULT(serializeResult, messageBufferSize); - - IoT_Publish_Message_Params publishParams; - publishParams.qos = qos; - publishParams.isRetained = 0; - publishParams.isDup = 0; - publishParams.id = 0; - publishParams.payload = messageBuffer; - publishParams.payloadLen = (size_t) serializeResult; - - return aws_iot_mqtt_publish(pClient, topicBuffer, topicSize, &publishParams); -} - -IoT_Error_t aws_iot_jobs_describe( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const AwsIotDescribeJobExecutionRequest *describeRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize) -{ - if (thingName == NULL || topicBuffer == NULL || describeRequest == NULL) { - return NULL_VALUE_ERROR; - } - - int neededSize = aws_iot_jobs_get_api_topic(topicBuffer, topicBufferSize, JOB_DESCRIBE_TOPIC, JOB_REQUEST_TYPE, thingName, jobId); - CHECK_GENERATE_STRING_RESULT(neededSize, topicBufferSize); - uint16_t topicSize = (uint16_t) neededSize; - - char emptyBuffer[1]; - size_t messageLength; - if (messageBuffer == NULL) { - messageLength = 0; - messageBuffer = emptyBuffer; - } else { - int serializeResult = aws_iot_jobs_json_serialize_describe_job_execution_request(messageBuffer, messageBufferSize, describeRequest); - CHECK_GENERATE_STRING_RESULT(serializeResult, messageBufferSize); - messageLength = (size_t) serializeResult; - } - - IoT_Publish_Message_Params publishParams; - publishParams.qos = qos; - publishParams.isRetained = 0; - publishParams.isDup = 0; - publishParams.id = 0; - publishParams.payload = messageBuffer; - publishParams.payloadLen = messageLength; - - return aws_iot_mqtt_publish(pClient, topicBuffer, topicSize, &publishParams); -} - -IoT_Error_t aws_iot_jobs_send_update( - AWS_IoT_Client *pClient, QoS qos, - const char *thingName, - const char *jobId, - const AwsIotJobExecutionUpdateRequest *updateRequest, - char *topicBuffer, - uint16_t topicBufferSize, - char *messageBuffer, - size_t messageBufferSize) -{ - if (thingName == NULL || topicBuffer == NULL || jobId == NULL || updateRequest == NULL) { - return NULL_VALUE_ERROR; - } - - int neededSize = aws_iot_jobs_get_api_topic(topicBuffer, topicBufferSize, JOB_UPDATE_TOPIC, JOB_REQUEST_TYPE, thingName, jobId); - CHECK_GENERATE_STRING_RESULT(neededSize, topicBufferSize); - uint16_t topicSize = (uint16_t) neededSize; - - int serializeResult = aws_iot_jobs_json_serialize_update_job_execution_request(messageBuffer, messageBufferSize, updateRequest); - CHECK_GENERATE_STRING_RESULT(serializeResult, messageBufferSize); - - IoT_Publish_Message_Params publishParams; - publishParams.qos = qos; - publishParams.isRetained = 0; - publishParams.isDup = 0; - publishParams.id = 0; - publishParams.payload = messageBuffer; - publishParams.payloadLen = (size_t) serializeResult; - - return aws_iot_mqtt_publish(pClient, topicBuffer, topicSize, &publishParams); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_json.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_json.c deleted file mode 100644 index 2213ddd7b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_json.c +++ /dev/null @@ -1,197 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#define __STDC_FORMAT_MACROS -#include -#include -#include -#include -#include -#include - -#include "jsmn.h" -#include "aws_iot_jobs_json.h" - -struct _SerializeState { - int totalSize; - char *nextPtr; - size_t remaingSize; -}; - -static void _printToBuffer(struct _SerializeState *state, const char *fmt, ...) { - if (state->totalSize == -1) return; - - va_list vl; - va_start(vl, fmt); - int len = vsnprintf(state->nextPtr, state->remaingSize, fmt, vl); - if (len < 0) { - state->totalSize = -1; - } else { - state->totalSize += len; - if (state->nextPtr != NULL) { - if (state->remaingSize > (size_t) len) { - state->remaingSize -= (size_t) len; - state->nextPtr += len; - } else { - state->remaingSize = 0; - state->nextPtr = NULL; - } - } - } - va_end(vl); -} - -static void _printKey(struct _SerializeState *state, bool first, const char *key) { - if (first) { - _printToBuffer(state, "{\"%s\":", key); - } else { - _printToBuffer(state, ",\"%s\":", key); - } -} - -static void _printStringValue(struct _SerializeState *state, const char *value) { - if (value == NULL) { - _printToBuffer(state, "null"); - } else { - _printToBuffer(state, "\"%s\"", value); - } -} - -static void _printLongValue(struct _SerializeState *state, int64_t value) { - _printToBuffer(state, "%lld", value); -} - -static void _printBooleanValue(struct _SerializeState *state, bool value) { - if(value) { - _printToBuffer(state, "true"); - } else { - _printToBuffer(state, "false"); - } -} - -int aws_iot_jobs_json_serialize_update_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotJobExecutionUpdateRequest *request) -{ - const char *statusStr = aws_iot_jobs_map_status_to_string(request->status); - if (statusStr == NULL) return -1; - if (requestBuffer == NULL) bufferSize = 0; - - struct _SerializeState state = { 0, requestBuffer, bufferSize }; - _printKey(&state, true, "status"); - _printStringValue(&state, statusStr); - if (request->statusDetails != NULL) { - _printKey(&state, false, "statusDetails"); - _printToBuffer(&state, "%s", request->statusDetails); - } - if (request->executionNumber != 0) { - _printKey(&state, false, "executionNumber"); - _printLongValue(&state, request->executionNumber); - } - if (request->expectedVersion != 0) { - _printKey(&state, false, "expectedVersion"); - _printLongValue(&state, request->expectedVersion); - } - if (request->includeJobExecutionState) { - _printKey(&state, false, "includeJobExecutionState"); - _printBooleanValue(&state, request->includeJobExecutionState); - } - if (request->includeJobDocument) { - _printKey(&state, false, "includeJobDocument"); - _printBooleanValue(&state, request->includeJobDocument); - } - if (request->clientToken != NULL) { - _printKey(&state, false, "clientToken"); - _printStringValue(&state, request->clientToken); - } - - _printToBuffer(&state, "}"); - - return state.totalSize; -} - -int aws_iot_jobs_json_serialize_client_token_only_request( - char *requestBuffer, size_t bufferSize, - const char *clientToken) -{ - struct _SerializeState state = { 0, requestBuffer, bufferSize }; - _printKey(&state, true, "clientToken"); - _printStringValue(&state, clientToken); - _printToBuffer(&state, "}"); - - return state.totalSize; -} - -int aws_iot_jobs_json_serialize_describe_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotDescribeJobExecutionRequest *request) -{ - bool first = true; - - if (requestBuffer == NULL) return 0; - - struct _SerializeState state = { 0, requestBuffer, bufferSize }; - if (request->clientToken != NULL) { - _printKey(&state, first, "clientToken"); - _printStringValue(&state, request->clientToken); - first = false; - } - if (request->executionNumber != 0) { - _printKey(&state, first, "executionNumber"); - _printLongValue(&state, request->executionNumber); - first = false; - } - if (request->includeJobDocument) { - _printKey(&state, first, "includeJobDocument"); - _printBooleanValue(&state, request->includeJobDocument); - } - - _printToBuffer(&state, "}"); - - return state.totalSize; -} - -int aws_iot_jobs_json_serialize_start_next_job_execution_request( - char *requestBuffer, size_t bufferSize, - const AwsIotStartNextPendingJobExecutionRequest *request) -{ - if (requestBuffer == NULL) bufferSize = 0; - struct _SerializeState state = { 0, requestBuffer, bufferSize }; - if (request->statusDetails != NULL) { - _printKey(&state, true, "statusDetails"); - _printToBuffer(&state, "%s", request->statusDetails); - } - if (request->clientToken != NULL) { - if(request->statusDetails != NULL) { - _printKey(&state, false, "clientToken"); - } else { - _printKey(&state, true, "clientToken"); - } - _printStringValue(&state, request->clientToken); - } - if (request->clientToken == NULL && request->statusDetails == NULL) { - _printToBuffer(&state, "{"); - } - _printToBuffer(&state, "}"); - return state.totalSize; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_topics.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_topics.c deleted file mode 100644 index 39c5cba28..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_topics.c +++ /dev/null @@ -1,129 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_jobs_topics.h" -#include -#include -#include - -#define BASE_THINGS_TOPIC "$aws/things/" - -#define NOTIFY_OPERATION "notify" -#define NOTIFY_NEXT_OPERATION "notify-next" -#define GET_OPERATION "get" -#define START_NEXT_OPERATION "start-next" -#define WILDCARD_OPERATION "+" -#define UPDATE_OPERATION "update" -#define ACCEPTED_REPLY "accepted" -#define REJECTED_REPLY "rejected" -#define WILDCARD_REPLY "+" - -static const char *_get_operation_for_base_topic(AwsIotJobExecutionTopicType topicType) { - switch (topicType) { - case JOB_UPDATE_TOPIC: - return UPDATE_OPERATION; - case JOB_NOTIFY_TOPIC: - return NOTIFY_OPERATION; - case JOB_NOTIFY_NEXT_TOPIC: - return NOTIFY_NEXT_OPERATION; - case JOB_GET_PENDING_TOPIC: - case JOB_DESCRIBE_TOPIC: - return GET_OPERATION; - case JOB_START_NEXT_TOPIC: - return START_NEXT_OPERATION; - case JOB_WILDCARD_TOPIC: - return WILDCARD_OPERATION; - case JOB_UNRECOGNIZED_TOPIC: - default: - return NULL; - } -} - -static bool _base_topic_requires_job_id(AwsIotJobExecutionTopicType topicType) { - switch (topicType) { - case JOB_UPDATE_TOPIC: - case JOB_DESCRIBE_TOPIC: - return true; - case JOB_NOTIFY_TOPIC: - case JOB_NOTIFY_NEXT_TOPIC: - case JOB_START_NEXT_TOPIC: - case JOB_GET_PENDING_TOPIC: - case JOB_WILDCARD_TOPIC: - case JOB_UNRECOGNIZED_TOPIC: - default: - return false; - } -} - -static const char *_get_suffix_for_topic_type(AwsIotJobExecutionTopicReplyType replyType) { - switch (replyType) { - case JOB_REQUEST_TYPE: - return ""; - break; - case JOB_ACCEPTED_REPLY_TYPE: - return "/" ACCEPTED_REPLY; - break; - case JOB_REJECTED_REPLY_TYPE: - return "/" REJECTED_REPLY; - break; - case JOB_WILDCARD_REPLY_TYPE: - return "/" WILDCARD_REPLY; - break; - case JOB_UNRECOGNIZED_TOPIC_TYPE: - default: - return NULL; - } -} - -int aws_iot_jobs_get_api_topic(char *buffer, size_t bufferSize, - AwsIotJobExecutionTopicType topicType, AwsIotJobExecutionTopicReplyType replyType, - const char* thingName, const char* jobId) -{ - if (thingName == NULL) { - return -1; - } - - if ((topicType == JOB_NOTIFY_TOPIC || topicType == JOB_NOTIFY_NEXT_TOPIC) && replyType != JOB_REQUEST_TYPE) { - return -1; - } - - bool requireJobId = _base_topic_requires_job_id(topicType); - if (jobId == NULL && requireJobId) { - return -1; - } - - const char *operation = _get_operation_for_base_topic(topicType); - if (operation == NULL) { - return -1; - } - - const char *suffix = _get_suffix_for_topic_type(replyType); - - if (requireJobId || (topicType == JOB_WILDCARD_TOPIC && jobId != NULL)) { - return snprintf(buffer, bufferSize, BASE_THINGS_TOPIC "%s/jobs/%s/%s%s", thingName, jobId, operation, suffix); - } else if (topicType == JOB_WILDCARD_TOPIC) { - return snprintf(buffer, bufferSize, BASE_THINGS_TOPIC "%s/jobs/#", thingName); - } else { - return snprintf(buffer, bufferSize, BASE_THINGS_TOPIC "%s/jobs/%s%s", thingName, operation, suffix); - } -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_types.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_types.c deleted file mode 100644 index 9dcbf5081..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_jobs_types.c +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "aws_iot_jobs_types.h" - -const char *JOB_EXECUTION_QUEUED_STR = "QUEUED"; -const char *JOB_EXECUTION_IN_PROGRESS_STR = "IN_PROGRESS"; -const char *JOB_EXECUTION_FAILED_STR = "FAILED"; -const char *JOB_EXECUTION_SUCCEEDED_STR = "SUCCEEDED"; -const char *JOB_EXECUTION_CANCELED_STR = "CANCELED"; -const char *JOB_EXECUTION_REJECTED_STR = "REJECTED"; - -JobExecutionStatus aws_iot_jobs_map_string_to_job_status(const char *str) { - if (str == NULL || str[0] == '\0') { - return JOB_EXECUTION_STATUS_NOT_SET; - } else if (strcmp(str, JOB_EXECUTION_QUEUED_STR) == 0) { - return JOB_EXECUTION_QUEUED; - } else if(strcmp(str, JOB_EXECUTION_IN_PROGRESS_STR) == 0) { - return JOB_EXECUTION_IN_PROGRESS; - } else if(strcmp(str, JOB_EXECUTION_FAILED_STR) == 0) { - return JOB_EXECUTION_FAILED; - } else if(strcmp(str, JOB_EXECUTION_SUCCEEDED_STR) == 0) { - return JOB_EXECUTION_SUCCEEDED; - } else if(strcmp(str, JOB_EXECUTION_CANCELED_STR) == 0) { - return JOB_EXECUTION_CANCELED; - } else if(strcmp(str, JOB_EXECUTION_REJECTED_STR) == 0) { - return JOB_EXECUTION_REJECTED; - } else { - return JOB_EXECUTION_UNKNOWN_STATUS; - } -} - -const char *aws_iot_jobs_map_status_to_string(JobExecutionStatus status) { - switch(status) { - case JOB_EXECUTION_QUEUED: - return JOB_EXECUTION_QUEUED_STR; - case JOB_EXECUTION_IN_PROGRESS: - return JOB_EXECUTION_IN_PROGRESS_STR; - case JOB_EXECUTION_FAILED: - return JOB_EXECUTION_FAILED_STR; - case JOB_EXECUTION_SUCCEEDED: - return JOB_EXECUTION_SUCCEEDED_STR; - case JOB_EXECUTION_CANCELED: - return JOB_EXECUTION_CANCELED_STR; - case JOB_EXECUTION_REJECTED: - return JOB_EXECUTION_REJECTED_STR; - case JOB_EXECUTION_STATUS_NOT_SET: - case JOB_EXECUTION_UNKNOWN_STATUS: - default: - return NULL; - } -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_json_utils.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_json_utils.c deleted file mode 100644 index f8485695f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_json_utils.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_json_utils.c - * @brief Utilities for manipulating JSON - * - * json_utils provides JSON parsing utilities for use with the IoT SDK. - * Underlying JSON parsing relies on the Jasmine JSON parser. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_json_utils.h" - -#include -#include -#include - -#include "aws_iot_log.h" - -int8_t jsoneq(const char *json, jsmntok_t *tok, const char *s) { - if(tok->type == JSMN_STRING) { - if((int) strlen(s) == tok->end - tok->start) { - if(strncmp(json + tok->start, s, (size_t) (tok->end - tok->start)) == 0) { - return 0; - } - } - } - return -1; -} - -IoT_Error_t parseUnsignedInteger32Value(uint32_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%u", i))) { - IOT_WARN("Token was not an unsigned integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseUnsignedInteger16Value(uint16_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%hu", i))) { - IOT_WARN("Token was not an unsigned integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseUnsignedInteger8Value(uint8_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%hhu", i))) { - IOT_WARN("Token was not an unsigned integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseInteger32Value(int32_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%i", i)) { - IOT_WARN("Token was not an integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseInteger16Value(int16_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%hi", i)) { - IOT_WARN("Token was not an integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseInteger8Value(int8_t *i, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not an integer"); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%hhi", i)) { - IOT_WARN("Token was not an integer."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseFloatValue(float *f, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not a float."); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%f", f)) { - IOT_WARN("Token was not a float."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseDoubleValue(double *d, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not a double."); - return JSON_PARSE_ERROR; - } - - if(1 != sscanf(jsonString + token->start, "%lf", d)) { - IOT_WARN("Token was not a double."); - return JSON_PARSE_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token) { - if(token->type != JSMN_PRIMITIVE) { - IOT_WARN("Token was not a primitive."); - return JSON_PARSE_ERROR; - } - if(strncmp(jsonString + token->start, "true", 4) == 0) { - *b = true; - } else if(strncmp(jsonString + token->start, "false", 5) == 0) { - *b = false; - } else { - IOT_WARN("Token was not a bool."); - return JSON_PARSE_ERROR; - } - return SUCCESS; -} - -IoT_Error_t parseStringValue(char *buf, size_t bufLen, const char *jsonString, jsmntok_t *token) { - /* This length does not include a null-terminator. */ - size_t stringLength = (size_t)(token->end - token->start); - - if(token->type != JSMN_STRING) { - IOT_WARN("Token was not a string."); - return JSON_PARSE_ERROR; - } - - if (stringLength+1 > bufLen) { - IOT_WARN("Buffer too small to hold string value."); - return SHADOW_JSON_ERROR; - } - - strncpy(buf, jsonString + token->start, stringLength); - buf[stringLength] = '\0'; - - return SUCCESS; -} - -jsmntok_t *findToken(const char *key, const char *jsonString, jsmntok_t *token) { - jsmntok_t *result = token; - int i; - - if(token->type != JSMN_OBJECT) { - IOT_WARN("Token was not an object."); - return NULL; - } - - if(token->size == 0) { - return NULL; - } - - result = token + 1; - - for (i = 0; i < token->size; i++) { - if (0 == jsoneq(jsonString, result, key)) { - return result + 1; - } - - int propertyEnd = (result + 1)->end; - result += 2; - while (result->start < propertyEnd) - result++; - } - - return NULL; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c deleted file mode 100644 index 21400faf5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client.c +++ /dev/null @@ -1,397 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client.c - * @brief MQTT client API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "aws_iot_log.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_mqtt_client_common_internal.h" -#include "aws_iot_version.h" - -#if !DISABLE_METRICS -/** Length of metrics username */ -#define SDK_METRICS_LEN 25 -/** Metrics username for AWS IoT */ -#define SDK_METRICS_TEMPLATE "?SDK=C&Version=%d.%d.%d" -/** Buffer for metrics username */ -static char pUsernameTemp[SDK_METRICS_LEN] = {0}; -#endif - -#ifdef _ENABLE_THREAD_SUPPORT_ -#include "threads_interface.h" -#endif - -const IoT_Client_Init_Params iotClientInitParamsDefault = IoT_Client_Init_Params_initializer; -const IoT_MQTT_Will_Options iotMqttWillOptionsDefault = IoT_MQTT_Will_Options_Initializer; -const IoT_Client_Connect_Params iotClientConnectParamsDefault = IoT_Client_Connect_Params_initializer; - -ClientState aws_iot_mqtt_get_client_state(AWS_IoT_Client *pClient) { - FUNC_ENTRY; - if(NULL == pClient) { - return CLIENT_STATE_INVALID; - } - - FUNC_EXIT_RC(pClient->clientStatus.clientState); -} - -#ifdef _ENABLE_THREAD_SUPPORT_ -/** - * @brief Lock a mutex in the MQTT client - * - * @param pClient MQTT client - * @param pMutex Mutex to lock - * - * @return IoT_Error_t of mutex operation - */ -IoT_Error_t aws_iot_mqtt_client_lock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex) { - FUNC_ENTRY; - IoT_Error_t threadRc = FAILURE; - - if(NULL == pClient || NULL == pMutex){ - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(false == pClient->clientData.isBlockOnThreadLockEnabled) { - threadRc = aws_iot_thread_mutex_trylock(pMutex); - } else { - threadRc = aws_iot_thread_mutex_lock(pMutex); - /* Should never return Error because the above request blocks until lock is obtained */ - } - - if(SUCCESS != threadRc) { - FUNC_EXIT_RC(threadRc); - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Unlock a mutex in the MQTT client - * - * @param pClient MQTT client - * @param pMutex Mutex to unlock - * - * @return IoT_Error_t of mutex operation - */ -IoT_Error_t aws_iot_mqtt_client_unlock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex) { - if(NULL == pClient || NULL == pMutex) { - return NULL_VALUE_ERROR; - } - IOT_UNUSED(pClient); - return aws_iot_thread_mutex_unlock(pMutex); -} -#endif - -/** - * @brief Change the state in an MQTT client - * - * @param pClient MQTT client - * @param expectedCurrentState What the current state of the client should be - * @param newState What the new state of the client should be - * - * @return IoT_Error_t of state change - */ -IoT_Error_t aws_iot_mqtt_set_client_state(AWS_IoT_Client *pClient, ClientState expectedCurrentState, - ClientState newState) { - IoT_Error_t rc; -#ifdef _ENABLE_THREAD_SUPPORT_ - IoT_Error_t threadRc = FAILURE; -#endif - - FUNC_ENTRY; - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.state_change_mutex)); - if(SUCCESS != threadRc) { - return threadRc; - } -#endif - if(expectedCurrentState == aws_iot_mqtt_get_client_state(pClient)) { - pClient->clientStatus.clientState = newState; - rc = SUCCESS; - } else { - rc = MQTT_UNEXPECTED_CLIENT_STATE_ERROR; - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.state_change_mutex)); - if(SUCCESS == rc && SUCCESS != threadRc) { - rc = threadRc; - } -#endif - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_mqtt_set_connect_params(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pNewConnectParams) { - FUNC_ENTRY; - if(NULL == pClient || NULL == pNewConnectParams) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - pClient->clientData.options.isWillMsgPresent = pNewConnectParams->isWillMsgPresent; - pClient->clientData.options.MQTTVersion = pNewConnectParams->MQTTVersion; - pClient->clientData.options.pClientID = pNewConnectParams->pClientID; - pClient->clientData.options.clientIDLen = pNewConnectParams->clientIDLen; -#if !DISABLE_METRICS - if (0 == strlen(pUsernameTemp)) { - snprintf(pUsernameTemp, SDK_METRICS_LEN, SDK_METRICS_TEMPLATE, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); - } - pClient->clientData.options.pUsername = (char*)&pUsernameTemp[0]; - pClient->clientData.options.usernameLen = strlen(pUsernameTemp); -#else - pClient->clientData.options.pUsername = pNewConnectParams->pUsername; - pClient->clientData.options.usernameLen = pNewConnectParams->usernameLen; -#endif - pClient->clientData.options.pPassword = pNewConnectParams->pPassword; - pClient->clientData.options.passwordLen = pNewConnectParams->passwordLen; - pClient->clientData.options.will.pTopicName = pNewConnectParams->will.pTopicName; - pClient->clientData.options.will.topicNameLen = pNewConnectParams->will.topicNameLen; - pClient->clientData.options.will.pMessage = pNewConnectParams->will.pMessage; - pClient->clientData.options.will.msgLen = pNewConnectParams->will.msgLen; - pClient->clientData.options.will.qos = pNewConnectParams->will.qos; - pClient->clientData.options.will.isRetained = pNewConnectParams->will.isRetained; - pClient->clientData.options.keepAliveIntervalInSec = pNewConnectParams->keepAliveIntervalInSec; - pClient->clientData.options.isCleanSession = pNewConnectParams->isCleanSession; - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_free(AWS_IoT_Client *pClient) -{ - IoT_Error_t rc = SUCCESS; - - if (NULL == pClient) { - rc = NULL_VALUE_ERROR; - }else - { - #ifdef _ENABLE_THREAD_SUPPORT_ - if (rc == SUCCESS) - { - rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); - } - - if (rc == SUCCESS) - { - rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); - }else{ - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); - } - - if (rc == SUCCESS) - { - rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex)); - }else{ - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex)); - } - #endif - } - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *pInitParams) { - uint32_t i; - IoT_Error_t rc; - IoT_Client_Connect_Params default_options = IoT_Client_Connect_Params_initializer; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pInitParams || NULL == pInitParams->pHostURL || 0 == pInitParams->port || - NULL == pInitParams->pRootCALocation || NULL == pInitParams->pDevicePrivateKeyLocation || - NULL == pInitParams->pDeviceCertLocation) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { - pClient->clientData.messageHandlers[i].topicName = NULL; - pClient->clientData.messageHandlers[i].pApplicationHandler = NULL; - pClient->clientData.messageHandlers[i].pApplicationHandlerData = NULL; - pClient->clientData.messageHandlers[i].qos = QOS0; - } - - pClient->clientData.packetTimeoutMs = pInitParams->mqttPacketTimeout_ms; - pClient->clientData.commandTimeoutMs = pInitParams->mqttCommandTimeout_ms; - pClient->clientData.writeBufSize = AWS_IOT_MQTT_TX_BUF_LEN; - pClient->clientData.readBufSize = AWS_IOT_MQTT_RX_BUF_LEN; - pClient->clientData.counterNetworkDisconnected = 0; - pClient->clientData.disconnectHandler = pInitParams->disconnectHandler; - pClient->clientData.disconnectHandlerData = pInitParams->disconnectHandlerData; - pClient->clientData.nextPacketId = 1; - - /* Initialize default connection options */ - rc = aws_iot_mqtt_set_connect_params(pClient, &default_options); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - pClient->clientData.isBlockOnThreadLockEnabled = pInitParams->isBlockOnThreadLockEnabled; - rc = aws_iot_thread_mutex_init(&(pClient->clientData.state_change_mutex)); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - rc = aws_iot_thread_mutex_init(&(pClient->clientData.tls_read_mutex)); - if(SUCCESS != rc) { - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); - FUNC_EXIT_RC(rc); - } - rc = aws_iot_thread_mutex_init(&(pClient->clientData.tls_write_mutex)); - if(SUCCESS != rc) { - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); - FUNC_EXIT_RC(rc); - } -#endif - - pClient->clientStatus.isPingOutstanding = 0; - pClient->clientStatus.isAutoReconnectEnabled = pInitParams->enableAutoReconnect; - - rc = iot_tls_init(&(pClient->networkStack), pInitParams->pRootCALocation, pInitParams->pDeviceCertLocation, - pInitParams->pDevicePrivateKeyLocation, pInitParams->pHostURL, pInitParams->port, - pInitParams->tlsHandshakeTimeout_ms, pInitParams->isSSLHostnameVerify); - - if(SUCCESS != rc) { - #ifdef _ENABLE_THREAD_SUPPORT_ - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); - (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex)); - #endif - pClient->clientStatus.clientState = CLIENT_STATE_INVALID; - FUNC_EXIT_RC(rc); - } - - init_timer(&(pClient->pingReqTimer)); - init_timer(&(pClient->pingRespTimer)); - init_timer(&(pClient->reconnectDelayTimer)); - - pClient->clientStatus.clientState = CLIENT_STATE_INITIALIZED; - - FUNC_EXIT_RC(SUCCESS); -} - -uint16_t aws_iot_mqtt_get_next_packet_id(AWS_IoT_Client *pClient) { - return pClient->clientData.nextPacketId = (uint16_t) ((MAX_PACKET_ID == pClient->clientData.nextPacketId) ? 1 : ( - pClient->clientData.nextPacketId + 1)); -} - -bool aws_iot_mqtt_is_client_connected(AWS_IoT_Client *pClient) { - bool isConnected; - - FUNC_ENTRY; - - if(NULL == pClient) { - IOT_WARN(" Client is null! "); - FUNC_EXIT_RC(false); - } - - switch(pClient->clientStatus.clientState) { - case CLIENT_STATE_INVALID: - case CLIENT_STATE_INITIALIZED: - case CLIENT_STATE_CONNECTING: - isConnected = false; - break; - case CLIENT_STATE_CONNECTED_IDLE: - case CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN: - isConnected = true; - break; - case CLIENT_STATE_DISCONNECTING: - case CLIENT_STATE_DISCONNECTED_ERROR: - case CLIENT_STATE_DISCONNECTED_MANUALLY: - case CLIENT_STATE_PENDING_RECONNECT: - default: - isConnected = false; - break; - } - - FUNC_EXIT_RC(isConnected); -} - -bool aws_iot_is_autoreconnect_enabled(AWS_IoT_Client *pClient) { - FUNC_ENTRY; - if(NULL == pClient) { - IOT_WARN(" Client is null! "); - FUNC_EXIT_RC(false); - } - - FUNC_EXIT_RC(pClient->clientStatus.isAutoReconnectEnabled); -} - -IoT_Error_t aws_iot_mqtt_autoreconnect_set_status(AWS_IoT_Client *pClient, bool newStatus) { - FUNC_ENTRY; - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - pClient->clientStatus.isAutoReconnectEnabled = newStatus; - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_set_disconnect_handler(AWS_IoT_Client *pClient, iot_disconnect_handler pDisconnectHandler, - void *pDisconnectHandlerData) { - FUNC_ENTRY; - if(NULL == pClient || NULL == pDisconnectHandler) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - pClient->clientData.disconnectHandler = pDisconnectHandler; - pClient->clientData.disconnectHandlerData = pDisconnectHandlerData; - FUNC_EXIT_RC(SUCCESS); -} - -uint32_t aws_iot_mqtt_get_network_disconnected_count(AWS_IoT_Client *pClient) { - return pClient->clientData.counterNetworkDisconnected; -} - -void aws_iot_mqtt_reset_network_disconnected_count(AWS_IoT_Client *pClient) { - pClient->clientData.counterNetworkDisconnected = 0; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_common_internal.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_common_internal.c deleted file mode 100644 index 8aaf4a321..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_common_internal.c +++ /dev/null @@ -1,793 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Sergio R. Caprile - non-blocking packet read functions for stream transport - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_common_internal.c - * @brief MQTT client internal API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "aws_iot_mqtt_client_common_internal.h" - -/** Max length of packet header */ -#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4 - -/** - * @brief Encodes the message length according to the MQTT algorithm - * - * @param buf the buffer into which the encoded data is written - * @param length the length to be encoded - * - * @return the number of bytes written to buffer - */ -size_t aws_iot_mqtt_internal_write_len_to_buffer(unsigned char *buf, uint32_t length) { - size_t outLen = 0; - unsigned char encodedByte; - - FUNC_ENTRY; - do { - encodedByte = (unsigned char) (length % 128); - length /= 128; - /* if there are more digits to encode, set the top bit of this digit */ - if(length > 0) { - encodedByte |= 0x80; - } - buf[outLen++] = encodedByte; - } while(length > 0); - - FUNC_EXIT_RC(outLen); -} - -/** - * @brief Decodes the message length according to the MQTT algorithm - * - * @param buf the buffer containing the message - * @param decodedLen value the decoded length returned - * @param readBytesLen output parameter for the number of bytes read from the socket - * - * @return IoT_Error_t indicating decode status - */ -IoT_Error_t aws_iot_mqtt_internal_decode_remaining_length_from_buffer(unsigned char *buf, uint32_t *decodedLen, - uint32_t *readBytesLen) { - unsigned char encodedByte; - uint32_t multiplier, len; - FUNC_ENTRY; - - multiplier = 1; - len = 0; - *decodedLen = 0; - - do { - if(++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) { - /* bad data */ - FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR); - } - encodedByte = *buf; - buf++; - *decodedLen += (encodedByte & 127) * multiplier; - multiplier *= 128; - } while((encodedByte & 128) != 0); - - *readBytesLen = len; - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Calculates the length of the "remaining length" encoding - * - * @param rem_len "remaining length" to encode - * - * @return length of the remaining length encoding - */ -uint32_t aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(uint32_t rem_len) { - rem_len += 1; /* header byte */ - /* now remaining_length field (MQTT 3.1.1 - 2.2.3)*/ - if(rem_len < 128) { - rem_len += 1; - } else if(rem_len < 16384) { - rem_len += 2; - } else if(rem_len < 2097152) { - rem_len += 3; - } else { - rem_len += 4; - } - return rem_len; -} - -/** - * @brief Calculates uint16 packet id from two bytes read from the input buffer - * - * Checks Endianness at runtime - * - * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned - * @return the value calculated - */ -uint16_t aws_iot_mqtt_internal_read_uint16_t(unsigned char **pptr) { - unsigned char *ptr = *pptr; - uint16_t len = 0; - uint8_t firstByte = (uint8_t) (*ptr); - uint8_t secondByte = (uint8_t) (*(ptr + 1)); - len = (uint16_t) (secondByte + (256 * firstByte)); - - *pptr += 2; - return len; -} - -/** - * @brief Writes an integer as 2 bytes to an output buffer. - * - * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned - * @param anInt the integer to write - */ -void aws_iot_mqtt_internal_write_uint_16(unsigned char **pptr, uint16_t anInt) { - **pptr = (unsigned char) (anInt / 256); - (*pptr)++; - **pptr = (unsigned char) (anInt % 256); - (*pptr)++; -} - -/** - * @brief Reads one character from the input buffer. - * - * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned - * @return the character read - */ -unsigned char aws_iot_mqtt_internal_read_char(unsigned char **pptr) { - unsigned char c = **pptr; - (*pptr)++; - return c; -} - -/** - * @brief Writes one character to an output buffer. - * - * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned - * @param c the character to write - */ -void aws_iot_mqtt_internal_write_char(unsigned char **pptr, unsigned char c) { - **pptr = c; - (*pptr)++; -} - -/** - * @brief Writes a UTF-8 string into an MQTT packet - * - * @param pptr Where the string should be written - * @param string The string to write - * @param stringLen Length to write - */ -void aws_iot_mqtt_internal_write_utf8_string(unsigned char **pptr, const char *string, uint16_t stringLen) { - /* Nothing that calls this function will have a stringLen with a size larger than 2 bytes (MQTT 3.1.1 - 1.5.3) */ - aws_iot_mqtt_internal_write_uint_16(pptr, stringLen); - if(stringLen > 0) { - memcpy(*pptr, string, stringLen); - *pptr += stringLen; - } -} - -/** - * @brief Initialize the MQTTHeader structure. - * - * Used to ensure that Header bits are always initialized using the proper mappings. - * No Endianness issues here since the individual fields are all less than a byte. - * Also generates no warnings since all fields are initialized using hex constants. - * - * @param pHeader Header to initialize - * @param message_type MQTT packet type - * @param qos Quality of service for packet - * @param dup DUP flag of a publish - * @param retained RETAIN flag of a publish - * - * @return Returns SUCCESS unless an invalid packet type is given. - */ -IoT_Error_t aws_iot_mqtt_internal_init_header(MQTTHeader *pHeader, MessageTypes message_type, - QoS qos, uint8_t dup, uint8_t retained) { - FUNC_ENTRY; - - if(NULL == pHeader) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Set all bits to zero */ - pHeader->byte = 0; - uint8_t type = 0; - switch(message_type) { - case UNKNOWN: - /* Should never happen */ - return FAILURE; - case CONNECT: - type = 0x01; - break; - case CONNACK: - type = 0x02; - break; - case PUBLISH: - type = 0x03; - break; - case PUBACK: - type = 0x04; - break; - case PUBREC: - type = 0x05; - break; - case PUBREL: - type = 0x06; - break; - case PUBCOMP: - type = 0x07; - break; - case SUBSCRIBE: - type = 0x08; - break; - case SUBACK: - type = 0x09; - break; - case UNSUBSCRIBE: - type = 0x0A; - break; - case UNSUBACK: - type = 0x0B; - break; - case PINGREQ: - type = 0x0C; - break; - case PINGRESP: - type = 0x0D; - break; - case DISCONNECT: - type = 0x0E; - break; - default: - /* Should never happen */ - FUNC_EXIT_RC(FAILURE); - } - - pHeader->byte = type << 4; - pHeader->byte |= dup << 3; - - switch(qos) { - case QOS0: - break; - case QOS1: - pHeader->byte |= 1 << 1; - break; - default: - /* Using QOS0 as default */ - break; - } - - pHeader->byte |= (1 == retained) ? 0x01 : 0x00; - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Send an MQTT packet on the network - * - * @param pClient MQTT client which holds packet - * @param length Length of packet to send - * @param pTimer Amount of time allowed to send packet - * - * @return IoT_Error_t of send status - */ -IoT_Error_t aws_iot_mqtt_internal_send_packet(AWS_IoT_Client *pClient, size_t length, Timer *pTimer) { - - size_t sentLen, sent; - IoT_Error_t rc = FAILURE; - -#ifdef _ENABLE_THREAD_SUPPORT_ - IoT_Error_t threadRc; -#endif - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pTimer) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(length >= pClient->clientData.writeBufSize) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.tls_write_mutex)); - if(SUCCESS != threadRc) { - FUNC_EXIT_RC(threadRc); - } -#endif - - sentLen = 0; - sent = 0; - - while(sent < length && !has_timer_expired(pTimer)) { - rc = pClient->networkStack.write(&(pClient->networkStack), - &pClient->clientData.writeBuf[sent], - (length - sent), - pTimer, - &sentLen); - if(SUCCESS != rc) { - /* there was an error writing the data */ - break; - } - sent += sentLen; - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.tls_write_mutex)); - if((SUCCESS != threadRc) && ( SUCCESS == rc )) { - FUNC_EXIT_RC(threadRc); - } -#endif - - if(sent == length) { - /* record the fact that we have successfully sent the packet */ - //countdown_sec(&c->pingTimer, c->clientData.keepAliveInterval); - FUNC_EXIT_RC(SUCCESS); - } - - FUNC_EXIT_RC(rc) -} - -static IoT_Error_t _aws_iot_mqtt_internal_readWrapper( AWS_IoT_Client *pClient, size_t offset, size_t size, Timer *pTimer, size_t * read_len ) { - IoT_Error_t rc; - int byteToRead; - size_t byteRead = 0; - - byteToRead = ( offset + size ) - pClient->clientData.readBufIndex; - - if ( byteToRead > 0 ) - { - rc = pClient->networkStack.read( &( pClient->networkStack ), - pClient->clientData.readBuf + pClient->clientData.readBufIndex, - (size_t)byteToRead, - pTimer, - &byteRead ); - pClient->clientData.readBufIndex += byteRead; - - /* refresh byte to read */ - byteToRead = ( offset + size ) - ((int)pClient->clientData.readBufIndex); - *read_len = size - (size_t)byteToRead; - } - else - { - *read_len = size; - rc = SUCCESS; - } - - - - return rc; -} -static IoT_Error_t _aws_iot_mqtt_internal_decode_packet_remaining_len(AWS_IoT_Client *pClient, size_t * offset, - size_t *rem_len, Timer *pTimer) { - size_t multiplier, len; - IoT_Error_t rc; - size_t read_len; - - FUNC_ENTRY; - - multiplier = 1; - len = 0; - *rem_len = 0; - - do { - if(++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) { - /* bad data */ - FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR); - } - rc = _aws_iot_mqtt_internal_readWrapper( pClient, len, 1, pTimer, &read_len ); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - *rem_len += (( pClient->clientData.readBuf[len] & 127) * multiplier); - multiplier *= 128; - } while(( pClient->clientData.readBuf[len] & 128) != 0); - *offset = len + 1; - FUNC_EXIT_RC(rc); -} - -static IoT_Error_t _aws_iot_mqtt_internal_read_packet(AWS_IoT_Client *pClient, Timer *pTimer, uint8_t *pPacketType) { - size_t rem_len, total_bytes_read, bytes_to_be_read, read_len; - IoT_Error_t rc; - size_t offset = 0; - MQTTHeader header = {0}; - - rem_len = 0; - total_bytes_read = 0; - bytes_to_be_read = 0; - read_len = 0; - - rc = _aws_iot_mqtt_internal_readWrapper( pClient, offset, 1, pTimer, &read_len ); - /* 1. read the header byte. This has the packet type in it */ - if(NETWORK_SSL_NOTHING_TO_READ == rc) { - return MQTT_NOTHING_TO_READ; - } else if(SUCCESS != rc) { - return rc; - } - - /* 2. read the remaining length. This is variable in itself */ - rc = _aws_iot_mqtt_internal_decode_packet_remaining_len(pClient, &offset, &rem_len, pTimer); - if(SUCCESS != rc) { - return rc; - } - - /* if the buffer is too short then the message will be dropped silently */ - if((rem_len + offset) >= pClient->clientData.readBufSize) { - bytes_to_be_read = pClient->clientData.readBufSize; - do { - rc = pClient->networkStack.read(&(pClient->networkStack), pClient->clientData.readBuf, bytes_to_be_read, - pTimer, &read_len); - if(SUCCESS == rc) { - total_bytes_read += read_len; - if((rem_len - total_bytes_read) >= pClient->clientData.readBufSize) { - bytes_to_be_read = pClient->clientData.readBufSize; - } else { - bytes_to_be_read = rem_len - total_bytes_read; - } - } - } while(total_bytes_read < rem_len && SUCCESS == rc); - - /* Check buffer was correctly emptied, otherwise, return error message. */ - if ( total_bytes_read == rem_len ) - { - aws_iot_mqtt_internal_flushBuffers( pClient ); - return MQTT_RX_BUFFER_TOO_SHORT_ERROR; - } - else - { - return rc; - } - } - - /* 3. read the rest of the buffer using a callback to supply the rest of the data */ - if(rem_len > 0) { - rc = _aws_iot_mqtt_internal_readWrapper( pClient, offset, rem_len, pTimer, &read_len ); - if(SUCCESS != rc || read_len != rem_len) { - return FAILURE; - } - } - - /* Pack has been received, we can flush the buffers for next call. */ - aws_iot_mqtt_internal_flushBuffers( pClient ); - header.byte = pClient->clientData.readBuf[0]; - *pPacketType = MQTT_HEADER_FIELD_TYPE(header.byte); - - FUNC_EXIT_RC(rc); -} - -// assume topic filter and name is in correct format -// # can only be at end -// + and # can only be next to separator -static bool _aws_iot_mqtt_internal_is_topic_matched(char *pTopicFilter, char *pTopicName, uint16_t topicNameLen) { - - char *curf, *curn, *curn_end; - - if(NULL == pTopicFilter || NULL == pTopicName) { - return false; - } - - curf = pTopicFilter; - curn = pTopicName; - curn_end = curn + topicNameLen; - - while(*curf && (curn < curn_end)) { - if(*curn == '/' && *curf != '/') { - break; - } - if(*curf != '+' && *curf != '#' && *curf != *curn) { - break; - } - if(*curf == '+') { - /* skip until we meet the next separator, or end of string */ - char *nextpos = curn + 1; - while(nextpos < curn_end && *nextpos != '/') - nextpos = ++curn + 1; - } else if(*curf == '#') { - /* skip until end of string */ - curn = curn_end - 1; - } - - curf++; - curn++; - }; - - return (curn == curn_end) && (*curf == '\0'); -} - -static IoT_Error_t _aws_iot_mqtt_internal_deliver_message(AWS_IoT_Client *pClient, char *pTopicName, - uint16_t topicNameLen, - IoT_Publish_Message_Params *pMessageParams) { - uint32_t itr; - IoT_Error_t rc; - ClientState clientState; - - FUNC_ENTRY; - - if(NULL == pTopicName) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* This function can be called from all MQTT APIs - * But while callback return is in progress, Yield should not be called. - * The state for CB_RETURN accomplishes that, as yield cannot be called while in that state */ - clientState = aws_iot_mqtt_get_client_state(pClient); - aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN); - - /* Find the right message handler - indexed by topic */ - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++itr) { - if(NULL != pClient->clientData.messageHandlers[itr].topicName) { - if(((topicNameLen == pClient->clientData.messageHandlers[itr].topicNameLen) - && - (strncmp(pTopicName, (char *) pClient->clientData.messageHandlers[itr].topicName, topicNameLen) == 0)) - || _aws_iot_mqtt_internal_is_topic_matched((char *) pClient->clientData.messageHandlers[itr].topicName, - pTopicName, topicNameLen)) { - if(NULL != pClient->clientData.messageHandlers[itr].pApplicationHandler) { - pClient->clientData.messageHandlers[itr].pApplicationHandler(pClient, pTopicName, topicNameLen, - pMessageParams, - pClient->clientData.messageHandlers[itr].pApplicationHandlerData); - } - } - } - } - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN, clientState); - - FUNC_EXIT_RC(rc); -} - -static IoT_Error_t _aws_iot_mqtt_internal_handle_publish(AWS_IoT_Client *pClient) { - char *topicName; - uint16_t topicNameLen; - uint32_t len; - IoT_Error_t rc; - IoT_Publish_Message_Params msg; - Timer sendTimer; - - FUNC_ENTRY; - - topicName = NULL; - topicNameLen = 0; - len = 0; - - rc = aws_iot_mqtt_internal_deserialize_publish(&msg.isDup, &msg.qos, &msg.isRetained, - &msg.id, &topicName, &topicNameLen, - (unsigned char **) &msg.payload, &msg.payloadLen, - pClient->clientData.readBuf, - pClient->clientData.readBufSize); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Send acknowledgement of QoS 1 message. */ - if(QOS1 == msg.qos) { - /* Initialize timer for sending PUBACK. */ - init_timer(&sendTimer); - countdown_ms(&sendTimer, pClient->clientData.commandTimeoutMs); - - /* Generate and send a PUBACK. Warn if the PUBACK isn't sent; the server - will send the PUBLISH again in that case. */ - rc = aws_iot_mqtt_internal_serialize_ack(pClient->clientData.writeBuf, - pClient->clientData.writeBufSize, PUBACK, 0, msg.id, &len); - - if(SUCCESS == rc) { - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &sendTimer); - - if(SUCCESS != rc) { - IOT_WARN("Failed to send PUBACK"); - } - } else { - IOT_WARN("Failed to generate PUBACK"); - } - } - - rc = _aws_iot_mqtt_internal_deliver_message(pClient, topicName, topicNameLen, &msg); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Read an MQTT packet from the network - * - * @param pClient MQTT client - * @param pTimer Amount of time allowed to read packet - * @param pPacketType Output parameter for packet read from network - * - * @return IoT_Error_t of read status - */ -IoT_Error_t aws_iot_mqtt_internal_cycle_read(AWS_IoT_Client *pClient, Timer *pTimer, uint8_t *pPacketType) { - IoT_Error_t rc; - -#ifdef _ENABLE_THREAD_SUPPORT_ - IoT_Error_t threadRc; -#endif - - if(NULL == pClient || NULL == pTimer) { - return NULL_VALUE_ERROR; - } - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.tls_read_mutex)); - if(SUCCESS != threadRc) { - FUNC_EXIT_RC(threadRc); - } -#endif - - /* read the socket, see what work is due */ - rc = _aws_iot_mqtt_internal_read_packet(pClient, pTimer, pPacketType); - -#ifdef _ENABLE_THREAD_SUPPORT_ - threadRc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.tls_read_mutex)); - if(SUCCESS != threadRc && (MQTT_NOTHING_TO_READ == rc || SUCCESS == rc)) { - return threadRc; - } -#endif - - if(MQTT_NOTHING_TO_READ == rc) { - /* Nothing to read, not a cycle failure */ - return SUCCESS; - } else if(SUCCESS != rc) { - return rc; - } - - switch(*pPacketType) { - case CONNACK: - case PUBACK: - case SUBACK: - case UNSUBACK: - /* SDK is blocking, these responses will be forwarded to calling function to process */ - break; - case PUBLISH: { - rc = _aws_iot_mqtt_internal_handle_publish(pClient); - break; - } - case PUBREC: - case PUBCOMP: - /* QoS2 not supported at this time */ - break; - case PINGRESP: { - /* There is no outstanding ping request anymore. */ - pClient->clientStatus.isPingOutstanding = false; - break; - } - default: { - /* Either unknown packet type or Failure occurred - * Should not happen */ - rc = MQTT_RX_MESSAGE_PACKET_TYPE_INVALID_ERROR; - break; - } - } - - return rc; -} - -/** - * @brief Flush incoming data from the MQTT client - * - * @param pClient Client with data to flush - * - * @return Always returns SUCCESS - */ -IoT_Error_t aws_iot_mqtt_internal_flushBuffers( AWS_IoT_Client *pClient ) { - pClient->clientData.readBufIndex = 0; - return SUCCESS; -} - -/** - * @brief Wait until a packet is read from the network - * - * Only used in single-threaded mode where one command at a time is in process - * - * @param pClient MQTT client - * @param packetType MQTT packet to read - * @param pTimer Amount of time allowed to read packet - * - * @return IoT_Error_t of read status - */ -IoT_Error_t aws_iot_mqtt_internal_wait_for_read(AWS_IoT_Client *pClient, uint8_t packetType, Timer *pTimer) { - IoT_Error_t rc; - uint8_t read_packet_type; - - FUNC_ENTRY; - if(NULL == pClient || NULL == pTimer) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - read_packet_type = 0; - do { - if(has_timer_expired(pTimer)) { - /* we timed out */ - rc = MQTT_REQUEST_TIMEOUT_ERROR; - break; - } - rc = aws_iot_mqtt_internal_cycle_read(pClient, pTimer, &read_packet_type); - } while(((SUCCESS == rc) || (MQTT_NOTHING_TO_READ == rc)) && (read_packet_type != packetType)); - - /* If rc is SUCCESS, we have received the expected - * MQTT packet. Otherwise rc tells the error. */ - FUNC_EXIT_RC(rc); -} - -/** - * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer, to avoid overruns - * @param packetType the message type - * @param pSerializedLength length - * @return IoT_Error_t indicating function execution status - */ -IoT_Error_t aws_iot_mqtt_internal_serialize_zero(unsigned char *pTxBuf, size_t txBufLen, MessageTypes packetType, - size_t *pSerializedLength) { - unsigned char *ptr; - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pTxBuf || NULL == pSerializedLength) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Buffer should have at least 2 bytes for the header */ - if(4 > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - ptr = pTxBuf; - - rc = aws_iot_mqtt_internal_init_header(&header, packetType, QOS0, 0, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* write header */ - aws_iot_mqtt_internal_write_char(&ptr, header.byte); - - /* write remaining length */ - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, 0); - *pSerializedLength = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_connect.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_connect.c deleted file mode 100644 index fbbfbec41..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_connect.c +++ /dev/null @@ -1,560 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_connect.c - * @brief MQTT client connect API definition and related functions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_mqtt_client_common_internal.h" - -/** @brief Connect request response codes from server */ -typedef enum { - CONNACK_CONNECTION_ACCEPTED = 0, /**< Connection accepted */ - CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1, /**< Unacceptable protocol version */ - CONNACK_IDENTIFIER_REJECTED_ERROR = 2, /**< Client identifier rejected */ - CONNACK_SERVER_UNAVAILABLE_ERROR = 3, /**< Server unavailable */ - CONNACK_BAD_USERDATA_ERROR = 4, /**< Bad username */ - CONNACK_NOT_AUTHORIZED_ERROR = 5 /**< Not authorized */ -} MQTT_Connack_Return_Codes; - -/** - * Determines the length of the MQTT connect packet that would be produced using the supplied connect options. - * @param options the options to be used to build the connect packet - * @param the length of buffer needed to contain the serialized version of the packet - * @return IoT_Error_t indicating function execution status - */ -static uint32_t _aws_iot_get_connect_packet_length(IoT_Client_Connect_Params *pConnectParams) { - uint32_t len; - /* Enable when adding further MQTT versions */ - /*size_t len = 0; - switch(pConnectParams->MQTTVersion) { - case MQTT_3_1_1: - len = 10; - break; - }*/ - FUNC_ENTRY; - - len = 10; // Len = 10 for MQTT_3_1_1 - len = len + pConnectParams->clientIDLen + 2; - - if(pConnectParams->isWillMsgPresent) { - len = len + pConnectParams->will.topicNameLen + 2 + pConnectParams->will.msgLen + 2; - } - - if(NULL != pConnectParams->pUsername) { - len = len + pConnectParams->usernameLen + 2; - } - - if(NULL != pConnectParams->pPassword) { - len = len + pConnectParams->passwordLen + 2; - } - - FUNC_EXIT_RC(len); -} - -/** - * Serializes the connect options into the buffer. - * @param buf the buffer into which the packet will be serialized - * @param len the length in bytes of the supplied buffer - * @param options the options to be used to build the connect packet - * @param serialized length - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t txBufLen, - IoT_Client_Connect_Params *pConnectParams, - size_t *pSerializedLen) { - unsigned char *ptr; - uint32_t len; - IoT_Error_t rc; - MQTTHeader header = {0}; - uint8_t flags = 0u; - - FUNC_ENTRY; - - if(NULL == pTxBuf || NULL == pConnectParams || NULL == pSerializedLen || - (NULL == pConnectParams->pClientID && 0 != pConnectParams->clientIDLen) || - (NULL != pConnectParams->pClientID && 0 == pConnectParams->clientIDLen)) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Check needed here before we start writing to the Tx buffer */ - switch(pConnectParams->MQTTVersion) { - case MQTT_3_1_1: - break; - default: - return MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR; - } - - ptr = pTxBuf; - len = _aws_iot_get_connect_packet_length(pConnectParams); - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, CONNECT, QOS0, 0, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, len); /* write remaining length */ - - // Enable if adding support for more versions - //if(MQTT_3_1_1 == pConnectParams->MQTTVersion) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, "MQTT", 4); - aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pConnectParams->MQTTVersion); - //} - - flags = 0; - if (pConnectParams->isCleanSession) - { - flags |= 1 << 1; - } - - if (pConnectParams->isWillMsgPresent) - { - flags |= 1 << 2; - flags |= (uint8_t) (pConnectParams->will.qos << 3); - flags |= (uint8_t) (pConnectParams->will.isRetained << 5); - } - - if(pConnectParams->pPassword) { - flags |= 1 << 6; - } - - if(pConnectParams->pUsername) { - flags |= 1 << 7; - } - - aws_iot_mqtt_internal_write_char(&ptr, flags); - aws_iot_mqtt_internal_write_uint_16(&ptr, pConnectParams->keepAliveIntervalInSec); - - /* If the code have passed the check for incorrect values above, no client id was passed as argument */ - if(NULL == pConnectParams->pClientID) { - aws_iot_mqtt_internal_write_uint_16(&ptr, 0); - } else { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pClientID, pConnectParams->clientIDLen); - } - - if(pConnectParams->isWillMsgPresent) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pTopicName, - pConnectParams->will.topicNameLen); - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pMessage, pConnectParams->will.msgLen); - } - - if(pConnectParams->pUsername) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pUsername, pConnectParams->usernameLen); - } - - if(pConnectParams->pPassword) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pPassword, pConnectParams->passwordLen); - } - - *pSerializedLen = (size_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Deserializes the supplied (wire) buffer into connack data - return code - * @param sessionPresent the session present flag returned (only for MQTT 3.1.1) - * @param connack_rc returned integer value of the connack return code - * @param buf the raw buffer data, of the correct length determined by the remaining length field - * @param buflen the length in bytes of the data in the supplied buffer - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_deserialize_connack(unsigned char *pSessionPresent, IoT_Error_t *pConnackRc, - unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char *curdata, *enddata; - unsigned char connack_rc_char; - uint32_t decodedLen, readBytesLen; - IoT_Error_t rc; - uint8_t flags = 0u; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - if(NULL == pSessionPresent || NULL == pConnackRc || NULL == pRxBuf) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* CONNACK header size is fixed at two bytes for fixed and 2 bytes for variable, - * using that as minimum size - * MQTT v3.1.1 Specification 3.2.1 */ - if(4 > rxBufLen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - curdata = pRxBuf; - enddata = NULL; - decodedLen = 0; - readBytesLen = 0; - - header.byte = aws_iot_mqtt_internal_read_char(&curdata); - if(CONNACK != MQTT_HEADER_FIELD_TYPE(header.byte)) { - FUNC_EXIT_RC(FAILURE); - } - - /* read remaining length */ - rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* CONNACK remaining length should always be 2 as per MQTT 3.1.1 spec */ - curdata += (readBytesLen); - enddata = curdata + decodedLen; - if(2 != (enddata - curdata)) { - FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR); - } - - flags = aws_iot_mqtt_internal_read_char(&curdata); - /* Session present is in the LSb. */ - *pSessionPresent = (flags & 0x01); - connack_rc_char = aws_iot_mqtt_internal_read_char(&curdata); - switch(connack_rc_char) { - case CONNACK_CONNECTION_ACCEPTED: - *pConnackRc = MQTT_CONNACK_CONNECTION_ACCEPTED; - break; - case CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR: - *pConnackRc = MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR; - break; - case CONNACK_IDENTIFIER_REJECTED_ERROR: - *pConnackRc = MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR; - break; - case CONNACK_SERVER_UNAVAILABLE_ERROR: - *pConnackRc = MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR; - break; - case CONNACK_BAD_USERDATA_ERROR: - *pConnackRc = MQTT_CONNACK_BAD_USERDATA_ERROR; - break; - case CONNACK_NOT_AUTHORIZED_ERROR: - *pConnackRc = MQTT_CONNACK_NOT_AUTHORIZED_ERROR; - break; - default: - *pConnackRc = MQTT_CONNACK_UNKNOWN_ERROR; - break; - } - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Check if client state is valid for a connect request - * - * Called to check if client state is valid for a connect request - * @param pClient Reference to the IoT Client - * - * @return bool true = state is valid, false = not valid - */ -static bool _aws_iot_mqtt_is_client_state_valid_for_connect(ClientState clientState) { - bool isValid = false; - - switch(clientState) { - case CLIENT_STATE_INVALID: - isValid = false; - break; - case CLIENT_STATE_INITIALIZED: - isValid = true; - break; - case CLIENT_STATE_CONNECTING: - case CLIENT_STATE_CONNECTED_IDLE: - case CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS: - case CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN: - case CLIENT_STATE_DISCONNECTING: - isValid = false; - break; - case CLIENT_STATE_DISCONNECTED_ERROR: - case CLIENT_STATE_DISCONNECTED_MANUALLY: - case CLIENT_STATE_PENDING_RECONNECT: - isValid = true; - break; - default: - break; - } - - return isValid; -} - -/** - * @brief MQTT Connection Function - * - * Called to establish an MQTT connection with the AWS IoT Service - * This is the internal function which is called by the connect API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param pConnectParams Pointer to MQTT connection parameters - * - * @return An IoT Error Type defining successful/failed connection - */ -static IoT_Error_t _aws_iot_mqtt_internal_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams) { - Timer connect_timer; - IoT_Error_t connack_rc = FAILURE; - char sessionPresent = 0; - size_t len = 0; - IoT_Error_t rc = FAILURE; - - FUNC_ENTRY; - - if(NULL != pConnectParams) { - /* override default options if new options were supplied */ - rc = aws_iot_mqtt_set_connect_params(pClient, pConnectParams); - if(SUCCESS != rc) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - } - - rc = pClient->networkStack.connect(&(pClient->networkStack), NULL); - if(SUCCESS != rc) { - /* TLS Connect failed, return error */ - FUNC_EXIT_RC(rc); - } - - init_timer(&connect_timer); - countdown_ms(&connect_timer, pClient->clientData.commandTimeoutMs); - - pClient->clientData.keepAliveInterval = pClient->clientData.options.keepAliveIntervalInSec; - rc = _aws_iot_mqtt_serialize_connect(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, - &(pClient->clientData.options), &len); - if(SUCCESS != rc || 0 >= len) { - FUNC_EXIT_RC(rc); - } - - /* send the connect packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &connect_timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* this will be a blocking call, wait for the CONNACK */ - rc = aws_iot_mqtt_internal_wait_for_read(pClient, CONNACK, &connect_timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Received CONNACK, check the return code */ - rc = _aws_iot_mqtt_deserialize_connack((unsigned char *) &sessionPresent, &connack_rc, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - if(MQTT_CONNACK_CONNECTION_ACCEPTED != connack_rc) { - FUNC_EXIT_RC(connack_rc); - } - - /* Ensure that a ping request is sent after keepAliveInterval. */ - pClient->clientStatus.isPingOutstanding = false; - countdown_sec(&pClient->pingReqTimer, pClient->clientData.keepAliveInterval); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief MQTT Connection Function - * - * Called to establish an MQTT connection with the AWS IoT Service - * This is the outer function which does the validations and calls the internal connect above - * to perform the actual operation. It is also responsible for client state changes - * - * @param pClient Reference to the IoT Client - * @param pConnectParams Pointer to MQTT connection parameters - * - * @return An IoT Error Type defining successful/failed connection - */ -IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams) { - IoT_Error_t rc, disconRc; - ClientState clientState; - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - aws_iot_mqtt_internal_flushBuffers( pClient ); - clientState = aws_iot_mqtt_get_client_state(pClient); - - if(false == _aws_iot_mqtt_is_client_state_valid_for_connect(clientState)) { - /* Don't send connect packet again if we are already connected - * or in the process of connecting/disconnecting */ - FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR); - } - - aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTING); - - rc = _aws_iot_mqtt_internal_connect(pClient, pConnectParams); - - if(SUCCESS != rc) { - pClient->networkStack.disconnect(&(pClient->networkStack)); - disconRc = pClient->networkStack.destroy(&(pClient->networkStack)); - if (SUCCESS != disconRc) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_DISCONNECTED_ERROR); - } else { - aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_CONNECTED_IDLE); - } - - FUNC_EXIT_RC(rc); -} - -/** - * @brief Disconnect an MQTT Connection - * - * Called to send a disconnect message to the broker. - * This is the internal function which is called by the disconnect API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed send of the disconnect control packet. - */ -static IoT_Error_t _aws_iot_mqtt_internal_disconnect(AWS_IoT_Client *pClient) { - /* We might wait for incomplete incoming publishes to complete */ - Timer timer; - size_t serialized_len = 0; - IoT_Error_t rc; - - FUNC_ENTRY; - - rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, - DISCONNECT, - &serialized_len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - /* send the disconnect packet */ - if(serialized_len > 0) { - (void)aws_iot_mqtt_internal_send_packet(pClient, serialized_len, &timer); - } - - /* Clean network stack */ - pClient->networkStack.disconnect(&(pClient->networkStack)); - rc = pClient->networkStack.destroy(&(pClient->networkStack)); - if(SUCCESS != rc) { - /* TLS Destroy failed, return error */ - FUNC_EXIT_RC(FAILURE); - } - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient) { - ClientState clientState; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(!aws_iot_mqtt_is_client_connected(pClient)) { - /* Network is already disconnected. Do nothing */ - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_DISCONNECTING); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = _aws_iot_mqtt_internal_disconnect(pClient); - - if(SUCCESS != rc) { - pClient->clientStatus.clientState = clientState; - } else { - /* If called from Keepalive, this gets set to CLIENT_STATE_DISCONNECTED_ERROR */ - pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_MANUALLY; - } - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_mqtt_attempt_reconnect(AWS_IoT_Client *pClient) { - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* Only attempt a connect if not already connected. */ - if(!aws_iot_mqtt_is_client_connected(pClient)) { - /* Ignoring return code. failures expected if network is disconnected */ - aws_iot_mqtt_connect(pClient, NULL); - - /* If still disconnected handle disconnect */ - if(CLIENT_STATE_CONNECTED_IDLE != aws_iot_mqtt_get_client_state(pClient)) { - aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_DISCONNECTED_ERROR, CLIENT_STATE_PENDING_RECONNECT); - FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT); - } - } - else { - /* If already connected and no subscribe operation pending, then return - already connected error. */ - if(CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS != aws_iot_mqtt_get_client_state(pClient)) { - FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR); - } - } - - rc = aws_iot_mqtt_resubscribe(pClient); - if(SUCCESS != rc) { - FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT); - } - - FUNC_EXIT_RC(NETWORK_RECONNECTED); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_publish.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_publish.c deleted file mode 100644 index 61822ad4a..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_publish.c +++ /dev/null @@ -1,411 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144 - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_publish.c - * @brief MQTT client publish API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * @param stringVar pointer to the String into which the data is to be read - * @param stringLen pointer to variable which has the length of the string - * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned - * @param enddata pointer to the end of the data: do not read beyond - * @return SUCCESS if successful, FAILURE if not - */ -static IoT_Error_t _aws_iot_mqtt_read_string_with_len(char **stringVar, uint16_t *stringLen, - unsigned char **pptr, unsigned char *enddata) { - IoT_Error_t rc = FAILURE; - - FUNC_ENTRY; - /* the first two bytes are the length of the string */ - /* enough length to read the integer? */ - if(enddata - (*pptr) > 1) { - *stringLen = aws_iot_mqtt_internal_read_uint16_t(pptr); /* increments pptr to point past length */ - if(&(*pptr)[*stringLen] <= enddata) { - *stringVar = (char *) *pptr; - *pptr += *stringLen; - rc = SUCCESS; - } - } - - FUNC_EXIT_RC(rc); -} - -/** - * Serializes the supplied publish data into the supplied buffer, ready for sending - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer - * @param dup uint8_t - the MQTT dup flag - * @param qos QoS - the MQTT QoS value - * @param retained uint8_t - the MQTT retained flag - * @param packetId uint16_t - the MQTT packet identifier - * @param pTopicName char * - the MQTT topic in the publish - * @param topicNameLen uint16_t - the length of the Topic Name - * @param pPayload byte buffer - the MQTT publish payload - * @param payloadLen size_t - the length of the MQTT payload - * @param pSerializedLen uint32_t - pointer to the variable that stores serialized len - * - * @return An IoT Error Type defining successful/failed call - */ -static IoT_Error_t _aws_iot_mqtt_internal_serialize_publish(unsigned char *pTxBuf, size_t txBufLen, uint8_t dup, - QoS qos, uint8_t retained, uint16_t packetId, - const char *pTopicName, uint16_t topicNameLen, - const unsigned char *pPayload, size_t payloadLen, - uint32_t *pSerializedLen) { - unsigned char *ptr; - uint32_t rem_len; - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pTxBuf || NULL == pPayload || NULL == pSerializedLen) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - ptr = pTxBuf; - rem_len = 0; - - rem_len += (uint32_t) (topicNameLen + payloadLen + 2); - if(qos > 0) { - rem_len += 2; /* packetId */ - } - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, PUBLISH, qos, dup, retained); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); /* write remaining length */; - - aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicName, topicNameLen); - - if(qos > 0) { - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - } - - memcpy(ptr, pPayload, payloadLen); - ptr += payloadLen; - - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Serializes the ack packet into the supplied buffer. - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer - * @param msgType the MQTT packet type - * @param dup the MQTT dup flag - * @param packetId the MQTT packet identifier - * @param pSerializedLen uint32_t - pointer to the variable that stores serialized len - * - * @return An IoT Error Type defining successful/failed call - */ -IoT_Error_t aws_iot_mqtt_internal_serialize_ack(unsigned char *pTxBuf, size_t txBufLen, - MessageTypes msgType, uint8_t dup, uint16_t packetId, - uint32_t *pSerializedLen) { - unsigned char *ptr; - QoS requestQoS; - IoT_Error_t rc; - MQTTHeader header = {0}; - FUNC_ENTRY; - if(NULL == pTxBuf || pSerializedLen == NULL) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - ptr = pTxBuf; - - /* Minimum byte length required by ACK headers is - * 2 for fixed and 2 for variable part */ - if(4 > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - requestQoS = (PUBREL == msgType) ? QOS1 : QOS0; - rc = aws_iot_mqtt_internal_init_header(&header, msgType, requestQoS, dup, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, 2); /* write remaining length */ - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Publish an MQTT message on a topic - * - * Called to publish an MQTT message on a topic. - * @note Call is blocking. In the case of a QoS 0 message the function returns - * after the message was successfully passed to the TLS layer. In the case of QoS 1 - * the function returns after the receipt of the PUBACK control packet. - * This is the internal function which is called by the publish API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * @param pParams Pointer to Publish Message parameters - * - * @return An IoT Error Type defining successful/failed publish - */ -static IoT_Error_t _aws_iot_mqtt_internal_publish(AWS_IoT_Client *pClient, const char *pTopicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *pParams) { - Timer timer; - uint32_t len = 0; - uint16_t packet_id; - unsigned char dup, type; - IoT_Error_t rc; - - FUNC_ENTRY; - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - if(QOS1 == pParams->qos) { - pParams->id = aws_iot_mqtt_get_next_packet_id(pClient); - } - - rc = _aws_iot_mqtt_internal_serialize_publish(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - pParams->qos, pParams->isRetained, pParams->id, pTopicName, - topicNameLen, (unsigned char *) pParams->payload, - pParams->payloadLen, &len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the publish packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Wait for ack if QoS1 */ - if(QOS1 == pParams->qos) { - rc = aws_iot_mqtt_internal_wait_for_read(pClient, PUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = aws_iot_mqtt_internal_deserialize_ack(&type, &dup, &packet_id, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - } - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *pParams) { - IoT_Error_t rc, pubRc; - ClientState clientState; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pTopicName || 0 == topicNameLen || NULL == pParams) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { - FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - pubRc = _aws_iot_mqtt_internal_publish(pClient, pTopicName, topicNameLen, pParams); - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS, clientState); - if(SUCCESS == pubRc && SUCCESS != rc) { - pubRc = rc; - } - - FUNC_EXIT_RC(pubRc); -} - -/** - * Deserializes the supplied (wire) buffer into publish data - * @param dup returned uint8_t - the MQTT dup flag - * @param qos returned QoS type - the MQTT QoS value - * @param retained returned uint8_t - the MQTT retained flag - * @param pPacketId returned uint16_t - the MQTT packet identifier - * @param pTopicName returned String - the MQTT topic in the publish - * @param topicNameLen returned uint16_t - the length of the MQTT topic in the publish - * @param payload returned byte buffer - the MQTT publish payload - * @param payloadLen returned size_t - the length of the MQTT payload - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBufLen the length in bytes of the data in the supplied buffer - * - * @return An IoT Error Type defining successful/failed call - */ -IoT_Error_t aws_iot_mqtt_internal_deserialize_publish(uint8_t *dup, QoS *qos, - uint8_t *retained, uint16_t *pPacketId, - char **pTopicName, uint16_t *topicNameLen, - unsigned char **payload, size_t *payloadLen, - unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char *curData = pRxBuf; - unsigned char *endData = NULL; - IoT_Error_t rc = FAILURE; - uint32_t decodedLen = 0; - uint32_t readBytesLen = 0; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - if(NULL == dup || NULL == qos || NULL == retained || NULL == pPacketId) { - FUNC_EXIT_RC(FAILURE); - } - - /* Publish header size is at least four bytes. - * Fixed header is two bytes. - * Variable header size depends on QoS And Topic Name. - * QoS level 0 doesn't have a message identifier (0 - 2 bytes) - * Topic Name length fields decide size of topic name field (at least 2 bytes) - * MQTT v3.1.1 Specification 3.3.1 */ - if(4 > rxBufLen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - header.byte = aws_iot_mqtt_internal_read_char(&curData); - if(PUBLISH != MQTT_HEADER_FIELD_TYPE(header.byte)) { - FUNC_EXIT_RC(FAILURE); - } - - *dup = MQTT_HEADER_FIELD_DUP(header.byte); - *qos = (QoS) MQTT_HEADER_FIELD_QOS(header.byte); - *retained = MQTT_HEADER_FIELD_RETAIN(header.byte); - - /* read remaining length */ - rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curData, &decodedLen, &readBytesLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - curData += (readBytesLen); - endData = curData + decodedLen; - - /* do we have enough data to read the protocol version byte? */ - if(SUCCESS != _aws_iot_mqtt_read_string_with_len(pTopicName, topicNameLen, &curData, endData) - || (0 > (endData - curData))) { - FUNC_EXIT_RC(FAILURE); - } - - if(QOS0 != *qos) { - *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curData); - } - - *payloadLen = (size_t) (endData - curData); - *payload = curData; - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Deserializes the supplied (wire) buffer into an ack - * @param pPacketType returned integer - the MQTT packet type - * @param dup returned integer - the MQTT dup flag - * @param pPacketId returned integer - the MQTT packet identifier - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBuflen the length in bytes of the data in the supplied buffer - * - * @return An IoT Error Type defining successful/failed call - */ -IoT_Error_t aws_iot_mqtt_internal_deserialize_ack(unsigned char *pPacketType, unsigned char *dup, - uint16_t *pPacketId, unsigned char *pRxBuf, - size_t rxBuflen) { - IoT_Error_t rc = FAILURE; - unsigned char *curdata = pRxBuf; - unsigned char *enddata = NULL; - uint32_t decodedLen = 0; - uint32_t readBytesLen = 0; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - if(NULL == pPacketType || NULL == dup || NULL == pPacketId || NULL == pRxBuf) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - /* PUBACK fixed header size is two bytes, variable header is 2 bytes, MQTT v3.1.1 Specification 3.4.1 */ - if(4 > rxBuflen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - - header.byte = aws_iot_mqtt_internal_read_char(&curdata); - *dup = MQTT_HEADER_FIELD_DUP(header.byte); - *pPacketType = MQTT_HEADER_FIELD_TYPE(header.byte); - - /* read remaining length */ - rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - curdata += (readBytesLen); - enddata = curdata + decodedLen; - - if(enddata - curdata < 2) { - FUNC_EXIT_RC(FAILURE); - } - - *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curdata); - - FUNC_EXIT_RC(SUCCESS); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_subscribe.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_subscribe.c deleted file mode 100644 index 00e091709..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_subscribe.c +++ /dev/null @@ -1,435 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_subscribe.c - * @brief MQTT client subscribe API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * Serializes the supplied subscribe data into the supplied buffer, ready for sending - * @param pTxBuf the buffer into which the packet will be serialized - * @param txBufLen the length in bytes of the supplied buffer - * @param dup unsigned char - the MQTT dup flag - * @param packetId uint16_t - the MQTT packet identifier - * @param topicCount - number of members in the topicFilters and reqQos arrays - * @param pTopicNameList - array of topic filter names - * @param pTopicNameLenList - array of length of topic filter names - * @param pRequestedQoSs - array of requested QoS - * @param pSerializedLen - the length of the serialized data - * - * @return An IoT Error Type defining successful/failed operation - */ -static IoT_Error_t _aws_iot_mqtt_serialize_subscribe(unsigned char *pTxBuf, size_t txBufLen, - unsigned char dup, uint16_t packetId, uint32_t topicCount, - const char **pTopicNameList, uint16_t *pTopicNameLenList, - QoS *pRequestedQoSs, uint32_t *pSerializedLen) { - unsigned char *ptr; - uint32_t itr, rem_len; - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pTxBuf || NULL == pSerializedLen) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - ptr = pTxBuf; - rem_len = 2; /* packetId */ - - for(itr = 0; itr < topicCount; ++itr) { - rem_len += (uint32_t) (pTopicNameLenList[itr] + 2 + 1); /* topic + length + req_qos */ - } - - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, SUBSCRIBE, QOS1, dup, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - /* write header */ - aws_iot_mqtt_internal_write_char(&ptr, header.byte); - - /* write remaining length */ - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); - - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - - for(itr = 0; itr < topicCount; ++itr) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicNameList[itr], pTopicNameLenList[itr]); - aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pRequestedQoSs[itr]); - } - - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * Deserializes the supplied (wire) buffer into suback data - * @param pPacketId returned integer - the MQTT packet identifier - * @param maxExpectedQoSCount - the maximum number of members allowed in the grantedQoSs array - * @param pGrantedQoSCount returned uint32_t - number of members in the grantedQoSs array - * @param pGrantedQoSs returned array of QoS type - the granted qualities of service - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBufLen the length in bytes of the data in the supplied buffer - * - * @return An IoT Error Type defining successful/failed operation - */ -static IoT_Error_t _aws_iot_mqtt_deserialize_suback(uint16_t *pPacketId, uint32_t maxExpectedQoSCount, - uint32_t *pGrantedQoSCount, QoS *pGrantedQoSs, - unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char *curData, *endData; - uint32_t decodedLen, readBytesLen; - IoT_Error_t decodeRc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - if(NULL == pPacketId || NULL == pGrantedQoSCount || NULL == pGrantedQoSs) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - curData = pRxBuf; - endData = NULL; - decodeRc = FAILURE; - decodedLen = 0; - readBytesLen = 0; - - /* SUBACK header size is 4 bytes for header and at least one byte for QoS payload - * Need at least a 5 bytes buffer. MQTT3.1.1 specification 3.9 - */ - if(5 > rxBufLen) { - FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR); - } - - header.byte = aws_iot_mqtt_internal_read_char(&curData); - if(SUBACK != MQTT_HEADER_FIELD_TYPE(header.byte)) { - FUNC_EXIT_RC(FAILURE); - } - - /* read remaining length */ - decodeRc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curData, &decodedLen, &readBytesLen); - if(SUCCESS != decodeRc) { - FUNC_EXIT_RC(decodeRc); - } - - curData += (readBytesLen); - endData = curData + decodedLen; - if(endData - curData < 2) { - FUNC_EXIT_RC(FAILURE); - } - - *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curData); - - *pGrantedQoSCount = 0; - while(curData < endData) { - if(*pGrantedQoSCount > maxExpectedQoSCount) { - FUNC_EXIT_RC(FAILURE); - } - pGrantedQoSs[(*pGrantedQoSCount)++] = (QoS) aws_iot_mqtt_internal_read_char(&curData); - } - - FUNC_EXIT_RC(SUCCESS); -} - -/* Returns MAX_MESSAGE_HANDLERS value if no free index is available */ -static uint32_t _aws_iot_mqtt_get_free_message_handler_index(AWS_IoT_Client *pClient) { - uint32_t itr; - - FUNC_ENTRY; - - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; itr++) { - if(pClient->clientData.messageHandlers[itr].topicName == NULL) { - break; - } - } - - FUNC_EXIT_RC(itr); -} - -/** - * @brief Subscribe to an MQTT topic. - * - * Called to send a subscribe message to the broker requesting a subscription - * to an MQTT topic. This is the internal function which is called by the - * subscribe API to perform the operation. Not meant to be called directly as - * it doesn't do validations or client state changes - * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. - * @warning pTopicName and pApplicationHandlerData need to be static in memory. - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to. pTopicName needs to be static in memory since - * no malloc are performed by the SDK - * @param topicNameLen Length of the topic name - * @param pApplicationHandler_t Reference to the handler function for this subscription - * @param pApplicationHandlerData Point to data passed to the callback. - * pApplicationHandlerData also needs to be static in memory since no malloc are performed by the SDK - * - * @return An IoT Error Type defining successful/failed subscription - */ -static IoT_Error_t _aws_iot_mqtt_internal_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, - uint16_t topicNameLen, QoS qos, - pApplicationHandler_t pApplicationHandler, - void *pApplicationHandlerData) { - uint16_t txPacketId, rxPacketId; - uint32_t serializedLen, indexOfFreeMessageHandler, count; - IoT_Error_t rc; - Timer timer; - QoS grantedQoS[3] = {QOS0, QOS0, QOS0}; - - FUNC_ENTRY; - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - serializedLen = 0; - count = 0; - txPacketId = aws_iot_mqtt_get_next_packet_id(pClient); - rxPacketId = 0; - - rc = _aws_iot_mqtt_serialize_subscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - txPacketId, 1, &pTopicName, &topicNameLen, &qos, &serializedLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - indexOfFreeMessageHandler = _aws_iot_mqtt_get_free_message_handler_index(pClient); - if(AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS <= indexOfFreeMessageHandler) { - FUNC_EXIT_RC(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR); - } - - /* send the subscribe packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, serializedLen, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* wait for suback */ - rc = aws_iot_mqtt_internal_wait_for_read(pClient, SUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Granted QoS can be 0, 1 or 2 */ - rc = _aws_iot_mqtt_deserialize_suback(&rxPacketId, 1, &count, grantedQoS, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* TODO : Figure out how to test this before activating this check */ - //if(txPacketId != rxPacketId) { - /* Different SUBACK received than expected. Return error - * This can cause issues if the request timeout value is too small */ - // return RX_MESSAGE_INVALID_ERROR; - //} - - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].topicName = - pTopicName; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].topicNameLen = - topicNameLen; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].pApplicationHandler = - pApplicationHandler; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].pApplicationHandlerData = - pApplicationHandlerData; - pClient->clientData.messageHandlers[indexOfFreeMessageHandler].qos = qos; - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, - QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData) { - ClientState clientState; - IoT_Error_t rc, subRc; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pTopicName || NULL == pApplicationHandler) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { - FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - subRc = _aws_iot_mqtt_internal_subscribe(pClient, pTopicName, topicNameLen, qos, - pApplicationHandler, pApplicationHandlerData); - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS, clientState); - if(SUCCESS == subRc && SUCCESS != rc) { - subRc = rc; - } - - FUNC_EXIT_RC(subRc); -} - -/** - * @brief Subscribe to an MQTT topic. - * - * Called to send a subscribe message to the broker requesting a subscription - * to an MQTT topic. - * This is the internal function which is called by the resubscribe API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. - * - * @param pClient Reference to the IoT Client - * - * @return An IoT Error Type defining successful/failed subscription - */ -static IoT_Error_t _aws_iot_mqtt_internal_resubscribe(AWS_IoT_Client *pClient) { - uint16_t packetId; - uint32_t len, count, existingSubCount, itr; - IoT_Error_t rc; - Timer timer; - QoS grantedQoS[3] = {QOS0, QOS0, QOS0}; - - FUNC_ENTRY; - - packetId = 0; - len = 0; - count = 0; - existingSubCount = _aws_iot_mqtt_get_free_message_handler_index(pClient); - - for(itr = 0; itr < existingSubCount; itr++) { - if(pClient->clientData.messageHandlers[itr].topicName == NULL) { - continue; - } - - /* Do not attempt to subscribe to topics which have already been subscribed - to in the previous re-subscribe attempts. */ - if(pClient->clientData.messageHandlers[itr].resubscribed == 1) { - continue; - } - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - rc = _aws_iot_mqtt_serialize_subscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - aws_iot_mqtt_get_next_packet_id(pClient), 1, - &(pClient->clientData.messageHandlers[itr].topicName), - &(pClient->clientData.messageHandlers[itr].topicNameLen), - &(pClient->clientData.messageHandlers[itr].qos), &len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the subscribe packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, len, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* wait for suback */ - rc = aws_iot_mqtt_internal_wait_for_read(pClient, SUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Granted QoS can be 0, 1 or 2 */ - rc = _aws_iot_mqtt_deserialize_suback(&packetId, 1, &count, grantedQoS, pClient->clientData.readBuf, - pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Record that this topic has been subscribed to, so that we do not - * attempt to subscribe again to the same topic. */ - pClient->clientData.messageHandlers[itr].resubscribed = 1; - } - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_resubscribe(AWS_IoT_Client *pClient) { - IoT_Error_t rc, resubRc; - ClientState currentState = aws_iot_mqtt_get_client_state(pClient); - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(false == aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - /* At this point, the client state should be either CLIENT_STATE_CONNECTED_IDLE - or CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS. The former means that it - is the first re-subscribe attempt while the latter means that it is second - or subsequent re-subscribe attempt. */ - if((CLIENT_STATE_CONNECTED_IDLE != currentState) && (CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS != currentState)) { - FUNC_EXIT_RC(MQTT_UNEXPECTED_CLIENT_STATE_ERROR); - } - - /* If it is the first re-subscribe attempt (i.e. client state is CLIENT_STATE_CONNECTED_IDLE), - set the client state to CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS. */ - if(CLIENT_STATE_CONNECTED_IDLE == currentState) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - } - - resubRc = _aws_iot_mqtt_internal_resubscribe(pClient); - - /* It is possible that the subscribe operation fails, do not change the state - in that case so that the subscribe is attempted again in the next iteration - of yield. */ - if(SUCCESS == resubRc) { - resubRc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS, CLIENT_STATE_CONNECTED_IDLE); - } - - FUNC_EXIT_RC(resubRc); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_unsubscribe.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_unsubscribe.c deleted file mode 100644 index 1d78a7477..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_unsubscribe.c +++ /dev/null @@ -1,234 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_unsubscribe.c - * @brief MQTT client unsubscribe API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending - * @param pTxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param txBufLen the length in bytes of the data in the supplied buffer - * @param dup integer - the MQTT dup flag - * @param packetId integer - the MQTT packet identifier - * @param count - number of members in the topicFilters array - * @param pTopicNameList - array of topic filter names - * @param pTopicNameLenList - array of length of topic filter names in pTopicNameList - * @param pSerializedLen - the length of the serialized data - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_serialize_unsubscribe(unsigned char *pTxBuf, size_t txBufLen, - uint8_t dup, uint16_t packetId, - uint32_t count, const char **pTopicNameList, - uint16_t *pTopicNameLenList, uint32_t *pSerializedLen) { - unsigned char *ptr = pTxBuf; - uint32_t i = 0; - uint32_t rem_len = 2; /* packetId */ - IoT_Error_t rc; - MQTTHeader header = {0}; - - FUNC_ENTRY; - - for(i = 0; i < count; ++i) { - rem_len += (uint32_t) (pTopicNameLenList[i] + 2); /* topic + length */ - } - - if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) { - FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); - } - - rc = aws_iot_mqtt_internal_init_header(&header, UNSUBSCRIBE, QOS1, dup, 0); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ - - ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); /* write remaining length */ - - aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); - - for(i = 0; i < count; ++i) { - aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicNameList[i], pTopicNameLenList[i]); - } - - *pSerializedLen = (uint32_t) (ptr - pTxBuf); - - FUNC_EXIT_RC(SUCCESS); -} - - -/** - * Deserializes the supplied (wire) buffer into unsuback data - * @param pPacketId returned integer - the MQTT packet identifier - * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field - * @param rxBufLen the length in bytes of the data in the supplied buffer - * @return IoT_Error_t indicating function execution status - */ -static IoT_Error_t _aws_iot_mqtt_deserialize_unsuback(uint16_t *pPacketId, unsigned char *pRxBuf, size_t rxBufLen) { - unsigned char type = 0; - unsigned char dup = 0; - IoT_Error_t rc; - - FUNC_ENTRY; - - rc = aws_iot_mqtt_internal_deserialize_ack(&type, &dup, pPacketId, pRxBuf, rxBufLen); - if(SUCCESS == rc && UNSUBACK != type) { - rc = FAILURE; - } - - FUNC_EXIT_RC(rc); -} - -/** - * @brief Unsubscribe to an MQTT topic. - * - * Called to send an unsubscribe message to the broker requesting removal of a subscription - * to an MQTT topic. - * @note Call is blocking. The call returns after the receipt of the UNSUBACK control packet. - * This is the internal function which is called by the unsubscribe API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param pTopicName Topic Name to publish to - * @param topicNameLen Length of the topic name - * - * @return An IoT Error Type defining successful/failed unsubscribe call - */ -static IoT_Error_t _aws_iot_mqtt_internal_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, - uint16_t topicFilterLen) { - /* No NULL checks because this is a static internal function */ - - Timer timer; - - uint16_t packet_id; - uint32_t serializedLen = 0; - uint32_t i = 0; - IoT_Error_t rc; - bool subscriptionExists = false; - - FUNC_ENTRY; - - /* Remove from message handler array */ - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { - if(pClient->clientData.messageHandlers[i].topicName != NULL && - (strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) { - subscriptionExists = true; - break; - } - } - - if(false == subscriptionExists) { - FUNC_EXIT_RC(FAILURE); - } - - init_timer(&timer); - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - - rc = _aws_iot_mqtt_serialize_unsubscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, - aws_iot_mqtt_get_next_packet_id(pClient), 1, &pTopicFilter, - &topicFilterLen, &serializedLen); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the unsubscribe packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, serializedLen, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = aws_iot_mqtt_internal_wait_for_read(pClient, UNSUBACK, &timer); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = _aws_iot_mqtt_deserialize_unsuback(&packet_id, pClient->clientData.readBuf, pClient->clientData.readBufSize); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* Remove from message handler array */ - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { - if(pClient->clientData.messageHandlers[i].topicName != NULL && - (strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) { - pClient->clientData.messageHandlers[i].topicName = NULL; - /* We don't want to break here, in case the same topic is registered - * with 2 callbacks. Unlikely scenario */ - } - } - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen) { - IoT_Error_t rc, unsubRc; - ClientState clientState; - - if(NULL == pClient || NULL == pTopicFilter) { - return NULL_VALUE_ERROR; - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - return NETWORK_DISCONNECTED_ERROR; - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { - return MQTT_CLIENT_NOT_IDLE_ERROR; - } - - rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS); - if(SUCCESS != rc) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState); - return rc; - } - - unsubRc = _aws_iot_mqtt_internal_unsubscribe(pClient, pTopicFilter, topicFilterLen); - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState); - if(SUCCESS == unsubRc && SUCCESS != rc) { - unsubRc = rc; - } - - return unsubRc; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_yield.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_yield.c deleted file mode 100644 index 25a46cbfe..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_mqtt_client_yield.c +++ /dev/null @@ -1,325 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -// Based on Eclipse Paho. -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file aws_iot_mqtt_client_yield.c - * @brief MQTT client yield API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_mqtt_client_common_internal.h" - -/** - * This is for the case when the aws_iot_mqtt_internal_send_packet Fails. - */ -static void _aws_iot_mqtt_force_client_disconnect(AWS_IoT_Client *pClient) { - pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_ERROR; - pClient->networkStack.disconnect(&(pClient->networkStack)); - pClient->networkStack.destroy(&(pClient->networkStack)); -} - -static IoT_Error_t _aws_iot_mqtt_handle_disconnect(AWS_IoT_Client *pClient) { - IoT_Error_t rc; - - FUNC_ENTRY; - - rc = aws_iot_mqtt_disconnect(pClient); - if(rc != SUCCESS) { - // If the aws_iot_mqtt_internal_send_packet prevents us from sending a disconnect packet then we have to clean the stack - _aws_iot_mqtt_force_client_disconnect(pClient); - } - - pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_ERROR; - - if(NULL != pClient->clientData.disconnectHandler) { - pClient->clientData.disconnectHandler(pClient, pClient->clientData.disconnectHandlerData); - } - - if (pClient->clientStatus.clientState == CLIENT_STATE_CONNECTED_IDLE) { - FUNC_EXIT_RC(SUCCESS); - } - - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); -} - - -static IoT_Error_t _aws_iot_mqtt_handle_reconnect(AWS_IoT_Client *pClient) { - IoT_Error_t rc; - - FUNC_ENTRY; - - if(!has_timer_expired(&(pClient->reconnectDelayTimer))) { - /* Timer has not expired. Not time to attempt reconnect yet. - * Return attempting reconnect */ - FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT); - } - - rc = NETWORK_PHYSICAL_LAYER_DISCONNECTED; - if(NULL != pClient->networkStack.isConnected) { - rc = pClient->networkStack.isConnected(&(pClient->networkStack)); - } - - if(NETWORK_PHYSICAL_LAYER_CONNECTED == rc) { - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, - CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - FUNC_EXIT_RC(NETWORK_RECONNECTED); - } - } - - pClient->clientData.currentReconnectWaitInterval *= 2; - - if(AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL < pClient->clientData.currentReconnectWaitInterval) { - FUNC_EXIT_RC(NETWORK_RECONNECT_TIMED_OUT_ERROR); - } - countdown_ms(&(pClient->reconnectDelayTimer), pClient->clientData.currentReconnectWaitInterval); - FUNC_EXIT_RC(rc); -} - -static IoT_Error_t _aws_iot_mqtt_keep_alive(AWS_IoT_Client *pClient) { - IoT_Error_t rc = SUCCESS; - Timer timer; - size_t serialized_len; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(0 == pClient->clientData.keepAliveInterval) { - FUNC_EXIT_RC(SUCCESS); - } - - if(pClient->clientStatus.isPingOutstanding) { - /* We are waiting for a PINGRESP from the broker. If the pingRespTimer, - * has expired, it indicates that the transport layer connection is - * lost and therefore, we initiate MQTT disconnect (which will triggger) - * the re-connect workflow, if enabled. If the pingRespTimer is not - * expired, there is nothing to do and we continue waiting for PINGRESP. */ - if(has_timer_expired(&pClient->pingRespTimer)) { - rc = _aws_iot_mqtt_handle_disconnect(pClient); - FUNC_EXIT_RC(rc); - } else { - FUNC_EXIT_RC(SUCCESS); - } - } else { - /* We are not waiting for a PINGRESP from the broker. If the - * pingReqTimer has expired, we send a PINGREQ. Otherwise, there is - * nothing to do. */ - if(!has_timer_expired(&pClient->pingReqTimer)) { - FUNC_EXIT_RC(SUCCESS); - } - } - - - /* there is no ping outstanding - send one */ - init_timer(&timer); - - countdown_ms(&timer, pClient->clientData.commandTimeoutMs); - serialized_len = 0; - rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, - PINGREQ, &serialized_len); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - /* send the ping packet */ - rc = aws_iot_mqtt_internal_send_packet(pClient, serialized_len, &timer); - if(SUCCESS != rc) { - //If sending a PING fails we can no longer determine if we are connected. In this case we decide we are disconnected and begin reconnection attempts - rc = _aws_iot_mqtt_handle_disconnect(pClient); - FUNC_EXIT_RC(rc); - } - - pClient->clientStatus.isPingOutstanding = true; - /* Start a timer to wait for PINGRESP from server. */ - countdown_sec(&pClient->pingRespTimer, pClient->clientData.keepAliveInterval); - /* Start a timer to keep track of when to send the next PINGREQ. */ - countdown_sec(&pClient->pingReqTimer, pClient->clientData.keepAliveInterval); - - FUNC_EXIT_RC(SUCCESS); -} - -/** - * @brief Yield to the MQTT client - * - * Called to yield the current thread to the underlying MQTT client. This time is used by - * the MQTT client to manage PING requests to monitor the health of the TCP connection as - * well as periodically check the socket receive buffer for subscribe messages. Yield() - * must be called at a rate faster than the keepalive interval. It must also be called - * at a rate faster than the incoming message rate as this is the only way the client receives - * processing time to manage incoming messages. - * This is the internal function which is called by the yield API to perform the operation. - * Not meant to be called directly as it doesn't do validations or client state changes - * - * @param pClient Reference to the IoT Client - * @param timeout_ms Maximum number of milliseconds to pass thread execution to the client. - * - * @return An IoT Error Type defining successful/failed client processing. - * If this call results in an error it is likely the MQTT connection has dropped. - * iot_is_mqtt_connected can be called to confirm. - */ - -static IoT_Error_t _aws_iot_mqtt_internal_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms) { - IoT_Error_t yieldRc = SUCCESS; - int itr = 0; - - uint8_t packet_type; - ClientState clientState; - Timer timer; - init_timer(&timer); - countdown_ms(&timer, timeout_ms); - - FUNC_ENTRY; - - // evaluate timeout at the end of the loop to make sure the actual yield runs at least once - do { - clientState = aws_iot_mqtt_get_client_state(pClient); - - /* If the client state is pending reconnect or resubscribe in progress, - we keep retrying _aws_iot_mqtt_handle_reconnect. This function only - attempts to connect if not already connected thereby ensuring that the - subsequent invocations only attempt remaining subscribes. */ - if((CLIENT_STATE_PENDING_RECONNECT == clientState) || - (CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS == clientState)) { - if(AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL < pClient->clientData.currentReconnectWaitInterval) { - yieldRc = NETWORK_RECONNECT_TIMED_OUT_ERROR; - break; - } - yieldRc = _aws_iot_mqtt_handle_reconnect(pClient); - /* Network reconnect attempted, check if yield timer expired before - * doing anything else */ - continue; - } - - yieldRc = aws_iot_mqtt_internal_cycle_read(pClient, &timer, &packet_type); - if(SUCCESS == yieldRc) { - yieldRc = _aws_iot_mqtt_keep_alive(pClient); - } else { - // SSL read and write errors are terminal, connection must be closed and retried - if(NETWORK_SSL_READ_ERROR == yieldRc || NETWORK_SSL_WRITE_ERROR == yieldRc || NETWORK_SSL_WRITE_TIMEOUT_ERROR == yieldRc) { - yieldRc = _aws_iot_mqtt_handle_disconnect(pClient); - } - } - - if(NETWORK_DISCONNECTED_ERROR == yieldRc) { - pClient->clientData.counterNetworkDisconnected++; - /* Always clear resubscribe flags. */ - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; itr++) { - pClient->clientData.messageHandlers[itr].resubscribed = 0; - } - - if(1 == pClient->clientStatus.isAutoReconnectEnabled) { - yieldRc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_DISCONNECTED_ERROR, - CLIENT_STATE_PENDING_RECONNECT); - if(SUCCESS != yieldRc) { - FUNC_EXIT_RC(yieldRc); - } - - pClient->clientData.currentReconnectWaitInterval = AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL; - countdown_ms(&(pClient->reconnectDelayTimer), pClient->clientData.currentReconnectWaitInterval); - - /* Depending on timer values, it is possible that yield timer has expired - * Set to rc to attempting reconnect to inform client that autoreconnect - * attempt has started */ - yieldRc = NETWORK_ATTEMPTING_RECONNECT; - } else { - break; - } - } else if(SUCCESS != yieldRc) { - break; - } - } while(!has_timer_expired(&timer)); - - FUNC_EXIT_RC(yieldRc); -} - -IoT_Error_t aws_iot_mqtt_yield(AWS_IoT_Client *pClient, uint32_t timeout_ms) { - IoT_Error_t rc, yieldRc; - ClientState clientState; - - if(NULL == pClient || 0 == timeout_ms) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - clientState = aws_iot_mqtt_get_client_state(pClient); - /* Check if network was manually disconnected */ - if(CLIENT_STATE_DISCONNECTED_MANUALLY == clientState) { - FUNC_EXIT_RC(NETWORK_MANUALLY_DISCONNECTED); - } - - /* If we are in the pending reconnect or resubscribe in progress state, skip other checks. - * Pending reconnect or resubscribe in progress state is only set when auto-reconnect - * is enabled */ - if((CLIENT_STATE_PENDING_RECONNECT != clientState) && - (CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS != clientState)) { - /* Check if network is disconnected and auto-reconnect is not enabled */ - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); - } - - /* Check if client is idle, if not another operation is in progress and we should return */ - if(CLIENT_STATE_CONNECTED_IDLE != clientState) { - FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); - } - - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, - CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - } - - yieldRc = _aws_iot_mqtt_internal_yield(pClient, timeout_ms); - - if(NETWORK_DISCONNECTED_ERROR != yieldRc && NETWORK_ATTEMPTING_RECONNECT != yieldRc) { - rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS, - CLIENT_STATE_CONNECTED_IDLE); - if(SUCCESS == yieldRc && SUCCESS != rc) { - yieldRc = rc; - } - } - - FUNC_EXIT_RC(yieldRc); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow.c deleted file mode 100644 index 5c69edb05..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_shadow.c - * @brief Shadow client API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" -#include "aws_iot_error.h" -#include "aws_iot_log.h" -#include "aws_iot_shadow_actions.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_shadow_key.h" -#include "aws_iot_shadow_records.h" - -const ShadowInitParameters_t ShadowInitParametersDefault = {(char *) AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, NULL, NULL, - NULL, false, NULL}; - -const ShadowConnectParameters_t ShadowConnectParametersDefault = {(char *) AWS_IOT_MY_THING_NAME, - (char *) AWS_IOT_MQTT_CLIENT_ID, 0, NULL}; - -static char deleteAcceptedTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - -void aws_iot_shadow_reset_last_received_version(void) { - shadowJsonVersionNum = 0; -} - -uint32_t aws_iot_shadow_get_last_received_version(void) { - return shadowJsonVersionNum; -} - -void aws_iot_shadow_enable_discard_old_delta_msgs(void) { - shadowDiscardOldDeltaFlag = true; -} - -void aws_iot_shadow_disable_discard_old_delta_msgs(void) { - shadowDiscardOldDeltaFlag = false; -} - -IoT_Error_t aws_iot_shadow_free(AWS_IoT_Client *pClient) -{ - IoT_Error_t rc; - - if (NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - rc = aws_iot_mqtt_free(pClient); - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, ShadowInitParameters_t *pParams) { - IoT_Client_Init_Params mqttInitParams = IoT_Client_Init_Params_initializer; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pParams) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - mqttInitParams.enableAutoReconnect = pParams->enableAutoReconnect; - mqttInitParams.pHostURL = pParams->pHost; - mqttInitParams.port = pParams->port; - mqttInitParams.pRootCALocation = pParams->pRootCA; - mqttInitParams.pDeviceCertLocation = pParams->pClientCRT; - mqttInitParams.pDevicePrivateKeyLocation = pParams->pClientKey; - mqttInitParams.mqttPacketTimeout_ms = 5000; - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = pParams->disconnectHandler; - - rc = aws_iot_mqtt_init(pClient, &mqttInitParams); - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - resetClientTokenSequenceNum(); - aws_iot_shadow_reset_last_received_version(); - initDeltaTokens(); - - FUNC_EXIT_RC(SUCCESS); -} - -IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, ShadowConnectParameters_t *pParams) { - IoT_Error_t rc = SUCCESS; - uint16_t deleteAcceptedTopicLen; - IoT_Client_Connect_Params ConnectParams = iotClientConnectParamsDefault; - - FUNC_ENTRY; - - if(NULL == pClient || NULL == pParams || NULL == pParams->pMqttClientId) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - snprintf(myThingName, MAX_SIZE_OF_THING_NAME, "%s", pParams->pMyThingName); - snprintf(mqttClientID, MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES, "%s", pParams->pMqttClientId); - - ConnectParams.keepAliveIntervalInSec = 600; // NOTE: Temporary fix - ConnectParams.MQTTVersion = MQTT_3_1_1; - ConnectParams.isCleanSession = true; - ConnectParams.isWillMsgPresent = false; - ConnectParams.pClientID = pParams->pMqttClientId; - ConnectParams.clientIDLen = pParams->mqttClientIdLen; - ConnectParams.pPassword = NULL; - ConnectParams.pUsername = NULL; - - rc = aws_iot_mqtt_connect(pClient, &ConnectParams); - - if(SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - initializeRecords(pClient); - - if(NULL != pParams->deleteActionHandler) { - snprintf(deleteAcceptedTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, - "$aws/things/%s/shadow/delete/accepted", myThingName); - deleteAcceptedTopicLen = (uint16_t) strlen(deleteAcceptedTopic); - rc = aws_iot_mqtt_subscribe(pClient, deleteAcceptedTopic, deleteAcceptedTopicLen, QOS1, - pParams->deleteActionHandler, (void *) myThingName); - } - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_register_delta(AWS_IoT_Client *pMqttClient, jsonStruct_t *pStruct) { - if(NULL == pMqttClient || NULL == pStruct) { - return NULL_VALUE_ERROR; - } - - if(!aws_iot_mqtt_is_client_connected(pMqttClient)) { - return MQTT_CONNECTION_ERROR; - } - - return registerJsonTokenOnDelta(pStruct); -} - -IoT_Error_t aws_iot_shadow_yield(AWS_IoT_Client *pClient, uint32_t timeout) { - if(NULL == pClient) { - return NULL_VALUE_ERROR; - } - - HandleExpiredResponseCallbacks(); - return aws_iot_mqtt_yield(pClient, timeout); -} - -IoT_Error_t aws_iot_shadow_disconnect(AWS_IoT_Client *pClient) { - return aws_iot_mqtt_disconnect(pClient); -} - -IoT_Error_t aws_iot_shadow_update(AWS_IoT_Client *pClient, const char *pThingName, char *pJsonString, - fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds, - bool isPersistentSubscribe) { - IoT_Error_t rc; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - - rc = aws_iot_shadow_internal_action(pThingName, SHADOW_UPDATE, pJsonString, strlen(pJsonString), callback, pContextData, - timeout_seconds, isPersistentSubscribe); - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_delete(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) { - char deleteRequestJsonBuf[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - - rc = aws_iot_shadow_internal_delete_request_json(deleteRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE ); - if ( SUCCESS != rc ) { - FUNC_EXIT_RC( rc ); - } - - rc = aws_iot_shadow_internal_action(pThingName, SHADOW_DELETE, deleteRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE, callback, pContextData, - timeout_seconds, isPersistentSubscribe); - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_get(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, - void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) { - char getRequestJsonBuf[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - IoT_Error_t rc; - - FUNC_ENTRY; - - if(NULL == pClient) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - if(!aws_iot_mqtt_is_client_connected(pClient)) { - FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); - } - - rc = aws_iot_shadow_internal_get_request_json(getRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE ); - if (SUCCESS != rc) { - FUNC_EXIT_RC(rc); - } - - rc = aws_iot_shadow_internal_action(pThingName, SHADOW_GET, getRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE, callback, pContextData, - timeout_seconds, isPersistentSubscribe); - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_set_autoreconnect_status(AWS_IoT_Client *pClient, bool newStatus) { - return aws_iot_mqtt_autoreconnect_set_status(pClient, newStatus); -} - -#ifdef __cplusplus -} -#endif - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_actions.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_actions.c deleted file mode 100644 index 95b81c56f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_actions.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_shadow_actions.c - * @brief Shadow client Action API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_actions.h" - -#include "aws_iot_log.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_shadow_records.h" -#include "aws_iot_config.h" - -IoT_Error_t aws_iot_shadow_internal_action(const char *pThingName, ShadowActions_t action, - const char *pJsonDocumentToBeSent, size_t jsonSize, fpActionCallback_t callback, - void *pCallbackContext, uint32_t timeout_seconds, bool isSticky) { - IoT_Error_t ret_val = SUCCESS; - bool isClientTokenPresent = false; - bool isAckWaitListFree = false; - uint8_t indexAckWaitList; - char extractedClientToken[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE]; - - FUNC_ENTRY; - - if(NULL == pThingName || NULL == pJsonDocumentToBeSent) { - FUNC_EXIT_RC(NULL_VALUE_ERROR); - } - - isClientTokenPresent = extractClientToken(pJsonDocumentToBeSent, jsonSize, extractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE ); - - if(isClientTokenPresent && (NULL != callback)) { - if(getNextFreeIndexOfAckWaitList(&indexAckWaitList)) { - isAckWaitListFree = true; - } - - if(isAckWaitListFree) { - if(!isSubscriptionPresent(pThingName, action)) { - ret_val = subscribeToShadowActionAcks(pThingName, action, isSticky); - } else { - incrementSubscriptionCnt(pThingName, action, isSticky); - } - } - else { - ret_val = FAILURE; - } - } - - if(SUCCESS == ret_val) { - ret_val = publishToShadowAction(pThingName, action, pJsonDocumentToBeSent); - } - - if(isClientTokenPresent && (NULL != callback) && (SUCCESS == ret_val) && isAckWaitListFree) { - addToAckWaitList(indexAckWaitList, pThingName, action, extractedClientToken, callback, pCallbackContext, - timeout_seconds); - } - - FUNC_EXIT_RC(ret_val); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_json.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_json.c deleted file mode 100644 index b1d777836..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_json.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_shadow_json.c - * @brief Shadow client JSON parsing API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_json.h" - -#include -#include - -#include "aws_iot_json_utils.h" -#include "aws_iot_log.h" -#include "aws_iot_shadow_key.h" -#include "aws_iot_config.h" - -extern char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES]; -#define AWS_IOT_SHADOW_CLIENT_TOKEN_KEY "{\"clientToken\":\"" -static uint32_t clientTokenNum = 0; - -//helper functions -static IoT_Error_t convertDataToString(char *pStringBuffer, size_t maxSizoStringBuffer, JsonPrimitiveType type, - void *pData); - -void resetClientTokenSequenceNum(void) { - clientTokenNum = 0; -} - -static IoT_Error_t emptyJsonWithClientToken(char *pBuffer, size_t bufferSize) { - - IoT_Error_t rc = SUCCESS; - size_t dataLenInBuffer = 0; - - if(pBuffer != NULL) - { - dataLenInBuffer = (size_t)snprintf(pBuffer, bufferSize, AWS_IOT_SHADOW_CLIENT_TOKEN_KEY); - }else - { - IOT_ERROR("NULL buffer in emptyJsonWithClientToken\n"); - rc = FAILURE; - } - - if(rc == SUCCESS) - { - if ( dataLenInBuffer < bufferSize ) - { - dataLenInBuffer += (size_t)snprintf(pBuffer + dataLenInBuffer, bufferSize - dataLenInBuffer, "%s-%d", mqttClientID, ( int )clientTokenNum++); - } - else - { - rc = FAILURE; - IOT_ERROR("Supplied buffer too small to create JSON file\n"); - } - } - - if(rc == SUCCESS) - { - if ( dataLenInBuffer < bufferSize ) - { - dataLenInBuffer += (size_t)snprintf( pBuffer + dataLenInBuffer, bufferSize - dataLenInBuffer, "\"}" ); - if ( dataLenInBuffer > bufferSize ) - { - rc = FAILURE; - IOT_ERROR( "Supplied buffer too small to create JSON file\n" ); - } - } - else - { - rc = FAILURE; - IOT_ERROR( "Supplied buffer too small to create JSON file\n" ); - } - } - - FUNC_EXIT_RC(rc); -} - -IoT_Error_t aws_iot_shadow_internal_get_request_json(char *pBuffer, size_t bufferSize) { - return emptyJsonWithClientToken( pBuffer, bufferSize); -} - -IoT_Error_t aws_iot_shadow_internal_delete_request_json(char *pBuffer, size_t bufferSize ) { - return emptyJsonWithClientToken( pBuffer, bufferSize); -} - -static inline IoT_Error_t checkReturnValueOfSnPrintf(int32_t snPrintfReturn, size_t maxSizeOfJsonDocument) { - if(snPrintfReturn < 0) { - return SHADOW_JSON_ERROR; - } else if((size_t) snPrintfReturn >= maxSizeOfJsonDocument) { - return SHADOW_JSON_BUFFER_TRUNCATED; - } - return SUCCESS; -} - -IoT_Error_t aws_iot_shadow_init_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument) { - - IoT_Error_t ret_val = SUCCESS; - int32_t snPrintfReturn = 0; - - if(pJsonDocument == NULL) { - return NULL_VALUE_ERROR; - } - snPrintfReturn = snprintf(pJsonDocument, maxSizeOfJsonDocument, "{\"state\":{"); - - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, maxSizeOfJsonDocument); - - return ret_val; - -} - -IoT_Error_t aws_iot_shadow_add_desired(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...) { - IoT_Error_t ret_val = SUCCESS; - size_t tempSize = 0; - int8_t i; - size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; - int32_t snPrintfReturn = 0; - va_list pArgs; - jsonStruct_t *pTemporary = NULL; - va_start(pArgs, count); - - if(pJsonDocument == NULL) { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - va_end(pArgs); - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"desired\":{"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - - for(i = 0; i < count; i++) { - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - va_end(pArgs); - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - pTemporary = va_arg (pArgs, jsonStruct_t *); - if(pTemporary != NULL) { - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"%s\":", - pTemporary->pKey); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - if(pTemporary->pKey != NULL && pTemporary->pData != NULL) { - ret_val = convertDataToString(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, - pTemporary->type, pTemporary->pData); - } else { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - } else { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - } - - va_end(pArgs); - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "},"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - return ret_val; -} - -IoT_Error_t aws_iot_shadow_add_reported(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...) { - IoT_Error_t ret_val = SUCCESS; - - int8_t i; - size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; - int32_t snPrintfReturn = 0; - size_t tempSize = 0; - jsonStruct_t *pTemporary; - va_list pArgs; - va_start(pArgs, count); - - if(pJsonDocument == NULL) { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - - - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - va_end(pArgs); - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"reported\":{"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - - for(i = 0; i < count; i++) { - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - va_end(pArgs); - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - pTemporary = va_arg (pArgs, jsonStruct_t *); - if(pTemporary != NULL) { - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"%s\":", - pTemporary->pKey); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - if(pTemporary->pKey != NULL && pTemporary->pData != NULL) { - ret_val = convertDataToString(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, - pTemporary->type, pTemporary->pData); - } else { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - if(ret_val != SUCCESS) { - va_end(pArgs); - return ret_val; - } - } else { - va_end(pArgs); - return NULL_VALUE_ERROR; - } - } - - va_end(pArgs); - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "},"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - return ret_val; -} - - -int32_t FillWithClientTokenSize(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument) { - int32_t snPrintfReturn; - snPrintfReturn = snprintf(pBufferToBeUpdatedWithClientToken, maxSizeOfJsonDocument, "%s-%d", mqttClientID, - (int) clientTokenNum++); - - return snPrintfReturn; -} - -IoT_Error_t aws_iot_fill_with_client_token(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument) { - - int32_t snPrintfRet = 0; - snPrintfRet = FillWithClientTokenSize(pBufferToBeUpdatedWithClientToken, maxSizeOfJsonDocument); - return checkReturnValueOfSnPrintf(snPrintfRet, maxSizeOfJsonDocument); - -} - -IoT_Error_t aws_iot_finalize_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument) { - size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; - int32_t snPrintfReturn = 0; - size_t tempSize = 0; - IoT_Error_t ret_val = SUCCESS; - - if(pJsonDocument == NULL) { - return NULL_VALUE_ERROR; - } - - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - // strlen(ShadowTxBuffer) - 1 is to ensure we remove the last ,(comma) that was added - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "}, \"%s\":\"", - SHADOW_CLIENT_TOKEN_STRING); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - return ret_val; - } - // refactor this XXX repeated code - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - - snPrintfReturn = FillWithClientTokenSize(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - if(ret_val != SUCCESS) { - return ret_val; - } - tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); - if(tempSize <= 1) { - return SHADOW_JSON_ERROR; - } - remSizeOfJsonBuffer = tempSize; - - - snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"}"); - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); - - return ret_val; -} - -static IoT_Error_t convertDataToString(char *pStringBuffer, size_t maxSizoStringBuffer, JsonPrimitiveType type, - void *pData) { - int32_t snPrintfReturn = 0; - IoT_Error_t ret_val = SUCCESS; - - if(maxSizoStringBuffer == 0) { - return SHADOW_JSON_ERROR; - } - - if(type == SHADOW_JSON_INT32) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%i,", *(int32_t *) (pData)); - } else if(type == SHADOW_JSON_INT16) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%hi,", *(int16_t *) (pData)); - } else if(type == SHADOW_JSON_INT8) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%hhi,", *(int8_t *) (pData)); - } else if(type == SHADOW_JSON_UINT32) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%u,", *(uint32_t *) (pData)); - } else if(type == SHADOW_JSON_UINT16) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%hu,", *(uint16_t *) (pData)); - } else if(type == SHADOW_JSON_UINT8) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%hhu,", *(uint8_t *) (pData)); - } else if(type == SHADOW_JSON_DOUBLE) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%f,", *(double *) (pData)); - } else if(type == SHADOW_JSON_FLOAT) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%f,", *(float *) (pData)); - } else if(type == SHADOW_JSON_BOOL) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%s,", *(bool *) (pData) ? "true" : "false"); - } else if(type == SHADOW_JSON_STRING) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "\"%s\",", (char *) (pData)); - } else if(type == SHADOW_JSON_OBJECT) { - snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%s,", (char *) (pData)); - } - - - ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, maxSizoStringBuffer); - - return ret_val; -} - -static jsmn_parser shadowJsonParser; -static jsmntok_t jsonTokenStruct[MAX_JSON_TOKEN_EXPECTED]; - -bool isJsonValidAndParse(const char *pJsonDocument, size_t jsonSize, void *pJsonHandler, int32_t *pTokenCount) { - int32_t tokenCount; - - IOT_UNUSED(pJsonHandler); - - jsmn_init(&shadowJsonParser); - - tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, jsonSize, jsonTokenStruct, - sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d\n", tokenCount); - return false; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object\n"); - return false; - } - - *pTokenCount = tokenCount; - - return true; -} - -static IoT_Error_t UpdateValueIfNoObject(const char *pJsonString, jsonStruct_t *pDataStruct, jsmntok_t token) { - IoT_Error_t ret_val = SHADOW_JSON_ERROR; - if(pDataStruct->type == SHADOW_JSON_BOOL && pDataStruct->dataLength >= sizeof(bool)) { - ret_val = parseBooleanValue((bool *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_INT32 && pDataStruct->dataLength >= sizeof(int32_t)) { - ret_val = parseInteger32Value((int32_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_INT16 && pDataStruct->dataLength >= sizeof(int16_t)) { - ret_val = parseInteger16Value((int16_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_INT8 && pDataStruct->dataLength >= sizeof(int8_t)) { - ret_val = parseInteger8Value((int8_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_UINT32 && pDataStruct->dataLength >= sizeof(uint32_t)) { - ret_val = parseUnsignedInteger32Value((uint32_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_UINT16 && pDataStruct->dataLength >= sizeof(uint16_t)) { - ret_val = parseUnsignedInteger16Value((uint16_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_UINT8 && pDataStruct->dataLength >= sizeof(uint8_t)) { - ret_val = parseUnsignedInteger8Value((uint8_t *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_FLOAT && pDataStruct->dataLength >= sizeof(float)) { - ret_val = parseFloatValue((float *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_DOUBLE && pDataStruct->dataLength >= sizeof(double)) { - ret_val = parseDoubleValue((double *) pDataStruct->pData, pJsonString, &token); - } else if(pDataStruct->type == SHADOW_JSON_STRING) { - ret_val = parseStringValue((char *) pDataStruct->pData, pDataStruct->dataLength, pJsonString, &token); - } - - return ret_val; -} - -bool isJsonKeyMatchingAndUpdateValue(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, - jsonStruct_t *pDataStruct, uint32_t *pDataLength, int32_t *pDataPosition) { - int32_t i, metadataEnd; - uint32_t dataLength; - jsmntok_t dataToken; - - IOT_UNUSED(pJsonHandler); - - for(i = 1; i < tokenCount; ) { - if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), pDataStruct->pKey) == 0) { - dataToken = jsonTokenStruct[i + 1]; - dataLength = (uint32_t) (dataToken.end - dataToken.start); - UpdateValueIfNoObject(pJsonDocument, pDataStruct, dataToken); - *pDataPosition = dataToken.start; - *pDataLength = dataLength; - return true; - } else if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), "metadata") == 0) { - /* Sanity check: must not be at the last key in the json object. */ - if(i >= tokenCount-2) - { - return false; - } - - /* Record where the metadata object ends. */ - metadataEnd = jsonTokenStruct[i+1].end; - - /* Skip past the "metadata" key and jsmn object element. */ - i+= 2; - - /* Skip past every key inside "metadata". Keys inside "metadata" have - * have an end character before the end of the metadata object. - */ - while(jsonTokenStruct[i].end < metadataEnd) - { - i++; - } - } - else - { - /* Only increment the loop counter if the current object doesn't - * match AND isn't "metadata". - */ - i++; - } - } - return false; -} - -bool isReceivedJsonValid(const char *pJsonDocument, size_t jsonSize ) { - int32_t tokenCount; - - jsmn_init(&shadowJsonParser); - - tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, jsonSize, jsonTokenStruct, - sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d\n", tokenCount); - return false; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - return false; - } - - return true; -} - -bool extractClientToken(const char *pJsonDocument, size_t jsonSize, char *pExtractedClientToken, size_t clientTokenSize) { - int32_t tokenCount, i; - size_t length; - jsmntok_t ClientJsonToken; - jsmn_init(&shadowJsonParser); - - tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, jsonSize, jsonTokenStruct, - sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d\n", tokenCount); - return false; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - return false; - } - - for(i = 1; i < tokenCount; i++) { - if(jsoneq(pJsonDocument, &jsonTokenStruct[i], SHADOW_CLIENT_TOKEN_STRING) == 0) { - ClientJsonToken = jsonTokenStruct[i + 1]; - length = (size_t) (ClientJsonToken.end - ClientJsonToken.start); - if (clientTokenSize >= length + 1) - { - strncpy( pExtractedClientToken, pJsonDocument + ClientJsonToken.start, length); - pExtractedClientToken[length] = '\0'; - return true; - }else{ - IOT_WARN( "Token size %zu too small for string %zu \n", clientTokenSize, length); - return false; - } - } - } - - return false; -} - -bool extractVersionNumber(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, uint32_t *pVersionNumber) { - int32_t i; - IoT_Error_t ret_val = SUCCESS; - - IOT_UNUSED(pJsonHandler); - - for(i = 1; i < tokenCount; i++) { - if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), SHADOW_VERSION_STRING) == 0) { - ret_val = parseUnsignedInteger32Value(pVersionNumber, pJsonDocument, &jsonTokenStruct[i + 1]); - if(ret_val == SUCCESS) { - return true; - } - } - } - return false; -} - -#ifdef __cplusplus -} -#endif - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_records.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_records.c deleted file mode 100644 index d3a2c7720..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/src/aws_iot_shadow_records.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_mqtt_client_subscribe.c - * @brief MQTT client subscribe API definitions - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "aws_iot_shadow_records.h" - -#include -#include - -#include "timer_interface.h" -#include "aws_iot_json_utils.h" -#include "aws_iot_log.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_config.h" - -typedef struct { - char clientTokenID[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE]; - char thingName[MAX_SIZE_OF_THING_NAME]; - ShadowActions_t action; - fpActionCallback_t callback; - void *pCallbackContext; - bool isFree; - Timer timer; -} ToBeReceivedAckRecord_t; - -typedef struct { - const char *pKey; - void *pStruct; - jsonStructCallback_t callback; - bool isFree; -} JsonTokenTable_t; - -typedef struct { - char Topic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - uint8_t count; - bool isFree; - bool isSticky; -} SubscriptionRecord_t; - -typedef enum { - SHADOW_ACCEPTED, SHADOW_REJECTED, SHADOW_ACTION -} ShadowAckTopicTypes_t; - -ToBeReceivedAckRecord_t AckWaitList[MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME]; - -AWS_IoT_Client *pMqttClient; - -char myThingName[MAX_SIZE_OF_THING_NAME]; -char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES]; - -char shadowDeltaTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - -#define MAX_TOPICS_AT_ANY_GIVEN_TIME 2*MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME -SubscriptionRecord_t SubscriptionList[MAX_TOPICS_AT_ANY_GIVEN_TIME]; - -#define SUBSCRIBE_SETTLING_TIME 2 -char shadowRxBuf[SHADOW_MAX_SIZE_OF_RX_BUFFER]; - -static JsonTokenTable_t tokenTable[MAX_JSON_TOKEN_EXPECTED]; -static uint32_t tokenTableIndex = 0; -static bool deltaTopicSubscribedFlag = false; -uint32_t shadowJsonVersionNum = 0; -bool shadowDiscardOldDeltaFlag = true; - -// local helper functions -static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData); - -static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData); - -static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action, - ShadowAckTopicTypes_t ackType); - -static int16_t getNextFreeIndexOfSubscriptionList(void); - -static void unsubscribeFromAcceptedAndRejected(uint8_t index); - -void initDeltaTokens(void) { - uint32_t i; - for(i = 0; i < MAX_JSON_TOKEN_EXPECTED; i++) { - tokenTable[i].isFree = true; - } - tokenTableIndex = 0; - deltaTopicSubscribedFlag = false; -} - -IoT_Error_t registerJsonTokenOnDelta(jsonStruct_t *pStruct) { - - IoT_Error_t rc = SUCCESS; - - if(!deltaTopicSubscribedFlag) { - snprintf(shadowDeltaTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/update/delta", myThingName); - rc = aws_iot_mqtt_subscribe(pMqttClient, shadowDeltaTopic, (uint16_t) strlen(shadowDeltaTopic), QOS0, - shadow_delta_callback, NULL); - deltaTopicSubscribedFlag = true; - } - - if(tokenTableIndex >= MAX_JSON_TOKEN_EXPECTED) { - return FAILURE; - } - - tokenTable[tokenTableIndex].pKey = pStruct->pKey; - tokenTable[tokenTableIndex].callback = pStruct->cb; - tokenTable[tokenTableIndex].pStruct = pStruct; - tokenTable[tokenTableIndex].isFree = false; - tokenTableIndex++; - - return rc; -} - -static int16_t getNextFreeIndexOfSubscriptionList(void) { - uint8_t i; - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(SubscriptionList[i].isFree) { - SubscriptionList[i].isFree = false; - return i; - } - } - return -1; -} - -static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action, - ShadowAckTopicTypes_t ackType) { - - char actionBuf[10]; - char ackTypeBuf[10]; - - if(SHADOW_GET == action) { - strncpy(actionBuf, "get", 10); - } else if(SHADOW_UPDATE == action) { - strncpy(actionBuf, "update", 10); - } else if(SHADOW_DELETE == action) { - strncpy(actionBuf, "delete", 10); - } - - if(SHADOW_ACCEPTED == ackType) { - strncpy(ackTypeBuf, "accepted", 10); - } else if(SHADOW_REJECTED == ackType) { - strncpy(ackTypeBuf, "rejected", 10); - } - - if(SHADOW_ACTION == ackType) { - snprintf(pTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/%s", pThingName, actionBuf); - } else { - snprintf(pTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/%s/%s", pThingName, actionBuf, - ackTypeBuf); - } -} - -static bool isValidShadowVersionUpdate(const char *pTopicName) { - if(strstr(pTopicName, myThingName) != NULL && - ((strstr(pTopicName, "get/accepted") != NULL) || - (strstr(pTopicName, "delta") != NULL))) { - return true; - } - return false; -} - -static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - int32_t tokenCount; - uint8_t i; - void *pJsonHandler = NULL; - char temporaryClientToken[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(params->payloadLen >= SHADOW_MAX_SIZE_OF_RX_BUFFER) { - IOT_WARN("Payload larger than RX Buffer"); - return; - } - - memcpy(shadowRxBuf, params->payload, params->payloadLen); - shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string - - if(!isJsonValidAndParse(shadowRxBuf, SHADOW_MAX_SIZE_OF_RX_BUFFER, pJsonHandler, &tokenCount)) { - IOT_WARN("Received JSON is not valid"); - return; - } - - if(isValidShadowVersionUpdate(topicName)) { - uint32_t tempVersionNumber = 0; - if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) { - if(tempVersionNumber > shadowJsonVersionNum) { - shadowJsonVersionNum = tempVersionNumber; - } - } - } - - if(extractClientToken(shadowRxBuf, SHADOW_MAX_SIZE_OF_RX_BUFFER, temporaryClientToken, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE)) { - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - if(!AckWaitList[i].isFree) { - if(strcmp(AckWaitList[i].clientTokenID, temporaryClientToken) == 0) { - Shadow_Ack_Status_t status = SHADOW_ACK_REJECTED; - if(strstr(topicName, "accepted") != NULL) { - status = SHADOW_ACK_ACCEPTED; - } else if(strstr(topicName, "rejected") != NULL) { - status = SHADOW_ACK_REJECTED; - } - if(status == SHADOW_ACK_ACCEPTED || status == SHADOW_ACK_REJECTED) { - if(AckWaitList[i].callback != NULL) { - AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, status, - shadowRxBuf, AckWaitList[i].pCallbackContext); - } - unsubscribeFromAcceptedAndRejected(i); - AckWaitList[i].isFree = true; - return; - } - } - } - } - } -} - -static int16_t findIndexOfSubscriptionList(const char *pTopic) { - uint8_t i; - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(!SubscriptionList[i].isFree) { - if((strcmp(pTopic, SubscriptionList[i].Topic) == 0)) { - return i; - } - } - } - return -1; -} - -static void unsubscribeFromAcceptedAndRejected(uint8_t index) { - - char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - IoT_Error_t ret_val = SUCCESS; - - int16_t indexSubList; - - topicNameFromThingAndAction(TemporaryTopicNameAccepted, AckWaitList[index].thingName, AckWaitList[index].action, - SHADOW_ACCEPTED); - topicNameFromThingAndAction(TemporaryTopicNameRejected, AckWaitList[index].thingName, AckWaitList[index].action, - SHADOW_REJECTED); - - indexSubList = findIndexOfSubscriptionList(TemporaryTopicNameAccepted); - if((indexSubList >= 0)) { - if(!SubscriptionList[indexSubList].isSticky && (SubscriptionList[indexSubList].count == 1)) { - ret_val = aws_iot_mqtt_unsubscribe(pMqttClient, TemporaryTopicNameAccepted, - (uint16_t) strlen(TemporaryTopicNameAccepted)); - if(ret_val == SUCCESS) { - SubscriptionList[indexSubList].isFree = true; - } - } else if(SubscriptionList[indexSubList].count > 1) { - SubscriptionList[indexSubList].count--; - } - } - - indexSubList = findIndexOfSubscriptionList(TemporaryTopicNameRejected); - if((indexSubList >= 0)) { - if(!SubscriptionList[indexSubList].isSticky && (SubscriptionList[indexSubList].count == 1)) { - ret_val = aws_iot_mqtt_unsubscribe(pMqttClient, TemporaryTopicNameRejected, - (uint16_t) strlen(TemporaryTopicNameRejected)); - if(ret_val == SUCCESS) { - SubscriptionList[indexSubList].isFree = true; - } - } else if(SubscriptionList[indexSubList].count > 1) { - SubscriptionList[indexSubList].count--; - } - } -} - -void initializeRecords(AWS_IoT_Client *pClient) { - uint8_t i; - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - AckWaitList[i].isFree = true; - } - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - SubscriptionList[i].isFree = true; - SubscriptionList[i].count = 0; - SubscriptionList[i].isSticky = false; - } - - pMqttClient = pClient; -} - -bool isSubscriptionPresent(const char *pThingName, ShadowActions_t action) { - - uint8_t i = 0; - bool isAcceptedPresent = false; - bool isRejectedPresent = false; - char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - - topicNameFromThingAndAction(TemporaryTopicNameAccepted, pThingName, action, SHADOW_ACCEPTED); - topicNameFromThingAndAction(TemporaryTopicNameRejected, pThingName, action, SHADOW_REJECTED); - - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(!SubscriptionList[i].isFree) { - if((strcmp(TemporaryTopicNameAccepted, SubscriptionList[i].Topic) == 0)) { - isAcceptedPresent = true; - } else if((strcmp(TemporaryTopicNameRejected, SubscriptionList[i].Topic) == 0)) { - isRejectedPresent = true; - } - } - } - - if(isRejectedPresent && isAcceptedPresent) { - return true; - } - - return false; -} - -IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t action, bool isSticky) { - IoT_Error_t ret_val = SUCCESS; - - bool clearBothEntriesFromList = true; - int16_t indexAcceptedSubList = 0; - int16_t indexRejectedSubList = 0; - Timer subSettlingtimer; - indexAcceptedSubList = getNextFreeIndexOfSubscriptionList(); - indexRejectedSubList = getNextFreeIndexOfSubscriptionList(); - - if(indexAcceptedSubList >= 0 && indexRejectedSubList >= 0) { - topicNameFromThingAndAction(SubscriptionList[indexAcceptedSubList].Topic, pThingName, action, SHADOW_ACCEPTED); - ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic, - (uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic), QOS0, - AckStatusCallback, NULL); - if(ret_val == SUCCESS) { - SubscriptionList[indexAcceptedSubList].count = 1; - SubscriptionList[indexAcceptedSubList].isSticky = isSticky; - topicNameFromThingAndAction(SubscriptionList[indexRejectedSubList].Topic, pThingName, action, - SHADOW_REJECTED); - ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexRejectedSubList].Topic, - (uint16_t) strlen(SubscriptionList[indexRejectedSubList].Topic), QOS0, - AckStatusCallback, NULL); - if(ret_val == SUCCESS) { - SubscriptionList[indexRejectedSubList].count = 1; - SubscriptionList[indexRejectedSubList].isSticky = isSticky; - clearBothEntriesFromList = false; - - // wait for SUBSCRIBE_SETTLING_TIME seconds to let the subscription take effect - init_timer(&subSettlingtimer); - countdown_sec(&subSettlingtimer, SUBSCRIBE_SETTLING_TIME); - while(!has_timer_expired(&subSettlingtimer)); - - } - } - } - - if(clearBothEntriesFromList) { - if(indexAcceptedSubList >= 0) { - SubscriptionList[indexAcceptedSubList].isFree = true; - - if(SubscriptionList[indexAcceptedSubList].count == 1) { - aws_iot_mqtt_unsubscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic, - (uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic)); - } - } - if(indexRejectedSubList >= 0) { - SubscriptionList[indexRejectedSubList].isFree = true; - } - - } - - return ret_val; -} - -void incrementSubscriptionCnt(const char *pThingName, ShadowActions_t action, bool isSticky) { - char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - uint8_t i; - topicNameFromThingAndAction(TemporaryTopicNameAccepted, pThingName, action, SHADOW_ACCEPTED); - topicNameFromThingAndAction(TemporaryTopicNameRejected, pThingName, action, SHADOW_REJECTED); - - for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) { - if(!SubscriptionList[i].isFree) { - if((strcmp(TemporaryTopicNameAccepted, SubscriptionList[i].Topic) == 0) - || (strcmp(TemporaryTopicNameRejected, SubscriptionList[i].Topic) == 0)) { - SubscriptionList[i].count++; - SubscriptionList[i].isSticky = isSticky; - } - } - } -} - -IoT_Error_t publishToShadowAction(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent) { - IoT_Error_t ret_val = SUCCESS; - char TemporaryTopicName[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - IoT_Publish_Message_Params msgParams; - - if(NULL == pThingName || NULL == pJsonDocumentToBeSent) { - return NULL_VALUE_ERROR; - } - - topicNameFromThingAndAction(TemporaryTopicName, pThingName, action, SHADOW_ACTION); - - msgParams.qos = QOS0; - msgParams.isRetained = 0; - msgParams.payloadLen = strlen(pJsonDocumentToBeSent); - msgParams.payload = (char *) pJsonDocumentToBeSent; - ret_val = aws_iot_mqtt_publish(pMqttClient, TemporaryTopicName, (uint16_t) strlen(TemporaryTopicName), &msgParams); - - return ret_val; -} - -bool getNextFreeIndexOfAckWaitList(uint8_t *pIndex) { - uint8_t i; - bool rc = false; - - if(NULL == pIndex) { - return false; - } - - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - if(AckWaitList[i].isFree) { - *pIndex = i; - rc = true; - break; - } - } - - return rc; -} - -void addToAckWaitList(uint8_t indexAckWaitList, const char *pThingName, ShadowActions_t action, - const char *pExtractedClientToken, fpActionCallback_t callback, void *pCallbackContext, - uint32_t timeout_seconds) { - AckWaitList[indexAckWaitList].callback = callback; - memcpy(AckWaitList[indexAckWaitList].clientTokenID, pExtractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE); - memcpy(AckWaitList[indexAckWaitList].thingName, pThingName, MAX_SIZE_OF_THING_NAME); - AckWaitList[indexAckWaitList].pCallbackContext = pCallbackContext; - AckWaitList[indexAckWaitList].action = action; - init_timer(&(AckWaitList[indexAckWaitList].timer)); - countdown_sec(&(AckWaitList[indexAckWaitList].timer), timeout_seconds); - AckWaitList[indexAckWaitList].isFree = false; -} - -void HandleExpiredResponseCallbacks(void) { - uint8_t i; - for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { - if(!AckWaitList[i].isFree) { - if(has_timer_expired(&(AckWaitList[i].timer))) { - if(AckWaitList[i].callback != NULL) { - AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, SHADOW_ACK_TIMEOUT, - shadowRxBuf, AckWaitList[i].pCallbackContext); - } - AckWaitList[i].isFree = true; - unsubscribeFromAcceptedAndRejected(i); - } - } - } -} - -static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - int32_t tokenCount; - uint32_t i = 0; - void *pJsonHandler = NULL; - int32_t DataPosition; - uint32_t dataLength; - uint32_t tempVersionNumber = 0; - - FUNC_ENTRY; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(params->payloadLen >= SHADOW_MAX_SIZE_OF_RX_BUFFER) { - IOT_WARN("Payload larger than RX Buffer"); - return; - } - - memcpy(shadowRxBuf, params->payload, params->payloadLen); - shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string - - if(!isJsonValidAndParse(shadowRxBuf, SHADOW_MAX_SIZE_OF_RX_BUFFER, pJsonHandler, &tokenCount)) { - IOT_WARN("Received JSON is not valid"); - return; - } - - if(shadowDiscardOldDeltaFlag) { - if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) { - if(tempVersionNumber > shadowJsonVersionNum) { - shadowJsonVersionNum = tempVersionNumber; - } else { - IOT_WARN("Old Delta Message received - Ignoring rx: %d local: %d", tempVersionNumber, - shadowJsonVersionNum); - return; - } - } - } - - for(i = 0; i < tokenTableIndex; i++) { - if(!tokenTable[i].isFree) { - if(isJsonKeyMatchingAndUpdateValue(shadowRxBuf, pJsonHandler, tokenCount, - (jsonStruct_t *) tokenTable[i].pStruct, &dataLength, &DataPosition)) { - if(tokenTable[i].callback != NULL) { - tokenTable[i].callback(shadowRxBuf + DataPosition, dataLength, - (jsonStruct_t *) tokenTable[i].pStruct); - } - } - } - } -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/README.md deleted file mode 100644 index 3625bae68..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Tests -This folder contains tests to verify SDK functionality. These have been tested to work with Linux but haven't been ported to any specific platform. For additional information about porting the Device SDK for embedded C onto additional platforms please refer to the [PortingGuide](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/PortingGuide.md/). -A description for each folder is given below - -## integration -This folder contains integration tests that run directly against the server. For further information on how to run these tests check out the [Integration Test README](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/integration/README.md/). - -## unit -This folder contains unit tests that test SDK functionality against a Mock TLS layer. They are built using the CppUTest testing framework. For further information on how to run these tests check out the [Unit Test README](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/tests/unit/README.md/). \ No newline at end of file diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/Makefile deleted file mode 100644 index e18648941..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/Makefile +++ /dev/null @@ -1,108 +0,0 @@ -#This target is to ensure accidental execution of Makefile as a bash script will not execute commands like rm in unexpected directories and exit gracefully. -.prevent_execution: - exit 0 - -CC = gcc -RM = rm - -DEBUG = - -#IoT client directory -IOT_CLIENT_DIR = ../.. - -APP_DIR = $(IOT_CLIENT_DIR)/tests/integration -APP_NAME = integration_tests_mbedtls -MT_APP_NAME = integration_tests_mbedtls_mt -APP_SRC_FILES = $(shell find $(APP_DIR)/src/ -name '*.c') -MT_APP_SRC_FILES = $(shell find $(APP_DIR)/multithreadingTest/ -name '*.c') -APP_INCLUDE_DIRS = -I $(APP_DIR)/include - -PLATFORM_DIR = $(IOT_CLIENT_DIR)/platform/linux - -#MbedTLS directory -TEMP_MBEDTLS_SRC_DIR = $(IOT_CLIENT_DIR)/external_libs/mbedTLS -TLS_LIB_DIR = $(TEMP_MBEDTLS_SRC_DIR)/library -CRYPTO_LIB_DIR = $(TEMP_MBEDTLS_SRC_DIR)/library -TLS_INCLUDE_DIR = -I $(TEMP_MBEDTLS_SRC_DIR)/include - -EXTERNAL_LIBS += -L$(TLS_LIB_DIR) -LD_FLAG += -Wl,-rpath,$(TLS_LIB_DIR) -LD_FLAG += -ldl $(TLS_LIB_DIR)/libmbedtls.a $(CRYPTO_LIB_DIR)/libmbedcrypto.a $(TLS_LIB_DIR)/libmbedx509.a -lpthread - -# Logging level control -#LOG_FLAGS += -DENABLE_IOT_DEBUG -#LOG_FLAGS += -DENABLE_IOT_TRACE -#LOG_FLAGS += -DENABLE_IOT_INFO -LOG_FLAGS += -DENABLE_IOT_WARN -LOG_FLAGS += -DENABLE_IOT_ERROR -COMPILER_FLAGS += $(LOG_FLAGS) - -#IoT client directory -PLATFORM_COMMON_DIR = $(PLATFORM_DIR)/common -PLATFORM_THREAD_DIR = $(PLATFORM_DIR)/pthread -PLATFORM_NETWORK_DIR = $(PLATFORM_DIR)/mbedtls - -IOT_INCLUDE_DIRS = -I $(PLATFORM_COMMON_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_THREAD_DIR) -IOT_INCLUDE_DIRS += -I $(PLATFORM_NETWORK_DIR) -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/include -IOT_INCLUDE_DIRS += -I $(IOT_CLIENT_DIR)/external_libs/jsmn - -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/src/ -name '*.c') -IOT_SRC_FILES += $(shell find $(IOT_CLIENT_DIR)/external_libs/jsmn/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_NETWORK_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_COMMON_DIR)/ -name '*.c') -IOT_SRC_FILES += $(shell find $(PLATFORM_THREAD_DIR)/ -name '*.c') - -#Aggregate all include and src directories -INCLUDE_ALL_DIRS += $(IOT_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(APP_INCLUDE_DIRS) -INCLUDE_ALL_DIRS += $(TLS_INCLUDE_DIR) - -SRC_FILES += $(APP_SRC_FILES) -SRC_FILES += $(IOT_SRC_FILES) - -MT_SRC_FILES += $(MT_APP_SRC_FILES) -MT_SRC_FILES += $(IOT_SRC_FILES) - -COMPILER_FLAGS += -g -COMPILER_FLAGS += $(LOG_FLAGS) -PRE_MAKE_CMDS += cd $(TEMP_MBEDTLS_SRC_DIR) && make - -MAKE_CMD = $(CC) $(SRC_FILES) $(COMPILER_FLAGS) -g3 -D_ENABLE_THREAD_SUPPORT_ -o $(APP_DIR)/$(APP_NAME) $(EXTERNAL_LIBS) $(LD_FLAG) $(INCLUDE_ALL_DIRS); -MAKE_MT_CMD = $(CC) $(MT_SRC_FILES) $(COMPILER_FLAGS) -g3 -D_ENABLE_THREAD_SUPPORT_ -o $(APP_DIR)/$(MT_APP_NAME) $(EXTERNAL_LIBS) $(LD_FLAG) $(INCLUDE_ALL_DIRS); - -ifeq ($(CODE_SIZE_ENABLE),Y) -POST_MAKE_CMDS += $(CC) -c $(SRC_FILES) $(INCLUDE_ALL_DIRS) -fstack-usage; -POST_MAKE_CMDS += (size --format=Berkeley *.o > $(APP_NAME)_size_info.txt); -POST_MAKE_CMDS += (cat *.su >> $(APP_NAME)_stack_usage.txt); -POST_MAKE_CMDS += ($(RM) *.o); -POST_MAKE_CMDS += ($(RM) *.su); -CLEAN_CMD += ($(RM) -f $(APP_NAME)_size_info.txt); -CLEAN_CMD += ($(RM) -f $(APP_NAME)_stack_usage.txt); -endif - -all: - $(PRE_MAKE_CMDS) - $(DEBUG)$(MAKE_CMD) - $(DEBUG)$(MAKE_MT_CMD) - ./$(APP_NAME) - ./$(MT_APP_NAME) - $(POST_MAKE_CMDS) - -app: - $(PRE_MAKE_CMDS) - $(DEBUG)$(MAKE_CMD) - $(DEBUG)$(MAKE_MT_CMD) - -tests: - ./$(APP_NAME) - ./$(MT_APP_NAME) - $(POST_MAKE_CMDS) - -clean: - $(RM) -f $(APP_DIR)/$(APP_NAME) - $(RM) -f $(APP_DIR)/$(MT_APP_NAME) - $(CLEAN_CMD) - -ALL_TARGETS_CLEAN += test-integration-assert-clean diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/README.md deleted file mode 100644 index b3ea04b25..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/README.md +++ /dev/null @@ -1,44 +0,0 @@ -## Integration Tests -This folder contains integration tests to verify Embedded C SDK functionality. These have been tested to work with Linux but haven't been ported to any specific platform. For additional information about porting the Device SDK for embedded C onto additional platforms please refer to the [PortingGuide](https://github.com/aws/aws-iot-device-sdk-embedded-c/blob/master/PortingGuide.md/). -To run these tests, follow the below steps: - - * Place device identity cert and private key in locations referenced in the `certs` folder - * Download certificate authority CA file from [Symantec](https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem) and place in `certs` folder - * Ensure the names of the cert files are the same as in the `aws_iot_config.h` file - * Ensure the certificate has an attached policy which allows the proper permissions for AWS IoT - * Update the Host endpoint in the `aws_iot_config.h` file - * Build the example using make. (''make''). The tests will run automatically as a part of the build process - * For more detailed Debug output, enable the IOT_DEBUG flag in `Logging level control` section of the Makefile. IOT_TRACE can be enabled as well for very detailed information on what functions are being executed - * More information on the each test is below - -### Integration test configuration -For all the tests below, there is additional configuration in the `integ_tests_config.h`. The configuration options are explained below: - - * PUBLISH_COUNT - Number of messages to publish in each publish thread - * MAX_PUB_THREAD_COUNT - Maximum number of threads to create for the multi-threading test - * RX_RECEIVE_PERCENTAGE - Minimum percentage of messages that must be received back by the yield thread. This is here ONLY because sometimes the yield thread doesn't get scheduled before the publish thread when it is created. In every other case, 100% messages should be received - * CONNECT_MAX_ATTEMPT_COUNT - Max number of initial connect retries - * THREAD_SLEEP_INTERVAL_USEC - Interval that each thread sleeps for - * INTEGRATION_TEST_TOPIC - Test topic to publish on - * INTEGRATION_TEST_CLIENT_ID - Client ID to be used for single client tests - * INTEGRATION_TEST_CLIENT_ID_PUB, INTEGRATION_TEST_CLIENT_ID_SUB - Client IDs to be used for multiple client tests - -### Test 1 - Basic Connectivity Test -This test verifies basic connectivity with the server. It creates one client instance and connects to the server. It subscribes to the Integration Test topic. Then it creates two threads, one publish thread and one yield thread. The publish thread publishes `PUBLISH_COUNT` messages on the test topic and the yield thread receives them. Once all the messages are published, the program waits for 1 sec to ensure all the messages have sufficient time to be received. -The test ends with the program verifying that all the messages were received and no other errors occurred. - -### Test 2 - Multiple Client Connectivity Test -This test verifies usage of multiple clients in the same application. It creates two client instances and both connect to the server. One client instance subscribes to the Integration Test topic. The other client instance publishes `PUBLISH_COUNT` messages on the test topic and the yield instance receives them. Once all the messages are published, the program waits for 1 sec to ensure all the messages have sufficient time to be received. -The test ends with the program verifying that all the messages were received and no other errors occurred. - -### Test 3 - Auto Reconnect Test -This test verifies Auto-reconnect functionality. It creates one client instance. Then it performs 3 separate tests - - * Tests the disconnect handler by causing a TLS layer disconnect. - * Tests manual reconnect API by causing a TLS layer disconnect with auto-reconnect disabled - * Lastly, it tests the Auto-reconnect API by enabling auto-reconnect. It renames the rootCA file to a different name to prevent immediate reconnect, verifies the error codes are returned properly and that the reconnect algorithm is running. Once that check is satisfied, it renames the rootCA file back to the original names and verifies the client was able to reconnect. - -### Test 4 - Multi-threading Validation Test -This test is used to validate thread-safe operations. This creates on client instance, one yield thread, one thread to test subscribe/unsubscribe behavior and MAX_PUB_THREAD_COUNT number of publish threads. Then it proceeds to publish PUBLISH_COUNT messages on the test topic from each publish thread. The subscribe/unsubscribe thread runs in the background constantly subscribing and unsubscribing to a second test topic. The yield threads records which messages were received. - -The test verifies whether all the messages that were published were received or not. It also checks for errors that could occur in multi-threaded scenarios. The test has been run with 10 threads sending 500 messages each and verified to be working fine. It can be used as a reference testing application to validate whether your use case will work with multi-threading enabled. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_config.h deleted file mode 100644 index 5d249bfef..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_config.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifndef SRC_SHADOW_IOT_SHADOW_CONFIG_H_ -#define SRC_SHADOW_IOT_SHADOW_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT 443 ///< default port for MQTT/S -#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" ///< Thing Name of the Shadow this device is associated with -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" ///< Root CA file name -#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem" ///< device signed certificate file name -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" ///< Device private key filename - -// MQTT PubSub -#ifndef DISABLE_IOT_JOBS -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#else -#define AWS_IOT_MQTT_RX_BUF_LEN 2048 -#endif -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Shadow and Job common configs -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_SIZE_OF_THING_NAME 30 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER 512 ///< Maximum size of the SHADOW buffer to store the received Shadow message -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Job specific configs -#ifndef DISABLE_IOT_JOBS -#define MAX_SIZE_OF_JOB_ID 64 -#define MAX_JOB_JSON_TOKEN_EXPECTED 120 -#define MAX_SIZE_OF_JOB_REQUEST AWS_IOT_MQTT_TX_BUF_LEN - -#define MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME 40 -#define MAX_JOB_TOPIC_LENGTH_BYTES MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME + MAX_SIZE_OF_THING_NAME + MAX_SIZE_OF_JOB_ID + 2 -#endif - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#define DISABLE_METRICS false ///< Disable the collection of metrics by setting this to true - -// TLS configs -#define IOT_SSL_READ_TIMEOUT_MS 3 ///< Timeout associated with underlying socket of TLS connection (set by mbedtls_ssl_conf_read_timeout) -#define IOT_SSL_READ_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_read when pending data has not yet been received -#define IOT_SSL_WRITE_RETRY_TIMEOUT_MS 10 ///< Minimum elapsed time before returning from iot_tls_write when pending data has not yet been written - -#endif /* SRC_SHADOW_IOT_SHADOW_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_integ_tests_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_integ_tests_config.h deleted file mode 100644 index a10933806..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_integ_tests_config.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifndef TESTS_INTEGRATION_INTEG_TESTS_CONFIG_H_ -#define TESTS_INTEGRATION_INTEG_TESTS_CONFIG_H_ - -/* Number of messages to publish in each publish thread */ -#define PUBLISH_COUNT 100 - -/* Maximum number of threads to create for the multi-threading test */ -#define MAX_PUB_THREAD_COUNT 3 - -/* Minimum percentage of messages that must be received back by the yield thread. - * This is here ONLY because sometimes the yield thread doesn't get scheduled before the publish - * thread when it is created. In every other case, 100% messages should be received. */ -#define RX_RECEIVE_PERCENTAGE 99.0f - -/* Max number of initial connect retries */ -#define CONNECT_MAX_ATTEMPT_COUNT 3 - -/* Interval that each thread sleeps for */ -#define THREAD_SLEEP_INTERVAL_USEC 500000 - -/* Test topic to publish on */ -#define INTEGRATION_TEST_TOPIC "Tests/Integration/EmbeddedC" - -/* Client ID to be used for single client tests */ -#define INTEGRATION_TEST_CLIENT_ID "EMB_C_SDK_INTEG_TESTER" - -/* Client IDs to be used for multiple client tests */ -#define INTEGRATION_TEST_CLIENT_ID_PUB "EMB_C_SDK_INTEG_TESTER_PUB" -#define INTEGRATION_TEST_CLIENT_ID_SUB "EMB_C_SDK_INTEG_TESTER_SUB" - -#endif /* TESTS_INTEGRATION_INTEG_TESTS_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_test_integration_common.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_test_integration_common.h deleted file mode 100644 index 39da671ce..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/include/aws_iot_test_integration_common.h +++ /dev/null @@ -1,43 +0,0 @@ - -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_test_integration_common.h - * @brief Integration Test common header - */ - -#ifndef TESTS_INTEGRATION_H_ -#define TESTS_INTEGRATION_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_log.h" -#include "aws_iot_integ_tests_config.h" -#include "aws_iot_config.h" - -int aws_iot_mqtt_tests_basic_connectivity(); -int aws_iot_mqtt_tests_multiple_clients(); -int aws_iot_mqtt_tests_auto_reconnect(); - -#endif /* TESTS_INTEGRATION_COMMON_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/multithreadingTest/aws_iot_test_multithreading_validation.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/multithreadingTest/aws_iot_test_multithreading_validation.c deleted file mode 100644 index 032661d4f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/multithreadingTest/aws_iot_test_multithreading_validation.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * multithreadedTest.c - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_log.h" - -#include "aws_iot_integ_tests_config.h" -#include "aws_iot_config.h" - -#define BUFFER_SIZE 100 - -static bool terminate_yield_thread; -static bool terminate_subUnsub_thread; - -static unsigned int countArray[MAX_PUB_THREAD_COUNT][PUBLISH_COUNT]; -static unsigned int rxMsgBufferTooBigCounter; -static unsigned int rxUnexpectedNumberCounter; -static unsigned int rePublishCount; -static unsigned int wrongYieldCount; -static unsigned int threadStatus[MAX_PUB_THREAD_COUNT]; - -typedef struct ThreadData { - int threadId; - AWS_IoT_Client *client; -} ThreadData; - -static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - char tempBuf[BUFFER_SIZE]; - char *temp = NULL; - char *next_token; - unsigned int tempRow = 0, tempCol = 0; - - IoT_Error_t rc; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(BUFFER_SIZE >= params->payloadLen) { - snprintf(tempBuf, params->payloadLen, params->payload); - printf("\n Message received : %s", tempBuf); - temp = strtok_r(tempBuf, " ,:", &next_token); - temp = strtok_r(NULL, " ,:", &next_token); - if(NULL == temp) { - return; - } - tempRow = atoi(temp); - temp = strtok_r(NULL, " ,:", &next_token); - temp = strtok_r(NULL, " ,:", &next_token); - - if(NULL == temp) { - return; - } - - tempCol = atoi(temp); - - if(((tempRow - 1) < MAX_PUB_THREAD_COUNT) && (tempCol < PUBLISH_COUNT)) { - countArray[tempRow - 1][tempCol]++; - } else { - IOT_ERROR(" \nUnexpected Thread : %d, Message : %d ", tempRow, tempCol); - rxUnexpectedNumberCounter++; - } - rc = aws_iot_mqtt_yield(pClient, 10); - if(MQTT_CLIENT_NOT_IDLE_ERROR != rc) { - IOT_ERROR("\n Yield succeeded in callback!!! Client state : %d Rc : %d\n", - aws_iot_mqtt_get_client_state(pClient), rc); - wrongYieldCount++; - } - } else { - rxMsgBufferTooBigCounter++; - } -} - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { - IOT_UNUSED(pClient); - IOT_UNUSED(param); -} - -static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pClient, QoS qos, struct timeval *pSubscribeTime) { - IoT_Error_t rc = SUCCESS; - struct timeval start, end; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos, - aws_iot_mqtt_tests_message_aggregator, NULL); - IOT_DEBUG(" Sub response : %d\n", rc); - gettimeofday(&end, NULL); - - timersub(&end, &start, pSubscribeTime); - - return rc; -} - -static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - while(SUCCESS == rc && false == terminate_yield_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - //DEBUG("\n Yielding \n"); - rc = aws_iot_mqtt_yield(pClient, 100); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("\nYield Returned : %d ", rc); - } - } - - return NULL; -} - -static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) { - int itr = 0; - char cPayload[100]; - IoT_Publish_Message_Params params; - IoT_Error_t rc = SUCCESS; - ThreadData *threadData = (ThreadData *) ptr; - AWS_IoT_Client *pClient = threadData->client; - int threadId = threadData->threadId; - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - snprintf(cPayload, 100, "%s_Thread : %d, Msg : %d", AWS_IOT_MY_THING_NAME, threadId, itr); - printf("\nMsg being published: %s \n", cPayload); - params.payload = (void *) cPayload; - params.payloadLen = strlen(cPayload) + 1; - params.qos = QOS1; - params.isRetained = 0; - - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - if(SUCCESS != rc) { - IOT_WARN("\nFailed attempt 1 Publishing Thread : %d, Msg : %d, cs : %d --> %d\n ", threadId, itr, rc, - aws_iot_mqtt_get_client_state(pClient)); - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - rePublishCount++; - if(SUCCESS != rc) { - IOT_ERROR("\nFailed attempt 2 Publishing Thread : %d, Msg : %d, cs : %d --> %d Second Attempt \n", threadId, - itr, rc, aws_iot_mqtt_get_client_state(pClient)); - } - } - } - threadStatus[threadId - 1] = 1; - return 0; - -} - -static void *aws_iot_mqtt_tests_sub_unsub_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - char testTopic[50]; - snprintf(testTopic, 50, "%s_temp", INTEGRATION_TEST_TOPIC); - while(SUCCESS == rc && false == terminate_subUnsub_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_subscribe(pClient, testTopic, strlen(testTopic), QOS1, - aws_iot_mqtt_tests_message_aggregator, NULL); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("Subscribe Returned : %d ", rc); - } - - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_unsubscribe(pClient, testTopic, strlen(testTopic)); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("Unsubscribe Returned : %d ", rc); - } - } - - return NULL; -} - -int aws_iot_mqtt_tests_multi_threading_validation() { - pthread_t publish_thread[MAX_PUB_THREAD_COUNT], yield_thread, sub_unsub_thread; - char certDirectory[15] = "../../certs"; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char root_CA[PATH_MAX + 1]; - - char clientId[50]; - IoT_Client_Init_Params initParams = IoT_Client_Init_Params_initializer; - IoT_Client_Connect_Params connectParams; - int threadId[MAX_PUB_THREAD_COUNT]; - int pubThreadReturn[MAX_PUB_THREAD_COUNT]; - int yieldThreadReturn = 0, subUnsubThreadReturn = 0; - float percentOfRxMsg = 0.0; - int finishedThreadCount = 0; - IoT_Error_t rc = SUCCESS; - int i, rxMsgCount = 0, j = 0; - struct timeval subscribeTopic; - unsigned int connectCounter = 0; - int test_result = 0; - ThreadData threadData[MAX_PUB_THREAD_COUNT]; - AWS_IoT_Client client; - terminate_yield_thread = false; - rxMsgBufferTooBigCounter = 0; - rxUnexpectedNumberCounter = 0; - rePublishCount = 0; - wrongYieldCount = 0; - for(j = 0; j < MAX_PUB_THREAD_COUNT; j++) { - threadId[j] = j + 1; - threadStatus[j] = 0; - for(i = 0; i < PUBLISH_COUNT; i++) { - countArray[j][i] = 0; - } - } - - printf("\nConnecting Client "); - do { - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int)time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - IOT_DEBUG(" Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = AWS_IOT_MQTT_PORT; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 10000; - initParams.tlsHandshakeTimeout_ms = 10000; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - initParams.isBlockOnThreadLockEnabled = true; - aws_iot_mqtt_init(&client, &initParams); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *)&clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = false; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - IOT_ERROR("ERROR Connecting %d\n", rc); - return -1; - } - - connectCounter++; - } while(SUCCESS != rc && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - printf("\n## Connect Success.\n"); - } else { - IOT_ERROR("## Connect Failed. error code %d\n", rc); - return -1; - } - - aws_iot_mqtt_tests_subscribe_to_test_topic(&client, QOS1, &subscribeTopic); - - printf("\nRunning Test! "); - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_thread_runner, &client); - subUnsubThreadReturn = pthread_create(&sub_unsub_thread, NULL, aws_iot_mqtt_tests_sub_unsub_thread_runner, &client); - - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { - threadData[i].client = &client; - threadData[i].threadId = threadId[i]; - pubThreadReturn[i] = pthread_create(&publish_thread[i], NULL, aws_iot_mqtt_tests_publish_thread_runner, - &threadData[i]); - } - - /* Wait until all publish threads have finished */ - do { - finishedThreadCount = 0; - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { finishedThreadCount += threadStatus[i]; } - printf("\nFinished thread count : %d \n", finishedThreadCount); - sleep(1); - } while(finishedThreadCount < MAX_PUB_THREAD_COUNT); - - printf("\nFinished publishing!!"); - - terminate_yield_thread = true; - terminate_subUnsub_thread = true; - pthread_join(yield_thread, NULL); - pthread_join(sub_unsub_thread, NULL); - - for(i = 0; i < MAX_PUB_THREAD_COUNT; i++) { - pthread_join(publish_thread[i], NULL); - } - - /* Not using pthread_join because all threads should have terminated gracefully at this point. If they haven't, - * which should not be possible, something below will fail. */ - - printf("\n\nCalculating Results!! \n\n"); - for(i = 0; i < PUBLISH_COUNT; i++) { - for(j = 0; j < MAX_PUB_THREAD_COUNT; j++) { - if(countArray[j][i] > 0) { - rxMsgCount++; - } - } - } - - printf("\n\nResult : \n"); - percentOfRxMsg = (float) rxMsgCount * 100 / (PUBLISH_COUNT * MAX_PUB_THREAD_COUNT); - if(RX_RECEIVE_PERCENTAGE <= percentOfRxMsg && 0 == rxMsgBufferTooBigCounter && 0 == rxUnexpectedNumberCounter && - 0 == wrongYieldCount) { - printf("\nSuccess: %f \%\n", percentOfRxMsg); - printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT * MAX_PUB_THREAD_COUNT, rxMsgCount); - printf("QoS 1 re publish count %d\n", rePublishCount); - printf("Connection Attempts %d\n", connectCounter); - printf("Yield count without error during callback %d\n", wrongYieldCount); - test_result = 0; - } else { - printf("\nFailure: %f\n", percentOfRxMsg); - printf("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter); - printf("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter); - printf("Yield count without error during callback %d\n", wrongYieldCount); - test_result = -2; - } - aws_iot_mqtt_disconnect(&client); - return test_result; -} - -int main() { - printf("\n\n"); - printf("******************************************************************\n"); - printf("* Starting MQTT Version 3.1.1 Multithreading Validation Test *\n"); - printf("******************************************************************\n"); - int rc = aws_iot_mqtt_tests_multi_threading_validation(); - if(0 != rc) { - printf("\n*******************************************************************\n"); - printf("*MQTT Version 3.1.1 Multithreading Validation Test FAILED! RC : %d \n", rc); - printf("*******************************************************************\n"); - return 1; - } - - printf("******************************************************************\n"); - printf("* MQTT Version 3.1.1 Multithreading Validation Test SUCCESS!! *\n"); - printf("******************************************************************\n"); - - return 0; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_auto_reconnect.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_auto_reconnect.c deleted file mode 100644 index 267d9dc05..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_auto_reconnect.c +++ /dev/null @@ -1,236 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_test_auto_reconnect.c - * @brief Integration Test for automatic reconnect - */ - -#include "aws_iot_test_integration_common.h" - -static char ModifiedPathBuffer[PATH_MAX + 1]; -char root_CA[PATH_MAX + 1]; - -bool terminate_yield_with_rc_thread = false; -IoT_Error_t yieldRC; -bool captureYieldReturnCode = false; -char * dummyLocation = "dummyLocation"; -char * savedLocation; -/** - * This function renames the rootCA.crt file to a temporary name to cause connect failure - */ -void aws_iot_mqtt_tests_block_tls_connect(AWS_IoT_Client *pClient) { - savedLocation = pClient->networkStack.tlsConnectParams.pRootCALocation; - pClient->networkStack.tlsConnectParams.pRootCALocation = dummyLocation; -} - -/** - * Always ensure this function is called after block_tls_connect - */ -void aws_iot_mqtt_tests_unblock_tls_connect(AWS_IoT_Client *pClient) { - pClient->networkStack.tlsConnectParams.pRootCALocation = savedLocation; -} - -void *aws_iot_mqtt_tests_yield_with_rc(void *ptr) { - IoT_Error_t rc = SUCCESS; - - struct timeval start, end, result; - static int cntr = 0; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - - while(terminate_yield_with_rc_thread == false - && (NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)) { - usleep(500000); - printf(" Client state : %d ", aws_iot_mqtt_get_client_state(pClient)); - rc = aws_iot_mqtt_yield(pClient, 100); - printf("yield rc %d\n", rc); - if(captureYieldReturnCode && SUCCESS != rc) { - printf("yield rc capture %d\n", rc); - captureYieldReturnCode = false; - yieldRC = rc; - } - } - - return NULL; -} - -unsigned int disconnectedCounter = 0; - -void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { - disconnectedCounter++; -} - -int aws_iot_mqtt_tests_auto_reconnect() { - pthread_t reconnectTester_thread, yield_thread; - int yieldThreadReturn = 0; - int test_result = 0; - - char certDirectory[15] = "../../certs"; - char CurrentWD[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char clientId[50]; - AWS_IoT_Client client; - - IoT_Error_t rc = SUCCESS; - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int) time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - printf(" Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - IoT_Client_Init_Params initParams = IoT_Client_Init_Params_initializer; - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = AWS_IOT_MQTT_PORT; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 20000; - initParams.tlsHandshakeTimeout_ms = 5000; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - aws_iot_mqtt_init(&client, &initParams); - - IoT_Client_Connect_Params connectParams; - connectParams.keepAliveIntervalInSec = 5; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *) &clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = 0; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(rc != SUCCESS) { - printf("ERROR Connecting %d\n", rc); - return -1; - } - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_with_rc, &client); - - /* - * Test disconnect handler - */ - printf("1. Test Disconnect Handler\n"); - aws_iot_mqtt_tests_block_tls_connect(&client); - iot_tls_disconnect(&(client.networkStack)); - sleep(connectParams.keepAliveIntervalInSec + 1); - if(disconnectedCounter == 1) { - printf("Success invoking Disconnect Handler\n"); - } else { - aws_iot_mqtt_tests_unblock_tls_connect(&client); - printf("Failure to invoke Disconnect Handler\n"); - return -1; - } - - terminate_yield_with_rc_thread = true; - pthread_join(yield_thread, NULL); - aws_iot_mqtt_tests_unblock_tls_connect(&client); - - /* - * Manual Reconnect Test - */ - printf("2. Test Manual Reconnect, Current Client state : %d \n", aws_iot_mqtt_get_client_state(&client)); - rc = aws_iot_mqtt_attempt_reconnect(&client); - if(rc != NETWORK_RECONNECTED) { - printf("ERROR reconnecting manually %d\n", rc); - return -4; - } - terminate_yield_with_rc_thread = false; - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_with_rc, &client); - - yieldRC = FAILURE; - captureYieldReturnCode = true; - - // ensure atleast 1 cycle of yield is executed to get the yield status to SUCCESS - sleep(1); - if(!captureYieldReturnCode) { - if(yieldRC == NETWORK_ATTEMPTING_RECONNECT) { - printf("Success reconnecting manually\n"); - } else { - printf("Failure to reconnect manually\n"); - return -3; - } - } - terminate_yield_with_rc_thread = true; - pthread_join(yield_thread, NULL); - - /* - * Auto Reconnect Test - */ - - printf("3. Test Auto_reconnect \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(rc != SUCCESS) { - printf("Error: Failed to enable auto-reconnect %d \n", rc); - } - - yieldRC = FAILURE; - captureYieldReturnCode = true; - - // Disconnect - aws_iot_mqtt_tests_block_tls_connect(&client); - iot_tls_disconnect(&(client.networkStack)); - - terminate_yield_with_rc_thread = false; - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_with_rc, &client); - - sleep(connectParams.keepAliveIntervalInSec + 1); - if(!captureYieldReturnCode) { - if(yieldRC == NETWORK_ATTEMPTING_RECONNECT) { - printf("Success attempting reconnect\n"); - } else { - printf("Failure to attempt to reconnect\n"); - return -6; - } - } - if(disconnectedCounter == 2) { - printf("Success: disconnect handler invoked on enabling auto-reconnect\n"); - } else { - printf("Failure: disconnect handler not invoked on enabling auto-reconnect : %d\n", disconnectedCounter); - return -7; - } - aws_iot_mqtt_tests_unblock_tls_connect(&client); - sleep(connectParams.keepAliveIntervalInSec + 1); - captureYieldReturnCode = true; - sleep(connectParams.keepAliveIntervalInSec + 1); - if(!captureYieldReturnCode) { - if(yieldRC == SUCCESS) { - printf("Success attempting reconnect\n"); - } else { - printf("Failure to attempt to reconnect\n"); - return -6; - } - } - - terminate_yield_with_rc_thread = true; - pthread_join(yield_thread, NULL); - - if(true == aws_iot_mqtt_is_client_connected(&client)) { - printf("Success: is Mqtt connected api\n"); - } else { - printf("Failure: is Mqtt Connected api\n"); - return -7; - } - - rc = aws_iot_mqtt_disconnect(&client); - return rc; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_basic_connectivity.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_basic_connectivity.c deleted file mode 100644 index 8d08980ee..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_basic_connectivity.c +++ /dev/null @@ -1,281 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_test_basic_connectivity.c - * @brief Integration Test for basic client connectivity - */ - -#include "aws_iot_test_integration_common.h" - -#define BUFFER_SIZE 100 - -static bool terminate_yield_thread; - -static unsigned int countArray[PUBLISH_COUNT]; -static unsigned int rxMsgBufferTooBigCounter; -static unsigned int rxUnexpectedNumberCounter; -static unsigned int rePublishCount; -static unsigned int wrongYieldCount; - -typedef struct ThreadData { - AWS_IoT_Client *client; - int threadId; -} ThreadData; - -static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - char tempBuf[BUFFER_SIZE]; - char *next_token; - char *temp = NULL; - unsigned int tempRow = 0, tempCol = 0; - IoT_Error_t rc; - - if(params->payloadLen <= BUFFER_SIZE) { - snprintf(tempBuf, params->payloadLen, params->payload); - printf("\nMsg received : %s", tempBuf); - temp = strtok_r(tempBuf, " ,:", &next_token); - temp = strtok_r(NULL, " ,:", &next_token); - if(NULL == temp) { - return; - } - tempRow = atoi(temp); - temp = strtok_r(NULL, " ,:", &next_token); - temp = strtok_r(NULL, " ,:", &next_token); - if(NULL == temp) { - return; - } - - tempCol = atoi(temp); - - if(tempCol > 0 && tempCol <= PUBLISH_COUNT) { - countArray[tempCol - 1]++; - } else { - IOT_WARN(" \n Thread : %d, Msg : %d ", tempRow, tempCol); - rxUnexpectedNumberCounter++; - } - rc = aws_iot_mqtt_yield(pClient, 10); - if(MQTT_CLIENT_NOT_IDLE_ERROR != rc) { - IOT_ERROR("\n Yield succeeded in callback!!! Client state : %d Rc : %d\n", - aws_iot_mqtt_get_client_state(pClient), rc); - wrongYieldCount++; - } - } else { - rxMsgBufferTooBigCounter++; - } -} - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { -} - -static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pClient, QoS qos, - struct timeval *pSubscribeTime) { - IoT_Error_t rc = SUCCESS; - struct timeval start, end; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos, - aws_iot_mqtt_tests_message_aggregator, NULL); - IOT_DEBUG("Sub response : %d\n", rc); - gettimeofday(&end, NULL); - - timersub(&end, &start, pSubscribeTime); - - return rc; -} - -static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - while(SUCCESS == rc && terminate_yield_thread == false) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_yield(pClient, 100); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); // Client is busy, wait to get lock - - if(SUCCESS != rc) { - IOT_DEBUG("\nYield Returned : %d ", rc); - } - } - - return NULL; -} - -static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) { - int i = 0; - char cPayload[100]; - IoT_Publish_Message_Params params; - IoT_Error_t rc = SUCCESS; - ThreadData *threadData = (ThreadData *) ptr; - AWS_IoT_Client *pClient = threadData->client; - int threadId = threadData->threadId; - - for(i = 0; i < PUBLISH_COUNT; i++) { - snprintf(cPayload, 100, "%s_Thread : %d, Msg : %d", AWS_IOT_MY_THING_NAME, threadId, i + 1); - printf("\nMsg being published: %s \n", cPayload); - params.payload = (void *) cPayload; - params.payloadLen = strlen(cPayload) + 1; - params.qos = QOS1; - params.isRetained = 0; - - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - if(rc != SUCCESS) { - IOT_WARN("Error Publishing #%d --> %d\n ", i, rc); - do { - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - usleep(THREAD_SLEEP_INTERVAL_USEC); - } while(MUTEX_LOCK_ERROR == rc || MQTT_CLIENT_NOT_IDLE_ERROR == rc); - rePublishCount++; - if(rc != SUCCESS) { - IOT_ERROR("Error Publishing #%d --> %d Second Attempt \n", i, rc); - } - } - } - return 0; -} - -int aws_iot_mqtt_tests_basic_connectivity() { - pthread_t publish_thread, yield_thread; - char certDirectory[15] = "../../certs"; - char clientCRT[PATH_MAX + 1]; - char root_CA[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char clientId[50]; - IoT_Client_Init_Params initParams; - IoT_Client_Connect_Params connectParams; - int pubThreadReturn; - int yieldThreadReturn = 0; - float percentOfRxMsg = 0.0; - IoT_Error_t rc = SUCCESS; - int i, rxMsgCount = 0, j = 0; - struct timeval connectTime, subscribeTopic; - struct timeval start, end; - unsigned int connectCounter = 0; - int test_result = 0; - ThreadData threadData; - AWS_IoT_Client client; - - terminate_yield_thread = false; - - rxMsgBufferTooBigCounter = 0; - rxUnexpectedNumberCounter = 0; - rePublishCount = 0; - wrongYieldCount = 0; - for(i = 0; i < PUBLISH_COUNT; i++) { - countArray[i] = 0; - } - - IOT_DEBUG("\nConnecting Client "); - do { - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int)time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - printf("\n\nClient ID : %s \n", clientId); - - IOT_DEBUG("Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = AWS_IOT_MQTT_PORT; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 10000; - initParams.tlsHandshakeTimeout_ms = 10000; - initParams.mqttPacketTimeout_ms = 5000; - initParams.isSSLHostnameVerify = true; - initParams.disconnectHandlerData = NULL; - initParams.isBlockOnThreadLockEnabled = true; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - aws_iot_mqtt_init(&client, &initParams); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *)&clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = false; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_connect(&client, &connectParams); - gettimeofday(&end, NULL); - timersub(&end, &start, &connectTime); - - connectCounter++; - } while(rc != SUCCESS && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - IOT_DEBUG("## Connect Success. Time sec: %d, usec: %d\n", connectTime.tv_sec, connectTime.tv_usec); - } else { - IOT_ERROR("## Connect Failed. error code %d\n", rc); - return -1; - } - - aws_iot_mqtt_tests_subscribe_to_test_topic(&client, QOS1, &subscribeTopic); - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_thread_runner, &client); - sleep(1); - - threadData.client = &client; - threadData.threadId = 1; - pubThreadReturn = pthread_create(&publish_thread, NULL, aws_iot_mqtt_tests_publish_thread_runner, &threadData); - - pthread_join(publish_thread, NULL); - // This sleep is to ensure that the last publish message has enough time to be received by us - sleep(1); - - terminate_yield_thread = true; - pthread_join(yield_thread, NULL); - - /* Not using pthread_join because all threads should have terminated gracefully at this point. If they haven't, - * which should not be possible, something below will fail. */ - - for(i = 0; i < PUBLISH_COUNT; i++) { - if(countArray[i] > 0) { - rxMsgCount++; - } - } - - IOT_DEBUG("\n\nResult : \n"); - percentOfRxMsg = (float) rxMsgCount * 100 / PUBLISH_COUNT; - if(percentOfRxMsg >= RX_RECEIVE_PERCENTAGE && rxMsgBufferTooBigCounter == 0 && rxUnexpectedNumberCounter == 0 && - wrongYieldCount == 0) { - IOT_DEBUG("\n\nSuccess: %f \%\n", percentOfRxMsg); - IOT_DEBUG("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT, rxMsgCount); - IOT_DEBUG("QoS 1 re publish count %d\n", rePublishCount); - IOT_DEBUG("Connection Attempts %d\n", connectCounter); - IOT_DEBUG("Yield count without error during callback %d\n", wrongYieldCount); - test_result = 0; - } else { - IOT_ERROR("\n\nFailure: %f\n", percentOfRxMsg); - IOT_ERROR("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter); - IOT_ERROR("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter); - IOT_ERROR("Yield count without error during callback %d\n", wrongYieldCount); - test_result = -2; - } - aws_iot_mqtt_disconnect(&client); - return test_result; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_integration_runner.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_integration_runner.c deleted file mode 100644 index 61ec00fab..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_integration_runner.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_test_integration_runner.c - * @brief Integration Test runner - */ - -#include "aws_iot_test_integration_common.h" - -int main() { - int rc = 0; - - printf("\n\n"); - printf("*************************************************************************************************\n"); - printf("* Starting TEST 1 MQTT Version 3.1.1 Basic Subscribe QoS 1 Publish QoS 1 with Single Client *\n"); - printf("*************************************************************************************************\n"); - rc = aws_iot_mqtt_tests_basic_connectivity(); - if(0 != rc) { - printf("\n********************************************************************************************************\n"); - printf("* TEST 1 MQTT Version 3.1.1 Basic Subscribe QoS 1 Publish QoS 1 with Single Client FAILED! RC : %4d *\n", rc); - printf("********************************************************************************************************\n"); - return 1; - } - printf("\n*************************************************************************************************\n"); - printf("* TEST 1 MQTT Version 3.1.1 Basic Subscribe QoS 1 Publish QoS 1 with Single Client SUCCESS!! *\n"); - printf("*************************************************************************************************\n"); - - printf("\n\n"); - printf("************************************************************************************************************\n"); - printf("* Starting TEST 2 MQTT Version 3.1.1 Multithreaded Subscribe QoS 1 Publish QoS 1 with Multiple Clients *\n"); - printf("************************************************************************************************************\n"); - rc = aws_iot_mqtt_tests_multiple_clients(); - if(0 != rc) { - printf("\n*******************************************************************************************************************\n"); - printf("* TEST 2 MQTT Version 3.1.1 Multithreaded Subscribe QoS 1 Publish QoS 1 with Multiple Clients FAILED! RC : %4d *\n", rc); - printf("*******************************************************************************************************************\n"); - return 1; - } - printf("\n*************************************************************************************************************\n"); - printf("* TEST 2 MQTT Version 3.1.1 Multithreaded Subscribe QoS 1 Publish QoS 1 with Multiple Clients SUCCESS!! *\n"); - printf("*************************************************************************************************************\n"); - - printf("\n\n"); - printf("*********************************************************\n"); - printf("* Starting TEST 3 MQTT Version 3.1.1 Auto Reconnect *\n"); - printf("*********************************************************\n"); - rc = aws_iot_mqtt_tests_auto_reconnect(); - if(0 != rc) { - printf("\n***************************************************************\n"); - printf("* TEST 3 MQTT Version 3.1.1 Auto Reconnect FAILED! RC : %4d *\n", rc); - printf("***************************************************************\n"); - return 1; - } - printf("\n**********************************************************\n"); - printf("* TEST 3 MQTT Version 3.1.1 Auto Reconnect SUCCESS!! *\n"); - printf("**********************************************************\n"); - -#ifndef DISABLE_IOT_JOBS -#ifndef DISABLE_IOT_JOBS_INTERFACE - printf("\n\n"); - printf("*************************************************************************************************\n"); - printf("* Starting TEST 4 Jobs API Test *\n"); - printf("*************************************************************************************************\n"); - rc = aws_iot_jobs_basic_test(); - if(0 != rc) { - printf("\n********************************************************************************************************\n"); - printf("* TEST 4 Jobs API Test FAILED! RC : %4d *\n", rc); - printf("********************************************************************************************************\n"); - return 1; - } - printf("\n*************************************************************************************************\n"); - printf("* TEST 4 Jobs API Test SUCCESS!! *\n"); - printf("*************************************************************************************************\n"); -#endif -#endif - - return 0; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_jobs_api.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_jobs_api.c deleted file mode 100644 index 4974eb857..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_jobs_api.c +++ /dev/null @@ -1,284 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -#ifndef DISABLE_IOT_JOBS -#ifndef DISABLE_IOT_JOBS_INTERFACE - -#include "aws_iot_test_integration_common.h" -#include -#include -#include -#include -#include - -static AWS_IoT_Client client; - -static jsmn_parser jsonParser; -static jsmntok_t jsonTokenStruct[MAX_JSON_TOKEN_EXPECTED]; -static int32_t tokenCount; - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { -} - -void iot_get_pending_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - IoT_Error_t rc = SUCCESS; - char topicToPublishGetNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - - IOT_UNUSED(pData); - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_GET_PENDING_TOPIC callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); - - jsmn_init(&jsonParser); - - tokenCount = jsmn_parse(&jsonParser, params->payload, (int) params->payloadLen, jsonTokenStruct, MAX_JSON_TOKEN_EXPECTED); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d", tokenCount); - return; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object"); - return; - } - - jsmntok_t *jobs; - - jobs = findToken("inProgressJobs", params->payload, jsonTokenStruct); - - if (jobs) { - IOT_INFO("inProgressJobs: %.*s", jobs->end - jobs->start, (char *)params->payload + jobs->start); - } - - jobs = findToken("queuedJobs", params->payload, jsonTokenStruct); - - if (jobs) { - IOT_INFO("queuedJobs: %.*s", jobs->end - jobs->start, (char *)params->payload + jobs->start); - } - - AwsIotDescribeJobExecutionRequest describeRequest; - describeRequest.executionNumber = 0; - describeRequest.includeJobDocument = true; - describeRequest.clientToken = NULL; - - rc = aws_iot_jobs_describe(&client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_NEXT, &describeRequest, topicToPublishGetNext, sizeof(topicToPublishGetNext), NULL, 0); -} - -void iot_next_job_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char topicToPublishUpdate[MAX_JOB_TOPIC_LENGTH_BYTES]; - char messageBuffer[200]; - - IOT_UNUSED(pClient); - IOT_INFO("\nJOB_NOTIFY_NEXT_TOPIC / JOB_DESCRIBE_TOPIC($next) callback"); - IOT_INFO("topic: %.*s", topicNameLen, topicName); - IOT_INFO("payload: %.*s", (int) params->payloadLen, (char *)params->payload); - - jsmn_init(&jsonParser); - - tokenCount = jsmn_parse(&jsonParser, params->payload, (int) params->payloadLen, jsonTokenStruct, MAX_JSON_TOKEN_EXPECTED); - - if(tokenCount < 0) { - IOT_WARN("Failed to parse JSON: %d", tokenCount); - return; - } - - /* Assume the top-level element is an object */ - if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { - IOT_WARN("Top Level is not an object"); - return; - } - - jsmntok_t *tokExecution; - - tokExecution = findToken("execution", params->payload, jsonTokenStruct); - - if (tokExecution) { - IOT_INFO("execution: %.*s", tokExecution->end - tokExecution->start, (char *)params->payload + tokExecution->start); - - jsmntok_t *tok; - - tok = findToken("jobId", params->payload, tokExecution); - - if (tok) { - IoT_Error_t rc; - char jobId[MAX_SIZE_OF_JOB_ID + 1]; - AwsIotJobExecutionUpdateRequest updateRequest; - - rc = parseStringValue(jobId, MAX_SIZE_OF_JOB_ID + 1, params->payload, tok); - if(SUCCESS != rc) { - IOT_ERROR("parseStringValue returned error : %d ", rc); - return; - } - - IOT_INFO("jobId: %s", jobId); - - tok = findToken("jobDocument", params->payload, tokExecution); - - /* - * Do your job processing here. - */ - - if (tok) { - IOT_INFO("jobDocument: %.*s", tok->end - tok->start, (char *)params->payload + tok->start); - /* Alternatively if the job still has more steps the status can be set to JOB_EXECUTION_IN_PROGRESS instead */ - updateRequest.status = JOB_EXECUTION_SUCCEEDED; - updateRequest.statusDetails = "{\"exampleDetail\":\"a value appropriate for your successful job\"}"; - } else { - updateRequest.status = JOB_EXECUTION_FAILED; - updateRequest.statusDetails = "{\"failureDetail\":\"Unable to process job document\"}"; - } - - updateRequest.expectedVersion = 0; - updateRequest.executionNumber = 0; - updateRequest.includeJobExecutionState = false; - updateRequest.includeJobDocument = false; - updateRequest.clientToken = NULL; - - rc = aws_iot_jobs_send_update(pClient, QOS0, AWS_IOT_MY_THING_NAME, jobId, &updateRequest, - topicToPublishUpdate, sizeof(topicToPublishUpdate), messageBuffer, sizeof(messageBuffer)); - } - } else { - IOT_INFO("execution property not found, nothing to do, jobs integration test complete"); - - bool *callbackDone = (bool *) pData; - *callbackDone = true; - } -} - -int aws_iot_jobs_basic_test() { - char certDirectory[15] = "../../certs"; - char clientCRT[PATH_MAX + 1]; - char root_CA[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - char CurrentWD[PATH_MAX + 1]; - char clientId[50]; - char cPayload[100]; - IoT_Client_Init_Params initParams = IoT_Client_Init_Params_initializer; - IoT_Client_Connect_Params connectParams; - IoT_Publish_Message_Params paramsQOS0; - IoT_Error_t rc = SUCCESS; - struct timeval connectTime, waitCallBackTime; - struct timeval start, end; - unsigned int connectCounter = 0; - - IOT_DEBUG("\nConnecting Client "); - do { - getcwd(CurrentWD, sizeof(CurrentWD)); - snprintf(root_CA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - srand((unsigned int)time(NULL)); - snprintf(clientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID, rand() % 10000); - - printf("\n\nClient ID : %s \n", clientId); - - IOT_DEBUG("Root CA Path : %s\n clientCRT : %s\n clientKey : %s\n", root_CA, clientCRT, clientKey); - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = AWS_IOT_MQTT_PORT; - initParams.pRootCALocation = root_CA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 10000; - initParams.tlsHandshakeTimeout_ms = 10000; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - aws_iot_mqtt_init(&client, &initParams); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = (char *)&clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = false; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_connect(&client, &connectParams); - gettimeofday(&end, NULL); - timersub(&end, &start, &connectTime); - - connectCounter++; - } while(rc != SUCCESS && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - IOT_DEBUG("## Connect Success. Time sec: %ld, usec: %ld\n", (long int)connectTime.tv_sec, (long int)connectTime.tv_usec); - } else { - IOT_ERROR("## Connect Failed. error code %d\n", rc); - return -1; - } - - bool callbackDone = false; - char topicToSubscribeGetPending[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeNotifyNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - char topicToSubscribeGetNext[MAX_JOB_TOPIC_LENGTH_BYTES]; - - char topicToPublishGetPending[MAX_JOB_TOPIC_LENGTH_BYTES]; - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, NULL, JOB_GET_PENDING_TOPIC, JOB_WILDCARD_REPLY_TYPE, - iot_get_pending_callback_handler, &callbackDone, topicToSubscribeGetPending, sizeof(topicToSubscribeGetPending)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_GET_PENDING_TOPIC: %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, NULL, JOB_NOTIFY_NEXT_TOPIC, JOB_REQUEST_TYPE, - iot_next_job_callback_handler, &callbackDone, topicToSubscribeNotifyNext, sizeof(topicToSubscribeNotifyNext)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_NOTIFY_NEXT_TOPIC: %d ", rc); - return rc; - } - - rc = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, AWS_IOT_MY_THING_NAME, JOB_ID_NEXT, JOB_DESCRIBE_TOPIC, JOB_WILDCARD_REPLY_TYPE, - iot_next_job_callback_handler, &callbackDone, topicToSubscribeGetNext, sizeof(topicToSubscribeGetNext)); - - if(SUCCESS != rc) { - IOT_ERROR("Error subscribing JOB_DESCRIBE_TOPIC ($next): %d ", rc); - return rc; - } - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - paramsQOS0.payloadLen = strlen(cPayload); - - rc = aws_iot_jobs_send_query(&client, QOS0, AWS_IOT_MY_THING_NAME, NULL, NULL, topicToPublishGetPending, sizeof(topicToPublishGetPending), NULL, 0, JOB_GET_PENDING_TOPIC); - gettimeofday(&start, NULL); - while (!callbackDone) { - aws_iot_mqtt_yield(&client, 5000); - - gettimeofday(&end, NULL); - timersub(&end, &start, &waitCallBackTime); - - if(waitCallBackTime.tv_sec > 10) break; - } - - return 0; -} - -#endif -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_multiple_clients.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_multiple_clients.c deleted file mode 100644 index 3ea85aae4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/integration/src/aws_iot_test_multiple_clients.c +++ /dev/null @@ -1,286 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_test_multiple_clients.c - * @brief Integration Test for multiple clients from the same application - */ - -#include "aws_iot_test_integration_common.h" - - -#define MAX_ERROR_DISPLAY 50 -static bool terminate_yield_thread; - -static unsigned int countArray[PUBLISH_COUNT]; -static unsigned int rxMsgBufferTooBigCounter; -static unsigned int rxUnexpectedNumberCounter; -static unsigned int rePublishCount; - -static void aws_iot_mqtt_tests_message_aggregator(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char tempBuf[10]; - unsigned int tempInt = 0; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - if(10 >= params->payloadLen) { - snprintf(tempBuf, params->payloadLen, params->payload); - printf("\nMsg received : %s", tempBuf); - tempInt = atoi(tempBuf); - if(0 < tempInt && PUBLISH_COUNT >= tempInt) { - countArray[tempInt - 1]++; - } else { - rxUnexpectedNumberCounter++; - } - } else { - if( params->payloadLen > MAX_ERROR_DISPLAY) - { - ((char *)params->payload)[MAX_ERROR_DISPLAY-1] = '\0'; - IOT_ERROR("\nWrong Msg received : %s", (char *)params->payload); - }else - { - IOT_ERROR("\nWrong Msg received : %s", (char *)params->payload); - } - rxMsgBufferTooBigCounter++; - } -} - -static void aws_iot_mqtt_tests_disconnect_callback_handler(AWS_IoT_Client *pClient, void *param) { - IOT_UNUSED(pClient); - IOT_UNUSED(param); -} - -static IoT_Error_t aws_iot_mqtt_tests_connect_client_to_service(AWS_IoT_Client *pClient, struct timeval *pConnectTime, - char *clientId, char *rootCA, char *clientCRT, - char *clientKey) { - IoT_Client_Init_Params initParams; - IoT_Client_Connect_Params connectParams; - IoT_Error_t rc; - struct timeval start, end; - - initParams.pHostURL = AWS_IOT_MQTT_HOST; - initParams.port = AWS_IOT_MQTT_PORT; - initParams.pRootCALocation = rootCA; - initParams.pDeviceCertLocation = clientCRT; - initParams.pDevicePrivateKeyLocation = clientKey; - initParams.mqttCommandTimeout_ms = 5000; - initParams.tlsHandshakeTimeout_ms = 2000; - initParams.mqttPacketTimeout_ms = 5000; - initParams.isSSLHostnameVerify = true; - initParams.disconnectHandlerData = NULL; - initParams.isBlockOnThreadLockEnabled = true; - initParams.disconnectHandler = aws_iot_mqtt_tests_disconnect_callback_handler; - initParams.enableAutoReconnect = false; - rc = aws_iot_mqtt_init(pClient, &initParams); - printf("\n Init response : %d", rc); - - printf("\nRoot CA Path : %s\nClientCRT : %s\nClientKey : %s \nClient ID : %s", rootCA, clientCRT, - clientKey, clientId); - connectParams.keepAliveIntervalInSec = 5; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - connectParams.pClientID = clientId; - connectParams.clientIDLen = strlen(clientId); - connectParams.isWillMsgPresent = 0; - connectParams.pUsername = NULL; - connectParams.usernameLen = 0; - connectParams.pPassword = NULL; - connectParams.passwordLen = 0; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_connect(pClient, &connectParams); - printf("\nConnect response : %d ", rc); - gettimeofday(&end, NULL); - timersub(&end, &start, pConnectTime); - - return rc; -} - -static IoT_Error_t aws_iot_mqtt_tests_subscribe_to_test_topic(AWS_IoT_Client *pClient, QoS qos, struct timeval *pSubscribeTime) { - IoT_Error_t rc = SUCCESS; - struct timeval start, end; - - gettimeofday(&start, NULL); - rc = aws_iot_mqtt_subscribe(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), qos, - aws_iot_mqtt_tests_message_aggregator, NULL); - printf("\nSub response : %d\n", rc); - gettimeofday(&end, NULL); - - timersub(&end, &start, pSubscribeTime); - - return rc; -} - -static void *aws_iot_mqtt_tests_yield_thread_runner(void *ptr) { - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - while(SUCCESS == rc && false == terminate_yield_thread) { - do { - usleep(THREAD_SLEEP_INTERVAL_USEC); - rc = aws_iot_mqtt_yield(pClient, 100); - } while(MQTT_CLIENT_NOT_IDLE_ERROR == rc); - - if(SUCCESS != rc) { - IOT_ERROR("\nYield Returned : %d ", rc); - } - } - - return NULL; -} - -static void *aws_iot_mqtt_tests_publish_thread_runner(void *ptr) { - int itr = 0; - char cPayload[10]; - IoT_Publish_Message_Params params; - IoT_Error_t rc = SUCCESS; - AWS_IoT_Client *pClient = (AWS_IoT_Client *) ptr; - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - sprintf(cPayload, "%d", itr + 1); - params.payload = (void *) cPayload; - params.payloadLen = strlen(cPayload) + 1; - params.qos = QOS1; - params.isRetained = 0; - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - printf("\n Publishing %s", cPayload); - if(SUCCESS != rc) { - printf("Error Publishing #%d --> %d\n ", itr, rc); - usleep(300000); - rc = aws_iot_mqtt_publish(pClient, INTEGRATION_TEST_TOPIC, strlen(INTEGRATION_TEST_TOPIC), ¶ms); - rePublishCount++; - if(SUCCESS != rc) { - printf("Error Publishing #%d --> %d Second Attempt \n", itr, rc); - } - } - usleep(300000); - } - - return NULL; -} - - -int aws_iot_mqtt_tests_multiple_clients() { - char certDirectory[15] = "../../certs"; - char CurrentWD[PATH_MAX + 1]; - char rootCA[PATH_MAX + 1]; - char clientCRT[PATH_MAX + 1]; - char clientKey[PATH_MAX + 1]; - - char subClientId[50]; - char pubClientId[50]; - - int itr = 0; - int rxMsgCount = 0; - int test_result = 0; - int pubThreadReturn = 0; - int yieldThreadReturn = 0; - unsigned int connectCounter = 0; - float percentOfRxMsg = 0.0; - - IoT_Error_t rc = SUCCESS; - pthread_t yield_thread; - pthread_t publish_thread; - struct timeval connectTime; - struct timeval subscribeTopic; - - AWS_IoT_Client pubClient; - AWS_IoT_Client subClient; - - terminate_yield_thread = false; - rxMsgBufferTooBigCounter = 0; - rxUnexpectedNumberCounter = 0; - rePublishCount = 0; - - srand((unsigned int)time(NULL)); - snprintf(subClientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID_SUB, rand() % 10000); - snprintf(pubClientId, 50, "%s_%d", INTEGRATION_TEST_CLIENT_ID_PUB, rand() % 10000); - - getcwd(CurrentWD, sizeof(CurrentWD)); - - snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); - snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); - snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - countArray[itr] = 0; - } - - printf(" \n Connecting Pub Client "); - do { - rc = aws_iot_mqtt_tests_connect_client_to_service(&pubClient, &connectTime, pubClientId, rootCA, - clientCRT, clientKey); - connectCounter++; - } while(SUCCESS != rc && CONNECT_MAX_ATTEMPT_COUNT > connectCounter); - - if(SUCCESS == rc) { - printf("\n## Connect Success. Time sec: %ld, usec: %ld\n", (long int)connectTime.tv_sec, (long int)connectTime.tv_usec); - } else { - printf("\n## Connect Failed. error code %d\n", rc); - return -1; - } - - printf("\n Connecting Sub Client "); - do { - rc = aws_iot_mqtt_tests_connect_client_to_service(&subClient, &connectTime, subClientId, rootCA, - clientCRT, clientKey); - connectCounter++; - } while(SUCCESS != rc && connectCounter < CONNECT_MAX_ATTEMPT_COUNT); - - if(SUCCESS == rc) { - printf("## Connect Success. Time sec: %ld, usec: %ld\n", (long int)connectTime.tv_sec, (long int)connectTime.tv_usec); - } else { - printf("## Connect Failed. error code %d\n", rc); - return -1; - } - - aws_iot_mqtt_tests_subscribe_to_test_topic(&subClient, QOS1, &subscribeTopic); - - yieldThreadReturn = pthread_create(&yield_thread, NULL, aws_iot_mqtt_tests_yield_thread_runner, &subClient); - pubThreadReturn = pthread_create(&publish_thread, NULL, aws_iot_mqtt_tests_publish_thread_runner, &pubClient); - - pthread_join(publish_thread, NULL); - - /* Kill yield thread */ - terminate_yield_thread = true; - pthread_join(yield_thread, NULL); - - aws_iot_mqtt_disconnect(&pubClient); - aws_iot_mqtt_disconnect(&subClient); - - for(itr = 0; itr < PUBLISH_COUNT; itr++) { - if(countArray[itr] > 0) { - rxMsgCount++; - } - } - - percentOfRxMsg = (float) rxMsgCount * 100 / PUBLISH_COUNT; - if(percentOfRxMsg >= RX_RECEIVE_PERCENTAGE && rxMsgBufferTooBigCounter == 0 && rxUnexpectedNumberCounter == 0) { - printf("\nSuccess: %f \%\n", percentOfRxMsg); - printf("Published Messages: %d , Received Messages: %d \n", PUBLISH_COUNT, rxMsgCount); - printf("QoS 1 re publish count %d\n", rePublishCount); - printf("Connection Attempts %d\n", connectCounter); - test_result = 0; - } else { - printf("\nFailure: %f\n", percentOfRxMsg); - printf("\"Received message was too big than anything sent\" count: %d\n", rxMsgBufferTooBigCounter); - printf("\"The number received is out of the range\" count: %d\n", rxUnexpectedNumberCounter); - test_result = -2; - } - return test_result; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/README.md deleted file mode 100644 index a58e2e475..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## Unit Tests -This folder contains unit tests to verify Embedded C SDK functionality. These have been tested to work with Linux using CppUTest as the testing framework. -CppUTest is not provided along with this code. It needs to be separately downloaded. These tests have been verified to work with CppUTest v3.6, which can be found [here](https://github.com/cpputest/cpputest/tree/v3.6). -Each test contains a comment describing what is being tested. The Tests can be run using the Makefile provided in the root folder for the SDK. There are a total of 187 tests. - -To run these tests, follow the below steps: - - * Copy the code for CppUTest v3.6 from github to external_libs/CppUTest - * Navigate to SDK Root folder - * run `make run-unit-tests` - -This will run all unit tests and generate coverage report in the build_output folder. The report can be viewed by opening /build_output/generated-coverage/index.html in a browser. \ No newline at end of file diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_config.h deleted file mode 100644 index b75d6e3b4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_config.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_config.h - * @brief IoT Client Unit Testing - IoT Config - */ - -#ifndef IOT_TESTS_UNIT_CONFIG_H_ -#define IOT_TESTS_UNIT_CONFIG_H_ - -// Get from console -// ================================================= -#define AWS_IOT_MQTT_HOST "localhost" -#define AWS_IOT_MQTT_PORT 443 -#define AWS_IOT_MQTT_CLIENT_ID "C-SDK_UnitTestClient" -#define AWS_IOT_MY_THING_NAME "C-SDK_UnitTestThing" -#define AWS_IOT_ROOT_CA_FILENAME "rootCA.crt" -#define AWS_IOT_CERTIFICATE_FILENAME "cert.crt" -#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem" -// ================================================= - - -// MQTT PubSub -#ifndef DISABLE_IOT_JOBS -#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#else -#define AWS_IOT_MQTT_RX_BUF_LEN 2048 -#endif -#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Shadow and Job common configs -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10 ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20 ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_SIZE_OF_THING_NAME 30 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger - -// Thing Shadow specific configs -#define SHADOW_MAX_SIZE_OF_RX_BUFFER 512 ///< Maximum size of the SHADOW buffer to store the received Shadow message -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the format $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SHADOW_TOPIC_LENGTH_BYTES MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME ///< This size includes the length of topic with Thing Name - -// Job specific configs -#ifndef DISABLE_IOT_JOBS -#define MAX_SIZE_OF_JOB_ID 64 -#define MAX_JOB_JSON_TOKEN_EXPECTED 120 -#define MAX_SIZE_OF_JOB_REQUEST AWS_IOT_MQTT_TX_BUF_LEN - -#define MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME 40 -#define MAX_JOB_TOPIC_LENGTH_BYTES MAX_JOB_TOPIC_LENGTH_WITHOUT_JOB_ID_OR_THING_NAME + MAX_SIZE_OF_THING_NAME + MAX_SIZE_OF_JOB_ID + 2 -#endif - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#endif /* IOT_TESTS_UNIT_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_helper_functions.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_helper_functions.h deleted file mode 100644 index 337353af4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_helper_functions.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_helper_functions.h - * @brief IoT Client Unit Testing - Helper Functions - */ - -#ifndef IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_ -#define IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_ - -#include -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_jobs_topics.h" - -typedef struct { - unsigned char PacketType; - unsigned int RemainingLength; - unsigned int ProtocolLength; - unsigned char ProtocolName[4]; - unsigned int ProtocolLevel; - unsigned char ConnectFlag; - unsigned int KeepAlive; -} ConnectBufferProofread; - -void ResetInvalidParameters(void); - -void InitMQTTParamsSetup(IoT_Client_Init_Params *params, char *pHost, uint16_t port, bool enableAutoReconnect, - iot_disconnect_handler disconnectHandler); - -void ConnectMQTTParamsSetup(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen); - -void ConnectMQTTParamsSetup_Detailed(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen, - QoS qos, bool isCleanSession, bool isWillMsgPresent, char *pWillTopicName, - uint16_t willTopicNameLen, char *pWillMessage, uint16_t willMsgLen, - char *pUsername, uint16_t userNameLen, char *pPassword, - uint16_t passwordLen); - -void printBuffer(unsigned char *buffer, size_t len); - -void setTLSRxBufferForConnack(IoT_Client_Connect_Params *params, unsigned char sessionPresent, - unsigned char connackResponseCode); - -void setTLSRxBufferForPuback(void); - -void setTLSRxBufferForSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params); - -void setTLSRxBufferForDoubleSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params); - -void setTLSRxBufferForSubFail(void); - -void setTLSRxBufferWithMsgOnSubscribedTopic(char *topicName, size_t topicNameLen, QoS qos, - IoT_Publish_Message_Params params, char *pMsg); - -void setTLSRxBufferForUnsuback(void); - -void setTLSRxBufferForPingresp(void); - -void setTLSRxBufferForError(IoT_Error_t error); - -void setTLSTxBufferForError(IoT_Error_t error); - -void setTLSRxBufferForConnackAndSuback(IoT_Client_Connect_Params *conParams, unsigned char sessionPresent, - char *topicName, size_t topicNameLen, QoS qos); - -unsigned char isLastTLSTxMessagePuback(void); - -unsigned char isLastTLSTxMessagePingreq(void); - -unsigned char isLastTLSTxMessageDisconnect(void); - -void setTLSRxBufferDelay(int seconds, int microseconds); - -void ResetTLSBuffer(void); - -unsigned char generateMultipleSubTopics(char *des, int boundary); - -void encodeRemainingLength(unsigned char *buf, size_t *st, size_t length); - -unsigned char *connectTxBufferHeaderParser(ConnectBufferProofread *params, unsigned char *buf); - -bool isConnectTxBufFlagCorrect(IoT_Client_Connect_Params *settings, ConnectBufferProofread *readRes); - -bool isConnectTxBufPayloadCorrect(IoT_Client_Connect_Params *settings, unsigned char *payloadBuf); - -void printPrfrdParams(ConnectBufferProofread *params); - -const char *getJobTopicTypeName(AwsIotJobExecutionTopicType topicType); - -const char *getJobReplyTypeName(AwsIotJobExecutionTopicReplyType replyType); - -#endif /* IOT_TESTS_UNIT_HELPER_FUNCTIONS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_shadow_helper.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_shadow_helper.h deleted file mode 100644 index 455a387b3..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/include/aws_iot_tests_unit_shadow_helper.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_shadow_helper.h - * @brief IoT Client Unit Testing - Shadow Helper functions - */ - -#ifndef IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_ -#define IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_ - -#define AWS_THINGS_TOPIC "$aws/things/" -#define SHADOW_TOPIC "/shadow/" -#define ACCEPTED_TOPIC "/accepted" -#define REJECTED_TOPIC "/rejected" -#define UPDATE_TOPIC "update" -#define GET_TOPIC "get" -#define DELETE_TOPIC "delete" - - -#define GET_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC ACCEPTED_TOPIC -#define GET_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC REJECTED_TOPIC -#define GET_PUB_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC GET_TOPIC - -#define DELETE_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC DELETE_TOPIC ACCEPTED_TOPIC -#define DELETE_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC DELETE_TOPIC REJECTED_TOPIC - -#define UPDATE_ACCEPTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC UPDATE_TOPIC ACCEPTED_TOPIC -#define UPDATE_REJECTED_TOPIC AWS_THINGS_TOPIC AWS_IOT_MY_THING_NAME SHADOW_TOPIC UPDATE_TOPIC REJECTED_TOPIC - -#endif /* IOT_TESTS_UNIT_SHADOW_HELPER_FUNCTIONS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests.cpp deleted file mode 100644 index 449647ecc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_common_tests.cpp - * @brief IoT Client Unit Testing - Common Tests - */ - -#include -#include - -TEST_GROUP_C(CommonTests){ - TEST_GROUP_C_SETUP_WRAPPER(CommonTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(CommonTests) -}; - -TEST_GROUP_C_WRAPPER(CommonTests, NullClientGetState) -TEST_GROUP_C_WRAPPER(CommonTests, NullClientSetAutoreconnect) - -TEST_GROUP_C_WRAPPER(CommonTests, UnexpectedAckFiltering) -TEST_GROUP_C_WRAPPER(CommonTests, BigMQTTRxMessageIgnore) -TEST_GROUP_C_WRAPPER(CommonTests, BigMQTTRxMessageReadNextMessage) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests_helper.c deleted file mode 100644 index 9d1604211..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_common_tests_helper.c +++ /dev/null @@ -1,186 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_common_tests_helper.h - * @brief IoT Client Unit Testing - Common Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_log.h" -#include "aws_iot_tests_unit_helper_functions.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static AWS_IoT_Client iotClient; - -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; -char cPayload[100]; - -char cbBuffer[AWS_IOT_MQTT_TX_BUF_LEN + 2]; - -static void iot_tests_unit_common_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, IoT_Publish_Message_Params *params, - void *pData) { - char *tmp = params->payload; - unsigned int i; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - for(i = 0; i < params->payloadLen; i++) { - cbBuffer[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(CommonTests) { - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - IoT_Error_t rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("\n\nMQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(CommonTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -TEST_C(CommonTests, NullClientGetState) { - ClientState cs = aws_iot_mqtt_get_client_state(NULL); - CHECK_EQUAL_C_INT(CLIENT_STATE_INVALID, cs); -} - -TEST_C(CommonTests, NullClientSetAutoreconnect) { - IoT_Error_t rc = aws_iot_mqtt_autoreconnect_set_status(NULL, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -// Unexpected Ack section -TEST_C(CommonTests, UnexpectedAckFiltering) { - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("\n-->Running CommonTests - Unexpected Ack Filtering\n"); - // Assume we are connected and have not done anything yet - // Connack - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Puback - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Suback: OoS1 - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Suback: QoS0 - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Unsuback - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); -} - -TEST_C(CommonTests, BigMQTTRxMessageIgnore) { - uint32_t i = 0; - IoT_Error_t rc = FAILURE; - char expectedCallbackString[AWS_IOT_MQTT_RX_BUF_LEN + 2]; - - IOT_DEBUG("\n-->Running CommonTests - Ignore Large Incoming Message \n"); - - setTLSRxBufferForSuback("limitTest/topic1", 16, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "limitTest/topic1", 16, QOS0, iot_tests_unit_common_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - for(i = 0; i < AWS_IOT_MQTT_RX_BUF_LEN; i++) { - expectedCallbackString[i] = 'X'; - } - expectedCallbackString[i + 1] = '\0'; - - setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, rc); -} - -/** - * - * On receiving a big message into the TLS buffer the MQTT client should flush it out, otherwise it can cause undefined behavior. - */ -TEST_C(CommonTests, BigMQTTRxMessageReadNextMessage) { - uint32_t i = 0; - IoT_Error_t rc = FAILURE; - char expectedCallbackString[AWS_IOT_MQTT_RX_BUF_LEN + 2]; - - IOT_DEBUG("\n-->Running CommonTests - Clear Buffer when large message received and continue reading \n"); - - setTLSRxBufferForSuback("limitTest/topic1", 16, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "limitTest/topic1", 16, QOS0, iot_tests_unit_common_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - for(i = 0; i < AWS_IOT_MQTT_RX_BUF_LEN; i++) { - expectedCallbackString[i] = 'X'; - } - expectedCallbackString[i + 1] = '\0'; - - setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, rc); - - ResetTLSBuffer(); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - expectedCallbackString[3] = '\0'; - setTLSRxBufferWithMsgOnSubscribedTopic("limitTest/topic1", 16, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(rc, SUCCESS); - CHECK_EQUAL_C_STRING("XXX", cbBuffer); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect.cpp deleted file mode 100644 index 5b7ae0897..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_connect.cpp - * @brief IoT Client Unit Testing - Connect API Tests - */ - -#include -#include - -TEST_GROUP_C(ConnectTests){ - TEST_GROUP_C_SETUP_WRAPPER(ConnectTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(ConnectTests) -}; - -/* B:1 - Init with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientInit) -/* B:2 - Connect with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientConnect) -/* B:3 - Connect with Null/Empty endpoint */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullHost) -/* B:4 - Connect with Null/Empty port */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullPort) -/* B:5 - Connect with Null/Empty root CA path */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullRootCAPath) -/* B:6 - Connect with Null/Empty Client certificate path */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientCertificate) -/* B:7 - Connect with Null/Empty private key Path */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullPrivateKeyPath) -/* B:8 - Connect with Null/Empty client ID */ -TEST_GROUP_C_WRAPPER(ConnectTests, NullClientID) -/* B:9 - Connect with invalid Endpoint */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidEndpoint) -/* B:10 - Connect with invalid correct endpoint but invalid port */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidPort) -/* B:11 - Connect with invalid Root CA path */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidRootCAPath) -/* B:12 - Connect with invalid Client certificate path */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidClientCertPath) -/* B:13 - Connect with invalid private key path */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidPrivateKeyPath) -/* B:14 - Connect, no response timeout */ -TEST_GROUP_C_WRAPPER(ConnectTests, NoResponseTimeout) -/* B:15 - Connect, connack malformed, too large */ -TEST_GROUP_C_WRAPPER(ConnectTests, ConnackTooLarge) -/* B:16 - Connect, connack malformed, fixed header corrupted */ -TEST_GROUP_C_WRAPPER(ConnectTests, FixedHeaderCorrupted) -/* B:17 - Connect, connack malformed, invalid remaining length */ -TEST_GROUP_C_WRAPPER(ConnectTests, InvalidRemainingLength) -/* B:18 - Connect, connack returned error, unacceptable protocol version */ -TEST_GROUP_C_WRAPPER(ConnectTests, UnacceptableProtocolVersion) -/* B:19 - Connect, connack returned error, identifier rejected */ -TEST_GROUP_C_WRAPPER(ConnectTests, IndentifierRejected) -/* B:20 - Connect, connack returned error, Server unavailable */ -TEST_GROUP_C_WRAPPER(ConnectTests, ServerUnavailable) -/* B:21 - Connect, connack returned error, bad user name or password */ -TEST_GROUP_C_WRAPPER(ConnectTests, BadUserNameOrPassword) -/* B:22 - Connect, connack returned error, not authorized */ -TEST_GROUP_C_WRAPPER(ConnectTests, NotAuthorized) -/* B:23 - Connect, connack return after half command timeout delay, success */ -TEST_GROUP_C_WRAPPER(ConnectTests, SuccessAfterDelayedConnack) -/* B:24 - Connect, connack returned success */ -TEST_GROUP_C_WRAPPER(ConnectTests, ConnectSuccess) -/* B:25 - Connect, flag settings and parameters are recorded in buffer */ -TEST_GROUP_C_WRAPPER(ConnectTests, FlagSettingsAndParamsAreRecordedIntoBuf) -/* B:26 - Connect attempt, Disconnect, Manually reconnect */ -TEST_GROUP_C_WRAPPER(ConnectTests, ConnectDisconnectConnect) -/* B:27 - Connect attempt, Clean session, Subscribe */ -TEST_GROUP_C_WRAPPER(ConnectTests, cleanSessionInitSubscribers) -/* B:28 - Connect attempt, power cycle with clean session false */ -TEST_GROUP_C_WRAPPER(ConnectTests, PowerCycleWithCleanSessionFalse) -/* B:29 - Reconnect attempt succeeds, but resubscribes fail */ -TEST_GROUP_C_WRAPPER(ConnectTests, ReconnectAndResubscribe) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect_helper.c deleted file mode 100644 index 40a0298cc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_connect_helper.c +++ /dev/null @@ -1,792 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_connect_helper.c - * @brief IoT Client Unit Testing - Connect API Tests Helper - */ - -#include -#include -#include -#include -#include - -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" - -#include "aws_iot_log.h" - -#include "aws_iot_mqtt_client_common_internal.h" - -static bool unitTestIsMqttConnected = false; - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static AWS_IoT_Client iotClient; - -static IoT_Publish_Message_Params testPubMsgParams; -static ConnectBufferProofread prfrdParams; - -static char subTopic1[12] = "sdk/Topic1"; -static char subTopic2[12] = "sdk/Topic2"; - -#define NO_MSG_XXXX "XXXX" -static char CallbackMsgStringclean[100] = NO_MSG_XXXX; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char *tmp = params->payload; - unsigned int i; - - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgStringclean[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(ConnectTests) { - unitTestIsMqttConnected = false; - ( void ) aws_iot_mqtt_disconnect(&iotClient); - ResetTLSBuffer(); - ResetInvalidParameters(); -} - -TEST_GROUP_C_TEARDOWN(ConnectTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -/* B:1 - Init with Null/empty client instance */ -TEST_C(ConnectTests, NullClientInit) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:1 - Init with Null/empty client instance \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(NULL, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:1 - Init with Null/empty client instance \n"); -} - -/* B:2 - Connect with Null/empty client instance */ -TEST_C(ConnectTests, NullClientConnect) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:2 - Connect with Null/empty client instance \n"); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(NULL, &connectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:2 - Connect with Null/empty client instance \n"); -} - -/* B:3 - Connect with Null/Empty endpoint */ -TEST_C(ConnectTests, NullHost) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:3 - Connect with Null/Empty endpoint \n"); - - InitMQTTParamsSetup(&initParams, NULL, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:3 - Connect with Null/Empty endpoint \n"); -} - -/* B:4 - Connect with Null/Empty port */ -TEST_C(ConnectTests, NullPort) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:4 - Connect with Null/Empty port \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, 0, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:4 - Connect with Null/Empty port \n"); -} - -/* B:5 - Connect with Null/Empty root CA path */ -TEST_C(ConnectTests, NullRootCAPath) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:6 - Connect with Null/Empty root CA path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.pRootCALocation = NULL; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:6 - Connect with Null/Empty root CA path \n"); -} - -/* B:6 - Connect with Null/Empty Client certificate path */ -TEST_C(ConnectTests, NullClientCertificate) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:7 - Connect with Null/Empty Client certificate path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.pDeviceCertLocation = NULL; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:7 - Connect with Null/Empty Client certificate path \n"); -} - -/* B:7 - Connect with Null/Empty private key Path */ -TEST_C(ConnectTests, NullPrivateKeyPath) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:8 - Connect with Null/Empty private key Path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.pDevicePrivateKeyLocation = NULL; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - B:8 - Connect with Null/Empty private key Path \n"); -} - -/* B:8 - Connect with Null/Empty client ID */ -TEST_C(ConnectTests, NullClientID) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:8 - Connect with Null/Empty client ID \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - setTLSRxBufferForConnack(&connectParams, 0, 0); - - /* If no client id is passed but a length was passed, return error */ - ConnectMQTTParamsSetup(&connectParams, NULL, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - /* If client id is passed but 0 length was passed, return error */ - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - /* If client id is NULL and length is 0 then request succeeds */ - ConnectMQTTParamsSetup(&connectParams, NULL, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - B:8 - Connect with Null/Empty client ID \n"); -} - -/* B:9 - Connect with invalid Endpoint */ -TEST_C(ConnectTests, InvalidEndpoint) { - IoT_Error_t rc = SUCCESS; - char invalidEndPoint[20]; - snprintf(invalidEndPoint, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:9 - Connect with invalid Endpoint \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidEndpointFilter = invalidEndPoint; - initParams.pHostURL = invalidEndpointFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:9 - Connect with invalid Endpoint \n"); -} - -/* B:10 - Connect with invalid correct endpoint but invalid port */ -TEST_C(ConnectTests, InvalidPort) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:10 - Connect with invalid correct endpoint but invalid port \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidPortFilter = 1234; - initParams.port = invalidPortFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:10 - Connect with invalid correct endpoint but invalid port \n"); -} - -/* B:11 - Connect with invalid Root CA path */ -TEST_C(ConnectTests, InvalidRootCAPath) { - IoT_Error_t rc = SUCCESS; - char invalidRootCAPath[20]; - snprintf(invalidRootCAPath, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:11 - Connect with invalid Root CA path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidRootCAPathFilter = invalidRootCAPath; - initParams.pRootCALocation = invalidRootCAPathFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:11 - Connect with invalid Root CA path \n"); -} - -/* B:12 - Connect with invalid Client certificate path */ -TEST_C(ConnectTests, InvalidClientCertPath) { - IoT_Error_t rc = SUCCESS; - char invalidCertPath[20]; - snprintf(invalidCertPath, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:12 - Connect with invalid Client certificate path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidCertPathFilter = invalidCertPath; - initParams.pDeviceCertLocation = invalidCertPathFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:12 - Connect with invalid Client certificate path \n"); -} - -/* B:13 - Connect with invalid private key path */ -TEST_C(ConnectTests, InvalidPrivateKeyPath) { - IoT_Error_t rc = SUCCESS; - char invalidPrivKeyPath[20]; - snprintf(invalidPrivKeyPath, 20, "invalid"); - - IOT_DEBUG("-->Running Connect Tests - B:13 - Connect with invalid private key path \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - invalidPrivKeyPathFilter = invalidPrivKeyPath; - initParams.pDevicePrivateKeyLocation = invalidPrivKeyPathFilter; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:13 - Connect with invalid private key path \n"); -} - -/* B:14 - Connect, no response timeout */ -TEST_C(ConnectTests, NoResponseTimeout) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:14 - Connect, no response timeout \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - B:14 - Connect, no response timeout \n"); -} - -/* B:15 - Connect, connack malformed, too large */ -TEST_C(ConnectTests, ConnackTooLarge) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:15 - Connect, connack malformed, too large \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - RxBuffer.pBuffer[1] = (char) (0x15); /* Set remaining length to a larger than expected value */ - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:15 - Connect, connack malformed, too large \n"); -} - -/* B:16 - Connect, connack malformed, fixed header corrupted */ -TEST_C(ConnectTests, FixedHeaderCorrupted) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:16 - Connect, connack malformed, fixed header corrupted \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - RxBuffer.pBuffer[0] = (char) (0x00); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_C(SUCCESS != rc); - - IOT_DEBUG("-->Success - B:16 - Connect, connack malformed, fixed header corrupted \n"); -} - -/* B:17 - Connect, connack malformed, invalid remaining length */ -TEST_C(ConnectTests, InvalidRemainingLength) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:17 - Connect, connack malformed, invalid remaining length \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - RxBuffer.pBuffer[1] = (char) (0x00); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_DECODE_REMAINING_LENGTH_ERROR, rc); - - IOT_DEBUG("-->Success - B:17 - Connect, connack malformed, invalid remaining length \n"); -} - -/* B:18 - Connect, connack returned error, unacceptable protocol version */ -TEST_C(ConnectTests, UnacceptableProtocolVersion) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:18 - Connect, connack returned error, unacceptable protocol version \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.MQTTVersion = 7; - setTLSRxBufferForConnack(&connectParams, 0, 1); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR, rc); - - IOT_DEBUG("-->Success - B:18 - Connect, connack returned error, unacceptable protocol version \n"); -} - -/* B:19 - Connect, connack returned error, identifier rejected */ -TEST_C(ConnectTests, IndentifierRejected) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:19 - Connect, connack returned error, identifier rejected \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 2); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR, rc); - - IOT_DEBUG("-->Success - B:19 - Connect, connack returned error, identifier rejected \n"); -} - -/* B:20 - Connect, connack returned error, Server unavailable */ -TEST_C(ConnectTests, ServerUnavailable) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:20 - Connect, connack returned error, Server unavailable \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 3); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR, rc); - - IOT_DEBUG("-->Success - B:20 - Connect, connack returned error, Server unavailable \n"); -} - -/* B:21 - Connect, connack returned error, bad user name or password */ -TEST_C(ConnectTests, BadUserNameOrPassword) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:21 - Connect, connack returned error, bad user name or password \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 4); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_BAD_USERDATA_ERROR, rc); - - IOT_DEBUG("-->Success - B:21 - Connect, connack returned error, bad user name or password \n"); -} - -/* B:22 - Connect, connack returned error, not authorized */ -TEST_C(ConnectTests, NotAuthorized) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("\n-->Running Connect Tests - B:22 - Connect, connack returned error, not authorized \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 5); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(MQTT_CONNACK_NOT_AUTHORIZED_ERROR, rc); - - IOT_DEBUG("\n-->Success - B:22 - Connect, connack returned error, not authorized \n"); -} - -/* B:23 - Connect, connack return after half command timeout delay, success */ -TEST_C(ConnectTests, SuccessAfterDelayedConnack) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:23 - Connect, connack return after half command timeout delay, success \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - setTLSRxBufferDelay(0, (int) initParams.mqttCommandTimeout_ms/2); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - B:23 - Connect, connack return after half command timeout delay, success \n"); -} - -/* B:24 - Connect, connack returned success */ -TEST_C(ConnectTests, ConnectSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:24 - Connect, connack returned success \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - B:24 - Connect, connack returned success \n"); -} - -/* B:25 - Connect, flag settings and parameters are recorded in buffer */ -TEST_C(ConnectTests, FlagSettingsAndParamsAreRecordedIntoBuf) { - IoT_Error_t rc = SUCCESS; - unsigned char *currPayload = NULL; - - IOT_DEBUG("-->Running Connect Tests - B:25 - Connect, flag settings and parameters are recorded in buffer \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - ConnectMQTTParamsSetup_Detailed(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID), - QOS1, false, true, "willTopicName", (uint16_t) strlen("willTopicName"), "willMsg", - (uint16_t) strlen("willMsg"), NULL, 0, NULL, 0); - connectParams.keepAliveIntervalInSec = (1 << 16) - 1; - setTLSRxBufferForConnack(&connectParams, 0, 0); - - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer); - CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams)); - CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload)); - - IOT_DEBUG("-->Success - B:25 - Connect, flag settings and parameters are recorded in buffer \n"); -} - -/* B:26 - Connect attempt, Disconnect, Manually reconnect */ -TEST_C(ConnectTests, ConnectDisconnectConnect) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Connect Tests - B:26 - Connect attempt, Disconnect, Manually reconnect \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - - // connect - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // check the is_connected call - unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(true, unitTestIsMqttConnected); - - // disconnect - rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // check the is_connected call - unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(false, unitTestIsMqttConnected); - - ResetTLSBuffer(); - setTLSRxBufferForConnack(&connectParams, 0, 0); - - // connect - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // check the is_connected call - unitTestIsMqttConnected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(true, unitTestIsMqttConnected); - - IOT_DEBUG("-->Success - B:26 - Connect attempt, Disconnect, Manually reconnect \n"); -} - -/* B:27 - Connect attempt, Clean session, Subscribe - * connect with clean session true and subscribe to a topic1, set msg to topic1 and ensure it is received - * connect cs false, set msg to topic1 and nothing should come in, Sub to topic2 and check if msg is received - * connect cs false and send msg to topic2 and should be received - * cs true and everything should be clean again - */ -TEST_C(ConnectTests, cleanSessionInitSubscribers) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "msg topic"; - - IOT_DEBUG("-->Running Connect Tests - B:27 - Connect attempt, Clean session, Subscribe \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); - - //1. connect with clean session true and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = true; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //1. subscribe to a topic1 and - testPubMsgParams.payload = expectedCallbackString; - testPubMsgParams.payloadLen = (uint16_t) strlen(expectedCallbackString); - setTLSRxBufferForSuback(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic1, (uint16_t) strlen(subTopic1), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - //1. receive message - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - ResetTLSBuffer(); - rc = aws_iot_mqtt_disconnect(&iotClient); - - //2. connect cs false and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = false; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - //3. set msg to topic1 and should receive the topic1 message - snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - ResetTLSBuffer(); - //4. ,sub to topic2 - snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX); - setTLSRxBufferForSuback(subTopic1, strlen(subTopic1), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic2, (uint16_t) strlen(subTopic2), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - //5. and check if topic 2 msg is received - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic2, strlen(subTopic2), QOS0, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - rc = aws_iot_mqtt_disconnect(&iotClient); - - //6. connect cs false and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = false; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //7. set msg to topic2 and - snprintf(CallbackMsgStringclean, 100, NO_MSG_XXXX); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic2, strlen(subTopic2), QOS0, testPubMsgParams, - expectedCallbackString); - //8. should be received - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgStringclean); - - IOT_DEBUG("-->Success - B:27 - Connect attempt, Clean session, Subscribe \n"); - -} - -/* B:28 - Connect attempt, power cycle with clean session false - * This test is to ensure we can initialize the subscribe table in mqtt even when connecting with CS = false - * currently the AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS is set to 5 - */ -TEST_C(ConnectTests, PowerCycleWithCleanSessionFalse) { - IoT_Error_t rc = SUCCESS; - int itr = 0; - char subTestTopic[12]; - uint16_t subTestTopicLen = 0; - - IOT_DEBUG("-->Running Connect Tests - B:28 - Connect attempt, power cycle with clean session false \n"); - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); - - //1. connect with clean session false and - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = true; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //2. subscribe to max number of topics - for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; itr++) { - snprintf(subTestTopic, 12, "sdk/topic%d", itr + 1); - subTestTopicLen = (uint16_t) strlen(subTestTopic); - setTLSRxBufferForSuback(subTestTopic, subTestTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTestTopic, subTestTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - //3. Subscribe to one more topic. Should return error - snprintf(subTestTopic, 12, "sdk/topic%d", itr + 1); - subTestTopicLen = (uint16_t) strlen(subTestTopic); - setTLSRxBufferForSuback(subTestTopic, subTestTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTestTopic, subTestTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc); - - IOT_DEBUG("-->Success - B:28 - Connect attempt, power cycle with clean session false \n"); -} - -/* B:29 - Reconnect attempt succeeds, but resubscribes fail. - * This test verifies the behaviour that if a subscribe operation fails after - * connect during the auto-reconnect sequence, the client must not disconnect - * and must only re-attempt the subscribe operation. */ -TEST_C(ConnectTests, ReconnectAndResubscribe) { - IoT_Error_t rc = SUCCESS; - int itr = 0; - char subTestTopic[12] = { 0 }; - uint16_t subTestTopicLen = 0; - IoT_Publish_Message_Params publish = { 0 }; - - IOT_DEBUG("-->Running Connect Tests - B:29 - Reconnect attempt succeeds, but resubscribes fail \n"); - - #if AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS < 3 - #error "ReconnectAndResubscribe needs at least 3 subscription handlers to run" - #endif - - // 1. Initialize client - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, true, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); - - // 2. Establish connection - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.isCleanSession = true; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // 3. Add 3 subscriptions - for(itr = 0; itr < 3; itr++) - { - snprintf(subTestTopic, 12, "sdk/topic%d", itr + 1); - subTestTopicLen = (uint16_t) strlen(subTestTopic); - setTLSRxBufferForSuback(subTestTopic, subTestTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTestTopic, subTestTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - // 4. Trigger a reconnect by mocking NETWORK_SSL_READ_ERROR and calling yield. - // Place a CONNACK and SUBACK in the Rx buffer so that connect and 1 subscribe - // succeed. Note that the CONNACK and SUBACK placed in the Rx buffer are not - // effected by the mocked error as it does not change thr content of the Rx - // buffer. - setTLSRxBufferForError(NETWORK_SSL_READ_ERROR); - setTLSRxBufferForConnackAndSuback(&connectParams, 0, "sdk/topic0", 10, QOS0); - rc = aws_iot_mqtt_yield(&iotClient, AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL * 2); - - // 5. Check results of yield call. As only 1 SUBACK was present in the Rx - // buffer, 2 resubscribes must fail. Client should be in a pending - // resubscribe state and the auto reconnect interval should have doubled. - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - CHECK_EQUAL_C_INT(1, iotClient.clientData.messageHandlers[0].resubscribed); - CHECK_EQUAL_C_INT(0, iotClient.clientData.messageHandlers[1].resubscribed); - CHECK_EQUAL_C_INT(0, iotClient.clientData.messageHandlers[2].resubscribed); - CHECK_EQUAL_C_INT(CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS, aws_iot_mqtt_get_client_state(&iotClient)); - CHECK_EQUAL_C_INT(2 * AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL, (int) iotClient.clientData.currentReconnectWaitInterval); - - // 6. Add 2 more SUBACKs to the Rx buffer to complete the resubscribe. - setTLSRxBufferForDoubleSuback("sdk/topic1", 10, QOS0, publish); - rc = aws_iot_mqtt_yield(&iotClient, 2 * AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL * 2); - CHECK_EQUAL_C_INT(CLIENT_STATE_CONNECTED_IDLE, aws_iot_mqtt_get_client_state(&iotClient)); - CHECK_EQUAL_C_INT(1, iotClient.clientData.messageHandlers[0].resubscribed); - CHECK_EQUAL_C_INT(1, iotClient.clientData.messageHandlers[1].resubscribed); - CHECK_EQUAL_C_INT(1, iotClient.clientData.messageHandlers[2].resubscribed); - - IOT_DEBUG("-->Success - B:29 - Reconnect attempt succeeds, but resubscribes fail \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect.cpp deleted file mode 100644 index 09edca39b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_disconnect.cpp - * @brief IoT Client Unit Testing - Disconnect API Tests - */ - -#include -#include - -TEST_GROUP_C(DisconnectTests){ - TEST_GROUP_C_SETUP_WRAPPER(DisconnectTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(DisconnectTests) -}; - -/* F:1 - Disconnect with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(DisconnectTests, NullClientDisconnect) -/* F:2 - Set Disconnect Handler with Null/empty Client */ -TEST_GROUP_C_WRAPPER(DisconnectTests, NullClientSetDisconnectHandler) -/* F:3 - Call Set Disconnect handler with Null handler */ -TEST_GROUP_C_WRAPPER(DisconnectTests, SetDisconnectHandlerNullHandler) -/* F:4 - Disconnect attempt, not connected */ -TEST_GROUP_C_WRAPPER(DisconnectTests, disconnectNotConnected) -/* F:5 - Disconnect success */ -TEST_GROUP_C_WRAPPER(DisconnectTests, disconnectNoAckSuccess) -/* F:6 - Disconnect, Handler invoked on disconnect */ -TEST_GROUP_C_WRAPPER(DisconnectTests, HandlerInvokedOnDisconnect) -/* F:7 - Disconnect, with set handler and invoked on disconnect */ -TEST_GROUP_C_WRAPPER(DisconnectTests, SetHandlerAndInvokedOnDisconnect) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect_helper.c deleted file mode 100644 index 681862b43..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_disconnect_helper.c +++ /dev/null @@ -1,244 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_disconnect_helper.c - * @brief IoT Client Unit Testing - Disconnect Tests helper - */ - -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static AWS_IoT_Client iotClient; - -static bool handlerInvoked = false; - -void disconnectTestHandler(AWS_IoT_Client *pClient, void *disconHandlerParam) { - IOT_UNUSED(pClient); - IOT_UNUSED(disconHandlerParam); - - handlerInvoked = true; -} - -TEST_GROUP_C_SETUP(DisconnectTests) { - IoT_Error_t rc; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, true, disconnectTestHandler); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.keepAliveIntervalInSec = 5; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(DisconnectTests) { } - - -/* F:1 - Disconnect with Null/empty client instance */ -TEST_C(DisconnectTests, NullClientDisconnect) { - IoT_Error_t rc = aws_iot_mqtt_disconnect(NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* F:2 - Set Disconnect Handler with Null/empty Client */ -TEST_C(DisconnectTests, NullClientSetDisconnectHandler) { - IoT_Error_t rc = aws_iot_mqtt_set_disconnect_handler(NULL, disconnectTestHandler, NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* F:3 - Call Set Disconnect handler with Null handler */ -TEST_C(DisconnectTests, SetDisconnectHandlerNullHandler) { - IoT_Error_t rc = aws_iot_mqtt_set_disconnect_handler(&iotClient, NULL, NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* F:4 - Disconnect attempt, not connected */ -TEST_C(DisconnectTests, disconnectNotConnected) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Disconnect Tests - F:4 - Disconnect attempt, not connected \n"); - - /* First make sure client is disconnected */ - rc = aws_iot_mqtt_disconnect(&iotClient); - - /* Check client is disconnected */ - CHECK_EQUAL_C_INT(false, aws_iot_mqtt_is_client_connected(&iotClient)); - - /* Now call disconnect again */ - rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - - IOT_DEBUG("-->Success - F:4 - Disconnect attempt, not connected \n"); -} - -/* F:5 - Disconnect success */ -TEST_C(DisconnectTests, disconnectNoAckSuccess) { - IoT_Error_t rc = SUCCESS; - rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(SUCCESS, rc); -} - -/* F:6 - Disconnect, Handler invoked on disconnect */ -TEST_C(DisconnectTests, HandlerInvokedOnDisconnect) { - bool connected = false; - bool currentAutoReconnectStatus = false; - int i; - int j; - int attempt = 3; - uint32_t dcCount = 0; - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Disconnect Tests - F:6 - Disconnect, Handler invoked on disconnect \n"); - - handlerInvoked = false; - - IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", connectParams.keepAliveIntervalInSec); - currentAutoReconnectStatus = aws_iot_is_autoreconnect_enabled(&iotClient); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(1, connected); - - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - - // 3 cycles of half keep alive time expiring - // verify a ping request is sent and give a ping response - for(i = 0; i < attempt; i++) { - /* Set TLS buffer for ping response */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - for(j = 0; j <= connectParams.keepAliveIntervalInSec; j++) { - sleep(1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq()); - } - - // keepalive() waits for 1/2 of keepalive time after sending ping request - // to receive a pingresponse before determining the connection is not alive - // wait for keepalive time and then yield() - sleep(connectParams.keepAliveIntervalInSec); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(0, connected); - - CHECK_EQUAL_C_INT(true, handlerInvoked); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(1 == dcCount); - - aws_iot_mqtt_reset_network_disconnected_count(&iotClient); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(0 == dcCount); - - ResetTLSBuffer(); - aws_iot_mqtt_autoreconnect_set_status(&iotClient, currentAutoReconnectStatus); - - IOT_DEBUG("-->Success - F:6 - Disconnect, Handler invoked on disconnect \n"); -} - - -/* F:7 - Disconnect, with set handler and invoked on disconnect */ -TEST_C(DisconnectTests, SetHandlerAndInvokedOnDisconnect) { - bool connected = false; - bool currentAutoReconnectStatus = false; - int i; - int j; - int attempt = 3; - uint32_t dcCount = 0; - IoT_Error_t rc = SUCCESS; - IOT_DEBUG("-->Running Disconnect Tests - F:7 - Disconnect, with set handler and invoked on disconnect \n"); - - handlerInvoked = false; - InitMQTTParamsSetup(&initParams, "localhost", AWS_IOT_MQTT_PORT, false, NULL); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - connectParams.keepAliveIntervalInSec = 5; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - aws_iot_mqtt_set_disconnect_handler(&iotClient, disconnectTestHandler, NULL); - aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - - IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", connectParams.keepAliveIntervalInSec); - currentAutoReconnectStatus = aws_iot_is_autoreconnect_enabled(&iotClient); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(1, connected); - - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - - // 3 cycles of keep alive time expiring - // verify a ping request is sent and give a ping response - for(i = 0; i < attempt; i++) { - /* Set TLS buffer for ping response */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - for(j = 0; j <= connectParams.keepAliveIntervalInSec; j++) { - sleep(1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq()); - } - ResetTLSBuffer(); - - // keepalive() waits for 1/2 of keepalive time after sending ping request - // to receive a pingresponse before determining the connection is not alive - // wait for keepalive time and then yield() - sleep(connectParams.keepAliveIntervalInSec); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(0, connected); - - CHECK_EQUAL_C_INT(true, handlerInvoked); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(1 == dcCount); - - aws_iot_mqtt_reset_network_disconnected_count(&iotClient); - - dcCount = aws_iot_mqtt_get_network_disconnected_count(&iotClient); - CHECK_C(0 == dcCount); - - ResetTLSBuffer(); - aws_iot_mqtt_autoreconnect_set_status(&iotClient, currentAutoReconnectStatus); - - IOT_DEBUG("-->Success - F:7 - Disconnect, with set handler and invoked on disconnect \n"); -} - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_helper_functions.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_helper_functions.c deleted file mode 100644 index 2f71b1435..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_helper_functions.c +++ /dev/null @@ -1,571 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_helper_functions.c - * @brief IoT Client Unit Testing - Helper Functions - */ - -#include -#include -#include "aws_iot_mqtt_client.h" -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_version.h" - -#if !DISABLE_METRICS -#define SDK_METRICS_LEN 25 -#define SDK_METRICS_TEMPLATE "?SDK=C&Version=%d.%d.%d" -static char pUsernameTemp[SDK_METRICS_LEN] = {0}; -#endif - -#define CONNACK_SUBACK_PACKET_SIZE 9 -#define PUBACK_PACKET_SIZE 4 -#define SUBACK_PACKET_SIZE 5 -#define UNSUBACK_PACKET_SIZE 4 -#define PINGRESP_PACKET_SIZE 2 - -void ResetInvalidParameters(void) { - invalidEndpointFilter = NULL; - invalidRootCAPathFilter = NULL; - invalidCertPathFilter = NULL; - invalidPrivKeyPathFilter = NULL; - invalidPortFilter = 0; -} - -void InitMQTTParamsSetup(IoT_Client_Init_Params *params, char *pHost, uint16_t port, bool enableAutoReconnect, - iot_disconnect_handler disconnectHandler) { - params->pHostURL = pHost; - params->port = port; - params->mqttCommandTimeout_ms = 5000; - params->tlsHandshakeTimeout_ms = 5000; - params->enableAutoReconnect = enableAutoReconnect; - params->disconnectHandler = disconnectHandler; - params->disconnectHandlerData = NULL; - params->isSSLHostnameVerify = true; - params->pDeviceCertLocation = AWS_IOT_ROOT_CA_FILENAME; - params->pDevicePrivateKeyLocation = AWS_IOT_CERTIFICATE_FILENAME; - params->pRootCALocation = AWS_IOT_PRIVATE_KEY_FILENAME; -} - -void ConnectMQTTParamsSetup(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen) { - params->keepAliveIntervalInSec = 10; - params->isCleanSession = 1; - params->MQTTVersion = MQTT_3_1_1; - params->pClientID = pClientID; - params->clientIDLen = clientIDLen; - params->isWillMsgPresent = false; - params->pUsername = NULL; - params->usernameLen = 0; - params->pPassword = NULL; - params->passwordLen = 0; -} - -void ConnectMQTTParamsSetup_Detailed(IoT_Client_Connect_Params *params, char *pClientID, uint16_t clientIDLen, QoS qos, - bool isCleanSession, bool isWillMsgPresent, char *pWillTopicName, - uint16_t willTopicNameLen, char *pWillMessage, uint16_t willMsgLen, - char *pUsername, uint16_t userNameLen, char *pPassword, uint16_t passwordLen) { - params->keepAliveIntervalInSec = 10; - params->isCleanSession = isCleanSession; - params->MQTTVersion = MQTT_3_1_1; - params->pClientID = pClientID; - params->clientIDLen = clientIDLen; - params->pUsername = pUsername; - params->usernameLen = userNameLen; - params->pPassword = pPassword; - params->passwordLen = passwordLen; - params->isWillMsgPresent = isWillMsgPresent; - params->will.pMessage = pWillMessage; - params->will.msgLen = willMsgLen; - params->will.pTopicName = pWillTopicName; - params->will.topicNameLen = willTopicNameLen; - params->will.qos = qos; - params->will.isRetained = false; -} - -void printBuffer(unsigned char *buffer, size_t len) { - size_t i; - printf("\n--\n"); - for(i = 0; i < len; i++) { - printf("%d: %c, %d\n", (uint32_t)i, buffer[i], buffer[i]); - } - printf("\n--\n"); -} - -#define CONNACK_PACKET_SIZE 4 - -void setTLSRxBufferForConnack(IoT_Client_Connect_Params *params, unsigned char sessionPresent, - unsigned char connackResponseCode) { - RxBuffer.NoMsgFlag = false; - - if(params->isCleanSession) { - sessionPresent = 0; - } - - RxBuffer.pBuffer[0] = (unsigned char) (0x20); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - RxBuffer.pBuffer[2] = sessionPresent; - RxBuffer.pBuffer[3] = connackResponseCode; - - RxBuffer.len = CONNACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForConnackAndSuback(IoT_Client_Connect_Params *conParams, unsigned char sessionPresent, - char *topicName, size_t topicNameLen, QoS qos) { - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - - RxBuffer.NoMsgFlag = false; - - if(conParams->isCleanSession) { - sessionPresent = 0; - } - - RxBuffer.pBuffer[0] = (unsigned char) (0x20); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - RxBuffer.pBuffer[2] = sessionPresent; - RxBuffer.pBuffer[3] = (unsigned char) (0x0); - - RxBuffer.pBuffer[4] = (unsigned char) (0x90); - RxBuffer.pBuffer[5] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[6] = (unsigned char) (2); - RxBuffer.pBuffer[7] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[8] = (unsigned char) (qos); - - RxBuffer.len = CONNACK_SUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForPuback(void) { - size_t i; - - RxBuffer.NoMsgFlag = true; - RxBuffer.len = PUBACK_PACKET_SIZE; - RxIndex = 0; - - for(i = 0; i < RxBuffer.BufMaxSize; i++) { - RxBuffer.pBuffer[i] = 0; - } - - RxBuffer.pBuffer[0] = (unsigned char) (0x40); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - RxBuffer.pBuffer[2] = (unsigned char) (0x02); - RxBuffer.pBuffer[3] = (unsigned char) (0x00); - RxBuffer.NoMsgFlag = false; -} - -void setTLSRxBufferForSubFail(void) { - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x90); - RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[4] = (unsigned char) (128); - - RxBuffer.len = SUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForDoubleSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params) { - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(params); - - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x90); - RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[4] = (unsigned char) (qos); - - RxBuffer.pBuffer[5] = (unsigned char) (0x90); - RxBuffer.pBuffer[6] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[7] = (unsigned char) (2); - RxBuffer.pBuffer[8] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[9] = (unsigned char) (qos); - - RxBuffer.len = SUBACK_PACKET_SIZE * 2; - RxIndex = 0; -} - -void setTLSRxBufferForSuback(char *topicName, size_t topicNameLen, QoS qos, IoT_Publish_Message_Params params) { - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(params); - - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x90); - RxBuffer.pBuffer[1] = (unsigned char) (0x2 + 1); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // payload - RxBuffer.pBuffer[4] = (unsigned char) (qos); - - RxBuffer.len = SUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForUnsuback(void) { - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0xB0); - RxBuffer.pBuffer[1] = (unsigned char) (0x02); - // Variable header - packet identifier - RxBuffer.pBuffer[2] = (unsigned char) (2); - RxBuffer.pBuffer[3] = (unsigned char) (0); - // No payload - RxBuffer.len = UNSUBACK_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForPingresp(void) { - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0xD0); - RxBuffer.pBuffer[1] = (unsigned char) (0x00); - RxBuffer.len = PINGRESP_PACKET_SIZE; - RxIndex = 0; -} - -void setTLSRxBufferForError(IoT_Error_t error) { - RxBuffer.mockedError = error; -} - -void setTLSTxBufferForError(IoT_Error_t error) { - TxBuffer.mockedError = error; -} - -void ResetTLSBuffer(void) { - size_t i; - RxBuffer.len = 0; - RxBuffer.NoMsgFlag = true; - - for(i = 0; i < RxBuffer.BufMaxSize; i++) { - RxBuffer.pBuffer[i] = 0; - } - - RxIndex = 0; - RxBuffer.expiry_time.tv_sec = 0; - RxBuffer.expiry_time.tv_usec = 0; - TxBuffer.len = 0; - for(i = 0; i < TxBuffer.BufMaxSize; i++) { - TxBuffer.pBuffer[i] = 0; - } -} - -void setTLSRxBufferDelay(int seconds, int microseconds) { - struct timeval now, duration, result; - duration.tv_sec = seconds; - duration.tv_usec = microseconds; - - gettimeofday(&now, NULL); - timeradd(&now, &duration, &result); - RxBuffer.expiry_time.tv_sec = result.tv_sec; - RxBuffer.expiry_time.tv_usec = result.tv_usec; -} - -void setTLSRxBufferWithMsgOnSubscribedTopic(char *topicName, size_t topicNameLen, QoS qos, - IoT_Publish_Message_Params params, char *pMsg) { - size_t VariableLen = topicNameLen + 2 + 2; - size_t i = 0, cursor = 0, packetIdStartLoc = 0, payloadStartLoc = 0, VarHeaderStartLoc = 0; - size_t PayloadLen = strlen(pMsg) + 1; - - RxBuffer.NoMsgFlag = false; - RxBuffer.pBuffer[0] = (unsigned char) (0x30 | ((params.qos << 1) & 0xF));// QoS1 - cursor++; // Move the cursor - - // Remaining Length - // Translate the Remaining Length into packet bytes - encodeRemainingLength(RxBuffer.pBuffer, &cursor, VariableLen + PayloadLen); - - VarHeaderStartLoc = cursor - 1; - // Variable header - RxBuffer.pBuffer[VarHeaderStartLoc + 1] = (unsigned char) ((topicNameLen & 0xFF00) >> 8); - RxBuffer.pBuffer[VarHeaderStartLoc + 2] = (unsigned char) (topicNameLen & 0xFF); - for(i = 0; i < topicNameLen; i++) { - RxBuffer.pBuffer[VarHeaderStartLoc + 3 + i] = (unsigned char) topicName[i]; - } - - packetIdStartLoc = VarHeaderStartLoc + topicNameLen + 2; - payloadStartLoc = (packetIdStartLoc + 1); - - if(QOS0 != qos) { - // packet id only for QoS 1 or 2 - RxBuffer.pBuffer[packetIdStartLoc + 1] = 2; - RxBuffer.pBuffer[packetIdStartLoc + 2] = 3; - payloadStartLoc = packetIdStartLoc + 3; - } - - // payload - for(i = 0; i < PayloadLen; i++) { - RxBuffer.pBuffer[payloadStartLoc + i] = (unsigned char) pMsg[i]; - } - - RxBuffer.len = VariableLen + PayloadLen + 2; // 2 for fixed header - RxIndex = 0; - //printBuffer(RxBuffer.pBuffer, RxBuffer.len); -} - -unsigned char isLastTLSTxMessagePuback() { - return (unsigned char) (TxBuffer.pBuffer[0] == 0x40 ? 1 : 0); -} - -unsigned char isLastTLSTxMessagePingreq() { - return (unsigned char) (TxBuffer.pBuffer[0] == 0xC0 ? 1 : 0); -} - -unsigned char isLastTLSTxMessageDisconnect() { - return (unsigned char) (TxBuffer.pBuffer[0] == 0xE0 ? 1 : 0); -} - -unsigned char generateMultipleSubTopics(char *des, int boundary) { - int i; - int currLen = 0; - char *op1 = des; - unsigned char ret = (unsigned char) (des == NULL ? 0 : 1); - while(*op1 != '\0') { - currLen++; - op1++; - } - // Save 1 byte for terminator '\0' - for(i = 0; i < boundary - currLen - 1; i++) { - //printf("%d\n", i); - strcat(des, "a"); - } - return ret; -} - -void encodeRemainingLength(unsigned char *buf, size_t *st, size_t length) { - unsigned char c; - // watch out for the type of length, could be over flow. Limits = 256MB - // No boundary check for 256MB!! - do { - c = (unsigned char) (length % 128); - length /= 128; - if(length > 0) c |= (unsigned char) (0x80); // If there is still another byte following - buf[(*st)++] = c; - } while(length > 0); - // At this point, *st should be the next position for a new part of data in the packet -} - -unsigned char *connectTxBufferHeaderParser(ConnectBufferProofread *params, unsigned char *buf) { - unsigned char *op = buf; - // Get packet type - unsigned char *ele1 = op; - unsigned int multiplier = 1; - int cnt = 0; - unsigned char *ele2; - unsigned int x; - unsigned char *op2; - params->PacketType = *ele1; - op++; - // Get remaining length (length bytes more than 4 bytes are ignored) - params->RemainingLength = 0; - do { - ele2 = op; - params->RemainingLength += ((unsigned int) (*ele2 & (0x7F)) * multiplier); - multiplier *= 128; - cnt++; - op++; - } while((*ele2 & (0x80)) != 0 && cnt < 4); - // At this point, op should be updated to the start address of the next chunk of information - // Get protocol length - params->ProtocolLength = 0; - params->ProtocolLength += (256 * (unsigned int) (*op++)); - params->ProtocolLength += (unsigned int) (*op++); - // Get protocol name - for(x = 0; x < params->ProtocolLength; x++) { - params->ProtocolName[x] = *op; - op++; - } - // Get protocol level - params->ProtocolLevel = (unsigned int) (*op++); - // Get connect flags - params->ConnectFlag = (*op++); - // Get keepalive - op2 = op; - params->KeepAlive = 0; - params->KeepAlive += (256 * (unsigned int) (*op2++)); // get rid of the sign bit - op++; - params->KeepAlive += (unsigned int) (*op2++); - op++; - - return op; -} - -bool isConnectTxBufFlagCorrect(IoT_Client_Connect_Params *settings, ConnectBufferProofread *readRes) { - bool ret = true; - int i; - unsigned char myByte[8]; // Construct our own connect flag byte according to the settings -#if !DISABLE_METRICS - myByte[0] = (unsigned char) (1); // User Name Flag -#else - myByte[0] = (unsigned char) (settings->pUsername == NULL ? 0 : 1); // User Name Flag -#endif - myByte[1] = (unsigned char) (settings->pPassword == NULL ? 0 : 1); // Password Flag - myByte[2] = 0; // Will Retain - // QoS - if(QOS1 == settings->will.qos) { - myByte[3] = 0; - myByte[4] = 1; - } else { // default QoS is QOS0 - myByte[3] = 0; - myByte[4] = 0; - } - // - myByte[5] = (unsigned char) settings->isWillMsgPresent; // Will Flag - myByte[6] = (unsigned char) settings->isCleanSession; // Clean Session - myByte[7] = 0; // Retained - // - for(i = 0; i < 8; i++) { - if(myByte[i] != (unsigned char) (((readRes->ConnectFlag) >> (7 - i)) & 0x01)) { - printf("ex %x ac %x\n", (unsigned char) (((readRes->ConnectFlag) >> (7 - i)) & 0x01) + '0', myByte[i]); - ret = false; - break; - } - } - return ret; -} - -bool isConnectTxBufPayloadCorrect(IoT_Client_Connect_Params *settings, unsigned char *payloadBuf) { - // Construct our own payload according to the settings to see if the real one matches with it - unsigned int ClientIDLen = (unsigned int) strlen(settings->pClientID); - unsigned int WillTopicLen = (unsigned int) strlen(settings->will.pTopicName); - unsigned int WillMsgLen = (unsigned int) strlen(settings->will.pMessage); -#if !DISABLE_METRICS - if (0 == strlen(pUsernameTemp)) { - snprintf(pUsernameTemp, SDK_METRICS_LEN, SDK_METRICS_TEMPLATE, - VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); - } - unsigned int UsernameLen = (unsigned int)strlen(pUsernameTemp); -#else - unsigned int UsernameLen = (unsigned int) settings->usernameLen; -#endif - unsigned int PasswordLen = (unsigned int) settings->passwordLen; - unsigned int myPayloadLen = ClientIDLen + 2 + WillTopicLen + 2 + WillMsgLen + UsernameLen + 2 + PasswordLen; - char *myPayload = (char *) malloc(sizeof(char) * (myPayloadLen + 1)); // reserve 1 byte for '\0' - // Construction starts... - unsigned int i; - bool ret = false; - char *op = myPayload; - *op = (char) (ClientIDLen & 0x0FF00); // MSB There is a writeInt inside paho... MQTTString.lenstring.len != 0 - op++; - *op = (char) (ClientIDLen & 0x00FF); // LSB - op++; - // ClientID - for(i = 0; i < ClientIDLen; i++) { - *op = settings->pClientID[i]; - op++; - } - if(true == settings->isWillMsgPresent) { - // WillTopic - for(i = 0; i < WillTopicLen; i++) { - *op = settings->will.pTopicName[i]; - op++; - } - // WillMsg Len - *op = (char) (WillMsgLen & 0x0FF00); // MSB - op++; - *op = (char) (WillMsgLen & 0x00FF); // LSB - op++; - // WillMsg - for(i = 0; i < WillMsgLen; i++) { - *op = settings->will.pMessage[i]; - op++; - } - } - // Username -#if !DISABLE_METRICS - for(i = 0; i < strlen(pUsernameTemp); i++) - { - *op = pUsernameTemp[i]; - op++; - } -#else - if(NULL != settings->pUsername) { - for(i = 0; i < UsernameLen; i++) { - *op = settings->pUsername[i]; - op++; - } - } -#endif - // PasswordLen + Password - if(NULL != settings->pPassword) { - *op = (char) (PasswordLen & 0x0FF00); // MSB - op++; - *op = (char) (PasswordLen & 0x00FF); // LSB - op++; - // - for(i = 0; i < PasswordLen; i++) { - *op = settings->pPassword[i]; - op++; - } - } - // - *op = '\0'; - ret = strcmp(myPayload, (const char *)payloadBuf) == 0 ? true : false; - free(myPayload); - return ret; -} - -void printPrfrdParams(ConnectBufferProofread *params) { - unsigned int i; - printf("\n----------------\n"); - printf("PacketType: %x\n", params->PacketType); - printf("RemainingLength: %u\n", params->RemainingLength); - printf("ProtocolLength: %u\n", params->ProtocolLength); - printf("ProtocolName: "); - for(i = 0; i < params->ProtocolLength; i++) { - printf("%c", params->ProtocolName[i]); - } - printf("\n"); - printf("ProtocolLevel: %u\n", params->ProtocolLevel); - printf("ConnectFlag: %x\n", params->ConnectFlag); - printf("KeepAliveInterval: %u\n", params->KeepAlive); - printf("----------------\n"); -} - -const char *getJobTopicTypeName(AwsIotJobExecutionTopicType topicType) { - switch (topicType) { - case JOB_UPDATE_TOPIC: return "JOB_UPDATE_TOPIC"; - case JOB_NOTIFY_TOPIC: return "JOB_NOTIFY_TOPIC"; - case JOB_NOTIFY_NEXT_TOPIC: return "JOB_NOTIFY_NEXT_TOPIC"; - case JOB_GET_PENDING_TOPIC: return "JOB_GET_PENDING_TOPIC"; - case JOB_DESCRIBE_TOPIC: return "JOB_DESCRIBE_TOPIC"; - case JOB_START_NEXT_TOPIC: return "JOB_START_NEXT_TOPIC"; - case JOB_WILDCARD_TOPIC: return "JOB_WILDCARD_TOPIC"; - case JOB_UNRECOGNIZED_TOPIC: return "JOB_UNRECOGNIZED_TOPIC"; - default: return "invalid"; - } -} - -const char *getJobReplyTypeName(AwsIotJobExecutionTopicReplyType replyType) { - switch (replyType) { - case JOB_REQUEST_TYPE: return "JOB_REQUEST_TYPE"; - case JOB_ACCEPTED_REPLY_TYPE: return "JOB_ACCEPTED_REPLY_TYPE"; - case JOB_REJECTED_REPLY_TYPE: return "JOB_REJECTED_REPLY_TYPE"; - case JOB_WILDCARD_REPLY_TYPE: return "JOB_WILDCARD_REPLY_TYPE"; - case JOB_UNRECOGNIZED_TOPIC_TYPE: return "JOB_UNRECOGNIZED_TOPIC_TYPE"; - default: return "invalid"; - } -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs.cpp deleted file mode 100644 index edbf8cee4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -#include -#include - - -TEST_GROUP_C(JobsTypesTests) { - TEST_GROUP_C_SETUP_WRAPPER(JobsTypesTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(JobsTypesTests) -}; - -TEST_GROUP_C_WRAPPER(JobsTypesTests, StringToStatus) -TEST_GROUP_C_WRAPPER(JobsTypesTests, StatusToString) - -TEST_GROUP_C(JobsJsonTests) { - TEST_GROUP_C_SETUP_WRAPPER(JobsJsonTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(JobsJsonTests) -}; - -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeUpdateRequest) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeUpdateRequestWithNullBuffer) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeUpdateRequestWithTooSmallBuffer) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeDescribeJobExecutionRequest) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeDescribeJobExecutionRequestWithNullBuffer) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeDescribeJobExecutionRequestWithTooSmallBuffer) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeStartNextRequest) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeStartNextRequestWithNullBuffer) -TEST_GROUP_C_WRAPPER(JobsJsonTests, SerializeStartNextRequestWithTooSmallBuffer) - -TEST_GROUP_C(JobsTopicsTests) { - TEST_GROUP_C_SETUP_WRAPPER(JobsTopicsTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(JobsTopicsTests) -}; - -TEST_GROUP_C_WRAPPER(JobsTopicsTests, GenerateValidTopics) -TEST_GROUP_C_WRAPPER(JobsTopicsTests, GenerateWithMissingJobId) -TEST_GROUP_C_WRAPPER(JobsTopicsTests, GenerateWithInvalidTopicOrReplyType) -TEST_GROUP_C_WRAPPER(JobsTopicsTests, GenerateWithInvalidCombinations) - -TEST_GROUP_C(JobsInterfaceTest) { - TEST_GROUP_C_SETUP_WRAPPER(JobsInterfaceTest) - TEST_GROUP_C_TEARDOWN_WRAPPER(JobsInterfaceTest) -}; - -TEST_GROUP_C_WRAPPER(JobsInterfaceTest, TestSubscribeAndUnsubscribe) -TEST_GROUP_C_WRAPPER(JobsInterfaceTest, TestSendQuery) -TEST_GROUP_C_WRAPPER(JobsInterfaceTest, TestSendUpdate) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_interface.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_interface.c deleted file mode 100644 index c19a38d88..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_interface.c +++ /dev/null @@ -1,337 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -#include - -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_config.h" -#include -#include -#include - -static AWS_IoT_Client client; -static IoT_Client_Connect_Params connectParams; -static IoT_Client_Init_Params mqttInitParams; - -static const char *THING_NAME = "T1"; -static const char *JOB_ID = "J1"; - -static int CALLBACK_DATA = 5; - -static const char *expectedTopic; -static const void *expectedData; -static size_t expectedDataLen; - -static int callbackCount = 0; - -static bool expectError; -static bool expectedJsonContext; - - -static void testCallback( - AWS_IoT_Client *pClient, - char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) -{ - callbackCount++; - - CHECK_C(pData == &CALLBACK_DATA); - CHECK_C(pClient == &client); - - CHECK_EQUAL_C_INT((int)strlen(expectedTopic), (int)topicNameLen); - CHECK_C(strncmp(expectedTopic, topicName, (size_t) topicNameLen) == 0); - - CHECK_C(memcmp(expectedData, params->payload, expectedDataLen) == 0); -} - -TEST_GROUP_C_SETUP(JobsInterfaceTest) { - IoT_Error_t ret_val = SUCCESS; - - InitMQTTParamsSetup(&mqttInitParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - ret_val = aws_iot_mqtt_init(&client, &mqttInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ConnectMQTTParamsSetup(&connectParams, (char *) AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_mqtt_connect(&client, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - - /* Ensure that old data can't be used */ - lastSubscribeMsgLen = 0; - lastUnsubscribeMsgLen = 0; - lastPublishMessageTopicLen = 0; - lastPublishMessagePayloadLen = 0; - - callbackCount = 0; - expectedTopic = NULL; - expectedData = NULL; - expectedDataLen = 0; - - expectError = false; - expectedJsonContext = false; -} - -TEST_GROUP_C_TEARDOWN(JobsInterfaceTest) { - IoT_Error_t rc = aws_iot_mqtt_disconnect(&client); - IOT_UNUSED(rc); -} - -static void publishTestMessage(AwsIotJobExecutionTopicType topicType, bool withJobId) { - char replyTopic[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - AwsIotJobExecutionTopicReplyType replyType; - char * message; - - if (topicType == JOB_NOTIFY_TOPIC) { - replyType = JOB_REQUEST_TYPE; - message = "{\"jobs\":{\"IN_PROGRESS\":[{}]},\"timestamp\":5}"; - } else if (topicType == JOB_NOTIFY_NEXT_TOPIC) { - replyType = JOB_REQUEST_TYPE; - message = "{\"execution\":{\"jobId\":\"J1\",\"status\":\"IN_PROGRESS\",\"queuedAt\":50,\"versionNumber\":20},\"timestamp\":5}"; - } - else { - replyType = JOB_REJECTED_REPLY_TYPE; - message = "{\"code\":\"foo\",\"message\":\"bar\", \"clientToken\":\"baz\",\"timestamp\":6}"; - } - - const char *passedJobId = NULL; - if (withJobId) { - if (topicType == JOB_WILDCARD_TOPIC) { - topicType = JOB_DESCRIBE_TOPIC; - } - passedJobId = JOB_ID; - } - - int replyTopicLen = aws_iot_jobs_get_api_topic( - replyTopic, MAX_JOB_TOPIC_LENGTH_BYTES + 1, - topicType, replyType, THING_NAME, passedJobId); - - expectedData = message; - expectedDataLen = strlen(message) + 1; - expectedTopic = replyTopic; - - IoT_Publish_Message_Params params; - params.payload = message; - params.payloadLen = strlen(message); - params.qos = QOS0; - - int preSendCount = callbackCount; - - setTLSRxBufferWithMsgOnSubscribedTopic(replyTopic, (size_t)replyTopicLen, QOS0, params, message); - IoT_Error_t error = aws_iot_mqtt_yield(&client, 100); - - CHECK_EQUAL_C_INT(SUCCESS, error); - CHECK_EQUAL_C_INT(preSendCount + 1, callbackCount); -} - -static void testSubscribeAndUnsubscribe(AwsIotJobExecutionTopicType topicType, bool withJobId) { - char expectedTopic[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - char topicBuffer[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - - IOT_DEBUG("\n-->Running Jobs Interface Tests - test subscribe/unsubscribe %s %s \n", getJobTopicTypeName(topicType), (withJobId ? "(w/ job id)" : "")); - - AwsIotJobExecutionTopicReplyType replyType; - if (topicType != JOB_NOTIFY_TOPIC && topicType != JOB_NOTIFY_NEXT_TOPIC) { - replyType = JOB_WILDCARD_REPLY_TYPE; - } else { - replyType = JOB_REQUEST_TYPE; - } - - const char *passedJobId = NULL; - if (withJobId) passedJobId = JOB_ID; - - int expectedTopicLength = aws_iot_jobs_get_api_topic( - expectedTopic, MAX_JOB_TOPIC_LENGTH_BYTES + 1, - topicType, replyType, - THING_NAME, passedJobId); - - CHECK_C(expectedTopicLength > 0 && expectedTopicLength < MAX_JOB_TOPIC_LENGTH_BYTES); - - /* Clear to make sure old data doesn't cause the test to pass when we shouldn't */ - lastSubscribeMsgLen = 0; - lastPublishMessageTopicLen = 0; - - IoT_Publish_Message_Params unused; - - setTLSRxBufferForSuback(expectedTopic, (size_t)expectedTopicLength, QOS0, unused); - - IoT_Error_t iotError; - if (topicType == JOB_WILDCARD_TOPIC && !withJobId) { - iotError = aws_iot_jobs_subscribe_to_all_job_messages( - &client, QOS0, THING_NAME, testCallback, &CALLBACK_DATA, topicBuffer, sizeof(topicBuffer)); - } else { - iotError = aws_iot_jobs_subscribe_to_job_messages( - &client, QOS0, THING_NAME, passedJobId, topicType, replyType, testCallback, &CALLBACK_DATA, topicBuffer, sizeof(topicBuffer)); - } - - CHECK_EQUAL_C_INT(SUCCESS, iotError); - - CHECK_EQUAL_C_INT(expectedTopicLength, (int)strlen(topicBuffer)); - CHECK_EQUAL_C_INT(expectedTopicLength, (int)lastSubscribeMsgLen); - CHECK_EQUAL_C_STRING(expectedTopic, topicBuffer); - CHECK_EQUAL_C_STRING(expectedTopic, LastSubscribeMessage); - - publishTestMessage(topicType, withJobId); - - LastUnsubscribeMessage[0] = 0; - lastUnsubscribeMsgLen = 0; - - setTLSRxBufferForUnsuback(); - iotError = aws_iot_jobs_unsubscribe_from_job_messages(&client, topicBuffer); - - CHECK_EQUAL_C_INT(SUCCESS, iotError); - - CHECK_EQUAL_C_STRING(expectedTopic, LastUnsubscribeMessage); - - IOT_DEBUG("-->Success - test subscribe/unsubscribe %s %s \n", getJobTopicTypeName(topicType), (withJobId ? "(w/ job id)" : "")); -} - -TEST_C(JobsInterfaceTest, TestSubscribeAndUnsubscribe) { - testSubscribeAndUnsubscribe(JOB_NOTIFY_TOPIC, false); - testSubscribeAndUnsubscribe(JOB_NOTIFY_NEXT_TOPIC, false); - testSubscribeAndUnsubscribe(JOB_DESCRIBE_TOPIC, true); - testSubscribeAndUnsubscribe(JOB_GET_PENDING_TOPIC, false); - testSubscribeAndUnsubscribe(JOB_UPDATE_TOPIC, true); - testSubscribeAndUnsubscribe(JOB_WILDCARD_TOPIC, true); - testSubscribeAndUnsubscribe(JOB_WILDCARD_TOPIC, false); - testSubscribeAndUnsubscribe(JOB_START_NEXT_TOPIC, false); -} - -static void testSendQuery(bool withJobId, bool withClientToken, AwsIotJobExecutionTopicType topicType) { - char expectedTopic[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - char topicBuffer[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - char messageBuffer[MAX_SIZE_OF_JOB_REQUEST + 1]; - - IOT_DEBUG("\n-->Running Jobs Interface Tests - test send query %s %s \n", getJobTopicTypeName(topicType), (withClientToken ? "(w/ clientToken)" : "")); - - char *clientToken = NULL; - char *bufferToPass = NULL; - size_t bufferLenToPass = 0; - if (withClientToken) { - clientToken = "FooBar"; - bufferToPass = messageBuffer; - bufferLenToPass = MAX_SIZE_OF_JOB_REQUEST + 1; - } - - const char *passedJobId = NULL; - if (withJobId) passedJobId = JOB_ID; - - int expectedTopicLength = aws_iot_jobs_get_api_topic( - expectedTopic, MAX_JOB_TOPIC_LENGTH_BYTES + 1, - topicType, JOB_REQUEST_TYPE, - THING_NAME, passedJobId); - - CHECK_C(expectedTopicLength > 0 && expectedTopicLength <= MAX_JOB_TOPIC_LENGTH_BYTES); - - LastPublishMessageTopic[0] = 0; - lastPublishMessageTopicLen = 0; - LastPublishMessagePayload[0] = 0; - lastPublishMessagePayloadLen = 0; - - setTLSRxBufferForPuback(); - IoT_Error_t iotError; - - if (topicType == JOB_DESCRIBE_TOPIC) { - AwsIotDescribeJobExecutionRequest request; - request.executionNumber = 0; - request.includeJobDocument = false; - request.clientToken = clientToken; - - iotError = aws_iot_jobs_describe( - &client, QOS0, THING_NAME, passedJobId, &request, topicBuffer, sizeof(topicBuffer), bufferToPass, bufferLenToPass); - } else if (topicType == JOB_START_NEXT_TOPIC) { - AwsIotStartNextPendingJobExecutionRequest request; - request.statusDetails = NULL; - request.clientToken = clientToken; - - iotError = aws_iot_jobs_start_next( - &client, QOS0, THING_NAME, &request, topicBuffer, sizeof(topicBuffer), messageBuffer, sizeof(messageBuffer)); - } else { - iotError = aws_iot_jobs_send_query( - &client, QOS0, THING_NAME, passedJobId, clientToken, topicBuffer, sizeof(topicBuffer), bufferToPass, bufferLenToPass, topicType); - } - - CHECK_EQUAL_C_INT(SUCCESS, iotError); - CHECK_EQUAL_C_INT(expectedTopicLength, (int)lastPublishMessageTopicLen); - CHECK_EQUAL_C_STRING(expectedTopic, LastPublishMessageTopic); - - if (withClientToken) { - CHECK_EQUAL_C_INT((int)strlen(LastPublishMessagePayload), (int)lastPublishMessagePayloadLen); - CHECK_EQUAL_C_STRING("{\"clientToken\":\"FooBar\"}", LastPublishMessagePayload); - } else if (topicType == JOB_START_NEXT_TOPIC) { - CHECK_EQUAL_C_INT(2, (int)lastPublishMessagePayloadLen); - CHECK_EQUAL_C_STRING("{}", LastPublishMessagePayload); - } else { - CHECK_EQUAL_C_INT(0, (int)lastPublishMessagePayloadLen); - } - - IOT_DEBUG("-->Success - test send query %s %s \n", getJobTopicTypeName(topicType), (withClientToken ? "(w/ clientToken)" : "")); -} - -TEST_C(JobsInterfaceTest, TestSendQuery) { - int token; - for (token = 0; token < 2; ++token) { - testSendQuery(false, token == 0, JOB_GET_PENDING_TOPIC); - testSendQuery(true, token == 0, JOB_DESCRIBE_TOPIC); - testSendQuery(false, token == 0, JOB_START_NEXT_TOPIC); - } -} - -TEST_C(JobsInterfaceTest, TestSendUpdate) { - AwsIotJobExecutionUpdateRequest updateRequest; - updateRequest.clientToken = "FooBar"; - updateRequest.status = JOB_EXECUTION_SUCCEEDED; - updateRequest.expectedVersion = 1; - updateRequest.executionNumber = 0; - updateRequest.statusDetails = NULL; - updateRequest.includeJobExecutionState = false; - updateRequest.includeJobDocument = false; - - char expectedTopic[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - char topicBuffer[MAX_JOB_TOPIC_LENGTH_BYTES + 1]; - char messageBuffer[AWS_IOT_MQTT_TX_BUF_LEN + 1]; - - IOT_DEBUG("\n-->Running Jobs Interface Tests - test send update \n"); - - int expectedTopicLength = aws_iot_jobs_get_api_topic( - expectedTopic, MAX_JOB_TOPIC_LENGTH_BYTES + 1, - JOB_UPDATE_TOPIC, JOB_REQUEST_TYPE, - THING_NAME, JOB_ID); - - CHECK_C(expectedTopicLength > 0 && expectedTopicLength <= MAX_JOB_TOPIC_LENGTH_BYTES); - - LastPublishMessageTopic[0] = 0; - lastPublishMessageTopicLen = 0; - LastPublishMessagePayload[0] = 0; - lastPublishMessagePayloadLen = 0; - - setTLSRxBufferForPuback(); - IoT_Error_t iotError; - iotError = aws_iot_jobs_send_update( - &client, QOS0, THING_NAME, JOB_ID, &updateRequest, - topicBuffer, sizeof(topicBuffer), - messageBuffer, sizeof(messageBuffer)); - - CHECK_EQUAL_C_INT(SUCCESS, iotError); - - CHECK_EQUAL_C_INT(expectedTopicLength, (int)lastPublishMessageTopicLen); - CHECK_EQUAL_C_STRING(expectedTopic, LastPublishMessageTopic); - - CHECK_EQUAL_C_STRING("{\"status\":\"SUCCEEDED\",\"expectedVersion\":1,\"clientToken\":\"FooBar\"}", LastPublishMessagePayload); - - IOT_DEBUG("-->Success - test send update \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_json.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_json.c deleted file mode 100644 index 5a04554e1..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_json.c +++ /dev/null @@ -1,244 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define NUM_TOKENS 50 - -static jsmntok_t tokens[NUM_TOKENS]; - -TEST_GROUP_C_SETUP(JobsJsonTests) { -} - -TEST_GROUP_C_TEARDOWN(JobsJsonTests) { -} - -static const char *defaultUpdateRequestSerialized = - "{\"status\":\"IN_PROGRESS\",\"statusDetails\":{\"Step\":\"1\",\"StepStatus\":\"Foo\"}," - "\"executionNumber\":2,\"expectedVersion\":1,\"includeJobExecutionState\":true,\"includeJobDocument\":true,\"clientToken\":\"1234\"}"; - -static void fillDefaultUpdateRequest(AwsIotJobExecutionUpdateRequest *request) -{ - request->status = JOB_EXECUTION_IN_PROGRESS; - request->statusDetails = "{\"Step\":\"1\",\"StepStatus\":\"Foo\"}"; - request->expectedVersion = 1; - request->executionNumber = 2; - request->includeJobExecutionState = true; - request->includeJobDocument = true; - request->clientToken = "1234"; -} - -TEST_C(JobsJsonTests, SerializeUpdateRequest) { - AwsIotJobExecutionUpdateRequest updateRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize update request \n"); - - fillDefaultUpdateRequest(&updateRequest); - - char buffer[256]; - int charsUsed = aws_iot_jobs_json_serialize_update_job_execution_request(buffer, sizeof(buffer), &updateRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultUpdateRequestSerialized), charsUsed); - CHECK_EQUAL_C_STRING(defaultUpdateRequestSerialized, buffer); - - jsmn_parser parser; - jsmn_init(&parser); - - int num_parsed_tokens = jsmn_parse(&parser, buffer, (size_t)charsUsed, tokens, NUM_TOKENS); - CHECK_C(num_parsed_tokens > 0); - - IOT_DEBUG("-->Success - serialize update request \n"); -} - -TEST_C(JobsJsonTests, SerializeUpdateRequestWithNullBuffer) { - AwsIotJobExecutionUpdateRequest updateRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize update request w/ null buffer \n"); - - fillDefaultUpdateRequest(&updateRequest); - - int charsUsed = aws_iot_jobs_json_serialize_update_job_execution_request(NULL, 0, &updateRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultUpdateRequestSerialized), charsUsed); - - IOT_DEBUG("-->Success - serialize update request w/ null buffer \n"); -} - -TEST_C(JobsJsonTests, SerializeUpdateRequestWithTooSmallBuffer) { - AwsIotJobExecutionUpdateRequest updateRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize update request w/ too small buffer \n"); - - fillDefaultUpdateRequest(&updateRequest); - - char buffer[11]; - // A check character which shouldn't be overwritten as we pass a length of 10 - buffer[10] = -1; - - int charsUsed = aws_iot_jobs_json_serialize_update_job_execution_request(buffer, 10, &updateRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultUpdateRequestSerialized), charsUsed); - - CHECK_EQUAL_C_CHAR(-1, buffer[10]); - CHECK_EQUAL_C_CHAR(0, buffer[9]); - // 9 because the 10th is \0 - CHECK_C(strncmp(defaultUpdateRequestSerialized, buffer, 9) == 0); - - IOT_DEBUG("-->Success - serialize update request w/ too small buffer \n"); -} - -static void fillDefaultDescribeJobExecutionRequest( - AwsIotDescribeJobExecutionRequest *request) -{ - request->executionNumber = 1; - request->includeJobDocument = true; - request->clientToken = "1234"; -} - -static const char *defaultDescribeJobExecutionRequestSerialized = - "{\"clientToken\":\"1234\",\"executionNumber\":1,\"includeJobDocument\":true}"; - -TEST_C(JobsJsonTests, SerializeDescribeJobExecutionRequest) { - AwsIotDescribeJobExecutionRequest describeJobExecutionRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize describe job execution request \n"); - - fillDefaultDescribeJobExecutionRequest(&describeJobExecutionRequest); - - char buffer[256]; - int charsUsed = aws_iot_jobs_json_serialize_describe_job_execution_request(buffer, 256, &describeJobExecutionRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultDescribeJobExecutionRequestSerialized), charsUsed); - - CHECK_EQUAL_C_STRING(defaultDescribeJobExecutionRequestSerialized, buffer); - - jsmn_parser parser; - jsmn_init(&parser); - - int num_parsed_tokens = jsmn_parse(&parser, buffer, (size_t)charsUsed, tokens, NUM_TOKENS); - CHECK_C(num_parsed_tokens > 0); - - IOT_DEBUG("-->Success - serialize describe job execution request \n"); -} - -TEST_C(JobsJsonTests, SerializeDescribeJobExecutionRequestWithNullBuffer) { - AwsIotDescribeJobExecutionRequest describeJobExecutionRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize describe job execution request w/ null buffer \n"); - - fillDefaultDescribeJobExecutionRequest(&describeJobExecutionRequest); - - int charsUsed = aws_iot_jobs_json_serialize_describe_job_execution_request(NULL, 0, &describeJobExecutionRequest); - CHECK_EQUAL_C_INT(0, charsUsed); - - IOT_DEBUG("-->Success - serialize describe job execution request w/ null buffer \n"); -} - -TEST_C(JobsJsonTests, SerializeDescribeJobExecutionRequestWithTooSmallBuffer) { - AwsIotDescribeJobExecutionRequest describeJobExecutionRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize describe job execution request w/ too small buffer \n"); - - fillDefaultDescribeJobExecutionRequest(&describeJobExecutionRequest); - - char buffer[11]; - // A check character which shouldn't be overwritten as we pass a length of 10 - buffer[10] = -1; - - int charsUsed = aws_iot_jobs_json_serialize_describe_job_execution_request(buffer, 10, &describeJobExecutionRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultDescribeJobExecutionRequestSerialized), charsUsed); - - CHECK_EQUAL_C_CHAR(-1, buffer[10]); - CHECK_EQUAL_C_CHAR(0, buffer[9]); - // 9 because the 10th is \0 - CHECK_C(strncmp(defaultDescribeJobExecutionRequestSerialized, buffer, 9) == 0); - - IOT_DEBUG("-->Success - serialize describe job execution request w/ too small buffer \n"); -} - -static void fillDefaultStartNextRequest(AwsIotStartNextPendingJobExecutionRequest *request) -{ - request->statusDetails = "{\"Step\":\"1\",\"StepStatus\":\"Foo\"}"; - request->clientToken = "1234"; -} - -static const char *defaultStartNextRequestSerialized = - "{\"statusDetails\":{\"Step\":\"1\",\"StepStatus\":\"Foo\"},\"clientToken\":\"1234\"}"; - -TEST_C(JobsJsonTests, SerializeStartNextRequest) { - AwsIotStartNextPendingJobExecutionRequest startNextRequest; - fillDefaultStartNextRequest(&startNextRequest); - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize start next request \n"); - - char buffer[256]; - int charsUsed = aws_iot_jobs_json_serialize_start_next_job_execution_request(buffer, 256, &startNextRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultStartNextRequestSerialized), charsUsed); - - CHECK_EQUAL_C_STRING(defaultStartNextRequestSerialized, buffer); - jsmn_parser parser; - jsmn_init(&parser); - - int num_parsed_tokens = jsmn_parse(&parser, buffer, (size_t)charsUsed, tokens, NUM_TOKENS); - CHECK_C(num_parsed_tokens > 0); - - IOT_DEBUG("-->Success - serialize start next request \n"); -} - -TEST_C(JobsJsonTests, SerializeStartNextRequestWithNullBuffer) { - AwsIotStartNextPendingJobExecutionRequest startNextRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize start next request w/ null buffer \n"); - - fillDefaultStartNextRequest(&startNextRequest); - - int charsUsed = aws_iot_jobs_json_serialize_start_next_job_execution_request(NULL, 0, &startNextRequest); - CHECK_EQUAL_C_INT((int)strlen(defaultStartNextRequestSerialized), charsUsed); - - IOT_DEBUG("-->Success - serialize start next request w/ null buffer \n"); -} - -TEST_C(JobsJsonTests, SerializeStartNextRequestWithTooSmallBuffer) { - AwsIotStartNextPendingJobExecutionRequest startNextRequest; - - IOT_DEBUG("\n-->Running Jobs Json Tests - serialize start next request w/ too small buffer \n"); - - fillDefaultStartNextRequest(&startNextRequest); - - char buffer[11]; - // A check character which shouldn't be overwritten as we pass a length of 10 - buffer[10] = -1; - - int charsUsed = aws_iot_jobs_json_serialize_start_next_job_execution_request(buffer, 10, &startNextRequest); - CHECK_EQUAL_C_INT((int) strlen(defaultStartNextRequestSerialized), charsUsed); - - CHECK_EQUAL_C_CHAR(-1, buffer[10]); - CHECK_EQUAL_C_CHAR(0, buffer[9]); - // 9 because the 10th is \0 - CHECK_C(strncmp(defaultStartNextRequestSerialized, buffer, 9) == 0); - - IOT_DEBUG("-->Success - serialize start next request w/ too small buffer \n"); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_topics.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_topics.c deleted file mode 100644 index b6c6ace08..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_topics.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -#include "aws_iot_jobs_topics.h" -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -TEST_GROUP_C_SETUP(JobsTopicsTests) { -} - -TEST_GROUP_C_TEARDOWN(JobsTopicsTests) { -} - -#define TEST_THING_NAME "TestThing" -#define TEST_TOPIC_PREFIX "$aws/things/" TEST_THING_NAME "/jobs" -#define TEST_JOB_ID "TestJob" -#define TEST_NEXT_JOB_ID "$next" -#define TEST_TOPIC_W_JOB_PREFIX TEST_TOPIC_PREFIX "/" TEST_JOB_ID - -static int generateTopicForTestThingAndJob( - char *buffer, size_t bufferSize, - AwsIotJobExecutionTopicType topicType, AwsIotJobExecutionTopicReplyType replyType) -{ - return aws_iot_jobs_get_api_topic( - buffer, bufferSize, topicType, replyType, TEST_THING_NAME, TEST_JOB_ID); -} - -static int generateTopicForTestThing( - char *buffer, size_t bufferSize, - AwsIotJobExecutionTopicType topicType, AwsIotJobExecutionTopicReplyType replyType) -{ - return aws_iot_jobs_get_api_topic( - buffer, bufferSize, topicType, replyType, TEST_THING_NAME, NULL); -} - -static void testGenerateValidApiTopic( - AwsIotJobExecutionTopicType topicType, AwsIotJobExecutionTopicReplyType replyType, - bool includeThingName, const char *expectedOutput) -{ - int requestedSize; - int expectedSize = (int)strlen(expectedOutput); - - IOT_DEBUG("\n-->Running Jobs Topics Tests - generate valid topics %s w/ reply type \n", getJobTopicTypeName(topicType), getJobReplyTypeName(replyType)); - - if (includeThingName) { - requestedSize = generateTopicForTestThingAndJob(NULL, 0, topicType, replyType); - CHECK_EQUAL_C_INT(expectedSize, requestedSize); - } else { - requestedSize = generateTopicForTestThing(NULL, 0, topicType, replyType); - CHECK_EQUAL_C_INT(expectedSize, requestedSize); - } - - CHECK_C(requestedSize > 3); - char *buffer = (char *) malloc((size_t)(requestedSize + 1) * sizeof(char)); - buffer[3] = -1; - - if (includeThingName) { - requestedSize = generateTopicForTestThingAndJob(buffer, 3, topicType, replyType); - } else { - requestedSize = generateTopicForTestThing(buffer, 3, topicType, replyType); - } - CHECK_EQUAL_C_INT(expectedSize, requestedSize); - - CHECK_EQUAL_C_CHAR(expectedOutput[0], buffer[0]); - CHECK_EQUAL_C_CHAR(expectedOutput[1], buffer[1]); - CHECK_EQUAL_C_CHAR('\0', buffer[2]); - CHECK_EQUAL_C_CHAR(-1, buffer[3]); - - if (includeThingName) { - requestedSize = generateTopicForTestThingAndJob(buffer, (size_t)requestedSize + 1, topicType, replyType); - } else { - requestedSize = generateTopicForTestThing(buffer, (size_t)requestedSize + 1, topicType, replyType); - } - - CHECK_EQUAL_C_INT(expectedSize, requestedSize); - CHECK_EQUAL_C_STRING(expectedOutput, buffer); - - free(buffer); - - IOT_DEBUG("-->Success - generate valid topics %s w/ reply type \n", getJobTopicTypeName(topicType), getJobReplyTypeName(replyType)); -} - -static void testGenerateValidApiTopicWithAllReplyTypes( - AwsIotJobExecutionTopicType topicType, bool includeThingName, - const char *expectedBaseTopic) -{ - char buffer[1024]; - - testGenerateValidApiTopic( - topicType, JOB_REQUEST_TYPE, includeThingName, expectedBaseTopic); - - snprintf(buffer, 1024, "%s/accepted", expectedBaseTopic); - testGenerateValidApiTopic( - topicType, JOB_ACCEPTED_REPLY_TYPE, includeThingName, buffer); - - snprintf(buffer, 1024, "%s/rejected", expectedBaseTopic); - testGenerateValidApiTopic( - topicType, JOB_REJECTED_REPLY_TYPE, includeThingName, buffer); - - snprintf(buffer, 1024, "%s/+", expectedBaseTopic); - testGenerateValidApiTopic( - topicType, JOB_WILDCARD_REPLY_TYPE, includeThingName, buffer); - -} - -TEST_C(JobsTopicsTests, GenerateValidTopics) { - testGenerateValidApiTopicWithAllReplyTypes(JOB_UPDATE_TOPIC, true, TEST_TOPIC_W_JOB_PREFIX "/update"); - testGenerateValidApiTopicWithAllReplyTypes(JOB_DESCRIBE_TOPIC, true, TEST_TOPIC_W_JOB_PREFIX "/get"); - testGenerateValidApiTopicWithAllReplyTypes(JOB_WILDCARD_TOPIC, true, TEST_TOPIC_W_JOB_PREFIX "/+"); - testGenerateValidApiTopic(JOB_WILDCARD_TOPIC, JOB_REQUEST_TYPE, false, TEST_TOPIC_PREFIX "/#"); - testGenerateValidApiTopic(JOB_NOTIFY_TOPIC, JOB_REQUEST_TYPE, false, TEST_TOPIC_PREFIX "/notify"); - testGenerateValidApiTopic(JOB_NOTIFY_NEXT_TOPIC, JOB_REQUEST_TYPE, false, TEST_TOPIC_PREFIX "/notify-next"); - testGenerateValidApiTopic(JOB_START_NEXT_TOPIC, JOB_REQUEST_TYPE, false, TEST_TOPIC_PREFIX "/start-next"); -} - -TEST_C(JobsTopicsTests, GenerateWithMissingJobId) { - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_UPDATE_TOPIC, JOB_REQUEST_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_DESCRIBE_TOPIC, JOB_REQUEST_TYPE)); -} - -TEST_C(JobsTopicsTests, GenerateWithInvalidTopicOrReplyType) { - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_UNRECOGNIZED_TOPIC, JOB_REQUEST_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, -1, JOB_REQUEST_TYPE)); - - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_DESCRIBE_TOPIC, JOB_UNRECOGNIZED_TOPIC_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_DESCRIBE_TOPIC, -1)); -} - -TEST_C(JobsTopicsTests, GenerateWithInvalidCombinations) { - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_TOPIC, JOB_ACCEPTED_REPLY_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_TOPIC, JOB_REJECTED_REPLY_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_TOPIC, JOB_WILDCARD_REPLY_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_NEXT_TOPIC, JOB_ACCEPTED_REPLY_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_NEXT_TOPIC, JOB_REJECTED_REPLY_TYPE)); - CHECK_EQUAL_C_INT(-1, generateTopicForTestThing(NULL, 0, JOB_NOTIFY_NEXT_TOPIC, JOB_WILDCARD_REPLY_TYPE)); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_types.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_types.c deleted file mode 100644 index 60dc8c9d3..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_jobs_types.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -* Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -TEST_GROUP_C_SETUP(JobsTypesTests) { -} - -TEST_GROUP_C_TEARDOWN(JobsTypesTests) { -} - -TEST_C(JobsTypesTests, StringToStatus) { - char emptyString = '\0'; - - IOT_DEBUG("\n-->Running Jobs Types Tests - string to status \n"); - - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_STATUS_NOT_SET, (int)aws_iot_jobs_map_string_to_job_status(NULL)); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_STATUS_NOT_SET, (int)aws_iot_jobs_map_string_to_job_status(&emptyString)); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_QUEUED, (int)aws_iot_jobs_map_string_to_job_status("QUEUED")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_IN_PROGRESS, (int)aws_iot_jobs_map_string_to_job_status("IN_PROGRESS")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_FAILED, (int)aws_iot_jobs_map_string_to_job_status("FAILED")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_SUCCEEDED, (int)aws_iot_jobs_map_string_to_job_status("SUCCEEDED")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_CANCELED, (int)aws_iot_jobs_map_string_to_job_status("CANCELED")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_REJECTED, (int)aws_iot_jobs_map_string_to_job_status("REJECTED")); - CHECK_EQUAL_C_INT((int)JOB_EXECUTION_UNKNOWN_STATUS, (int)aws_iot_jobs_map_string_to_job_status("invalidStatus")); - - IOT_DEBUG("-->Success - string to status \n"); -} - -TEST_C(JobsTypesTests, StatusToString) { - IOT_DEBUG("\n-->Running Jobs Types Tests - status to string \n"); - - CHECK_EQUAL_C_STRING("QUEUED", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_QUEUED)); - CHECK_EQUAL_C_STRING("IN_PROGRESS", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_IN_PROGRESS)); - CHECK_EQUAL_C_STRING("FAILED", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_FAILED)); - CHECK_EQUAL_C_STRING("SUCCEEDED", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_SUCCEEDED)); - CHECK_EQUAL_C_STRING("CANCELED", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_CANCELED)); - CHECK_EQUAL_C_STRING("REJECTED", aws_iot_jobs_map_status_to_string(JOB_EXECUTION_REJECTED)); - CHECK_EQUAL_C_STRING(NULL, aws_iot_jobs_map_status_to_string(JOB_EXECUTION_STATUS_NOT_SET)); - CHECK_EQUAL_C_STRING(NULL, aws_iot_jobs_map_status_to_string(JOB_EXECUTION_UNKNOWN_STATUS)); - - IOT_DEBUG("-->Success - status to string \n"); -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils.cpp deleted file mode 100644 index f1fe2e33b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_json_utils.cpp - * @brief IoT Client Unit Testing - JSON Utility Tests - */ - -#include -#include - -TEST_GROUP_C(JsonUtils) { - TEST_GROUP_C_SETUP_WRAPPER(JsonUtils) - TEST_GROUP_C_TEARDOWN_WRAPPER(JsonUtils) -}; - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringLongerStringIsValid) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringWithBufferTooSmall) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringEmptyStringIsValid) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringErrorOnInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseStringErrorOnBoolean) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanTrue) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanFalse) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanErrorOnString) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseBooleanErrorOnInvalidJson) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleNumberWithNoDecimal) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleSmallDouble) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnString) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleErrorOnJsonObject) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseDoubleNegativeNumber) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatNumberWithNoDecimal) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatSmallFloat) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnString) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatErrorOnJsonObject) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseFloatNegativeNumber) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseIntegerErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger16bitErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseInteger8bitErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedIntegerErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger16bitErrorOnString) - -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitBasic) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitLargeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnNegativeInteger) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnBoolean) -TEST_GROUP_C_WRAPPER(JsonUtils, ParseUnsignedInteger8bitErrorOnString) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils_helper.c deleted file mode 100644 index 864d379d7..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_json_utils_helper.c +++ /dev/null @@ -1,834 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_json_utils_helper.c - * @brief IoT Client Unit Testing - JSON Utility Tests helper - */ - -#include -#include -#include -#include - -#include "aws_iot_json_utils.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -#define STRING_BUFFER_LENGTH (50) - -static IoT_Error_t rc = SUCCESS; - -static jsmn_parser test_parser; -static jsmntok_t t[128]; - -TEST_GROUP_C_SETUP(JsonUtils) { - jsmn_init(&test_parser); -} - -TEST_GROUP_C_TEARDOWN(JsonUtils) { - -} - -TEST_C(JsonUtils, ParseStringBasic) { - int r; - const char *json = "{\"x\":\"test1\"}"; - char parsedString[STRING_BUFFER_LENGTH]; - - IOT_DEBUG("\n-->Running Json Utils Tests - Basic String Parsing \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("test1", parsedString); -} - -TEST_C(JsonUtils, ParseStringLongerStringIsValid) { - int r; - const char *json = "{\"x\":\"this is a longer string for test 2\"}"; - char parsedString[STRING_BUFFER_LENGTH]; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse long string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("this is a longer string for test 2", parsedString); -} - -/* Test that parsing a string doesn't overflow the given buffer. */ -TEST_C(JsonUtils, ParseStringWithBufferTooSmall) { - static const char* const pJsonString = "{\"key\":\"This value is longer than JSON_BUFFER_LENGTH, which should be 50.\"}"; - char parsedString[STRING_BUFFER_LENGTH] = {0}; - int jsmnReturn, i; - - IOT_DEBUG("\n-->Running Json Utils Tests - String parsing with buffer too small. \n"); - - jsmnReturn = jsmn_parse(&test_parser, pJsonString, strlen(pJsonString), t, sizeof(t)/sizeof(t[0])); - CHECK_EQUAL_C_INT(3, jsmnReturn); - - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, pJsonString, t + 2); - - CHECK_EQUAL_C_INT(SHADOW_JSON_ERROR, rc); - - /* Ensure there was no attempt to write to a buffer that's too small. */ - for(i = 0; i < STRING_BUFFER_LENGTH; i++) - { - CHECK_EQUAL_C_CHAR(0, parsedString[i]); - } -} - -TEST_C(JsonUtils, ParseStringEmptyStringIsValid) { int r; - const char *json = "{\"x\":\"\"}"; - char parsedString[STRING_BUFFER_LENGTH]; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse empty string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("", parsedString); -} - -TEST_C(JsonUtils, ParseStringErrorOnInteger) { - int r; - const char *json = "{\"x\":3}"; - char parsedString[STRING_BUFFER_LENGTH]; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse integer as string returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseStringErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - char parsedString[STRING_BUFFER_LENGTH]; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean as string returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseStringValue(parsedString, STRING_BUFFER_LENGTH, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseBooleanTrue) { - int r; - const char *json = "{\"x\":true}"; - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean with true value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, (int) parsedBool); -} - -TEST_C(JsonUtils, ParseBooleanFalse) { - int r; - const char *json = "{\"x\":false}"; - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean with false value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(0, (int) parsedBool); -} - -TEST_C(JsonUtils, ParseBooleanErrorOnString) { - int r; - const char *json = "{\"x\":\"not a bool\"}"; - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse string as boolean returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseBooleanErrorOnInvalidJson) { - int r; - const char *json = "{\"x\":frue}"; // Invalid - bool parsedBool; - - IOT_DEBUG("\n-->Running Json Utils Tests - parse boolean returns error with invalid json \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseBooleanValue(&parsedBool, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleBasic) { - int r; - const char *json = "{\"x\":20.5}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse double test \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(20.5, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseDoubleNumberWithNoDecimal) { - int r; - const char *json = "{\"x\":100}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse double number with no decimal \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(100, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseDoubleSmallDouble) { - int r; - const char *json = "{\"x\":0.000004}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse small double value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(0.000004, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseDoubleErrorOnString) { - int r; - const char *json = "{\"x\":\"20.5\"}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse string as double returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse boolean as double returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleErrorOnJsonObject) { - int r; - const char *json = "{\"x\":{}}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse json object as double returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseDoubleNegativeNumber) { - int r; - const char *json = "{\"x\":-56.78}"; - double parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative double value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseDoubleValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(-56.78, parsedDouble, 0.0); -} - -TEST_C(JsonUtils, ParseFloatBasic) { - int r; - const char *json = "{\"x\":20.5}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse float test \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(20.5, parsedFloat, 0.0); -} - -TEST_C(JsonUtils, ParseFloatNumberWithNoDecimal) { - int r; - const char *json = "{\"x\":100}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse float number with no decimal \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_REAL(100, parsedFloat, 0.0); -} - -TEST_C(JsonUtils, ParseFloatSmallFloat) { - int r; - const char *json = "{\"x\":0.0004}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse small float value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(0.0004f == parsedFloat); -} - -TEST_C(JsonUtils, ParseFloatErrorOnString) { - int r; - const char *json = "{\"x\":\"20.5\"}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse string as float returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseFloatErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse boolean as float returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseFloatErrorOnJsonObject) { - int r; - const char *json = "{\"x\":{}}"; - float parsedDouble; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse json object as float returns error \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedDouble, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseFloatNegativeNumber) { - int r; - const char *json = "{\"x\":-56.78}"; - float parsedFloat; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative float value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseFloatValue(&parsedFloat, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(-56.78f == parsedFloat); -} - -TEST_C(JsonUtils, ParseIntegerBasic) { - int r; - const char *json = "{\"x\":1}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseIntegerLargeInteger) { - int r; - const char *json = "{\"x\":2147483647}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(2147483647, parsedInteger); -} - -TEST_C(JsonUtils, ParseIntegerNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(-308, parsedInteger); -} - -TEST_C(JsonUtils, ParseIntegerErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseIntegerErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - int32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 32 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger16bitBasic) { - int r; - const char *json = "{\"x\":1}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger16bitLargeInteger) { - int r; - const char *json = "{\"x\":32767}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(32767, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger16bitNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(-308, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger16bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger16bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - int16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 16 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger8bitBasic) { - int r; - const char *json = "{\"x\":1}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger8bitLargeInteger) { - int r; - const char *json = "{\"x\":127}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(127, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger8bitNegativeInteger) { - int r; - const char *json = "{\"x\":-30}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse negative 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(-30, parsedInteger); -} - -TEST_C(JsonUtils, ParseInteger8bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseInteger8bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - int8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse 8 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerBasic) { - int r; - const char *json = "{\"x\":1}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(1 == parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerLargeInteger) { - int r; - const char *json = "{\"x\":2147483647}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 32 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_C(2147483647 == parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error with negative value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedIntegerErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - uint32_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 32 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger32Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitBasic) { - int r; - const char *json = "{\"x\":1}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitLargeInteger) { - int r; - const char *json = "{\"x\":65535}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 16 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(65535, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnNegativeInteger) { - int r; - const char *json = "{\"x\":-308}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error on negative value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger16bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - uint16_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 16 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger16Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitBasic) { - int r; - const char *json = "{\"x\":1}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(1, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitLargeInteger) { - int r; - const char *json = "{\"x\":255}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse large unsigned 8 bit integer \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(255, parsedInteger); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnNegativeInteger) { - int r; - const char *json = "{\"x\":-30}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error on negative value \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnBoolean) { - int r; - const char *json = "{\"x\":true}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error with boolean \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} - -TEST_C(JsonUtils, ParseUnsignedInteger8bitErrorOnString) { - int r; - const char *json = "{\"x\":\"45\"}"; - uint8_t parsedInteger; - - IOT_DEBUG("\n-->Running Json Utils Tests - Parse unsigned 8 bit integer returns error on string \n"); - - r = jsmn_parse(&test_parser, json, strlen(json), t, sizeof(t) / sizeof(t[0])); - rc = parseUnsignedInteger8Value(&parsedInteger, json, t + 2); - - CHECK_EQUAL_C_INT(3, r); - CHECK_EQUAL_C_INT(JSON_PARSE_ERROR, rc); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish.cpp deleted file mode 100644 index da188e0fe..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_publish.cpp - * @brief IoT Client Unit Testing - Publish API Tests - */ - -#include -#include - -TEST_GROUP_C(PublishTests) { - TEST_GROUP_C_SETUP_WRAPPER(PublishTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(PublishTests) -}; - -/* E:1 - Publish with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNullClient) -/* E:2 - Publish with Null/empty Topic Name */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNullTopic) -/* E:3 - Publish with Null/empty payload */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNullParams) -/* E:4 - Publish with network disconnected */ -TEST_GROUP_C_WRAPPER(PublishTests, PublishNetworkDisconnected) -/* E:5 - Publish with QoS2 */ -/* Not required here, enum value doesn't exist for QoS2 */ -/* E:6 - Publish with QoS1 send success, Puback not received */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1FailureToReceivePuback) -/* E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1FailureDelayedPuback) -/* E:8 - Publish with send success, Delayed Puback received before command timeout */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1Success10msDelayedPuback) -/* E:9 - Publish QoS0 success */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS0NoPubackSuccess) -/* E:10 - Publish with QoS1 send success, Puback received */ -TEST_GROUP_C_WRAPPER(PublishTests, publishQoS1Success) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish_helper.c deleted file mode 100644 index 2f2c6406c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_publish_helper.c +++ /dev/null @@ -1,205 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_publish_helper.c - * @brief IoT Client Unit Testing - Publish API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static AWS_IoT_Client iotClient; -char cPayload[100]; - -TEST_GROUP_C_SETUP(PublishTests) { - IoT_Error_t rc = SUCCESS; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - sprintf(cPayload, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(PublishTests) { } - -/* E:1 - Publish with Null/empty client instance */ -TEST_C(PublishTests, PublishNullClient) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:1 - Publish with Null/empty client instance \n"); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = "Message"; - testPubMsgParams.payloadLen = 7; - - rc = aws_iot_mqtt_publish(NULL, "sdkTest/Sub", 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - E:1 - Publish with Null/empty client instance \n"); -} - -/* E:2 - Publish with Null/empty Topic Name */ -TEST_C(PublishTests, PublishNullTopic) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:2 - Publish with Null/empty Topic Name \n"); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = "Message"; - testPubMsgParams.payloadLen = 7; - - rc = aws_iot_mqtt_publish(&iotClient, NULL, 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 0, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - E:2 - Publish with Null/empty Topic Name \n"); -} - -/* E:3 - Publish with Null/empty payload */ -TEST_C(PublishTests, PublishNullParams) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:3 - Publish with Null/empty payload \n"); - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = NULL; - testPubMsgParams.payloadLen = 0; - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); - - IOT_DEBUG("-->Success - E:3 - Publish with Null/empty payload \n"); -} - -/* E:4 - Publish with network disconnected */ -TEST_C(PublishTests, PublishNetworkDisconnected) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:4 - Publish with network disconnected \n"); - - /* Ensure network is disconnected */ - rc = aws_iot_mqtt_disconnect(&iotClient); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - testPubMsgParams.payload = NULL; - testPubMsgParams.payloadLen = 0; - - rc = aws_iot_mqtt_publish(&iotClient, "sdkTest/Sub", 11, &testPubMsgParams); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - - IOT_DEBUG("-->Success - E:4 - Publish with network disconnected \n"); -} - -/* E:6 - Publish with QoS1 send success, Puback not received */ -TEST_C(PublishTests, publishQoS1FailureToReceivePuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:6 - Publish with QoS1 send success, Puback not received \n"); - - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - E:6 - Publish with QoS1 send success, Puback not received \n"); -} - -/* E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout */ -TEST_C(PublishTests, publishQoS1FailureDelayedPuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout \n"); - - setTLSRxBufferDelay(10, 0); - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - E:7 - Publish with QoS1 send success, Delayed Puback received after command timeout \n"); -} - -/* E:8 - Publish with send success, Delayed Puback received before command timeout */ -TEST_C(PublishTests, publishQoS1Success10msDelayedPuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:8 - Publish with send success, Delayed Puback received before command timeout \n"); - - ResetTLSBuffer(); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - E:8 - Publish with send success, Delayed Puback received before command timeout \n"); -} - -/* E:9 - Publish QoS0 success */ -TEST_C(PublishTests, publishQoS0NoPubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:9 - Publish QoS0 success \n"); - - testPubMsgParams.qos = QOS0; // switch to a Qos0 PUB - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - E:9 - Publish QoS0 success \n"); -} - -/* E:10 - Publish with QoS1 send success, Puback received */ -TEST_C(PublishTests, publishQoS1Success) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Publish Tests - E:10 - Publish with QoS1 send success, Puback received \n"); - - setTLSRxBufferForPuback(); - rc = aws_iot_mqtt_publish(&iotClient, subTopic, subTopicLen, &testPubMsgParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - E:10 - Publish with QoS1 send success, Puback received \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_runner.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_runner.cpp deleted file mode 100644 index ba1f5cb48..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_runner.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_runner.cpp - * @brief IoT Client Unit Testing - Runner - */ - -#include - -int main(int ac, char **argv) { - return CommandLineTestRunner::RunAllTests(ac, argv); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action.cpp deleted file mode 100644 index 32f1be2e1..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_shadow_action.cpp - * @brief IoT Client Unit Testing - Shadow Action Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowActionTests) { - TEST_GROUP_C_SETUP_WRAPPER(ShadowActionTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowActionTests) -}; - -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetTheFullJSONDocument) -TEST_GROUP_C_WRAPPER(ShadowActionTests, DeleteTheJSONDocument) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UpdateTheJSONDocument) -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetTheFullJSONDocumentTimeout) -TEST_GROUP_C_WRAPPER(ShadowActionTests, SubscribeToAcceptedRejectedOnGet) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeout) -TEST_GROUP_C_WRAPPER(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeoutWithSticky) -TEST_GROUP_C_WRAPPER(ShadowActionTests, WrongTokenInGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, NoTokenInGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, InvalidInboundJSONInGetResponse) -TEST_GROUP_C_WRAPPER(ShadowActionTests, AcceptedSubFailsGetRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, RejectedSubFailsGetRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, PublishFailsGetRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetVersionFromAckStatus) -TEST_GROUP_C_WRAPPER(ShadowActionTests, StickyNonStickyNeverConflict) -TEST_GROUP_C_WRAPPER(ShadowActionTests, ACKWaitingMoreThanAllowed) -TEST_GROUP_C_WRAPPER(ShadowActionTests, InboundDataTooBigForBuffer) -TEST_GROUP_C_WRAPPER(ShadowActionTests, NoClientTokenForShadowAction) -TEST_GROUP_C_WRAPPER(ShadowActionTests, NoCallbackForShadowAction) -TEST_GROUP_C_WRAPPER(ShadowActionTests, GetAndDeleteRequest) -TEST_GROUP_C_WRAPPER(ShadowActionTests, ExtractClientToken) -TEST_GROUP_C_WRAPPER(ShadowActionTests, IsReceivedJsonValid) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action_helper.c deleted file mode 100644 index 86e603197..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_action_helper.c +++ /dev/null @@ -1,944 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_shadow_action_helper.c - * @brief IoT Client Unit Testing - Shadow Action API Tests Helper - */ - -#include -#include -#include -#include -#include - -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_tests_unit_shadow_helper.h" - -#include "aws_iot_shadow_interface.h" -#include "aws_iot_shadow_actions.h" -#include "aws_iot_shadow_json.h" -#include "aws_iot_log.h" - -#define SIZE_OF_UPDATE_DOCUMENT 200 -#define TEST_JSON_RESPONSE_FULL_DOCUMENT "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" -#define TEST_JSON_RESPONSE_DELETE_DOCUMENT "{\"version\":2,\"timestamp\":1443473857,\"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" -#define TEST_JSON_RESPONSE_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" -#define TEST_JSON_SIZE 120 -static AWS_IoT_Client client; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -static Shadow_Ack_Status_t ackStatusRx; -static char jsonFullDocument[200]; -static ShadowActions_t actionRx; - -static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action) { - char actionBuf[10]; - - if(SHADOW_GET == action) { - strcpy(actionBuf, "get"); - } else if(SHADOW_UPDATE == action) { - strcpy(actionBuf, "update"); - } else if(SHADOW_DELETE == action) { - strcpy(actionBuf, "delete"); - } - - snprintf(pTopic, 100, "$aws/things/%s/shadow/%s", pThingName, actionBuf); -} - -TEST_GROUP_C_SETUP(ShadowActionTests) { - IoT_Error_t ret_val = SUCCESS; - char cPayload[100]; - char topic[120]; - - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - ret_val = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_shadow_connect(&client, &shadowConnectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - setTLSRxBufferForPuback(); - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload) + 1; - topicNameFromThingAndAction(topic, AWS_IOT_MY_THING_NAME, SHADOW_GET); - setTLSRxBufferForDoubleSuback(topic, strlen(topic), QOS1, testPubMsgParams); -} - -TEST_GROUP_C_TEARDOWN(ShadowActionTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_shadow_disconnect(&client); - IOT_UNUSED(rc); -} - -static void actionCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(pContextData); - IOT_DEBUG("%s", pReceivedJsonDocument); - actionRx = action; - ackStatusRx = status; - if(SHADOW_ACK_TIMEOUT != status) { - strcpy(jsonFullDocument, pReceivedJsonDocument); - } -} - -// Happy path for Get, Update, Delete -TEST_C(ShadowActionTests, GetTheFullJSONDocument) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Get full json document \n"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - IOT_DEBUG("-->Success - Get full json document \n"); -} - -TEST_C(ShadowActionTests, DeleteTheJSONDocument) { - IoT_Error_t ret_val = SUCCESS; - IoT_Publish_Message_Params params; - char deleteRequestJson[TEST_JSON_SIZE]; - - IOT_DEBUG("-->Running Shadow Action Tests - Delete json document \n"); - - aws_iot_shadow_internal_delete_request_json(deleteRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_DELETE, deleteRequestJson, TEST_JSON_SIZE, actionCallback, - NULL, 4, false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_DELETE_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_DELETE_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(DELETE_ACCEPTED_TOPIC, strlen(DELETE_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_DELETE_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_DELETE, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - IOT_DEBUG("-->Success - Delete json document \n"); -} - -TEST_C(ShadowActionTests, UpdateTheJSONDocument) { - IoT_Error_t ret_val = SUCCESS; - char updateRequestJson[SIZE_OF_UPDATE_DOCUMENT]; - char expectedUpdateRequestJson[SIZE_OF_UPDATE_DOCUMENT]; - double doubleData = 4.0908f; - float floatData = 3.445f; - bool boolData = true; - jsonStruct_t dataFloatHandler; - jsonStruct_t dataDoubleHandler; - jsonStruct_t dataBoolHandler; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Update json document \n"); - - dataFloatHandler.cb = NULL; - dataFloatHandler.pData = &floatData; - dataFloatHandler.dataLength = sizeof(float); - dataFloatHandler.pKey = "floatData"; - dataFloatHandler.type = SHADOW_JSON_FLOAT; - - dataDoubleHandler.cb = NULL; - dataDoubleHandler.pData = &doubleData; - dataDoubleHandler.dataLength = sizeof(double); - dataDoubleHandler.pKey = "doubleData"; - dataDoubleHandler.type = SHADOW_JSON_DOUBLE; - - dataBoolHandler.cb = NULL; - dataBoolHandler.pData = &boolData; - dataBoolHandler.dataLength = sizeof(bool); - dataBoolHandler.pKey = "boolData"; - dataBoolHandler.type = SHADOW_JSON_BOOL; - - ret_val = aws_iot_shadow_init_json_document(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_reported(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, 2, &dataDoubleHandler, - &dataFloatHandler); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_desired(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, 1, &dataBoolHandler); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_finalize_json_document(updateRequestJson, SIZE_OF_UPDATE_DOCUMENT); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - snprintf(expectedUpdateRequestJson, SIZE_OF_UPDATE_DOCUMENT, - "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000},\"desired\":{\"boolData\":true}}, \"clientToken\":\"%s-0\"}", - AWS_IOT_MQTT_CLIENT_ID); - CHECK_EQUAL_C_STRING(expectedUpdateRequestJson, updateRequestJson); - - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_UPDATE, updateRequestJson, SIZE_OF_UPDATE_DOCUMENT, actionCallback, - NULL, 4, false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - snprintf(jsonFullDocument, 200, "%s", ""); - params.payloadLen = strlen(TEST_JSON_RESPONSE_UPDATE_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_UPDATE_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(UPDATE_ACCEPTED_TOPIC, strlen(UPDATE_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_UPDATE_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_UPDATE, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - IOT_DEBUG("-->Success - Update json document \n"); -} - -TEST_C(ShadowActionTests, GetTheFullJSONDocumentTimeout) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Get full json document timeout \n"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx); - - IOT_DEBUG("-->Success - Get full json document timeout \n"); -} - -// Subscribe and UnSubscribe on reception of thing names. Will perform the test with Get operation -TEST_C(ShadowActionTests, SubscribeToAcceptedRejectedOnGet) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - - uint8_t firstByte, secondByte; - uint16_t topicNameLen; - char topicName[128] = "test"; - - IOT_DEBUG("-->Running Shadow Action Tests - Subscribe to get/accepted and get/rejected \n"); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - firstByte = (uint8_t)(TxBuffer.pBuffer[2]); - secondByte = (uint8_t)(TxBuffer.pBuffer[3]); - topicNameLen = (uint16_t) (secondByte + (256 * firstByte)); - - snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character - - // Verify publish happens - CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName); - - IOT_DEBUG("-->Success - Subscribe to get/accepted and get/rejected \n"); -} - -TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - unsubscribe to get/accepted and get/rejected on response \n"); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - unsubscribe to get/accepted and get/rejected on response \n"); -} - -TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeout) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Unsubscribe to get/accepted and get/rejected on get timeout \n"); - - snprintf(jsonFullDocument, 200, "aa"); - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("aa", jsonFullDocument); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - Unsubscribe to get/accepted and get/rejected on get timeout \n"); -} - - -TEST_C(ShadowActionTests, UnSubscribeToAcceptedRejectedOnGetTimeoutWithSticky) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - No unsubscribe to get/accepted and get/rejected on get timeout with a sticky subscription \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - true); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("timeout", jsonFullDocument); - - CHECK_EQUAL_C_STRING(GET_REJECTED_TOPIC, LastSubscribeMessage); - CHECK_EQUAL_C_STRING(GET_ACCEPTED_TOPIC, SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - No unsubscribe to get/accepted and get/rejected on get timeout with a sticky subscription \n"); -} - -#define TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(num) "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\",\"version\":" #num "}" - -TEST_C(ShadowActionTests, GetVersionFromAckStatus) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - IoT_Publish_Message_Params params2; - - IOT_DEBUG("-->Running Shadow Action Tests - Get version from Ack status \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - true); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(1); - params.payloadLen = strlen(params.payload); - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_C(1u == aws_iot_shadow_get_last_received_version()); - - ResetTLSBuffer(); - params2.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_WITH_VERSION(132387); - params2.payloadLen = strlen(params2.payload); - params2.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params2, - params2.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_C(132387u == aws_iot_shadow_get_last_received_version()); - - IOT_DEBUG("-->Success - Get version from Ack status \n"); -} - -#define TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}, \"clientToken\":\"TroubleToken1234\"}" - -TEST_C(ShadowActionTests, WrongTokenInGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Wrong token in get response \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_ALWAYS_WRONG_TOKEN; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("timeout", jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx); - - IOT_DEBUG("-->Success - Wrong token in get response \n"); -} - -#define TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}}" - -TEST_C(ShadowActionTests, NoTokenInGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - No token in get response \n"); - - snprintf(jsonFullDocument, 200, "timeout"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - sleep(4 + 1); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT_NO_TOKEN; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("timeout", jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_TIMEOUT, ackStatusRx); - - IOT_DEBUG("-->Success - No token in get response \n"); -} - -TEST_C(ShadowActionTests, InvalidInboundJSONInGetResponse) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Invalid inbound json in get response \n"); - - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen("{\"state\":{{"); - params.payload = "{\"state\":{{"; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - IOT_DEBUG("-->Success - Invalid inbound json in get response \n"); -} - -TEST_C(ShadowActionTests, AcceptedSubFailsGetRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Accepted sub fails get request \n"); - - snprintf(jsonFullDocument, 200, "NOT_SENT"); - - ResetTLSBuffer(); - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback - - IOT_DEBUG("-->Success - Accepted sub fails get request \n"); -} - -TEST_C(ShadowActionTests, RejectedSubFailsGetRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Rejected sub fails get request \n"); - - snprintf(jsonFullDocument, 200, "NOT_SENT"); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params); - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(GET_REJECTED_TOPIC, strlen(GET_REJECTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback - - IOT_DEBUG("-->Success - Rejected sub fails get request \n"); -} - -TEST_C(ShadowActionTests, PublishFailsGetRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - publish fails on get request \n"); - - snprintf(jsonFullDocument, 200, "NOT_SENT"); - - ResetTLSBuffer(); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, ret_val); // Should never subscribe and publish - - ResetTLSBuffer(); - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING("NOT_SENT", jsonFullDocument); // Never called callback - - IOT_DEBUG("-->Success - publish fails on get request \n"); -} - -TEST_C(ShadowActionTests, StickyNonStickyNeverConflict) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - IOT_DEBUG("-->Running Shadow Action Tests - Sticky and non-sticky subscriptions do not conflict \n"); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - true); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - lastSubscribeMsgLen = 11; - snprintf(LastSubscribeMessage, lastSubscribeMsgLen, "No Message"); - secondLastSubscribeMsgLen = 11; - snprintf(SecondLastSubscribeMessage, secondLastSubscribeMsgLen, "No Message"); - - // Non-sticky shadow get, same thing name. Should never unsub since they are sticky - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - ResetTLSBuffer(); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_FULL_DOCUMENT, jsonFullDocument); - CHECK_EQUAL_C_INT(SHADOW_GET, actionRx); - CHECK_EQUAL_C_INT(SHADOW_ACK_ACCEPTED, ackStatusRx); - - CHECK_EQUAL_C_STRING("No Message", LastSubscribeMessage); - CHECK_EQUAL_C_STRING("No Message", SecondLastSubscribeMessage); - - IOT_DEBUG("-->Success - Sticky and non-sticky subscriptions do not conflict \n"); - -} - -TEST_C(ShadowActionTests, ACKWaitingMoreThanAllowed) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - - IOT_DEBUG("-->Running Shadow Action Tests - Ack waiting more than allowed wait time \n"); - - // 1st - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 2nd - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 3rd - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 4th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 5th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 6th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 7th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 8th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 9th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 10th - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // 11th - // Should return some error code, since we are running out of ACK space - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, - 100, false); // 100 sec to timeout - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - IOT_DEBUG("-->Success - Ack waiting more than allowed wait time \n"); -} - -TEST_C(ShadowActionTests, InboundDataTooBigForBuffer) { - uint32_t i = 0; - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - char expectedCallbackString[AWS_IOT_MQTT_RX_BUF_LEN + 2]; - - IOT_DEBUG("-->Running Shadow Action Tests - Inbound data too big for buffer \n"); - - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - for(i = 0; i < AWS_IOT_MQTT_RX_BUF_LEN; i++) { - expectedCallbackString[i] = 'X'; - } - expectedCallbackString[i + 1] = '\0'; - - params.payloadLen = strlen(expectedCallbackString); - params.payload = expectedCallbackString; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - CHECK_EQUAL_C_INT(MQTT_RX_BUFFER_TOO_SHORT_ERROR, ret_val); - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - IOT_DEBUG("-->Success - Inbound data too big for buffer \n"); -} - -#define TEST_JSON_RESPONSE_NO_TOKEN "{\"state\":{\"reported\":{\"sensor1\":98}}}" - -TEST_C(ShadowActionTests, NoClientTokenForShadowAction) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - uint8_t firstByte, secondByte; - uint16_t topicNameLen; - char topicName[128] = "test"; - - IOT_DEBUG("-->Running Shadow Action Tests - No client token for shadow action \n"); - - snprintf(getRequestJson, TEST_JSON_SIZE, "{}"); - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, actionCallback, NULL, 4, - false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_NO_TOKEN); - params.payload = TEST_JSON_RESPONSE_NO_TOKEN; - params.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // Should never subscribe to accepted/rejected topics since we have no token to track the response - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - firstByte = (uint8_t)(TxBuffer.pBuffer[2]); - secondByte = (uint8_t)(TxBuffer.pBuffer[3]); - topicNameLen = (uint16_t) (secondByte + (256 * firstByte)); - - snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character - - // Verify publish happens - CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName); - - IOT_DEBUG("-->Success - No client token for shadow action \n"); -} - -TEST_C(ShadowActionTests, IsReceivedJsonValid) -{ - bool ret_val; - char getRequestJson[TEST_JSON_SIZE]; - - IOT_DEBUG("-->Running Shadow Action Tests - IsReceivedJsonValid \n"); - - snprintf(getRequestJson, TEST_JSON_SIZE, TEST_JSON_RESPONSE_FULL_DOCUMENT); - - //Test by cutting the JSON document - ret_val = isReceivedJsonValid(getRequestJson, 3); - CHECK_EQUAL_C_INT(false, ret_val); - - //Happy path - ret_val = isReceivedJsonValid(getRequestJson, TEST_JSON_SIZE); - CHECK_EQUAL_C_INT(true, ret_val); - - IOT_DEBUG("-->Success - IsReceivedJsonValid"); -} - -TEST_C(ShadowActionTests, ExtractClientToken) -{ - bool ret_val; - char getRequestJson[TEST_JSON_SIZE]; - char extractedClientToken[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE]; - - IOT_DEBUG("-->Running Shadow Action Tests - ExtractClientToken \n"); - - //Try JSON with no token - snprintf(getRequestJson, TEST_JSON_SIZE, "{}"); - ret_val = extractClientToken(getRequestJson, TEST_JSON_SIZE, extractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE ); - CHECK_EQUAL_C_INT(false, ret_val); - - //Try JSON with token but not enough memory - snprintf(getRequestJson, TEST_JSON_SIZE, TEST_JSON_RESPONSE_FULL_DOCUMENT); - ret_val = extractClientToken(getRequestJson, TEST_JSON_SIZE, extractedClientToken, 1 ); - CHECK_EQUAL_C_INT(false, ret_val); - - //Happy path - ret_val = extractClientToken(getRequestJson, TEST_JSON_SIZE, extractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE ); - CHECK_EQUAL_C_INT(true, ret_val); - - IOT_DEBUG("-->Success - ExtractClientToken"); -} - -TEST_C(ShadowActionTests, GetAndDeleteRequest) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - - IOT_DEBUG("-->Running Shadow Action Tests - GetAndDeleteRequest \n"); - - ret_val = aws_iot_shadow_internal_get_request_json(NULL, TEST_JSON_SIZE); - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - ret_val = aws_iot_shadow_internal_get_request_json(getRequestJson, 1); - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - ret_val = aws_iot_shadow_internal_delete_request_json(NULL, TEST_JSON_SIZE); - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - ret_val = aws_iot_shadow_internal_delete_request_json(getRequestJson, 1); - CHECK_EQUAL_C_INT(FAILURE, ret_val); - - IOT_DEBUG("-->Success - GetAndDeleteRequest"); -} - -TEST_C(ShadowActionTests, NoCallbackForShadowAction) { - IoT_Error_t ret_val = SUCCESS; - char getRequestJson[TEST_JSON_SIZE]; - IoT_Publish_Message_Params params; - - uint8_t firstByte, secondByte; - uint16_t topicNameLen; - char topicName[128] = "test"; - - IOT_DEBUG("-->Running Shadow Action Tests - No callback for shadow action \n"); - - snprintf(jsonFullDocument, 200, "NOT_VISITED"); - - aws_iot_shadow_internal_get_request_json(getRequestJson, TEST_JSON_SIZE); - ret_val = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_GET, getRequestJson, TEST_JSON_SIZE, NULL, NULL, 4, false); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - params.payloadLen = strlen(TEST_JSON_RESPONSE_FULL_DOCUMENT); - params.payload = TEST_JSON_RESPONSE_FULL_DOCUMENT; - setTLSRxBufferWithMsgOnSubscribedTopic(GET_ACCEPTED_TOPIC, strlen(GET_ACCEPTED_TOPIC), QOS0, params, - params.payload); - ret_val = aws_iot_shadow_yield(&client, 200); - - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - // Should never subscribe to accepted/rejected topics since we have no callback to track the response - CHECK_EQUAL_C_STRING("NOT_VISITED", jsonFullDocument); - - firstByte = (uint8_t)(TxBuffer.pBuffer[2]); - secondByte = (uint8_t)(TxBuffer.pBuffer[3]); - topicNameLen = (uint16_t) (secondByte + (256 * firstByte)); - - snprintf(topicName, topicNameLen + 1u, "%s", &(TxBuffer.pBuffer[4])); // Added one for null character - - // Verify publish happens - CHECK_EQUAL_C_STRING(GET_PUB_TOPIC, topicName); - - IOT_DEBUG("-->Success - No callback for shadow action"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta.cpp deleted file mode 100644 index db9c0b25d..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_shadow_delta.cpp - * @brief IoT Client Unit Testing - Shadow Delta Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowDeltaTest){ - TEST_GROUP_C_SETUP_WRAPPER(ShadowDeltaTest) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowDeltaTest) -}; - -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaSuccess) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaInt) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, registerDeltaIntNoCallback) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, DeltaNestedObject) -TEST_GROUP_C_WRAPPER(ShadowDeltaTest, DeltaVersionIgnoreOldVersion) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta_helper.c deleted file mode 100644 index 1e6cc2a0a..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_delta_helper.c +++ /dev/null @@ -1,324 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_shadow_delta_helper.c - * @brief IoT Client Unit Testing - Shadow Delta Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_shadow_interface.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static AWS_IoT_Client client; -static IoT_Client_Connect_Params connectParams; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -static char receivedNestedObject[100] = ""; -static char sentNestedObjectData[100] = "{\"sensor1\":23}"; -static char shadowDeltaTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; - -#define SHADOW_DELTA_UPDATE "$aws/things/%s/shadow/update/delta" - -#undef AWS_IOT_MY_THING_NAME -#define AWS_IOT_MY_THING_NAME "AWS-IoT-C-SDK" - -void genericCallback(const char *pJsonStringData, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - printf("\nkey[%s]==Data[%.*s]\n", pContext->pKey, JsonStringDataLen, pJsonStringData); -} - -void nestedObjectCallback(const char *pJsonStringData, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - printf("\nkey[%s]==Data[%.*s]\n", pContext->pKey, JsonStringDataLen, pJsonStringData); - snprintf(receivedNestedObject, 100, "%.*s", JsonStringDataLen, pJsonStringData); -} - -TEST_GROUP_C_SETUP(ShadowDeltaTest) { - IoT_Error_t ret_val = SUCCESS; - - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - ret_val = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_shadow_connect(&client, &shadowConnectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - snprintf(shadowDeltaTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, SHADOW_DELTA_UPDATE, AWS_IOT_MY_THING_NAME); -} - -TEST_GROUP_C_TEARDOWN(ShadowDeltaTest) { - -} - -TEST_C(ShadowDeltaTest, registerDeltaSuccess) { - jsonStruct_t windowHandler; - char deltaJSONString[] = "{\"state\":{\"delta\":{\"window\":true}},\"version\":1}"; - bool windowOpenData = false; - IoT_Publish_Message_Params params; - IoT_Error_t ret_val = SUCCESS; - - IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta success \n"); - - windowHandler.cb = genericCallback; - windowHandler.pKey = "window"; - windowHandler.type = SHADOW_JSON_BOOL; - windowHandler.pData = &windowOpenData; - windowHandler.dataLength = sizeof(bool); - - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &windowHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - ret_val = aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_INT(true, windowOpenData); -} - - -TEST_C(ShadowDeltaTest, registerDeltaInt) { - IoT_Error_t ret_val = SUCCESS; - jsonStruct_t intHandler; - int32_t intData = 0; - char deltaJSONString[] = "{\"state\":{\"delta\":{\"length\":23}},\"version\":1}"; - IoT_Publish_Message_Params params; - - IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta integer \n"); - - intHandler.cb = genericCallback; - intHandler.pKey = "length"; - intHandler.type = SHADOW_JSON_INT32; - intHandler.pData = &intData; - intHandler.dataLength = sizeof(int32_t); - - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &intHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_INT(23, intData); -} - -TEST_C(ShadowDeltaTest, registerDeltaIntNoCallback) { - IoT_Error_t ret_val = SUCCESS; - jsonStruct_t intHandler; - int32_t intData = 0; - char deltaJSONString[] = "{\"state\":{\"delta\":{\"length_nocb\":23}},\"version\":1}"; - IoT_Publish_Message_Params params; - - IOT_DEBUG("\n-->Running Shadow Delta Tests - Register delta integer with no callback \n"); - - intHandler.cb = NULL; - intHandler.pKey = "length_nocb"; - intHandler.type = SHADOW_JSON_INT32; - intHandler.pData = &intData; - intHandler.dataLength = sizeof(int32_t); - - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &intHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_INT(23, intData); -} - -TEST_C(ShadowDeltaTest, DeltaNestedObject) { - IoT_Error_t ret_val = SUCCESS; - IoT_Publish_Message_Params params; - jsonStruct_t nestedObjectHandler; - char nestedObject[100]; - char deltaJSONString[100]; - - printf("\n-->Running Shadow Delta Tests - Delta received with nested object \n"); - - nestedObjectHandler.cb = nestedObjectCallback; - nestedObjectHandler.pKey = "sensors"; - nestedObjectHandler.type = SHADOW_JSON_OBJECT; - nestedObjectHandler.pData = &nestedObject; - nestedObjectHandler.dataLength = 100; - - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":1}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &nestedObjectHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 3000); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); -} - - -// Send back to back version and ensure a wrong version is ignored with old message enabled -TEST_C(ShadowDeltaTest, DeltaVersionIgnoreOldVersion) { - IoT_Error_t ret_val = SUCCESS; - char deltaJSONString[100]; - jsonStruct_t nestedObjectHandler; - char nestedObject[100]; - IoT_Publish_Message_Params params; - - printf("\n-->Running Shadow Delta Tests - delta received, old version ignored \n"); - - nestedObjectHandler.cb = nestedObjectCallback; - nestedObjectHandler.pKey = "sensors"; - nestedObjectHandler.type = SHADOW_JSON_OBJECT; - nestedObjectHandler.pData = &nestedObject; - nestedObjectHandler.dataLength = 100; - - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":1}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferForSuback(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params); - - ret_val = aws_iot_shadow_register_delta(&client, &nestedObjectHandler); - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":2}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":2}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(" ", receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - aws_iot_shadow_reset_last_received_version(); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(" ", receivedNestedObject); - - aws_iot_shadow_disable_discard_old_delta_msgs(); - - snprintf(receivedNestedObject, 100, " "); - snprintf(deltaJSONString, 100, "{\"state\":{\"delta\":{\"%s\":%s}},\"version\":3}", nestedObjectHandler.pKey, - sentNestedObjectData); - params.payloadLen = strlen(deltaJSONString); - params.payload = deltaJSONString; - params.qos = QOS0; - - ResetTLSBuffer(); - setTLSRxBufferWithMsgOnSubscribedTopic(shadowDeltaTopic, strlen(shadowDeltaTopic), QOS0, params, params.payload); - - aws_iot_shadow_yield(&client, 100); - CHECK_EQUAL_C_STRING(sentNestedObjectData, receivedNestedObject); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder.cpp deleted file mode 100644 index 8feb144e5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_shadow_json_builder.cpp - * @brief IoT Client Unit Testing - Shadow JSON Builder Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowJsonBuilderTests){ - TEST_GROUP_C_SETUP_WRAPPER(ShadowJsonBuilderTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowJsonBuilderTests) -}; - -TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, UpdateTheJSONDocumentBuilder) -TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, PassingNullValue) -TEST_GROUP_C_WRAPPER(ShadowJsonBuilderTests, SmallBuffer) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder_helper.c deleted file mode 100644 index 3541341b5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_json_builder_helper.c +++ /dev/null @@ -1,131 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_shadow_json_builder_helper.c - * @brief IoT Client Unit Testing - Shadow JSON Builder Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_shadow_actions.h" -#include "aws_iot_log.h" -#include "aws_iot_tests_unit_helper_functions.h" - -static jsonStruct_t dataFloatHandler; -static jsonStruct_t dataDoubleHandler; -static double doubleData = 4.0908f; -static float floatData = 3.445f; -static AWS_IoT_Client iotClient; -static IoT_Client_Connect_Params connectParams; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -TEST_GROUP_C_SETUP(ShadowJsonBuilderTests) { - IoT_Error_t ret_val; - - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - ret_val = aws_iot_shadow_init(&iotClient, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - ret_val = aws_iot_shadow_connect(&iotClient, &shadowConnectParams); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - dataFloatHandler.cb = NULL; - dataFloatHandler.pData = &floatData; - dataFloatHandler.pKey = "floatData"; - dataFloatHandler.type = SHADOW_JSON_FLOAT; - dataFloatHandler.dataLength = sizeof(float); - - dataDoubleHandler.cb = NULL; - dataDoubleHandler.pData = &doubleData; - dataDoubleHandler.pKey = "doubleData"; - dataDoubleHandler.type = SHADOW_JSON_DOUBLE; - dataDoubleHandler.dataLength = sizeof(double); -} - -TEST_GROUP_C_TEARDOWN(ShadowJsonBuilderTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -#define TEST_JSON_RESPONSE_UPDATE_DOCUMENT "{\"state\":{\"reported\":{\"doubleData\":4.090800,\"floatData\":3.445000}}, \"clientToken\":\"" AWS_IOT_MQTT_CLIENT_ID "-0\"}" - -#define SIZE_OF_UPFATE_BUF 200 - -TEST_C(ShadowJsonBuilderTests, UpdateTheJSONDocumentBuilder) { - IoT_Error_t ret_val; - char updateRequestJson[SIZE_OF_UPFATE_BUF]; - size_t jsonBufSize = sizeof(updateRequestJson) / sizeof(updateRequestJson[0]); - - IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Update the Json document builder \n"); - - ret_val = aws_iot_shadow_init_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_reported(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_finalize_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - - CHECK_EQUAL_C_STRING(TEST_JSON_RESPONSE_UPDATE_DOCUMENT, updateRequestJson); -} - -TEST_C(ShadowJsonBuilderTests, PassingNullValue) { - IoT_Error_t ret_val; - - IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Passing Null value to Shadow json builder \n"); - - ret_val = aws_iot_shadow_init_json_document(NULL, SIZE_OF_UPFATE_BUF); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); - ret_val = aws_iot_shadow_add_reported(NULL, SIZE_OF_UPFATE_BUF, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); - ret_val = aws_iot_shadow_add_desired(NULL, SIZE_OF_UPFATE_BUF, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); - ret_val = aws_iot_finalize_json_document(NULL, SIZE_OF_UPFATE_BUF); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, ret_val); -} - -TEST_C(ShadowJsonBuilderTests, SmallBuffer) { - IoT_Error_t ret_val; - char updateRequestJson[14]; - size_t jsonBufSize = sizeof(updateRequestJson) / sizeof(updateRequestJson[0]); - - IOT_DEBUG("\n-->Running Shadow Json Builder Tests - Json Buffer is too small \n"); - - ret_val = aws_iot_shadow_init_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SUCCESS, ret_val); - ret_val = aws_iot_shadow_add_reported(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(SHADOW_JSON_BUFFER_TRUNCATED, ret_val); - ret_val = aws_iot_shadow_add_desired(updateRequestJson, jsonBufSize, 2, &dataDoubleHandler, &dataFloatHandler); - CHECK_EQUAL_C_INT(SHADOW_JSON_ERROR, ret_val); - ret_val = aws_iot_finalize_json_document(updateRequestJson, jsonBufSize); - CHECK_EQUAL_C_INT(SHADOW_JSON_ERROR, ret_val); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields.cpp deleted file mode 100644 index dd4d02a6b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_shadow_null_fields.cpp - * @brief IoT Client Unit Testing - Shadow APIs NULL field Tests - */ - -#include -#include - -TEST_GROUP_C(ShadowNullFields){ - TEST_GROUP_C_SETUP_WRAPPER(ShadowNullFields) - TEST_GROUP_C_TEARDOWN_WRAPPER(ShadowNullFields) -}; - -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientInit) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientConnect) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullHost) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullPort) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientID) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullUpdateDocument) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientYield) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientDisconnect) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowGet) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowUpdate) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientShadowDelete) -TEST_GROUP_C_WRAPPER(ShadowNullFields, NullClientSetAutoreconnect) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields_helper.c deleted file mode 100644 index 0848bd0a5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_shadow_null_fields_helper.c +++ /dev/null @@ -1,151 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_shadow_null_fields_helper.c - * @brief IoT Client Unit Testing - Shadow APIs NULL field Tests helper - */ - -#include -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_shadow_interface.h" -#include "aws_iot_shadow_actions.h" -#include "aws_iot_log.h" - -static AWS_IoT_Client client; -static ShadowInitParameters_t shadowInitParams; -static ShadowConnectParameters_t shadowConnectParams; - -static Shadow_Ack_Status_t ackStatusRx; -static ShadowActions_t actionRx; -static char jsonFullDocument[200]; - -void actionCallbackNullTest(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(pContextData); - IOT_DEBUG("%s", pReceivedJsonDocument); - actionRx = action; - ackStatusRx = status; - if(status != SHADOW_ACK_TIMEOUT) { - strcpy(jsonFullDocument, pReceivedJsonDocument); - } -} - -TEST_GROUP_C_SETUP(ShadowNullFields) { - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(ShadowNullFields) { } - -TEST_C(ShadowNullFields, NullHost) { - shadowInitParams.pHost = NULL; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.disconnectHandler = NULL; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullPort) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = 0; - shadowInitParams.disconnectHandler = NULL; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientID) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = NULL; - rc = aws_iot_shadow_connect(&client, &shadowConnectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientInit) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.disconnectHandler = NULL; - IoT_Error_t rc = aws_iot_shadow_init(NULL, &shadowInitParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientConnect) { - shadowInitParams.pHost = AWS_IOT_MQTT_HOST; - shadowInitParams.port = AWS_IOT_MQTT_PORT; - shadowInitParams.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME; - shadowInitParams.pRootCA = AWS_IOT_ROOT_CA_FILENAME; - shadowInitParams.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME; - shadowInitParams.disconnectHandler = NULL; - shadowInitParams.enableAutoReconnect = false; - IoT_Error_t rc = aws_iot_shadow_init(&client, &shadowInitParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - shadowConnectParams.pMyThingName = AWS_IOT_MY_THING_NAME; - shadowConnectParams.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; - shadowConnectParams.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); - rc = aws_iot_shadow_connect(NULL, &shadowConnectParams); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullUpdateDocument) { - IoT_Error_t rc = aws_iot_shadow_internal_action(AWS_IOT_MY_THING_NAME, SHADOW_UPDATE, NULL, 0, actionCallbackNullTest, - NULL, 4, false); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientYield) { - IoT_Error_t rc = aws_iot_shadow_yield(NULL, 1000); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientDisconnect) { - IoT_Error_t rc = aws_iot_shadow_disconnect(NULL); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientShadowGet) { - IoT_Error_t rc = aws_iot_shadow_get(NULL, AWS_IOT_MY_THING_NAME, actionCallbackNullTest, NULL, 100, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientShadowUpdate) { - IoT_Error_t rc = aws_iot_shadow_update(NULL, AWS_IOT_MY_THING_NAME, jsonFullDocument, - actionCallbackNullTest, NULL, 100, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientShadowDelete) { - IoT_Error_t rc = aws_iot_shadow_delete(NULL, AWS_IOT_MY_THING_NAME, actionCallbackNullTest, NULL, 100, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -TEST_C(ShadowNullFields, NullClientSetAutoreconnect) { - IoT_Error_t rc = aws_iot_shadow_set_autoreconnect_status(NULL, true); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe.cpp deleted file mode 100644 index f19a7c9c7..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_subscribe.cpp - * @brief IoT Client Unit Testing - Subscribe API Tests - */ - -#include -#include - -TEST_GROUP_C(SubscribeTests){ - TEST_GROUP_C_SETUP_WRAPPER(SubscribeTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(SubscribeTests) -}; - -/* C:1 - Subscribe with Null/empty Client Instance */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullClient) -/* C:2 - Subscribe with Null/empty Topic Name */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullTopic) -/* C:3 - Subscribe with Null client callback */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullSubscribeHandler) -/* C:4 - Subscribe with Null client callback data */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNullSubscribeHandlerData) -/* C:5 - Subscribe with no connection */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeNoConnection) -/* C:6 - Subscribe QoS2, error */ -/* Not required, QoS enum doesn't have value for QoS2 */ - -/* C:7 - Subscribe attempt, QoS0, no response timeout */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0FailureOnNoSuback) -/* C:8 - Subscribe attempt, QoS1, no response timeout */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1FailureOnNoSuback) - -/* C:9 - Subscribe QoS0 success, suback received */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0Success) -/* C:10 - Subscribe QoS1 success, suback received */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1Success) - -/* C:11 - Subscribe, QoS0, delayed suback, success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0WithDelayedSubackSuccess) -/* C:12 - Subscribe, QoS1, delayed suback, success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1WithDelayedSubackSuccess) - -/* C:13 - Subscribe QoS0 success, no puback sent on message */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS0MsgReceivedAndNoPubackSent) -/* C:14 - Subscribe QoS1 success, puback sent on message */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeQoS1MsgReceivedAndSendPuback) - -/* C:15 - Subscribe, malformed response */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeMalformedResponse) - -/* C:16 - Subscribe, multiple topics, messages on each topic */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeToMultipleTopicsSuccess) -/* C:17 - Subscribe, max topics, messages on each topic */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeToMaxAllowedTopicsSuccess) -/* C:18 - Subscribe, max topics, another subscribe */ -TEST_GROUP_C_WRAPPER(SubscribeTests, SubscribeToMaxPlusOneAllowedTopicsFailure) - -/* C:19 - Subscribe, '#' not last character in topic name, Failure */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicWithHashkeyAllSubTopicSuccess) -/* C:20 - Subscribe with '#', subscribed to all subtopics */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicHashkeyMustBeTheLastFail) -/* C:21 - Subscribe with '+' as wildcard success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicWithPluskeySuccess) -/* C:22 - Subscribe with '+' as last character in topic name, Success */ -TEST_GROUP_C_WRAPPER(SubscribeTests, subscribeTopicPluskeyComesLastSuccess) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe_helper.c deleted file mode 100644 index 53e4c67fc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_subscribe_helper.c +++ /dev/null @@ -1,606 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_subscribe_helper.c - * @brief IoT Client Unit Testing - Subscribe API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static AWS_IoT_Client iotClient; -static char CallbackMsgString[100]; -char cPayload[100]; - -static char CallbackMsgString1[100] = {"XXXX"}; -static char CallbackMsgString2[100] = {"XXXX"}; -static char CallbackMsgString3[100] = {"XXXX"}; -static char CallbackMsgString4[100] = {"XXXX"}; -static char CallbackMsgString5[100] = {"XXXX"}; -static char CallbackMsgString6[100] = {"XXXX"}; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler1(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - printf("callback topic %.*s\n", topicNameLen, topicName); - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString1[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler2(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString2[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler3(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString3[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler4(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString4[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler5(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString5[i] = tmp[i]; - } -} - -static void iot_subscribe_callback_handler6(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString6[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(SubscribeTests) { - IoT_Error_t rc; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(SubscribeTests) { } - - - -/* C:1 - Subscribe with Null/empty Client Instance */ -TEST_C(SubscribeTests, SubscribeNullClient) { - IoT_Error_t rc = aws_iot_mqtt_subscribe(NULL, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, &iotClient); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* C:2 - Subscribe with Null/empty Topic Name */ -TEST_C(SubscribeTests, SubscribeNullTopic) { - IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, NULL, 11, QOS1, iot_subscribe_callback_handler, &iotClient); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* C:3 - Subscribe with Null client callback */ -TEST_C(SubscribeTests, SubscribeNullSubscribeHandler) { - IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, NULL, &iotClient); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} -/* C:4 - Subscribe with Null client callback data */ -TEST_C(SubscribeTests, SubscribeNullSubscribeHandlerData) { - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - IoT_Error_t rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); -} -/* C:5 - Subscribe with no connection */ -TEST_C(SubscribeTests, SubscribeNoConnection) { - /* Disconnect first */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - - rc = aws_iot_mqtt_subscribe(&iotClient, "sdkTest/Sub", 11, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); -} -/* C:6 - Subscribe QoS2, error */ -/* Not required, QoS enum doesn't have value for QoS2 */ - -/* C:7 - Subscribe attempt, QoS0, no response timeout */ -TEST_C(SubscribeTests, subscribeQoS0FailureOnNoSuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:7 - Subscribe attempt, QoS0, no response timeout \n"); - - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - C:7 - Subscribe attempt, QoS0, no response timeout \n"); -} -/* C:8 - Subscribe attempt, QoS1, no response timeout */ -TEST_C(SubscribeTests, subscribeQoS1FailureOnNoSuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:8 - Subscribe attempt, QoS1, no response timeout \n"); - - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - - IOT_DEBUG("-->Success - C:8 - Subscribe attempt, QoS1, no response timeout \n"); -} - -/* C:9 - Subscribe QoS0 success, suback received */ -TEST_C(SubscribeTests, subscribeQoS0Success) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:9 - Subscribe QoS0 success, suback received \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:9 - Subscribe QoS0 success, suback received \n"); -} - -/* C:10 - Subscribe QoS1 success, suback received */ -TEST_C(SubscribeTests, subscribeQoS1Success) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:10 - Subscribe QoS1 success, suback received \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:10 - Subscribe QoS1 success, suback received \n"); -} - -/* C:11 - Subscribe, QoS0, delayed suback, success */ -TEST_C(SubscribeTests, subscribeQoS0WithDelayedSubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:11 - Subscribe, QoS0, delayed suback, success \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:11 - Subscribe, QoS0, delayed suback, success \n"); -} - -/* C:12 - Subscribe, QoS1, delayed suback, success */ -TEST_C(SubscribeTests, subscribeQoS1WithDelayedSubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:12 - Subscribe, QoS1, delayed suback, success \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - C:12 - Subscribe, QoS1, delayed suback, success \n"); -} - -/* C:13 - Subscribe QoS0 success, no puback sent on message */ -TEST_C(SubscribeTests, subscribeQoS0MsgReceivedAndNoPubackSent) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "Test msg - unit test"; - - IOT_DEBUG("-->Running Subscribe Tests - C:13 - Subscribe QoS0 success, no puback sent on message \n"); - - ResetTLSBuffer(); - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS == rc) { - testPubMsgParams.qos = QOS0; - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - } - } - CHECK_EQUAL_C_INT(0, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:13 - Subscribe QoS0 success, no puback sent on message \n"); -} - -/* C:14 - Subscribe QoS1 success, puback sent on message */ -TEST_C(SubscribeTests, subscribeQoS1MsgReceivedAndSendPuback) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "0xA5A5A3"; - - IOT_DEBUG("-->Running Subscribe Tests - C:14 - Subscribe QoS1 success, puback sent on message \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, NULL); - if(SUCCESS == rc) { - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - } - - IOT_DEBUG("-->Success - C:14 - Subscribe QoS1 success, puback sent on message \n"); -} - -/* C:15 - Subscribe, malformed response */ -TEST_C(SubscribeTests, subscribeMalformedResponse) {} - -/* C:16 - Subscribe, multiple topics, messages on each topic */ -TEST_C(SubscribeTests, SubscribeToMultipleTopicsSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "0xA5A5A3"; - - IOT_DEBUG("-->Running Subscribe Tests - C:16 - Subscribe, multiple topics, messages on each topic \n"); - - setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test1", 9, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString1); - - IOT_DEBUG("-->Success - C:16 - Subscribe, multiple topics, messages on each topic \n"); -} -/* C:17 - Subscribe, max topics, messages on each topic */ -TEST_C(SubscribeTests, SubscribeToMaxAllowedTopicsSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "topics sdk/Test1"; - char expectedCallbackString2[] = "topics sdk/Test2"; - char expectedCallbackString3[] = "topics sdk/Test3"; - char expectedCallbackString4[] = "topics sdk/Test4"; - char expectedCallbackString5[] = "topics sdk/Test5"; - - IOT_DEBUG("-->Running Subscribe Tests - C:17 - Subscribe, max topics, messages on each topic \n"); - - setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test3", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test3", 9, QOS1, iot_subscribe_callback_handler3, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test4", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test4", 9, QOS1, iot_subscribe_callback_handler4, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test5", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test5", 9, QOS1, iot_subscribe_callback_handler5, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test1", 9, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test2", 9, QOS1, testPubMsgParams, expectedCallbackString2); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test3", 9, QOS1, testPubMsgParams, expectedCallbackString3); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test4", 9, QOS1, testPubMsgParams, expectedCallbackString4); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test5", 9, QOS1, testPubMsgParams, expectedCallbackString5); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString1); - CHECK_EQUAL_C_STRING(expectedCallbackString2, CallbackMsgString2); - CHECK_EQUAL_C_STRING(expectedCallbackString3, CallbackMsgString3); - CHECK_EQUAL_C_STRING(expectedCallbackString4, CallbackMsgString4); - CHECK_EQUAL_C_STRING(expectedCallbackString5, CallbackMsgString5); - - IOT_DEBUG("-->Success - C:17 - Subscribe, max topics, messages on each topic \n"); -} -/* C:18 - Subscribe, max topics, another subscribe */ -TEST_C(SubscribeTests, SubscribeToMaxPlusOneAllowedTopicsFailure) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Subscribe Tests - C:18 - Subscribe, max topics, another subscribe \n"); - - setTLSRxBufferForSuback("sdk/Test1", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test1", 9, QOS1, iot_subscribe_callback_handler1, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test2", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test2", 9, QOS1, iot_subscribe_callback_handler2, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test3", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test3", 9, QOS1, iot_subscribe_callback_handler3, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test4", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test4", 9, QOS1, iot_subscribe_callback_handler4, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test5", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test5", 9, QOS1, iot_subscribe_callback_handler5, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - setTLSRxBufferForSuback("sdk/Test6", 9, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test6", 9, QOS1, iot_subscribe_callback_handler6, NULL); - CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc); - - IOT_DEBUG("-->Success - C:18 - Subscribe, max topics, another subscribe \n"); -} - -/* C:19 - Subscribe, '#' not last character in topic name, Failure */ -TEST_C(SubscribeTests, subscribeTopicWithHashkeyAllSubTopicSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: sub/sub, Hashkey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:19 - Subscribe, '#' not last character in topic name, Failure \n"); - - // Set up the subscribed topic, including '#' - setTLSRxBufferForSuback("sdk/Test/#", strlen("sdk/Test/#"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/#", strlen("sdk/Test/#"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // Now provide a published message from a sub topic - IOT_DEBUG("[Matching '#'] Checking first sub topic message, with '#' be the last..\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/sub/sub", strlen("sdk/Test/sub/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - // Re-initialize Rx Tx Buffer - ResetTLSBuffer(); - - // Now provide another message from a different sub topic - IOT_DEBUG("[Matching '#'] Checking second sub topic message, with '#' be the last...\n"); - snprintf(expectedCallbackString, 100, "New message: sub2, Hashkey"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/sub2", strlen("sdk/Test/sub2"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:19 - Subscribe, '#' not last character in topic name, Failure \n"); -} -/* C:20 - Subscribe with '#', subscribed to all subtopics */ -TEST_C(SubscribeTests, subscribeTopicHashkeyMustBeTheLastFail) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: foo1/sub, Hashkey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:20 - Subscribe with '#', subscribed to all subtopics \n"); - - // Set up the subscribed topic, with '#' in the middle - // Topic directory not permitted, should fail - setTLSRxBufferForSuback("sdk/#/sub", strlen("sdk/#/sub"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/#/sub", strlen("sdk/#/sub"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - // Now provide a published message from a sub directoy with this sub topic - IOT_DEBUG("[Matching '#'] Checking sub topic message, with '#' in the middle...\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo1/sub", strlen("sdk/Test/foo1/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING("NOT_VISITED", CallbackMsgString); - - IOT_DEBUG("-->Success - C:20 - Subscribe with '#', subscribed to all subtopics \n"); -} -/* C:21 - Subscribe with '+' as wildcard success */ -TEST_C(SubscribeTests, subscribeTopicWithPluskeySuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: 1/sub, Pluskey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:21 - Subscribe with '+' as wildcard success \n"); - - // Set up the subscribed topic, including '+' - setTLSRxBufferForSuback("sdk/Test/+/sub", strlen("sdk/Test/+/sub"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/+/sub", strlen("sdk/Test/+/sub"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // Now provide a published message from a sub topic - IOT_DEBUG("[Matching '+'] Checking first sub topic message, with '+' in the middle...\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/1/sub", strlen("sdk/Test/1/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - // Re-initialize Rx Tx Buffer - ResetTLSBuffer(); - - // Now provide another message from a different sub topic - IOT_DEBUG("[Matching '+'] Checking second sub topic message, with '+' in the middle...\n"); - snprintf(expectedCallbackString, 100, "New message: 2/sub, Pluskey"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/2/sub", strlen("sdk/Test/2/sub"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:21 - Subscribe with '+' as wildcard success \n"); -} -/* C:22 - Subscribe with '+' as last character in topic name, Success */ -TEST_C(SubscribeTests, subscribeTopicPluskeyComesLastSuccess) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100] = "New message: foo1, Pluskey"; - - IOT_DEBUG("-->Running Subscribe Tests - C:22 - Subscribe with '+' as last character in topic name, Success \n"); - - // Set up the subscribed topic, with '+' comes the last - setTLSRxBufferForSuback("sdk/Test/+", strlen("sdk/Test/+"), QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "sdk/Test/+", strlen("sdk/Test/+"), QOS1, - iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // Now provide a published message from a single layer of sub directroy - IOT_DEBUG("[Matching '+'] Checking first sub topic message, with '+' be the last...\n"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo1", strlen("sdk/Test/foo1"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - // Re-initialize Rx Tx Buffer - ResetTLSBuffer(); - - // Now provide a published message from another single layer of sub directroy - IOT_DEBUG("[Matching '+'] Checking second sub topic message, with '+' be the last...\n"); - snprintf(expectedCallbackString, 100, "New message: foo2, Pluskey"); - setTLSRxBufferWithMsgOnSubscribedTopic("sdk/Test/foo2", strlen("sdk/Test/foo2"), QOS1, testPubMsgParams, - expectedCallbackString); - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - - IOT_DEBUG("-->Success - C:22 - Subscribe with '+' as last character in topic name, Success \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe.cpp deleted file mode 100644 index bedea1f38..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_unsubscribe.cpp - * @brief IoT Client Unit Testing - Unsubscribe API Tests - */ - -#include -#include - -TEST_GROUP_C(UnsubscribeTests){ - TEST_GROUP_C_SETUP_WRAPPER(UnsubscribeTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(UnsubscribeTests) -}; - -/* D:1 - Unsubscribe with Null/empty client instance */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNullClient) -/* D:2 - Unsubscribe with Null/empty topic name */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNullTopic) -/* D:3 - Unsubscribe, Not subscribed to topic */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, UnsubscribeNotSubscribed) - -/* D:4 - Unsubscribe, QoS0, No response, timeout */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0FailureOnNoUnsuback) -/* D:5 - Unsubscribe, QoS1, No response, timeout */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1FailureOnNoUnsuback) - -/* D:6 - Unsubscribe, QoS0, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0WithUnsubackSuccess) -/* D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS0WithDelayedUnsubackSuccess) -/* D:8 - Unsubscribe, QoS1, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1WithUnsubackSuccess) -/* D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, unsubscribeQoS1WithDelayedUnsubackSuccess) - -/* D:10 - Unsubscribe, success, message on topic ignored */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, MsgAfterUnsubscribe) -/* D:11 - Unsubscribe after max topics reached */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, MaxTopicsSubscription) -/* D:12 - Repeated Subscribe and Unsubscribe */ -TEST_GROUP_C_WRAPPER(UnsubscribeTests, RepeatedSubUnSub) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe_helper.c deleted file mode 100644 index a4d245378..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_unsubscribe_helper.c +++ /dev/null @@ -1,343 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_unsubscribe_helper.c - * @brief IoT Client Unit Testing - Unsubscribe API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static IoT_Publish_Message_Params testPubMsgParams; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static AWS_IoT_Client iotClient; -static char CallbackMsgString[100]; -char cPayload[100]; - -static void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - if(NULL == pClient || NULL == topicName || 0 == topicNameLen) { - return; - } - - IOT_UNUSED(pData); - - char *tmp = params->payload; - unsigned int i; - - for(i = 0; i < (params->payloadLen); i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -TEST_GROUP_C_SETUP(UnsubscribeTests) { - IoT_Error_t rc = SUCCESS; - ResetTLSBuffer(); - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, NULL); - initParams.mqttCommandTimeout_ms = 2000; - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ConnectMQTTParamsSetup(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID)); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - IOT_DEBUG("MQTT Status State : %d, RC : %d\n\n", aws_iot_mqtt_get_client_state(&iotClient), rc); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(UnsubscribeTests) { } - -/* D:1 - Unsubscribe with Null/empty client instance */ -TEST_C(UnsubscribeTests, UnsubscribeNullClient) { - IoT_Error_t rc = aws_iot_mqtt_unsubscribe(NULL, "sdkTest/Sub", 11); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* D:2 - Unsubscribe with Null/empty topic name */ -TEST_C(UnsubscribeTests, UnsubscribeNullTopic) { - IoT_Error_t rc = aws_iot_mqtt_unsubscribe(&iotClient, NULL, 11); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* D:3 - Unsubscribe, Not subscribed to topic */ -TEST_C(UnsubscribeTests, UnsubscribeNotSubscribed) { - IoT_Error_t rc = aws_iot_mqtt_unsubscribe(&iotClient, "sdkTest/Sub", 11); - CHECK_EQUAL_C_INT(FAILURE, rc); -} - -/* D:4 - Unsubscribe, QoS0, No response, timeout */ -TEST_C(UnsubscribeTests, unsubscribeQoS0FailureOnNoUnsuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:4 - Unsubscribe, QoS0, No response, timeout \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - } - - IOT_DEBUG("-->Success - D:4 - Unsubscribe, QoS0, No response, timeout \n"); -} - -/* D:5 - Unsubscribe, QoS1, No response, timeout */ -TEST_C(UnsubscribeTests, unsubscribeQoS1FailureOnNoUnsuback) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:5 - Unsubscribe, QoS1, No response, timeout \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(MQTT_REQUEST_TIMEOUT_ERROR, rc); - } - - IOT_DEBUG("-->Success - D:5 - Unsubscribe, QoS1, No response, timeout \n"); -} - -/* D:6 - Unsubscribe, QoS0, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS0WithUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:6 - Unsubscribe, QoS0, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:6 - Unsubscribe, QoS0, success \n"); -} - -/* D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS0WithDelayedUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:7 - Unsubscribe, QoS0, half command timeout delayed unsuback, success \n"); -} - -/* D:8 - Unsubscribe, QoS1, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS1WithUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:8 - Unsubscribe, QoS1, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:8 - Unsubscribe, QoS1, success \n"); -} - -/* D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success */ -TEST_C(UnsubscribeTests, unsubscribeQoS1WithDelayedUnsubackSuccess) { - IoT_Error_t rc = SUCCESS; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success \n"); - - // First, subscribe to a topic - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, iot_subscribe_callback_handler, - NULL); - if(SUCCESS == rc) { - // Then, unsubscribe - setTLSRxBufferForUnsuback(); - setTLSRxBufferDelay(0, (int) iotClient.clientData.commandTimeoutMs/2); - rc = aws_iot_mqtt_unsubscribe(&iotClient, subTopic, (uint16_t) strlen(subTopic)); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:9 - Unsubscribe, QoS1, half command timeout delayed unsuback, success \n"); -} - -/* D:10 - Unsubscribe, success, message on topic ignored - * 1. Subscribe to topic 1 - * 2. Send message and receive it - * 3. Unsubscribe to topic 1 - * 4. Should not receive message - */ -TEST_C(UnsubscribeTests, MsgAfterUnsubscribe) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[100]; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:10 - Unsubscribe, success, message on topic ignored \n"); - - // 1. - setTLSRxBufferForSuback("topic1", 6, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, "topic1", 6, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - // 2. - snprintf(expectedCallbackString, 100, "Message for topic1"); - setTLSRxBufferWithMsgOnSubscribedTopic("topic1", 6, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - //3. - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, "topic1", 6); - CHECK_EQUAL_C_INT(SUCCESS, rc); - //reset the string - snprintf(CallbackMsgString, 100, " "); - - // 4. - // Have a new message published to that topic coming in - snprintf(expectedCallbackString, 100, "Message after unsubscribe"); - setTLSRxBufferWithMsgOnSubscribedTopic("topic1", 6, QOS0, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - // No new msg was received - CHECK_EQUAL_C_STRING(" ", CallbackMsgString); - - IOT_DEBUG("-->Success - D:10 - Unsubscribe, success, message on topic ignored \n"); -} - -/* D:11 - Unsubscribe after max topics reached - * 1. Subscribe to max topics + 1 fail for last subscription - * 2. Unsubscribe from one topic - * 3. Subscribe again and should have no error - * 4. Receive msg test - last subscribed topic - */ -TEST_C(UnsubscribeTests, MaxTopicsSubscription) { - IoT_Error_t rc = SUCCESS; - int i = 0; - char topics[AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS + 1][10]; - char expectedCallbackString[] = "Message after subscribe - topic[i]"; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:11 - Unsubscribe after max topics reached \n"); - - // 1. - for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; i++) { - snprintf(topics[i], 10, "topic-%d", i); - setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - snprintf(topics[i], 10, "topic-%d", i); - setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR, rc); - - // 2. - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, topics[i - 1], (uint16_t) strlen(topics[i - 1])); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //3. - setTLSRxBufferForSuback(topics[i], strlen(topics[i]), QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i]), QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - //4. - setTLSRxBufferWithMsgOnSubscribedTopic(topics[i], strlen(topics[i]), QOS1, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - IOT_DEBUG("-->Success - D:11 - Unsubscribe after max topics reached \n"); -} - -/* D:12 - Repeated Subscribe and Unsubscribe - * 1. subscribe and unsubscribe for more than the max subscribed topic - * 2. ensure every time the subscribed topic msg is received - */ -TEST_C(UnsubscribeTests, RepeatedSubUnSub) { - IoT_Error_t rc = SUCCESS; - int i = 0; - char expectedCallbackString[100]; - char topics[3 * AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS][10]; - - IOT_DEBUG("-->Running Unsubscribe Tests - D:12 - Repeated Subscribe and Unsubscribe \n"); - - - for(i = 0; i < 3 * AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; i++) { - //1. - snprintf(topics[i], 10, "topic-%d", i); - setTLSRxBufferForSuback(topics[i], 10, QOS0, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, topics[i], 10, QOS0, iot_subscribe_callback_handler, NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - snprintf(expectedCallbackString, 10, "message##%d", i); - testPubMsgParams.payload = (void *) expectedCallbackString; - testPubMsgParams.payloadLen = strlen(expectedCallbackString); - setTLSRxBufferWithMsgOnSubscribedTopic(topics[i], strlen(topics[i]), QOS1, testPubMsgParams, - expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - //2. - setTLSRxBufferForUnsuback(); - rc = aws_iot_mqtt_unsubscribe(&iotClient, topics[i], (uint16_t) strlen(topics[i])); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - IOT_DEBUG("-->Success - D:12 - Repeated Subscribe and Unsubscribe \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield.cpp b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield.cpp deleted file mode 100644 index afca69c5c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_yield.cpp - * @brief IoT Client Unit Testing - Yield API Tests - */ - -#include -#include - -TEST_GROUP_C(YieldTests){ - TEST_GROUP_C_SETUP_WRAPPER(YieldTests) - TEST_GROUP_C_TEARDOWN_WRAPPER(YieldTests) -}; - -/* G:1 - Yield with Null/empty Client Instance */ -TEST_GROUP_C_WRAPPER(YieldTests, NullClientYield) -/* G:2 - Yield with zero yield timeout */ -TEST_GROUP_C_WRAPPER(YieldTests, ZeroTimeoutYield) -/* G:3 - Yield, network disconnected, never connected */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldNetworkDisconnectedNeverConnected) -/* G:4 - Yield, network disconnected, disconnected manually */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldNetworkDisconnectedDisconnectedManually) -/* G:5 - Yield, network connected, yield called while in subscribe application callback */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldInSubscribeCallback) -/* G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectNoAutoReconnect) - -/* G:7 - Yield, network connected, no incoming messages */ -TEST_GROUP_C_WRAPPER(YieldTests, YieldSuccessNoMessages) -/* G:8 - Yield, network connected, ping request/response */ -TEST_GROUP_C_WRAPPER(YieldTests, PingRequestPingResponse) - -/* G:9 - Yield, disconnected, Auto-reconnect timed-out */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectAutoReconnectTimeout) -/* G:10 - Yield, disconnected, Auto-reconnect successful */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectAutoReconnectSuccess) -/* G:11 - Yield, disconnected, Manual reconnect */ -TEST_GROUP_C_WRAPPER(YieldTests, disconnectManualAutoReconnect) -/* G:12 - Yield, resubscribe to all topics on reconnect */ -TEST_GROUP_C_WRAPPER(YieldTests, resubscribeSuccessfulReconnect) - -/* G:13 - Delayed Ping response. */ -TEST_GROUP_C_WRAPPER(YieldTests, delayedPingResponse) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield_helper.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield_helper.c deleted file mode 100644 index bc4aa0523..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/src/aws_iot_tests_unit_yield_helper.c +++ /dev/null @@ -1,493 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_yield_helper.c - * @brief IoT Client Unit Testing - Yield API Tests Helper - */ - -#include -#include -#include - -#include "aws_iot_tests_unit_helper_functions.h" -#include "aws_iot_tests_unit_mock_tls_params.h" -#include "aws_iot_log.h" - -static IoT_Client_Init_Params initParams; -static IoT_Client_Connect_Params connectParams; -static AWS_IoT_Client iotClient; -static IoT_Publish_Message_Params testPubMsgParams; - -static ConnectBufferProofread prfrdParams; -static char CallbackMsgString[100]; -static char subTopic[10] = "sdk/Test"; -static uint16_t subTopicLen = 8; - -static bool dcHandlerInvoked = false; - -static void iot_tests_unit_acr_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char *tmp = params->payload; - unsigned int i; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - for(i = 0; i < params->payloadLen; i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -static void iot_tests_unit_yield_test_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, - uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - char *tmp = params->payload; - unsigned int i; - IoT_Error_t rc = SUCCESS; - - IOT_UNUSED(pClient); - IOT_UNUSED(topicName); - IOT_UNUSED(topicNameLen); - IOT_UNUSED(pData); - - rc = aws_iot_mqtt_yield(pClient, 1000); - CHECK_EQUAL_C_INT(MQTT_CLIENT_NOT_IDLE_ERROR, rc); - - for(i = 0; i < params->payloadLen; i++) { - CallbackMsgString[i] = tmp[i]; - } -} - -void iot_tests_unit_disconnect_handler(AWS_IoT_Client *pClient, void *disconParam) { - IOT_UNUSED(pClient); - IOT_UNUSED(disconParam); - dcHandlerInvoked = true; -} - - -TEST_GROUP_C_SETUP(YieldTests) { - IoT_Error_t rc = SUCCESS; - dcHandlerInvoked = false; - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, iot_tests_unit_disconnect_handler); - rc = aws_iot_mqtt_init(&iotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - - ConnectMQTTParamsSetup_Detailed(&connectParams, AWS_IOT_MQTT_CLIENT_ID, (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID), - QOS1, false, true, "willTopicName", (uint16_t) strlen("willTopicName"), "willMsg", - (uint16_t) strlen("willMsg"), NULL, 0, NULL, 0); - connectParams.keepAliveIntervalInSec = 5; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_connect(&iotClient, &connectParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - CHECK_EQUAL_C_INT(SUCCESS, rc); - ResetTLSBuffer(); -} - -TEST_GROUP_C_TEARDOWN(YieldTests) { - /* Clean up. Not checking return code here because this is common to all tests. - * A test might have already caused a disconnect by this point. - */ - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - IOT_UNUSED(rc); -} - -/* G:1 - Yield with Null/empty Client Instance */ -TEST_C(YieldTests, NullClientYield) { - IoT_Error_t rc = aws_iot_mqtt_yield(NULL, 1000); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} - -/* G:2 - Yield with zero yield timeout */ - -TEST_C(YieldTests, ZeroTimeoutYield) { - IoT_Error_t rc = aws_iot_mqtt_yield(&iotClient, 0); - CHECK_EQUAL_C_INT(NULL_VALUE_ERROR, rc); -} -/* G:3 - Yield, network disconnected, never connected */ - -TEST_C(YieldTests, YieldNetworkDisconnectedNeverConnected) { - AWS_IoT_Client tempIotClient; - IoT_Error_t rc; - - InitMQTTParamsSetup(&initParams, AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, false, iot_tests_unit_disconnect_handler); - rc = aws_iot_mqtt_init(&tempIotClient, &initParams); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - rc = aws_iot_mqtt_yield(&tempIotClient, 1000); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); -} - -/* G:4 - Yield, network disconnected, disconnected manually */ -TEST_C(YieldTests, YieldNetworkDisconnectedDisconnectedManually) { - IoT_Error_t rc = aws_iot_mqtt_disconnect(&iotClient); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - CHECK_EQUAL_C_INT(NETWORK_MANUALLY_DISCONNECTED, rc); -} - -/* G:5 - Yield, network connected, yield called while in subscribe application callback */ -TEST_C(YieldTests, YieldInSubscribeCallback) { - IoT_Error_t rc = SUCCESS; - char expectedCallbackString[] = "0xA5A5A3"; - - IOT_DEBUG("-->Running Yield Tests - G:5 - Yield, network connected, yield called while in subscribe application callback \n"); - - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS1, - iot_tests_unit_yield_test_subscribe_callback_handler, NULL); - if(SUCCESS == rc) { - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - } - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePuback()); - } - - IOT_DEBUG("-->Success - G:5 - Yield, network connected, yield called while in subscribe application callback \n"); -} - -/* G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled */ -TEST_C(YieldTests, disconnectNoAutoReconnect) { - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("-->Running Yield Tests - G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient)); - - /* Disable Autoreconnect, then let ping request time out and call yield */ - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - sleep((uint16_t)(iotClient.clientData.keepAliveInterval)); - - ResetTLSBuffer(); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - CHECK_EQUAL_C_INT(0, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:6 - Yield, network disconnected, ping timeout, auto-reconnect disabled \n"); -} - -/* G:7 - Yield, network connected, no incoming messages */ -TEST_C(YieldTests, YieldSuccessNoMessages) { - IoT_Error_t rc; - int i; - - IOT_DEBUG("-->Running Yield Tests - G:7 - Yield, network connected, no incoming messages \n"); - - for(i = 0; i < 100; i++) { - CallbackMsgString[i] = 'x'; - } - - rc = aws_iot_mqtt_yield(&iotClient, 1000); - if(SUCCESS == rc) { - /* Check no messages were received */ - for(i = 0; i < 100; i++) { - if('x' != CallbackMsgString[i]) { - rc = FAILURE; - } - } - } - - CHECK_EQUAL_C_INT(SUCCESS, rc); - - IOT_DEBUG("-->Success - G:7 - Yield, network connected, no incoming messages \n"); -} - -/* G:8 - Yield, network connected, ping request/response */ -TEST_C(YieldTests, PingRequestPingResponse) { - IoT_Error_t rc = SUCCESS; - int i = 0; - int j = 0; - int attempt = 3; - - IOT_DEBUG("-->Running Yield Tests - G:8 - Yield, network connected, ping request/response \n"); - IOT_DEBUG("Current Keep Alive Interval is set to %d sec.\n", iotClient.clientData.keepAliveInterval); - - for(i = 0; i < attempt; i++) { - IOT_DEBUG("[Round_%d/Total_%d] Waiting for %d sec...\n", i + 1, attempt, iotClient.clientData.keepAliveInterval); - /* Set TLS buffer for ping response */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - - for(j = 0; j <= iotClient.clientData.keepAliveInterval; j++) { - sleep(1); - IOT_DEBUG("[Waited %d secs]", j + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - } - - /* Check whether ping was processed correctly and new Ping request was generated */ - CHECK_EQUAL_C_INT(1, isLastTLSTxMessagePingreq()); - } - - IOT_DEBUG("-->Success - G:8 - Yield, network connected, ping request/response \n"); -} - -/* G:9 - Yield, disconnected, Auto-reconnect timed-out */ -TEST_C(YieldTests, disconnectAutoReconnectTimeout) { - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("-->Running Yield Tests - G:9 - Yield, disconnected, Auto-reconnect timed-out \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient)); - - ResetTLSBuffer(); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - CHECK_EQUAL_C_INT(0, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:9 - Yield, disconnected, Auto-reconnect timed-out \n"); -} - -/* G:10 - Yield, disconnected, Auto-reconnect successful */ -TEST_C(YieldTests, disconnectAutoReconnectSuccess) { - IoT_Error_t rc = FAILURE; - unsigned char *currPayload = NULL; - - IOT_DEBUG("-->Running Yield Tests - G:10 - Yield, disconnected, Auto-reconnect successful \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, aws_iot_is_autoreconnect_enabled(&iotClient)); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - - sleep(2); /* Default min reconnect delay is 1 sec */ - printf("\nWakeup"); - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer); - CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams)); - CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload)); - CHECK_EQUAL_C_INT(true, aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:10 - Yield, disconnected, Auto-reconnect successful \n"); -} - -/* G:11 - Yield, disconnected, Manual reconnect */ -TEST_C(YieldTests, disconnectManualAutoReconnect) { - IoT_Error_t rc = FAILURE; - unsigned char *currPayload = NULL; - - IOT_DEBUG("-->Running Yield Tests - G:11 - Yield, disconnected, Manual reconnect \n"); - - CHECK_C(aws_iot_mqtt_is_client_connected(&iotClient)); - - /* Disable Autoreconnect, then let ping request time out and call yield */ - aws_iot_mqtt_autoreconnect_set_status(&iotClient, false); - CHECK_C(!aws_iot_is_autoreconnect_enabled(&iotClient)); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_DISCONNECTED_ERROR, rc); - CHECK_EQUAL_C_INT(1, isLastTLSTxMessageDisconnect()); - CHECK_C(!aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - dcHandlerInvoked = false; - setTLSRxBufferForConnack(&connectParams, 0, 0); - rc = aws_iot_mqtt_attempt_reconnect(&iotClient); - CHECK_EQUAL_C_INT(NETWORK_RECONNECTED, rc); - - currPayload = connectTxBufferHeaderParser(&prfrdParams, TxBuffer.pBuffer); - CHECK_C(true == isConnectTxBufFlagCorrect(&connectParams, &prfrdParams)); - CHECK_C(true == isConnectTxBufPayloadCorrect(&connectParams, currPayload)); - CHECK_C(aws_iot_mqtt_is_client_connected(&iotClient)); - CHECK_EQUAL_C_INT(false, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:11 - Yield, disconnected, Manual reconnect \n"); -} - -/* G:12 - Yield, resubscribe to all topics on reconnect */ -TEST_C(YieldTests, resubscribeSuccessfulReconnect) { - IoT_Error_t rc = FAILURE; - char cPayload[100]; - bool connected = false; - bool autoReconnectEnabled = false; - char expectedCallbackString[100]; - - IOT_DEBUG("-->Running Yield Tests - G:12 - Yield, resubscribe to all topics on reconnect \n"); - - rc = aws_iot_mqtt_autoreconnect_set_status(&iotClient, true); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - snprintf(CallbackMsgString, 100, "NOT_VISITED"); - - testPubMsgParams.qos = QOS1; - testPubMsgParams.isRetained = 0; - snprintf(cPayload, 100, "%s : %d ", "hello from SDK", 0); - testPubMsgParams.payload = (void *) cPayload; - testPubMsgParams.payloadLen = strlen(cPayload); - - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(1, connected); - - ResetTLSBuffer(); - - /* Subscribe to a topic */ - setTLSRxBufferForSuback(subTopic, subTopicLen, QOS1, testPubMsgParams); - rc = aws_iot_mqtt_subscribe(&iotClient, subTopic, subTopicLen, QOS0, iot_tests_unit_acr_subscribe_callback_handler, - NULL); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - ResetTLSBuffer(); - - /* Check subscribe */ - snprintf(expectedCallbackString, 100, "Message for %s", subTopic); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - - ResetTLSBuffer(); - - autoReconnectEnabled = aws_iot_is_autoreconnect_enabled(&iotClient); - CHECK_EQUAL_C_INT(1, autoReconnectEnabled); - - /* Sleep for keep alive interval to allow the first ping to be sent out */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Let ping request time out and call yield */ - sleep(iotClient.clientData.keepAliveInterval + 1); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(NETWORK_ATTEMPTING_RECONNECT, rc); - - sleep(2); /* Default min reconnect delay is 1 sec */ - - ResetTLSBuffer(); - setTLSRxBufferForConnackAndSuback(&connectParams, 0, subTopic, subTopicLen, QOS1); - - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - /* Test if reconnect worked */ - connected = aws_iot_mqtt_is_client_connected(&iotClient); - CHECK_EQUAL_C_INT(true, connected); - - ResetTLSBuffer(); - - /* Check subscribe */ - snprintf(expectedCallbackString, 100, "Message for %s after resub", subTopic); - setTLSRxBufferWithMsgOnSubscribedTopic(subTopic, subTopicLen, QOS1, testPubMsgParams, expectedCallbackString); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_STRING(expectedCallbackString, CallbackMsgString); - CHECK_EQUAL_C_INT(true, dcHandlerInvoked); - - IOT_DEBUG("-->Success - G:12 - Yield, resubscribe to all topics on reconnect \n"); -} - -/* G:13 - Delayed Ping response. */ -TEST_C(YieldTests, delayedPingResponse) -{ - IoT_Error_t rc = FAILURE; - - IOT_DEBUG("-->Running Yield Tests - G:13 - Delayed Ping response. \n"); - - ResetTLSBuffer(); - - /* Sleep for keep alive interval to allow the first ping to be sent out. */ - sleep(iotClient.clientData.keepAliveInterval); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - /* Sleep for half of the keep alive interval to simulate a delayed ping - * response. */ - sleep(iotClient.clientData.keepAliveInterval / 2); - - /* Receive the delayed ping response. */ - ResetTLSBuffer(); - setTLSRxBufferForPingresp(); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - - /* Sleep for half of the keep alive interval - at this time a ping request - * must be sent out because a full keep alive interval has passed since we - * last sent a ping request. This ensures that the timer which tracks when - * to send a ping request does not incorrectly get reset upon receipt of a - * ping response. +1 is done to ensure that we don't hit boundry condition - * where timer does not expire because the time elasped is exactly equal to - * the keep alive interval (as opposed to more than that). */ - sleep(iotClient.clientData.keepAliveInterval / 2 + 1); - ResetTLSBuffer(); - rc = aws_iot_mqtt_yield(&iotClient, 100); - CHECK_EQUAL_C_INT(SUCCESS, rc); - CHECK_EQUAL_C_INT(true, isLastTLSTxMessagePingreq()); - - IOT_DEBUG("-->Success - G:13 - Delayed Ping response. \n"); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls.c deleted file mode 100644 index 720202a5f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls.c +++ /dev/null @@ -1,223 +0,0 @@ -#include -#include -#include - -#include "network_interface.h" -#include "aws_iot_tests_unit_mock_tls_params.h" - - -void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - pNetwork->tlsConnectParams.DestinationPort = destinationPort; - pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL; - pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation; - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation; - pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation; - pNetwork->tlsConnectParams.timeout_ms = timeout_ms; - pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag; -} - -IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation, - pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag); - - pNetwork->connect = iot_tls_connect; - pNetwork->read = iot_tls_read; - pNetwork->write = iot_tls_write; - pNetwork->disconnect = iot_tls_disconnect; - pNetwork->isConnected = iot_tls_is_connected; - pNetwork->destroy = iot_tls_destroy; - - return SUCCESS; -} - -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { - IOT_UNUSED(pNetwork); - - if(NULL != params) { - _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, - params->pDevicePrivateKeyLocation, params->pDestinationURL, params->DestinationPort, - params->timeout_ms, params->ServerVerificationFlag); - } - - if(NULL != invalidEndpointFilter && 0 == strcmp(invalidEndpointFilter, pNetwork->tlsConnectParams.pDestinationURL)) { - return NETWORK_ERR_NET_UNKNOWN_HOST; - } - - if(invalidPortFilter == pNetwork->tlsConnectParams.DestinationPort) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - - if(NULL != invalidRootCAPathFilter && 0 == strcmp(invalidRootCAPathFilter, pNetwork->tlsConnectParams.pRootCALocation)) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - - if(NULL != invalidCertPathFilter && 0 == strcmp(invalidCertPathFilter, pNetwork->tlsConnectParams.pDeviceCertLocation)) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - - if(NULL != invalidPrivKeyPathFilter && 0 == strcmp(invalidPrivKeyPathFilter, pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)) { - return NETWORK_ERR_NET_CONNECT_FAILED; - } - return SUCCESS; -} - -IoT_Error_t iot_tls_is_connected(Network *pNetwork) { - IOT_UNUSED(pNetwork); - - /* Use this to add implementation which can check for physical layer disconnect */ - return NETWORK_PHYSICAL_LAYER_CONNECTED; -} - -static size_t iot_tls_mqtt_read_variable_length_int(const unsigned char *buffer, size_t startPos) { - size_t result = 0; - size_t pos = startPos; - size_t multiplier = 1; - do { - result = (buffer[pos] & 0x7f) * multiplier; - multiplier *= 0x80; - pos++; - } while ((buffer[pos - 1] & 0x80) && pos - startPos < 4); - - return result; -} - -static size_t iot_tls_mqtt_get_end_of_variable_length_int(const unsigned char *buffer, size_t startPos) { - size_t pos = startPos; - while ((buffer[pos] & 0x80) && pos - startPos < 3) pos++; - pos++; - - return pos; -} - -static uint16_t iot_tls_mqtt_get_fixed_uint16_from_message(const unsigned char *msgBuffer, size_t startPos) { - uint8_t firstByte = (uint8_t)(msgBuffer[startPos]); - uint8_t secondByte = (uint8_t)(msgBuffer[startPos + 1]); - return (uint16_t) (secondByte + (256 * firstByte)); -} - -static uint16_t iot_tls_mqtt_copy_string_from_message(char *dest, const unsigned char *msgBuffer, size_t startPos) { - uint16_t length = iot_tls_mqtt_get_fixed_uint16_from_message(msgBuffer, startPos); - - snprintf(dest, length + 1u, "%s", &(msgBuffer[startPos + 2])); // Added one for null character - return length; -} - -IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) { - size_t i = 0; - uint8_t firstPacketByte; - size_t mqttPacketLength; - size_t variableHeaderStart; - IoT_Error_t status = SUCCESS; - IOT_UNUSED(pNetwork); - IOT_UNUSED(timer); - - if(TxBuffer.mockedError != SUCCESS ) { - status = TxBuffer.mockedError; - - /* Clear the error before returning. */ - TxBuffer.mockedError = SUCCESS; - - return status; - } - - for(i = 0; (i < len) && left_ms(timer) > 0; i++) { - TxBuffer.pBuffer[i] = pMsg[i]; - } - TxBuffer.len = len; - *written_len = len; - - mqttPacketLength = iot_tls_mqtt_read_variable_length_int(TxBuffer.pBuffer, 1); - variableHeaderStart = iot_tls_mqtt_get_end_of_variable_length_int(TxBuffer.pBuffer, 1); - - firstPacketByte = TxBuffer.pBuffer[0]; - /* Save last two subscribed topics */ - if((firstPacketByte == 0x82 ? true : false)) { - snprintf(SecondLastSubscribeMessage, lastSubscribeMsgLen + 1u, "%s", LastSubscribeMessage); - secondLastSubscribeMsgLen = lastSubscribeMsgLen; - - lastSubscribeMsgLen = iot_tls_mqtt_copy_string_from_message( - LastSubscribeMessage, TxBuffer.pBuffer, variableHeaderStart + 2); - } else if (firstPacketByte == 0xA2) { - lastUnsubscribeMsgLen = iot_tls_mqtt_copy_string_from_message( - LastUnsubscribeMessage, TxBuffer.pBuffer, variableHeaderStart + 2); - } else if ((firstPacketByte & 0x30) == 0x30) { - QoS qos = (QoS) (firstPacketByte & 0x6 >> 1); - - lastPublishMessageTopicLen = - iot_tls_mqtt_copy_string_from_message(LastPublishMessageTopic, TxBuffer.pBuffer, variableHeaderStart); - - size_t payloadStart = variableHeaderStart + 2 + lastPublishMessageTopicLen; - - if (qos > QOS0) { - payloadStart += 2; - } - - lastPublishMessagePayloadLen = mqttPacketLength - payloadStart + 2; /* + 2 as the first two bytes don't count towards the length */ - memcpy(LastPublishMessagePayload, TxBuffer.pBuffer + payloadStart, lastPublishMessagePayloadLen); - LastPublishMessagePayload[lastPublishMessagePayloadLen] = 0; - } - - return status; -} - -static unsigned char isTimerExpired(struct timeval target_time) { - unsigned char ret_val = 0; - struct timeval now, result; - - if(target_time.tv_sec != 0 || target_time.tv_usec != 0) { - gettimeofday(&now, NULL); - timersub(&(target_time), &now, &result); - if(result.tv_sec < 0 || (result.tv_sec == 0 && result.tv_usec <= 0)) { - ret_val = 1; - } - } else { - ret_val = 1; - } - return ret_val; -} - -IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *pTimer, size_t *read_len) { - IoT_Error_t status = SUCCESS; - - IOT_UNUSED(pNetwork); - IOT_UNUSED(pTimer); - - if(RxBuffer.mockedError != SUCCESS) { - status = RxBuffer.mockedError; - - /* Clear the error before returning. */ - RxBuffer.mockedError = SUCCESS; - - return status; - } - - if(RxIndex > TLSMaxBufferSize - 1) { - RxIndex = TLSMaxBufferSize - 1; - } - - if(RxBuffer.len <= RxIndex || !isTimerExpired(RxBuffer.expiry_time)) { - return NETWORK_SSL_NOTHING_TO_READ; - } - - if((false == RxBuffer.NoMsgFlag) && (RxIndex < RxBuffer.len)) { - memcpy(pMsg, &(RxBuffer.pBuffer[RxIndex]), len); - RxIndex += len; - *read_len = len; - } - - return status; -} - -IoT_Error_t iot_tls_disconnect(Network *pNetwork) { - IOT_UNUSED(pNetwork); - return SUCCESS; -} - -IoT_Error_t iot_tls_destroy(Network *pNetwork) { - IOT_UNUSED(pNetwork); - return SUCCESS; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.c b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.c deleted file mode 100644 index c816a7d2d..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.c +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_mock_tls_params.c - * @brief IoT Client Unit Testing Mock TLS Params - */ - -#include "aws_iot_tests_unit_mock_tls_params.h" - -unsigned char RxBuf[TLSMaxBufferSize]; -unsigned char TxBuf[TLSMaxBufferSize]; -char LastSubscribeMessage[TLSMaxBufferSize]; -size_t lastSubscribeMsgLen; -char SecondLastSubscribeMessage[TLSMaxBufferSize]; -size_t secondLastSubscribeMsgLen; - -char LastUnsubscribeMessage[TLSMaxBufferSize]; -size_t lastUnsubscribeMsgLen; - -char LastPublishMessageTopic[TLSMaxBufferSize]; -size_t lastPublishMessageTopicLen; -char LastPublishMessagePayload[TLSMaxBufferSize]; -size_t lastPublishMessagePayloadLen; - -TlsBuffer RxBuffer = {.pBuffer = RxBuf,.len = 512, .NoMsgFlag=1, .expiry_time = {0, 0}, .BufMaxSize = TLSMaxBufferSize, .mockedError = SUCCESS}; -TlsBuffer TxBuffer = {.pBuffer = TxBuf,.len = 512, .NoMsgFlag=1, .expiry_time = {0, 0}, .BufMaxSize = TLSMaxBufferSize, .mockedError = SUCCESS}; - -size_t RxIndex = 0; - -char *invalidEndpointFilter; -char *invalidRootCAPathFilter; -char *invalidCertPathFilter; -char *invalidPrivKeyPathFilter; -uint16_t invalidPortFilter; diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.h deleted file mode 100644 index 20262d5bd..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/aws_iot_tests_unit_mock_tls_params.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"). -* You may not use this file except in compliance with the License. -* A copy of the License is located at -* -* http://aws.amazon.com/apache2.0 -* -* or in the "license" file accompanying this file. This file 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. -*/ - -/** - * @file aws_iot_tests_unit_mock_tls_params.h - * @brief IoT Client Unit Testing Mock TLS Params - */ - -#ifndef UNITTESTS_MOCKS_TLS_PARAMS_H_ -#define UNITTESTS_MOCKS_TLS_PARAMS_H_ - -#include -#include -#include -#include -#include - -#define TLSMaxBufferSize 2560 -#define NO_MSG_LENGTH_MENTIONED -1 - -typedef struct { - unsigned char *pBuffer; - size_t len; - bool NoMsgFlag; - struct timeval expiry_time; - size_t BufMaxSize; - IoT_Error_t mockedError; -} TlsBuffer; - - -extern TlsBuffer RxBuffer; -extern TlsBuffer TxBuffer; - -extern size_t RxIndex; -extern unsigned char RxBuf[TLSMaxBufferSize]; -extern unsigned char TxBuf[TLSMaxBufferSize]; -extern char LastSubscribeMessage[TLSMaxBufferSize]; -extern size_t lastSubscribeMsgLen; -extern char SecondLastSubscribeMessage[TLSMaxBufferSize]; -extern size_t secondLastSubscribeMsgLen; - -extern char LastUnsubscribeMessage[TLSMaxBufferSize]; -extern size_t lastUnsubscribeMsgLen; - -extern char LastPublishMessageTopic[TLSMaxBufferSize]; -extern size_t lastPublishMessageTopicLen; -extern char LastPublishMessagePayload[TLSMaxBufferSize]; -extern size_t lastPublishMessagePayloadLen; - -extern char hostAddress[512]; -extern uint16_t port; -extern uint32_t handshakeTimeout_ms; - -extern char *invalidEndpointFilter; -extern char *invalidRootCAPathFilter; -extern char *invalidCertPathFilter; -extern char *invalidPrivKeyPathFilter; -extern uint16_t invalidPortFilter; - -#endif /* UNITTESTS_MOCKS_TLS_PARAMS_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/network_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/network_platform.h deleted file mode 100644 index 1bbec842f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/aws-iot-device-sdk-embedded-C/tests/unit/tls_mock/network_platform.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by chaurah on 3/22/16. -// - -#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct _TLSDataParams { - uint32_t flags; -}TLSDataParams; - -#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/component.mk b/examples/espidf-aws-iot/components/esp-aws-iot/component.mk deleted file mode 100644 index b9a705a27..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/component.mk +++ /dev/null @@ -1,10 +0,0 @@ -# -# Component Makefile -# - -COMPONENT_ADD_INCLUDEDIRS := port/include aws-iot-device-sdk-embedded-C/include - -COMPONENT_SRCDIRS := aws-iot-device-sdk-embedded-C/src port - -# Check the submodule is initialised -COMPONENT_SUBMODULES := aws-iot-device-sdk-embedded-C diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/examples/README.md deleted file mode 100644 index 4a898d1df..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# Amazon Web Services IoT Examples - -These examples are adaptations of some of the [AWS IoT C SDK](https://github.com/aws/aws-iot-device-sdk-embedded-C) examples. - -The provisioning/configuration steps for these examples are the same, and are given in this README. - -This README also contains some troubleshooting information for common problems found when connecting to AWS IoT. - -# Provisioning/Configuration - -There are some additional steps that need to be run before you can build this example. - -The [Getting Started section of the AWS IoT Developer Guide](http://docs.aws.amazon.com/iot/latest/developerguide/iot-gs.html) lays out the steps to get started with AWS IoT. - -To build and use this example, follow all the AWS IoT Getting Started steps from the beginning ("Sign in to the AWS Iot Console") up until "Configuring Your Device". For configuring the device, these are the steps: - -# Authentication (Based on X.509 certificates) - -### Device Authentication - -AWS IoT can use AWS IoT-generated certificates or certificates signed by a CA certificate for device authentication. To use a certificate that is not created by AWS IoT, you must register a CA certificate. All device certificates must be signed by the CA certificate you register. Please refer to guide at https://docs.aws.amazon.com/iot/latest/developerguide/device-certs-your-own.html for step-by-step instructions to register custom X.509 certificates. - -### Server Authentication - -Server certificates allow devices to verify that they're communicating with AWS IoT and not another server impersonating AWS IoT. By default [Amazon Root CA 1](https://www.amazontrust.com/repository/AmazonRootCA1.pem) (signed by Amazon Trust Services Endpoints CA) is embedded in applications, for more information please refer to https://docs.aws.amazon.com/iot/latest/developerguide/managing-device-certs.html#server-authentication - -## Configuring Your Device - -### Installing Private Key & Certificate - -As part of creating a device certificate, you downloaded a Private Key (`xxx-private.pem.key`) and a Certificate file (`xxx-certificate.pem.crt`). These keys need to be loaded by the ESP32 to identify itself. - -There are currently two options for how to load the key & cert. - -* Embed the files into the app binary (default) -* Load the files from SD card - -### Option 1: Embedded Key & Cert into App Binary - -Copy the `.pem.key` and `.pem.crt` files to the `main/certs` subdirectory of the example. Rename them by removing the device-specific prefix - the new names are `private.pem.key` and `certificate.pem.crt`. - -As these files are bound to your AWS IoT account, take care not to accidentally commit them to public source control. In a commercial IoT device these files would be flashed to the device via a provisioning step, but for these examples they are compiled in. - -### Option 2: Loading Key & Cert from SD Card - -The alternative to embedding the key and certificate is to load them from a FAT filesystem on an SD card. - -Before loading data from SD, format your SD card as FAT and run the `examples/storage/sd_card` example on it to verify that it's working as expected in ESP-IDF. This helps cut down the possible causes of errors in the more complex AWS IoT examples! - -Run `make menuconfig`, navigate to "Example Configuration" and change "AWS IoT Certificate Source" to "Load from SD card". - -Three new prompts will appear for filenames for the device key, device certificate and root CA certificate path. These paths start with `/sdcard/` as this is where the example mounts the (FAT formatted) SD card. - -Copy the certificate and key files to the SD card, and make sure the file names match the names given in the example configuration (either rename the files, or change the config). For the Root CA certificate file (which is not device-specific), you can find the file in the `main/certs` directory or download it from AWS. - -*Note: By default, esp-idf's FATFS support only allows 8.3 character filenames. However, the AWS IoT examples pre-configure the sdkconfig to enable long filenames. If you're setting up your projects, you will probably want to enable these options as well (under Component Config -> FAT Filesystem Support). You can also consider configure the FAT filesystem for read-only support, if you don't need to write to the SD card.* - -## Find & Set AWS Endpoint Hostname - -Your AWS IoT account has a unique endpoint hostname to connect to. To find it, open the AWS IoT Console and click the "Settings" button on the bottom left side. The endpoint hostname is shown under the "Custom Endpoint" heading on this page. - -Run `make menuconfig` and navigate to `Component Config` -> `Amazon Web Service IoT Config` -> `AWS IoT MQTT Hostname`. Enter the host name here. - -*Note: It may seem odd that you have to configure parts of the AWS settings under Component Config and some under Example Configuration.* The IoT MQTT Hostname and Port are set as part of the component because when using the AWS IoT SDK's Thing Shadow API (in examples or in other projects) the `ShadowInitParametersDefault` structure means the Thing Shadow connection will default to that host & port. You're not forced to use these config values in your own projects, you can set the values in code via the AWS IoT SDK's init parameter structures - `ShadowInitParameters_t` for Thing Shadow API or `IoT_Client_Init_Params` for MQTT API. - -### (Optional) Set Client ID - -Run `make menuconfig`. Under `Example Configuration`, set the `AWS IoT Client ID` to a unique value. - -The Client ID is used in the MQTT protocol used to send messages to/from AWS IoT. AWS IoT requires that each connected device within a single AWS account uses a unique Client ID. Other than this restriction, the Client ID can be any value that you like. The example default should be fine if you're only connecting one ESP32 at a time. - -In a production IoT app this ID would be set dynamically, but for these examples it is compiled in via menuconfig. - -### (Optional) Locally Check The Root Certificate - -The Root CA certificate provides a root-of-trust when the ESP32 connects to AWS IoT. We have supplied the root CA certificate already (in PEM format) in the file `main/certs/aws-root-ca.pem`. - -If you want to locally verify that this Root CA certificate hasn't changed, you can run the following command against your AWS MQTT Host: - -``` -openssl s_client -showcerts -connect hostname:8883 < /dev/null -``` - -(Replace hostname with your AWS MQTT endpoint host.) The Root CA certificate is the last certificate in the list of certificates printed. You can copy-paste this in place of the existing `aws-root-ca.pem` file. - - -# Troubleshooting - -## Tips - -* Raise the ESP debug log level to Debug in order to see messages about the connection to AWS, certificate contents, etc. - -* Enable mbedTLS debugging (under Components -> mbedTLS -> mbedTLS Debug) in order to see even more low-level debug output from the mbedTLS layer. - -* To create a successful AWS IoT connection, the following factors must all be present: - - Endpoint hostname is correct for your AWS account. - - Certificate & private key are both attached to correct Thing in AWS IoT Console. - - Certificate is activated. - - Policy is attached to the Certificate in AWS IoT Console. - - Policy contains sufficient permissions to authorize AWS IoT connection. - -## TLS connection fails - -If connecting fails entirely (handshake doesn't complete), this usually indicates a problem with certification configuration. The error usually looks like this: - -``` -aws_iot: failed! mbedtls_ssl_handshake returned -0x7780 -``` - -(0x7780 is the mbedTLS error code when the server sends an alert message and closes the connection.) - -* Check your client private key and certificate file match a Certificate registered and **activated** in AWS IoT console. You can find the Certificate in IoT Console in one of two ways, via the Thing or via Certificates: - - To find the Certificate directly, click on "Registry" -> "Security Certificates". Then click on the Certificate itself to view it. - - To find the Certificate via the Thing, click on "Registry" -> "Things", then click on the particular Thing you are using. Click "Certificates" in the sidebar to view all Certificates attached to that Thing. Then click on the Certificate itself to view it. - -Verify the Certificate is activated (when viewing the Certificate, it will say "ACTIVE" or "INACTIVE" near the top under the certificate name). - -If the Certificate appears correct and activated, verify that you are connecting to the correct AWS IoT endpoint (see above.) - -## TLS connection closes immediately - -Sometimes connecting is successful (the handshake completes) but as soon as the client sends its `MQTT CONNECT` message the server sends back a TLS alert and closes the connection, without anything else happening. - -The error returned from AWS IoT is usually -28 (`MQTT_REQUEST_TIMEOUT_ERROR`). You may also see mbedtls error `-0x7780` (server alert), although if this error comes during `mbedtls_ssl_handshake` then it's usually a different problem (see above). - -In the subscribe_publish example, the error may look like this in the log: - -``` -subpub: Error(-28) connecting to (endpoint)... -``` - -In the thing_shadow example, the error may look like this in the log: - -``` -shadow: aws_iot_shadow_connect returned error -28, aborting... -``` - -This error implies the Certificate is recognised, but the Certificate is either missing the correct Thing or the correct Policy attached to it. - -* Check in the AWS IoT console that your certificate is activated and has both a **security policy** and a **Thing** attached to it. You can find this in IoT Console by clicking "Registry" -> "Security Certificates", then click the Certificate. Once viewing the Certificate, you can click the "Policies" and "Things" links in the sidebar. - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/CMakeLists.txt b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/CMakeLists.txt deleted file mode 100644 index a415bf5de..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set (EXTRA_COMPONENT_DIRS "../..") -project(subscribe_publish) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/Makefile deleted file mode 100644 index 798941a9f..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := subscribe_publish - -EXTRA_COMPONENT_DIRS := $(realpath ../..) - -include $(IDF_PATH)/make/project.mk - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/README.md deleted file mode 100644 index 031dc72a9..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Amazon Web Services IoT MQTT Subscribe/Publish Example - -This is an adaptation of the [AWS IoT C SDK](https://github.com/aws/aws-iot-device-sdk-embedded-C) "subscribe_publish" example for ESP-IDF. - -# Configuration - -See the README.md in the parent directory for information about configuring the AWS IoT examples. - -# Monitoring MQTT Data from the device - -After flashing the example to your ESP32, it should connect to Amazon and start subscribing/publishing MQTT data. - -The example code publishes MQTT data to the topic `test_topic/esp32`. Amazon provides a web interface to subscribe to MQTT topics for testing: - -* On the AWS IoT console, click "MQTT Client" near the top-right. -* Click "Generate Client ID" to generate a random client ID. -* Click "Connect" - -One connection succeeds, you can subscribe to the data published by the ESP32: - -* Click "Subscribe to Topic" -* Enter "Subscription Topic" `test_topic/esp32` -* Click "Subscribe" - -... you should see MQTT data published from the running example. - -To publish data back to the device: - -* Click "Publish to Topic" -* Enter "Publish Topic" `test_topic/esp32` -* Enter a message in the payload field -* Click Publish - -# Important Note - -This example has dependency on `esp-aws-iot` component which is added through `EXTRA_COMPONENT_DIRS` in its `Makefile` or `CMakeLists.txt` (using relative path). Hence if example is moved outside of this repository then this dependency can be resolved by copying `esp_aws_iot` under `components` subdirectory of the example project. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/CMakeLists.txt b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/CMakeLists.txt deleted file mode 100644 index 807ad6ea0..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(COMPONENT_SRCS "subscribe_publish_sample.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") - - -register_component() - -if(CONFIG_EXAMPLE_EMBEDDED_CERTS) -target_add_binary_data(${COMPONENT_TARGET} "certs/aws-root-ca.pem" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/certificate.pem.crt" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/private.pem.key" TEXT) -endif() diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/Kconfig.projbuild b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/Kconfig.projbuild deleted file mode 100644 index 96a022a5c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/Kconfig.projbuild +++ /dev/null @@ -1,60 +0,0 @@ -menu "Example Configuration" - - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - - config AWS_EXAMPLE_CLIENT_ID - string "AWS IoT Client ID" - default "myesp32" - help - AWS IoT Client ID for the example. Should be unique for every device. - - choice EXAMPLE_CERT_SOURCE - prompt "AWS IoT Certificate Source" - default EXAMPLE_EMBEDDED_CERTS - help - AWS IoT requires loading of a device-specific certificate and private key, - and a common Root CA Certificate. These can be compiled into the example - app, or they can be loaded via the filesystem from an SD card. - - config EXAMPLE_EMBEDDED_CERTS - bool "Embed into app" - config EXAMPLE_SDCARD_CERTS - bool "Load from SD card" - select EXAMPLE_FILESYSTEM_CERTS - endchoice - - # Currently this is equivalent to EXAMPLE_SDCARD_CERTS, - # however eventually we want to support more filesystem - # sources (SPIFFS, etc.) So this hidden config item - # is selected whenever the item should load from filesystem. - config EXAMPLE_FILESYSTEM_CERTS - bool - - config EXAMPLE_CERTIFICATE_PATH - string "Device Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/certificate.pem.crt" - - config EXAMPLE_PRIVATE_KEY_PATH - string "Device Private Key Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/private.pem.key" - - config EXAMPLE_ROOT_CA_PATH - string "Root CA Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/aws-root-ca.pem" - -endmenu diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/README.md deleted file mode 100644 index d445cc62b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Copy certificate files for AWS IoT SDK example here - -See README.md in main example directory for details. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/aws-root-ca.pem b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/aws-root-ca.pem deleted file mode 100644 index a6f3e92af..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/certs/aws-root-ca.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/component.mk b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/component.mk deleted file mode 100644 index 401de47a5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/component.mk +++ /dev/null @@ -1,14 +0,0 @@ -# -# Main Makefile. This is basically the same as a component makefile. -# - -ifdef CONFIG_EXAMPLE_EMBEDDED_CERTS -# Certificate files. certificate.pem.crt & private.pem.key must be downloaded -# from AWS, see README for details. -COMPONENT_EMBED_TXTFILES := certs/aws-root-ca.pem certs/certificate.pem.crt certs/private.pem.key - -# Print an error if the certificate/key files are missing -$(COMPONENT_PATH)/certs/certificate.pem.crt $(COMPONENT_PATH)/certs/private.pem.key: - @echo "Missing PEM file $@. This file identifies the ESP32 to AWS for the example, see README for details." - exit 1 -endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/subscribe_publish_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/subscribe_publish_sample.c deleted file mode 100644 index c5b48ae8e..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/main/subscribe_publish_sample.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 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. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ -/** - * @file subscribe_publish_sample.c - * @brief simple MQTT publish and subscribe on the same topic - * - * This example takes the parameters from the build configuration and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "test_topic/esp32" - * - * Some setup is required. See example README for details. - * - */ -#include -#include -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "esp_vfs_fat.h" -#include "driver/sdmmc_host.h" - -#include "nvs.h" -#include "nvs_flash.h" - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -static const char *TAG = "subpub"; - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - - -/* CA Root certificate, device ("Thing") certificate and device - * ("Thing") key. - - Example can be configured one of two ways: - - "Embedded Certs" are loaded from files in "certs/" and embedded into the app binary. - - "Filesystem Certs" are loaded from the filesystem (SD card, etc.) - - See example README for more details. -*/ -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - -extern const uint8_t aws_root_ca_pem_start[] asm("_binary_aws_root_ca_pem_start"); -extern const uint8_t aws_root_ca_pem_end[] asm("_binary_aws_root_ca_pem_end"); -extern const uint8_t certificate_pem_crt_start[] asm("_binary_certificate_pem_crt_start"); -extern const uint8_t certificate_pem_crt_end[] asm("_binary_certificate_pem_crt_end"); -extern const uint8_t private_pem_key_start[] asm("_binary_private_pem_key_start"); -extern const uint8_t private_pem_key_end[] asm("_binary_private_pem_key_end"); - -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - -static const char * DEVICE_CERTIFICATE_PATH = CONFIG_EXAMPLE_CERTIFICATE_PATH; -static const char * DEVICE_PRIVATE_KEY_PATH = CONFIG_EXAMPLE_PRIVATE_KEY_PATH; -static const char * ROOT_CA_PATH = CONFIG_EXAMPLE_ROOT_CA_PATH; - -#else -#error "Invalid method for loading certs" -#endif - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -char HostAddress[255] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -uint32_t port = AWS_IOT_MQTT_PORT; - - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - ESP_LOGI(TAG, "Subscribe callback"); - ESP_LOGI(TAG, "%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, (char *)params->payload); -} - -void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - ESP_LOGW(TAG, "MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - ESP_LOGI(TAG, "Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - ESP_LOGW(TAG, "Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - ESP_LOGW(TAG, "Manual Reconnect Successful"); - } else { - ESP_LOGW(TAG, "Manual Reconnect Failed - %d", rc); - } - } -} - -void aws_iot_task(void *param) { - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - ESP_LOGI(TAG, "AWS IoT SDK Version %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - mqttInitParams.pRootCALocation = (const char *)aws_root_ca_pem_start; - mqttInitParams.pDeviceCertLocation = (const char *)certificate_pem_crt_start; - mqttInitParams.pDevicePrivateKeyLocation = (const char *)private_pem_key_start; - -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - mqttInitParams.pRootCALocation = ROOT_CA_PATH; - mqttInitParams.pDeviceCertLocation = DEVICE_CERTIFICATE_PATH; - mqttInitParams.pDevicePrivateKeyLocation = DEVICE_PRIVATE_KEY_PATH; -#endif - - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - -#ifdef CONFIG_EXAMPLE_SDCARD_CERTS - ESP_LOGI(TAG, "Mounting SD card..."); - sdmmc_host_t host = SDMMC_HOST_DEFAULT(); - sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = false, - .max_files = 3, - }; - sdmmc_card_t* card; - esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to mount SD card VFAT filesystem. Error: %s", esp_err_to_name(ret)); - abort(); - } -#endif - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "aws_iot_mqtt_init returned error : %d ", rc); - abort(); - } - - /* Wait for WiFI to show as connected */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - /* Client ID is set in the menuconfig of the example */ - connectParams.pClientID = CONFIG_AWS_EXAMPLE_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(CONFIG_AWS_EXAMPLE_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - ESP_LOGI(TAG, "Connecting to AWS..."); - do { - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - vTaskDelay(1000 / portTICK_RATE_MS); - } - } while(SUCCESS != rc); - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Unable to set Auto Reconnect to true - %d", rc); - abort(); - } - - const char *TOPIC = "test_topic/esp32"; - const int TOPIC_LEN = strlen(TOPIC); - - ESP_LOGI(TAG, "Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, TOPIC, TOPIC_LEN, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Error subscribing : %d ", rc); - abort(); - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - ESP_LOGI(TAG, "Stack remaining for task '%s' is %d bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); - vTaskDelay(1000 / portTICK_RATE_MS); - sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS0)", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, ¶msQOS0); - - sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS1)", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - ESP_LOGW(TAG, "QOS1 publish ack not received."); - rc = SUCCESS; - } - } - - ESP_LOGE(TAG, "An error occurred in the main loop."); - abort(); -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - - -void app_main() -{ - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); - - initialise_wifi(); - xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 9216, NULL, 5, NULL, 1); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.ci b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.ci deleted file mode 100644 index b59dfb870..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.ci +++ /dev/null @@ -1,2 +0,0 @@ -# For CI build example assuming certificates stored on sdcard -CONFIG_EXAMPLE_SDCARD_CERTS=y diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.defaults b/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.defaults deleted file mode 100644 index 1b9028247..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/subscribe_publish/sdkconfig.defaults +++ /dev/null @@ -1,9 +0,0 @@ -# Enable FATFS read only with long filename support -# for loading Cert/CA/etc from filesystem -# (if enabled in config) -CONFIG_FATFS_READONLY=y -CONFIG_FATFS_CODEPAGE_437=y -CONFIG_FATFS_LFN_HEAP=y - -# Enable TLS asymmetric in/out content length -CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/CMakeLists.txt b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/CMakeLists.txt deleted file mode 100644 index 54aa85bc1..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set (EXTRA_COMPONENT_DIRS "../..") -project(thing_shadow) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/Makefile b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/Makefile deleted file mode 100644 index db8d0136c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := thing_shadow - -EXTRA_COMPONENT_DIRS := $(realpath ../..) - -include $(IDF_PATH)/make/project.mk - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/README.md deleted file mode 100644 index a508e73a4..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Amazon Web Services IoT Thing Shadow Example - -This is an adaptation of the [AWS IoT C SDK](https://github.com/aws/aws-iot-device-sdk-embedded-C) "shadow_sample" example for ESP-IDF. - -# Provisioning/Configuration - -See the README.md in the parent directory for information about configuring the AWS IoT examples. - -After following those steps, there is one additional step for this exmaple: - -## Set Thing Name - -For this example, you will need to set a Thing Name under `make menuconfig` -> `Example Configuration` -> `AWS IoT Thing Name`. - -The Thing Name should match a Thing that you created while following the Getting Started guide (to check the Things you have registered, go t othe AWS IoT console web interface, click Registry and then click Things). - -# Monitoring Thing Status - -After flashing the example to your ESP32, it should connect to Amazon and start updating the example Thing's shadow. - -In the ESP32's serial output, you should see the message "Update accepted" logged every couple of seconds. - -You can monitor the Thing status from the AWS IoT console web interface: - -* On the left-hand toolbar, click Registry and then click Things. -* Click on the "Thing" you set up for the example. -* Click on the "Shadow" sidebar link. You should see the Thing Shadow updating regularly. -* Click on the "Activity" sidebar link to see all Thing Shadow updates in a list. You can examine each update individually. - -# Troubleshooting - -If you're having problems with the AWS IoT connection itself, check the Troubleshooting section of the README in the parent directory. - -* If your Thing is connecting and appears to be successfully updating, but you don't see any updates in the AWS IoT console, then check that the Thing Name in the Example Configuration under menuconfig matches exactly the thing name in AWS IoT console (including case). - -# Important Note - -This example has dependency on `esp-aws-iot` component which is added through `EXTRA_COMPONENT_DIRS` in its `Makefile` or `CMakeLists.txt` (using relative path). Hence if example is moved outside of this repository then this dependency can be resolved by copying `esp_aws_iot` under `components` subdirectory of the example project. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/CMakeLists.txt b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/CMakeLists.txt deleted file mode 100644 index f97a426c6..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(COMPONENT_SRCS "thing_shadow_sample.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") - - -register_component() - -if(CONFIG_EXAMPLE_EMBEDDED_CERTS) -target_add_binary_data(${COMPONENT_TARGET} "certs/aws-root-ca.pem" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/certificate.pem.crt" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/private.pem.key" TEXT) -endif() diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/Kconfig.projbuild b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/Kconfig.projbuild deleted file mode 100644 index d0ee5c2cb..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/Kconfig.projbuild +++ /dev/null @@ -1,66 +0,0 @@ -menu "Example Configuration" - - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - - config AWS_EXAMPLE_CLIENT_ID - string "AWS IoT Client ID" - default "myesp32" - help - AWS IoT Client ID for the example. Should be unique for every device. - - config AWS_EXAMPLE_THING_NAME - string "AWS IoT Thing Name" - default "myesp32" - help - AWS IoT Thing Name for the example. Should be unique for every device. - - choice EXAMPLE_CERT_SOURCE - prompt "AWS IoT Certificate Source" - default EXAMPLE_EMBEDDED_CERTS - help - AWS IoT requires loading of a device-specific certificate and private key, - and a common Root CA Certificate. These can be compiled into the example - app, or they can be loaded via the filesystem from an SD card. - - config EXAMPLE_EMBEDDED_CERTS - bool "Embed into app" - config EXAMPLE_SDCARD_CERTS - bool "Load from SD card" - select EXAMPLE_FILESYSTEM_CERTS - endchoice - - # Currently this is equivalent to EXAMPLE_SDCARD_CERTS, - # however eventually we want to support more filesystem - # sources (SPIFFS, etc.) So this hidden config item - # is selected whenever the item should load from filesystem. - config EXAMPLE_FILESYSTEM_CERTS - bool - - config EXAMPLE_CERTIFICATE_PATH - string "Device Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/certificate.pem.crt" - - config EXAMPLE_PRIVATE_KEY_PATH - string "Device Private Key Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/private.pem.key" - - config EXAMPLE_ROOT_CA_PATH - string "Root CA Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/aws-root-ca.pem" - -endmenu diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/README.md b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/README.md deleted file mode 100644 index d445cc62b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Copy certificate files for AWS IoT SDK example here - -See README.md in main example directory for details. diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/aws-root-ca.pem b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/aws-root-ca.pem deleted file mode 100644 index a6f3e92af..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/certs/aws-root-ca.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/component.mk b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/component.mk deleted file mode 100644 index 401de47a5..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/component.mk +++ /dev/null @@ -1,14 +0,0 @@ -# -# Main Makefile. This is basically the same as a component makefile. -# - -ifdef CONFIG_EXAMPLE_EMBEDDED_CERTS -# Certificate files. certificate.pem.crt & private.pem.key must be downloaded -# from AWS, see README for details. -COMPONENT_EMBED_TXTFILES := certs/aws-root-ca.pem certs/certificate.pem.crt certs/private.pem.key - -# Print an error if the certificate/key files are missing -$(COMPONENT_PATH)/certs/certificate.pem.crt $(COMPONENT_PATH)/certs/private.pem.key: - @echo "Missing PEM file $@. This file identifies the ESP32 to AWS for the example, see README for details." - exit 1 -endif diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/thing_shadow_sample.c b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/thing_shadow_sample.c deleted file mode 100644 index 82ef78358..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/main/thing_shadow_sample.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 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. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ -/** - * @file thing_shadow_sample.c - * @brief A simple connected window example demonstrating the use of Thing Shadow - * - * See example README for more details. - */ -#include -#include -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "esp_vfs_fat.h" -#include "driver/sdmmc_host.h" - -#include "nvs.h" -#include "nvs_flash.h" - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" -#include "aws_iot_shadow_interface.h" - -/*! - * The goal of this sample application is to demonstrate the capabilities of shadow. - * This device(say Connected Window) will open the window of a room based on temperature - * It can report to the Shadow the following parameters: - * 1. temperature of the room (double) - * 2. status of the window (open or close) - * It can act on commands from the cloud. In this case it will open or close the window based on the json object "windowOpen" data[open/close] - * - * The two variables from a device's perspective are double temperature and bool windowOpen - * The device needs to act on only on windowOpen variable, so we will create a primitiveJson_t object with callback - The Json Document in the cloud will be - { - "reported": { - "temperature": 0, - "windowOpen": false - }, - "desired": { - "windowOpen": false - } - } - */ - -static const char *TAG = "shadow"; - -#define ROOMTEMPERATURE_UPPERLIMIT 32.0f -#define ROOMTEMPERATURE_LOWERLIMIT 25.0f -#define STARTING_ROOMTEMPERATURE ROOMTEMPERATURE_LOWERLIMIT - -#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - - -/* CA Root certificate, device ("Thing") certificate and device - * ("Thing") key. - - Example can be configured one of two ways: - - "Embedded Certs" are loaded from files in "certs/" and embedded into the app binary. - - "Filesystem Certs" are loaded from the filesystem (SD card, etc.) - - See example README for more details. -*/ -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - -extern const uint8_t aws_root_ca_pem_start[] asm("_binary_aws_root_ca_pem_start"); -extern const uint8_t aws_root_ca_pem_end[] asm("_binary_aws_root_ca_pem_end"); -extern const uint8_t certificate_pem_crt_start[] asm("_binary_certificate_pem_crt_start"); -extern const uint8_t certificate_pem_crt_end[] asm("_binary_certificate_pem_crt_end"); -extern const uint8_t private_pem_key_start[] asm("_binary_private_pem_key_start"); -extern const uint8_t private_pem_key_end[] asm("_binary_private_pem_key_end"); - -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - -static const char * DEVICE_CERTIFICATE_PATH = CONFIG_EXAMPLE_CERTIFICATE_PATH; -static const char * DEVICE_PRIVATE_KEY_PATH = CONFIG_EXAMPLE_PRIVATE_KEY_PATH; -static const char * ROOT_CA_PATH = CONFIG_EXAMPLE_ROOT_CA_PATH; - -#else -#error "Invalid method for loading certs" -#endif - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void simulateRoomTemperature(float *pRoomTemperature) { - static float deltaChange; - - if(*pRoomTemperature >= ROOMTEMPERATURE_UPPERLIMIT) { - deltaChange = -0.5f; - } else if(*pRoomTemperature <= ROOMTEMPERATURE_LOWERLIMIT) { - deltaChange = 0.5f; - } - - *pRoomTemperature += deltaChange; -} - -static bool shadowUpdateInProgress; - -void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, - const char *pReceivedJsonDocument, void *pContextData) { - IOT_UNUSED(pThingName); - IOT_UNUSED(action); - IOT_UNUSED(pReceivedJsonDocument); - IOT_UNUSED(pContextData); - - shadowUpdateInProgress = false; - - if(SHADOW_ACK_TIMEOUT == status) { - ESP_LOGE(TAG, "Update timed out"); - } else if(SHADOW_ACK_REJECTED == status) { - ESP_LOGE(TAG, "Update rejected"); - } else if(SHADOW_ACK_ACCEPTED == status) { - ESP_LOGI(TAG, "Update accepted"); - } -} - -void windowActuate_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { - IOT_UNUSED(pJsonString); - IOT_UNUSED(JsonStringDataLen); - - if(pContext != NULL) { - ESP_LOGI(TAG, "Delta - Window state changed to %d", *(bool *) (pContext->pData)); - } -} - -void aws_iot_task(void *param) { - IoT_Error_t rc = FAILURE; - - char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER]; - size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]); - float temperature = 0.0; - - bool windowOpen = false; - jsonStruct_t windowActuator; - windowActuator.cb = windowActuate_Callback; - windowActuator.pData = &windowOpen; - windowActuator.pKey = "windowOpen"; - windowActuator.type = SHADOW_JSON_BOOL; - windowActuator.dataLength = sizeof(bool); - - jsonStruct_t temperatureHandler; - temperatureHandler.cb = NULL; - temperatureHandler.pKey = "temperature"; - temperatureHandler.pData = &temperature; - temperatureHandler.type = SHADOW_JSON_FLOAT; - temperatureHandler.dataLength = sizeof(float); - - ESP_LOGI(TAG, "AWS IoT SDK Version %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - // initialize the mqtt client - AWS_IoT_Client mqttClient; - - ShadowInitParameters_t sp = ShadowInitParametersDefault; - sp.pHost = AWS_IOT_MQTT_HOST; - sp.port = AWS_IOT_MQTT_PORT; - -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - sp.pClientCRT = (const char *)certificate_pem_crt_start; - sp.pClientKey = (const char *)private_pem_key_start; - sp.pRootCA = (const char *)aws_root_ca_pem_start; -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - sp.pClientCRT = DEVICE_CERTIFICATE_PATH; - sp.pClientKey = DEVICE_PRIVATE_KEY_PATH; - sp.pRootCA = ROOT_CA_PATH; -#endif - sp.enableAutoReconnect = false; - sp.disconnectHandler = NULL; - -#ifdef CONFIG_EXAMPLE_SDCARD_CERTS - ESP_LOGI(TAG, "Mounting SD card..."); - sdmmc_host_t host = SDMMC_HOST_DEFAULT(); - sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = false, - .max_files = 3, - }; - sdmmc_card_t* card; - esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to mount SD card VFAT filesystem. Error: %s", esp_err_to_name(ret)); - abort(); - } -#endif - - /* Wait for WiFI to show as connected */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - - ESP_LOGI(TAG, "Shadow Init"); - rc = aws_iot_shadow_init(&mqttClient, &sp); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "aws_iot_shadow_init returned error %d, aborting...", rc); - abort(); - } - - ShadowConnectParameters_t scp = ShadowConnectParametersDefault; - scp.pMyThingName = CONFIG_AWS_EXAMPLE_THING_NAME; - scp.pMqttClientId = CONFIG_AWS_EXAMPLE_CLIENT_ID; - scp.mqttClientIdLen = (uint16_t) strlen(CONFIG_AWS_EXAMPLE_CLIENT_ID); - - ESP_LOGI(TAG, "Shadow Connect"); - rc = aws_iot_shadow_connect(&mqttClient, &scp); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "aws_iot_shadow_connect returned error %d, aborting...", rc); - abort(); - } - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Unable to set Auto Reconnect to true - %d, aborting...", rc); - abort(); - } - - rc = aws_iot_shadow_register_delta(&mqttClient, &windowActuator); - - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Shadow Register Delta Error"); - } - temperature = STARTING_ROOMTEMPERATURE; - - // loop and publish a change in temperature - while(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) { - rc = aws_iot_shadow_yield(&mqttClient, 200); - if(NETWORK_ATTEMPTING_RECONNECT == rc || shadowUpdateInProgress) { - rc = aws_iot_shadow_yield(&mqttClient, 1000); - // If the client is attempting to reconnect, or already waiting on a shadow update, - // we will skip the rest of the loop. - continue; - } - ESP_LOGI(TAG, "======================================================================================="); - ESP_LOGI(TAG, "On Device: window state %s", windowOpen ? "true" : "false"); - simulateRoomTemperature(&temperature); - - rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); - if(SUCCESS == rc) { - rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 2, &temperatureHandler, - &windowActuator); - if(SUCCESS == rc) { - rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); - if(SUCCESS == rc) { - ESP_LOGI(TAG, "Update Shadow: %s", JsonDocumentBuffer); - rc = aws_iot_shadow_update(&mqttClient, CONFIG_AWS_EXAMPLE_THING_NAME, JsonDocumentBuffer, - ShadowUpdateStatusCallback, NULL, 4, true); - shadowUpdateInProgress = true; - } - } - } - ESP_LOGI(TAG, "*****************************************************************************************"); - ESP_LOGI(TAG, "Stack remaining for task '%s' is %d bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); - - vTaskDelay(1000 / portTICK_RATE_MS); - } - - if(SUCCESS != rc) { - ESP_LOGE(TAG, "An error occurred in the loop %d", rc); - } - - ESP_LOGI(TAG, "Disconnecting"); - rc = aws_iot_shadow_disconnect(&mqttClient); - - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Disconnect error %d", rc); - } - - vTaskDelete(NULL); -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - - -void app_main() -{ - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); - - initialise_wifi(); - /* Temporarily pin task to core, due to FPU uncertainty */ - xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 9216, NULL, 5, NULL, 1); -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.ci b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.ci deleted file mode 100644 index b59dfb870..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.ci +++ /dev/null @@ -1,2 +0,0 @@ -# For CI build example assuming certificates stored on sdcard -CONFIG_EXAMPLE_SDCARD_CERTS=y diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.defaults b/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.defaults deleted file mode 100644 index 8d8e882fc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/examples/thing_shadow/sdkconfig.defaults +++ /dev/null @@ -1,8 +0,0 @@ -# Enable FATFS read only with long filename support -# for loading Cert/CA/etc from filesystem -# (if enabled in config) -CONFIG_FATFS_CODEPAGE_437=y -CONFIG_FATFS_LFN_HEAP=y - -# Enable TLS asymmetric in/out content length -CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_config.h b/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_config.h deleted file mode 100644 index c98f7dea2..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_config.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file aws_iot_config.h - * @brief AWS IoT specific configuration file - */ - -#ifndef _AWS_IOT_CONFIG_H_ -#define _AWS_IOT_CONFIG_H_ - -#include "aws_iot_log.h" - -// This configuration macro needs to be available globally to enable threading -#define _ENABLE_THREAD_SUPPORT_ - -// These values are defined in the menuconfig of the AWS IoT component. -// However, you can override these constants from your own code. -#define AWS_IOT_MQTT_HOST CONFIG_AWS_IOT_MQTT_HOST ///< Customer specific MQTT HOST. The same will be used for Thing Shadow -#define AWS_IOT_MQTT_PORT CONFIG_AWS_IOT_MQTT_PORT ///< default port for MQTT/S - -// These values are defaults and are used for ShadowConnectParametersDefault. -// You should override them from your own code. -#define AWS_IOT_MQTT_CLIENT_ID "ESP32" ///< MQTT client ID should be unique for every device -#define AWS_IOT_MY_THING_NAME "ESP32" ///< Thing Name of the Shadow this device is associated with - -// MQTT PubSub -#define AWS_IOT_MQTT_TX_BUF_LEN CONFIG_AWS_IOT_MQTT_TX_BUF_LEN ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow -#define AWS_IOT_MQTT_RX_BUF_LEN CONFIG_AWS_IOT_MQTT_RX_BUF_LEN ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped. -#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS CONFIG_AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow - -// Thing Shadow specific configs -#ifdef CONFIG_AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER -#define SHADOW_MAX_SIZE_OF_RX_BUFFER CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_RX_BUFFER ///< Maximum size of the SHADOW buffer to store the received Shadow message, including NULL terminating byte -#else -#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN + 1) -#endif - -#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments" -#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE (MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10) ///< This is size of the extra sequence number that will be appended to the Unique client Id -#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE (MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20) ///< This is size of the the total clientToken key and value pair in the JSON -#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested -#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time -#define MAX_JSON_TOKEN_EXPECTED CONFIG_AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published -#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME CONFIG_AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME ///< All shadow actions have to be published or subscribed to a topic which is of the formablogt $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name -#define MAX_SIZE_OF_THING_NAME CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger -#define MAX_SHADOW_TOPIC_LENGTH_BYTES (MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME) ///< This size includes the length of topic with Thing Name - -// Auto Reconnect specific config -#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL CONFIG_AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm -#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL CONFIG_AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL ///< Maximum time interval after which exponential back-off will stop attempting to reconnect. - -#endif /* _AWS_IOT_CONFIG_H_ */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_log.h b/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_log.h deleted file mode 100644 index 7d83960cc..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/aws_iot_log.h +++ /dev/null @@ -1,50 +0,0 @@ -// 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. -#pragma once - -/* (these two headers aren't used here, but AWS IoT SDK code relies on them - being included from here...) */ -#include -#include - -#include "esp_log.h" - -/* This is a stub replacement for the aws_iot_log.h header in the AWS IoT SDK, - which redirects their logging framework into the esp-idf logging framework. - - The current (2.1.1) upstream AWS IoT SDK doesn't allow this as some of its - headers include aws_iot_log.h, but our modified fork does. -*/ - -// redefine the AWS IoT log functions to call into the IDF log layer -#undef IOT_DEBUG -#define IOT_DEBUG(format, ...) ESP_LOGD("aws_iot", format, ##__VA_ARGS__) -#undef IOT_INFO -#define IOT_INFO(format, ...) ESP_LOGI("aws_iot", format, ##__VA_ARGS__) -#undef IOT_WARN -#define IOT_WARN(format, ...) ESP_LOGW("aws_iot", format, ##__VA_ARGS__) -#undef IOT_ERROR -#define IOT_ERROR(format, ...) ESP_LOGE("aws_iot", format, ##__VA_ARGS__) - -/* Function tracing macros used in AWS IoT SDK, - mapped to "verbose" level output -*/ -#undef FUNC_ENTRY -#define FUNC_ENTRY ESP_LOGV("aws_iot", "FUNC_ENTRY: %s L#%d \n", __func__, __LINE__) -#undef FUNC_EXIT_RC -#define FUNC_EXIT_RC(x) \ - do { \ - ESP_LOGV("aws_iot", "FUNC_EXIT: %s L#%d Return Code : %d \n", __func__, __LINE__, x); \ - return x; \ - } while(0) diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/network_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/port/include/network_platform.h deleted file mode 100644 index a5e87d71a..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/network_platform.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 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. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/platform.h" -#include "mbedtls/net_sockets.h" -#include "mbedtls/ssl.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/certs.h" -#include "mbedtls/x509.h" -#include "mbedtls/error.h" -#include "mbedtls/debug.h" -#include "mbedtls/timing.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief TLS Connection Parameters - * - * Defines a type containing TLS specific parameters to be passed down to the - * TLS networking layer to create a TLS secured socket. - */ -typedef struct _TLSDataParams { - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_context ssl; - mbedtls_ssl_config conf; - uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; - mbedtls_pk_context pkey; - mbedtls_net_context server_fd; -}TLSDataParams; - -#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H - -#ifdef __cplusplus -} -#endif - -#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/threads_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/port/include/threads_platform.h deleted file mode 100644 index 011a1a0b2..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/threads_platform.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 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. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#include "threads_interface.h" - -#ifndef AWS_IOTSDK_THREADS_PLATFORM_H -#define AWS_IOTSDK_THREADS_PLATFORM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" - -/** - * @brief Mutex Type - * - * definition of the Mutex struct. Platform specific - * - */ -struct _IoT_Mutex_t { - SemaphoreHandle_t mutex; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOTSDK_THREADS_PLATFORM_H */ - - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/timer_platform.h b/examples/espidf-aws-iot/components/esp-aws-iot/port/include/timer_platform.h deleted file mode 100644 index 07e7385db..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/include/timer_platform.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 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. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -#ifndef AWS_IOT_PLATFORM_H -#define AWS_IOT_PLATFORM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "timer_interface.h" - -/** - * definition of the Timer struct. Platform specific - */ -struct Timer { - uint32_t start_ticks; - uint32_t timeout_ticks; - uint32_t last_polled_ticks; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* AWS_IOT_PLATFORM_H */ diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/network_mbedtls_wrapper.c b/examples/espidf-aws-iot/components/esp-aws-iot/port/network_mbedtls_wrapper.c deleted file mode 100644 index 61ddec02b..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/network_mbedtls_wrapper.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 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. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ -#include -#include -#include -#include -#include - -#include "aws_iot_config.h" -#include "aws_iot_error.h" -#include "network_interface.h" -#include "network_platform.h" - -#include "mbedtls/esp_debug.h" - -#include "esp_log.h" -#include "esp_vfs.h" - -static const char *TAG = "aws_iot"; - -/* This is the value used for ssl read timeout */ -#define IOT_SSL_READ_TIMEOUT 10 - -/* - * This is a function to do further verification if needed on the cert received. - * - * Currently used to print debug-level information about each cert. - */ -static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { - char buf[256]; - ((void) data); - - if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { - ESP_LOGD(TAG, "Verify requested for (Depth %d):", depth); - mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); - ESP_LOGD(TAG, "%s", buf); - - if((*flags) == 0) { - ESP_LOGD(TAG, " This certificate has no flags"); - } else { - ESP_LOGD(TAG, "Verify result:%s", buf); - } - } - - return 0; -} - -static void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - pNetwork->tlsConnectParams.DestinationPort = destinationPort; - pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL; - pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation; - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation; - pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation; - pNetwork->tlsConnectParams.timeout_ms = timeout_ms; - pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag; -} - -IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, - char *pDevicePrivateKeyLocation, char *pDestinationURL, - uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { - _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation, - pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag); - - pNetwork->connect = iot_tls_connect; - pNetwork->read = iot_tls_read; - pNetwork->write = iot_tls_write; - pNetwork->disconnect = iot_tls_disconnect; - pNetwork->isConnected = iot_tls_is_connected; - pNetwork->destroy = iot_tls_destroy; - - pNetwork->tlsDataParams.flags = 0; - - return SUCCESS; -} - -IoT_Error_t iot_tls_is_connected(Network *pNetwork) { - /* Use this to add implementation which can check for physical layer disconnect */ - return NETWORK_PHYSICAL_LAYER_CONNECTED; -} - -IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { - int ret = SUCCESS; - TLSDataParams *tlsDataParams = NULL; - char portBuffer[6]; - char info_buf[256]; - - if(NULL == pNetwork) { - return NULL_VALUE_ERROR; - } - - if(NULL != params) { - _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, - params->pDevicePrivateKeyLocation, params->pDestinationURL, - params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag); - } - - tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_init(&(tlsDataParams->server_fd)); - mbedtls_ssl_init(&(tlsDataParams->ssl)); - mbedtls_ssl_config_init(&(tlsDataParams->conf)); - -#ifdef CONFIG_MBEDTLS_DEBUG - mbedtls_esp_enable_debug_log(&(tlsDataParams->conf), 4); -#endif - - mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); - mbedtls_x509_crt_init(&(tlsDataParams->cacert)); - mbedtls_x509_crt_init(&(tlsDataParams->clicert)); - mbedtls_pk_init(&(tlsDataParams->pkey)); - - ESP_LOGD(TAG, "Seeding the random number generator..."); - mbedtls_entropy_init(&(tlsDataParams->entropy)); - if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), - (const unsigned char *) TAG, strlen(TAG))) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ctr_drbg_seed returned -0x%x", -ret); - return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; - } - - /* Load root CA... - - Certs/keys can be paths or they can be raw data. These use a - very basic heuristic: if the cert starts with '/' then it's a - path, if it's longer than this then it's raw cert data (PEM or DER, - neither of which can start with a slash. */ - if (pNetwork->tlsConnectParams.pRootCALocation[0] == '/') { - ESP_LOGD(TAG, "Loading CA root certificate from file ..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation); - } else { - ESP_LOGD(TAG, "Loading embedded CA root certificate ..."); - ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char *)pNetwork->tlsConnectParams.pRootCALocation, - strlen(pNetwork->tlsConnectParams.pRootCALocation)+1); - } - - if(ret < 0) { - ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing root cert", -ret); - return NETWORK_X509_ROOT_CRT_PARSE_ERROR; - } - ESP_LOGD(TAG, "ok (%d skipped)", ret); - - /* Load client certificate... */ - if (pNetwork->tlsConnectParams.pDeviceCertLocation[0] == '/') { - ESP_LOGD(TAG, "Loading client cert from file..."); - ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), - pNetwork->tlsConnectParams.pDeviceCertLocation); - } else { - ESP_LOGD(TAG, "Loading embedded client certificate..."); - ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert), - (const unsigned char *)pNetwork->tlsConnectParams.pDeviceCertLocation, - strlen(pNetwork->tlsConnectParams.pDeviceCertLocation)+1); - } - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing device cert", -ret); - return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; - } - - /* Parse client private key... */ - if (pNetwork->tlsConnectParams.pDevicePrivateKeyLocation[0] == '/') { - ESP_LOGD(TAG, "Loading client private key from file..."); - ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), - pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, - ""); - } else { - ESP_LOGD(TAG, "Loading embedded client private key..."); - ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey), - (const unsigned char *)pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, - strlen(pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)+1, - (const unsigned char *)"", 0); - } - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_pk_parse_key returned -0x%x while parsing private key", -ret); - return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; - } - - /* Done parsing certs */ - ESP_LOGD(TAG, "ok"); - snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); - ESP_LOGD(TAG, "Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); - if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, - portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_net_connect returned -0x%x", -ret); - switch(ret) { - case MBEDTLS_ERR_NET_SOCKET_FAILED: - return NETWORK_ERR_NET_SOCKET_FAILED; - case MBEDTLS_ERR_NET_UNKNOWN_HOST: - return NETWORK_ERR_NET_UNKNOWN_HOST; - case MBEDTLS_ERR_NET_CONNECT_FAILED: - default: - return NETWORK_ERR_NET_CONNECT_FAILED; - }; - } - - ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); - if(ret != 0) { - ESP_LOGE(TAG, "failed! net_set_(non)block() returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } ESP_LOGD(TAG, "ok"); - - ESP_LOGD(TAG, "Setting up the SSL/TLS structure..."); - if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_config_defaults returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); - } else { - mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); - } - mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); - - mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); - ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey)); - if(ret != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_own_cert returned %d", ret); - return SSL_CONNECTION_ERROR; - } - - mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); - -#ifdef CONFIG_MBEDTLS_SSL_ALPN - /* Use the AWS IoT ALPN extension for MQTT, if port 443 is requested */ - if (pNetwork->tlsConnectParams.DestinationPort == 443) { - const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; - if ((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - } -#endif - - if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_setup returned -0x%x", -ret); - return SSL_CONNECTION_ERROR; - } - if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_set_hostname returned %d", ret); - return SSL_CONNECTION_ERROR; - } - ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); - mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, - mbedtls_net_recv_timeout); - ESP_LOGD(TAG, "ok"); - - ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); - ESP_LOGD(TAG, "Performing the SSL/TLS handshake..."); - while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_handshake returned -0x%x", -ret); - if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - ESP_LOGE(TAG, " Unable to verify the server's certificate. "); - } - return SSL_CONNECTION_ERROR; - } - } - - ESP_LOGD(TAG, "ok [ Protocol is %s ] [ Ciphersuite is %s ]", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), - mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); - if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { - ESP_LOGD(TAG, " [ Record expansion is %d ]", ret); - } else { - ESP_LOGD(TAG, " [ Record expansion is unknown (compression) ]"); - } - - ESP_LOGD(TAG, "Verifying peer X.509 certificate..."); - - if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { - if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { - ESP_LOGE(TAG, "failed"); - mbedtls_x509_crt_verify_info(info_buf, sizeof(info_buf), " ! ", tlsDataParams->flags); - ESP_LOGE(TAG, "%s", info_buf); - ret = SSL_CONNECTION_ERROR; - } else { - ESP_LOGD(TAG, "ok"); - ret = SUCCESS; - } - } else { - ESP_LOGW(TAG, " Server Verification skipped"); - ret = SUCCESS; - } - - if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { - if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { - ESP_LOGD(TAG, "Peer certificate information:"); - mbedtls_x509_crt_info((char *) info_buf, sizeof(info_buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); - ESP_LOGD(TAG, "%s", info_buf); - } - } - - return (IoT_Error_t) ret; -} - -IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) { - size_t written_so_far; - bool isErrorFlag = false; - int frags, ret = 0; - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - - for(written_so_far = 0, frags = 0; - written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) { - while(!has_timer_expired(timer) && - (ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) { - if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ESP_LOGE(TAG, "failed! mbedtls_ssl_write returned -0x%x", -ret); - /* All other negative return values indicate connection needs to be reset. - * Will be caught in ping request so ignored here */ - isErrorFlag = true; - break; - } - } - if(isErrorFlag) { - break; - } - } - - *written_len = written_so_far; - - if(isErrorFlag) { - return NETWORK_SSL_WRITE_ERROR; - } else if(has_timer_expired(timer) && written_so_far != len) { - return NETWORK_SSL_WRITE_TIMEOUT_ERROR; - } - - return SUCCESS; -} - -IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *read_len) { - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - mbedtls_ssl_context *ssl = &(tlsDataParams->ssl); - mbedtls_ssl_config *ssl_conf = &(tlsDataParams->conf); - uint32_t read_timeout; - size_t rxLen = 0; - int ret; - - read_timeout = ssl_conf->read_timeout; - - while (len > 0) { - - /* Make sure we never block on read for longer than timer has left, - but also that we don't block indefinitely (ie read_timeout > 0) */ - mbedtls_ssl_conf_read_timeout(ssl_conf, MAX(1, MIN(read_timeout, left_ms(timer)))); - - ret = mbedtls_ssl_read(ssl, pMsg, len); - - /* Restore the old timeout */ - mbedtls_ssl_conf_read_timeout(ssl_conf, read_timeout); - - if (ret > 0) { - rxLen += ret; - pMsg += ret; - len -= ret; - } else if (ret == 0 || (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_TIMEOUT)) { - return NETWORK_SSL_READ_ERROR; - } - - // Evaluate timeout after the read to make sure read is done at least once - if (has_timer_expired(timer)) { - break; - } - } - - if (len == 0) { - *read_len = rxLen; - return SUCCESS; - } - - if (rxLen == 0) { - return NETWORK_SSL_NOTHING_TO_READ; - } else { - return NETWORK_SSL_READ_TIMEOUT_ERROR; - } -} - -IoT_Error_t iot_tls_disconnect(Network *pNetwork) { - mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl); - int ret = 0; - do { - ret = mbedtls_ssl_close_notify(ssl); - } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE); - - /* All other negative return values indicate connection needs to be reset. - * No further action required since this is disconnect call */ - - return SUCCESS; -} - -IoT_Error_t iot_tls_destroy(Network *pNetwork) { - TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); - - mbedtls_net_free(&(tlsDataParams->server_fd)); - - mbedtls_x509_crt_free(&(tlsDataParams->clicert)); - mbedtls_x509_crt_free(&(tlsDataParams->cacert)); - mbedtls_pk_free(&(tlsDataParams->pkey)); - mbedtls_ssl_free(&(tlsDataParams->ssl)); - mbedtls_ssl_config_free(&(tlsDataParams->conf)); - mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg)); - mbedtls_entropy_free(&(tlsDataParams->entropy)); - - return SUCCESS; -} diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/threads_freertos.c b/examples/espidf-aws-iot/components/esp-aws-iot/port/threads_freertos.c deleted file mode 100644 index 065ead78c..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/threads_freertos.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 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. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include "threads_platform.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialize the provided mutex - * - * Call this function to initialize the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be initialized - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *pMutex) { - - pMutex->mutex = xSemaphoreCreateRecursiveMutex(); - return pMutex->mutex ? SUCCESS : MUTEX_INIT_ERROR; -} - -/** - * @brief Lock the provided mutex - * - * Call this function to lock the mutex before performing a state change - * Blocking, thread will block until lock request fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *pMutex) { - xSemaphoreTakeRecursive(pMutex->mutex, portMAX_DELAY); - return SUCCESS; -} - -/** - * @brief Try to lock the provided mutex - * - * Call this function to attempt to lock the mutex before performing a state change - * Non-Blocking, immediately returns with failure if lock attempt fails - * - * @param IoT_Mutex_t - pointer to the mutex to be locked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *pMutex) { - if (xSemaphoreTakeRecursive(pMutex->mutex, 0)) { - return SUCCESS; - } else { - return MUTEX_LOCK_ERROR; - } -} - -/** - * @brief Unlock the provided mutex - * - * Call this function to unlock the mutex before performing a state change - * - * @param IoT_Mutex_t - pointer to the mutex to be unlocked - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *pMutex) { - if (xSemaphoreGiveRecursive(pMutex->mutex)) { - return SUCCESS; - } else { - return MUTEX_UNLOCK_ERROR; - } -} - -/** - * @brief Destroy the provided mutex - * - * Call this function to destroy the mutex - * - * @param IoT_Mutex_t - pointer to the mutex to be destroyed - * @return IoT_Error_t - error code indicating result of operation - */ -IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *pMutex) { - vSemaphoreDelete(pMutex->mutex); - return SUCCESS; -} - -#ifdef __cplusplus -} -#endif - diff --git a/examples/espidf-aws-iot/components/esp-aws-iot/port/timer.c b/examples/espidf-aws-iot/components/esp-aws-iot/port/timer.c deleted file mode 100644 index ee4d8b5be..000000000 --- a/examples/espidf-aws-iot/components/esp-aws-iot/port/timer.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 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. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ - -/** - * @file timer.c - * @brief FreeRTOS implementation of the timer interface uses ticks. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "timer_platform.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_log.h" - -const static char *TAG = "aws_timer"; - -bool has_timer_expired(Timer *timer) { - uint32_t now = xTaskGetTickCount(); - bool expired = (now - timer->start_ticks) >= timer->timeout_ticks; - - /* AWS IoT SDK isn't very RTOS friendly because it polls for "done - timers" a lot without ever sleeping on them. So we hack in some - amount of sleeping here: if it seems like the caller is polling - an unexpired timer in a tight loop then we delay a tick to let - things progress elsewhere. - */ - if(!expired && now == timer->last_polled_ticks) { - vTaskDelay(1); - } - timer->last_polled_ticks = now; - return expired; -} - -void countdown_ms(Timer *timer, uint32_t timeout) { - timer->start_ticks = xTaskGetTickCount(); - timer->timeout_ticks = timeout / portTICK_PERIOD_MS; - timer->last_polled_ticks = 0; -} - -uint32_t left_ms(Timer *timer) { - uint32_t now = xTaskGetTickCount(); - uint32_t elapsed = now - timer->start_ticks; - if (elapsed < timer->timeout_ticks) { - return (timer->timeout_ticks - elapsed) * portTICK_PERIOD_MS; - } else { - return 0; - } -} - -void countdown_sec(Timer *timer, uint32_t timeout) { - if (timeout > UINT32_MAX / 1000) { - ESP_LOGE(TAG, "timeout is out of range: %ds", timeout); - } - countdown_ms(timer, timeout * 1000); -} - -void init_timer(Timer *timer) { - timer->start_ticks = 0; - timer->timeout_ticks = 0; - timer->last_polled_ticks = 0; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-aws-iot/include/README b/examples/espidf-aws-iot/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/espidf-aws-iot/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-aws-iot/lib/README b/examples/espidf-aws-iot/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/espidf-aws-iot/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-aws-iot/platformio.ini b/examples/espidf-aws-iot/platformio.ini deleted file mode 100644 index 5bf94f9d8..000000000 --- a/examples/espidf-aws-iot/platformio.ini +++ /dev/null @@ -1,26 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[env:esp32dev] -platform = espressif32 -framework = espidf -board = esp32dev -monitor_speed = 115200 -monitor_filters = colorize - -board_build.embed_txtfiles = - src/certs/private.pem.key - src/certs/certificate.pem.crt - src/certs/aws-root-ca.pem - -# IDF v5 is not supported by ASW-IoT SDK -# https://github.com/espressif/esp-aws-iot/blob/bbaf03d7d1fbf8a3f91dc18489d7bd27d5b9e9df/README.md?plain=1#L21 -platform_packages = - framework-espidf @ ~3.40403.0 - toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5 diff --git a/examples/espidf-aws-iot/sdkconfig.defaults b/examples/espidf-aws-iot/sdkconfig.defaults deleted file mode 100644 index b1a90483c..000000000 --- a/examples/espidf-aws-iot/sdkconfig.defaults +++ /dev/null @@ -1,13 +0,0 @@ -# Enable FATFS read only with long filename support -# for loading Cert/CA/etc from filesystem -# (if enabled in config) -CONFIG_FATFS_READONLY=y -CONFIG_FATFS_CODEPAGE_437=y -CONFIG_FATFS_LFN_HEAP=y - -# Enable TLS asymmetric in/out content length -CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y - -# Example configs -CONFIG_EXAMPLE_WIFI_SSID="MYSSID" -CONFIG_EXAMPLE_WIFI_PASSWORD="MYPASS" diff --git a/examples/espidf-aws-iot/src/CMakeLists.txt b/examples/espidf-aws-iot/src/CMakeLists.txt deleted file mode 100644 index 807ad6ea0..000000000 --- a/examples/espidf-aws-iot/src/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(COMPONENT_SRCS "subscribe_publish_sample.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") - - -register_component() - -if(CONFIG_EXAMPLE_EMBEDDED_CERTS) -target_add_binary_data(${COMPONENT_TARGET} "certs/aws-root-ca.pem" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/certificate.pem.crt" TEXT) -target_add_binary_data(${COMPONENT_TARGET} "certs/private.pem.key" TEXT) -endif() diff --git a/examples/espidf-aws-iot/src/Kconfig.projbuild b/examples/espidf-aws-iot/src/Kconfig.projbuild deleted file mode 100644 index 96a022a5c..000000000 --- a/examples/espidf-aws-iot/src/Kconfig.projbuild +++ /dev/null @@ -1,60 +0,0 @@ -menu "Example Configuration" - - config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - - config AWS_EXAMPLE_CLIENT_ID - string "AWS IoT Client ID" - default "myesp32" - help - AWS IoT Client ID for the example. Should be unique for every device. - - choice EXAMPLE_CERT_SOURCE - prompt "AWS IoT Certificate Source" - default EXAMPLE_EMBEDDED_CERTS - help - AWS IoT requires loading of a device-specific certificate and private key, - and a common Root CA Certificate. These can be compiled into the example - app, or they can be loaded via the filesystem from an SD card. - - config EXAMPLE_EMBEDDED_CERTS - bool "Embed into app" - config EXAMPLE_SDCARD_CERTS - bool "Load from SD card" - select EXAMPLE_FILESYSTEM_CERTS - endchoice - - # Currently this is equivalent to EXAMPLE_SDCARD_CERTS, - # however eventually we want to support more filesystem - # sources (SPIFFS, etc.) So this hidden config item - # is selected whenever the item should load from filesystem. - config EXAMPLE_FILESYSTEM_CERTS - bool - - config EXAMPLE_CERTIFICATE_PATH - string "Device Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/certificate.pem.crt" - - config EXAMPLE_PRIVATE_KEY_PATH - string "Device Private Key Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/private.pem.key" - - config EXAMPLE_ROOT_CA_PATH - string "Root CA Certificate Path" - depends on EXAMPLE_FILESYSTEM_CERTS - default "/sdcard/aws-root-ca.pem" - -endmenu diff --git a/examples/espidf-aws-iot/src/certs/README.md b/examples/espidf-aws-iot/src/certs/README.md deleted file mode 100644 index d445cc62b..000000000 --- a/examples/espidf-aws-iot/src/certs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Copy certificate files for AWS IoT SDK example here - -See README.md in main example directory for details. diff --git a/examples/espidf-aws-iot/src/certs/aws-root-ca.pem b/examples/espidf-aws-iot/src/certs/aws-root-ca.pem deleted file mode 100644 index a6f3e92af..000000000 --- a/examples/espidf-aws-iot/src/certs/aws-root-ca.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- diff --git a/examples/espidf-aws-iot/src/certs/certificate.pem.crt b/examples/espidf-aws-iot/src/certs/certificate.pem.crt deleted file mode 100644 index d831f6f16..000000000 --- a/examples/espidf-aws-iot/src/certs/certificate.pem.crt +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -DUMMY CONTENT ------END CERTIFICATE----- \ No newline at end of file diff --git a/examples/espidf-aws-iot/src/certs/private.pem.key b/examples/espidf-aws-iot/src/certs/private.pem.key deleted file mode 100644 index d831f6f16..000000000 --- a/examples/espidf-aws-iot/src/certs/private.pem.key +++ /dev/null @@ -1,3 +0,0 @@ ------BEGIN CERTIFICATE----- -DUMMY CONTENT ------END CERTIFICATE----- \ No newline at end of file diff --git a/examples/espidf-aws-iot/src/subscribe_publish_sample.c b/examples/espidf-aws-iot/src/subscribe_publish_sample.c deleted file mode 100644 index 833261c86..000000000 --- a/examples/espidf-aws-iot/src/subscribe_publish_sample.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Additions Copyright 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. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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. - */ -/** - * @file subscribe_publish_sample.c - * @brief simple MQTT publish and subscribe on the same topic - * - * This example takes the parameters from the build configuration and establishes a connection to the AWS IoT MQTT Platform. - * It subscribes and publishes to the same topic - "test_topic/esp32" - * - * Some setup is required. See example README for details. - * - */ -#include -#include -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event.h" -#include "esp_log.h" -#include "esp_vfs_fat.h" -#include "driver/sdmmc_host.h" - -#include "nvs.h" -#include "nvs_flash.h" - -#include "aws_iot_config.h" -#include "aws_iot_log.h" -#include "aws_iot_version.h" -#include "aws_iot_mqtt_client_interface.h" - -static const char *TAG = "subpub"; - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - - -/* CA Root certificate, device ("Thing") certificate and device - * ("Thing") key. - - Example can be configured one of two ways: - - "Embedded Certs" are loaded from files in "certs/" and embedded into the app binary. - - "Filesystem Certs" are loaded from the filesystem (SD card, etc.) - - See example README for more details. -*/ -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - -extern const uint8_t aws_root_ca_pem_start[] asm("_binary_aws_root_ca_pem_start"); -extern const uint8_t aws_root_ca_pem_end[] asm("_binary_aws_root_ca_pem_end"); -extern const uint8_t certificate_pem_crt_start[] asm("_binary_certificate_pem_crt_start"); -extern const uint8_t certificate_pem_crt_end[] asm("_binary_certificate_pem_crt_end"); -extern const uint8_t private_pem_key_start[] asm("_binary_private_pem_key_start"); -extern const uint8_t private_pem_key_end[] asm("_binary_private_pem_key_end"); - -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - -static const char * DEVICE_CERTIFICATE_PATH = CONFIG_EXAMPLE_CERTIFICATE_PATH; -static const char * DEVICE_PRIVATE_KEY_PATH = CONFIG_EXAMPLE_PRIVATE_KEY_PATH; -static const char * ROOT_CA_PATH = CONFIG_EXAMPLE_ROOT_CA_PATH; - -#else -#error "Invalid method for loading certs" -#endif - -/** - * @brief Default MQTT HOST URL is pulled from the aws_iot_config.h - */ -char HostAddress[255] = AWS_IOT_MQTT_HOST; - -/** - * @brief Default MQTT port is pulled from the aws_iot_config.h - */ -uint32_t port = AWS_IOT_MQTT_PORT; - - -static void event_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data) -{ - ESP_LOGI(TAG, "event_handler: %s:%d", base, id); - - if(base == WIFI_EVENT) { - switch(id) { - case WIFI_EVENT_STA_START: - esp_wifi_connect(); - break; - case WIFI_EVENT_STA_CONNECTED: - break; - case WIFI_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - } - else if(base == IP_EVENT) { - switch(id) { - case IP_EVENT_STA_GOT_IP: - { - ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; - ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - } - } - } -} - -void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, - IoT_Publish_Message_Params *params, void *pData) { - ESP_LOGI(TAG, "Subscribe callback"); - ESP_LOGI(TAG, "%.*s\t%.*s", topicNameLen, topicName, (int) params->payloadLen, (char *)params->payload); -} - -void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { - ESP_LOGW(TAG, "MQTT Disconnect"); - IoT_Error_t rc = FAILURE; - - if(NULL == pClient) { - return; - } - - if(aws_iot_is_autoreconnect_enabled(pClient)) { - ESP_LOGI(TAG, "Auto Reconnect is enabled, Reconnecting attempt will start now"); - } else { - ESP_LOGW(TAG, "Auto Reconnect not enabled. Starting manual reconnect..."); - rc = aws_iot_mqtt_attempt_reconnect(pClient); - if(NETWORK_RECONNECTED == rc) { - ESP_LOGW(TAG, "Manual Reconnect Successful"); - } else { - ESP_LOGW(TAG, "Manual Reconnect Failed - %d", rc); - } - } -} - -void aws_iot_task(void *param) { - char cPayload[100]; - - int32_t i = 0; - - IoT_Error_t rc = FAILURE; - - AWS_IoT_Client client; - IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; - IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; - - IoT_Publish_Message_Params paramsQOS0; - IoT_Publish_Message_Params paramsQOS1; - - ESP_LOGI(TAG, "AWS IoT SDK Version %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); - - mqttInitParams.enableAutoReconnect = false; // We enable this later below - mqttInitParams.pHostURL = HostAddress; - mqttInitParams.port = port; - -#if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) - mqttInitParams.pRootCALocation = (char *)aws_root_ca_pem_start; - mqttInitParams.pDeviceCertLocation = (char *)certificate_pem_crt_start; - mqttInitParams.pDevicePrivateKeyLocation = (char *)private_pem_key_start; - -#elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) - mqttInitParams.pRootCALocation = ROOT_CA_PATH; - mqttInitParams.pDeviceCertLocation = DEVICE_CERTIFICATE_PATH; - mqttInitParams.pDevicePrivateKeyLocation = DEVICE_PRIVATE_KEY_PATH; -#endif - - mqttInitParams.mqttCommandTimeout_ms = 20000; - mqttInitParams.tlsHandshakeTimeout_ms = 5000; - mqttInitParams.isSSLHostnameVerify = true; - mqttInitParams.disconnectHandler = disconnectCallbackHandler; - mqttInitParams.disconnectHandlerData = NULL; - -#ifdef CONFIG_EXAMPLE_SDCARD_CERTS - ESP_LOGI(TAG, "Mounting SD card..."); - sdmmc_host_t host = SDMMC_HOST_DEFAULT(); - sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = false, - .max_files = 3, - }; - sdmmc_card_t* card; - esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to mount SD card VFAT filesystem. Error: %s", esp_err_to_name(ret)); - abort(); - } -#endif - - rc = aws_iot_mqtt_init(&client, &mqttInitParams); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "aws_iot_mqtt_init returned error : %d ", rc); - abort(); - } - - /* Wait for WiFI to show as connected */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - - connectParams.keepAliveIntervalInSec = 10; - connectParams.isCleanSession = true; - connectParams.MQTTVersion = MQTT_3_1_1; - /* Client ID is set in the menuconfig of the example */ - connectParams.pClientID = CONFIG_AWS_EXAMPLE_CLIENT_ID; - connectParams.clientIDLen = (uint16_t) strlen(CONFIG_AWS_EXAMPLE_CLIENT_ID); - connectParams.isWillMsgPresent = false; - - ESP_LOGI(TAG, "Connecting to AWS with client ID '%s'", connectParams.pClientID); - do { - rc = aws_iot_mqtt_connect(&client, &connectParams); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); - vTaskDelay(1000 / portTICK_RATE_MS); - } - } while(SUCCESS != rc); - - /* - * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h - * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL - * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL - */ - rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Unable to set Auto Reconnect to true - %d", rc); - abort(); - } - - const char *TOPIC = "test_topic/esp32"; - const int TOPIC_LEN = strlen(TOPIC); - - ESP_LOGI(TAG, "Subscribing..."); - rc = aws_iot_mqtt_subscribe(&client, TOPIC, TOPIC_LEN, QOS0, iot_subscribe_callback_handler, NULL); - if(SUCCESS != rc) { - ESP_LOGE(TAG, "Error subscribing : %d ", rc); - abort(); - } - - sprintf(cPayload, "%s : %d ", "hello from SDK", i); - - paramsQOS0.qos = QOS0; - paramsQOS0.payload = (void *) cPayload; - paramsQOS0.isRetained = 0; - - paramsQOS1.qos = QOS1; - paramsQOS1.payload = (void *) cPayload; - paramsQOS1.isRetained = 0; - - while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)) { - - //Max time the yield function will wait for read messages - rc = aws_iot_mqtt_yield(&client, 100); - if(NETWORK_ATTEMPTING_RECONNECT == rc) { - // If the client is attempting to reconnect we will skip the rest of the loop. - continue; - } - - ESP_LOGI(TAG, "Stack remaining for task '%s' is %d bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); - vTaskDelay(1000 / portTICK_RATE_MS); - sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS0)", i++); - paramsQOS0.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, ¶msQOS0); - - sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS1)", i++); - paramsQOS1.payloadLen = strlen(cPayload); - rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, ¶msQOS1); - if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { - ESP_LOGW(TAG, "QOS1 publish ack not received."); - rc = SUCCESS; - } - } - - ESP_LOGE(TAG, "An error occurred in the main loop."); - abort(); -} - -static void initialise_wifi(void) -{ - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_netif_init()); - - ESP_ERROR_CHECK(esp_event_loop_create_default()); - esp_netif_create_default_wifi_sta(); - - ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, - ESP_EVENT_ANY_ID, - &event_handler, - NULL, - NULL)); - ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, - IP_EVENT_STA_GOT_IP, - &event_handler, - NULL, - NULL)); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - - -void app_main() -{ - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); - - initialise_wifi(); - xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 9216, NULL, 5, NULL, 1); -} diff --git a/examples/espidf-aws-iot/test/README b/examples/espidf-aws-iot/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/espidf-aws-iot/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html From 03653207f2ee0f7fdbbb2e6390fce21f2ad450e5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Feb 2023 11:55:41 +0100 Subject: [PATCH 285/666] esptool.py v4.5 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index b65c8a46f..fed707e6a 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.4.5/esptool-4.4.5.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.5/esptool-4.5.zip" }, "tool-openocd-esp32": { "type": "debugger", From e2a38056ff6e2f94ec986239c41112059ed2f3e3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Feb 2023 18:08:21 +0100 Subject: [PATCH 286/666] esptool.py v4.5.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index fed707e6a..2e16812e2 100644 --- a/platform.json +++ b/platform.json @@ -89,7 +89,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.5/esptool-4.5.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.5.1/esptool-4.5.1.zip" }, "tool-openocd-esp32": { "type": "debugger", From afd13ccbccf6db5a1c248742201e51a0610c5c7b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 17 Feb 2023 14:31:28 +0100 Subject: [PATCH 287/666] IDF 5.0.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 2e16812e2..ab72af53f 100644 --- a/platform.json +++ b/platform.json @@ -54,7 +54,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.0/esp-idf-v5.0.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.0.1/esp-idf-v5.0.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 8f9f429bf9e412a84a869760dbc82c59de5551ec Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 17 Feb 2023 14:42:35 +0100 Subject: [PATCH 288/666] update test Arduino build --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index ab72af53f..9c3382fc6 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1179/framework-arduinoespressif32-Tasmota_v5-d6ffee9234.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1216/framework-arduinoespressif32-Tasmota_v5-fa36814ed9.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1179/framework-arduinoespressif32-Tasmota_v5-d6ffee9234.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1216/framework-arduinoespressif32-Tasmota_v5-fa36814ed9.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1179/framework-arduinoespressif32-Tasmota_v5-d6ffee9234.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1216/framework-arduinoespressif32-Tasmota_v5-fa36814ed9.zip" }, "framework-espidf": { "type": "framework", From 0c7e5016a57ba1902a7d348a70319aa105b1a5a7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 17 Feb 2023 15:19:38 +0100 Subject: [PATCH 289/666] Update platform.json --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 9c3382fc6..79c902ccb 100644 --- a/platform.json +++ b/platform.json @@ -53,8 +53,8 @@ "framework-espidf": { "type": "framework", "optional": true, - "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.0.1/esp-idf-v5.0.1.zip" + "owner": "platformio", + "version": "~3.50000.0" }, "toolchain-xtensa-esp32": { "type": "toolchain", From ad8c6b039be21867441c41c570d51b1d6af10888 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 1 Mar 2023 16:24:13 +0100 Subject: [PATCH 290/666] IDF 5.0.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 79c902ccb..0d40b90cd 100644 --- a/platform.json +++ b/platform.json @@ -54,7 +54,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.50000.0" + "version": "~3.50001.0" }, "toolchain-xtensa-esp32": { "type": "toolchain", From a235017582cbd91849592bfb7bba0bad9de01d84 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 3 Mar 2023 14:26:14 +0100 Subject: [PATCH 291/666] IDF: Propagate build flags for ASM files --- builder/frameworks/espidf.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index bd6997fb9..9cc5114fd 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -620,7 +620,10 @@ def prepare_build_envs(config, default_env, debug_allowed=True): source_index = cg.get("sourceIndexes")[0] build_flags = _fix_component_relative_include( config, build_flags, source_index) - build_env.AppendUnique(**build_env.ParseFlags(build_flags)) + parsed_flags = build_env.ParseFlags(build_flags) + build_env.AppendUnique(**parsed_flags) + if cg.get("language", "") == "ASM": + build_env.AppendUnique(ASFLAGS=parsed_flags.get("CCFLAGS", [])) build_env.AppendUnique(CPPDEFINES=defines, CPPPATH=includes) if sys_includes: build_env.Append(CCFLAGS=[("-isystem", inc) for inc in sys_includes]) From 31e462bbc026e392797b9840aebe56f67f01ccde Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 3 Mar 2023 14:39:45 +0100 Subject: [PATCH 292/666] Update espidf.py --- builder/frameworks/espidf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 9cc5114fd..6fde305d9 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -621,9 +621,9 @@ def prepare_build_envs(config, default_env, debug_allowed=True): build_flags = _fix_component_relative_include( config, build_flags, source_index) parsed_flags = build_env.ParseFlags(build_flags) - build_env.AppendUnique(**parsed_flags) - if cg.get("language", "") == "ASM": - build_env.AppendUnique(ASFLAGS=parsed_flags.get("CCFLAGS", [])) + build_env.AppendUnique(**parsed_flags) + if cg.get("language", "") == "ASM": + build_env.AppendUnique(ASFLAGS=parsed_flags.get("CCFLAGS", [])) build_env.AppendUnique(CPPDEFINES=defines, CPPPATH=includes) if sys_includes: build_env.Append(CCFLAGS=[("-isystem", inc) for inc in sys_includes]) From 6c878f9efd3a6cc66f3abd458b10188954078e6e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 22 Mar 2023 13:25:43 +0100 Subject: [PATCH 293/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 0d40b90cd..6498ce3a1 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1216/framework-arduinoespressif32-Tasmota_v5-fa36814ed9.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1263/framework-arduinoespressif32-master-015a166b2b.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1216/framework-arduinoespressif32-Tasmota_v5-fa36814ed9.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1263/framework-arduinoespressif32-master-015a166b2b.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1216/framework-arduinoespressif32-Tasmota_v5-fa36814ed9.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1263/framework-arduinoespressif32-master-015a166b2b.zip" }, "framework-espidf": { "type": "framework", From b9c1d3f916e56433beaae75c45067746c1fdc2eb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 22 Mar 2023 13:31:15 +0100 Subject: [PATCH 294/666] Update platformio.ini --- examples/arduino-blink/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 7f9d443e6..81c2de64f 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -7,7 +7,7 @@ ; Please visit documentation for the other options and examples ; http://docs.platformio.org/page/projectconf.html -[env:esp wrover kit] +[env:esp-wrover-kit] platform = espressif32 framework = arduino board = esp-wrover-kit From 789430b37628d08f4efbbd8f619bf0b36c30c3d4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 22 Mar 2023 13:32:07 +0100 Subject: [PATCH 295/666] Update platformio.ini --- examples/arduino-wifiscan/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/arduino-wifiscan/platformio.ini b/examples/arduino-wifiscan/platformio.ini index 32cbdd883..bc9223323 100644 --- a/examples/arduino-wifiscan/platformio.ini +++ b/examples/arduino-wifiscan/platformio.ini @@ -13,7 +13,7 @@ framework = arduino board = esp32dev monitor_speed = 115200 -[env:esp wrover kit] +[env:esp-wrover-kit] platform = espressif32 framework = arduino board = esp-wrover-kit From c81cc69a8a2fab91720567ce8bf3cb6d80b8600b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 26 Mar 2023 18:44:37 +0200 Subject: [PATCH 296/666] Update examples.yml --- .github/workflows/examples.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 13f6eef7d..1702eddd1 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -20,7 +20,6 @@ jobs: - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/espidf-blink" - - "examples/espidf-ble-eddystone" - "examples/espidf-coap-server" - "examples/espidf-exceptions" - "examples/espidf-hello-world" From 4c8794b16d9e2ca2f1bc4dce350f952829ccb9c9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 26 Mar 2023 18:45:43 +0200 Subject: [PATCH 297/666] Delete examples/espidf-ble-eddystone directory --- examples/espidf-ble-eddystone/.gitignore | 1 - examples/espidf-ble-eddystone/.travis.yml | 67 ----- examples/espidf-ble-eddystone/CMakeLists.txt | 6 - examples/espidf-ble-eddystone/README.md | 27 -- examples/espidf-ble-eddystone/include/README | 39 --- examples/espidf-ble-eddystone/lib/README | 46 ---- examples/espidf-ble-eddystone/platformio.ini | 14 - .../espidf-ble-eddystone/sdkconfig.defaults | 6 - .../espidf-ble-eddystone/src/CMakeLists.txt | 4 - .../src/esp_eddystone_api.c | 251 ------------------ .../src/esp_eddystone_api.h | 67 ----- .../src/esp_eddystone_demo.c | 173 ------------ .../src/esp_eddystone_protocol.h | 110 -------- examples/espidf-ble-eddystone/test/README | 11 - 14 files changed, 822 deletions(-) delete mode 100644 examples/espidf-ble-eddystone/.gitignore delete mode 100644 examples/espidf-ble-eddystone/.travis.yml delete mode 100644 examples/espidf-ble-eddystone/CMakeLists.txt delete mode 100644 examples/espidf-ble-eddystone/README.md delete mode 100644 examples/espidf-ble-eddystone/include/README delete mode 100644 examples/espidf-ble-eddystone/lib/README delete mode 100644 examples/espidf-ble-eddystone/platformio.ini delete mode 100644 examples/espidf-ble-eddystone/sdkconfig.defaults delete mode 100644 examples/espidf-ble-eddystone/src/CMakeLists.txt delete mode 100644 examples/espidf-ble-eddystone/src/esp_eddystone_api.c delete mode 100644 examples/espidf-ble-eddystone/src/esp_eddystone_api.h delete mode 100644 examples/espidf-ble-eddystone/src/esp_eddystone_demo.c delete mode 100644 examples/espidf-ble-eddystone/src/esp_eddystone_protocol.h delete mode 100644 examples/espidf-ble-eddystone/test/README diff --git a/examples/espidf-ble-eddystone/.gitignore b/examples/espidf-ble-eddystone/.gitignore deleted file mode 100644 index 03f4a3c19..000000000 --- a/examples/espidf-ble-eddystone/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/espidf-ble-eddystone/.travis.yml b/examples/espidf-ble-eddystone/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-ble-eddystone/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-ble-eddystone/CMakeLists.txt b/examples/espidf-ble-eddystone/CMakeLists.txt deleted file mode 100644 index 9c5943ef0..000000000 --- a/examples/espidf-ble-eddystone/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(ble_eddystone_demo) diff --git a/examples/espidf-ble-eddystone/README.md b/examples/espidf-ble-eddystone/README.md deleted file mode 100644 index 95ad3377c..000000000 --- a/examples/espidf-ble-eddystone/README.md +++ /dev/null @@ -1,27 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/espidf-ble-eddystone - -# Build project -$ pio run - -# Upload firmware -$ pio run --target upload - -# Build specific environment -$ pio run -e esp32dev - -# Upload firmware for the specific environment -$ pio run -e esp32dev --target upload - -# Clean build files -$ pio run --target clean -``` \ No newline at end of file diff --git a/examples/espidf-ble-eddystone/include/README b/examples/espidf-ble-eddystone/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/espidf-ble-eddystone/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-ble-eddystone/lib/README b/examples/espidf-ble-eddystone/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/espidf-ble-eddystone/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-ble-eddystone/platformio.ini b/examples/espidf-ble-eddystone/platformio.ini deleted file mode 100644 index 6d6af7407..000000000 --- a/examples/espidf-ble-eddystone/platformio.ini +++ /dev/null @@ -1,14 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[env:esp32dev] -platform = espressif32 -framework = espidf -board = esp32dev -monitor_speed = 115200 diff --git a/examples/espidf-ble-eddystone/sdkconfig.defaults b/examples/espidf-ble-eddystone/sdkconfig.defaults deleted file mode 100644 index 00fb52113..000000000 --- a/examples/espidf-ble-eddystone/sdkconfig.defaults +++ /dev/null @@ -1,6 +0,0 @@ -# Override some defaults so BT stack is enabled -# and WiFi disabled by default in this example -CONFIG_BT_ENABLED=y -CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y -CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n -CONFIG_BTDM_CTRL_MODE_BTDM=n diff --git a/examples/espidf-ble-eddystone/src/CMakeLists.txt b/examples/espidf-ble-eddystone/src/CMakeLists.txt deleted file mode 100644 index 0820e85fc..000000000 --- a/examples/espidf-ble-eddystone/src/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_register(SRCS "esp_eddystone_api.c" - "esp_eddystone_demo.c" - INCLUDE_DIRS "") -target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") diff --git a/examples/espidf-ble-eddystone/src/esp_eddystone_api.c b/examples/espidf-ble-eddystone/src/esp_eddystone_api.c deleted file mode 100644 index 283211650..000000000 --- a/examples/espidf-ble-eddystone/src/esp_eddystone_api.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - - -/**************************************************************************** -* -* This file is used to decode eddystone information. -* -****************************************************************************/ - -#include -#include -#include -#include - -#include "esp_err.h" -#include "esp_gap_ble_api.h" -#include "esp_eddystone_protocol.h" -#include "esp_eddystone_api.h" - - -/* Declare static functions */ -static esp_err_t esp_eddystone_uid_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res); -static esp_err_t esp_eddystone_url_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res); -static char* esp_eddystone_resolve_url_scheme(const uint8_t* url_start, const uint8_t* url_end); -static esp_err_t esp_eddystone_tlm_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res); -static esp_err_t esp_eddystone_get_inform(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res); - -/* Eddystone-URL scheme prefixes */ -static const char* eddystone_url_prefix[4] = { - "http://www.", - "https://www.", - "http://", - "https://" -}; - -/* Eddystone-URL HTTP URL encoding */ -static const char* eddystone_url_encoding[14] = { - ".com/", - ".org/", - ".edu/", - ".net/", - ".info/", - ".biz/", - ".gov/", - ".com", - ".org", - ".edu", - ".net", - ".info", - ".biz", - ".gov" - }; - -/****************** Eddystone-UID ************** -Byte offset Field Description - 0 Frame Type Value = 0x00 - 1 Ranging Data Calibrated Tx power at 0 m - 2 NID[0] 10-byte Namespace - 3 NID[1] - 4 NID[2] - 5 NID[3] - 6 NID[4] - 7 NID[5] - 8 NID[6] - 9 NID[7] - 10 NID[8] - 11 NID[9] - 12 BID[0] 6-byte Instance - 13 BID[1] - 14 BID[2] - 15 BID[3] - 16 BID[4] - 17 BID[5] - 18 RFU Reserved for future use, must be0x00 - 19 RFU Reserved for future use, must be0x00 -*********************************************/ -/* decode and store received UID */ -static esp_err_t esp_eddystone_uid_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res) -{ - uint8_t pos = 0; - //1-byte Ranging Data + 10-byte Namespace + 6-byte Instance - if((len != EDDYSTONE_UID_DATA_LEN) && (len != (EDDYSTONE_UID_RFU_LEN+EDDYSTONE_UID_DATA_LEN))) { - //ERROR:uid len wrong - return -1; - } - res->inform.uid.ranging_data = buf[pos++]; - for(int i=0; iinform.uid.namespace_id[i] = buf[pos++]; - } - for(int i=0; iinform.uid.instance_id[i] = buf[pos++]; - } - return 0; -} - -/* resolve received URL to url_res pointer */ -static char* esp_eddystone_resolve_url_scheme(const uint8_t *url_start, const uint8_t *url_end) -{ - int pos = 0; - static char url_buf[100] = {0}; - const uint8_t *p = url_start; - - pos += sprintf(&url_buf[pos], "%s", eddystone_url_prefix[*p++]); - - for (; p <= url_end; p++) { - if (esp_eddystone_is_char_invalid((*p))) { - pos += sprintf(&url_buf[pos], "%s", eddystone_url_encoding[*p]); - } else { - pos += sprintf(&url_buf[pos], "%c", *p); - } - } - return url_buf; -} - -/************************** Eddystone-URL ************* -Frame Specification - Byte offset Field Description - 0 Frame Type Value = 0x10 - 1 TX Power Calibrated Tx power at 0 m - 2 URL Scheme Encoded Scheme Prefix - 3+ Encoded URL Length 1-17 -*******************************************************/ -/* decode and store received URL, the pointer url_res points to the resolved url */ -static esp_err_t esp_eddystone_url_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res) -{ - char *url_res = NULL; - uint8_t pos = 0; - if(len-EDDYSTONE_URL_TX_POWER_LEN > EDDYSTONE_URL_MAX_LEN) { - //ERROR:too long url - return -1; - } - res->inform.url.tx_power = buf[pos++]; - url_res = esp_eddystone_resolve_url_scheme(buf+pos, buf+len-1); - memcpy(&res->inform.url.url, url_res, strlen(url_res)); - res->inform.url.url[strlen(url_res)] = '\0'; - return 0; -} - -/****************** eddystone-tlm *************** - * Unencrypted TLM Frame Specification -Byte offset Field Description - 0 Frame Type Value = 0x20 - 1 Version TLM version, value = 0x00 - 2 VBATT[0] Battery voltage, 1 mV/bit - 3 VBATT[1] - 4 TEMP[0] Beacon temperature - 5 TEMP[1] - 6 ADV_CNT[0] Advertising PDU count - 7 ADV_CNT[1] - 8 ADV_CNT[2] - 9 ADV_CNT[3] - 10 SEC_CNT[0] Time since power-on or reboot - 11 SEC_CNT[1] - 12 SEC_CNT[2] - 13 SEC_CNT[3] -************************************************/ -/* decode and store received TLM */ -static esp_err_t esp_eddystone_tlm_received(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res) -{ - uint8_t pos = 0; - if(len > EDDYSTONE_TLM_DATA_LEN) { - //ERROR:TLM too long - return -1; - } - res->inform.tlm.version = buf[pos++]; - res->inform.tlm.battery_voltage = big_endian_read_16(buf, pos); - pos += 2; - uint16_t temp = big_endian_read_16(buf, pos); - int8_t temp_integral = (int8_t)((temp >> 8) & 0xff); - float temp_decimal = (temp & 0xff) / 256.0; - res->inform.tlm.temperature = temp_integral + temp_decimal; - pos += 2; - res->inform.tlm.adv_count = big_endian_read_32(buf, pos); - pos += 4; - res->inform.tlm.time = big_endian_read_32(buf, pos); - return 0; -} - -static esp_err_t esp_eddystone_get_inform(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res) -{ - static esp_err_t ret=-1; - switch(res->common.frame_type) - { - case EDDYSTONE_FRAME_TYPE_UID: { - ret = esp_eddystone_uid_received(buf, len, res); - break; - } - case EDDYSTONE_FRAME_TYPE_URL: { - ret = esp_eddystone_url_received(buf, len, res); - break; - } - case EDDYSTONE_FRAME_TYPE_TLM: { - ret = esp_eddystone_tlm_received(buf, len, res); - break; - } - default: - break; - } - return ret; -} - -esp_err_t esp_eddystone_decode(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res) -{ - if (len == 0 || buf == NULL || res == NULL) { - return -1; - } - uint8_t pos=0; - while(res->common.srv_data_type != EDDYSTONE_SERVICE_UUID) - { - pos++; - if(pos >= len ) { - return -1; - } - uint8_t ad_type = buf[pos++]; - switch(ad_type) - { - case ESP_BLE_AD_TYPE_FLAG: { - res->common.flags = buf[pos++]; - break; - } - case ESP_BLE_AD_TYPE_16SRV_CMPL: { - uint16_t uuid = little_endian_read_16(buf, pos); - if(uuid != EDDYSTONE_SERVICE_UUID) { - return -1; - } - res->common.srv_uuid = uuid; - pos += 2; - break; - } - case ESP_BLE_AD_TYPE_SERVICE_DATA: { - uint16_t type = little_endian_read_16(buf, pos); - pos += 2; - uint8_t frame_type = buf[pos++]; - if(type != EDDYSTONE_SERVICE_UUID || !(frame_type == EDDYSTONE_FRAME_TYPE_UID || frame_type == EDDYSTONE_FRAME_TYPE_URL || - frame_type == EDDYSTONE_FRAME_TYPE_TLM)) { - return -1; - } - res->common.srv_data_type = type; - res->common.frame_type = frame_type; - break; - } - default: - break; - } - } - return esp_eddystone_get_inform(buf+pos, len-pos, res); -} diff --git a/examples/espidf-ble-eddystone/src/esp_eddystone_api.h b/examples/espidf-ble-eddystone/src/esp_eddystone_api.h deleted file mode 100644 index 752044f67..000000000 --- a/examples/espidf-ble-eddystone/src/esp_eddystone_api.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - - -#ifndef __ESP_EDDYSTONE_API_H__ -#define __ESP_EDDYSTONE_API_H__ - -typedef struct { - struct { - uint8_t flags; /* -#include -#include - -#include "esp_bt.h" -#include "nvs_flash.h" -#include "esp_log.h" -#include "esp_bt_defs.h" -#include "esp_bt_main.h" -#include "esp_gatt_defs.h" -#include "esp_gattc_api.h" -#include "esp_gap_ble_api.h" -#include "freertos/FreeRTOS.h" - -#include "esp_eddystone_protocol.h" -#include "esp_eddystone_api.h" - -static const char* DEMO_TAG = "EDDYSTONE_DEMO"; - -/* declare static functions */ -static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param); -static void esp_eddystone_show_inform(const esp_eddystone_result_t* res); - -static esp_ble_scan_params_t ble_scan_params = { - .scan_type = BLE_SCAN_TYPE_ACTIVE, - .own_addr_type = BLE_ADDR_TYPE_PUBLIC, - .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, - .scan_interval = 0x50, - .scan_window = 0x30, - .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE -}; - -static void esp_eddystone_show_inform(const esp_eddystone_result_t* res) -{ - switch(res->common.frame_type) - { - case EDDYSTONE_FRAME_TYPE_UID: { - ESP_LOGI(DEMO_TAG, "Eddystone UID inform:"); - ESP_LOGI(DEMO_TAG, "Measured power(RSSI at 0m distance):%d dbm", res->inform.uid.ranging_data); - ESP_LOGI(DEMO_TAG, "EDDYSTONE_DEMO: Namespace ID:0x"); - esp_log_buffer_hex(DEMO_TAG, res->inform.uid.namespace_id, 10); - ESP_LOGI(DEMO_TAG, "EDDYSTONE_DEMO: Instance ID:0x"); - esp_log_buffer_hex(DEMO_TAG, res->inform.uid.instance_id, 6); - break; - } - case EDDYSTONE_FRAME_TYPE_URL: { - ESP_LOGI(DEMO_TAG, "Eddystone URL inform:"); - ESP_LOGI(DEMO_TAG, "Measured power(RSSI at 0m distance):%d dbm", res->inform.url.tx_power); - ESP_LOGI(DEMO_TAG, "URL: %s", res->inform.url.url); - break; - } - case EDDYSTONE_FRAME_TYPE_TLM: { - ESP_LOGI(DEMO_TAG, "Eddystone TLM inform:"); - ESP_LOGI(DEMO_TAG, "version: %d", res->inform.tlm.version); - ESP_LOGI(DEMO_TAG, "battery voltage: %d mV", res->inform.tlm.battery_voltage); - ESP_LOGI(DEMO_TAG, "beacon temperature in degrees Celsius: %6.1f", res->inform.tlm.temperature); - ESP_LOGI(DEMO_TAG, "adv pdu count since power-up: %d", res->inform.tlm.adv_count); - ESP_LOGI(DEMO_TAG, "time since power-up: %d s", (res->inform.tlm.time)/10); - break; - } - default: - break; - } -} - -static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) -{ - esp_err_t err; - - switch(event) - { - case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: { - uint32_t duration = 0; - esp_ble_gap_start_scanning(duration); - break; - } - case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: { - if((err = param->scan_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) { - ESP_LOGE(DEMO_TAG,"Scan start failed: %s", esp_err_to_name(err)); - } - else { - ESP_LOGI(DEMO_TAG,"Start scanning..."); - } - break; - } - case ESP_GAP_BLE_SCAN_RESULT_EVT: { - esp_ble_gap_cb_param_t* scan_result = (esp_ble_gap_cb_param_t*)param; - switch(scan_result->scan_rst.search_evt) - { - case ESP_GAP_SEARCH_INQ_RES_EVT: { - esp_eddystone_result_t eddystone_res; - memset(&eddystone_res, 0, sizeof(eddystone_res)); - esp_err_t ret = esp_eddystone_decode(scan_result->scan_rst.ble_adv, scan_result->scan_rst.adv_data_len, &eddystone_res); - if (ret) { - // error:The received data is not an eddystone frame packet or a correct eddystone frame packet. - // just return - return; - } else { - // The received adv data is a correct eddystone frame packet. - // Here, we get the eddystone infomation in eddystone_res, we can use the data in res to do other things. - // For example, just print them: - ESP_LOGI(DEMO_TAG, "--------Eddystone Found----------"); - esp_log_buffer_hex("EDDYSTONE_DEMO: Device address:", scan_result->scan_rst.bda, ESP_BD_ADDR_LEN); - ESP_LOGI(DEMO_TAG, "RSSI of packet:%d dbm", scan_result->scan_rst.rssi); - esp_eddystone_show_inform(&eddystone_res); - } - break; - } - default: - break; - } - break; - } - case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:{ - if((err = param->scan_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS) { - ESP_LOGE(DEMO_TAG,"Scan stop failed: %s", esp_err_to_name(err)); - } - else { - ESP_LOGI(DEMO_TAG,"Stop scan successfully"); - } - break; - } - default: - break; - } -} - -void esp_eddystone_appRegister(void) -{ - esp_err_t status; - - ESP_LOGI(DEMO_TAG,"Register callback"); - - /*= 0x00 && ch <= 0x20) || (ch >= 0x7f && ch <= 0xff); -} - -#endif /* __ESP_EDDYSTONE_PROTOCOL_H__ */ diff --git a/examples/espidf-ble-eddystone/test/README b/examples/espidf-ble-eddystone/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/espidf-ble-eddystone/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html From e6aae2c40fb87cbc79b861cf17b5c7d8246abbfe Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Apr 2023 10:58:49 +0200 Subject: [PATCH 298/666] Update OpenOCD --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 6498ce3a1..3bec5664e 100644 --- a/platform.json +++ b/platform.json @@ -95,7 +95,7 @@ "type": "debugger", "optional": true, "owner": "platformio", - "version": "~2.1100.0" + "version": "~2.1200.0" }, "tool-mkspiffs": { "type": "uploader", From 0a550ababb07cb7b60720644f09005e9f4620e03 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 18 Apr 2023 19:10:06 +0200 Subject: [PATCH 299/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 3bec5664e..eaa65f341 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1263/framework-arduinoespressif32-master-015a166b2b.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1310/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1263/framework-arduinoespressif32-master-015a166b2b.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1310/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1263/framework-arduinoespressif32-master-015a166b2b.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1310/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" }, "framework-espidf": { "type": "framework", From f62fb423a8ad93a6d98e67c39c7f8569c6db7528 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 18 Apr 2023 23:57:30 +0200 Subject: [PATCH 300/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index eaa65f341..f866c5a60 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1310/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1311/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1310/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1311/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1310/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1311/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" }, "framework-espidf": { "type": "framework", From bf03eb3809c14a7b91d01ca9e90061986d0e8b77 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 19 Apr 2023 11:43:35 +0200 Subject: [PATCH 301/666] toolchain 12.2.0_20230208 --- platform.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform.json b/platform.json index f866c5a60..a0bf632c6 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.01.0", + "version": "2023.04.00", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -60,25 +60,25 @@ "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0_20230208" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0_20230208" }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0_20230208" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0_20230208" }, "toolchain-esp32ulp": { "type": "toolchain", From 1d1987efef93de52e2c04d39adc77c9cee2a3d62 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 19 Apr 2023 12:33:12 +0200 Subject: [PATCH 302/666] Update platform.json --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index a0bf632c6..324c6d6dd 100644 --- a/platform.json +++ b/platform.json @@ -60,25 +60,25 @@ "type": "toolchain", "optional": true, "owner": "espressif", - "version": "12.2.0_20230208" + "version": "11.2.0+2022r18" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "12.2.0_20230208" + "version": "11.2.0+2022r1" }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "12.2.0_20230208" + "version": "11.2.0+2022r1" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "12.2.0_20230208" + "version": "11.2.0+2022r1" }, "toolchain-esp32ulp": { "type": "toolchain", From 32f22d8df379a7c72a2f17e960d07e074cef1e4d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 19 Apr 2023 12:36:45 +0200 Subject: [PATCH 303/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 324c6d6dd..9f5aa8d0a 100644 --- a/platform.json +++ b/platform.json @@ -60,7 +60,7 @@ "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r18" + "version": "11.2.0+2022r1" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", From 53b13b10936d6297e092ee5755e3ec5577c47dc7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 19 Apr 2023 17:44:58 +0200 Subject: [PATCH 304/666] GCC 12.2.0+20230208 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 9f5aa8d0a..57421ce6a 100644 --- a/platform.json +++ b/platform.json @@ -60,25 +60,25 @@ "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0+20230208" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0+20230208" }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0+20230208" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0+20230208" }, "toolchain-esp32ulp": { "type": "toolchain", From 30a0e8f280d487b2b779fc4023855b8b53d75609 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 19 Apr 2023 18:55:28 +0200 Subject: [PATCH 305/666] Build 1314 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 57421ce6a..7a8260b54 100644 --- a/platform.json +++ b/platform.json @@ -36,19 +36,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1311/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1314/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1311/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1314/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1311/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1314/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" }, "framework-espidf": { "type": "framework", From 0a6c22974fdabc7e7bb8671707ddc725fb5ee0c6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 28 Apr 2023 23:35:40 +0200 Subject: [PATCH 306/666] Update platform.json --- platform.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 7a8260b54..1d41eb248 100644 --- a/platform.json +++ b/platform.json @@ -25,10 +25,7 @@ }, "espidf": { "package": "framework-espidf", - "script": "builder/frameworks/espidf.py", - "description": "ESP-IDF is the official development framework for the ESP32 and ESP32-S Series SoCs.", - "homepage": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32/", - "title": "Espressif IoT Development Framework" + "script": "builder/frameworks/espidf.py" } }, "packages": { From caa3799857553880dcbbb8f0544b97959f960ffb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 3 May 2023 17:22:45 +0200 Subject: [PATCH 307/666] Update espidf.py --- builder/frameworks/espidf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 6fde305d9..73c0d0a03 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1275,6 +1275,10 @@ def _create_venv(venv_dir): "the `variant` field! The default `esp32` variant will be used." ) extra_components.append(ARDUINO_FRAMEWORK_DIR) + # Add path to internal Arduino libraries so that the LDF will be able to find them + env.Append( + LIBSOURCE_DIRS=[os.path.join(ARDUINO_FRAMEWORK_DIR, "libraries")] + ) print("Reading CMake configuration...") project_codemodel = get_cmake_code_model( From c806f96030cf7bafb0768d4d33362d0c7f8eeaeb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 May 2023 11:30:02 +0200 Subject: [PATCH 308/666] Better handling of macros exported from IDF --- builder/frameworks/espidf.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 73c0d0a03..61e189244 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -84,10 +84,10 @@ PROJECT_DIR = env.subst("$PROJECT_DIR") PROJECT_SRC_DIR = env.subst("$PROJECT_SRC_DIR") CMAKE_API_REPLY_PATH = os.path.join(".cmake", "api", "v1", "reply") -SDKCONFIG_PATH = board.get( +SDKCONFIG_PATH = os.path.expandvars(board.get( "build.esp-idf.sdkconfig_path", os.path.join(PROJECT_DIR, "sdkconfig.%s" % env.subst("$PIOENV")), -) +)) def get_project_lib_includes(env): @@ -302,16 +302,25 @@ def get_app_includes(app_config): def extract_defines(compile_group): - result = [] - result.extend( - [ - d.get("define").replace('"', '\\"').strip() - for d in compile_group.get("defines", []) - ] - ) + def _normalize_define(define_string): + define_string = define_string.strip() + if "=" in define_string: + define, value = define_string.split("=", maxsplit=1) + if '"' in value and not value.startswith("\\"): + # Escape only raw values + value = value.replace('"', '\\"') + return (define, value) + return define_string + + result = [ + _normalize_define(d.get("define", "")) + for d in compile_group.get("defines", []) if d + ] + for f in compile_group.get("compileCommandFragments", []): if f.get("fragment", "").startswith("-D"): - result.append(f["fragment"][2:]) + result.append(_normalize_define(f["fragment"][2:])) + return result @@ -1013,8 +1022,10 @@ def generate_mbedtls_bundle(sdk_config): crt_args = ["--input"] if sdk_config.get("MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL", False): crt_args.append(os.path.join(default_crt_dir, "cacrt_all.pem")) + crt_args.append(os.path.join(default_crt_dir, "cacrt_local.pem")) elif sdk_config.get("MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN", False): crt_args.append(os.path.join(default_crt_dir, "cacrt_all.pem")) + crt_args.append(os.path.join(default_crt_dir, "cacrt_local.pem")) cmd.extend( ["--filter", os.path.join(default_crt_dir, "cmn_crt_authorities.csv")] ) From cb20d2e61b7dbea1471e282088e7eff6543a9b08 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 May 2023 11:36:55 +0200 Subject: [PATCH 309/666] 12.2.0+20230208 --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index 14244a586..bc0932501 100644 --- a/platform.py +++ b/platform.py @@ -73,7 +73,7 @@ def configure_default_packages(self, variables, targets): "xtensa-esp32s3", "riscv32-esp" ): - self.packages["toolchain-%s" % target]["version"] = "11.2.0+2022r1" + self.packages["toolchain-%s" % target]["version"] = "12.2.0+20230208" for available_mcu in ("esp32", "esp32s2", "esp32s3"): if available_mcu == mcu: From ef5bcb71d35d1ff8c46f2bcdbd477d7fc2f5e910 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 May 2023 12:06:28 +0200 Subject: [PATCH 310/666] Update platform.py --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index bc0932501..14244a586 100644 --- a/platform.py +++ b/platform.py @@ -73,7 +73,7 @@ def configure_default_packages(self, variables, targets): "xtensa-esp32s3", "riscv32-esp" ): - self.packages["toolchain-%s" % target]["version"] = "12.2.0+20230208" + self.packages["toolchain-%s" % target]["version"] = "11.2.0+2022r1" for available_mcu in ("esp32", "esp32s2", "esp32s3"): if available_mcu == mcu: From 2a56c95135d27943041e2f48c9c11baffe92c29c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 May 2023 12:07:44 +0200 Subject: [PATCH 311/666] Update platform.json --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 1d41eb248..052547170 100644 --- a/platform.json +++ b/platform.json @@ -57,25 +57,25 @@ "type": "toolchain", "optional": true, "owner": "espressif", - "version": "12.2.0+20230208" + "version": "11.2.0+2022r1" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "12.2.0+20230208" + "version": "11.2.0+2022r1" }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "12.2.0+20230208" + "version": "11.2.0+2022r1" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "12.2.0+20230208" + "version": "11.2.0+2022r1" }, "toolchain-esp32ulp": { "type": "toolchain", From d293db3af5eef84065f249363e5c550ed194d36d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 May 2023 12:27:59 +0200 Subject: [PATCH 312/666] idf v5.1.0.20230509 --- platform.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/platform.json b/platform.json index 052547170..7ab36b8f4 100644 --- a/platform.json +++ b/platform.json @@ -33,49 +33,49 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1314/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1341/framework-arduinoespressif32-release_v5.1-86f6b6c08b.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1314/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1341/framework-arduinoespressif32-release_v5.1-86f6b6c08b.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1314/framework-arduinoespressif32-release_v5.1-ff37e959a1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1341/framework-arduinoespressif32-release_v5.1-86f6b6c08b.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.50001.0" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.0.20230509/esp-idf-v5.1.0.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0+20230208" }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0+20230208" }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0+20230208" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", - "version": "11.2.0+2022r1" + "version": "12.2.0+20230208" }, "toolchain-esp32ulp": { "type": "toolchain", From 9f917ee385b3e8505f85e678659f238b4dd20412 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 May 2023 12:29:05 +0200 Subject: [PATCH 313/666] 12.2.0+20230208 --- platform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.py b/platform.py index 14244a586..deeab0537 100644 --- a/platform.py +++ b/platform.py @@ -66,14 +66,14 @@ def configure_default_packages(self, variables, targets): elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: self.packages[p]["optional"] = False - # Use the latest toolchains available for IDF v5.0 + # Use the latest toolchains available for IDF v5.1 for target in ( "xtensa-esp32", "xtensa-esp32s2", "xtensa-esp32s3", "riscv32-esp" ): - self.packages["toolchain-%s" % target]["version"] = "11.2.0+2022r1" + self.packages["toolchain-%s" % target]["version"] = "12.2.0+20230208" for available_mcu in ("esp32", "esp32s2", "esp32s3"): if available_mcu == mcu: From 5ffacfe3c01ff5a7fd2b44800e04a10e7f566d83 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 May 2023 15:17:28 +0200 Subject: [PATCH 314/666] idf-component-manager~=1.2 --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 61e189244..ba2287bb6 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1100,7 +1100,7 @@ def _get_installed_pip_packages(python_exe_path): "future": ">=0.15.2", "pyparsing": ">=2.0.3,<2.4.0", "kconfiglib": "==13.7.1", - "idf-component-manager": "~=1.0", + "idf-component-manager": "~=1.2", } if IDF5: From f98319c050fb5001b2108b2d74b5727aff1dd699 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 May 2023 15:29:15 +0200 Subject: [PATCH 315/666] "esp-idf-kconfig": ">=1.1.0" --- builder/frameworks/espidf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index ba2287bb6..af9f4b11c 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1101,6 +1101,7 @@ def _get_installed_pip_packages(python_exe_path): "pyparsing": ">=2.0.3,<2.4.0", "kconfiglib": "==13.7.1", "idf-component-manager": "~=1.2", + "esp-idf-kconfig": ">=1.1.0", } if IDF5: From 0a7f6ad66c918ea993f695e8e8ebeb4ff87a54bb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 May 2023 16:54:29 +0200 Subject: [PATCH 316/666] urllib3<2 --- builder/frameworks/espidf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index af9f4b11c..0134e7d5c 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1102,6 +1102,7 @@ def _get_installed_pip_packages(python_exe_path): "kconfiglib": "==13.7.1", "idf-component-manager": "~=1.2", "esp-idf-kconfig": ">=1.1.0", + "urllib3": "<2", } if IDF5: From f20f4891f4c5bb7ab236d81fe111ed46bf928ea0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 10 May 2023 12:51:19 +0200 Subject: [PATCH 317/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 7ab36b8f4..72388ffbd 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1341/framework-arduinoespressif32-release_v5.1-86f6b6c08b.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1342/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1341/framework-arduinoespressif32-release_v5.1-86f6b6c08b.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1342/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1341/framework-arduinoespressif32-release_v5.1-86f6b6c08b.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1342/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" }, "framework-espidf": { "type": "framework", From a273a74f9a04c4722c7d5cacb6e31d9a58133af4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 11 May 2023 20:12:32 +0200 Subject: [PATCH 318/666] build 1344 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 72388ffbd..a56cbe63f 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1342/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1342/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1342/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" }, "framework-espidf": { "type": "framework", From f103b7ec62b4ffb5c00fce3d67b0433f833ecb00 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 11 May 2023 20:23:21 +0200 Subject: [PATCH 319/666] Update RMTWriteNeoPixel.ino --- .../src/RMTWriteNeoPixel.ino | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino b/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino index eee7dcf3b..300b60419 100644 --- a/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino +++ b/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino @@ -1,15 +1,29 @@ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "Arduino.h" +// Copyright 2023 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. -#include "esp32-hal.h" +/** + * @brief This example demonstrates usage of RGB LED driven by RMT + * + * The output is a visual WS2812 RGB LED color moving in a 8 x 4 LED matrix + * Parameters can be changed by the user. In a single LED circuit, it will just blink. + */ // The effect seen in ESP32C3, ESP32S2 and ESP32S3 is like a Blink of RGB LED //#if CONFIG_IDF_TARGET_ESP32S2 //#define BUILTIN_RGBLED_PIN 18 //#elif CONFIG_IDF_TARGET_ESP32S3 -//#define BUILTIN_RGBLED_PIN 48 +//#define BUILTIN_RGBLED_PIN 48 // 48 or 38 //#elif CONFIG_IDF_TARGET_ESP32C3 //#define BUILTIN_RGBLED_PIN 8 //#else @@ -46,27 +60,18 @@ rmt_data_t led_data[NR_OF_ALL_BITS]; -rmt_obj_t* rmt_send = NULL; - -void setup() -{ +void setup() { Serial.begin(115200); - - if ((rmt_send = rmtInit(BUILTIN_RGBLED_PIN, RMT_TX_MODE, RMT_MEM_64)) == NULL) - { + if (!rmtInit(BUILTIN_RGBLED_PIN, RMT_TX_MODE, RMT_MEM_NUM_BLOCKS_1, 10000000)) { Serial.println("init sender failed\n"); } - - float realTick = rmtSetTick(rmt_send, 100); - Serial.printf("real tick set to: %fns\n", realTick); - + Serial.println("real tick set to: 100ns"); } -int color[] = { 0x55, 0x11, 0x77 }; // RGB value +int color[] = { 0x55, 0x11, 0x77 }; // Green Red Blue values int led_index = 0; -void loop() -{ +void loop() { // Init data with only one led ON int led, col, bit; int i=0; @@ -92,9 +97,7 @@ void loop() if ((++led_index)>=NR_OF_LEDS) { led_index = 0; } - - // Send the data - rmtWrite(rmt_send, led_data, NR_OF_ALL_BITS); - + // Send the data and wait until it is done + rmtWrite(BUILTIN_RGBLED_PIN, led_data, NR_OF_ALL_BITS, RMT_WAIT_FOR_EVER); delay(100); } From 9422fc8d090e53f8a40bef20946ee47d51488461 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 13 May 2023 18:04:24 +0200 Subject: [PATCH 320/666] build 1346 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index a56cbe63f..ac7c23a40 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1346/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1346/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1346/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-espidf": { "type": "framework", From 816f928d44b1ea729c3a98af179684077997e812 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 13 May 2023 18:40:51 +0200 Subject: [PATCH 321/666] build 1344 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index ac7c23a40..a56cbe63f 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1346/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1346/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1346/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" }, "framework-espidf": { "type": "framework", From f6a647a8d07d29b65344a54a7271083b8787a8fc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 13 May 2023 20:55:50 +0200 Subject: [PATCH 322/666] build 1349 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index a56cbe63f..ad8c4746b 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1349/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1349/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1344/framework-arduinoespressif32-release_v5.1-c8f0df9461.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1349/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-espidf": { "type": "framework", From d0a4840b646495be6b22d2ef4c2acba7e358b3f0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 15 May 2023 17:52:18 +0200 Subject: [PATCH 323/666] Build 1355 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index ad8c4746b..e4c28b38a 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1349/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1355/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1349/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1355/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1349/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1355/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-espidf": { "type": "framework", From 195e97b3b8f22283bd8bc87579d9cc59ecd9454e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 15 May 2023 17:58:38 +0200 Subject: [PATCH 324/666] Build 1356 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index e4c28b38a..e842636bd 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1355/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1356/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1355/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1356/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1355/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1356/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" }, "framework-espidf": { "type": "framework", From a9360ecb98f57af668b158afc44a21417559335d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 16 May 2023 11:56:34 +0200 Subject: [PATCH 325/666] Update esp32s3camlcd.json --- boards/esp32s3camlcd.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index d35f26798..79231614a 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -36,9 +36,9 @@ ], "name": "ESP32S3 CAM LCD", "upload": { - "flash_size": "4MB", + "flash_size": "8MB", "maximum_ram_size": 327680, - "maximum_size": 16777216, + "maximum_size": 8388608, "require_upload_port": true, "speed": 921600 }, From 37f5ad00412f5a9b38d26c721df25f34c620b2e2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 1 Jun 2023 23:24:26 +0200 Subject: [PATCH 326/666] esptool v4.6.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index e842636bd..23cd21e68 100644 --- a/platform.json +++ b/platform.json @@ -86,7 +86,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.5.1/esptool-4.5.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.6.1/esptool-4.6.1.zip" }, "tool-openocd-esp32": { "type": "debugger", From 3042c27d05a58ac5e20f1579096c44babc4d0be5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 5 Jun 2023 12:17:07 +0200 Subject: [PATCH 327/666] Update platform.json --- platform.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform.json b/platform.json index 23cd21e68..36d765ed0 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.04.00", + "version": "2023.06.05", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,25 +33,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1356/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1379/framework-arduinoespressif32-release_v5.1-ca243adfb2.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1356/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1379/framework-arduinoespressif32-release_v5.1-ca243adfb2.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1356/framework-arduinoespressif32-release_v5.1-3bd955bff8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1379/framework-arduinoespressif32-release_v5.1-ca243adfb2.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.0.20230509/esp-idf-v5.1.0.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.0.20230605/esp-idf-v5.1.0.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 611a432bf47245ecd254413b8e8f8e4ac8d72af6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 12 Jun 2023 16:05:03 +0200 Subject: [PATCH 328/666] esptool v4.6.2 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 36d765ed0..12c1096e9 100644 --- a/platform.json +++ b/platform.json @@ -86,7 +86,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.6.1/esptool-4.6.1.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.6.2/esptool-4.6.2.zip" }, "tool-openocd-esp32": { "type": "debugger", From 2f3241e87abc123a9ce055751ea5f53b6b1f3053 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 15 Jun 2023 12:13:11 +0200 Subject: [PATCH 329/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 12c1096e9..a829798d2 100644 --- a/platform.json +++ b/platform.json @@ -92,7 +92,7 @@ "type": "debugger", "optional": true, "owner": "platformio", - "version": "~2.1200.0" + "version": "~2.1100.0" }, "tool-mkspiffs": { "type": "uploader", From e134750e59971f44add45c0a72c516e74f86faf3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 11:33:32 +0200 Subject: [PATCH 330/666] Update espidf.py --- builder/frameworks/espidf.py | 86 ++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 0134e7d5c..eed06667d 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -24,6 +24,7 @@ import json import subprocess import sys +import shutil import os import pkg_resources @@ -58,6 +59,7 @@ # Required until Arduino switches to v5 IDF5 = platform.get_package_version("framework-espidf").split(".")[1].startswith("5") +IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( "toolchain-%s" % ("riscv32-esp" if mcu == "esp32c3" else ("xtensa-%s" % mcu)) @@ -1094,21 +1096,17 @@ def _get_installed_pip_packages(python_exe_path): return result deps = { - # https://github.com/platformio/platform-espressif32/issues/635 "wheel": ">=0.35.1", - "cryptography": ">=2.1.4,<35.0.0", - "future": ">=0.15.2", - "pyparsing": ">=2.0.3,<2.4.0", - "kconfiglib": "==13.7.1", - "idf-component-manager": "~=1.2", - "esp-idf-kconfig": ">=1.1.0", + # https://github.com/platformio/platformio-core/issues/4614 "urllib3": "<2", + # https://github.com/platformio/platform-espressif32/issues/635 + "cryptography": "~=41.0.1" if IDF5 else ">=2.1.4,<35.0.0", + "future": ">=0.18.3", + "pyparsing": "~=3.0.9" if IDF5 else ">=2.0.3,<2.4.0", + "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", + "idf-component-manager": "~=1.2.3" if IDF5 else "~=1.0", } - if IDF5: - # Remove specific versions for IDF5 as not required - deps = {dep: "" for dep in deps} - python_exe_path = get_python_exe() installed_packages = _get_installed_pip_packages(python_exe_path) packages_to_install = [] @@ -1152,40 +1150,71 @@ def _get_installed_pip_packages(python_exe_path): ) ) +def get_idf_venv_dir(): + # The name of the IDF venv contains the IDF version to avoid possible conflicts and + # unnecessary reinstallation of Python dependencies in cases when Arduino + # as an IDF component requires a different version of the IDF package and + # hence a different set of Python deps or their versions + idf_version = get_original_version(platform.get_package_version("framework-espidf")) + return os.path.join( + env.subst("$PROJECT_CORE_DIR"), "penv", ".espidf-" + idf_version + ) + +def ensure_python_venv_available(): + + def _is_venv_outdated(venv_data_file): + try: + with open(venv_data_file, "r", encoding="utf8") as fp: + venv_data = json.load(fp) + if venv_data.get("version", "") != IDF_ENV_VERSION: + return True + return False + except: + return True -def get_python_exe(): def _create_venv(venv_dir): pip_path = os.path.join( venv_dir, "Scripts" if IS_WINDOWS else "bin", "pip" + (".exe" if IS_WINDOWS else ""), ) - if not os.path.isfile(pip_path): - # Use the built-in PlatformIO Python to create a standalone IDF virtual env - env.Execute( - env.VerboseAction( - '"$PYTHONEXE" -m venv --clear "%s"' % venv_dir, - "Creating a virtual environment for IDF Python dependencies", + + if os.path.isdir(venv_dir): + try: + print("Removing an oudated IDF virtual environment") + shutil.rmtree(venv_dir) + except OSError: + print( + "Error: Cannot remove an outdated IDF virtual environment. " \ + "Please remove the `%s` folder manually!" % venv_dir ) + env.Exit(1) + + # Use the built-in PlatformIO Python to create a standalone IDF virtual env + env.Execute( + env.VerboseAction( + '"$PYTHONEXE" -m venv --clear "%s"' % venv_dir, + "Creating a new virtual environment for IDF Python dependencies", ) + ) assert os.path.isfile( pip_path - ), "Error: Failed to create a proper virtual environment. Missing the pip binary!" + ), "Error: Failed to create a proper virtual environment. Missing the `pip` binary!" - # The name of the IDF venv contains the IDF version to avoid possible conflicts and - # unnecessary reinstallation of Python dependencies in cases when Arduino - # as an IDF component requires a different version of the IDF package and - # hence a different set of Python deps or their versions - idf_version = get_original_version(platform.get_package_version("framework-espidf")) - venv_dir = os.path.join( - env.subst("$PROJECT_CORE_DIR"), "penv", ".espidf-" + idf_version) - if not os.path.isdir(venv_dir): + venv_dir = get_idf_venv_dir() + venv_data_file = os.path.join(venv_dir, "pio-idf-venv.json") + if not os.path.isfile(venv_data_file) or _is_venv_outdated(venv_data_file): _create_venv(venv_dir) + with open(venv_data_file, "w", encoding="utf8") as fp: + venv_info = {"version": IDF_ENV_VERSION} + json.dump(venv_info, fp, indent=2) + +def get_python_exe(): python_exe_path = os.path.join( - venv_dir, + get_idf_venv_dir(), "Scripts" if IS_WINDOWS else "bin", "python" + (".exe" if IS_WINDOWS else ""), ) @@ -1201,6 +1230,7 @@ def _create_venv(venv_dir): # ESP-IDF requires Python packages with specific versions in a virtual environment # +ensure_python_venv_available() install_python_deps() # ESP-IDF package doesn't contain .git folder, instead package version is specified From c28d2d1efd29978abf076a98fd21542c4895bf3a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 13:11:16 +0200 Subject: [PATCH 331/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index a829798d2..c2bcfc355 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1379/framework-arduinoespressif32-release_v5.1-ca243adfb2.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1398/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1379/framework-arduinoespressif32-release_v5.1-ca243adfb2.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1398/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1379/framework-arduinoespressif32-release_v5.1-ca243adfb2.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1398/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" }, "framework-espidf": { "type": "framework", From 7687834592dddcb4f75a09c2283839dc84f39147 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 13:27:05 +0200 Subject: [PATCH 332/666] Create esp32-c6-devkitc-1.json --- boards/esp32-c6-devkitc-1.json | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 boards/esp32-c6-devkitc-1.json diff --git a/boards/esp32-c6-devkitc-1.json b/boards/esp32-c6-devkitc-1.json new file mode 100644 index 000000000..09bbd89c9 --- /dev/null +++ b/boards/esp32-c6-devkitc-1.json @@ -0,0 +1,29 @@ +{ + "build": { + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6", + "variant": "esp32c6" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "espidf" + ], + "name": "Espressif ESP32-C6-DevKitC-1", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/index.html", + "vendor": "Espressif" +} From 2184186ef3e9f38d106602f1d10ba84f1adf83e6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 13:31:18 +0200 Subject: [PATCH 333/666] c6 --- builder/frameworks/espidf.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index eed06667d..99d07616e 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -62,7 +62,7 @@ IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" % ("riscv32-esp" if mcu == "esp32c3" else ("xtensa-%s" % mcu)) + "toolchain-%s" % ("riscv32-esp" if mcu in ("esp32c3","esp32c6") else ("xtensa-%s" % mcu)) ) @@ -234,7 +234,7 @@ def populate_idf_env_vars(idf_env): os.path.dirname(get_python_exe()), ] - if mcu != "esp32c3": + if mcu not in ("esp32c3", "esp32c6"): additional_packages.append( os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), ) @@ -489,7 +489,7 @@ def extract_linker_script_fragments(framework_components_dir, sdk_config): sys.stderr.write("Error: Failed to extract paths to linker script fragments\n") env.Exit(1) - if mcu == "esp32c3": + if mcu in ("esp32c3", "esp32c6"): result.append(os.path.join(framework_components_dir, "riscv", "linker.lf")) # Add extra linker fragments @@ -1499,7 +1499,7 @@ def _skip_prj_source_files(node): ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ("esp32c3", "esp32s3") else "0x1000", + "0x0" if mcu in ("esp32c3", "esp32c6", "esp32s3") else "0x1000", ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), @@ -1578,7 +1578,7 @@ def _skip_prj_source_files(node): # ulp_dir = os.path.join(PROJECT_DIR, "ulp") -if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu != "esp32c3": +if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c3", "esp32c6"): env.SConscript("ulp.py", exports="env sdk_config project_config idf_variant") # From 75a80992e5d90cd1ab81994ce918c8a3a5d3a93a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 13:32:02 +0200 Subject: [PATCH 334/666] Update main.py --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index 36354b6e9..95f84b543 100644 --- a/builder/main.py +++ b/builder/main.py @@ -203,7 +203,7 @@ def __fetch_fs_size(target, source, env): mcu = board.get("build.mcu", "esp32") toolchain_arch = "xtensa-%s" % mcu filesystem = board.get("build.filesystem", "spiffs") -if mcu == "esp32c3": +if mcu in ("esp32c3", "esp32c6"): toolchain_arch = "riscv32-esp" if "INTEGRATION_EXTRA_DATA" not in env: From 783a9254fd46553cd349908be9591827113d5c61 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 16:17:21 +0200 Subject: [PATCH 335/666] Update _embed_files.py --- builder/frameworks/_embed_files.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index 5469e3bce..c89dc4338 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -110,14 +110,14 @@ def transform_to_asm(target, source, env): " ".join( [ "riscv32-esp-elf-objcopy" - if mcu == "esp32c3" + if mcu in ("esp32c3", "esp32c6") else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", - "elf32-littleriscv" if mcu == "esp32c3" else "elf32-xtensa-le", + "elf32-littleriscv" if mcu in ("esp32c3","esp32c6") else "elf32-xtensa-le", "--binary-architecture", - "riscv" if mcu == "esp32c3" else "xtensa", + "riscv" if mcu in ("esp32c3","esp32c6") else "xtensa", "--rename-section", ".data=.rodata.embedded", "$SOURCE", From e7b42e9648fc339c78aee42eec4f6648d4cda969 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 16:25:18 +0200 Subject: [PATCH 336/666] Update platform.py --- platform.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.py b/platform.py index deeab0537..e73e1d1ec 100644 --- a/platform.py +++ b/platform.py @@ -81,10 +81,10 @@ def configure_default_packages(self, variables, targets): else: self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) - if mcu in ("esp32s2", "esp32s3", "esp32c3"): - if mcu == "esp32c3": + if mcu in ("esp32s2", "esp32s3", "esp32c3", "esp32c6"): + if mcu in ("esp32c3", "esp32c6"): self.packages.pop("toolchain-esp32ulp", None) - # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP + # RISC-V based toolchain for ESP32C3, ESP32C6 ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp"]["optional"] = False return super().configure_default_packages(variables, targets) @@ -124,7 +124,7 @@ def _add_dynamic_options(self, board): "tumpa", ] - if board.get("build.mcu", "") in ("esp32c3", "esp32s3"): + if board.get("build.mcu", "") in ("esp32c3", "esp32c6", "esp32s3"): supported_debug_tools.append("esp-builtin") upload_protocol = board.manifest.get("upload", {}).get("protocol") From 59149b0d1c2b3a524e8d13c1670d231c5950a4ed Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 16:36:42 +0200 Subject: [PATCH 337/666] esp-idf-kconfig is needed --- builder/frameworks/espidf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 99d07616e..55c7ff16e 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1103,6 +1103,7 @@ def _get_installed_pip_packages(python_exe_path): "cryptography": "~=41.0.1" if IDF5 else ">=2.1.4,<35.0.0", "future": ">=0.18.3", "pyparsing": "~=3.0.9" if IDF5 else ">=2.0.3,<2.4.0", + "esp-idf-kconfig": "~=1.1.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", "idf-component-manager": "~=1.2.3" if IDF5 else "~=1.0", } From b743d1fe462c0e6db68b4dc4ec1c60eaf74638a9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 16:43:20 +0200 Subject: [PATCH 338/666] Update platformio.ini --- examples/arduino-blink/platformio.ini | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 81c2de64f..4f7de520f 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -16,10 +16,10 @@ build_flags = ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led -D LED_BUILTIN=2 -[env:esp32doit-devkit-v1] +[env:esp32-c6-devkitc-1] platform = espressif32 framework = arduino -board = esp32doit-devkit-v1 +board = esp32-c6-devkitc-1 monitor_speed = 115200 [env:esp32-solo1] @@ -34,14 +34,3 @@ platform = espressif32 framework = arduino board = esp32doit-devkit-v1 build_flags = -DFRAMEWORK_ARDUINO_ITEAD - -[env:lolin32] -platform = espressif32 -framework = arduino -board = lolin32 -monitor_speed = 115200 - -[env:ttgo-lora32-v21] -platform = espressif32 -framework = arduino -board = ttgo-lora32-v21 From af5c4202c27295ba61227fd339b8cbdd5dcd9fd2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 16:48:10 +0200 Subject: [PATCH 339/666] Arduino for esp32-c6-devkitc-1 --- boards/esp32-c6-devkitc-1.json | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/esp32-c6-devkitc-1.json b/boards/esp32-c6-devkitc-1.json index 09bbd89c9..b82e07f8d 100644 --- a/boards/esp32-c6-devkitc-1.json +++ b/boards/esp32-c6-devkitc-1.json @@ -14,6 +14,7 @@ "openocd_target": "esp32c6.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Espressif ESP32-C6-DevKitC-1", From 3573643e16ba196b4acdb7e0f03823a9c2f28f78 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 16:54:01 +0200 Subject: [PATCH 340/666] add c6 --- examples/espidf-blink/platformio.ini | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/examples/espidf-blink/platformio.ini b/examples/espidf-blink/platformio.ini index d10e91722..35b3b70a5 100644 --- a/examples/espidf-blink/platformio.ini +++ b/examples/espidf-blink/platformio.ini @@ -18,3 +18,12 @@ build_flags = -D CONFIG_BLINK_LED_GPIO=2 -D CONFIG_BLINK_PERIOD=1000 +[env:esp32-c6-devkitc-1] +platform = espressif32 +framework = espidf +board = esp32-c6-devkitc-1 +monitor_speed = 115200 +build_flags = + -D CONFIG_BLINK_GPIO=2 + -D CONFIG_BLINK_LED_GPIO=2 + -D CONFIG_BLINK_PERIOD=1000 From 8a74ec816b1f8319e919f4c3cf4d0ebe66de4382 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Jun 2023 18:27:24 +0200 Subject: [PATCH 341/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index c2bcfc355..d3b50fe9f 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1398/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1399/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1398/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1399/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1398/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1399/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" }, "framework-espidf": { "type": "framework", From d56a7a030df41920d3d3cfbe2755889901f16e33 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 21 Jun 2023 08:40:47 +0200 Subject: [PATCH 342/666] build 1400 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index d3b50fe9f..74a1774a0 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1399/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1400/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1399/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1400/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1399/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1400/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" }, "framework-espidf": { "type": "framework", From 404160f669c14987d2b36149f4fb778a0085fde3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 23 Jun 2023 17:10:44 +0200 Subject: [PATCH 343/666] use correct import --- monitor/filter_exception_decoder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index a580550c9..ecb4ef7cd 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -17,7 +17,7 @@ import subprocess import sys -from platformio.project.exception import PlatformioException +from platformio.exception import PlatformioException from platformio.public import ( DeviceMonitorFilterBase, load_build_metadata, From f7dc77cc00e61bca5df650713e975aff956da38b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 1 Jul 2023 11:02:19 +0200 Subject: [PATCH 344/666] Release IDF 5.1.0 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 74a1774a0..f7dad66ae 100644 --- a/platform.json +++ b/platform.json @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.0.20230605/esp-idf-v5.1.0.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.0/esp-idf-v5.1.0.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 95da377f8519b4c4b3ed97dad054e63fc9c6cdb6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 2 Jul 2023 15:59:27 +0200 Subject: [PATCH 345/666] ESP32-H2 support --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index f7dad66ae..0d30b8317 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1400/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1404/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1400/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1404/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1400/framework-arduinoespressif32-release_v5.1-f6e43248a8.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1404/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" }, "framework-espidf": { "type": "framework", From 572d4ce4bfba767833530591d614364c72bc2a34 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:28:45 +0200 Subject: [PATCH 346/666] Create esp32-h2-devkitm-1.json --- boards/esp32-h2-devkitm-1.json | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 boards/esp32-h2-devkitm-1.json diff --git a/boards/esp32-h2-devkitm-1.json b/boards/esp32-h2-devkitm-1.json new file mode 100644 index 000000000..423310d6a --- /dev/null +++ b/boards/esp32-h2-devkitm-1.json @@ -0,0 +1,30 @@ +{ + "build": { + "core": "esp32", + "f_cpu": "96000000L", + "f_flash": "64000000L", + "flash_mode": "qio", + "mcu": "esp32h2", + "variant": "esp32h2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32h2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-H2-DevKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32h2/esp32-h2-devkitm-1/index.html", + "vendor": "Espressif" +} From b41e2253c892694411cb8186a76e91deba7df563 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:30:28 +0200 Subject: [PATCH 347/666] add h2 to examples blink --- examples/arduino-blink/platformio.ini | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 4f7de520f..126adf36f 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -22,6 +22,12 @@ framework = arduino board = esp32-c6-devkitc-1 monitor_speed = 115200 +[env:esp32-h2-devkitm-1] +platform = espressif32 +framework = arduino +board = esp32-h2-devkitm-1 +monitor_speed = 115200 + [env:esp32-solo1] platform = espressif32 framework = arduino From eaebbc4fe87b008ca001e3d0e25a2a1ad0eaf6cb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:41:53 +0200 Subject: [PATCH 348/666] Update esp32-h2-devkitm-1.json --- boards/esp32-h2-devkitm-1.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/boards/esp32-h2-devkitm-1.json b/boards/esp32-h2-devkitm-1.json index 423310d6a..69adbcf72 100644 --- a/boards/esp32-h2-devkitm-1.json +++ b/boards/esp32-h2-devkitm-1.json @@ -2,7 +2,14 @@ "build": { "core": "esp32", "f_cpu": "96000000L", - "f_flash": "64000000L", + "f_flash": "48000000L", + "flash_freq": "64000000L", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], "flash_mode": "qio", "mcu": "esp32h2", "variant": "esp32h2" @@ -20,6 +27,7 @@ "name": "Espressif ESP32-H2-DevKit", "upload": { "flash_size": "4MB", + "flash_freq": "64000000L", "maximum_ram_size": 327680, "maximum_size": 4194304, "require_upload_port": true, From 903a155515cc57400cad85196192172b0128debd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:57:22 +0200 Subject: [PATCH 349/666] Update esp32-h2-devkitm-1.json --- boards/esp32-h2-devkitm-1.json | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/esp32-h2-devkitm-1.json b/boards/esp32-h2-devkitm-1.json index 69adbcf72..9c72dfcdf 100644 --- a/boards/esp32-h2-devkitm-1.json +++ b/boards/esp32-h2-devkitm-1.json @@ -4,6 +4,7 @@ "f_cpu": "96000000L", "f_flash": "48000000L", "flash_freq": "64000000L", + "img_freq": "48000000L", "hwids": [ [ "0x303A", From bc55cf4d57f61253fba871b7bd490240ac2147a7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:59:42 +0200 Subject: [PATCH 350/666] Update esp32-h2-devkitm-1.json --- boards/esp32-h2-devkitm-1.json | 1 - 1 file changed, 1 deletion(-) diff --git a/boards/esp32-h2-devkitm-1.json b/boards/esp32-h2-devkitm-1.json index 9c72dfcdf..baf626742 100644 --- a/boards/esp32-h2-devkitm-1.json +++ b/boards/esp32-h2-devkitm-1.json @@ -2,7 +2,6 @@ "build": { "core": "esp32", "f_cpu": "96000000L", - "f_flash": "48000000L", "flash_freq": "64000000L", "img_freq": "48000000L", "hwids": [ From 2b10d9f152304f414d3728a970dd68e010c6f14b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jul 2023 18:03:09 +0200 Subject: [PATCH 351/666] no H2 in CI tests --- examples/arduino-blink/platformio.ini | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 126adf36f..8307dea1b 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -22,11 +22,11 @@ framework = arduino board = esp32-c6-devkitc-1 monitor_speed = 115200 -[env:esp32-h2-devkitm-1] -platform = espressif32 -framework = arduino -board = esp32-h2-devkitm-1 -monitor_speed = 115200 +;[env:esp32-h2-devkitm-1] +;platform = espressif32 +;framework = arduino +;board = esp32-h2-devkitm-1 +;monitor_speed = 115200 [env:esp32-solo1] platform = espressif32 From 9054e17b4c52028d4a2c2153f29840be7142010e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:23:12 +0200 Subject: [PATCH 352/666] Change upload lash params https://github.com/espressif/arduino-esp32/commit/645d5ce9ce93467ccaa8101cfa2b9a7ed7bdf646 --- builder/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builder/main.py b/builder/main.py index 95f84b543..483abe0b1 100644 --- a/builder/main.py +++ b/builder/main.py @@ -273,8 +273,8 @@ def __fetch_fs_size(target, source, env): '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", "--dont-append-digest", - "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_mode", "keep", + "--flash_freq", "keep", "--flash_size", board.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" ]), "Building $TARGET"), @@ -407,8 +407,8 @@ def __fetch_fs_size(target, source, env): "--before", board.get("upload.before_reset", "default_reset"), "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", - "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_mode", "keep", + "--flash_freq", "keep", "--flash_size", board.get("upload.flash_size", "detect") ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE' From a465b68c9dd478e081ad2d41a6a5dc47d15dc338 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:27:28 +0200 Subject: [PATCH 353/666] part revert flash settings from last commit --- builder/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index 483abe0b1..b2cf40e5e 100644 --- a/builder/main.py +++ b/builder/main.py @@ -273,7 +273,7 @@ def __fetch_fs_size(target, source, env): '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", "--dont-append-digest", - "--flash_mode", "keep", + "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "keep", "--flash_size", board.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" @@ -407,7 +407,7 @@ def __fetch_fs_size(target, source, env): "--before", board.get("upload.before_reset", "default_reset"), "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", - "--flash_mode", "keep", + "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "keep", "--flash_size", board.get("upload.flash_size", "detect") ], From db10709744bd3628f7a80f6679bf9e76a03efdc4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:33:03 +0200 Subject: [PATCH 354/666] only "keep" with upload with esptool --- builder/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builder/main.py b/builder/main.py index b2cf40e5e..b6632f15e 100644 --- a/builder/main.py +++ b/builder/main.py @@ -274,7 +274,7 @@ def __fetch_fs_size(target, source, env): "--chip", mcu, "elf2image", "--dont-append-digest", "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "keep", + "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" ]), "Building $TARGET"), @@ -407,7 +407,7 @@ def __fetch_fs_size(target, source, env): "--before", board.get("upload.before_reset", "default_reset"), "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", - "--flash_mode", "${__get_board_flash_mode(__env__)}", + "--flash_mode", "keep", "--flash_freq", "keep", "--flash_size", board.get("upload.flash_size", "detect") ], @@ -425,8 +425,8 @@ def __fetch_fs_size(target, source, env): "--before", board.get("upload.before_reset", "default_reset"), "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", - "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_mode", "keep", + "--flash_freq", "keep", "--flash_size", board.get("upload.flash_size", "detect"), "$FS_START" ], From 21488eb9da2cbf2fe9057d1233e75cdbc9301021 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:52:11 +0200 Subject: [PATCH 355/666] fix h2 boards.json --- boards/esp32-h2-devkitm-1.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/boards/esp32-h2-devkitm-1.json b/boards/esp32-h2-devkitm-1.json index baf626742..35ef2c9bf 100644 --- a/boards/esp32-h2-devkitm-1.json +++ b/boards/esp32-h2-devkitm-1.json @@ -1,18 +1,21 @@ { "build": { + "arduino": { + "ldscript": "esp32h2_out.ld" + }, "core": "esp32", "f_cpu": "96000000L", "flash_freq": "64000000L", "img_freq": "48000000L", + "flash_mode": "qio", + "mcu": "esp32h2", + "variant": "esp32h2" "hwids": [ [ "0x303A", "0x1001" ] - ], - "flash_mode": "qio", - "mcu": "esp32h2", - "variant": "esp32h2" + ] }, "connectivity": [ "wifi" From b1e2e3c751eba9ee6c35e5972797ea7a23ae687b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:55:10 +0200 Subject: [PATCH 356/666] Update esp32-h2-devkitm-1.json --- boards/esp32-h2-devkitm-1.json | 1 - 1 file changed, 1 deletion(-) diff --git a/boards/esp32-h2-devkitm-1.json b/boards/esp32-h2-devkitm-1.json index 35ef2c9bf..0ae650169 100644 --- a/boards/esp32-h2-devkitm-1.json +++ b/boards/esp32-h2-devkitm-1.json @@ -30,7 +30,6 @@ "name": "Espressif ESP32-H2-DevKit", "upload": { "flash_size": "4MB", - "flash_freq": "64000000L", "maximum_ram_size": 327680, "maximum_size": 4194304, "require_upload_port": true, From ac0c61c50902aca02ef459b2cdb298cef95f6c3d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 12:06:17 +0200 Subject: [PATCH 357/666] Use "img_freq" for flash_freq when in boards.json --- builder/main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/builder/main.py b/builder/main.py index b6632f15e..d8f8811b3 100644 --- a/builder/main.py +++ b/builder/main.py @@ -74,6 +74,9 @@ def _get_board_memory_type(env): def _get_board_f_flash(env): frequency = env.subst("$BOARD_F_FLASH") frequency = str(frequency).replace("L", "") + img_freq = env.BoardConfig().get("build.arduino.img_freq", "") + if not "" in img_freq: + frequency = str(img_freq).replace("L", "") return str(int(int(frequency) / 1000000)) + "m" From f3d8fe0ecdf70910ac38ef9b0e6ddcfedc94eda8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 12:12:26 +0200 Subject: [PATCH 358/666] try build for H2 --- examples/arduino-blink/platformio.ini | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 8307dea1b..126adf36f 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -22,11 +22,11 @@ framework = arduino board = esp32-c6-devkitc-1 monitor_speed = 115200 -;[env:esp32-h2-devkitm-1] -;platform = espressif32 -;framework = arduino -;board = esp32-h2-devkitm-1 -;monitor_speed = 115200 +[env:esp32-h2-devkitm-1] +platform = espressif32 +framework = arduino +board = esp32-h2-devkitm-1 +monitor_speed = 115200 [env:esp32-solo1] platform = espressif32 From 094cb6e243399cdb114846c8b3f2f3fb6dc9b61f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 12:15:58 +0200 Subject: [PATCH 359/666] Update esp32-h2-devkitm-1.json --- boards/esp32-h2-devkitm-1.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/esp32-h2-devkitm-1.json b/boards/esp32-h2-devkitm-1.json index 0ae650169..742344b16 100644 --- a/boards/esp32-h2-devkitm-1.json +++ b/boards/esp32-h2-devkitm-1.json @@ -9,7 +9,7 @@ "img_freq": "48000000L", "flash_mode": "qio", "mcu": "esp32h2", - "variant": "esp32h2" + "variant": "esp32h2", "hwids": [ [ "0x303A", From 298dc90b7a364b04f785584cef8a297c2b519e8c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 12:25:59 +0200 Subject: [PATCH 360/666] Update main.py --- builder/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index d8f8811b3..802481694 100644 --- a/builder/main.py +++ b/builder/main.py @@ -74,9 +74,10 @@ def _get_board_memory_type(env): def _get_board_f_flash(env): frequency = env.subst("$BOARD_F_FLASH") frequency = str(frequency).replace("L", "") - img_freq = env.BoardConfig().get("build.arduino.img_freq", "") + img_freq = str(env.BoardConfig().get("build.arduino.img_freq", "")) if not "" in img_freq: frequency = str(img_freq).replace("L", "") + print("Frequency img_frq: ", img_freq) return str(int(int(frequency) / 1000000)) + "m" From b7e27e2d31a71d33d8bde483c0f1af16bf8d1331 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 13:00:22 +0200 Subject: [PATCH 361/666] h2 --- builder/frameworks/_embed_files.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index c89dc4338..1b685ff82 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -110,12 +110,12 @@ def transform_to_asm(target, source, env): " ".join( [ "riscv32-esp-elf-objcopy" - if mcu in ("esp32c3", "esp32c6") + if mcu in ("esp32c3", "esp32c6", "esp32h2") else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", - "elf32-littleriscv" if mcu in ("esp32c3","esp32c6") else "elf32-xtensa-le", + "elf32-littleriscv" if mcu in ("esp32c3","esp32c6","esp32h2") else "elf32-xtensa-le", "--binary-architecture", "riscv" if mcu in ("esp32c3","esp32c6") else "xtensa", "--rename-section", From 7d12996e6116607cf5abe88e8e6c82237a7a3368 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 13:02:36 +0200 Subject: [PATCH 362/666] h2 support --- builder/frameworks/espidf.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 55c7ff16e..a225a7d29 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -62,7 +62,7 @@ IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" % ("riscv32-esp" if mcu in ("esp32c3","esp32c6") else ("xtensa-%s" % mcu)) + "toolchain-%s" % ("riscv32-esp" if mcu in ("esp32c3","esp32c6","esp32h2") else ("xtensa-%s" % mcu)) ) @@ -234,7 +234,7 @@ def populate_idf_env_vars(idf_env): os.path.dirname(get_python_exe()), ] - if mcu not in ("esp32c3", "esp32c6"): + if mcu not in ("esp32c3", "esp32c6","esp32h2"): additional_packages.append( os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), ) @@ -489,7 +489,7 @@ def extract_linker_script_fragments(framework_components_dir, sdk_config): sys.stderr.write("Error: Failed to extract paths to linker script fragments\n") env.Exit(1) - if mcu in ("esp32c3", "esp32c6"): + if mcu in ("esp32c3", "esp32c6", "esp32h2"): result.append(os.path.join(framework_components_dir, "riscv", "linker.lf")) # Add extra linker fragments @@ -1500,7 +1500,7 @@ def _skip_prj_source_files(node): ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ("esp32c3", "esp32c6", "esp32s3") else "0x1000", + "0x0" if mcu in ("esp32c3", "esp32c6", "esp32s3", "esp32h2") else "0x1000", ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), @@ -1579,7 +1579,7 @@ def _skip_prj_source_files(node): # ulp_dir = os.path.join(PROJECT_DIR, "ulp") -if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c3", "esp32c6"): +if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c3", "esp32c6", "esp32h2"): env.SConscript("ulp.py", exports="env sdk_config project_config idf_variant") # From ac69746db215b361bbb671c667438369a8e35297 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 13:03:51 +0200 Subject: [PATCH 363/666] support h2 --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index 802481694..0b8dce2b5 100644 --- a/builder/main.py +++ b/builder/main.py @@ -207,7 +207,7 @@ def __fetch_fs_size(target, source, env): mcu = board.get("build.mcu", "esp32") toolchain_arch = "xtensa-%s" % mcu filesystem = board.get("build.filesystem", "spiffs") -if mcu in ("esp32c3", "esp32c6"): +if mcu in ("esp32c3", "esp32c6", "esp32h2"): toolchain_arch = "riscv32-esp" if "INTEGRATION_EXTRA_DATA" not in env: From 87606b32946f12b423c9f0e9e5b28ff02f3c96fb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 13:06:11 +0200 Subject: [PATCH 364/666] h2 support --- platform.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.py b/platform.py index e73e1d1ec..4e7abb86b 100644 --- a/platform.py +++ b/platform.py @@ -81,8 +81,8 @@ def configure_default_packages(self, variables, targets): else: self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) - if mcu in ("esp32s2", "esp32s3", "esp32c3", "esp32c6"): - if mcu in ("esp32c3", "esp32c6"): + if mcu in ("esp32s2", "esp32s3", "esp32c3", "esp32c6", "esp32h2"): + if mcu in ("esp32c3", "esp32c6", "esp32h2"): self.packages.pop("toolchain-esp32ulp", None) # RISC-V based toolchain for ESP32C3, ESP32C6 ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp"]["optional"] = False @@ -124,7 +124,7 @@ def _add_dynamic_options(self, board): "tumpa", ] - if board.get("build.mcu", "") in ("esp32c3", "esp32c6", "esp32s3"): + if board.get("build.mcu", "") in ("esp32c3", "esp32c6", "esp32s3", "esp32h2"): supported_debug_tools.append("esp-builtin") upload_protocol = board.manifest.get("upload", {}).get("protocol") From ceec6f5e57bcb2d2401c120a7ee5619085ac169a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 14:44:33 +0200 Subject: [PATCH 365/666] Update main.py --- builder/main.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/builder/main.py b/builder/main.py index 0b8dce2b5..d054c8c39 100644 --- a/builder/main.py +++ b/builder/main.py @@ -74,10 +74,6 @@ def _get_board_memory_type(env): def _get_board_f_flash(env): frequency = env.subst("$BOARD_F_FLASH") frequency = str(frequency).replace("L", "") - img_freq = str(env.BoardConfig().get("build.arduino.img_freq", "")) - if not "" in img_freq: - frequency = str(img_freq).replace("L", "") - print("Frequency img_frq: ", img_freq) return str(int(int(frequency) / 1000000)) + "m" From 37cafcc4745c0764f931fa0c6a26596041ba58ba Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 15:24:26 +0200 Subject: [PATCH 366/666] Working h2 compile --- builder/main.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index d054c8c39..a7b46a8e4 100644 --- a/builder/main.py +++ b/builder/main.py @@ -70,6 +70,15 @@ def _get_board_memory_type(env): ), ) +def _get_board_img_freq(env): + board_config = env.BoardConfig() + img_freq = board_config.get("build.img_freq", "") + img_freq = str(img_freq).replace("L", "") + print("img_freq: ", img_freq) + if img_freq =="": + img_freq = env.subst("$BOARD_F_FLASH") + img_freq = str(img_freq).replace("L", "") + return str(int(int(img_freq) / 1000000)) + "m" def _get_board_f_flash(env): frequency = env.subst("$BOARD_F_FLASH") @@ -211,6 +220,7 @@ def __fetch_fs_size(target, source, env): env.Replace( __get_board_boot_mode=_get_board_boot_mode, + __get_board_img_freq=_get_board_img_freq, __get_board_f_flash=_get_board_f_flash, __get_board_flash_mode=_get_board_flash_mode, __get_board_memory_type=_get_board_memory_type, @@ -274,7 +284,7 @@ def __fetch_fs_size(target, source, env): "--chip", mcu, "elf2image", "--dont-append-digest", "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_freq", "${__get_board_img_freq(__env__)}", "--flash_size", board.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" ]), "Building $TARGET"), From 5211f5b60f40712c1cd4c5fc39e91fdf7b1375d2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:22:00 +0200 Subject: [PATCH 367/666] Update esp32-h2-devkitm-1.json --- boards/esp32-h2-devkitm-1.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/esp32-h2-devkitm-1.json b/boards/esp32-h2-devkitm-1.json index 742344b16..8e8ca1f3e 100644 --- a/boards/esp32-h2-devkitm-1.json +++ b/boards/esp32-h2-devkitm-1.json @@ -5,7 +5,7 @@ }, "core": "esp32", "f_cpu": "96000000L", - "flash_freq": "64000000L", + "f_flash": "64000000L", "img_freq": "48000000L", "flash_mode": "qio", "mcu": "esp32h2", From 24b081d7f4ffc68abe5a186b9f72a56599631689 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:28:38 +0200 Subject: [PATCH 368/666] Update main.py --- builder/main.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/builder/main.py b/builder/main.py index a7b46a8e4..37f98f021 100644 --- a/builder/main.py +++ b/builder/main.py @@ -73,15 +73,15 @@ def _get_board_memory_type(env): def _get_board_img_freq(env): board_config = env.BoardConfig() img_freq = board_config.get("build.img_freq", "") - img_freq = str(img_freq).replace("L", "") - print("img_freq: ", img_freq) if img_freq =="": - img_freq = env.subst("$BOARD_F_FLASH") - img_freq = str(img_freq).replace("L", "") + img_freq = board_config.get("build.f_flash", "") + img_freq = str(img_freq).replace("L", "") return str(int(int(img_freq) / 1000000)) + "m" + def _get_board_f_flash(env): - frequency = env.subst("$BOARD_F_FLASH") + board_config = env.BoardConfig() + frequency = board_config.get("build.f_flash", "") frequency = str(frequency).replace("L", "") return str(int(int(frequency) / 1000000)) + "m" @@ -220,8 +220,8 @@ def __fetch_fs_size(target, source, env): env.Replace( __get_board_boot_mode=_get_board_boot_mode, - __get_board_img_freq=_get_board_img_freq, __get_board_f_flash=_get_board_f_flash, + __get_board_img_freq=_get_board_img_freq, __get_board_flash_mode=_get_board_flash_mode, __get_board_memory_type=_get_board_memory_type, From 09fa35a91501bc7942fc505fc81060c9603faaf1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jul 2023 17:08:41 +0200 Subject: [PATCH 369/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 0d30b8317..eec9365d2 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1404/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1406/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1404/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1406/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1404/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1406/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" }, "framework-espidf": { "type": "framework", From b5b676860c4a4b813dcee377bfc66bd75b07a1bc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 7 Jul 2023 17:24:10 +0200 Subject: [PATCH 370/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index eec9365d2..73100b433 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1406/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1407/framework-arduinoespressif32-release_v5.1-6105f97b10.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1406/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1407/framework-arduinoespressif32-release_v5.1-6105f97b10.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1406/framework-arduinoespressif32-release_v5.1-79f24ab233.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1407/framework-arduinoespressif32-release_v5.1-6105f97b10.zip" }, "framework-espidf": { "type": "framework", From d99aa8a9dc3fcb137c73f4c179f6893637b2b4b6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Jul 2023 19:32:05 +0200 Subject: [PATCH 371/666] fix ULP example --- examples/espidf-ulp/main/CMakeLists.txt | 4 ++-- examples/espidf-ulp/main/component.mk | 24 --------------------- examples/espidf-ulp/main/ulp_example_main.c | 18 ++++++++++------ examples/espidf-ulp/ulp/pulse_cnt.S | 0 examples/espidf-ulp/ulp/wake_up.S | 16 +++++++++++++- 5 files changed, 29 insertions(+), 33 deletions(-) mode change 100644 => 100755 examples/espidf-ulp/main/CMakeLists.txt delete mode 100644 examples/espidf-ulp/main/component.mk mode change 100644 => 100755 examples/espidf-ulp/main/ulp_example_main.c mode change 100644 => 100755 examples/espidf-ulp/ulp/pulse_cnt.S mode change 100644 => 100755 examples/espidf-ulp/ulp/wake_up.S diff --git a/examples/espidf-ulp/main/CMakeLists.txt b/examples/espidf-ulp/main/CMakeLists.txt old mode 100644 new mode 100755 index 51dd8d369..6ded342e1 --- a/examples/espidf-ulp/main/CMakeLists.txt +++ b/examples/espidf-ulp/main/CMakeLists.txt @@ -10,11 +10,11 @@ set(ulp_app_name ulp_${COMPONENT_NAME}) # 2. Specify all assembly source files. # Files should be placed into a separate directory (in this case, ulp/), # which should not be added to COMPONENT_SRCS. -set(ulp_s_sources "ulp/pulse_cnt.S" "ulp/wake_up.S") +set(ulp_s_sources "../ulp/pulse_cnt.S" "../ulp/wake_up.S") # # 3. List all the component source files which include automatically # generated ULP export file, ${ulp_app_name}.h: -set(ulp_exp_dep_srcs "../ulp_example_main.c") +set(ulp_exp_dep_srcs "ulp_example_main.c") # # 4. Call function to build ULP binary and embed in project using the argument # values above. diff --git a/examples/espidf-ulp/main/component.mk b/examples/espidf-ulp/main/component.mk deleted file mode 100644 index 22e0a859a..000000000 --- a/examples/espidf-ulp/main/component.mk +++ /dev/null @@ -1,24 +0,0 @@ -# -# ULP support additions to component makefile. -# -# 1. ULP_APP_NAME must be unique (if multiple components use ULP) -# Default value, override if necessary: -ULP_APP_NAME ?= ulp_$(COMPONENT_NAME) -# -# 2. Specify all assembly source files here. -# Files should be placed into a separate directory (in this case, ulp/), -# which should not be added to COMPONENT_SRCDIRS. -ULP_S_SOURCES = $(addprefix $(COMPONENT_PATH)/ulp/, \ - pulse_cnt.S \ - wake_up.S \ - ) -# -# 3. List all the component object files which include automatically -# generated ULP export file, $(ULP_APP_NAME).h: -ULP_EXP_DEP_OBJECTS := ulp_example_main.o -# -# 4. Include build rules for ULP program -include $(IDF_PATH)/components/ulp/component_ulp_common.mk -# -# End of ULP support additions to component makefile. -# diff --git a/examples/espidf-ulp/main/ulp_example_main.c b/examples/espidf-ulp/main/ulp_example_main.c old mode 100644 new mode 100755 index 1607e7b07..226ebef2e --- a/examples/espidf-ulp/main/ulp_example_main.c +++ b/examples/espidf-ulp/main/ulp_example_main.c @@ -17,7 +17,13 @@ #include "soc/rtc_periph.h" #include "driver/gpio.h" #include "driver/rtc_io.h" -#include "ulp.h" +#if CONFIG_IDF_TARGET_ESP32 +#include "esp32/ulp.h" +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/ulp.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/ulp.h" +#endif #include "ulp_main.h" extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); @@ -98,27 +104,27 @@ static void init_ulp_program(void) static void update_pulse_count(void) { - const char* namespace = "plusecnt"; + const char* nvs_namespace = "plusecnt"; const char* count_key = "count"; ESP_ERROR_CHECK( nvs_flash_init() ); nvs_handle_t handle; - ESP_ERROR_CHECK( nvs_open(namespace, NVS_READWRITE, &handle)); + ESP_ERROR_CHECK( nvs_open(nvs_namespace, NVS_READWRITE, &handle)); uint32_t pulse_count = 0; esp_err_t err = nvs_get_u32(handle, count_key, &pulse_count); assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND); - printf("Read pulse count from NVS: %5"PRIu32"\n", pulse_count); + printf("Read pulse count from NVS: %5" PRIu32"\n", pulse_count); /* ULP program counts signal edges, convert that to the number of pulses */ uint32_t pulse_count_from_ulp = (ulp_edge_count & UINT16_MAX) / 2; /* In case of an odd number of edges, keep one until next time */ ulp_edge_count = ulp_edge_count % 2; - printf("Pulse count from ULP: %5"PRIu32"\n", pulse_count_from_ulp); + printf("Pulse count from ULP: %5" PRIu32"\n", pulse_count_from_ulp); /* Save the new pulse count to NVS */ pulse_count += pulse_count_from_ulp; ESP_ERROR_CHECK(nvs_set_u32(handle, count_key, pulse_count)); ESP_ERROR_CHECK(nvs_commit(handle)); nvs_close(handle); - printf("Wrote updated pulse count to NVS: %5"PRIu32"\n", pulse_count); + printf("Wrote updated pulse count to NVS: %5" PRIu32"\n", pulse_count); } diff --git a/examples/espidf-ulp/ulp/pulse_cnt.S b/examples/espidf-ulp/ulp/pulse_cnt.S old mode 100644 new mode 100755 diff --git a/examples/espidf-ulp/ulp/wake_up.S b/examples/espidf-ulp/ulp/wake_up.S old mode 100644 new mode 100755 index 34b80b411..f6bf8fa3b --- a/examples/espidf-ulp/ulp/wake_up.S +++ b/examples/espidf-ulp/ulp/wake_up.S @@ -1,14 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ /* ULP assembly files are passed through C preprocessor first, so include directives and C macros may be used in these files */ #include "soc/rtc_cntl_reg.h" #include "soc/soc_ulp.h" +#include "sdkconfig.h" .global wake_up wake_up: + /* Check if the system is in sleep mode */ +#if CONFIG_IDF_TARGET_ESP32 + READ_RTC_REG(RTC_CNTL_LOW_POWER_ST_REG, 27, 1) +#else + READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_MAIN_STATE_IN_IDLE) +#endif + move r1, r0 /* Check if the system can be woken up */ READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP) - and r0, r0, 1 + /* If the system is in normal mode or if the system is in sleep mode with ready for wakeup set, we can signal the main CPU to wakeup */ + or r0, r0, r1 jump wake_up, eq /* Wake up the SoC, end program */ From 5be00758fbe9e2a78a4de4d06db3484bea3e4435 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Jul 2023 20:42:30 +0200 Subject: [PATCH 372/666] USE ADC example --- examples/espidf-ulp-riscv/main/CMakeLists.txt | 4 +- .../main/ulp_riscv_example_main.c | 33 +++-- examples/espidf-ulp-riscv/ulp/main.c | 139 ++---------------- 3 files changed, 32 insertions(+), 144 deletions(-) diff --git a/examples/espidf-ulp-riscv/main/CMakeLists.txt b/examples/espidf-ulp-riscv/main/CMakeLists.txt index 51344fa9a..b2f277f2e 100644 --- a/examples/espidf-ulp-riscv/main/CMakeLists.txt +++ b/examples/espidf-ulp-riscv/main/CMakeLists.txt @@ -14,12 +14,12 @@ set(ulp_app_name ulp_${COMPONENT_NAME}) # 2. Specify all C and Assembly source files. # Files should be placed into a separate directory (in this case, ulp/), # which should not be added to COMPONENT_SRCS. -set(ulp_riscv_sources "ulp/main.c") +set(ulp_riscv_sources "../ulp/main.c") # # 3. List all the component source files which include automatically # generated ULP export file, ${ulp_app_name}.h: -set(ulp_exp_dep_srcs "../ulp_riscv_example_main.c") +set(ulp_exp_dep_srcs "ulp_riscv_example_main.c") # # 4. Call function to build ULP binary and embed in project using the argument diff --git a/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c b/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c index ba5c5845f..42fb16b11 100644 --- a/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c +++ b/examples/espidf-ulp-riscv/main/ulp_riscv_example_main.c @@ -1,4 +1,4 @@ -/* ULP riscv example +/* ULP riscv DS18B20 1wire temperature sensor example This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -12,7 +12,6 @@ #include "soc/rtc_cntl_reg.h" #include "soc/sens_reg.h" #include "soc/rtc_periph.h" -#include "hal/rtc_io_ll.h" #include "driver/gpio.h" #include "driver/rtc_io.h" #include "ulp_riscv.h" @@ -20,11 +19,6 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -/* We alternate between start conversion and read result every other ULP wakeup, - Conversion time is 750 ms for 12 bit resolution -*/ -#define WAKEUP_PERIOD_US (750000) - extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end"); @@ -32,18 +26,28 @@ static void init_ulp_program(void); void app_main(void) { + /* Initialize selected GPIO as RTC IO, enable input, disable pullup and pulldown */ + rtc_gpio_init(GPIO_NUM_0); + rtc_gpio_set_direction(GPIO_NUM_0, RTC_GPIO_MODE_INPUT_ONLY); + rtc_gpio_pulldown_dis(GPIO_NUM_0); + rtc_gpio_pullup_dis(GPIO_NUM_0); + rtc_gpio_hold_en(GPIO_NUM_0); + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); /* not a wakeup from ULP, load the firmware */ if (cause != ESP_SLEEP_WAKEUP_ULP) { - printf("Not a ULP-RISC-V wakeup (cause = %d), initializing it! \n", cause); + printf("Not a ULP-RISC-V wakeup, initializing it! \n"); init_ulp_program(); } - /* ULP Risc-V read and detected a temperature above the limit */ + /* ULP Risc-V read and detected a change in GPIO_0, prints */ if (cause == ESP_SLEEP_WAKEUP_ULP) { - printf("ULP-RISC-V woke up the main CPU, temperature is above set limit! \n"); - printf("ULP-RISC-V read temperature is %f\n", ulp_temp_reg_val / 16.0); + printf("ULP-RISC-V woke up the main CPU! \n"); + printf("ULP-RISC-V read changes in GPIO_0 current is: %s \n", + (bool)(ulp_gpio_level_previous == 0) ? "Low" : "High" ); + } + /* Go back to sleep, only the ULP Risc-V will run */ printf("Entering in deep sleep\n\n"); @@ -51,7 +55,6 @@ void app_main(void) vTaskDelay(100); ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup()); - esp_deep_sleep_start(); } @@ -61,11 +64,11 @@ static void init_ulp_program(void) ESP_ERROR_CHECK(err); /* The first argument is the period index, which is not used by the ULP-RISC-V timer - * The second argument is the period in microseconds, which gives a wakeup time period of: 750ms + * The second argument is the period in microseconds, which gives a wakeup time period of: 20ms */ - ulp_set_wakeup_period(0, WAKEUP_PERIOD_US); + ulp_set_wakeup_period(0, 20000); /* Start the program */ err = ulp_riscv_run(); ESP_ERROR_CHECK(err); -} +} \ No newline at end of file diff --git a/examples/espidf-ulp-riscv/ulp/main.c b/examples/espidf-ulp-riscv/ulp/main.c index dfabfd192..91e8a3d22 100644 --- a/examples/espidf-ulp-riscv/ulp/main.c +++ b/examples/espidf-ulp-riscv/ulp/main.c @@ -16,141 +16,26 @@ #include "ulp_riscv_utils.h" #include "ulp_riscv_gpio.h" -#define EXAMPLE_1WIRE_GPIO GPIO_NUM_4 +static bool gpio_level = false; -#define WAKEUP_TEMP_C 32.5 -#define TEMP_ALARM_LIMIT ( (int)(WAKEUP_TEMP_C*16) ) - -typedef enum { - SENSOR_CONVERSION_INIT, - SENSOR_CONVERSION_READ, -} sensor_state_t; - -sensor_state_t state = SENSOR_CONVERSION_INIT; -int32_t temp_reg_val = INT32_MIN; - -static void ds18b20_write_bit(bool bit) -{ - ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0); - if (bit) { - /* Must pull high within 15 us, without delay this takes 5 us */ - ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1); - } - - /* Write slot duration at least 60 us */ - ulp_riscv_delay_cycles(60 * ULP_RISCV_CYCLES_PER_US); - ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1); -} - -static bool ds18b20_read_bit(void) -{ - bool bit; - - /* Pull low minimum 1 us */ - ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0); - ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1); - - /* Must sample within 15 us of the failing edge */ - ulp_riscv_delay_cycles(5 * ULP_RISCV_CYCLES_PER_US); - bit = ulp_riscv_gpio_get_level(EXAMPLE_1WIRE_GPIO); - - /* Read slot duration at least 60 us */ - ulp_riscv_delay_cycles(55 * ULP_RISCV_CYCLES_PER_US); - - return bit; -} - -static void ds18b20_write_byte(uint8_t data) -{ - for (int i = 0; i < 8; i++) { - ds18b20_write_bit((data >> i) & 0x1); - } -} - -static uint8_t ds18b20_read_byte(void) -{ - uint8_t data = 0; - for (int i = 0; i < 8; i++) { - data |= ds18b20_read_bit() << i; - } - return data; -} - -bool ds18b20_reset_pulse(void) -{ - bool presence_pulse; - /* min 480 us reset pulse + 480 us reply time is specified by datasheet */ - ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0); - ulp_riscv_delay_cycles(480 * ULP_RISCV_CYCLES_PER_US); - - ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1); - - /* Wait for ds18b20 to pull low before sampling */ - ulp_riscv_delay_cycles(60 * ULP_RISCV_CYCLES_PER_US); - presence_pulse = ulp_riscv_gpio_get_level(EXAMPLE_1WIRE_GPIO) == 0; - - ulp_riscv_delay_cycles(420 * ULP_RISCV_CYCLES_PER_US); - - return presence_pulse; -} +/* this variable will be exported as a public symbol, visible from main CPU: */ +bool gpio_level_previous = false; int main (void) { - uint8_t temp_high_byte; - uint8_t temp_low_byte; - - /* Setup GPIO used for 1wire */ - ulp_riscv_gpio_init(EXAMPLE_1WIRE_GPIO); - ulp_riscv_gpio_input_enable(EXAMPLE_1WIRE_GPIO); - ulp_riscv_gpio_output_enable(EXAMPLE_1WIRE_GPIO); - ulp_riscv_gpio_set_output_mode(EXAMPLE_1WIRE_GPIO, RTCIO_MODE_OUTPUT_OD); - ulp_riscv_gpio_pullup(EXAMPLE_1WIRE_GPIO); - ulp_riscv_gpio_pulldown_disable(EXAMPLE_1WIRE_GPIO); - + gpio_level = (bool)ulp_riscv_gpio_get_level(GPIO_NUM_0); + gpio_level_previous = gpio_level; - switch (state) { - case SENSOR_CONVERSION_INIT: - if (!ds18b20_reset_pulse()) { - temp_reg_val = INT32_MIN; - break; - } - /* Start conversion */ - ds18b20_write_byte(0xCC); - ds18b20_write_byte(0x44); + while(1) { + gpio_level = (bool)ulp_riscv_gpio_get_level(GPIO_NUM_0); - /* shutdown and wait for next period (750ms) where the data is ready for reading */ - state = SENSOR_CONVERSION_READ; - break; - - case SENSOR_CONVERSION_READ: - if (!ds18b20_reset_pulse()) { - temp_reg_val = INT32_MIN; - state = SENSOR_CONVERSION_INIT; - break; - } - - /* Read scratchpad */ - ds18b20_write_byte(0xCC); - ds18b20_write_byte(0xBE); - - temp_low_byte = ds18b20_read_byte(); - temp_high_byte = ds18b20_read_byte(); - - temp_reg_val = temp_high_byte << 8; - temp_reg_val |= temp_low_byte; - state = SENSOR_CONVERSION_INIT; - - /* Wakes up the main CPU if the temperature exceeds the limit */ - if (temp_reg_val > TEMP_ALARM_LIMIT) { + /* Wakes up the main CPU if pin changed its state */ + if(gpio_level != gpio_level_previous) { + gpio_level_previous = gpio_level; ulp_riscv_wakeup_main_processor(); + break; } - - break; } - - /* ulp_riscv_halt() is called automatically when main exits, - main will be executed again at the next timeout period, - according to ulp_set_wakeup_period() - */ + /* ulp_riscv_halt() is called automatically when main exits */ return 0; } From efe7af3f294e50220a4acbf620a5a2811cdab074 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 12 Jul 2023 10:56:03 +0200 Subject: [PATCH 373/666] fix ULP riscv compile --- examples/espidf-ulp-riscv/sdkconfig.defaults | 4 ---- examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 | 7 +++++++ examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 | 7 +++++++ 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 create mode 100644 examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 diff --git a/examples/espidf-ulp-riscv/sdkconfig.defaults b/examples/espidf-ulp-riscv/sdkconfig.defaults index a28f71162..302c87aa9 100644 --- a/examples/espidf-ulp-riscv/sdkconfig.defaults +++ b/examples/espidf-ulp-riscv/sdkconfig.defaults @@ -1,7 +1,3 @@ -# Enable ULP -CONFIG_ULP_COPROC_ENABLED=y -CONFIG_ULP_COPROC_RISCV=y -CONFIG_ULP_COPROC_RESERVE_MEM=4096 # Set log level to Warning to produce clean output CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y CONFIG_BOOTLOADER_LOG_LEVEL=2 diff --git a/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 b/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 new file mode 100644 index 000000000..039f3584c --- /dev/null +++ b/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s2 @@ -0,0 +1,7 @@ +# Enable ULP +CONFIG_ESP32S2_ULP_COPROC_ENABLED=y +CONFIG_ESP32S2_ULP_COPROC_RISCV=y +CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=4096 +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_RESERVE_MEM=4096 +CONFIG_ULP_COPROC_TYPE_RISCV=y \ No newline at end of file diff --git a/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 b/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 new file mode 100644 index 000000000..df96a349d --- /dev/null +++ b/examples/espidf-ulp-riscv/sdkconfig.defaults.esp32s3 @@ -0,0 +1,7 @@ +# Enable ULP +CONFIG_ESP32S3_ULP_COPROC_ENABLED=y +CONFIG_ESP32S3_ULP_COPROC_RISCV=y +CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=4096 +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_RESERVE_MEM=4096 +CONFIG_ULP_COPROC_TYPE_RISCV=y From 3b20427db136db937e174afe822f8c7920721426 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 21 Jul 2023 16:21:35 +0200 Subject: [PATCH 374/666] Update espidf.py --- builder/frameworks/espidf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index a225a7d29..a39e49fc1 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1549,6 +1549,7 @@ def _skip_prj_source_files(node): + get_project_lib_includes(env) ) + project_env.ProcessFlags(env.get("SRC_BUILD_FLAGS")) env.Append( PIOBUILDFILES=compile_source_files( target_configs.get(project_target_name), From a1da3abc959199d92f44b89373df9a8e91c01e50 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 22 Jul 2023 14:47:14 +0200 Subject: [PATCH 375/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 73100b433..bac5de4da 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1407/framework-arduinoespressif32-release_v5.1-6105f97b10.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1431/framework-arduinoespressif32-release_v5.1-9407eb5299.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1407/framework-arduinoespressif32-release_v5.1-6105f97b10.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1431/framework-arduinoespressif32-release_v5.1-9407eb5299.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1407/framework-arduinoespressif32-release_v5.1-6105f97b10.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1431/framework-arduinoespressif32-release_v5.1-9407eb5299.zip" }, "framework-espidf": { "type": "framework", From c4c9c2d7d807867d1b0e491bf6b7589dc000aa6d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 22 Jul 2023 15:01:11 +0200 Subject: [PATCH 376/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index bac5de4da..3fc1f8826 100644 --- a/platform.json +++ b/platform.json @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.0/esp-idf-v5.1.0.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.0.20230722/esp-idf-v5.1.0.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 16d2fc59f387ca2fa9a4158395fbb7405590a6b0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 22 Jul 2023 15:42:13 +0200 Subject: [PATCH 377/666] Update ulp.py --- builder/frameworks/ulp.py | 1 - 1 file changed, 1 deletion(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 416b5b20d..5af8f87d1 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -129,7 +129,6 @@ def compile_ulp_binary(): os.path.join(ULP_BUILD_DIR, "ulp_main.h"), os.path.join(ULP_BUILD_DIR, "ulp_main.ld"), os.path.join(ULP_BUILD_DIR, "ulp_main.bin"), - os.path.join(ULP_BUILD_DIR, "esp32.ulp.ld"), ], None, ulp_env.VerboseAction(" ".join(cmd), "Generating ULP project files $TARGETS"), From bc7ed1dc28298109e1845edd5dbbf15029bfb474 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 22 Jul 2023 15:46:38 +0200 Subject: [PATCH 378/666] Create sizedata.py --- builder/sizedata.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 builder/sizedata.py diff --git a/builder/sizedata.py b/builder/sizedata.py new file mode 100644 index 000000000..e6e947627 --- /dev/null +++ b/builder/sizedata.py @@ -0,0 +1,26 @@ +import re + +Import("env") + + +def pioSizeIsRamSectionCustom(env, section): + if section and re.search( + r"\.dram0\.data|\.dram0\.bss|\.noinit", section.get("name", "") + ): + return True + + return False + + +def pioSizeIsFlashectionCustom(env, section): + if section and re.search( + r"\.iram0\.text|\.iram0\.vectors|\.dram0\.data|\.flash\.text|\.flash\.rodata|\.flash\.appdesc", + section.get("name", ""), + ): + return True + + return False + + +env.AddMethod(pioSizeIsRamSectionCustom, "pioSizeIsRamSection") +env.AddMethod(pioSizeIsFlashectionCustom, "pioSizeIsFlashSection") From 70ce541647d9c9f538563dcc2dba0e27e622874f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 22 Jul 2023 15:47:17 +0200 Subject: [PATCH 379/666] Update main.py --- builder/main.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/builder/main.py b/builder/main.py index 37f98f021..c4e78cf0d 100644 --- a/builder/main.py +++ b/builder/main.py @@ -530,6 +530,12 @@ def __fetch_fs_size(target, source, env): "Erase Flash", ) +# +# Override memory inspection behavior +# + +env.SConscript("sizedata.py", exports="env") + # # Default targets # From b7e9fce1921369240504fccb4a3b8dff10987589 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 22 Jul 2023 16:00:20 +0200 Subject: [PATCH 380/666] initial c2 support --- boards/esp32-c2-devkitm-1.json | 29 ++++++++++++++++++++++++++++ builder/frameworks/_embed_files.py | 6 +++--- builder/frameworks/espidf.py | 10 +++++----- builder/main.py | 2 +- examples/espidf-blink/platformio.ini | 8 ++++---- platform.json | 4 ++-- platform.py | 6 +++--- 7 files changed, 47 insertions(+), 18 deletions(-) create mode 100644 boards/esp32-c2-devkitm-1.json diff --git a/boards/esp32-c2-devkitm-1.json b/boards/esp32-c2-devkitm-1.json new file mode 100644 index 000000000..16b6444e2 --- /dev/null +++ b/boards/esp32-c2-devkitm-1.json @@ -0,0 +1,29 @@ +{ + "build": { + "core": "esp32", + "f_cpu": "120000000L", + "f_flash": "60000000L", + "flash_mode": "qio", + "mcu": "esp32c2", + "variant": "esp32c2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c2.cfg" + }, + "frameworks": [ + "espidf" + ], + "name": "Espressif ESP32-C2-DevKitM-1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 278528, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp8684/esp8684-devkitm-1/user_guide.html", + "vendor": "Espressif" +} diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index 1b685ff82..354c244bb 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -110,14 +110,14 @@ def transform_to_asm(target, source, env): " ".join( [ "riscv32-esp-elf-objcopy" - if mcu in ("esp32c3", "esp32c6", "esp32h2") + if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2") else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", - "elf32-littleriscv" if mcu in ("esp32c3","esp32c6","esp32h2") else "elf32-xtensa-le", + "elf32-littleriscv" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2") else "elf32-xtensa-le", "--binary-architecture", - "riscv" if mcu in ("esp32c3","esp32c6") else "xtensa", + "riscv" if mcu in ("esp32c2","esp32c3","esp32c6") else "xtensa", "--rename-section", ".data=.rodata.embedded", "$SOURCE", diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index a39e49fc1..c6faafa6b 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -62,7 +62,7 @@ IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" % ("riscv32-esp" if mcu in ("esp32c3","esp32c6","esp32h2") else ("xtensa-%s" % mcu)) + "toolchain-%s" % ("riscv32-esp" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2") else ("xtensa-%s" % mcu)) ) @@ -234,7 +234,7 @@ def populate_idf_env_vars(idf_env): os.path.dirname(get_python_exe()), ] - if mcu not in ("esp32c3", "esp32c6","esp32h2"): + if mcu not in ("esp32c2", "esp32c3", "esp32c6","esp32h2"): additional_packages.append( os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), ) @@ -489,7 +489,7 @@ def extract_linker_script_fragments(framework_components_dir, sdk_config): sys.stderr.write("Error: Failed to extract paths to linker script fragments\n") env.Exit(1) - if mcu in ("esp32c3", "esp32c6", "esp32h2"): + if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2"): result.append(os.path.join(framework_components_dir, "riscv", "linker.lf")) # Add extra linker fragments @@ -1500,7 +1500,7 @@ def _skip_prj_source_files(node): ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ("esp32c3", "esp32c6", "esp32s3", "esp32h2") else "0x1000", + "0x0" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2") else "0x1000", ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), @@ -1580,7 +1580,7 @@ def _skip_prj_source_files(node): # ulp_dir = os.path.join(PROJECT_DIR, "ulp") -if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c3", "esp32c6", "esp32h2"): +if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "esp32c3", "esp32c6", "esp32h2"): env.SConscript("ulp.py", exports="env sdk_config project_config idf_variant") # diff --git a/builder/main.py b/builder/main.py index c4e78cf0d..f3d1dda8f 100644 --- a/builder/main.py +++ b/builder/main.py @@ -212,7 +212,7 @@ def __fetch_fs_size(target, source, env): mcu = board.get("build.mcu", "esp32") toolchain_arch = "xtensa-%s" % mcu filesystem = board.get("build.filesystem", "spiffs") -if mcu in ("esp32c3", "esp32c6", "esp32h2"): +if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2"): toolchain_arch = "riscv32-esp" if "INTEGRATION_EXTRA_DATA" not in env: diff --git a/examples/espidf-blink/platformio.ini b/examples/espidf-blink/platformio.ini index 35b3b70a5..d9885f0a7 100644 --- a/examples/espidf-blink/platformio.ini +++ b/examples/espidf-blink/platformio.ini @@ -18,12 +18,12 @@ build_flags = -D CONFIG_BLINK_LED_GPIO=2 -D CONFIG_BLINK_PERIOD=1000 -[env:esp32-c6-devkitc-1] +[env:esp32-c2-devkitm-1] platform = espressif32 framework = espidf -board = esp32-c6-devkitc-1 +board = esp32-c2-devkitm-1 monitor_speed = 115200 build_flags = - -D CONFIG_BLINK_GPIO=2 - -D CONFIG_BLINK_LED_GPIO=2 + -D CONFIG_BLINK_GPIO=8 + -D CONFIG_BLINK_LED_GPIO=8 -D CONFIG_BLINK_PERIOD=1000 diff --git a/platform.json b/platform.json index 3fc1f8826..2e1e6db0c 100644 --- a/platform.json +++ b/platform.json @@ -12,13 +12,13 @@ "RISC-V" ], "engines": { - "platformio": ">=6.1.6" + "platformio": ">=6.1.9" }, "repository": { "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.06.05", + "version": "2023.07.00", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" diff --git a/platform.py b/platform.py index 4e7abb86b..b661d650f 100644 --- a/platform.py +++ b/platform.py @@ -81,8 +81,8 @@ def configure_default_packages(self, variables, targets): else: self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) - if mcu in ("esp32s2", "esp32s3", "esp32c3", "esp32c6", "esp32h2"): - if mcu in ("esp32c3", "esp32c6", "esp32h2"): + if mcu in ("esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2"): + if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2"): self.packages.pop("toolchain-esp32ulp", None) # RISC-V based toolchain for ESP32C3, ESP32C6 ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp"]["optional"] = False @@ -124,7 +124,7 @@ def _add_dynamic_options(self, board): "tumpa", ] - if board.get("build.mcu", "") in ("esp32c3", "esp32c6", "esp32s3", "esp32h2"): + if board.get("build.mcu", "") in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2"): supported_debug_tools.append("esp-builtin") upload_protocol = board.manifest.get("upload", {}).get("protocol") From d6816bda594dfb34634dbe0a71750bb6da98dc80 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 22 Jul 2023 16:03:32 +0200 Subject: [PATCH 381/666] Update platformio.ini --- examples/espidf-blink/platformio.ini | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/examples/espidf-blink/platformio.ini b/examples/espidf-blink/platformio.ini index d9885f0a7..44b4ff9a1 100644 --- a/examples/espidf-blink/platformio.ini +++ b/examples/espidf-blink/platformio.ini @@ -27,3 +27,13 @@ build_flags = -D CONFIG_BLINK_GPIO=8 -D CONFIG_BLINK_LED_GPIO=8 -D CONFIG_BLINK_PERIOD=1000 + +[env:esp32-c6-devkitc-1] +platform = espressif32 +framework = espidf +board = esp32-c6-devkitc-1 +monitor_speed = 115200 +build_flags = + -D CONFIG_BLINK_GPIO=2 + -D CONFIG_BLINK_LED_GPIO=2 + -D CONFIG_BLINK_PERIOD=1000 From 315b722ad4f6236c30500274d5ea7f79382af3c1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 23 Jul 2023 20:18:59 +0200 Subject: [PATCH 382/666] Arduino C2 support --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 2e1e6db0c..0b5b71354 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1431/framework-arduinoespressif32-release_v5.1-9407eb5299.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1437/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1431/framework-arduinoespressif32-release_v5.1-9407eb5299.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1437/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1431/framework-arduinoespressif32-release_v5.1-9407eb5299.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1437/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-espidf": { "type": "framework", From 2c28f37ebb0e7c8d79fbcebf702c377b8616d207 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 23 Jul 2023 20:21:05 +0200 Subject: [PATCH 383/666] alpha Arduino support --- boards/esp32-c2-devkitm-1.json | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/esp32-c2-devkitm-1.json b/boards/esp32-c2-devkitm-1.json index 16b6444e2..eb3a58c50 100644 --- a/boards/esp32-c2-devkitm-1.json +++ b/boards/esp32-c2-devkitm-1.json @@ -14,6 +14,7 @@ "openocd_target": "esp32c2.cfg" }, "frameworks": [ + "arduino", "espidf" ], "name": "Espressif ESP32-C2-DevKitM-1", From 8c258d7b3b527762a6cadfdaf149c1b4ceb56178 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 23 Jul 2023 20:25:12 +0200 Subject: [PATCH 384/666] add c2 to Blink example --- examples/arduino-blink/platformio.ini | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 126adf36f..11bed64e8 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -13,9 +13,16 @@ framework = arduino board = esp-wrover-kit monitor_speed = 115200 build_flags = - ; https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#rgb-led - -D LED_BUILTIN=2 + -DLED_BUILTIN=2 +[env:esp32-c2-devkitm-1] +platform = espressif32 +framework = arduino +board = esp32-c2-devkitm-1 +monitor_speed = 115200 +build_flags = + -DLED_BUILTIN=8 + [env:esp32-c6-devkitc-1] platform = espressif32 framework = arduino From 33a53f620c1cdd87869b8d1295903533b4ba6cc9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 23 Jul 2023 20:42:56 +0200 Subject: [PATCH 385/666] Update platformio.ini --- examples/arduino-blink/platformio.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 11bed64e8..7a5ae6a81 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -20,8 +20,6 @@ platform = espressif32 framework = arduino board = esp32-c2-devkitm-1 monitor_speed = 115200 -build_flags = - -DLED_BUILTIN=8 [env:esp32-c6-devkitc-1] platform = espressif32 From 9141268189f954490b02445bf958d3ea905162fd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 23 Jul 2023 23:25:44 +0200 Subject: [PATCH 386/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 0b5b71354..b68a0c3a2 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1437/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1438/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1437/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1438/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1437/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1438/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-espidf": { "type": "framework", From de30cb481639c6dee2086561cb07f908e3980573 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 24 Jul 2023 10:22:26 +0200 Subject: [PATCH 387/666] Update platformio.ini --- examples/arduino-blink/platformio.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 7a5ae6a81..77db237d3 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -20,6 +20,8 @@ platform = espressif32 framework = arduino board = esp32-c2-devkitm-1 monitor_speed = 115200 +build_flags = + -DLED_BUILTIN=8 ;blue [env:esp32-c6-devkitc-1] platform = espressif32 From 416c4a1f1612dc1a1eacebfc83296445ef93a10d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 24 Jul 2023 11:07:20 +0200 Subject: [PATCH 388/666] Update platformio.ini --- examples/arduino-blink/platformio.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 77db237d3..7a5ae6a81 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -20,8 +20,6 @@ platform = espressif32 framework = arduino board = esp32-c2-devkitm-1 monitor_speed = 115200 -build_flags = - -DLED_BUILTIN=8 ;blue [env:esp32-c6-devkitc-1] platform = espressif32 From 0514b3723fe47c6c4e22a1f6eb802df986f803b4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 24 Jul 2023 12:46:05 +0200 Subject: [PATCH 389/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index b68a0c3a2..8e89e9ad4 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1438/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1439/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1438/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1439/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1438/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1439/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-espidf": { "type": "framework", From d1dbb65c6acad061b7869a2d5742ed792925aaa6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 24 Jul 2023 14:30:02 +0200 Subject: [PATCH 390/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 8e89e9ad4..08d06e33d 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1439/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1440/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1439/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1440/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1439/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1440/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" }, "framework-espidf": { "type": "framework", From 5a1a95d0253bf9da84b027f1937cdc1fdb4a52a3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 27 Jul 2023 14:09:20 +0200 Subject: [PATCH 391/666] Fix update max size --- builder/main.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/builder/main.py b/builder/main.py index f3d1dda8f..79477bd34 100644 --- a/builder/main.py +++ b/builder/main.py @@ -162,12 +162,17 @@ def _parse_partitions(env): def _update_max_upload_size(env): if not env.get("PARTITIONS_TABLE_CSV"): return - sizes = [ - _parse_size(p["size"]) for p in _parse_partitions(env) + sizes = { + p["subtype"]: _parse_size(p["size"]) for p in _parse_partitions(env) if p["type"] in ("0", "app") - ] - if sizes: - board.update("upload.maximum_size", max(sizes)) + } + + # One of the `factory` or `ota_0` partitions is used to determine available memory + # size. If both partitions are set, then the `factory` partition is used by default + # https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html#subtype + max_upload_size = sizes.get("factory", sizes.get("ota_0", 0)) + if max_upload_size: + board.update("upload.maximum_size", max_upload_size) def _to_unix_slashes(path): From bc7f2974569c96a2a7501b7124821be35f83da59 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:08:09 +0200 Subject: [PATCH 392/666] hack to fix IDF 5.1 compile --- builder/frameworks/espidf.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index c6faafa6b..adea0421b 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -343,6 +343,17 @@ def _add_archive(archive_path, link_args): link_args = {"LINKFLAGS": [], "LIBS": [], "LIBPATH": [], "__LIB_DEPS": []} + _add_to_libpath(os.path.join(FRAMEWORK_DIR, "components", "bootloader", "subproject", "main", "ld", mcu), link_args) + _add_to_libpath(os.path.join(FRAMEWORK_DIR, "components", "esp_phy", "lib", mcu), link_args) + _add_to_libpath(os.path.join(FRAMEWORK_DIR, "components", "esp_rom", mcu, "ld"), link_args) + _add_to_libpath(os.path.join(FRAMEWORK_DIR, "components", "soc", mcu, "ld"), link_args) + +#def generate_project_ld_script(sdk_config, ignore_targets=None): +# ignore_targets = ignore_targets or [] +# linker_script_fragments = extract_linker_script_fragments( +# os.path.join(FRAMEWORK_DIR, "components"), sdk_config +# ) + for f in target_config.get("link", {}).get("commandFragments", []): fragment = f.get("fragment", "").strip() fragment_role = f.get("role", "").strip() From 21583a5a9b0732eb4037135ed955238555b978ad Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:33:54 +0200 Subject: [PATCH 393/666] remove left overs from IDF 5.1 hack --- builder/frameworks/espidf.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index adea0421b..8058cfbdc 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -348,12 +348,6 @@ def _add_archive(archive_path, link_args): _add_to_libpath(os.path.join(FRAMEWORK_DIR, "components", "esp_rom", mcu, "ld"), link_args) _add_to_libpath(os.path.join(FRAMEWORK_DIR, "components", "soc", mcu, "ld"), link_args) -#def generate_project_ld_script(sdk_config, ignore_targets=None): -# ignore_targets = ignore_targets or [] -# linker_script_fragments = extract_linker_script_fragments( -# os.path.join(FRAMEWORK_DIR, "components"), sdk_config -# ) - for f in target_config.get("link", {}).get("commandFragments", []): fragment = f.get("fragment", "").strip() fragment_role = f.get("role", "").strip() From 65cec09313f5962ef311950af419d4bcd03539a9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 27 Jul 2023 17:06:08 +0200 Subject: [PATCH 394/666] Use Arduino 3.0 from 20230727 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 08d06e33d..35d1c16f5 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1440/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1448/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1440/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1448/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1440/framework-arduinoespressif32-release_v5.1-3d4f85e3f4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1448/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" }, "framework-espidf": { "type": "framework", From 384c167629dcc9307637bf1efb66bf724931bf9d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 3 Aug 2023 15:08:01 +0200 Subject: [PATCH 395/666] official IDF 5.1 support --- builder/frameworks/espidf.py | 12 ++++-------- builder/main.py | 33 +++++++++++++++++++++++++++++---- platform.json | 2 +- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 8058cfbdc..dbd92ade3 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -343,11 +343,6 @@ def _add_archive(archive_path, link_args): link_args = {"LINKFLAGS": [], "LIBS": [], "LIBPATH": [], "__LIB_DEPS": []} - _add_to_libpath(os.path.join(FRAMEWORK_DIR, "components", "bootloader", "subproject", "main", "ld", mcu), link_args) - _add_to_libpath(os.path.join(FRAMEWORK_DIR, "components", "esp_phy", "lib", mcu), link_args) - _add_to_libpath(os.path.join(FRAMEWORK_DIR, "components", "esp_rom", mcu, "ld"), link_args) - _add_to_libpath(os.path.join(FRAMEWORK_DIR, "components", "soc", mcu, "ld"), link_args) - for f in target_config.get("link", {}).get("commandFragments", []): fragment = f.get("fragment", "").strip() fragment_role = f.get("role", "").strip() @@ -356,7 +351,7 @@ def _add_archive(archive_path, link_args): args = click.parser.split_arg_string(fragment) if fragment_role == "flags": link_args["LINKFLAGS"].extend(args) - elif fragment_role == "libraries": + elif fragment_role in ("libraries", "libraryPath"): if fragment.startswith("-l"): link_args["LIBS"].extend(args) elif fragment.startswith("-L"): @@ -629,6 +624,7 @@ def prepare_build_envs(config, default_env, debug_allowed=True): defines = extract_defines(cg) compile_commands = cg.get("compileCommandFragments", []) build_env = default_env.Clone() + build_env.SetOption("implicit_cache", 1) for cc in compile_commands: build_flags = cc.get("fragment") if not build_flags.startswith("-D"): @@ -1108,9 +1104,9 @@ def _get_installed_pip_packages(python_exe_path): "cryptography": "~=41.0.1" if IDF5 else ">=2.1.4,<35.0.0", "future": ">=0.18.3", "pyparsing": "~=3.0.9" if IDF5 else ">=2.0.3,<2.4.0", - "esp-idf-kconfig": "~=1.1.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", "idf-component-manager": "~=1.2.3" if IDF5 else "~=1.0", + "esp-idf-kconfig": "~=1.2.0" } python_exe_path = get_python_exe() @@ -1550,7 +1546,7 @@ def _skip_prj_source_files(node): # Add include dirs from PlatformIO build system to project CPPPATH so # they're visible to PIOBUILDFILES project_env.AppendUnique( - CPPPATH=["$PROJECT_INCLUDE_DIR", "$PROJECT_SRC_DIR"] + CPPPATH=["$PROJECT_INCLUDE_DIR", "$PROJECT_SRC_DIR", "$PROJECT_DIR"] + get_project_lib_includes(env) ) diff --git a/builder/main.py b/builder/main.py index 79477bd34..f548cdc24 100644 --- a/builder/main.py +++ b/builder/main.py @@ -168,11 +168,14 @@ def _update_max_upload_size(env): } # One of the `factory` or `ota_0` partitions is used to determine available memory - # size. If both partitions are set, then the `factory` partition is used by default + # size. If both partitions are set, we should prefer the `factory`, but there are + # cases (e.g. Adafruit's `partitions-4MB-tinyuf2.csv`) that uses the `factory` + # partition for their UF2 bootloader. So let's use the first match # https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html#subtype - max_upload_size = sizes.get("factory", sizes.get("ota_0", 0)) - if max_upload_size: - board.update("upload.maximum_size", max_upload_size) + for p in _parse_partitions(env): + if p["type"] in ("0", "app") and p["subtype"] in ("factory", "ota_0"): + board.update("upload.maximum_size", _parse_size(p["size"])) + break def _to_unix_slashes(path): @@ -453,6 +456,28 @@ def __fetch_fs_size(target, source, env): env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE") ] +elif upload_protocol == "dfu": + # C:\Users\ROOT\AppData\Local\Arduino15\packages\arduino\tools\dfu-util\0.11.0-arduino5/dfu-util --device 0x2341:0x0070 -D C:\Users\ROOT\AppData\Local\Temp\arduino_build_789426/sketch_jul31a.ino.bin -Q + + hwids = board.get("build.hwids", [["0x2341", "0x0070"]]) + vid = hwids[0][0] + pid = hwids[0][1] + + upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")] + + env.Replace( + UPLOADER=join( + platform.get_package_dir("tool-dfuutil-arduino") or "", "dfu-util" + ), + UPLOADERFLAGS=[ + "-d", + ",".join(["%s:%s" % (hwid[0], hwid[1]) for hwid in hwids]), + "-Q", + "-D" + ], + UPLOADCMD='"$UPLOADER" $UPLOADERFLAGS "$SOURCE"', + ) + elif upload_protocol in debug_tools: _parse_partitions(env) diff --git a/platform.json b/platform.json index 35d1c16f5..0a6b17534 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.07.00", + "version": "2023.07.01", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From 797b013197eec2b6b89cba7eb79d80d041a3ea41 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 3 Aug 2023 15:22:37 +0200 Subject: [PATCH 396/666] small changes in C6 boards.json --- boards/esp32-c6-devkitc-1.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boards/esp32-c6-devkitc-1.json b/boards/esp32-c6-devkitc-1.json index b82e07f8d..64b48ff13 100644 --- a/boards/esp32-c6-devkitc-1.json +++ b/boards/esp32-c6-devkitc-1.json @@ -4,8 +4,7 @@ "f_cpu": "160000000L", "f_flash": "80000000L", "flash_mode": "qio", - "mcu": "esp32c6", - "variant": "esp32c6" + "mcu": "esp32c6" }, "connectivity": [ "wifi" From 9e97914b85d2747db05fe7d3ee5dd347a231966d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 3 Aug 2023 17:04:43 +0200 Subject: [PATCH 397/666] dont use "keep" for flashing --- builder/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builder/main.py b/builder/main.py index f548cdc24..6f7eb18e7 100644 --- a/builder/main.py +++ b/builder/main.py @@ -425,8 +425,8 @@ def __fetch_fs_size(target, source, env): "--before", board.get("upload.before_reset", "default_reset"), "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", - "--flash_mode", "keep", - "--flash_freq", "keep", + "--flash_mode", "${__get_board_flash_mode(__env__)}", + "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "detect") ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE' @@ -443,8 +443,8 @@ def __fetch_fs_size(target, source, env): "--before", board.get("upload.before_reset", "default_reset"), "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", - "--flash_mode", "keep", - "--flash_freq", "keep", + "--flash_mode", "${__get_board_flash_mode(__env__)}", + "--flash_freq", "${__get_board_f_flash(__env__)}", "--flash_size", board.get("upload.flash_size", "detect"), "$FS_START" ], From cde84e40d664b7752ef620891fd75e4fdbdee3d9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 3 Aug 2023 17:08:16 +0200 Subject: [PATCH 398/666] Update esp32-c6-devkitc-1.json --- boards/esp32-c6-devkitc-1.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boards/esp32-c6-devkitc-1.json b/boards/esp32-c6-devkitc-1.json index 64b48ff13..b82e07f8d 100644 --- a/boards/esp32-c6-devkitc-1.json +++ b/boards/esp32-c6-devkitc-1.json @@ -4,7 +4,8 @@ "f_cpu": "160000000L", "f_flash": "80000000L", "flash_mode": "qio", - "mcu": "esp32c6" + "mcu": "esp32c6", + "variant": "esp32c6" }, "connectivity": [ "wifi" From 52419b25cba35ffebdf6b01e58db249f8f860cef Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 3 Aug 2023 17:45:37 +0200 Subject: [PATCH 399/666] board updates from upstream --- boards/esp32-s2-usb.json | 34 ---------- boards/esp32-s3-usb.json | 34 ---------- .../adafruit_feather_esp32_v2.json | 2 + .../adafruit_feather_esp32s2_reversetft.json | 63 ++++++++++++++++++ .../adafruit_feather_esp32s2_tft.json | 11 +++- .../adafruit_feather_esp32s3.json | 4 +- .../adafruit_feather_esp32s3_nopsram.json | 5 +- .../adafruit_feather_esp32s3_reversetft.json | 65 +++++++++++++++++++ .../adafruit_feather_esp32s3_tft.json | 6 +- .../adafruit_funhouse_esp32s2.json | 0 .../adafruit_itsybitsy_esp32.json | 2 + .../adafruit_magtag29_esp32s2.json | 0 builder/adafruit_matrixportal_esp32s3.json | 65 +++++++++++++++++++ .../adafruit_metro_esp32s2.json | 0 {boards => builder}/adafruit_qtpy_esp32.json | 2 + .../adafruit_qtpy_esp32c3.json | 0 .../adafruit_qtpy_esp32s2.json | 0 .../adafruit_qtpy_esp32s3_nopsram.json | 7 +- {boards => builder}/airm2m_core_esp32c3.json | 0 {boards => builder}/alksesp32.json | 0 builder/arduino_nano_esp32.json | 53 +++++++++++++++ {boards => builder}/atmegazero_esp32s2.json | 0 .../az-delivery-devkit-v4.json | 0 {boards => builder}/bee_motion.json | 0 {boards => builder}/bee_motion_mini.json | 0 {boards => builder}/bee_motion_s3.json | 2 + {boards => builder}/bee_s3.json | 4 +- {boards => builder}/bpi-bit.json | 0 {boards => builder}/bpi_leaf_s3.json | 0 {boards => builder}/briki_abc_esp32.json | 0 {boards => builder}/briki_mbc-wb_esp32.json | 0 {boards => builder}/cnrs_aw2eth.json | 0 {boards => builder}/connaxio_espoir.json | 0 .../cytron_maker_feather_aiot_s3.json | 0 {boards => builder}/d-duino-32.json | 0 {boards => builder}/deneyapkart.json | 9 +-- {boards => builder}/deneyapkart1A.json | 9 +-- {boards => builder}/deneyapkart1Av2.json | 15 +++-- {boards => builder}/deneyapkartg.json | 13 ++-- {boards => builder}/deneyapmini.json | 8 +-- {boards => builder}/deneyapminiv2.json | 10 ++- {boards => builder}/denky32.json | 0 {boards => builder}/denky_d4.json | 0 .../dfrobot_beetle_esp32c3.json | 0 builder/dfrobot_firebeetle2_esp32e.json | 39 +++++++++++ .../dfrobot_firebeetle2_esp32s3.json | 4 +- .../dfrobot_romeo_esp32s3.json | 22 +++---- {boards => builder}/dpu_esp32.json | 0 builder/edgebox-esp-100.json | 40 ++++++++++++ {boards => builder}/esp-wrover-kit.json | 0 .../esp32-c3-devkitc-02.json | 9 +-- {boards => builder}/esp32-c3-devkitm-1.json | 3 +- {boards => builder}/esp32-c3-m1i-kit.json | 0 {boards => builder}/esp32-devkitlipo.json | 0 {boards => builder}/esp32-evb.json | 0 {boards => builder}/esp32-gateway.json | 0 {boards => builder}/esp32-poe-iso.json | 0 {boards => builder}/esp32-poe.json | 0 {boards => builder}/esp32-pro.json | 0 {boards => builder}/esp32-s2-franzininho.json | 0 {boards => builder}/esp32-s2-kaluga-1.json | 0 {boards => builder}/esp32-s2-saola-1.json | 0 {boards => builder}/esp32-s3-devkitc-1.json | 4 +- {boards => builder}/esp320.json | 0 {boards => builder}/esp32cam.json | 0 {boards => builder}/esp32dev.json | 0 {boards => builder}/esp32doit-devkit-v1.json | 0 {boards => builder}/esp32doit-espduino.json | 0 {boards => builder}/esp32s3box.json | 0 {boards => builder}/esp32s3camlcd.json | 2 + {boards => builder}/esp32thing.json | 0 {boards => builder}/esp32thing_plus.json | 0 {boards => builder}/esp32vn-iot-uno.json | 0 {boards => builder}/espea32.json | 0 {boards => builder}/espectro32.json | 0 {boards => builder}/espino32.json | 0 {boards => builder}/etboard.json | 0 {boards => builder}/featheresp32-s2.json | 0 {boards => builder}/featheresp32.json | 0 {boards => builder}/firebeetle32.json | 0 {boards => builder}/fm-devkit.json | 0 .../franzininho_wifi_esp32s2.json | 0 .../franzininho_wifi_msc_esp32s2.json | 0 {boards => builder}/frogboard.json | 0 {boards => builder}/healthypi4.json | 0 {boards => builder}/heltec_wifi_kit_32.json | 0 builder/heltec_wifi_kit_32_V3.json | 47 ++++++++++++++ .../heltec_wifi_kit_32_v2.json | 0 {boards => builder}/heltec_wifi_lora_32.json | 0 .../heltec_wifi_lora_32_V2.json | 0 builder/heltec_wifi_lora_32_V3.json | 48 ++++++++++++++ .../heltec_wireless_stick.json | 0 .../heltec_wireless_stick_lite.json | 0 {boards => builder}/honeylemon.json | 0 {boards => builder}/hornbill32dev.json | 0 {boards => builder}/hornbill32minima.json | 0 {boards => builder}/imbrios-logsens-v1p1.json | 0 {boards => builder}/inex_openkb.json | 0 {boards => builder}/intorobot.json | 0 {boards => builder}/iotaap_magnolia.json | 0 {boards => builder}/iotbusio.json | 0 {boards => builder}/iotbusproteus.json | 0 {boards => builder}/kb32-ft.json | 0 {boards => builder}/kits-edu.json | 0 {boards => builder}/labplus_mpython.json | 0 builder/lilygo-t-display-s3.json | 48 ++++++++++++++ {boards => builder}/lionbit.json | 4 +- {boards => builder}/lolin32.json | 0 {boards => builder}/lolin32_lite.json | 0 {boards => builder}/lolin_c3_mini.json | 0 {boards => builder}/lolin_d32.json | 0 {boards => builder}/lolin_d32_pro.json | 0 {boards => builder}/lolin_s2_mini.json | 2 +- {boards => builder}/lolin_s2_pico.json | 2 +- {boards => builder}/lolin_s3.json | 0 builder/lolin_s3_mini.json | 46 +++++++++++++ {boards => builder}/lopy.json | 0 {boards => builder}/lopy4.json | 0 {boards => builder}/m5stack-atom.json | 0 builder/m5stack-atoms3.json | 46 +++++++++++++ {boards => builder}/m5stack-core-esp32.json | 0 {boards => builder}/m5stack-core2.json | 4 +- {boards => builder}/m5stack-coreink.json | 0 builder/m5stack-cores3.json | 46 +++++++++++++ {boards => builder}/m5stack-fire.json | 0 {boards => builder}/m5stack-grey.json | 0 builder/m5stack-stamps3.json | 46 +++++++++++++ {boards => builder}/m5stack-station.json | 0 {boards => builder}/m5stack-timer-cam.json | 0 .../m5stamp-pico.json | 17 ++--- {boards => builder}/m5stick-c.json | 0 {boards => builder}/magicbit.json | 0 {boards => builder}/mgbot-iotik32a.json | 0 {boards => builder}/mgbot-iotik32b.json | 0 {boards => builder}/mhetesp32devkit.json | 0 {boards => builder}/mhetesp32minikit.json | 0 .../microduino-core-esp32.json | 0 {boards => builder}/micros2.json | 0 {boards => builder}/minimain_esp32s2.json | 2 + {boards => builder}/nano32.json | 0 builder/nebulas3.json | 47 ++++++++++++++ {boards => builder}/nina_w10.json | 0 {boards => builder}/node32s.json | 0 {boards => builder}/nodemcu-32s.json | 0 {boards => builder}/nodemcu-32s2.json | 0 {boards => builder}/nscreen-32.json | 0 {boards => builder}/odroid_esp32.json | 0 {boards => builder}/onehorse32dev.json | 2 +- {boards => builder}/oroca_edubot.json | 0 {boards => builder}/pico32.json | 2 +- {boards => builder}/piranha_esp32.json | 0 {boards => builder}/pocket_32.json | 0 {boards => builder}/pycom_gpy.json | 0 {boards => builder}/qchip.json | 0 {boards => builder}/quantum.json | 0 {boards => builder}/redpill_esp32s3.json | 0 builder/roboheart_hercules.json | 39 +++++++++++ {boards => builder}/s_odi_ultra.json | 0 {boards => builder}/seeed_xiao_esp32c3.json | 8 ++- builder/seeed_xiao_esp32s3.json | 53 +++++++++++++++ {boards => builder}/sensesiot_weizen.json | 0 {boards => builder}/sg-o_airMon.json | 0 .../sparkfun_esp32_iot_redboard.json | 4 +- .../sparkfun_esp32micromod.json | 0 .../sparkfun_esp32s2_thing_plus.json | 0 .../sparkfun_esp32s2_thing_plus_c.json | 0 .../sparkfun_lora_gateway_1-channel.json | 0 {boards => builder}/tamc_termod_s3.json | 2 + {boards => builder}/tinypico.json | 0 .../trueverit-iot-driver-mk2.json | 0 .../trueverit-iot-driver-mk3.json | 0 {boards => builder}/trueverit-iot-driver.json | 0 {boards => builder}/ttgo-lora32-v1.json | 0 {boards => builder}/ttgo-lora32-v2.json | 0 {boards => builder}/ttgo-lora32-v21.json | 0 {boards => builder}/ttgo-t-beam.json | 0 {boards => builder}/ttgo-t-oi-plus.json | 0 {boards => builder}/ttgo-t-watch.json | 0 {boards => builder}/ttgo-t1.json | 0 {boards => builder}/ttgo-t7-v13-mini32.json | 0 {boards => builder}/ttgo-t7-v14-mini32.json | 0 {boards => builder}/turta_iot_node.json | 0 {boards => builder}/um_feathers2.json | 0 {boards => builder}/um_feathers2_neo.json | 0 {boards => builder}/um_feathers3.json | 4 +- {boards => builder}/um_pros3.json | 4 +- {boards => builder}/um_rmp.json | 0 {boards => builder}/um_tinys2.json | 0 {boards => builder}/um_tinys3.json | 4 +- {boards => builder}/unphone7.json | 0 {boards => builder}/unphone8.json | 2 + {boards => builder}/unphone9.json | 4 +- {boards => builder}/upesy_wroom.json | 0 {boards => builder}/upesy_wrover.json | 0 builder/valtrack_v4_mfw_esp32_c3.json | 44 +++++++++++++ builder/valtrack_v4_vts_esp32_c3.json | 44 +++++++++++++ {boards => builder}/vintlabs-devkit-v1.json | 0 {boards => builder}/watchy.json | 0 {boards => builder}/wemos_d1_mini32.json | 0 {boards => builder}/wemos_d1_uno32.json | 0 {boards => builder}/wemosbat.json | 0 {boards => builder}/wesp32.json | 0 {boards => builder}/widora-air.json | 0 {boards => builder}/wifiduino32.json | 0 {boards => builder}/wifiduino32c3.json | 0 {boards => builder}/wifiduino32s3.json | 4 +- {boards => builder}/wipy3.json | 0 {boards => builder}/wt32-eth01.json | 0 {boards => builder}/xinabox_cw02.json | 0 209 files changed, 1022 insertions(+), 149 deletions(-) delete mode 100644 boards/esp32-s2-usb.json delete mode 100644 boards/esp32-s3-usb.json rename {boards => builder}/adafruit_feather_esp32_v2.json (92%) create mode 100644 builder/adafruit_feather_esp32s2_reversetft.json rename {boards => builder}/adafruit_feather_esp32s2_tft.json (80%) rename {boards => builder}/adafruit_feather_esp32s3.json (89%) rename {boards => builder}/adafruit_feather_esp32s3_nopsram.json (88%) create mode 100644 builder/adafruit_feather_esp32s3_reversetft.json rename {boards => builder}/adafruit_feather_esp32s3_tft.json (87%) rename {boards => builder}/adafruit_funhouse_esp32s2.json (100%) rename {boards => builder}/adafruit_itsybitsy_esp32.json (92%) rename {boards => builder}/adafruit_magtag29_esp32s2.json (100%) create mode 100644 builder/adafruit_matrixportal_esp32s3.json rename {boards => builder}/adafruit_metro_esp32s2.json (100%) rename {boards => builder}/adafruit_qtpy_esp32.json (92%) rename {boards => builder}/adafruit_qtpy_esp32c3.json (100%) rename {boards => builder}/adafruit_qtpy_esp32s2.json (100%) rename {boards => builder}/adafruit_qtpy_esp32s3_nopsram.json (85%) rename {boards => builder}/airm2m_core_esp32c3.json (100%) rename {boards => builder}/alksesp32.json (100%) create mode 100644 builder/arduino_nano_esp32.json rename {boards => builder}/atmegazero_esp32s2.json (100%) rename {boards => builder}/az-delivery-devkit-v4.json (100%) rename {boards => builder}/bee_motion.json (100%) rename {boards => builder}/bee_motion_mini.json (100%) rename {boards => builder}/bee_motion_s3.json (92%) rename {boards => builder}/bee_s3.json (88%) rename {boards => builder}/bpi-bit.json (100%) rename {boards => builder}/bpi_leaf_s3.json (100%) rename {boards => builder}/briki_abc_esp32.json (100%) rename {boards => builder}/briki_mbc-wb_esp32.json (100%) rename {boards => builder}/cnrs_aw2eth.json (100%) rename {boards => builder}/connaxio_espoir.json (100%) rename {boards => builder}/cytron_maker_feather_aiot_s3.json (100%) rename {boards => builder}/d-duino-32.json (100%) rename {boards => builder}/deneyapkart.json (79%) rename {boards => builder}/deneyapkart1A.json (78%) rename {boards => builder}/deneyapkart1Av2.json (68%) rename {boards => builder}/deneyapkartg.json (82%) rename {boards => builder}/deneyapmini.json (84%) rename {boards => builder}/deneyapminiv2.json (85%) rename {boards => builder}/denky32.json (100%) rename {boards => builder}/denky_d4.json (100%) rename {boards => builder}/dfrobot_beetle_esp32c3.json (100%) create mode 100644 builder/dfrobot_firebeetle2_esp32e.json rename {boards => builder}/dfrobot_firebeetle2_esp32s3.json (89%) rename boards/ttgo-t-simcam.json => builder/dfrobot_romeo_esp32s3.json (63%) rename {boards => builder}/dpu_esp32.json (100%) create mode 100644 builder/edgebox-esp-100.json rename {boards => builder}/esp-wrover-kit.json (100%) rename boards/esp32-c3-mini.json => builder/esp32-c3-devkitc-02.json (77%) rename {boards => builder}/esp32-c3-devkitm-1.json (96%) rename {boards => builder}/esp32-c3-m1i-kit.json (100%) rename {boards => builder}/esp32-devkitlipo.json (100%) rename {boards => builder}/esp32-evb.json (100%) rename {boards => builder}/esp32-gateway.json (100%) rename {boards => builder}/esp32-poe-iso.json (100%) rename {boards => builder}/esp32-poe.json (100%) rename {boards => builder}/esp32-pro.json (100%) rename {boards => builder}/esp32-s2-franzininho.json (100%) rename {boards => builder}/esp32-s2-kaluga-1.json (100%) rename {boards => builder}/esp32-s2-saola-1.json (100%) rename {boards => builder}/esp32-s3-devkitc-1.json (90%) rename {boards => builder}/esp320.json (100%) rename {boards => builder}/esp32cam.json (100%) rename {boards => builder}/esp32dev.json (100%) rename {boards => builder}/esp32doit-devkit-v1.json (100%) rename {boards => builder}/esp32doit-espduino.json (100%) rename {boards => builder}/esp32s3box.json (100%) rename {boards => builder}/esp32s3camlcd.json (92%) rename {boards => builder}/esp32thing.json (100%) rename {boards => builder}/esp32thing_plus.json (100%) rename {boards => builder}/esp32vn-iot-uno.json (100%) rename {boards => builder}/espea32.json (100%) rename {boards => builder}/espectro32.json (100%) rename {boards => builder}/espino32.json (100%) rename {boards => builder}/etboard.json (100%) rename {boards => builder}/featheresp32-s2.json (100%) rename {boards => builder}/featheresp32.json (100%) rename {boards => builder}/firebeetle32.json (100%) rename {boards => builder}/fm-devkit.json (100%) rename {boards => builder}/franzininho_wifi_esp32s2.json (100%) rename {boards => builder}/franzininho_wifi_msc_esp32s2.json (100%) rename {boards => builder}/frogboard.json (100%) rename {boards => builder}/healthypi4.json (100%) rename {boards => builder}/heltec_wifi_kit_32.json (100%) create mode 100644 builder/heltec_wifi_kit_32_V3.json rename {boards => builder}/heltec_wifi_kit_32_v2.json (100%) rename {boards => builder}/heltec_wifi_lora_32.json (100%) rename {boards => builder}/heltec_wifi_lora_32_V2.json (100%) create mode 100644 builder/heltec_wifi_lora_32_V3.json rename {boards => builder}/heltec_wireless_stick.json (100%) rename {boards => builder}/heltec_wireless_stick_lite.json (100%) rename {boards => builder}/honeylemon.json (100%) rename {boards => builder}/hornbill32dev.json (100%) rename {boards => builder}/hornbill32minima.json (100%) rename {boards => builder}/imbrios-logsens-v1p1.json (100%) rename {boards => builder}/inex_openkb.json (100%) rename {boards => builder}/intorobot.json (100%) rename {boards => builder}/iotaap_magnolia.json (100%) rename {boards => builder}/iotbusio.json (100%) rename {boards => builder}/iotbusproteus.json (100%) rename {boards => builder}/kb32-ft.json (100%) rename {boards => builder}/kits-edu.json (100%) rename {boards => builder}/labplus_mpython.json (100%) create mode 100644 builder/lilygo-t-display-s3.json rename {boards => builder}/lionbit.json (88%) rename {boards => builder}/lolin32.json (100%) rename {boards => builder}/lolin32_lite.json (100%) rename {boards => builder}/lolin_c3_mini.json (100%) rename {boards => builder}/lolin_d32.json (100%) rename {boards => builder}/lolin_d32_pro.json (100%) rename {boards => builder}/lolin_s2_mini.json (96%) rename {boards => builder}/lolin_s2_pico.json (96%) rename {boards => builder}/lolin_s3.json (100%) create mode 100644 builder/lolin_s3_mini.json rename {boards => builder}/lopy.json (100%) rename {boards => builder}/lopy4.json (100%) rename {boards => builder}/m5stack-atom.json (100%) create mode 100644 builder/m5stack-atoms3.json rename {boards => builder}/m5stack-core-esp32.json (100%) rename {boards => builder}/m5stack-core2.json (92%) rename {boards => builder}/m5stack-coreink.json (100%) create mode 100644 builder/m5stack-cores3.json rename {boards => builder}/m5stack-fire.json (100%) rename {boards => builder}/m5stack-grey.json (100%) create mode 100644 builder/m5stack-stamps3.json rename {boards => builder}/m5stack-station.json (100%) rename {boards => builder}/m5stack-timer-cam.json (100%) rename boards/esp32-solo1.json => builder/m5stamp-pico.json (56%) rename {boards => builder}/m5stick-c.json (100%) rename {boards => builder}/magicbit.json (100%) rename {boards => builder}/mgbot-iotik32a.json (100%) rename {boards => builder}/mgbot-iotik32b.json (100%) rename {boards => builder}/mhetesp32devkit.json (100%) rename {boards => builder}/mhetesp32minikit.json (100%) rename {boards => builder}/microduino-core-esp32.json (100%) rename {boards => builder}/micros2.json (100%) rename {boards => builder}/minimain_esp32s2.json (93%) rename {boards => builder}/nano32.json (100%) create mode 100644 builder/nebulas3.json rename {boards => builder}/nina_w10.json (100%) rename {boards => builder}/node32s.json (100%) rename {boards => builder}/nodemcu-32s.json (100%) rename {boards => builder}/nodemcu-32s2.json (100%) rename {boards => builder}/nscreen-32.json (100%) rename {boards => builder}/odroid_esp32.json (100%) rename {boards => builder}/onehorse32dev.json (96%) rename {boards => builder}/oroca_edubot.json (100%) rename {boards => builder}/pico32.json (96%) rename {boards => builder}/piranha_esp32.json (100%) rename {boards => builder}/pocket_32.json (100%) rename {boards => builder}/pycom_gpy.json (100%) rename {boards => builder}/qchip.json (100%) rename {boards => builder}/quantum.json (100%) rename {boards => builder}/redpill_esp32s3.json (100%) create mode 100644 builder/roboheart_hercules.json rename {boards => builder}/s_odi_ultra.json (100%) rename {boards => builder}/seeed_xiao_esp32c3.json (91%) create mode 100644 builder/seeed_xiao_esp32s3.json rename {boards => builder}/sensesiot_weizen.json (100%) rename {boards => builder}/sg-o_airMon.json (100%) rename {boards => builder}/sparkfun_esp32_iot_redboard.json (86%) rename {boards => builder}/sparkfun_esp32micromod.json (100%) rename {boards => builder}/sparkfun_esp32s2_thing_plus.json (100%) rename {boards => builder}/sparkfun_esp32s2_thing_plus_c.json (100%) rename {boards => builder}/sparkfun_lora_gateway_1-channel.json (100%) rename {boards => builder}/tamc_termod_s3.json (92%) rename {boards => builder}/tinypico.json (100%) rename {boards => builder}/trueverit-iot-driver-mk2.json (100%) rename {boards => builder}/trueverit-iot-driver-mk3.json (100%) rename {boards => builder}/trueverit-iot-driver.json (100%) rename {boards => builder}/ttgo-lora32-v1.json (100%) rename {boards => builder}/ttgo-lora32-v2.json (100%) rename {boards => builder}/ttgo-lora32-v21.json (100%) rename {boards => builder}/ttgo-t-beam.json (100%) rename {boards => builder}/ttgo-t-oi-plus.json (100%) rename {boards => builder}/ttgo-t-watch.json (100%) rename {boards => builder}/ttgo-t1.json (100%) rename {boards => builder}/ttgo-t7-v13-mini32.json (100%) rename {boards => builder}/ttgo-t7-v14-mini32.json (100%) rename {boards => builder}/turta_iot_node.json (100%) rename {boards => builder}/um_feathers2.json (100%) rename {boards => builder}/um_feathers2_neo.json (100%) rename {boards => builder}/um_feathers3.json (89%) rename {boards => builder}/um_pros3.json (89%) rename {boards => builder}/um_rmp.json (100%) rename {boards => builder}/um_tinys2.json (100%) rename {boards => builder}/um_tinys3.json (89%) rename {boards => builder}/unphone7.json (100%) rename {boards => builder}/unphone8.json (92%) rename {boards => builder}/unphone9.json (89%) rename {boards => builder}/upesy_wroom.json (100%) rename {boards => builder}/upesy_wrover.json (100%) create mode 100644 builder/valtrack_v4_mfw_esp32_c3.json create mode 100644 builder/valtrack_v4_vts_esp32_c3.json rename {boards => builder}/vintlabs-devkit-v1.json (100%) rename {boards => builder}/watchy.json (100%) rename {boards => builder}/wemos_d1_mini32.json (100%) rename {boards => builder}/wemos_d1_uno32.json (100%) rename {boards => builder}/wemosbat.json (100%) rename {boards => builder}/wesp32.json (100%) rename {boards => builder}/widora-air.json (100%) rename {boards => builder}/wifiduino32.json (100%) rename {boards => builder}/wifiduino32c3.json (100%) rename {boards => builder}/wifiduino32s3.json (88%) rename {boards => builder}/wipy3.json (100%) rename {boards => builder}/wt32-eth01.json (100%) rename {boards => builder}/xinabox_cw02.json (100%) diff --git a/boards/esp32-s2-usb.json b/boards/esp32-s2-usb.json deleted file mode 100644 index 9ef92b3e2..000000000 --- a/boards/esp32-s2-usb.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32s2", - "variant": "adafruit_qtpy_esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit QT Py ESP32-S2", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://www.adafruit.com/product/5325", - "vendor": "Adafruit" -} diff --git a/boards/esp32-s3-usb.json b/boards/esp32-s3-usb.json deleted file mode 100644 index 68153b8f6..000000000 --- a/boards/esp32-s3-usb.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld" - }, - "core": "esp32", - "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32s3", - "variant": "esp32s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Espressif ESP32-S3-DevKitC-1", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 524288, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html", - "vendor": "Espressif" -} diff --git a/boards/adafruit_feather_esp32_v2.json b/builder/adafruit_feather_esp32_v2.json similarity index 92% rename from boards/adafruit_feather_esp32_v2.json rename to builder/adafruit_feather_esp32_v2.json index 78333e8d7..9414b995c 100644 --- a/boards/adafruit_feather_esp32_v2.json +++ b/builder/adafruit_feather_esp32_v2.json @@ -7,6 +7,8 @@ "extra_flags": [ "-DARDUINO_ADAFRUIT_FEATHER_ESP32_V2", "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-mfix-esp32-psram-cache-issue", "-mfix-esp32-psram-cache-strategy=memw" ], diff --git a/builder/adafruit_feather_esp32s2_reversetft.json b/builder/adafruit_feather_esp32s2_reversetft.json new file mode 100644 index 000000000..bd1f3ca8c --- /dev/null +++ b/builder/adafruit_feather_esp32s2_reversetft.json @@ -0,0 +1,63 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_REVTFT", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80ED" + ], + [ + "0x239A", + "0x00ED" + ], + [ + "0x239A", + "0x80EE" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_feather_esp32s2_reversetft" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S2 Reverse TFT", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2_reversetft/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5345", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s2_tft.json b/builder/adafruit_feather_esp32s2_tft.json similarity index 80% rename from boards/adafruit_feather_esp32s2_tft.json rename to builder/adafruit_feather_esp32s2_tft.json index aee443134..e1e948144 100644 --- a/boards/adafruit_feather_esp32s2_tft.json +++ b/builder/adafruit_feather_esp32s2_tft.json @@ -2,7 +2,8 @@ "build": { "arduino": { "ldscript": "esp32s2_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" + "partitions": "partitions-4MB-tinyuf2.csv", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": [ @@ -42,6 +43,14 @@ ], "name": "Adafruit Feather ESP32-S2 TFT", "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2_tft/tinyuf2.bin" + ] + ] + }, "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, diff --git a/boards/adafruit_feather_esp32s3.json b/builder/adafruit_feather_esp32s3.json similarity index 89% rename from boards/adafruit_feather_esp32s3.json rename to builder/adafruit_feather_esp32s3.json index 9778ec20b..5796b0559 100644 --- a/boards/adafruit_feather_esp32s3.json +++ b/builder/adafruit_feather_esp32s3.json @@ -2,12 +2,14 @@ "build": { "arduino":{ "ldscript": "esp32s3_out.ld", - "partitions": "partitions.csv" + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3", "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-DBOARD_HAS_PSRAM" ], "f_cpu": "240000000L", diff --git a/boards/adafruit_feather_esp32s3_nopsram.json b/builder/adafruit_feather_esp32s3_nopsram.json similarity index 88% rename from boards/adafruit_feather_esp32s3_nopsram.json rename to builder/adafruit_feather_esp32s3_nopsram.json index da2550184..79ee24d1d 100644 --- a/boards/adafruit_feather_esp32s3_nopsram.json +++ b/builder/adafruit_feather_esp32s3_nopsram.json @@ -2,12 +2,15 @@ "build": { "arduino":{ "ldscript": "esp32s3_out.ld", + "partitions": "partitions-8MB-tinyuf2.csv", "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/builder/adafruit_feather_esp32s3_reversetft.json b/builder/adafruit_feather_esp32s3_reversetft.json new file mode 100644 index 000000000..fc3b8bc36 --- /dev/null +++ b/builder/adafruit_feather_esp32s3_reversetft.json @@ -0,0 +1,65 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_REVTFT", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8123" + ], + [ + "0x239A", + "0x0123" + ], + [ + "0x239A", + "0x8124" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3_reversetft" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S3 Reverse TFT", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s3_reversetft/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5691", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3_tft.json b/builder/adafruit_feather_esp32s3_tft.json similarity index 87% rename from boards/adafruit_feather_esp32s3_tft.json rename to builder/adafruit_feather_esp32s3_tft.json index 4eb9df9e5..dbf7612bd 100644 --- a/boards/adafruit_feather_esp32s3_tft.json +++ b/builder/adafruit_feather_esp32s3_tft.json @@ -2,12 +2,14 @@ "build": { "arduino": { "ldscript": "esp32s3_out.ld", - "partitions": "partitions.csv" + "partitions": "partitions-4MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/adafruit_funhouse_esp32s2.json b/builder/adafruit_funhouse_esp32s2.json similarity index 100% rename from boards/adafruit_funhouse_esp32s2.json rename to builder/adafruit_funhouse_esp32s2.json diff --git a/boards/adafruit_itsybitsy_esp32.json b/builder/adafruit_itsybitsy_esp32.json similarity index 92% rename from boards/adafruit_itsybitsy_esp32.json rename to builder/adafruit_itsybitsy_esp32.json index 821b285fa..dd87bfccc 100644 --- a/boards/adafruit_itsybitsy_esp32.json +++ b/builder/adafruit_itsybitsy_esp32.json @@ -7,6 +7,8 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_ITSYBITSY_ESP32", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-DBOARD_HAS_PSRAM", "-mfix-esp32-psram-cache-issue", "-mfix-esp32-psram-cache-strategy=memw" diff --git a/boards/adafruit_magtag29_esp32s2.json b/builder/adafruit_magtag29_esp32s2.json similarity index 100% rename from boards/adafruit_magtag29_esp32s2.json rename to builder/adafruit_magtag29_esp32s2.json diff --git a/builder/adafruit_matrixportal_esp32s3.json b/builder/adafruit_matrixportal_esp32s3.json new file mode 100644 index 000000000..3446cd217 --- /dev/null +++ b/builder/adafruit_matrixportal_esp32s3.json @@ -0,0 +1,65 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-8MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8125" + ], + [ + "0x239A", + "0x0125" + ], + [ + "0x239A", + "0x8126" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_matrixportal_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit MatrixPortal ESP32-S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_matrixportal_esp32s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5778", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_metro_esp32s2.json b/builder/adafruit_metro_esp32s2.json similarity index 100% rename from boards/adafruit_metro_esp32s2.json rename to builder/adafruit_metro_esp32s2.json diff --git a/boards/adafruit_qtpy_esp32.json b/builder/adafruit_qtpy_esp32.json similarity index 92% rename from boards/adafruit_qtpy_esp32.json rename to builder/adafruit_qtpy_esp32.json index 9cc3aec42..d2371f7e3 100644 --- a/boards/adafruit_qtpy_esp32.json +++ b/builder/adafruit_qtpy_esp32.json @@ -7,6 +7,8 @@ "extra_flags": [ "-DARDUINO_ADAFRUIT_QTPY_ESP32_PICO", "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-mfix-esp32-psram-cache-issue", "-mfix-esp32-psram-cache-strategy=memw" ], diff --git a/boards/adafruit_qtpy_esp32c3.json b/builder/adafruit_qtpy_esp32c3.json similarity index 100% rename from boards/adafruit_qtpy_esp32c3.json rename to builder/adafruit_qtpy_esp32c3.json diff --git a/boards/adafruit_qtpy_esp32s2.json b/builder/adafruit_qtpy_esp32s2.json similarity index 100% rename from boards/adafruit_qtpy_esp32s2.json rename to builder/adafruit_qtpy_esp32s2.json diff --git a/boards/adafruit_qtpy_esp32s3_nopsram.json b/builder/adafruit_qtpy_esp32s3_nopsram.json similarity index 85% rename from boards/adafruit_qtpy_esp32s3_nopsram.json rename to builder/adafruit_qtpy_esp32s3_nopsram.json index 804bf37e3..15589da92 100644 --- a/boards/adafruit_qtpy_esp32s3_nopsram.json +++ b/builder/adafruit_qtpy_esp32s3_nopsram.json @@ -1,12 +1,15 @@ { "build": { "arduino": { - "ldscript": "esp32s3_out.ld" + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-8MB-tinyuf2.csv" }, "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/airm2m_core_esp32c3.json b/builder/airm2m_core_esp32c3.json similarity index 100% rename from boards/airm2m_core_esp32c3.json rename to builder/airm2m_core_esp32c3.json diff --git a/boards/alksesp32.json b/builder/alksesp32.json similarity index 100% rename from boards/alksesp32.json rename to builder/alksesp32.json diff --git a/builder/arduino_nano_esp32.json b/builder/arduino_nano_esp32.json new file mode 100644 index 000000000..c6da4e227 --- /dev/null +++ b/builder/arduino_nano_esp32.json @@ -0,0 +1,53 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "app3M_fat9M_fact512k_16MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_NANO_ESP32", + "-DBOARD_HAS_PIN_REMAP", + "-DBOARD_HAS_PSRAM", + "-DUSB_MANUFACTURER=\\\"Arduino\\\"", + "-DUSB_PRODUCT=\\\"NanoESP32\\\"", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_DFU_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x2341", + "0x0070" + ] + ], + "mcu": "esp32s3", + "variant": "arduino_nano_nora" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Arduino Nano ESP32", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800, + "protocol": "dfu" + }, + "url": "https://docs.arduino.cc/hardware/nano-esp32", + "vendor": "Arduino" +} diff --git a/boards/atmegazero_esp32s2.json b/builder/atmegazero_esp32s2.json similarity index 100% rename from boards/atmegazero_esp32s2.json rename to builder/atmegazero_esp32s2.json diff --git a/boards/az-delivery-devkit-v4.json b/builder/az-delivery-devkit-v4.json similarity index 100% rename from boards/az-delivery-devkit-v4.json rename to builder/az-delivery-devkit-v4.json diff --git a/boards/bee_motion.json b/builder/bee_motion.json similarity index 100% rename from boards/bee_motion.json rename to builder/bee_motion.json diff --git a/boards/bee_motion_mini.json b/builder/bee_motion_mini.json similarity index 100% rename from boards/bee_motion_mini.json rename to builder/bee_motion_mini.json diff --git a/boards/bee_motion_s3.json b/builder/bee_motion_s3.json similarity index 92% rename from boards/bee_motion_s3.json rename to builder/bee_motion_s3.json index e5f3a1700..c620b80c3 100644 --- a/boards/bee_motion_s3.json +++ b/builder/bee_motion_s3.json @@ -6,6 +6,8 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_BeeMotionS3", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", diff --git a/boards/bee_s3.json b/builder/bee_s3.json similarity index 88% rename from boards/bee_s3.json rename to builder/bee_s3.json index d4bfb9b38..16e47ee79 100644 --- a/boards/bee_s3.json +++ b/builder/bee_s3.json @@ -1,11 +1,13 @@ { "build": { "arduino": { - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s3_out.ld" }, "core": "esp32", "extra_flags": [ "-DARDUINO_Bee_S3", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", diff --git a/boards/bpi-bit.json b/builder/bpi-bit.json similarity index 100% rename from boards/bpi-bit.json rename to builder/bpi-bit.json diff --git a/boards/bpi_leaf_s3.json b/builder/bpi_leaf_s3.json similarity index 100% rename from boards/bpi_leaf_s3.json rename to builder/bpi_leaf_s3.json diff --git a/boards/briki_abc_esp32.json b/builder/briki_abc_esp32.json similarity index 100% rename from boards/briki_abc_esp32.json rename to builder/briki_abc_esp32.json diff --git a/boards/briki_mbc-wb_esp32.json b/builder/briki_mbc-wb_esp32.json similarity index 100% rename from boards/briki_mbc-wb_esp32.json rename to builder/briki_mbc-wb_esp32.json diff --git a/boards/cnrs_aw2eth.json b/builder/cnrs_aw2eth.json similarity index 100% rename from boards/cnrs_aw2eth.json rename to builder/cnrs_aw2eth.json diff --git a/boards/connaxio_espoir.json b/builder/connaxio_espoir.json similarity index 100% rename from boards/connaxio_espoir.json rename to builder/connaxio_espoir.json diff --git a/boards/cytron_maker_feather_aiot_s3.json b/builder/cytron_maker_feather_aiot_s3.json similarity index 100% rename from boards/cytron_maker_feather_aiot_s3.json rename to builder/cytron_maker_feather_aiot_s3.json diff --git a/boards/d-duino-32.json b/builder/d-duino-32.json similarity index 100% rename from boards/d-duino-32.json rename to builder/d-duino-32.json diff --git a/boards/deneyapkart.json b/builder/deneyapkart.json similarity index 79% rename from boards/deneyapkart.json rename to builder/deneyapkart.json index 018813d78..7d499bd4b 100644 --- a/boards/deneyapkart.json +++ b/builder/deneyapkart.json @@ -7,6 +7,8 @@ "extra_flags": [ "-DARDUINO_DYDK", "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-mfix-esp32-psram-cache-issue", "-mfix-esp32-psram-cache-strategy=memw" ], @@ -18,8 +20,7 @@ }, "connectivity": [ "wifi", - "bluetooth", - "ethernet" + "bluetooth" ], "debug": { "openocd_board": "esp32-wrover.cfg" @@ -36,6 +37,6 @@ "require_upload_port": true, "speed": 460800 }, - "url": "https://deneyapkart.org/magaza/urun-deneyap-kart.html", - "vendor": "Deneyap" + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart", + "vendor": "T3 Foundation" } diff --git a/boards/deneyapkart1A.json b/builder/deneyapkart1A.json similarity index 78% rename from boards/deneyapkart1A.json rename to builder/deneyapkart1A.json index 8aac1883f..46f513fac 100644 --- a/boards/deneyapkart1A.json +++ b/builder/deneyapkart1A.json @@ -7,6 +7,8 @@ "extra_flags": [ "-DARDUINO_DYDK1A", "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-mfix-esp32-psram-cache-issue", "-mfix-esp32-psram-cache-strategy=memw" ], @@ -18,8 +20,7 @@ }, "connectivity": [ "wifi", - "bluetooth", - "ethernet" + "bluetooth" ], "debug": { "openocd_board": "esp32-wrover.cfg" @@ -36,6 +37,6 @@ "require_upload_port": true, "speed": 460800 }, - "url": "https://deneyapkart.org/magaza/urun-deneyap-kart.html", - "vendor": "Deneyap" + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart-1a", + "vendor": "T3 Foundation" } diff --git a/boards/deneyapkart1Av2.json b/builder/deneyapkart1Av2.json similarity index 68% rename from boards/deneyapkart1Av2.json rename to builder/deneyapkart1Av2.json index b287551aa..e57a00846 100644 --- a/boards/deneyapkart1Av2.json +++ b/builder/deneyapkart1Av2.json @@ -2,12 +2,16 @@ "build": { "arduino": { "ldscript": "esp32s3_out.ld", - "memory_type": "qio_qspi" + "memory_type": "qio_opi" }, "core": "esp32", "extra_flags": [ "-DARDUINO_DYDK1Av2", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", @@ -22,7 +26,8 @@ "variant": "deneyapkart1Av2" }, "connectivity": [ - "wifi" + "wifi", + "bluetooth" ], "debug": { "openocd_target": "esp32s3.cfg" @@ -41,6 +46,6 @@ "require_upload_port": true, "speed": 460800 }, - "url": "https://wiki.banana-pi.org/BPI-Leaf-S3", - "vendor": "Deneyap" + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart-1a-v2-type-c", + "vendor": "T3 Foundation" } diff --git a/boards/deneyapkartg.json b/builder/deneyapkartg.json similarity index 82% rename from boards/deneyapkartg.json rename to builder/deneyapkartg.json index 8b0bb333a..19f1b0415 100644 --- a/boards/deneyapkartg.json +++ b/builder/deneyapkartg.json @@ -4,19 +4,20 @@ "ldscript": "esp32c3_out.ld" }, "core": "esp32", - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", "extra_flags": [ "-DARDUINO_DYG", "-DARDUINO_USB_MODE=1", "-DARDUINO_USB_CDC_ON_BOOT=1" ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", "mcu": "esp32c3", "variant": "deneyapkartg" }, "connectivity": [ - "wifi" + "wifi", + "bluetooth" ], "debug": { "openocd_target": "esp32c3.cfg" @@ -33,6 +34,6 @@ "require_upload_port": true, "speed": 460800 }, - "url": "https://deneyapkart.org/en/", - "vendor": "Deneyap" + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart-g-type-c", + "vendor": "T3 Foundation" } diff --git a/boards/deneyapmini.json b/builder/deneyapmini.json similarity index 84% rename from boards/deneyapmini.json rename to builder/deneyapmini.json index 046fcba0b..5a358cdb5 100644 --- a/boards/deneyapmini.json +++ b/builder/deneyapmini.json @@ -21,9 +21,7 @@ "variant": "deneyapmini" }, "connectivity": [ - "wifi", - "bluetooth", - "ethernet" + "wifi" ], "debug": { "openocd_target": "esp32s2.cfg" @@ -42,6 +40,6 @@ "require_upload_port": true, "speed": 460800 }, - "url": "https://deneyapkart.org/magaza/urun-deneyap-kart-mini.html", - "vendor": "Deneyap" + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-mini", + "vendor": "T3 Foundation" } diff --git a/boards/deneyapminiv2.json b/builder/deneyapminiv2.json similarity index 85% rename from boards/deneyapminiv2.json rename to builder/deneyapminiv2.json index b0c6cfdeb..42058a81b 100644 --- a/boards/deneyapminiv2.json +++ b/builder/deneyapminiv2.json @@ -5,8 +5,8 @@ }, "core": "esp32", "extra_flags": [ - "-DBOARD_HAS_PSRAM", "-DARDUINO_DYMv2", + "-DBOARD_HAS_PSRAM", "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", @@ -22,9 +22,7 @@ "variant": "deneyapminiv2" }, "connectivity": [ - "wifi", - "bluetooth", - "ethernet" + "wifi" ], "debug": { "openocd_target": "esp32s2.cfg" @@ -43,6 +41,6 @@ "require_upload_port": true, "speed": 460800 }, - "url": "https://deneyapkart.org/magaza/urun-deneyap-kart-mini.html", - "vendor": "Deneyap" + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-mini-v2-type-c", + "vendor": "T3 Foundation" } diff --git a/boards/denky32.json b/builder/denky32.json similarity index 100% rename from boards/denky32.json rename to builder/denky32.json diff --git a/boards/denky_d4.json b/builder/denky_d4.json similarity index 100% rename from boards/denky_d4.json rename to builder/denky_d4.json diff --git a/boards/dfrobot_beetle_esp32c3.json b/builder/dfrobot_beetle_esp32c3.json similarity index 100% rename from boards/dfrobot_beetle_esp32c3.json rename to builder/dfrobot_beetle_esp32c3.json diff --git a/builder/dfrobot_firebeetle2_esp32e.json b/builder/dfrobot_firebeetle2_esp32e.json new file mode 100644 index 000000000..0d3790cf1 --- /dev/null +++ b/builder/dfrobot_firebeetle2_esp32e.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DFROBOT_FIREBEETLE_2_ESP32E", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "dfrobot_firebeetle2_esp32e" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DFRobot Firebeetle 2 ESP32-E", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.dfrobot.com/FireBeetle_Board_ESP32_E_SKU_DFR0654", + "vendor": "DFRobot" +} diff --git a/boards/dfrobot_firebeetle2_esp32s3.json b/builder/dfrobot_firebeetle2_esp32s3.json similarity index 89% rename from boards/dfrobot_firebeetle2_esp32s3.json rename to builder/dfrobot_firebeetle2_esp32s3.json index 83d842d3f..0f87150d6 100644 --- a/boards/dfrobot_firebeetle2_esp32s3.json +++ b/builder/dfrobot_firebeetle2_esp32s3.json @@ -6,7 +6,9 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ESP32S3_DEV", - "-DARDUINO_USB_MODE=1" + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/ttgo-t-simcam.json b/builder/dfrobot_romeo_esp32s3.json similarity index 63% rename from boards/ttgo-t-simcam.json rename to builder/dfrobot_romeo_esp32s3.json index 1f3314e05..63a7cb472 100644 --- a/boards/ttgo-t-simcam.json +++ b/builder/dfrobot_romeo_esp32s3.json @@ -1,14 +1,16 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32s3_out.ld", + "partitions": "app3M_fat9M_16MB.csv", "memory_type": "qio_opi" }, "core": "esp32", "extra_flags": [ - "-DBOARD_HAS_PSRAM", - "-DARDUINO_ESP32S3_CAM_LCD", - "-DARDUINO_USB_MODE=1" + "-DARDUINO_DFROBOT_ROMEO_ESP32S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", @@ -20,11 +22,10 @@ ] ], "mcu": "esp32s3", - "variant": "esp32s3" + "variant": "dfrobot_romeo_esp32s3" }, "connectivity": [ - "wifi", - "bluetooth" + "wifi" ], "debug": { "openocd_target": "esp32s3.cfg" @@ -33,15 +34,14 @@ "arduino", "espidf" ], - "name": "LilyGo T-SIMCAM ESP32-S3 16M QIO Flash 8MB OPI PSRAM", + "name": "DFRobot Romeo ESP32-S3", "upload": { "flash_size": "16MB", "maximum_ram_size": 327680, "maximum_size": 16777216, "require_upload_port": true, - "before_reset": "usb_reset", "speed": 460800 }, - "url": "https://github.com/Xinyuan-LilyGO/LilyGo-Camera-Series", - "vendor": "LilyGo" + "url": "https://wiki.dfrobot.com/", + "vendor": "DFRobot" } diff --git a/boards/dpu_esp32.json b/builder/dpu_esp32.json similarity index 100% rename from boards/dpu_esp32.json rename to builder/dpu_esp32.json diff --git a/builder/edgebox-esp-100.json b/builder/edgebox-esp-100.json new file mode 100644 index 000000000..22aee2f8b --- /dev/null +++ b/builder/edgebox-esp-100.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_Edgebox_ESP_100", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s3", + "variant": "Edgebox-ESP-100" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Seeed Studio Edgebox-ESP-100", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.seeedstudio.com/EdgeBox-ESP-100-p-5490.html", + "vendor": "Seeed Studio" +} diff --git a/boards/esp-wrover-kit.json b/builder/esp-wrover-kit.json similarity index 100% rename from boards/esp-wrover-kit.json rename to builder/esp-wrover-kit.json diff --git a/boards/esp32-c3-mini.json b/builder/esp32-c3-devkitc-02.json similarity index 77% rename from boards/esp32-c3-mini.json rename to builder/esp32-c3-devkitc-02.json index 936f27c26..320b763a0 100644 --- a/boards/esp32-c3-mini.json +++ b/builder/esp32-c3-devkitc-02.json @@ -4,15 +4,16 @@ "ldscript": "esp32c3_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1", "f_cpu": "160000000L", "f_flash": "80000000L", "flash_mode": "qio", + "extra_flags": "-DARDUINO_ESP32C3_DEV", "mcu": "esp32c3", "variant": "esp32c3" }, "connectivity": [ - "wifi" + "wifi", + "bluetooth" ], "debug": { "openocd_target": "esp32c3.cfg" @@ -21,7 +22,7 @@ "arduino", "espidf" ], - "name": "Espressif ESP32-C3-MINI", + "name": "Espressif ESP32-C3-DevKitC-02", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, @@ -29,6 +30,6 @@ "require_upload_port": true, "speed": 460800 }, - "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html", + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitc-02.html", "vendor": "Espressif" } diff --git a/boards/esp32-c3-devkitm-1.json b/builder/esp32-c3-devkitm-1.json similarity index 96% rename from boards/esp32-c3-devkitm-1.json rename to builder/esp32-c3-devkitm-1.json index bc4ba058c..cf1a5736a 100644 --- a/boards/esp32-c3-devkitm-1.json +++ b/builder/esp32-c3-devkitm-1.json @@ -12,7 +12,8 @@ "variant": "esp32c3" }, "connectivity": [ - "wifi" + "wifi", + "bluetooth" ], "debug": { "openocd_target": "esp32c3.cfg" diff --git a/boards/esp32-c3-m1i-kit.json b/builder/esp32-c3-m1i-kit.json similarity index 100% rename from boards/esp32-c3-m1i-kit.json rename to builder/esp32-c3-m1i-kit.json diff --git a/boards/esp32-devkitlipo.json b/builder/esp32-devkitlipo.json similarity index 100% rename from boards/esp32-devkitlipo.json rename to builder/esp32-devkitlipo.json diff --git a/boards/esp32-evb.json b/builder/esp32-evb.json similarity index 100% rename from boards/esp32-evb.json rename to builder/esp32-evb.json diff --git a/boards/esp32-gateway.json b/builder/esp32-gateway.json similarity index 100% rename from boards/esp32-gateway.json rename to builder/esp32-gateway.json diff --git a/boards/esp32-poe-iso.json b/builder/esp32-poe-iso.json similarity index 100% rename from boards/esp32-poe-iso.json rename to builder/esp32-poe-iso.json diff --git a/boards/esp32-poe.json b/builder/esp32-poe.json similarity index 100% rename from boards/esp32-poe.json rename to builder/esp32-poe.json diff --git a/boards/esp32-pro.json b/builder/esp32-pro.json similarity index 100% rename from boards/esp32-pro.json rename to builder/esp32-pro.json diff --git a/boards/esp32-s2-franzininho.json b/builder/esp32-s2-franzininho.json similarity index 100% rename from boards/esp32-s2-franzininho.json rename to builder/esp32-s2-franzininho.json diff --git a/boards/esp32-s2-kaluga-1.json b/builder/esp32-s2-kaluga-1.json similarity index 100% rename from boards/esp32-s2-kaluga-1.json rename to builder/esp32-s2-kaluga-1.json diff --git a/boards/esp32-s2-saola-1.json b/builder/esp32-s2-saola-1.json similarity index 100% rename from boards/esp32-s2-saola-1.json rename to builder/esp32-s2-saola-1.json diff --git a/boards/esp32-s3-devkitc-1.json b/builder/esp32-s3-devkitc-1.json similarity index 90% rename from boards/esp32-s3-devkitc-1.json rename to builder/esp32-s3-devkitc-1.json index 31b2ab4da..a2f8b22f5 100644 --- a/boards/esp32-s3-devkitc-1.json +++ b/builder/esp32-s3-devkitc-1.json @@ -7,7 +7,9 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_ESP32S3_DEV", - "-DARDUINO_USB_MODE=1" + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/esp320.json b/builder/esp320.json similarity index 100% rename from boards/esp320.json rename to builder/esp320.json diff --git a/boards/esp32cam.json b/builder/esp32cam.json similarity index 100% rename from boards/esp32cam.json rename to builder/esp32cam.json diff --git a/boards/esp32dev.json b/builder/esp32dev.json similarity index 100% rename from boards/esp32dev.json rename to builder/esp32dev.json diff --git a/boards/esp32doit-devkit-v1.json b/builder/esp32doit-devkit-v1.json similarity index 100% rename from boards/esp32doit-devkit-v1.json rename to builder/esp32doit-devkit-v1.json diff --git a/boards/esp32doit-espduino.json b/builder/esp32doit-espduino.json similarity index 100% rename from boards/esp32doit-espduino.json rename to builder/esp32doit-espduino.json diff --git a/boards/esp32s3box.json b/builder/esp32s3box.json similarity index 100% rename from boards/esp32s3box.json rename to builder/esp32s3box.json diff --git a/boards/esp32s3camlcd.json b/builder/esp32s3camlcd.json similarity index 92% rename from boards/esp32s3camlcd.json rename to builder/esp32s3camlcd.json index 79231614a..5a807a858 100644 --- a/boards/esp32s3camlcd.json +++ b/builder/esp32s3camlcd.json @@ -7,6 +7,8 @@ "boot": "opi", "core": "esp32", "extra_flags": [ + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-DBOARD_HAS_PSRAM", "-DARDUINO_ESP32S3_CAM_LCD", "-DARDUINO_USB_MODE=1" diff --git a/boards/esp32thing.json b/builder/esp32thing.json similarity index 100% rename from boards/esp32thing.json rename to builder/esp32thing.json diff --git a/boards/esp32thing_plus.json b/builder/esp32thing_plus.json similarity index 100% rename from boards/esp32thing_plus.json rename to builder/esp32thing_plus.json diff --git a/boards/esp32vn-iot-uno.json b/builder/esp32vn-iot-uno.json similarity index 100% rename from boards/esp32vn-iot-uno.json rename to builder/esp32vn-iot-uno.json diff --git a/boards/espea32.json b/builder/espea32.json similarity index 100% rename from boards/espea32.json rename to builder/espea32.json diff --git a/boards/espectro32.json b/builder/espectro32.json similarity index 100% rename from boards/espectro32.json rename to builder/espectro32.json diff --git a/boards/espino32.json b/builder/espino32.json similarity index 100% rename from boards/espino32.json rename to builder/espino32.json diff --git a/boards/etboard.json b/builder/etboard.json similarity index 100% rename from boards/etboard.json rename to builder/etboard.json diff --git a/boards/featheresp32-s2.json b/builder/featheresp32-s2.json similarity index 100% rename from boards/featheresp32-s2.json rename to builder/featheresp32-s2.json diff --git a/boards/featheresp32.json b/builder/featheresp32.json similarity index 100% rename from boards/featheresp32.json rename to builder/featheresp32.json diff --git a/boards/firebeetle32.json b/builder/firebeetle32.json similarity index 100% rename from boards/firebeetle32.json rename to builder/firebeetle32.json diff --git a/boards/fm-devkit.json b/builder/fm-devkit.json similarity index 100% rename from boards/fm-devkit.json rename to builder/fm-devkit.json diff --git a/boards/franzininho_wifi_esp32s2.json b/builder/franzininho_wifi_esp32s2.json similarity index 100% rename from boards/franzininho_wifi_esp32s2.json rename to builder/franzininho_wifi_esp32s2.json diff --git a/boards/franzininho_wifi_msc_esp32s2.json b/builder/franzininho_wifi_msc_esp32s2.json similarity index 100% rename from boards/franzininho_wifi_msc_esp32s2.json rename to builder/franzininho_wifi_msc_esp32s2.json diff --git a/boards/frogboard.json b/builder/frogboard.json similarity index 100% rename from boards/frogboard.json rename to builder/frogboard.json diff --git a/boards/healthypi4.json b/builder/healthypi4.json similarity index 100% rename from boards/healthypi4.json rename to builder/healthypi4.json diff --git a/boards/heltec_wifi_kit_32.json b/builder/heltec_wifi_kit_32.json similarity index 100% rename from boards/heltec_wifi_kit_32.json rename to builder/heltec_wifi_kit_32.json diff --git a/builder/heltec_wifi_kit_32_V3.json b/builder/heltec_wifi_kit_32_V3.json new file mode 100644 index 000000000..d10631917 --- /dev/null +++ b/builder/heltec_wifi_kit_32_V3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_heltec_wifi_kit_32_V3", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "heltec_wifi_kit_32_v3" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec WiFi Kit 32 (V3)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://heltec.org/project/wifi-kit-32-v3/", + "vendor": "Heltec" +} diff --git a/boards/heltec_wifi_kit_32_v2.json b/builder/heltec_wifi_kit_32_v2.json similarity index 100% rename from boards/heltec_wifi_kit_32_v2.json rename to builder/heltec_wifi_kit_32_v2.json diff --git a/boards/heltec_wifi_lora_32.json b/builder/heltec_wifi_lora_32.json similarity index 100% rename from boards/heltec_wifi_lora_32.json rename to builder/heltec_wifi_lora_32.json diff --git a/boards/heltec_wifi_lora_32_V2.json b/builder/heltec_wifi_lora_32_V2.json similarity index 100% rename from boards/heltec_wifi_lora_32_V2.json rename to builder/heltec_wifi_lora_32_V2.json diff --git a/builder/heltec_wifi_lora_32_V3.json b/builder/heltec_wifi_lora_32_V3.json new file mode 100644 index 000000000..09a8e1c74 --- /dev/null +++ b/builder/heltec_wifi_lora_32_V3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_heltec_wifi_lora_32_V3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "heltec_wifi_lora_32_V3" + }, + "connectivity": [ + "wifi", + "bluetooth", + "lora" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec WiFi LoRa 32 (V3)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://heltec.org/project/wifi-lora-32-v3/", + "vendor": "Heltec" +} diff --git a/boards/heltec_wireless_stick.json b/builder/heltec_wireless_stick.json similarity index 100% rename from boards/heltec_wireless_stick.json rename to builder/heltec_wireless_stick.json diff --git a/boards/heltec_wireless_stick_lite.json b/builder/heltec_wireless_stick_lite.json similarity index 100% rename from boards/heltec_wireless_stick_lite.json rename to builder/heltec_wireless_stick_lite.json diff --git a/boards/honeylemon.json b/builder/honeylemon.json similarity index 100% rename from boards/honeylemon.json rename to builder/honeylemon.json diff --git a/boards/hornbill32dev.json b/builder/hornbill32dev.json similarity index 100% rename from boards/hornbill32dev.json rename to builder/hornbill32dev.json diff --git a/boards/hornbill32minima.json b/builder/hornbill32minima.json similarity index 100% rename from boards/hornbill32minima.json rename to builder/hornbill32minima.json diff --git a/boards/imbrios-logsens-v1p1.json b/builder/imbrios-logsens-v1p1.json similarity index 100% rename from boards/imbrios-logsens-v1p1.json rename to builder/imbrios-logsens-v1p1.json diff --git a/boards/inex_openkb.json b/builder/inex_openkb.json similarity index 100% rename from boards/inex_openkb.json rename to builder/inex_openkb.json diff --git a/boards/intorobot.json b/builder/intorobot.json similarity index 100% rename from boards/intorobot.json rename to builder/intorobot.json diff --git a/boards/iotaap_magnolia.json b/builder/iotaap_magnolia.json similarity index 100% rename from boards/iotaap_magnolia.json rename to builder/iotaap_magnolia.json diff --git a/boards/iotbusio.json b/builder/iotbusio.json similarity index 100% rename from boards/iotbusio.json rename to builder/iotbusio.json diff --git a/boards/iotbusproteus.json b/builder/iotbusproteus.json similarity index 100% rename from boards/iotbusproteus.json rename to builder/iotbusproteus.json diff --git a/boards/kb32-ft.json b/builder/kb32-ft.json similarity index 100% rename from boards/kb32-ft.json rename to builder/kb32-ft.json diff --git a/boards/kits-edu.json b/builder/kits-edu.json similarity index 100% rename from boards/kits-edu.json rename to builder/kits-edu.json diff --git a/boards/labplus_mpython.json b/builder/labplus_mpython.json similarity index 100% rename from boards/labplus_mpython.json rename to builder/labplus_mpython.json diff --git a/builder/lilygo-t-display-s3.json b/builder/lilygo-t-display-s3.json new file mode 100644 index 000000000..7230d3bd2 --- /dev/null +++ b/builder/lilygo-t-display-s3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LILYGO_T_DISPLAY_S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "lilygo_t_display_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "LilyGo T-Display-S3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.lilygo.cc/products/t-display-s3", + "vendor": "LilyGo" +} diff --git a/boards/lionbit.json b/builder/lionbit.json similarity index 88% rename from boards/lionbit.json rename to builder/lionbit.json index 92c20d138..c8186d0b2 100644 --- a/boards/lionbit.json +++ b/builder/lionbit.json @@ -5,7 +5,9 @@ }, "core": "esp32", "extra_flags": [ - "-DARDUINO_LIONBIT" + "-DARDUINO_LIONBIT", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "40000000L", diff --git a/boards/lolin32.json b/builder/lolin32.json similarity index 100% rename from boards/lolin32.json rename to builder/lolin32.json diff --git a/boards/lolin32_lite.json b/builder/lolin32_lite.json similarity index 100% rename from boards/lolin32_lite.json rename to builder/lolin32_lite.json diff --git a/boards/lolin_c3_mini.json b/builder/lolin_c3_mini.json similarity index 100% rename from boards/lolin_c3_mini.json rename to builder/lolin_c3_mini.json diff --git a/boards/lolin_d32.json b/builder/lolin_d32.json similarity index 100% rename from boards/lolin_d32.json rename to builder/lolin_d32.json diff --git a/boards/lolin_d32_pro.json b/builder/lolin_d32_pro.json similarity index 100% rename from boards/lolin_d32_pro.json rename to builder/lolin_d32_pro.json diff --git a/boards/lolin_s2_mini.json b/builder/lolin_s2_mini.json similarity index 96% rename from boards/lolin_s2_mini.json rename to builder/lolin_s2_mini.json index 3fe4f7122..59832f8cb 100644 --- a/boards/lolin_s2_mini.json +++ b/builder/lolin_s2_mini.json @@ -25,7 +25,7 @@ "wifi" ], "debug": { - "openocd_board": "esp32s2.cfg" + "openocd_target": "esp32s2.cfg" }, "frameworks": [ "arduino", diff --git a/boards/lolin_s2_pico.json b/builder/lolin_s2_pico.json similarity index 96% rename from boards/lolin_s2_pico.json rename to builder/lolin_s2_pico.json index dab2b7ec0..0214a0eea 100644 --- a/boards/lolin_s2_pico.json +++ b/builder/lolin_s2_pico.json @@ -25,7 +25,7 @@ "wifi" ], "debug": { - "openocd_board": "esp32s2.cfg" + "openocd_target": "esp32s2.cfg" }, "frameworks": [ "arduino", diff --git a/boards/lolin_s3.json b/builder/lolin_s3.json similarity index 100% rename from boards/lolin_s3.json rename to builder/lolin_s3.json diff --git a/builder/lolin_s3_mini.json b/builder/lolin_s3_mini.json new file mode 100644 index 000000000..ad3794bcb --- /dev/null +++ b/builder/lolin_s3_mini.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_LOLIN_S3_MINI", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8167" + ] + ], + "mcu": "esp32s3", + "variant": "lolin_s3_mini" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S3 Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc/en/latest/s3/index.html", + "vendor": "WEMOS" +} + \ No newline at end of file diff --git a/boards/lopy.json b/builder/lopy.json similarity index 100% rename from boards/lopy.json rename to builder/lopy.json diff --git a/boards/lopy4.json b/builder/lopy4.json similarity index 100% rename from boards/lopy4.json rename to builder/lopy4.json diff --git a/boards/m5stack-atom.json b/builder/m5stack-atom.json similarity index 100% rename from boards/m5stack-atom.json rename to builder/m5stack-atom.json diff --git a/builder/m5stack-atoms3.json b/builder/m5stack-atoms3.json new file mode 100644 index 000000000..f5e87d3ab --- /dev/null +++ b/builder/m5stack-atoms3.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_M5Stack_ATOMS3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "m5stack_atoms3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack AtomS3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.m5stack.com/en/core/AtomS3", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-core-esp32.json b/builder/m5stack-core-esp32.json similarity index 100% rename from boards/m5stack-core-esp32.json rename to builder/m5stack-core-esp32.json diff --git a/boards/m5stack-core2.json b/builder/m5stack-core2.json similarity index 92% rename from boards/m5stack-core2.json rename to builder/m5stack-core2.json index c860124e2..2c3b95154 100644 --- a/boards/m5stack-core2.json +++ b/builder/m5stack-core2.json @@ -7,8 +7,8 @@ "core": "esp32", "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM", "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", + "f_flash": "40000000L", + "flash_mode": "dio", "mcu": "esp32", "variant": "m5stack_core2" }, diff --git a/boards/m5stack-coreink.json b/builder/m5stack-coreink.json similarity index 100% rename from boards/m5stack-coreink.json rename to builder/m5stack-coreink.json diff --git a/builder/m5stack-cores3.json b/builder/m5stack-cores3.json new file mode 100644 index 000000000..72571e0b7 --- /dev/null +++ b/builder/m5stack-cores3.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_M5STACK_CORES3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8119" + ] + ], + "mcu": "esp32s3", + "variant": "m5stack_cores3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack CoreS3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://docs.m5stack.com/en/core/CoreS3", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-fire.json b/builder/m5stack-fire.json similarity index 100% rename from boards/m5stack-fire.json rename to builder/m5stack-fire.json diff --git a/boards/m5stack-grey.json b/builder/m5stack-grey.json similarity index 100% rename from boards/m5stack-grey.json rename to builder/m5stack-grey.json diff --git a/builder/m5stack-stamps3.json b/builder/m5stack-stamps3.json new file mode 100644 index 000000000..6c92e3b5d --- /dev/null +++ b/builder/m5stack-stamps3.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_M5Stack_StampS3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "m5stack_stamp_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack StampS3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.m5stack.com/en/core/StampS3", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-station.json b/builder/m5stack-station.json similarity index 100% rename from boards/m5stack-station.json rename to builder/m5stack-station.json diff --git a/boards/m5stack-timer-cam.json b/builder/m5stack-timer-cam.json similarity index 100% rename from boards/m5stack-timer-cam.json rename to builder/m5stack-timer-cam.json diff --git a/boards/esp32-solo1.json b/builder/m5stamp-pico.json similarity index 56% rename from boards/esp32-solo1.json rename to builder/m5stamp-pico.json index e87b7e13d..8f39fe5ce 100644 --- a/boards/esp32-solo1.json +++ b/builder/m5stamp-pico.json @@ -4,12 +4,12 @@ "ldscript": "esp32_out.ld" }, "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV -DARDUINO_USB_CDC_ON_BOOT=0 -DCORE32SOLO1", - "f_cpu": "80000000L", + "extra_flags": "-DARDUINO_M5Stamp_Pico", + "f_cpu": "240000000L", "f_flash": "40000000L", "flash_mode": "dio", "mcu": "esp32", - "variant": "esp32" + "variant": "m5stack_stamp_pico" }, "connectivity": [ "wifi", @@ -17,21 +17,18 @@ "ethernet", "can" ], - "debug": { - "openocd_target": "esp32-solo-1.cfg" - }, "frameworks": [ "arduino", "espidf" ], - "name": "Espressif Generic ESP32-solo1 4M Flash", + "name": "M5Stamp-Pico", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, "maximum_size": 4194304, "require_upload_port": true, - "speed": 460800 + "speed": 1500000 }, - "url": "https://en.wikipedia.org/wiki/ESP32", - "vendor": "Espressif" + "url": "https://shop.m5stack.com/products/m5stamp-pico-mate-with-pin-headers", + "vendor": "M5Stack" } diff --git a/boards/m5stick-c.json b/builder/m5stick-c.json similarity index 100% rename from boards/m5stick-c.json rename to builder/m5stick-c.json diff --git a/boards/magicbit.json b/builder/magicbit.json similarity index 100% rename from boards/magicbit.json rename to builder/magicbit.json diff --git a/boards/mgbot-iotik32a.json b/builder/mgbot-iotik32a.json similarity index 100% rename from boards/mgbot-iotik32a.json rename to builder/mgbot-iotik32a.json diff --git a/boards/mgbot-iotik32b.json b/builder/mgbot-iotik32b.json similarity index 100% rename from boards/mgbot-iotik32b.json rename to builder/mgbot-iotik32b.json diff --git a/boards/mhetesp32devkit.json b/builder/mhetesp32devkit.json similarity index 100% rename from boards/mhetesp32devkit.json rename to builder/mhetesp32devkit.json diff --git a/boards/mhetesp32minikit.json b/builder/mhetesp32minikit.json similarity index 100% rename from boards/mhetesp32minikit.json rename to builder/mhetesp32minikit.json diff --git a/boards/microduino-core-esp32.json b/builder/microduino-core-esp32.json similarity index 100% rename from boards/microduino-core-esp32.json rename to builder/microduino-core-esp32.json diff --git a/boards/micros2.json b/builder/micros2.json similarity index 100% rename from boards/micros2.json rename to builder/micros2.json diff --git a/boards/minimain_esp32s2.json b/builder/minimain_esp32s2.json similarity index 93% rename from boards/minimain_esp32s2.json rename to builder/minimain_esp32s2.json index 0f537fd7b..5502a6aff 100644 --- a/boards/minimain_esp32s2.json +++ b/builder/minimain_esp32s2.json @@ -7,6 +7,8 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_DEPARTMENT_OF_ALCHEMY_MINIMAIN_ESP32S2", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-DBOARD_HAS_PSRAM", "-DARDUINO_USB_MODE=1", "-DARDUINO_USB_CDC_ON_BOOT=1" diff --git a/boards/nano32.json b/builder/nano32.json similarity index 100% rename from boards/nano32.json rename to builder/nano32.json diff --git a/builder/nebulas3.json b/builder/nebulas3.json new file mode 100644 index 000000000..dc6236494 --- /dev/null +++ b/builder/nebulas3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_NEBULAS3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "Nebula_S3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Kinetic Dynamics Nebula S3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://kineticdynamics.in/product/nebula-s3/", + "vendor": "Kinetic Dynamics" +} diff --git a/boards/nina_w10.json b/builder/nina_w10.json similarity index 100% rename from boards/nina_w10.json rename to builder/nina_w10.json diff --git a/boards/node32s.json b/builder/node32s.json similarity index 100% rename from boards/node32s.json rename to builder/node32s.json diff --git a/boards/nodemcu-32s.json b/builder/nodemcu-32s.json similarity index 100% rename from boards/nodemcu-32s.json rename to builder/nodemcu-32s.json diff --git a/boards/nodemcu-32s2.json b/builder/nodemcu-32s2.json similarity index 100% rename from boards/nodemcu-32s2.json rename to builder/nodemcu-32s2.json diff --git a/boards/nscreen-32.json b/builder/nscreen-32.json similarity index 100% rename from boards/nscreen-32.json rename to builder/nscreen-32.json diff --git a/boards/odroid_esp32.json b/builder/odroid_esp32.json similarity index 100% rename from boards/odroid_esp32.json rename to builder/odroid_esp32.json diff --git a/boards/onehorse32dev.json b/builder/onehorse32dev.json similarity index 96% rename from boards/onehorse32dev.json rename to builder/onehorse32dev.json index 42a2f00a5..4b2364100 100644 --- a/boards/onehorse32dev.json +++ b/builder/onehorse32dev.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ONEHORSE_ESP32_DEV", "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "dio", + "flash_mode": "dout", "mcu": "esp32", "variant": "onehorse32dev" }, diff --git a/boards/oroca_edubot.json b/builder/oroca_edubot.json similarity index 100% rename from boards/oroca_edubot.json rename to builder/oroca_edubot.json diff --git a/boards/pico32.json b/builder/pico32.json similarity index 96% rename from boards/pico32.json rename to builder/pico32.json index c5bf35332..5580b07e0 100644 --- a/boards/pico32.json +++ b/builder/pico32.json @@ -7,7 +7,7 @@ "extra_flags": "-DARDUINO_ESP32_PICO", "f_cpu": "240000000L", "f_flash": "40000000L", - "flash_mode": "qio", + "flash_mode": "dio", "mcu": "esp32", "variant": "pico32" }, diff --git a/boards/piranha_esp32.json b/builder/piranha_esp32.json similarity index 100% rename from boards/piranha_esp32.json rename to builder/piranha_esp32.json diff --git a/boards/pocket_32.json b/builder/pocket_32.json similarity index 100% rename from boards/pocket_32.json rename to builder/pocket_32.json diff --git a/boards/pycom_gpy.json b/builder/pycom_gpy.json similarity index 100% rename from boards/pycom_gpy.json rename to builder/pycom_gpy.json diff --git a/boards/qchip.json b/builder/qchip.json similarity index 100% rename from boards/qchip.json rename to builder/qchip.json diff --git a/boards/quantum.json b/builder/quantum.json similarity index 100% rename from boards/quantum.json rename to builder/quantum.json diff --git a/boards/redpill_esp32s3.json b/builder/redpill_esp32s3.json similarity index 100% rename from boards/redpill_esp32s3.json rename to builder/redpill_esp32s3.json diff --git a/builder/roboheart_hercules.json b/builder/roboheart_hercules.json new file mode 100644 index 000000000..46740d2e9 --- /dev/null +++ b/builder/roboheart_hercules.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_roboheart_hercules", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "roboheart_hercules" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "RoboHeart Hercules", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://roboheart.de/en_gb/", + "vendor": "RoboHeart" +} diff --git a/boards/s_odi_ultra.json b/builder/s_odi_ultra.json similarity index 100% rename from boards/s_odi_ultra.json rename to builder/s_odi_ultra.json diff --git a/boards/seeed_xiao_esp32c3.json b/builder/seeed_xiao_esp32c3.json similarity index 91% rename from boards/seeed_xiao_esp32c3.json rename to builder/seeed_xiao_esp32c3.json index 4d8ded042..24b167120 100644 --- a/boards/seeed_xiao_esp32c3.json +++ b/builder/seeed_xiao_esp32c3.json @@ -15,8 +15,12 @@ "hwids": [ [ "0x2886", - "0x0047" - ] + "0x0046" + ], + [ + "0x303a", + "0x1001" + ] ], "mcu": "esp32c3", "variant": "XIAO_ESP32C3" diff --git a/builder/seeed_xiao_esp32s3.json b/builder/seeed_xiao_esp32s3.json new file mode 100644 index 000000000..cf98a6aa4 --- /dev/null +++ b/builder/seeed_xiao_esp32s3.json @@ -0,0 +1,53 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_XIAO_ESP32S3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x2886", + "0x0056" + ], + [ + "0x2886", + "0x8056" + ] + ], + "mcu": "esp32s3", + "variant": "XIAO_ESP32S3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Seeed Studio XIAO ESP32S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.seeedstudio.com/XIAO-ESP32S3-p-5627.html", + "vendor": "Seeed Studio" +} diff --git a/boards/sensesiot_weizen.json b/builder/sensesiot_weizen.json similarity index 100% rename from boards/sensesiot_weizen.json rename to builder/sensesiot_weizen.json diff --git a/boards/sg-o_airMon.json b/builder/sg-o_airMon.json similarity index 100% rename from boards/sg-o_airMon.json rename to builder/sg-o_airMon.json diff --git a/boards/sparkfun_esp32_iot_redboard.json b/builder/sparkfun_esp32_iot_redboard.json similarity index 86% rename from boards/sparkfun_esp32_iot_redboard.json rename to builder/sparkfun_esp32_iot_redboard.json index b451c8812..e97c2d886 100644 --- a/boards/sparkfun_esp32_iot_redboard.json +++ b/builder/sparkfun_esp32_iot_redboard.json @@ -5,7 +5,9 @@ }, "core": "esp32", "extra_flags": [ - "-DARDUINO_ESP32_IOT_REDBOARD" + "-DARDUINO_ESP32_IOT_REDBOARD", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/sparkfun_esp32micromod.json b/builder/sparkfun_esp32micromod.json similarity index 100% rename from boards/sparkfun_esp32micromod.json rename to builder/sparkfun_esp32micromod.json diff --git a/boards/sparkfun_esp32s2_thing_plus.json b/builder/sparkfun_esp32s2_thing_plus.json similarity index 100% rename from boards/sparkfun_esp32s2_thing_plus.json rename to builder/sparkfun_esp32s2_thing_plus.json diff --git a/boards/sparkfun_esp32s2_thing_plus_c.json b/builder/sparkfun_esp32s2_thing_plus_c.json similarity index 100% rename from boards/sparkfun_esp32s2_thing_plus_c.json rename to builder/sparkfun_esp32s2_thing_plus_c.json diff --git a/boards/sparkfun_lora_gateway_1-channel.json b/builder/sparkfun_lora_gateway_1-channel.json similarity index 100% rename from boards/sparkfun_lora_gateway_1-channel.json rename to builder/sparkfun_lora_gateway_1-channel.json diff --git a/boards/tamc_termod_s3.json b/builder/tamc_termod_s3.json similarity index 92% rename from boards/tamc_termod_s3.json rename to builder/tamc_termod_s3.json index a0301e12c..934c15fb1 100644 --- a/boards/tamc_termod_s3.json +++ b/builder/tamc_termod_s3.json @@ -9,6 +9,8 @@ "-DARDUINO_TAMC_TERMOD_S3", "-DARDUINO_USB_MODE=1", "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", "-DBOARD_HAS_PSRAM" ], "f_cpu": "240000000L", diff --git a/boards/tinypico.json b/builder/tinypico.json similarity index 100% rename from boards/tinypico.json rename to builder/tinypico.json diff --git a/boards/trueverit-iot-driver-mk2.json b/builder/trueverit-iot-driver-mk2.json similarity index 100% rename from boards/trueverit-iot-driver-mk2.json rename to builder/trueverit-iot-driver-mk2.json diff --git a/boards/trueverit-iot-driver-mk3.json b/builder/trueverit-iot-driver-mk3.json similarity index 100% rename from boards/trueverit-iot-driver-mk3.json rename to builder/trueverit-iot-driver-mk3.json diff --git a/boards/trueverit-iot-driver.json b/builder/trueverit-iot-driver.json similarity index 100% rename from boards/trueverit-iot-driver.json rename to builder/trueverit-iot-driver.json diff --git a/boards/ttgo-lora32-v1.json b/builder/ttgo-lora32-v1.json similarity index 100% rename from boards/ttgo-lora32-v1.json rename to builder/ttgo-lora32-v1.json diff --git a/boards/ttgo-lora32-v2.json b/builder/ttgo-lora32-v2.json similarity index 100% rename from boards/ttgo-lora32-v2.json rename to builder/ttgo-lora32-v2.json diff --git a/boards/ttgo-lora32-v21.json b/builder/ttgo-lora32-v21.json similarity index 100% rename from boards/ttgo-lora32-v21.json rename to builder/ttgo-lora32-v21.json diff --git a/boards/ttgo-t-beam.json b/builder/ttgo-t-beam.json similarity index 100% rename from boards/ttgo-t-beam.json rename to builder/ttgo-t-beam.json diff --git a/boards/ttgo-t-oi-plus.json b/builder/ttgo-t-oi-plus.json similarity index 100% rename from boards/ttgo-t-oi-plus.json rename to builder/ttgo-t-oi-plus.json diff --git a/boards/ttgo-t-watch.json b/builder/ttgo-t-watch.json similarity index 100% rename from boards/ttgo-t-watch.json rename to builder/ttgo-t-watch.json diff --git a/boards/ttgo-t1.json b/builder/ttgo-t1.json similarity index 100% rename from boards/ttgo-t1.json rename to builder/ttgo-t1.json diff --git a/boards/ttgo-t7-v13-mini32.json b/builder/ttgo-t7-v13-mini32.json similarity index 100% rename from boards/ttgo-t7-v13-mini32.json rename to builder/ttgo-t7-v13-mini32.json diff --git a/boards/ttgo-t7-v14-mini32.json b/builder/ttgo-t7-v14-mini32.json similarity index 100% rename from boards/ttgo-t7-v14-mini32.json rename to builder/ttgo-t7-v14-mini32.json diff --git a/boards/turta_iot_node.json b/builder/turta_iot_node.json similarity index 100% rename from boards/turta_iot_node.json rename to builder/turta_iot_node.json diff --git a/boards/um_feathers2.json b/builder/um_feathers2.json similarity index 100% rename from boards/um_feathers2.json rename to builder/um_feathers2.json diff --git a/boards/um_feathers2_neo.json b/builder/um_feathers2_neo.json similarity index 100% rename from boards/um_feathers2_neo.json rename to builder/um_feathers2_neo.json diff --git a/boards/um_feathers3.json b/builder/um_feathers3.json similarity index 89% rename from boards/um_feathers3.json rename to builder/um_feathers3.json index 5a3402f47..4430f59b0 100644 --- a/boards/um_feathers3.json +++ b/builder/um_feathers3.json @@ -9,7 +9,9 @@ "extra_flags": [ "-DARDUINO_FEATHERS3", "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/um_pros3.json b/builder/um_pros3.json similarity index 89% rename from boards/um_pros3.json rename to builder/um_pros3.json index c73aa3686..b0b379834 100644 --- a/boards/um_pros3.json +++ b/builder/um_pros3.json @@ -9,7 +9,9 @@ "extra_flags": [ "-DARDUINO_PROS3", "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/um_rmp.json b/builder/um_rmp.json similarity index 100% rename from boards/um_rmp.json rename to builder/um_rmp.json diff --git a/boards/um_tinys2.json b/builder/um_tinys2.json similarity index 100% rename from boards/um_tinys2.json rename to builder/um_tinys2.json diff --git a/boards/um_tinys3.json b/builder/um_tinys3.json similarity index 89% rename from boards/um_tinys3.json rename to builder/um_tinys3.json index bb9ebc4d0..6a9e3c14c 100644 --- a/boards/um_tinys3.json +++ b/builder/um_tinys3.json @@ -9,7 +9,9 @@ "extra_flags": [ "-DARDUINO_TINYS3", "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/unphone7.json b/builder/unphone7.json similarity index 100% rename from boards/unphone7.json rename to builder/unphone7.json diff --git a/boards/unphone8.json b/builder/unphone8.json similarity index 92% rename from boards/unphone8.json rename to builder/unphone8.json index 8eca3333f..3ee0955d9 100644 --- a/boards/unphone8.json +++ b/builder/unphone8.json @@ -9,6 +9,8 @@ "-DBOARD_HAS_PSRAM", "-DUNPHONE_SPIN=8", "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=0", + "-DARDUINO_RUNNING_CORE=1", "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", diff --git a/boards/unphone9.json b/builder/unphone9.json similarity index 89% rename from boards/unphone9.json rename to builder/unphone9.json index 8715bb577..e269a9662 100644 --- a/boards/unphone9.json +++ b/builder/unphone9.json @@ -9,7 +9,9 @@ "-DBOARD_HAS_PSRAM", "-DUNPHONE_SPIN=9", "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/upesy_wroom.json b/builder/upesy_wroom.json similarity index 100% rename from boards/upesy_wroom.json rename to builder/upesy_wroom.json diff --git a/boards/upesy_wrover.json b/builder/upesy_wrover.json similarity index 100% rename from boards/upesy_wrover.json rename to builder/upesy_wrover.json diff --git a/builder/valtrack_v4_mfw_esp32_c3.json b/builder/valtrack_v4_mfw_esp32_c3.json new file mode 100644 index 000000000..c910f152e --- /dev/null +++ b/builder/valtrack_v4_mfw_esp32_c3.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_VALTRACK_V4_MFW_ESP32_C3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "VALTRACK_V4_MFW_ESP32_C3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Valetron Systems VALTRACK-V4MVF", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.valetron.com/", + "vendor": "Valetron Systems" +} diff --git a/builder/valtrack_v4_vts_esp32_c3.json b/builder/valtrack_v4_vts_esp32_c3.json new file mode 100644 index 000000000..8197b0bf0 --- /dev/null +++ b/builder/valtrack_v4_vts_esp32_c3.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_VALTRACK_V4_VTS_ESP32_C3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "VALTRACK_V4_VTS_ESP32_C3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Valetron Systems VALTRACK-V4VTS", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.valetron.com/", + "vendor": "Valetron Systems" +} diff --git a/boards/vintlabs-devkit-v1.json b/builder/vintlabs-devkit-v1.json similarity index 100% rename from boards/vintlabs-devkit-v1.json rename to builder/vintlabs-devkit-v1.json diff --git a/boards/watchy.json b/builder/watchy.json similarity index 100% rename from boards/watchy.json rename to builder/watchy.json diff --git a/boards/wemos_d1_mini32.json b/builder/wemos_d1_mini32.json similarity index 100% rename from boards/wemos_d1_mini32.json rename to builder/wemos_d1_mini32.json diff --git a/boards/wemos_d1_uno32.json b/builder/wemos_d1_uno32.json similarity index 100% rename from boards/wemos_d1_uno32.json rename to builder/wemos_d1_uno32.json diff --git a/boards/wemosbat.json b/builder/wemosbat.json similarity index 100% rename from boards/wemosbat.json rename to builder/wemosbat.json diff --git a/boards/wesp32.json b/builder/wesp32.json similarity index 100% rename from boards/wesp32.json rename to builder/wesp32.json diff --git a/boards/widora-air.json b/builder/widora-air.json similarity index 100% rename from boards/widora-air.json rename to builder/widora-air.json diff --git a/boards/wifiduino32.json b/builder/wifiduino32.json similarity index 100% rename from boards/wifiduino32.json rename to builder/wifiduino32.json diff --git a/boards/wifiduino32c3.json b/builder/wifiduino32c3.json similarity index 100% rename from boards/wifiduino32c3.json rename to builder/wifiduino32c3.json diff --git a/boards/wifiduino32s3.json b/builder/wifiduino32s3.json similarity index 88% rename from boards/wifiduino32s3.json rename to builder/wifiduino32s3.json index cb3637118..fa8989469 100644 --- a/boards/wifiduino32s3.json +++ b/builder/wifiduino32s3.json @@ -6,7 +6,9 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_WiFiduino32S3", - "-DARDUINO_USB_MODE=1" + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/wipy3.json b/builder/wipy3.json similarity index 100% rename from boards/wipy3.json rename to builder/wipy3.json diff --git a/boards/wt32-eth01.json b/builder/wt32-eth01.json similarity index 100% rename from boards/wt32-eth01.json rename to builder/wt32-eth01.json diff --git a/boards/xinabox_cw02.json b/builder/xinabox_cw02.json similarity index 100% rename from boards/xinabox_cw02.json rename to builder/xinabox_cw02.json From d162233005c9b2eff160c370de6d05ddd5cfc07c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 3 Aug 2023 18:01:53 +0200 Subject: [PATCH 400/666] fix wrong boards update --- builder/adafruit_feather_esp32_v2.json | 44 ------------- .../adafruit_feather_esp32s2_reversetft.json | 63 ------------------ builder/adafruit_feather_esp32s2_tft.json | 64 ------------------ builder/adafruit_feather_esp32s3.json | 57 ---------------- builder/adafruit_feather_esp32s3_nopsram.json | 65 ------------------- .../adafruit_feather_esp32s3_reversetft.json | 65 ------------------- builder/adafruit_feather_esp32s3_tft.json | 64 ------------------ builder/adafruit_funhouse_esp32s2.json | 55 ---------------- builder/adafruit_itsybitsy_esp32.json | 45 ------------- builder/adafruit_magtag29_esp32s2.json | 55 ---------------- builder/adafruit_matrixportal_esp32s3.json | 65 ------------------- builder/adafruit_metro_esp32s2.json | 55 ---------------- builder/adafruit_qtpy_esp32.json | 44 ------------- builder/adafruit_qtpy_esp32c3.json | 44 ------------- builder/adafruit_qtpy_esp32s2.json | 55 ---------------- builder/adafruit_qtpy_esp32s3_nopsram.json | 64 ------------------ builder/airm2m_core_esp32c3.json | 37 ----------- builder/alksesp32.json | 36 ---------- builder/arduino_nano_esp32.json | 53 --------------- builder/atmegazero_esp32s2.json | 46 ------------- builder/az-delivery-devkit-v4.json | 37 ----------- builder/bee_motion.json | 45 ------------- builder/bee_motion_mini.json | 38 ----------- builder/bee_motion_s3.json | 47 -------------- builder/bee_s3.json | 47 -------------- builder/bpi-bit.json | 34 ---------- builder/bpi_leaf_s3.json | 48 -------------- builder/briki_abc_esp32.json | 41 ------------ builder/briki_mbc-wb_esp32.json | 41 ------------ builder/cnrs_aw2eth.json | 36 ---------- builder/connaxio_espoir.json | 47 -------------- builder/cytron_maker_feather_aiot_s3.json | 56 ---------------- builder/d-duino-32.json | 37 ----------- builder/deneyapkart.json | 42 ------------ builder/deneyapkart1A.json | 42 ------------ builder/deneyapkart1Av2.json | 51 --------------- builder/deneyapkartg.json | 39 ----------- builder/deneyapmini.json | 45 ------------- builder/deneyapminiv2.json | 46 ------------- builder/denky32.json | 39 ----------- builder/denky_d4.json | 37 ----------- builder/dfrobot_beetle_esp32c3.json | 48 -------------- builder/dfrobot_firebeetle2_esp32e.json | 39 ----------- builder/dfrobot_firebeetle2_esp32s3.json | 49 -------------- builder/dfrobot_romeo_esp32s3.json | 47 -------------- builder/dpu_esp32.json | 43 ------------ builder/edgebox-esp-100.json | 40 ------------ builder/esp-wrover-kit.json | 52 --------------- builder/esp32-c3-devkitc-02.json | 35 ---------- builder/esp32-c3-devkitm-1.json | 35 ---------- builder/esp32-c3-m1i-kit.json | 37 ----------- builder/esp32-devkitlipo.json | 38 ----------- builder/esp32-evb.json | 38 ----------- builder/esp32-gateway.json | 38 ----------- builder/esp32-poe-iso.json | 35 ---------- builder/esp32-poe.json | 35 ---------- builder/esp32-pro.json | 34 ---------- builder/esp32-s2-franzininho.json | 32 --------- builder/esp32-s2-kaluga-1.json | 37 ----------- builder/esp32-s2-saola-1.json | 34 ---------- builder/esp32-s3-devkitc-1.json | 50 -------------- builder/esp320.json | 34 ---------- builder/esp32cam.json | 38 ----------- builder/esp32dev.json | 37 ----------- builder/esp32doit-devkit-v1.json | 37 ----------- builder/esp32doit-espduino.json | 37 ----------- builder/esp32s3box.json | 47 -------------- builder/esp32s3camlcd.json | 49 -------------- builder/esp32thing.json | 37 ----------- builder/esp32thing_plus.json | 38 ----------- builder/esp32vn-iot-uno.json | 37 ----------- builder/espea32.json | 34 ---------- builder/espectro32.json | 37 ----------- builder/espino32.json | 37 ----------- builder/etboard.json | 34 ---------- builder/featheresp32-s2.json | 62 ------------------ builder/featheresp32.json | 37 ----------- builder/firebeetle32.json | 35 ---------- builder/fm-devkit.json | 37 ----------- builder/franzininho_wifi_esp32s2.json | 45 ------------- builder/franzininho_wifi_msc_esp32s2.json | 47 -------------- builder/frogboard.json | 37 ----------- builder/healthypi4.json | 34 ---------- builder/heltec_wifi_kit_32.json | 34 ---------- builder/heltec_wifi_kit_32_V3.json | 47 -------------- builder/heltec_wifi_kit_32_v2.json | 35 ---------- builder/heltec_wifi_lora_32.json | 37 ----------- builder/heltec_wifi_lora_32_V2.json | 38 ----------- builder/heltec_wifi_lora_32_V3.json | 48 -------------- builder/heltec_wireless_stick.json | 38 ----------- builder/heltec_wireless_stick_lite.json | 34 ---------- builder/honeylemon.json | 37 ----------- builder/hornbill32dev.json | 37 ----------- builder/hornbill32minima.json | 37 ----------- builder/imbrios-logsens-v1p1.json | 34 ---------- builder/inex_openkb.json | 34 ---------- builder/intorobot.json | 34 ---------- builder/iotaap_magnolia.json | 36 ---------- builder/iotbusio.json | 39 ----------- builder/iotbusproteus.json | 39 ----------- builder/kb32-ft.json | 42 ------------ builder/kits-edu.json | 34 ---------- builder/labplus_mpython.json | 35 ---------- builder/lilygo-t-display-s3.json | 48 -------------- builder/lionbit.json | 45 ------------- builder/lolin32.json | 37 ----------- builder/lolin32_lite.json | 34 ---------- builder/lolin_c3_mini.json | 44 ------------- builder/lolin_d32.json | 37 ----------- builder/lolin_d32_pro.json | 37 ----------- builder/lolin_s2_mini.json | 46 ------------- builder/lolin_s2_pico.json | 46 ------------- builder/lolin_s3.json | 49 -------------- builder/lolin_s3_mini.json | 46 ------------- builder/lopy.json | 37 ----------- builder/lopy4.json | 37 ----------- builder/m5stack-atom.json | 34 ---------- builder/m5stack-atoms3.json | 46 ------------- builder/m5stack-core-esp32.json | 34 ---------- builder/m5stack-core2.json | 35 ---------- builder/m5stack-coreink.json | 34 ---------- builder/m5stack-cores3.json | 46 ------------- builder/m5stack-fire.json | 40 ------------ builder/m5stack-grey.json | 34 ---------- builder/m5stack-stamps3.json | 46 ------------- builder/m5stack-station.json | 34 ---------- builder/m5stack-timer-cam.json | 39 ----------- builder/m5stamp-pico.json | 34 ---------- builder/m5stick-c.json | 34 ---------- builder/magicbit.json | 34 ---------- builder/mgbot-iotik32a.json | 34 ---------- builder/mgbot-iotik32b.json | 34 ---------- builder/mhetesp32devkit.json | 37 ----------- builder/mhetesp32minikit.json | 37 ----------- builder/microduino-core-esp32.json | 34 ---------- builder/micros2.json | 48 -------------- builder/minimain_esp32s2.json | 50 -------------- builder/nano32.json | 34 ---------- builder/nebulas3.json | 47 -------------- builder/nina_w10.json | 35 ---------- builder/node32s.json | 37 ----------- builder/nodemcu-32s.json | 37 ----------- builder/nodemcu-32s2.json | 34 ---------- builder/nscreen-32.json | 40 ------------ builder/odroid_esp32.json | 34 ---------- builder/onehorse32dev.json | 34 ---------- builder/oroca_edubot.json | 35 ---------- builder/pico32.json | 37 ----------- builder/piranha_esp32.json | 34 ---------- builder/pocket_32.json | 37 ----------- builder/pycom_gpy.json | 34 ---------- builder/qchip.json | 34 ---------- builder/quantum.json | 34 ---------- builder/redpill_esp32s3.json | 55 ---------------- builder/roboheart_hercules.json | 39 ----------- builder/s_odi_ultra.json | 34 ---------- builder/seeed_xiao_esp32c3.json | 48 -------------- builder/seeed_xiao_esp32s3.json | 53 --------------- builder/sensesiot_weizen.json | 37 ----------- builder/sg-o_airMon.json | 40 ------------ builder/sparkfun_esp32_iot_redboard.json | 41 ------------ builder/sparkfun_esp32micromod.json | 34 ---------- builder/sparkfun_esp32s2_thing_plus.json | 42 ------------ builder/sparkfun_esp32s2_thing_plus_c.json | 38 ----------- builder/sparkfun_lora_gateway_1-channel.json | 37 ----------- builder/tamc_termod_s3.json | 48 -------------- builder/tinypico.json | 39 ----------- builder/trueverit-iot-driver-mk2.json | 37 ----------- builder/trueverit-iot-driver-mk3.json | 38 ----------- builder/trueverit-iot-driver.json | 37 ----------- builder/ttgo-lora32-v1.json | 37 ----------- builder/ttgo-lora32-v2.json | 37 ----------- builder/ttgo-lora32-v21.json | 37 ----------- builder/ttgo-t-beam.json | 37 ----------- builder/ttgo-t-oi-plus.json | 34 ---------- builder/ttgo-t-watch.json | 40 ------------ builder/ttgo-t1.json | 37 ----------- builder/ttgo-t7-v13-mini32.json | 34 ---------- builder/ttgo-t7-v14-mini32.json | 37 ----------- builder/turta_iot_node.json | 34 ---------- builder/um_feathers2.json | 46 ------------- builder/um_feathers2_neo.json | 46 ------------- builder/um_feathers3.json | 50 -------------- builder/um_pros3.json | 50 -------------- builder/um_rmp.json | 46 ------------- builder/um_tinys2.json | 46 ------------- builder/um_tinys3.json | 50 -------------- builder/unphone7.json | 40 ------------ builder/unphone8.json | 44 ------------- builder/unphone9.json | 50 -------------- builder/upesy_wroom.json | 37 ----------- builder/upesy_wrover.json | 42 ------------ builder/valtrack_v4_mfw_esp32_c3.json | 44 ------------- builder/valtrack_v4_vts_esp32_c3.json | 44 ------------- builder/vintlabs-devkit-v1.json | 37 ----------- builder/watchy.json | 38 ----------- builder/wemos_d1_mini32.json | 37 ----------- builder/wemos_d1_uno32.json | 37 ----------- builder/wemosbat.json | 37 ----------- builder/wesp32.json | 37 ----------- builder/widora-air.json | 34 ---------- builder/wifiduino32.json | 34 ---------- builder/wifiduino32c3.json | 37 ----------- builder/wifiduino32s3.json | 45 ------------- builder/wipy3.json | 37 ----------- builder/wt32-eth01.json | 39 ----------- builder/xinabox_cw02.json | 37 ----------- 207 files changed, 8483 deletions(-) delete mode 100644 builder/adafruit_feather_esp32_v2.json delete mode 100644 builder/adafruit_feather_esp32s2_reversetft.json delete mode 100644 builder/adafruit_feather_esp32s2_tft.json delete mode 100644 builder/adafruit_feather_esp32s3.json delete mode 100644 builder/adafruit_feather_esp32s3_nopsram.json delete mode 100644 builder/adafruit_feather_esp32s3_reversetft.json delete mode 100644 builder/adafruit_feather_esp32s3_tft.json delete mode 100644 builder/adafruit_funhouse_esp32s2.json delete mode 100644 builder/adafruit_itsybitsy_esp32.json delete mode 100644 builder/adafruit_magtag29_esp32s2.json delete mode 100644 builder/adafruit_matrixportal_esp32s3.json delete mode 100644 builder/adafruit_metro_esp32s2.json delete mode 100644 builder/adafruit_qtpy_esp32.json delete mode 100644 builder/adafruit_qtpy_esp32c3.json delete mode 100644 builder/adafruit_qtpy_esp32s2.json delete mode 100644 builder/adafruit_qtpy_esp32s3_nopsram.json delete mode 100644 builder/airm2m_core_esp32c3.json delete mode 100644 builder/alksesp32.json delete mode 100644 builder/arduino_nano_esp32.json delete mode 100644 builder/atmegazero_esp32s2.json delete mode 100644 builder/az-delivery-devkit-v4.json delete mode 100644 builder/bee_motion.json delete mode 100644 builder/bee_motion_mini.json delete mode 100644 builder/bee_motion_s3.json delete mode 100644 builder/bee_s3.json delete mode 100644 builder/bpi-bit.json delete mode 100644 builder/bpi_leaf_s3.json delete mode 100644 builder/briki_abc_esp32.json delete mode 100644 builder/briki_mbc-wb_esp32.json delete mode 100644 builder/cnrs_aw2eth.json delete mode 100644 builder/connaxio_espoir.json delete mode 100644 builder/cytron_maker_feather_aiot_s3.json delete mode 100644 builder/d-duino-32.json delete mode 100644 builder/deneyapkart.json delete mode 100644 builder/deneyapkart1A.json delete mode 100644 builder/deneyapkart1Av2.json delete mode 100644 builder/deneyapkartg.json delete mode 100644 builder/deneyapmini.json delete mode 100644 builder/deneyapminiv2.json delete mode 100644 builder/denky32.json delete mode 100644 builder/denky_d4.json delete mode 100644 builder/dfrobot_beetle_esp32c3.json delete mode 100644 builder/dfrobot_firebeetle2_esp32e.json delete mode 100644 builder/dfrobot_firebeetle2_esp32s3.json delete mode 100644 builder/dfrobot_romeo_esp32s3.json delete mode 100644 builder/dpu_esp32.json delete mode 100644 builder/edgebox-esp-100.json delete mode 100644 builder/esp-wrover-kit.json delete mode 100644 builder/esp32-c3-devkitc-02.json delete mode 100644 builder/esp32-c3-devkitm-1.json delete mode 100644 builder/esp32-c3-m1i-kit.json delete mode 100644 builder/esp32-devkitlipo.json delete mode 100644 builder/esp32-evb.json delete mode 100644 builder/esp32-gateway.json delete mode 100644 builder/esp32-poe-iso.json delete mode 100644 builder/esp32-poe.json delete mode 100644 builder/esp32-pro.json delete mode 100644 builder/esp32-s2-franzininho.json delete mode 100644 builder/esp32-s2-kaluga-1.json delete mode 100644 builder/esp32-s2-saola-1.json delete mode 100644 builder/esp32-s3-devkitc-1.json delete mode 100644 builder/esp320.json delete mode 100644 builder/esp32cam.json delete mode 100644 builder/esp32dev.json delete mode 100644 builder/esp32doit-devkit-v1.json delete mode 100644 builder/esp32doit-espduino.json delete mode 100644 builder/esp32s3box.json delete mode 100644 builder/esp32s3camlcd.json delete mode 100644 builder/esp32thing.json delete mode 100644 builder/esp32thing_plus.json delete mode 100644 builder/esp32vn-iot-uno.json delete mode 100644 builder/espea32.json delete mode 100644 builder/espectro32.json delete mode 100644 builder/espino32.json delete mode 100644 builder/etboard.json delete mode 100644 builder/featheresp32-s2.json delete mode 100644 builder/featheresp32.json delete mode 100644 builder/firebeetle32.json delete mode 100644 builder/fm-devkit.json delete mode 100644 builder/franzininho_wifi_esp32s2.json delete mode 100644 builder/franzininho_wifi_msc_esp32s2.json delete mode 100644 builder/frogboard.json delete mode 100644 builder/healthypi4.json delete mode 100644 builder/heltec_wifi_kit_32.json delete mode 100644 builder/heltec_wifi_kit_32_V3.json delete mode 100644 builder/heltec_wifi_kit_32_v2.json delete mode 100644 builder/heltec_wifi_lora_32.json delete mode 100644 builder/heltec_wifi_lora_32_V2.json delete mode 100644 builder/heltec_wifi_lora_32_V3.json delete mode 100644 builder/heltec_wireless_stick.json delete mode 100644 builder/heltec_wireless_stick_lite.json delete mode 100644 builder/honeylemon.json delete mode 100644 builder/hornbill32dev.json delete mode 100644 builder/hornbill32minima.json delete mode 100644 builder/imbrios-logsens-v1p1.json delete mode 100644 builder/inex_openkb.json delete mode 100644 builder/intorobot.json delete mode 100644 builder/iotaap_magnolia.json delete mode 100644 builder/iotbusio.json delete mode 100644 builder/iotbusproteus.json delete mode 100644 builder/kb32-ft.json delete mode 100644 builder/kits-edu.json delete mode 100644 builder/labplus_mpython.json delete mode 100644 builder/lilygo-t-display-s3.json delete mode 100644 builder/lionbit.json delete mode 100644 builder/lolin32.json delete mode 100644 builder/lolin32_lite.json delete mode 100644 builder/lolin_c3_mini.json delete mode 100644 builder/lolin_d32.json delete mode 100644 builder/lolin_d32_pro.json delete mode 100644 builder/lolin_s2_mini.json delete mode 100644 builder/lolin_s2_pico.json delete mode 100644 builder/lolin_s3.json delete mode 100644 builder/lolin_s3_mini.json delete mode 100644 builder/lopy.json delete mode 100644 builder/lopy4.json delete mode 100644 builder/m5stack-atom.json delete mode 100644 builder/m5stack-atoms3.json delete mode 100644 builder/m5stack-core-esp32.json delete mode 100644 builder/m5stack-core2.json delete mode 100644 builder/m5stack-coreink.json delete mode 100644 builder/m5stack-cores3.json delete mode 100644 builder/m5stack-fire.json delete mode 100644 builder/m5stack-grey.json delete mode 100644 builder/m5stack-stamps3.json delete mode 100644 builder/m5stack-station.json delete mode 100644 builder/m5stack-timer-cam.json delete mode 100644 builder/m5stamp-pico.json delete mode 100644 builder/m5stick-c.json delete mode 100644 builder/magicbit.json delete mode 100644 builder/mgbot-iotik32a.json delete mode 100644 builder/mgbot-iotik32b.json delete mode 100644 builder/mhetesp32devkit.json delete mode 100644 builder/mhetesp32minikit.json delete mode 100644 builder/microduino-core-esp32.json delete mode 100644 builder/micros2.json delete mode 100644 builder/minimain_esp32s2.json delete mode 100644 builder/nano32.json delete mode 100644 builder/nebulas3.json delete mode 100644 builder/nina_w10.json delete mode 100644 builder/node32s.json delete mode 100644 builder/nodemcu-32s.json delete mode 100644 builder/nodemcu-32s2.json delete mode 100644 builder/nscreen-32.json delete mode 100644 builder/odroid_esp32.json delete mode 100644 builder/onehorse32dev.json delete mode 100644 builder/oroca_edubot.json delete mode 100644 builder/pico32.json delete mode 100644 builder/piranha_esp32.json delete mode 100644 builder/pocket_32.json delete mode 100644 builder/pycom_gpy.json delete mode 100644 builder/qchip.json delete mode 100644 builder/quantum.json delete mode 100644 builder/redpill_esp32s3.json delete mode 100644 builder/roboheart_hercules.json delete mode 100644 builder/s_odi_ultra.json delete mode 100644 builder/seeed_xiao_esp32c3.json delete mode 100644 builder/seeed_xiao_esp32s3.json delete mode 100644 builder/sensesiot_weizen.json delete mode 100644 builder/sg-o_airMon.json delete mode 100644 builder/sparkfun_esp32_iot_redboard.json delete mode 100644 builder/sparkfun_esp32micromod.json delete mode 100644 builder/sparkfun_esp32s2_thing_plus.json delete mode 100644 builder/sparkfun_esp32s2_thing_plus_c.json delete mode 100644 builder/sparkfun_lora_gateway_1-channel.json delete mode 100644 builder/tamc_termod_s3.json delete mode 100644 builder/tinypico.json delete mode 100644 builder/trueverit-iot-driver-mk2.json delete mode 100644 builder/trueverit-iot-driver-mk3.json delete mode 100644 builder/trueverit-iot-driver.json delete mode 100644 builder/ttgo-lora32-v1.json delete mode 100644 builder/ttgo-lora32-v2.json delete mode 100644 builder/ttgo-lora32-v21.json delete mode 100644 builder/ttgo-t-beam.json delete mode 100644 builder/ttgo-t-oi-plus.json delete mode 100644 builder/ttgo-t-watch.json delete mode 100644 builder/ttgo-t1.json delete mode 100644 builder/ttgo-t7-v13-mini32.json delete mode 100644 builder/ttgo-t7-v14-mini32.json delete mode 100644 builder/turta_iot_node.json delete mode 100644 builder/um_feathers2.json delete mode 100644 builder/um_feathers2_neo.json delete mode 100644 builder/um_feathers3.json delete mode 100644 builder/um_pros3.json delete mode 100644 builder/um_rmp.json delete mode 100644 builder/um_tinys2.json delete mode 100644 builder/um_tinys3.json delete mode 100644 builder/unphone7.json delete mode 100644 builder/unphone8.json delete mode 100644 builder/unphone9.json delete mode 100644 builder/upesy_wroom.json delete mode 100644 builder/upesy_wrover.json delete mode 100644 builder/valtrack_v4_mfw_esp32_c3.json delete mode 100644 builder/valtrack_v4_vts_esp32_c3.json delete mode 100644 builder/vintlabs-devkit-v1.json delete mode 100644 builder/watchy.json delete mode 100644 builder/wemos_d1_mini32.json delete mode 100644 builder/wemos_d1_uno32.json delete mode 100644 builder/wemosbat.json delete mode 100644 builder/wesp32.json delete mode 100644 builder/widora-air.json delete mode 100644 builder/wifiduino32.json delete mode 100644 builder/wifiduino32c3.json delete mode 100644 builder/wifiduino32s3.json delete mode 100644 builder/wipy3.json delete mode 100644 builder/wt32-eth01.json delete mode 100644 builder/xinabox_cw02.json diff --git a/builder/adafruit_feather_esp32_v2.json b/builder/adafruit_feather_esp32_v2.json deleted file mode 100644 index 9414b995c..000000000 --- a/builder/adafruit_feather_esp32_v2.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_FEATHER_ESP32_V2", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "adafruit_feather_esp32_v2" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit Feather ESP32 V2", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5400", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_feather_esp32s2_reversetft.json b/builder/adafruit_feather_esp32s2_reversetft.json deleted file mode 100644 index bd1f3ca8c..000000000 --- a/builder/adafruit_feather_esp32s2_reversetft.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_REVTFT", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x80ED" - ], - [ - "0x239A", - "0x00ED" - ], - [ - "0x239A", - "0x80EE" - ] - ], - "mcu": "esp32s2", - "variant": "adafruit_feather_esp32s2_reversetft" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit Feather ESP32-S2 Reverse TFT", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_feather_esp32s2_reversetft/tinyuf2.bin" - ] - ] - }, - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5345", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_feather_esp32s2_tft.json b/builder/adafruit_feather_esp32s2_tft.json deleted file mode 100644 index e1e948144..000000000 --- a/builder/adafruit_feather_esp32s2_tft.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x810F" - ], - [ - "0x239A", - "0x010F" - ], - [ - "0x239A", - "0x8110" - ] - ], - "mcu": "esp32s2", - "variant": "adafruit_feather_esp32s2_tft" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit Feather ESP32-S2 TFT", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_feather_esp32s2_tft/tinyuf2.bin" - ] - ] - }, - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5300", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_feather_esp32s3.json b/builder/adafruit_feather_esp32s3.json deleted file mode 100644 index 5796b0559..000000000 --- a/builder/adafruit_feather_esp32s3.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-DBOARD_HAS_PSRAM" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x811B" - ], - [ - "0x239A", - "0x011B" - ], - [ - "0x239A", - "0x811C" - ] - ], - "mcu": "esp32s3", - "variant": "adafruit_feather_esp32s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit Feather ESP32-S3 2MB PSRAM", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5477", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_feather_esp32s3_nopsram.json b/builder/adafruit_feather_esp32s3_nopsram.json deleted file mode 100644 index 79ee24d1d..000000000 --- a/builder/adafruit_feather_esp32s3_nopsram.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld", - "partitions": "partitions-8MB-tinyuf2.csv", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x811B" - ], - [ - "0x239A", - "0x011B" - ], - [ - "0x239A", - "0x811C" - ] - ], - "mcu": "esp32s3", - "variant": "adafruit_feather_esp32s3_nopsram" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit Feather ESP32-S3 No PSRAM", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin" - ] - ] - }, - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5323", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_feather_esp32s3_reversetft.json b/builder/adafruit_feather_esp32s3_reversetft.json deleted file mode 100644 index fc3b8bc36..000000000 --- a/builder/adafruit_feather_esp32s3_reversetft.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_REVTFT", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x8123" - ], - [ - "0x239A", - "0x0123" - ], - [ - "0x239A", - "0x8124" - ] - ], - "mcu": "esp32s3", - "variant": "adafruit_feather_esp32s3_reversetft" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit Feather ESP32-S3 Reverse TFT", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_feather_esp32s3_reversetft/tinyuf2.bin" - ] - ] - }, - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5691", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_feather_esp32s3_tft.json b/builder/adafruit_feather_esp32s3_tft.json deleted file mode 100644 index dbf7612bd..000000000 --- a/builder/adafruit_feather_esp32s3_tft.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x811D" - ], - [ - "0x239A", - "0x011D" - ], - [ - "0x239A", - "0x811E" - ] - ], - "mcu": "esp32s3", - "variant": "adafruit_feather_esp32s3_tft" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit Feather ESP32-S3 TFT", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_feather_esp32s3_tft/tinyuf2.bin" - ] - ] - }, - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5483", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_funhouse_esp32s2.json b/builder/adafruit_funhouse_esp32s2.json deleted file mode 100644 index eb5ee1d52..000000000 --- a/builder/adafruit_funhouse_esp32s2.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_FUNHOUSE_ESP32S2", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x80F9" - ], - [ - "0x239A", - "0x00F9" - ], - [ - "0x239A", - "0x80FA" - ] - ], - "mcu": "esp32s2", - "variant": "adafruit_funhouse_esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit FunHouse", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/4985", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_itsybitsy_esp32.json b/builder/adafruit_itsybitsy_esp32.json deleted file mode 100644 index dd87bfccc..000000000 --- a/builder/adafruit_itsybitsy_esp32.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_ITSYBITSY_ESP32", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-DBOARD_HAS_PSRAM", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "adafruit_itsybitsy_esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit ItsyBitsy ESP32", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/4363", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_magtag29_esp32s2.json b/builder/adafruit_magtag29_esp32s2.json deleted file mode 100644 index fc51f6101..000000000 --- a/builder/adafruit_magtag29_esp32s2.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_MAGTAG29_ESP32S2", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x80E5" - ], - [ - "0x239A", - "0x00E5" - ], - [ - "0x239A", - "0x80E6" - ] - ], - "mcu": "esp32s2", - "variant": "adafruit_magtag29_esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit MagTag 2.9", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/4800", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_matrixportal_esp32s3.json b/builder/adafruit_matrixportal_esp32s3.json deleted file mode 100644 index 3446cd217..000000000 --- a/builder/adafruit_matrixportal_esp32s3.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld", - "partitions": "partitions-8MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-DBOARD_HAS_PSRAM" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x8125" - ], - [ - "0x239A", - "0x0125" - ], - [ - "0x239A", - "0x8126" - ] - ], - "mcu": "esp32s3", - "variant": "adafruit_matrixportal_esp32s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit MatrixPortal ESP32-S3", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x410000", - "variants/adafruit_matrixportal_esp32s3/tinyuf2.bin" - ] - ] - }, - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5778", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_metro_esp32s2.json b/builder/adafruit_metro_esp32s2.json deleted file mode 100644 index 7f75dfbe4..000000000 --- a/builder/adafruit_metro_esp32s2.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_METRO_ESP32S2", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x80DF" - ], - [ - "0x239A", - "0x00DF" - ], - [ - "0x239A", - "0x80E0" - ] - ], - "mcu": "esp32s2", - "variant": "adafruit_metro_esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit Metro ESP32-S2", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/4775", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_qtpy_esp32.json b/builder/adafruit_qtpy_esp32.json deleted file mode 100644 index d2371f7e3..000000000 --- a/builder/adafruit_qtpy_esp32.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_QTPY_ESP32_PICO", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "adafruit_qtpy_esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit QT Py ESP32", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5395", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_qtpy_esp32c3.json b/builder/adafruit_qtpy_esp32c3.json deleted file mode 100644 index 7c870e019..000000000 --- a/builder/adafruit_qtpy_esp32c3.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_QTPY_ESP32C3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0X303A", - "0x1001" - ] - ], - "mcu": "esp32c3", - "variant": "adafruit_qtpy_esp32c3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit QT Py ESP32-C3", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5405", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_qtpy_esp32s2.json b/builder/adafruit_qtpy_esp32s2.json deleted file mode 100644 index 51beac63e..000000000 --- a/builder/adafruit_qtpy_esp32s2.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_QTPY_ESP32S2", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x8111" - ], - [ - "0x239A", - "0x0111" - ], - [ - "0x239A", - "0x8112" - ] - ], - "mcu": "esp32s2", - "variant": "adafruit_qtpy_esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit QT Py ESP32-S2", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5325", - "vendor": "Adafruit" -} diff --git a/builder/adafruit_qtpy_esp32s3_nopsram.json b/builder/adafruit_qtpy_esp32s3_nopsram.json deleted file mode 100644 index 15589da92..000000000 --- a/builder/adafruit_qtpy_esp32s3_nopsram.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "partitions-8MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x8119" - ], - [ - "0x239A", - "0x0119" - ], - [ - "0x239A", - "0x811A" - ] - ], - "mcu": "esp32s3", - "variant": "adafruit_qtpy_esp32s3_nopsram" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit QT Py ESP32-S3 No PSRAM", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x410000", - "variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin" - ] - ] - }, - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/5426", - "vendor": "Adafruit" -} diff --git a/builder/airm2m_core_esp32c3.json b/builder/airm2m_core_esp32c3.json deleted file mode 100644 index e227fadd8..000000000 --- a/builder/airm2m_core_esp32c3.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "extra_flags": [ - "-DARDUINO_AirM2M_CORE_ESP32C3", - "-DARDUINO_USB_MODE=1" - ], - "mcu": "esp32c3", - "variant": "AirM2M_CORE_ESP32C3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "AirM2M CORE ESP32C3", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://wiki.luatos.com/chips/esp32c3/board.html", - "vendor": "AirM2M" -} diff --git a/builder/alksesp32.json b/builder/alksesp32.json deleted file mode 100644 index d94ec71fa..000000000 --- a/builder/alksesp32.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ALKS", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "alksesp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino" - ], - "name": "ALKS ESP32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/RoboticsBrno/ArduinoLearningKitStarter.git", - "vendor": "RoboticsBrno" -} diff --git a/builder/arduino_nano_esp32.json b/builder/arduino_nano_esp32.json deleted file mode 100644 index c6da4e227..000000000 --- a/builder/arduino_nano_esp32.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld", - "partitions": "app3M_fat9M_fact512k_16MB.csv", - "memory_type": "qio_opi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_NANO_ESP32", - "-DBOARD_HAS_PIN_REMAP", - "-DBOARD_HAS_PSRAM", - "-DUSB_MANUFACTURER=\\\"Arduino\\\"", - "-DUSB_PRODUCT=\\\"NanoESP32\\\"", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_USB_DFU_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x2341", - "0x0070" - ] - ], - "mcu": "esp32s3", - "variant": "arduino_nano_nora" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Arduino Nano ESP32", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800, - "protocol": "dfu" - }, - "url": "https://docs.arduino.cc/hardware/nano-esp32", - "vendor": "Arduino" -} diff --git a/builder/atmegazero_esp32s2.json b/builder/atmegazero_esp32s2.json deleted file mode 100644 index a23a6ce9d..000000000 --- a/builder/atmegazero_esp32s2.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld", - "partitions": "partitions-16MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_atmegazero_esp32s2", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x800A" - ] - ], - "mcu": "esp32s2", - "variant": "atmegazero_esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "EspinalLab ATMegaZero ESP32-S2", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://shop.atmegazero.com/", - "vendor": "EspinalLab" -} diff --git a/builder/az-delivery-devkit-v4.json b/builder/az-delivery-devkit-v4.json deleted file mode 100644 index 93237d723..000000000 --- a/builder/az-delivery-devkit-v4.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "AZ-Delivery ESP-32 Dev Kit C V4", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 532480, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.az-delivery.com/products/esp-32-dev-kit-c-v4", - "vendor": "AZ-Delivery" -} diff --git a/builder/bee_motion.json b/builder/bee_motion.json deleted file mode 100644 index c8577902b..000000000 --- a/builder/bee_motion.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_Bee_Motion", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x810D" - ] - ], - "mcu": "esp32s2", - "variant": "Bee_Motion" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Smart Bee Motion", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/strid3r21/Bee-Motion", - "vendor": "Smart Bee" -} diff --git a/builder/bee_motion_mini.json b/builder/bee_motion_mini.json deleted file mode 100644 index d24163ec8..000000000 --- a/builder/bee_motion_mini.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "extra_flags": [ - "-DARDUINO_Bee_Motion_Mini", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "mcu": "esp32c3", - "variant": "Bee_Motion_Mini" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Smart Bee Motion Mini", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/strid3r21/BeeMotionMini", - "vendor": "Smart Bee" -} diff --git a/builder/bee_motion_s3.json b/builder/bee_motion_s3.json deleted file mode 100644 index c620b80c3..000000000 --- a/builder/bee_motion_s3.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_BeeMotionS3", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x8113" - ] - ], - "mcu": "esp32s3", - "variant": "Bee_Motion_S3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Smart Bee Motion S3", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/strid3r21/BeeMotionS3/", - "vendor": "Smart Bee" -} diff --git a/builder/bee_s3.json b/builder/bee_s3.json deleted file mode 100644 index 16e47ee79..000000000 --- a/builder/bee_s3.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_Bee_S3", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x8110" - ] - ], - "mcu": "esp32s3", - "variant": "Bee_S3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Smart Bee S3", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/strid3r21/BeeS3", - "vendor": "Smart Bee" -} diff --git a/builder/bpi-bit.json b/builder/bpi-bit.json deleted file mode 100644 index ec5c0dc73..000000000 --- a/builder/bpi-bit.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_BPI_BIT", - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "bpi-bit" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "BPI-Bit", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://en.wikipedia.org/wiki/ESP32", - "vendor": "BPI Tech" -} diff --git a/builder/bpi_leaf_s3.json b/builder/bpi_leaf_s3.json deleted file mode 100644 index c1d8a154c..000000000 --- a/builder/bpi_leaf_s3.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DBOARD_HAS_PSRAM", - "-DARDUINO_BPI_LEAF_S3", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x80DF" - ] - ], - "mcu": "esp32s3", - "variant": "bpi_leaf_s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "BPI-Leaf-S3", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://wiki.banana-pi.org/BPI-Leaf-S3", - "vendor": "BPI Tech" -} diff --git a/builder/briki_abc_esp32.json b/builder/briki_abc_esp32.json deleted file mode 100644 index 429514895..000000000 --- a/builder/briki_abc_esp32.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "mbcwb", - "extra_flags": "-DBRIKI_MBC_WB_ESP -DBRIKI_ABC -w", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "briki_mbcwb_esp32", - "partitions": "8MB_ffat.csv" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino" - ], - "name": "Briki ABC (MBC-WB) - ESP32", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 3407872, - "protocol": "mbctool", - "protocols": [ - "mbctool" - ], - "require_upload_port": true, - "speed": 1500000 - }, - "url": "https://briki.org", - "vendor": "meteca" -} diff --git a/builder/briki_mbc-wb_esp32.json b/builder/briki_mbc-wb_esp32.json deleted file mode 100644 index df5c3756a..000000000 --- a/builder/briki_mbc-wb_esp32.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "mbcwb", - "extra_flags": "-DBRIKI_MBC_WB_ESP -DBRIKI_MBC_WB -w", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "briki_mbcwb_esp32", - "partitions": "8MB_ffat.csv" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino" - ], - "name": "Briki MBC-WB - ESP32", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 3407872, - "protocol": "mbctool", - "protocols": [ - "mbctool" - ], - "require_upload_port": true, - "speed": 1500000 - }, - "url": "https://briki.org", - "vendor": "meteca" -} diff --git a/builder/cnrs_aw2eth.json b/builder/cnrs_aw2eth.json deleted file mode 100644 index 3669347a4..000000000 --- a/builder/cnrs_aw2eth.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ESP32_PICO" - ], - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "cnrs_aw2eth" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "CNRS AW2ETH", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://en.wikipedia.org/wiki/ESP32", - "vendor": "CNRS" -} diff --git a/builder/connaxio_espoir.json b/builder/connaxio_espoir.json deleted file mode 100644 index e9e7265bf..000000000 --- a/builder/connaxio_espoir.json +++ /dev/null @@ -1,47 +0,0 @@ - -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_CONNAXIO_ESPOIR", - "-DCONFIG_FREERTOS_UNICORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "connaxio_espoir", - "hwids": [ - [ - "0x10C4", - "0x8D9A" - ] - ] - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp32-solo-1.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Connaxio's Espoir", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://www.connaxio.com/electronics/espoir/", - "vendor": "Connaxio" -} diff --git a/builder/cytron_maker_feather_aiot_s3.json b/builder/cytron_maker_feather_aiot_s3.json deleted file mode 100644 index 4b7a2704c..000000000 --- a/builder/cytron_maker_feather_aiot_s3.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "memory_type": "qio_opi", - "partitions": "partitions-8MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_CYTRON_MAKER_FEATHER_AIOT_S3", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x80F8" - ] - ], - "mcu": "esp32s3", - "variant": "cytron_maker_feather_aiot_s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Cytron Maker Feather AIoT S3", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x410000", - "variants/cytron_maker_feather_aiot_s3/tinyuf2.bin" - ] - ] - }, - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://sg.cytron.io/c-development-tools/c-maker-series/p-v-maker-feather-aiot-s3-simplifying-aiot-with-esp32", - "vendor": "Cytron Technologies" -} diff --git a/builder/d-duino-32.json b/builder/d-duino-32.json deleted file mode 100644 index e4d92e3df..000000000 --- a/builder/d-duino-32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_D_DUINO_32", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "d-duino-32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "D-duino-32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.tindie.com/products/lspoplove/dstike-d-duino-32-v3/", - "vendor": "DSTIKE" -} diff --git a/builder/deneyapkart.json b/builder/deneyapkart.json deleted file mode 100644 index 7d499bd4b..000000000 --- a/builder/deneyapkart.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DYDK", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "deneyapkart" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_board": "esp32-wrover.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Deneyap Kart", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart", - "vendor": "T3 Foundation" -} diff --git a/builder/deneyapkart1A.json b/builder/deneyapkart1A.json deleted file mode 100644 index 46f513fac..000000000 --- a/builder/deneyapkart1A.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DYDK1A", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "deneyapkart1A" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_board": "esp32-wrover.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Deneyap Kart 1A", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart-1a", - "vendor": "T3 Foundation" -} diff --git a/builder/deneyapkart1Av2.json b/builder/deneyapkart1Av2.json deleted file mode 100644 index e57a00846..000000000 --- a/builder/deneyapkart1Av2.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "memory_type": "qio_opi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DYDK1Av2", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x8147" - ] - ], - "mcu": "esp32s3", - "variant": "deneyapkart1Av2" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Deneyap Kart 1A v2", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart-1a-v2-type-c", - "vendor": "T3 Foundation" -} diff --git a/builder/deneyapkartg.json b/builder/deneyapkartg.json deleted file mode 100644 index 19f1b0415..000000000 --- a/builder/deneyapkartg.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DYG", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32c3", - "variant": "deneyapkartg" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Deneyap Kart G", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart-g-type-c", - "vendor": "T3 Foundation" -} diff --git a/builder/deneyapmini.json b/builder/deneyapmini.json deleted file mode 100644 index 5a358cdb5..000000000 --- a/builder/deneyapmini.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DYM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x8141" - ] - ], - "mcu": "esp32s2", - "variant": "deneyapmini" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Deneyap Mini", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-mini", - "vendor": "T3 Foundation" -} diff --git a/builder/deneyapminiv2.json b/builder/deneyapminiv2.json deleted file mode 100644 index 42058a81b..000000000 --- a/builder/deneyapminiv2.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DYMv2", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x8144" - ] - ], - "mcu": "esp32s2", - "variant": "deneyapminiv2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Deneyap Mini v2", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-mini-v2-type-c", - "vendor": "T3 Foundation" -} diff --git a/builder/denky32.json b/builder/denky32.json deleted file mode 100644 index 3b2c40762..000000000 --- a/builder/denky32.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DENKY_WROOM32", - "-DBOARD_HAS_PSRAM", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "ch_denky" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Denky32 (WROOM32)", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://en.wikipedia.org/wiki/ESP32", - "vendor": "Denky" -} diff --git a/builder/denky_d4.json b/builder/denky_d4.json deleted file mode 100644 index 7846bf1d8..000000000 --- a/builder/denky_d4.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DENKY_PICOV3", - "-DBOARD_HAS_PSRAM" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "ch_denky" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Denky D4 (PICO-V3-02)", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 2000000 - }, - "url": "https://en.wikipedia.org/wiki/ESP32", - "vendor": "Denky" -} diff --git a/builder/dfrobot_beetle_esp32c3.json b/builder/dfrobot_beetle_esp32c3.json deleted file mode 100644 index ab0b4c92c..000000000 --- a/builder/dfrobot_beetle_esp32c3.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ESP32C3_DEV", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x3343", - "0x8364" - ], - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32c3", - "variant": "dfrobot_beetle_esp32c3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "DFRobot Beetle ESP32-C3", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.dfrobot.com/product-2566.html", - "vendor": "DFRobot" -} diff --git a/builder/dfrobot_firebeetle2_esp32e.json b/builder/dfrobot_firebeetle2_esp32e.json deleted file mode 100644 index 0d3790cf1..000000000 --- a/builder/dfrobot_firebeetle2_esp32e.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DFROBOT_FIREBEETLE_2_ESP32E", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "dfrobot_firebeetle2_esp32e" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "DFRobot Firebeetle 2 ESP32-E", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://wiki.dfrobot.com/FireBeetle_Board_ESP32_E_SKU_DFR0654", - "vendor": "DFRobot" -} diff --git a/builder/dfrobot_firebeetle2_esp32s3.json b/builder/dfrobot_firebeetle2_esp32s3.json deleted file mode 100644 index 0f87150d6..000000000 --- a/builder/dfrobot_firebeetle2_esp32s3.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ESP32S3_DEV", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x83CF" - ], - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "dfrobot_firebeetle2_esp32s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "DFRobot Firebeetle 2 ESP32-S3", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.dfrobot.com/product-1590.html", - "vendor": "DFRobot" -} diff --git a/builder/dfrobot_romeo_esp32s3.json b/builder/dfrobot_romeo_esp32s3.json deleted file mode 100644 index 63a7cb472..000000000 --- a/builder/dfrobot_romeo_esp32s3.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "app3M_fat9M_16MB.csv", - "memory_type": "qio_opi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DFROBOT_ROMEO_ESP32S3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "dfrobot_romeo_esp32s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "DFRobot Romeo ESP32-S3", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://wiki.dfrobot.com/", - "vendor": "DFRobot" -} diff --git a/builder/dpu_esp32.json b/builder/dpu_esp32.json deleted file mode 100644 index 1f5b89a67..000000000 --- a/builder/dpu_esp32.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DPU_ESP32", - "-DBOARD_HAS_PSRAM", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "dpu_esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp32-wrover.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TAMC DPU ESP32", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/TAMCTec/dpu-esp32", - "vendor": "TAMC" -} diff --git a/builder/edgebox-esp-100.json b/builder/edgebox-esp-100.json deleted file mode 100644 index 22aee2f8b..000000000 --- a/builder/edgebox-esp-100.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_Edgebox_ESP_100", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32s3", - "variant": "Edgebox-ESP-100" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Seeed Studio Edgebox-ESP-100", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.seeedstudio.com/EdgeBox-ESP-100-p-5490.html", - "vendor": "Seeed Studio" -} diff --git a/builder/esp-wrover-kit.json b/builder/esp-wrover-kit.json deleted file mode 100644 index 50d66a7fb..000000000 --- a/builder/esp-wrover-kit.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "hwids": [ - [ - "0x0403", - "0x6010" - ] - ], - "mcu": "esp32", - "variant": "esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "default_tool": "ftdi", - "onboard_tools": [ - "ftdi" - ], - "openocd_board": "esp32-wrover.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Espressif ESP-WROVER-KIT", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "protocols": [ - "esptool", - "espota", - "ftdi" - ], - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://espressif.com/en/products/hardware/esp-wrover-kit/overview", - "vendor": "Espressif" -} diff --git a/builder/esp32-c3-devkitc-02.json b/builder/esp32-c3-devkitc-02.json deleted file mode 100644 index 320b763a0..000000000 --- a/builder/esp32-c3-devkitc-02.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "extra_flags": "-DARDUINO_ESP32C3_DEV", - "mcu": "esp32c3", - "variant": "esp32c3" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Espressif ESP32-C3-DevKitC-02", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitc-02.html", - "vendor": "Espressif" -} diff --git a/builder/esp32-c3-devkitm-1.json b/builder/esp32-c3-devkitm-1.json deleted file mode 100644 index cf1a5736a..000000000 --- a/builder/esp32-c3-devkitm-1.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "extra_flags": "-DARDUINO_ESP32C3_DEV", - "mcu": "esp32c3", - "variant": "esp32c3" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Espressif ESP32-C3-DevKitM-1", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html", - "vendor": "Espressif" -} diff --git a/builder/esp32-c3-m1i-kit.json b/builder/esp32-c3-m1i-kit.json deleted file mode 100644 index 8e7d7cb08..000000000 --- a/builder/esp32-c3-m1i-kit.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "extra_flags": [ - "-DARDUINO_ESP32C3_M1_I_KIT", - "-DARDUINO_USB_MODE=1" - ], - "mcu": "esp32c3", - "variant": "esp_c3_m1_i_kit" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Ai-Thinker ESP-C3-M1-I-Kit", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.ai-thinker.com/en/esp32c3", - "vendor": "Ai-Thinker" -} diff --git a/builder/esp32-devkitlipo.json b/builder/esp32-devkitlipo.json deleted file mode 100644 index 419edfd79..000000000 --- a/builder/esp32-devkitlipo.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEVKIT_LIPO", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [["0x1A86", "0x7523"]], - "mcu": "esp32", - "variant": "esp32-devkit-lipo" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "OLIMEX ESP32-DevKit-LiPo", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.olimex.com/Products/IoT/ESP32/ESP32-DevKit-LiPo/open-source-hardware", - "vendor": "OLIMEX" -} diff --git a/builder/esp32-evb.json b/builder/esp32-evb.json deleted file mode 100644 index c821386ae..000000000 --- a/builder/esp32-evb.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_EVB", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "hwids": [["0x1A86", "0x7523"]], - "mcu": "esp32", - "variant": "esp32-evb" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "OLIMEX ESP32-EVB", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.olimex.com/Products/IoT/ESP32-EVB/open-source-hardware", - "vendor": "OLIMEX" -} diff --git a/builder/esp32-gateway.json b/builder/esp32-gateway.json deleted file mode 100644 index 33f0f2f2a..000000000 --- a/builder/esp32-gateway.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_GATEWAY", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "hwids": [["0x1A86", "0x7523"]], - "mcu": "esp32", - "variant": "esp32-gateway" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "OLIMEX ESP32-GATEWAY", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.olimex.com/Products/IoT/ESP32-GATEWAY/open-source-hardware", - "vendor": "OLIMEX" -} diff --git a/builder/esp32-poe-iso.json b/builder/esp32-poe-iso.json deleted file mode 100644 index 4412f9466..000000000 --- a/builder/esp32-poe-iso.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_POE_ISO", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "hwids": [["0x1A86", "0x7523"]], - "mcu": "esp32", - "variant": "esp32-poe-iso" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "OLIMEX ESP32-PoE-ISO", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.olimex.com/Products/IoT/ESP32/ESP32-POE-ISO/open-source-hardware", - "vendor": "OLIMEX" -} diff --git a/builder/esp32-poe.json b/builder/esp32-poe.json deleted file mode 100644 index 0cf9bd46e..000000000 --- a/builder/esp32-poe.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_POE", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "hwids": [["0x1A86", "0x7523"]], - "mcu": "esp32", - "variant": "esp32-poe" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "OLIMEX ESP32-PoE", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.olimex.com/Products/IoT/ESP32/ESP32-POE/open-source-hardware", - "vendor": "OLIMEX" -} diff --git a/builder/esp32-pro.json b/builder/esp32-pro.json deleted file mode 100644 index ab1957206..000000000 --- a/builder/esp32-pro.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_PRO", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32-evb" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "OLIMEX ESP32-PRO", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.olimex.com/Products/IoT/ESP32/ESP32-PRO/open-source-hardware", - "vendor": "OLIMEX" -} diff --git a/builder/esp32-s2-franzininho.json b/builder/esp32-s2-franzininho.json deleted file mode 100644 index 206456339..000000000 --- a/builder/esp32-s2-franzininho.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "build": { - "arduino":{ - "ld": "esp32s2_out.ld" - }, - "core": "esp32", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32s2", - "variant": "esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "espidf" - ], - "name": "Franzininho WiFi Board", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/Franzininho/Franzininho-WIFI", - "vendor": "Franzininho" -} diff --git a/builder/esp32-s2-kaluga-1.json b/builder/esp32-s2-kaluga-1.json deleted file mode 100644 index 1f1653351..000000000 --- a/builder/esp32-s2-kaluga-1.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32s2", - "variant": "esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "default_tool": "ftdi", - "onboard_tools": [ - "ftdi" - ], - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Espressif ESP32-S2-Kaluga-1 Kit", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-esp32-s2-kaluga-1-kit.html", - "vendor": "Espressif" -} diff --git a/builder/esp32-s2-saola-1.json b/builder/esp32-s2-saola-1.json deleted file mode 100644 index f264131f9..000000000 --- a/builder/esp32-s2-saola-1.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32S2_DEV", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32s2", - "variant": "esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Espressif ESP32-S2-Saola-1", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html", - "vendor": "Espressif" -} diff --git a/builder/esp32-s3-devkitc-1.json b/builder/esp32-s3-devkitc-1.json deleted file mode 100644 index a2f8b22f5..000000000 --- a/builder/esp32-s3-devkitc-1.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ESP32S3_DEV", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "esp32s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "default_tool": "esp-builtin", - "onboard_tools": [ - "esp-builtin" - ], - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html", - "vendor": "Espressif" -} diff --git a/builder/esp320.json b/builder/esp320.json deleted file mode 100644 index dfa8720e1..000000000 --- a/builder/esp320.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP320", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "esp320" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Electronic SweetPeas ESP320", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.sweetpeas.se/controller-modules/10-esp210.html", - "vendor": "Electronic SweetPeas" -} diff --git a/builder/esp32cam.json b/builder/esp32cam.json deleted file mode 100644 index f7129392c..000000000 --- a/builder/esp32cam.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "huge_app.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "AI Thinker ESP32-CAM", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://wiki.ai-thinker.com/esp32-cam", - "vendor": "AI Thinker" -} diff --git a/builder/esp32dev.json b/builder/esp32dev.json deleted file mode 100644 index 53c81b656..000000000 --- a/builder/esp32dev.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Espressif ESP32 Dev Module", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://en.wikipedia.org/wiki/ESP32", - "vendor": "Espressif" -} diff --git a/builder/esp32doit-devkit-v1.json b/builder/esp32doit-devkit-v1.json deleted file mode 100644 index 5aff5de64..000000000 --- a/builder/esp32doit-devkit-v1.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "doitESP32devkitV1" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "DOIT ESP32 DEVKIT V1", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.doit.am/", - "vendor": "DOIT" -} diff --git a/builder/esp32doit-espduino.json b/builder/esp32doit-espduino.json deleted file mode 100644 index 1cadd7e9a..000000000 --- a/builder/esp32doit-espduino.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "doitESPduino32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "DOIT ESPduino32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.doit.am/", - "vendor": "DOIT" -} diff --git a/builder/esp32s3box.json b/builder/esp32s3box.json deleted file mode 100644 index 8a7bfa907..000000000 --- a/builder/esp32s3box.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld", - "memory_type": "qio_opi" - }, - "core": "esp32", - "extra_flags": [ - "-DBOARD_HAS_PSRAM", - "-DARDUINO_ESP32_S3_BOX", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0X303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "esp32s3box" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Espressif ESP32-S3-Box", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://www.adafruit.com/product/5290", - "vendor": "Espressif" -} diff --git a/builder/esp32s3camlcd.json b/builder/esp32s3camlcd.json deleted file mode 100644 index 5a807a858..000000000 --- a/builder/esp32s3camlcd.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "memory_type": "opi_opi" - }, - "boot": "opi", - "core": "esp32", - "extra_flags": [ - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_ESP32S3_CAM_LCD", - "-DARDUINO_USB_MODE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dout", - "hwids": [ - [ - "0X303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "esp32s3camlcd" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "ESP32S3 CAM LCD", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://www.espressif.com/en/news/Maple_Eye_ESP32-S3", - "vendor": "Espressif" -} diff --git a/builder/esp32thing.json b/builder/esp32thing.json deleted file mode 100644 index 4c168e395..000000000 --- a/builder/esp32thing.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_THING", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32thing" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "SparkFun ESP32 Thing", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.sparkfun.com/products/13907", - "vendor": "SparkFun Electronics" -} diff --git a/builder/esp32thing_plus.json b/builder/esp32thing_plus.json deleted file mode 100644 index cf1a74d68..000000000 --- a/builder/esp32thing_plus.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "default_16MB.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_THING_PLUS", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32thing_plus" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "SparkFun ESP32 Thing Plus", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.sparkfun.com/products/15663", - "vendor": "SparkFun Electronics" -} diff --git a/builder/esp32vn-iot-uno.json b/builder/esp32vn-iot-uno.json deleted file mode 100644 index 83e794ee8..000000000 --- a/builder/esp32vn-iot-uno.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_esp32vn_iot_uno", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32vn-iot-uno" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "ESP32vn IoT Uno", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://esp32.vn/", - "vendor": "ESP32vn" -} diff --git a/builder/espea32.json b/builder/espea32.json deleted file mode 100644 index d995b8bb6..000000000 --- a/builder/espea32.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESPea32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "espea32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "April Brother ESPea32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://blog.aprbrother.com/product/espea", - "vendor": "April Brother" -} diff --git a/builder/espectro32.json b/builder/espectro32.json deleted file mode 100644 index 973c6080e..000000000 --- a/builder/espectro32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESPECTRO32", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "espectro32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "ESPectro32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://shop.makestro.com/product/espectro32", - "vendor": "DycodeX" -} diff --git a/builder/espino32.json b/builder/espino32.json deleted file mode 100644 index 162d97929..000000000 --- a/builder/espino32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESPino32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "espino32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "ESPino32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://thaieasyelec.com/products/development-boards/espino-wifi-development-board-detail.html", - "vendor": "ThaiEasyElec" -} diff --git a/builder/etboard.json b/builder/etboard.json deleted file mode 100644 index 8ae9775d0..000000000 --- a/builder/etboard.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ETBoard", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "ET-Board" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "ETBoard", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://et.ketri.re.kr", - "vendor": "ETBoard" -} diff --git a/builder/featheresp32-s2.json b/builder/featheresp32-s2.json deleted file mode 100644 index 6933ccb57..000000000 --- a/builder/featheresp32-s2.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_NOPSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x239A", - "0x80EB" - ], - [ - "0x239A", - "0x00EB" - ], - [ - "0x239A", - "0x80EC" - ] - ], - "mcu": "esp32s2", - "variant": "adafruit_feather_esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit ESP32-S2 Feather Development Board", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x2d0000", - "variants/adafruit_feather_esp32s2/tinyuf2.bin" - ] - ] - }, - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/4769", - "vendor": "Adafruit" -} diff --git a/builder/featheresp32.json b/builder/featheresp32.json deleted file mode 100644 index ac922db5a..000000000 --- a/builder/featheresp32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_FEATHER_ESP32", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "feather_esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Adafruit ESP32 Feather", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.adafruit.com/product/3405", - "vendor": "Adafruit" -} diff --git a/builder/firebeetle32.json b/builder/firebeetle32.json deleted file mode 100644 index 3463fa131..000000000 --- a/builder/firebeetle32.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "firebeetle32" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "FireBeetle-ESP32", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 532480, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://wiki.dfrobot.com/FireBeetle_ESP32_IOT_Microcontroller(V3.0)__Supports_Wi-Fi_&_Bluetooth__SKU__DFR0478", - "vendor": "DFRobot" -} diff --git a/builder/fm-devkit.json b/builder/fm-devkit.json deleted file mode 100644 index 322975ac8..000000000 --- a/builder/fm-devkit.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_fm_devkit", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "fm-devkit" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "ESP32 FM DevKit", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/dragon-engineer/esp32_fmdevkit", - "vendor": "Unknown" -} diff --git a/builder/franzininho_wifi_esp32s2.json b/builder/franzininho_wifi_esp32s2.json deleted file mode 100644 index df3a5651f..000000000 --- a/builder/franzininho_wifi_esp32s2.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_FRANZININHO_WIFI", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "hwids": [ - [ - "0x303A", - "0x80A9" - ] - ], - "mcu": "esp32s2", - "variant": "franzininho_wifi_esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Franzininho WiFi", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.franzininho.com.br/docs/franzininho-wifi/franzininho-wifi/", - "vendor": "Franzininho" -} diff --git a/builder/franzininho_wifi_msc_esp32s2.json b/builder/franzininho_wifi_msc_esp32s2.json deleted file mode 100644 index 163587b4f..000000000 --- a/builder/franzininho_wifi_msc_esp32s2.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_FRANZININHO_WIFI_MSC", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_USB_MSC_ON_BOOT=1", - "-DARDUINO_USB_DFU_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "hwids": [ - [ - "0x303A", - "0x80A9" - ] - ], - "mcu": "esp32s2", - "variant": "franzininho_wifi_msc_esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Franzininho WiFi MSC", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.franzininho.com.br/docs/franzininho-wifi/franzininho-wifi/", - "vendor": "Franzininho" -} diff --git a/builder/frogboard.json b/builder/frogboard.json deleted file mode 100644 index 93a772920..000000000 --- a/builder/frogboard.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_FROG_ESP32", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "frog32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Frog Board ESP32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.tindie.com/products/fred_IOT/esp32s-esp-wroom32-frogopins-development-board/", - "vendor": "Fred" -} diff --git a/builder/healthypi4.json b/builder/healthypi4.json deleted file mode 100644 index bfebc98a8..000000000 --- a/builder/healthypi4.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HEALTHYPI_4", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "healthypi4" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "ProtoCentral HealthyPi 4", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://healthypi.protocentral.com", - "vendor": "ProtoCentral" -} diff --git a/builder/heltec_wifi_kit_32.json b/builder/heltec_wifi_kit_32.json deleted file mode 100644 index 0960dd454..000000000 --- a/builder/heltec_wifi_kit_32.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HELTEC_WIFI_KIT_32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "heltec_wifi_kit_32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Heltec WiFi Kit 32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.heltec.cn/project/wifi-kit-32/?lang=en", - "vendor": "Heltec Automation" -} diff --git a/builder/heltec_wifi_kit_32_V3.json b/builder/heltec_wifi_kit_32_V3.json deleted file mode 100644 index d10631917..000000000 --- a/builder/heltec_wifi_kit_32_V3.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_heltec_wifi_kit_32_V3", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-DARDUINO_USB_MODE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "heltec_wifi_kit_32_v3" - }, - "connectivity": [ - "wifi", - "bluetooth" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Heltec WiFi Kit 32 (V3)", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://heltec.org/project/wifi-kit-32-v3/", - "vendor": "Heltec" -} diff --git a/builder/heltec_wifi_kit_32_v2.json b/builder/heltec_wifi_kit_32_v2.json deleted file mode 100644 index eb80db671..000000000 --- a/builder/heltec_wifi_kit_32_v2.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HELTEC_WIFI_KIT_32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "heltec_wifi_kit_32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Heltec WiFi Kit 32 (V2)", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.heltec.cn/project/wifi-kit-32/?lang=en", - "vendor": "Heltec Automation" -} diff --git a/builder/heltec_wifi_lora_32.json b/builder/heltec_wifi_lora_32.json deleted file mode 100644 index 39371182d..000000000 --- a/builder/heltec_wifi_lora_32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HELTEC_WIFI_LORA_32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "heltec_wifi_lora_32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Heltec WiFi LoRa 32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.heltec.cn", - "vendor": "Heltec Automation" -} diff --git a/builder/heltec_wifi_lora_32_V2.json b/builder/heltec_wifi_lora_32_V2.json deleted file mode 100644 index c2a0f950a..000000000 --- a/builder/heltec_wifi_lora_32_V2.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HELTEC_WIFI_LORA_32_V2", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "heltec_wifi_lora_32_V2" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Heltec WiFi LoRa 32 (V2)", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.heltec.cn/project/wifi-lora-32/?lang=en", - "vendor": "Heltec Automation" -} diff --git a/builder/heltec_wifi_lora_32_V3.json b/builder/heltec_wifi_lora_32_V3.json deleted file mode 100644 index 09a8e1c74..000000000 --- a/builder/heltec_wifi_lora_32_V3.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_heltec_wifi_lora_32_V3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "heltec_wifi_lora_32_V3" - }, - "connectivity": [ - "wifi", - "bluetooth", - "lora" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Heltec WiFi LoRa 32 (V3)", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://heltec.org/project/wifi-lora-32-v3/", - "vendor": "Heltec" -} diff --git a/builder/heltec_wireless_stick.json b/builder/heltec_wireless_stick.json deleted file mode 100644 index 1f09ca497..000000000 --- a/builder/heltec_wireless_stick.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HELTEC_WIRELESS_STICK", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "heltec_wireless_stick" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Heltec Wireless Stick", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.heltec.cn/project/wireless-stick/?lang=en", - "vendor": "Heltec Automation" -} diff --git a/builder/heltec_wireless_stick_lite.json b/builder/heltec_wireless_stick_lite.json deleted file mode 100644 index 6ffac9acf..000000000 --- a/builder/heltec_wireless_stick_lite.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HELTEC_WIRELESS_STICK_LITE", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "heltec_wireless_stick_lite" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Heltec Wireless Stick Lite", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://heltec.org/project/wireless-stick-lite/", - "vendor": "Heltec Automation" -} diff --git a/builder/honeylemon.json b/builder/honeylemon.json deleted file mode 100644 index c3796dfe0..000000000 --- a/builder/honeylemon.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HONEYLEMON", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "honeylemon" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "HONEYLemon", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://en.wikipedia.org/wiki/ESP32", - "vendor": "HONEYLemon" -} diff --git a/builder/hornbill32dev.json b/builder/hornbill32dev.json deleted file mode 100644 index 6d96e58b5..000000000 --- a/builder/hornbill32dev.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HORNBILL_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "hornbill32dev" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Hornbill ESP32 Dev", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://hackaday.io/project/18997-hornbill", - "vendor": "Hornbill" -} diff --git a/builder/hornbill32minima.json b/builder/hornbill32minima.json deleted file mode 100644 index fce2579de..000000000 --- a/builder/hornbill32minima.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HORNBILL_ESP32_MINIMA", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "hornbill32minima" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Hornbill ESP32 Minima", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://hackaday.io/project/18997-hornbill", - "vendor": "Hornbill" -} diff --git a/builder/imbrios-logsens-v1p1.json b/builder/imbrios-logsens-v1p1.json deleted file mode 100644 index a65362f98..000000000 --- a/builder/imbrios-logsens-v1p1.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_IMBRIOS_LOGSENS_V1P1", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "imbrios-logsens-v1p1" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Imbrios LogSens V1P1", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.imbrios.com/products/logsens", - "vendor": "Imbrios" -} diff --git a/builder/inex_openkb.json b/builder/inex_openkb.json deleted file mode 100644 index 8f326d5f3..000000000 --- a/builder/inex_openkb.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_openkb", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "openkb" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "INEX OpenKB", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://inex.co.th/home/product/openkb/", - "vendor": "INEX" -} diff --git a/builder/intorobot.json b/builder/intorobot.json deleted file mode 100644 index 6149bce8b..000000000 --- a/builder/intorobot.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_INTOROBOT_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "intorobot-fig" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "IntoRobot Fig", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://docs.intorobot.com/zh/hardware/fig/hardware/", - "vendor": "IntoRobot" -} diff --git a/builder/iotaap_magnolia.json b/builder/iotaap_magnolia.json deleted file mode 100644 index 47c1ebad6..000000000 --- a/builder/iotaap_magnolia.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino" - ], - "name": "IoTaaP Magnolia", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://www.iotaap.io", - "vendor": "IoTaaP" -} diff --git a/builder/iotbusio.json b/builder/iotbusio.json deleted file mode 100644 index 11c4264ae..000000000 --- a/builder/iotbusio.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32" - }, - "certified": true, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "default_tool": "iot-bus-jtag", - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "oddWires IoT-Bus Io", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.oddwires.com/iot-bus-io-esp32-processor-with-wifi-and-bluetooth/", - "vendor": "oddWires" -} diff --git a/builder/iotbusproteus.json b/builder/iotbusproteus.json deleted file mode 100644 index 3859504f7..000000000 --- a/builder/iotbusproteus.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32" - }, - "certified": true, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "default_tool": "iot-bus-jtag", - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "oddWires IoT-Bus Proteus", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.oddwires.com/proteus-iot-bus-esp32-microprocessor-wi-fi-and-bluetooth-with-prototype-board-form-factor/", - "vendor": "oddWires" -} diff --git a/builder/kb32-ft.json b/builder/kb32-ft.json deleted file mode 100644 index 4bfab5e8d..000000000 --- a/builder/kb32-ft.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ESP32_DEV", - "-DBOARD_HAS_PSRAM", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "MakerAsia KB32-FT", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://kb32ft.makerasia.com/", - "vendor": "MakerAsia" -} diff --git a/builder/kits-edu.json b/builder/kits-edu.json deleted file mode 100644 index 6ec72aef9..000000000 --- a/builder/kits-edu.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_PICO", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "pico32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "KITS ESP32 EDU", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.koreaits.com/new/product/summary.htm?goods_no=468&mid_no=103&no=17", - "vendor": "KITS" -} diff --git a/builder/labplus_mpython.json b/builder/labplus_mpython.json deleted file mode 100644 index 3d3a4ff4e..000000000 --- a/builder/labplus_mpython.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "huge_app.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "mpython" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Labplus mPython", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/labplus-cn/mpython", - "vendor": "Labplus" -} diff --git a/builder/lilygo-t-display-s3.json b/builder/lilygo-t-display-s3.json deleted file mode 100644 index 7230d3bd2..000000000 --- a/builder/lilygo-t-display-s3.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "memory_type": "qio_opi", - "partitions": "default_16MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_LILYGO_T_DISPLAY_S3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "lilygo_t_display_s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "LilyGo T-Display-S3", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.lilygo.cc/products/t-display-s3", - "vendor": "LilyGo" -} diff --git a/builder/lionbit.json b/builder/lionbit.json deleted file mode 100644 index c8186d0b2..000000000 --- a/builder/lionbit.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_LIONBIT", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "flags" : "-DCORE_DEBUG_LEVEL=5", - "mcu": "esp32", - "variant": "lionbit" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Lion:Bit Dev Board", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 115200 - }, - "monitor": { - "speed" : 115200 - }, - "url": "http://lionbit.lk/", - "vendor": "Lion:Bit" -} diff --git a/builder/lolin32.json b/builder/lolin32.json deleted file mode 100644 index 446b2cd44..000000000 --- a/builder/lolin32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_LOLIN32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "lolin32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS LOLIN32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://wiki.wemos.cc/products:lolin32:lolin32", - "vendor": "WEMOS" -} diff --git a/builder/lolin32_lite.json b/builder/lolin32_lite.json deleted file mode 100644 index 5e16bc85a..000000000 --- a/builder/lolin32_lite.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_LOLIN32_LITE", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "lolin32-lite" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS LOLIN32 Lite", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://diyprojects.io/wemos-lolin32-lite-compact-revision-lolin32-4-90/", - "vendor": "WEMOS" -} diff --git a/builder/lolin_c3_mini.json b/builder/lolin_c3_mini.json deleted file mode 100644 index 63afade2c..000000000 --- a/builder/lolin_c3_mini.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_LOLIN_C3_MINI", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0X303A", - "0x1001" - ] - ], - "mcu": "esp32c3", - "variant": "lolin_c3_mini" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS LOLIN C3 Mini", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.wemos.cc/en/latest/c3/c3_mini.html", - "vendor": "WEMOS" -} diff --git a/builder/lolin_d32.json b/builder/lolin_d32.json deleted file mode 100644 index bde02b347..000000000 --- a/builder/lolin_d32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_LOLIN_D32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "d32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS LOLIN D32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://wiki.wemos.cc/products:d32:d32", - "vendor": "WEMOS" -} diff --git a/builder/lolin_d32_pro.json b/builder/lolin_d32_pro.json deleted file mode 100644 index 732b07318..000000000 --- a/builder/lolin_d32_pro.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_LOLIN_D32_PRO -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "d32_pro" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp32-wrover.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS LOLIN D32 PRO", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.wemos.cc/en/latest/d32/d32_pro.html", - "vendor": "WEMOS" -} diff --git a/builder/lolin_s2_mini.json b/builder/lolin_s2_mini.json deleted file mode 100644 index 59832f8cb..000000000 --- a/builder/lolin_s2_mini.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_LOLIN_S2_MINI", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "hwids": [ - [ - "0X303A", - "0x80C2" - ] - ], - "mcu": "esp32s2", - "variant": "lolin_s2_mini" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS LOLIN S2 Mini", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://www.wemos.cc/en/latest/s2/s2_mini.html", - "vendor": "WEMOS" -} diff --git a/builder/lolin_s2_pico.json b/builder/lolin_s2_pico.json deleted file mode 100644 index 0214a0eea..000000000 --- a/builder/lolin_s2_pico.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_LOLIN_S2_PICO", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "hwids": [ - [ - "0X303A", - "0x80C5" - ] - ], - "mcu": "esp32s2", - "variant": "lolin_s2_pico" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS LOLIN S2 PICO", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://www.wemos.cc/en/latest/s2/s2_pico.html", - "vendor": "WEMOS" -} diff --git a/builder/lolin_s3.json b/builder/lolin_s3.json deleted file mode 100644 index 30f360e0c..000000000 --- a/builder/lolin_s3.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "default_16MB.csv", - "memory_type": "qio_opi" - }, - "core": "esp32", - "extra_flags": [ - "-DBOARD_HAS_PSRAM", - "-DARDUINO_LOLIN_S3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "lolin_s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS LOLIN S3", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.wemos.cc/en/latest/s3/index.html", - "vendor": "WEMOS" -} diff --git a/builder/lolin_s3_mini.json b/builder/lolin_s3_mini.json deleted file mode 100644 index ad3794bcb..000000000 --- a/builder/lolin_s3_mini.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DBOARD_HAS_PSRAM", - "-DARDUINO_LOLIN_S3_MINI", - "-DARDUINO_USB_MODE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x8167" - ] - ], - "mcu": "esp32s3", - "variant": "lolin_s3_mini" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS LOLIN S3 Mini", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.wemos.cc/en/latest/s3/index.html", - "vendor": "WEMOS" -} - \ No newline at end of file diff --git a/builder/lopy.json b/builder/lopy.json deleted file mode 100644 index 307d06a1a..000000000 --- a/builder/lopy.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_LoPy", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "lopy" - }, - "connectivity": [ - "wifi", - "bluetooth", - "can", - "ethernet" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Pycom LoPy", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://pycom.io/", - "vendor": "Pycom Ltd." -} diff --git a/builder/lopy4.json b/builder/lopy4.json deleted file mode 100644 index 29062f0fa..000000000 --- a/builder/lopy4.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_LoPy4", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "lopy4" - }, - "connectivity": [ - "wifi", - "bluetooth", - "can", - "ethernet" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Pycom LoPy4", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 1310720, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://pycom.io/", - "vendor": "Pycom Ltd." -} diff --git a/builder/m5stack-atom.json b/builder/m5stack-atom.json deleted file mode 100644 index fd704b0d1..000000000 --- a/builder/m5stack-atom.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_M5Stack_ATOM", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "m5stack_atom" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack-ATOM", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 1500000 - }, - "url": "http://www.m5stack.com", - "vendor": "M5Stack" -} diff --git a/builder/m5stack-atoms3.json b/builder/m5stack-atoms3.json deleted file mode 100644 index f5e87d3ab..000000000 --- a/builder/m5stack-atoms3.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_M5Stack_ATOMS3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "m5stack_atoms3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack AtomS3", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.m5stack.com/en/core/AtomS3", - "vendor": "M5Stack" -} diff --git a/builder/m5stack-core-esp32.json b/builder/m5stack-core-esp32.json deleted file mode 100644 index 8d015f417..000000000 --- a/builder/m5stack-core-esp32.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_M5Stack_Core_ESP32", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "m5stack_core_esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack Core ESP32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.m5stack.com", - "vendor": "M5Stack" -} diff --git a/builder/m5stack-core2.json b/builder/m5stack-core2.json deleted file mode 100644 index 2c3b95154..000000000 --- a/builder/m5stack-core2.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "default_16MB.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "m5stack_core2" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack Core2", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 4521984, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.m5stack.com", - "vendor": "M5Stack" -} diff --git a/builder/m5stack-coreink.json b/builder/m5stack-coreink.json deleted file mode 100644 index e7b3cbb1c..000000000 --- a/builder/m5stack-coreink.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_M5Stack_CoreInk", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "m5stack_coreink" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack-Core Ink", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.m5stack.com", - "vendor": "M5Stack" -} diff --git a/builder/m5stack-cores3.json b/builder/m5stack-cores3.json deleted file mode 100644 index 72571e0b7..000000000 --- a/builder/m5stack-cores3.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "default_16MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_M5STACK_CORES3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x8119" - ] - ], - "mcu": "esp32s3", - "variant": "m5stack_cores3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack CoreS3", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://docs.m5stack.com/en/core/CoreS3", - "vendor": "M5Stack" -} diff --git a/builder/m5stack-fire.json b/builder/m5stack-fire.json deleted file mode 100644 index 1a500ab87..000000000 --- a/builder/m5stack-fire.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "default_16MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_M5STACK_FIRE", - "-DBOARD_HAS_PSRAM", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "m5stack_fire" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack FIRE", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 4521984, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.m5stack.com", - "vendor": "M5Stack" -} diff --git a/builder/m5stack-grey.json b/builder/m5stack-grey.json deleted file mode 100644 index 886208ee4..000000000 --- a/builder/m5stack-grey.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_M5Stack_Core_ESP32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "m5stack_core_esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack GREY ESP32", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 532480, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.m5stack.com", - "vendor": "M5Stack" -} diff --git a/builder/m5stack-stamps3.json b/builder/m5stack-stamps3.json deleted file mode 100644 index 6c92e3b5d..000000000 --- a/builder/m5stack-stamps3.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_M5Stack_StampS3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "m5stack_stamp_s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack StampS3", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.m5stack.com/en/core/StampS3", - "vendor": "M5Stack" -} diff --git a/builder/m5stack-station.json b/builder/m5stack-station.json deleted file mode 100644 index 31693d501..000000000 --- a/builder/m5stack-station.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_M5Stack_Station", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "m5stack_station" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack Station", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 4521984, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.m5stack.com", - "vendor": "M5Stack" -} diff --git a/builder/m5stack-timer-cam.json b/builder/m5stack-timer-cam.json deleted file mode 100644 index 5f76a861e..000000000 --- a/builder/m5stack-timer-cam.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_M5Stack_Timer_CAM", - "-DBOARD_HAS_PSRAM", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "m5stack_timer_cam" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stack Timer CAM", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.m5stack.com", - "vendor": "M5Stack" -} diff --git a/builder/m5stamp-pico.json b/builder/m5stamp-pico.json deleted file mode 100644 index 8f39fe5ce..000000000 --- a/builder/m5stamp-pico.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_M5Stamp_Pico", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "m5stack_stamp_pico" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stamp-Pico", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 1500000 - }, - "url": "https://shop.m5stack.com/products/m5stamp-pico-mate-with-pin-headers", - "vendor": "M5Stack" -} diff --git a/builder/m5stick-c.json b/builder/m5stick-c.json deleted file mode 100644 index 5c96d7e86..000000000 --- a/builder/m5stick-c.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_M5Stick_C", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "m5stick_c" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "M5Stick-C", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 1500000 - }, - "url": "http://www.m5stack.com", - "vendor": "M5Stack" -} diff --git a/builder/magicbit.json b/builder/magicbit.json deleted file mode 100644 index 53b939e2a..000000000 --- a/builder/magicbit.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "magicbit" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "MagicBit", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://magicblocks.io/", - "vendor": "Magicblocks.io" -} diff --git a/builder/mgbot-iotik32a.json b/builder/mgbot-iotik32a.json deleted file mode 100644 index b4dc416f5..000000000 --- a/builder/mgbot-iotik32a.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_MGBOT_IOTIK32A", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "mgbot-iotik32a" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "MGBOT IOTIK 32A", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://iotik.ru/en/iotik32a/", - "vendor": "MGBOT" -} diff --git a/builder/mgbot-iotik32b.json b/builder/mgbot-iotik32b.json deleted file mode 100644 index 15f3d8535..000000000 --- a/builder/mgbot-iotik32b.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_MGBOT_IOTIK32B", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "mgbot-iotik32b" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "MGBOT IOTIK 32B", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://iotik.ru/en/iotik32b/", - "vendor": "MGBOT" -} diff --git a/builder/mhetesp32devkit.json b/builder/mhetesp32devkit.json deleted file mode 100644 index 7b677c905..000000000 --- a/builder/mhetesp32devkit.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_MH_ET_LIVE_ESP32DEVKIT", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "mhetesp32devkit" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "MH ET LIVE ESP32DevKIT", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://forum.mhetlive.com", - "vendor": "MH-ET Live" -} diff --git a/builder/mhetesp32minikit.json b/builder/mhetesp32minikit.json deleted file mode 100644 index 67f451e4a..000000000 --- a/builder/mhetesp32minikit.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_MH_ET_LIVE_ESP32MINIKIT", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "mhetesp32minikit" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "MH ET LIVE ESP32MiniKit", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://forum.mhetlive.com", - "vendor": "MH-ET Live" -} diff --git a/builder/microduino-core-esp32.json b/builder/microduino-core-esp32.json deleted file mode 100644 index f1dddb727..000000000 --- a/builder/microduino-core-esp32.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_CoreESP32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "Microduino-esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Microduino Core ESP32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://microduinoinc.com", - "vendor": "Microduino" -} diff --git a/builder/micros2.json b/builder/micros2.json deleted file mode 100644 index 93243bdba..000000000 --- a/builder/micros2.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld", - "partitions": "ffat.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_MICROS2", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_USB_MSC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "hwids": [ - [ - "0x239A", - "0x80C5" - ] - ], - "mcu": "esp32s2", - "variant": "micro_s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "microS2", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/MicroDev1/microS2", - "vendor": "microS2" -} diff --git a/builder/minimain_esp32s2.json b/builder/minimain_esp32s2.json deleted file mode 100644 index 5502a6aff..000000000 --- a/builder/minimain_esp32s2.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_DEPARTMENT_OF_ALCHEMY_MINIMAIN_ESP32S2", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x80FF" - ] - ], - "mcu": "esp32s2", - "variant": "department_of_alchemy_minimain_esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Deparment of Alchemy MiniMain ESP32-S2", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/DepartmentOfAlchemy/minimain-esp32-s2", - "vendor": "Deparment of Alchemy" -} diff --git a/builder/nano32.json b/builder/nano32.json deleted file mode 100644 index 2e1f5568c..000000000 --- a/builder/nano32.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_NANO32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "nano32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "MakerAsia Nano32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://iot-bits.com/nano32-esp32-development-board", - "vendor": "MakerAsia" -} diff --git a/builder/nebulas3.json b/builder/nebulas3.json deleted file mode 100644 index dc6236494..000000000 --- a/builder/nebulas3.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "memory_type": "qio_opi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_NEBULAS3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "Nebula_S3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Kinetic Dynamics Nebula S3", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://kineticdynamics.in/product/nebula-s3/", - "vendor": "Kinetic Dynamics" -} diff --git a/builder/nina_w10.json b/builder/nina_w10.json deleted file mode 100644 index a0041df2f..000000000 --- a/builder/nina_w10.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "minimal.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_UBLOX_NINA_W10", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "nina_w10" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "u-blox NINA-W10 series", - "upload": { - "flash_size": "2MB", - "maximum_ram_size": 327680, - "maximum_size": 2097152, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.u-blox.com/en/product/nina-w10-series", - "vendor": "u-blox" -} diff --git a/builder/node32s.json b/builder/node32s.json deleted file mode 100644 index 192bda36a..000000000 --- a/builder/node32s.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_Node32s", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Node32s", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.ayarafun.com", - "vendor": "Aiyarafun" -} diff --git a/builder/nodemcu-32s.json b/builder/nodemcu-32s.json deleted file mode 100644 index 5d30f2c2e..000000000 --- a/builder/nodemcu-32s.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_NodeMCU_32S", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "nodemcu-32s" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "NodeMCU-32S", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.nodemcu.com/", - "vendor": "NodeMCU" -} diff --git a/builder/nodemcu-32s2.json b/builder/nodemcu-32s2.json deleted file mode 100644 index 984b90d2b..000000000 --- a/builder/nodemcu-32s2.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32S2_DEV", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32s2", - "variant": "esp32s2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Ai-Thinker NodeMCU-32S2 (ESP-12K)", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://docs.ai-thinker.com/en/esp32s2", - "vendor": "Ai-Thinker" -} diff --git a/builder/nscreen-32.json b/builder/nscreen-32.json deleted file mode 100644 index d9b3a40af..000000000 --- a/builder/nscreen-32.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x0403", - "0x6010" - ] - ], - "mcu": "esp32", - "variant": "esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "YeaCreate NSCREEN-32", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://yeacreate.com", - "vendor": "YeaCreate" -} diff --git a/builder/odroid_esp32.json b/builder/odroid_esp32.json deleted file mode 100644 index 0634df32a..000000000 --- a/builder/odroid_esp32.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ODROID_ESP32 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "odroid_esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "ODROID-GO", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.hardkernel.com/main/products/prdt_info.php?g_code=G152875062626", - "vendor": "Hardkernel" -} diff --git a/builder/onehorse32dev.json b/builder/onehorse32dev.json deleted file mode 100644 index 4b2364100..000000000 --- a/builder/onehorse32dev.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ONEHORSE_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dout", - "mcu": "esp32", - "variant": "onehorse32dev" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Onehorse ESP32 Dev Module", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.tindie.com/products/onehorse/esp32-development-board/", - "vendor": "Onehorse" -} diff --git a/builder/oroca_edubot.json b/builder/oroca_edubot.json deleted file mode 100644 index 2a99c8c6c..000000000 --- a/builder/oroca_edubot.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "huge_app.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_OROCA_EDUBOT", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "oroca_edubot" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "OROCA EduBot", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/oroca/OROCA-EduBot", - "vendor": "OROCA" -} diff --git a/builder/pico32.json b/builder/pico32.json deleted file mode 100644 index 5580b07e0..000000000 --- a/builder/pico32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_PICO", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "pico32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "ESP32 Pico Kit", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://esp-idf.readthedocs.io/en/latest/get-started/get-started-pico-kit.html", - "vendor": "Espressif" -} diff --git a/builder/piranha_esp32.json b/builder/piranha_esp32.json deleted file mode 100644 index acd8a231a..000000000 --- a/builder/piranha_esp32.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_Piranha", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "piranha_esp-32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Fishino Piranha ESP-32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://fishino.it/boards.html", - "vendor": "Fishino" -} diff --git a/builder/pocket_32.json b/builder/pocket_32.json deleted file mode 100644 index 153ac2322..000000000 --- a/builder/pocket_32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_Pocket32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "pocket_32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Dongsen Tech Pocket 32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://dong-sen.com", - "vendor": "Dongsen Technology" -} diff --git a/builder/pycom_gpy.json b/builder/pycom_gpy.json deleted file mode 100644 index 37cc507e1..000000000 --- a/builder/pycom_gpy.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_PYCOM_GPY", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "gpy" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Pycom GPy", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://pycom.io/product/gpy/", - "vendor": "Pycom Ltd." -} diff --git a/builder/qchip.json b/builder/qchip.json deleted file mode 100644 index 11f4c9259..000000000 --- a/builder/qchip.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_HELTEC_WIFI_KIT_32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "heltec_wifi_kit_32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Qchip", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://qmobot.com/", - "vendor": "Qmobot LLP" - } \ No newline at end of file diff --git a/builder/quantum.json b/builder/quantum.json deleted file mode 100644 index ea5ae279f..000000000 --- a/builder/quantum.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_QUANTUM", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "quantum" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Noduino Quantum", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://wiki.jackslab.org/Noduino", - "vendor": "Noduino" -} diff --git a/builder/redpill_esp32s3.json b/builder/redpill_esp32s3.json deleted file mode 100644 index 8dff2ff49..000000000 --- a/builder/redpill_esp32s3.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_REDPILL_ESP32S3", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x80F8" - ] - ], - "mcu": "esp32s3", - "variant": "redpill_esp32s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Munich Labs RedPill ESP32-S3", - "upload": { - "arduino": { - "flash_extra_images": [ - [ - "0x410000", - "variants/redpill_esp32s3/tinyuf2.bin" - ] - ] - }, - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://munich-labs.com/index.php/redpill-esp32-s3/", - "vendor": "Munich Labs" -} diff --git a/builder/roboheart_hercules.json b/builder/roboheart_hercules.json deleted file mode 100644 index 46740d2e9..000000000 --- a/builder/roboheart_hercules.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_roboheart_hercules", - "-DBOARD_HAS_PSRAM", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "roboheart_hercules" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "RoboHeart Hercules", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://roboheart.de/en_gb/", - "vendor": "RoboHeart" -} diff --git a/builder/s_odi_ultra.json b/builder/s_odi_ultra.json deleted file mode 100644 index 3a0307867..000000000 --- a/builder/s_odi_ultra.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "S_ODI_Ultra_v1" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "S.ODI Ultra v1", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.espressif.com/en/products/socs/esp32", - "vendor": "S.ODI" -} diff --git a/builder/seeed_xiao_esp32c3.json b/builder/seeed_xiao_esp32c3.json deleted file mode 100644 index 24b167120..000000000 --- a/builder/seeed_xiao_esp32c3.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_XIAO_ESP32C3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x2886", - "0x0046" - ], - [ - "0x303a", - "0x1001" - ] - ], - "mcu": "esp32c3", - "variant": "XIAO_ESP32C3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Seeed Studio XIAO ESP32C3", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/", - "vendor": "Seeed Studio" -} diff --git a/builder/seeed_xiao_esp32s3.json b/builder/seeed_xiao_esp32s3.json deleted file mode 100644 index cf98a6aa4..000000000 --- a/builder/seeed_xiao_esp32s3.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv", - "memory_type": "qio_opi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_XIAO_ESP32S3", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x2886", - "0x0056" - ], - [ - "0x2886", - "0x8056" - ] - ], - "mcu": "esp32s3", - "variant": "XIAO_ESP32S3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Seeed Studio XIAO ESP32S3", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.seeedstudio.com/XIAO-ESP32S3-p-5627.html", - "vendor": "Seeed Studio" -} diff --git a/builder/sensesiot_weizen.json b/builder/sensesiot_weizen.json deleted file mode 100644 index 4492655c4..000000000 --- a/builder/sensesiot_weizen.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_sensesiot_weizen", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp32-wrover.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "LOGISENSES Senses Weizen", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.logisenses.com/index.php/product/senses-weizen/", - "vendor": "LOGISENSES" -} diff --git a/builder/sg-o_airMon.json b/builder/sg-o_airMon.json deleted file mode 100644 index 53e254435..000000000 --- a/builder/sg-o_airMon.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_SG_O_AIRMON_ESP32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "platforms": [ - "espressif32" - ], - "name": "SG-O AirMon", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/SG-O/airMon", - "vendor": "SG-O" -} diff --git a/builder/sparkfun_esp32_iot_redboard.json b/builder/sparkfun_esp32_iot_redboard.json deleted file mode 100644 index e97c2d886..000000000 --- a/builder/sparkfun_esp32_iot_redboard.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_ESP32_IOT_REDBOARD", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "sparkfun_esp32_iot_redboard" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "SparkFun ESP32 IoT RedBoard", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.sparkfun.com/products/19177", - "vendor": "SparkFun" -} diff --git a/builder/sparkfun_esp32micromod.json b/builder/sparkfun_esp32micromod.json deleted file mode 100644 index 16fb0f168..000000000 --- a/builder/sparkfun_esp32micromod.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_MICROMOD", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "esp32micromod" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "SparkFun ESP32 MicroMod", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.sparkfun.com/products/16781", - "vendor": "SparkFun" -} diff --git a/builder/sparkfun_esp32s2_thing_plus.json b/builder/sparkfun_esp32s2_thing_plus.json deleted file mode 100644 index f8697e73a..000000000 --- a/builder/sparkfun_esp32s2_thing_plus.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32S2_THING_PLUS", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x1B4F", - "0x0027" - ] - ], - "mcu": "esp32s2", - "variant": "esp32s2thing_plus" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "SparkFun ESP32-S2 Thing Plus", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.sparkfun.com/products/17743", - "vendor": "SparkFun" -} diff --git a/builder/sparkfun_esp32s2_thing_plus_c.json b/builder/sparkfun_esp32s2_thing_plus_c.json deleted file mode 100644 index 01aaed7cb..000000000 --- a/builder/sparkfun_esp32s2_thing_plus_c.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld", - "partitions": "default_16MB.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_THING_PLUS_C", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32thing_plus_c" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "SparkFun ESP32 Thing Plus C", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.sparkfun.com/products/18018", - "vendor": "SparkFun" -} diff --git a/builder/sparkfun_lora_gateway_1-channel.json b/builder/sparkfun_lora_gateway_1-channel.json deleted file mode 100644 index 16eb8438c..000000000 --- a/builder/sparkfun_lora_gateway_1-channel.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "sparkfun_lora_gateway_1-channel" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "SparkFun LoRa Gateway 1-Channel", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.sparkfun.com/products/15006", - "vendor": "SparkFun" -} diff --git a/builder/tamc_termod_s3.json b/builder/tamc_termod_s3.json deleted file mode 100644 index 934c15fb1..000000000 --- a/builder/tamc_termod_s3.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_TAMC_TERMOD_S3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", - "-DBOARD_HAS_PSRAM" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "tamc_termod_s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TAMC Termod S3", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://termod-s3.readthedocs.io/en/latest/", - "vendor": "TAMC" -} diff --git a/builder/tinypico.json b/builder/tinypico.json deleted file mode 100644 index 0b1302e8a..000000000 --- a/builder/tinypico.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_TINYPICO", - "-DBOARD_HAS_PSRAM", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "um_tinypico" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Unexpected Maker TinyPICO", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.tinypico.com", - "vendor": "Unexpected Maker" -} diff --git a/builder/trueverit-iot-driver-mk2.json b/builder/trueverit-iot-driver-mk2.json deleted file mode 100644 index 22e3eca79..000000000 --- a/builder/trueverit-iot-driver-mk2.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver_MK_II", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32-trueverit-iot-driver-mkii" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Trueverit ESP32 Universal IoT Driver MK II", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://trueverit.com/", - "vendor": "Trueverit" -} diff --git a/builder/trueverit-iot-driver-mk3.json b/builder/trueverit-iot-driver-mk3.json deleted file mode 100644 index 0b394a723..000000000 --- a/builder/trueverit-iot-driver-mk3.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver_MK_III", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "esp32-trueverit-iot-driver-mkiii" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Trueverit ESP32 Universal IoT Driver MK III", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://trueverit.com/", - "vendor": "Trueverit" -} - diff --git a/builder/trueverit-iot-driver.json b/builder/trueverit-iot-driver.json deleted file mode 100644 index 7f808ec32..000000000 --- a/builder/trueverit-iot-driver.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "esp32-trueverit-iot-driver" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Trueverit ESP32 Universal IoT Driver", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://trueverit.com/", - "vendor": "Trueverit" -} diff --git a/builder/ttgo-lora32-v1.json b/builder/ttgo-lora32-v1.json deleted file mode 100644 index 339a8b61b..000000000 --- a/builder/ttgo-lora32-v1.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_TTGO_LoRa32_V1", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "ttgo-lora32-v1" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TTGO LoRa32-OLED V1", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/Xinyuan-LilyGO/TTGO-LoRa-Series", - "vendor": "TTGO" -} diff --git a/builder/ttgo-lora32-v2.json b/builder/ttgo-lora32-v2.json deleted file mode 100644 index 502c3576f..000000000 --- a/builder/ttgo-lora32-v2.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_TTGO_LoRa32_V2", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "ttgo-lora32-v2" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TTGO LoRa32-OLED V2", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/LilyGO/TTGO-LORA32-V2.0", - "vendor": "TTGO" -} diff --git a/builder/ttgo-lora32-v21.json b/builder/ttgo-lora32-v21.json deleted file mode 100644 index c2fb118b3..000000000 --- a/builder/ttgo-lora32-v21.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_TTGO_LoRa32_v21new", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "ttgo-lora32-v21new" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TTGO LoRa32-OLED v2.1.6", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/LilyGO/TTGO-LoRa32-V2.1", - "vendor": "TTGO" -} diff --git a/builder/ttgo-t-beam.json b/builder/ttgo-t-beam.json deleted file mode 100644 index f2d144aa2..000000000 --- a/builder/ttgo-t-beam.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_T_Beam -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "tbeam" - }, - "connectivity": [ - "wifi", - "bluetooth", - "can", - "ethernet" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TTGO T-Beam", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 1310720, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/LilyGO/TTGO-T-Beam", - "vendor": "TTGO" -} diff --git a/builder/ttgo-t-oi-plus.json b/builder/ttgo-t-oi-plus.json deleted file mode 100644 index 3b05918ef..000000000 --- a/builder/ttgo-t-oi-plus.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "extra_flags": "-DARDUINO_TTGO_T_OI_PLUS_DEV", - "mcu": "esp32c3", - "variant": "ttgo-t-oi-plus" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TTGO T-OI PLUS RISC-V ESP32-C3", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.lilygo.cn/prod_view.aspx?TypeId=50044&Id=1361&FId=t3:50044:3", - "vendor": "TTGO" -} diff --git a/builder/ttgo-t-watch.json b/builder/ttgo-t-watch.json deleted file mode 100644 index 354f54f14..000000000 --- a/builder/ttgo-t-watch.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "default_16MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_TWATCH_BASE", - "-DBOARD_HAS_PSRAM", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "twatch" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TTGO T-Watch", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 2000000 - }, - "url": "https://github.com/Xinyuan-LilyGO/TTGO-T-Watch", - "vendor": "TTGO" -} diff --git a/builder/ttgo-t1.json b/builder/ttgo-t1.json deleted file mode 100644 index 4f428cd08..000000000 --- a/builder/ttgo-t1.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_TTGO_T1", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "ttgo-t1" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TTGO T1", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/LilyGO/ESP32-TTGO-T1", - "vendor": "TTGO" -} diff --git a/builder/ttgo-t7-v13-mini32.json b/builder/ttgo-t7-v13-mini32.json deleted file mode 100644 index 21552df94..000000000 --- a/builder/ttgo-t7-v13-mini32.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_TTGO_T7_V13_Mini32", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "ttgo-t7-v13-mini32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "can", - "ethernet" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TTGO T7 V1.3 Mini32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 1310720, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://github.com/LilyGO/ESP32-MINI-32-V1.3", - "vendor": "TTGO" -} diff --git a/builder/ttgo-t7-v14-mini32.json b/builder/ttgo-t7-v14-mini32.json deleted file mode 100644 index 23d327196..000000000 --- a/builder/ttgo-t7-v14-mini32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_TTGO_T7_V14_Mini32", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "ttgo-t7-v14-mini32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "can", - "ethernet" - ], - "debug": { - "openocd_board": "esp32-wrover.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "TTGO T7 V1.4 Mini32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 1310720, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.lilygo.cn/prod_view.aspx?TypeId=50033&Id=978&FId=t3:50033:3", - "vendor": "TTGO" -} diff --git a/builder/turta_iot_node.json b/builder/turta_iot_node.json deleted file mode 100644 index 3f3482510..000000000 --- a/builder/turta_iot_node.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_PICO", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "pico32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Turta IoT Node", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.turta.io/en/iotnode", - "vendor": "Turta" -} diff --git a/builder/um_feathers2.json b/builder/um_feathers2.json deleted file mode 100644 index 7434f195e..000000000 --- a/builder/um_feathers2.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_FEATHERS2", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "hwids": [ - [ - "0x239A", - "0x80AB" - ] - ], - "mcu": "esp32s2", - "variant": "um_feathers2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Unexpected Maker FeatherS2", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://feathers2.io", - "vendor": "Unexpected Maker" -} diff --git a/builder/um_feathers2_neo.json b/builder/um_feathers2_neo.json deleted file mode 100644 index 7277d45ff..000000000 --- a/builder/um_feathers2_neo.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_FEATHERS2NEO", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "hwids": [ - [ - "0x303A", - "0x80B4" - ] - ], - "mcu": "esp32s2", - "variant": "um_feathers2neo" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Unexpected Maker FeatherS2 Neo", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://unexpectedmaker.com/feathers2-neo", - "vendor": "Unexpected Maker" -} diff --git a/builder/um_feathers3.json b/builder/um_feathers3.json deleted file mode 100644 index 4430f59b0..000000000 --- a/builder/um_feathers3.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld", - "partitions": "default_16MB.csv", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_FEATHERS3", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0X303A", - "0x80D0" - ] - ], - "mcu": "esp32s3", - "variant": "um_feathers3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Unexpected Maker FeatherS3", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://unexpectedmaker.com/shop/feathers3", - "vendor": "Unexpected Maker" -} diff --git a/builder/um_pros3.json b/builder/um_pros3.json deleted file mode 100644 index b0b379834..000000000 --- a/builder/um_pros3.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld", - "partitions": "default_16MB.csv", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_PROS3", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "um_pros3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Unexpected Maker PROS3", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://unexpectedmaker.com/shop/pros3", - "vendor": "Unexpected Maker" -} diff --git a/builder/um_rmp.json b/builder/um_rmp.json deleted file mode 100644 index c5e547acc..000000000 --- a/builder/um_rmp.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_RMP", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "hwids": [ - [ - "0X303A", - "0x80F6" - ] - ], - "mcu": "esp32s2", - "variant": "um_rmp" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Unexpected Maker RMP", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://unexpectedmaker.com/esp32s2", - "vendor": "Unexpected Maker" -} diff --git a/builder/um_tinys2.json b/builder/um_tinys2.json deleted file mode 100644 index 8a57216ac..000000000 --- a/builder/um_tinys2.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s2_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_TINYS2", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "hwids": [ - [ - "0x303A", - "0x8001" - ] - ], - "mcu": "esp32s2", - "variant": "um_tinys2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s2.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Unexpected Maker TinyS2", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 921600 - }, - "url": "https://tinys2.io", - "vendor": "Unexpected Maker" -} diff --git a/builder/um_tinys3.json b/builder/um_tinys3.json deleted file mode 100644 index 6a9e3c14c..000000000 --- a/builder/um_tinys3.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv", - "memory_type": "qio_qspi" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_TINYS3", - "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0X303A", - "0x80D0" - ] - ], - "mcu": "esp32s3", - "variant": "um_tinys3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Unexpected Maker TinyS3", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://unexpectedmaker.com/shop/ttinys3-esp32s3", - "vendor": "Unexpected Maker" -} diff --git a/builder/unphone7.json b/builder/unphone7.json deleted file mode 100644 index 4204c79da..000000000 --- a/builder/unphone7.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DUNPHONE_SPIN=7", - "-DARDUINO_FEATHER_ESP32" - ], - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "feather_esp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "unPhone 7", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://unphone.net/", - "vendor": "University of Sheffield" -} diff --git a/builder/unphone8.json b/builder/unphone8.json deleted file mode 100644 index 3ee0955d9..000000000 --- a/builder/unphone8.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DBOARD_HAS_PSRAM", - "-DUNPHONE_SPIN=8", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=0", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32s3", - "variant": "unphone8" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_board": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "unPhone 8", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 2424832, - "maximum_size": 8323072, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://unphone.net/", - "vendor": "University of Sheffield" -} diff --git a/builder/unphone9.json b/builder/unphone9.json deleted file mode 100644 index e269a9662..000000000 --- a/builder/unphone9.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32s3_out.ld", - "partitions": "default_8MB.csv" - }, - "core": "esp32", - "extra_flags": [ - "-DBOARD_HAS_PSRAM", - "-DUNPHONE_SPIN=9", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x16D0", - "0x1178" - ] - ], - "mcu": "esp32s3", - "variant": "unphone9" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_board": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "unPhone 9", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 8716288, - "maximum_size": 8323072, - "use_1200bps_touch": true, - "wait_for_upload_port": true, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://unphone.net/", - "vendor": "University of Sheffield" -} diff --git a/builder/upesy_wroom.json b/builder/upesy_wroom.json deleted file mode 100644 index 5d2553225..000000000 --- a/builder/upesy_wroom.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_uPesy_WROOM", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "uPesy_esp32_wroom_devkit" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "uPesy ESP32 Wroom DevKit", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.upesy.fr/products/upesy-esp32-wroom-devkit-board", - "vendor": "uPesy" -} diff --git a/builder/upesy_wrover.json b/builder/upesy_wrover.json deleted file mode 100644 index 5eb0e0fd3..000000000 --- a/builder/upesy_wrover.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_uPesy_WROVER", - "-DBOARD_HAS_PSRAM", - "-mfix-esp32-psram-cache-issue", - "-mfix-esp32-psram-cache-strategy=memw" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "uPesy_esp32_wrover_devkit" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp32-wrover.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "uPesy ESP32 Wrover DevKit", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.upesy.fr/products/upesy-esp32-wrover-devkit-board", - "vendor": "uPesy" -} diff --git a/builder/valtrack_v4_mfw_esp32_c3.json b/builder/valtrack_v4_mfw_esp32_c3.json deleted file mode 100644 index c910f152e..000000000 --- a/builder/valtrack_v4_mfw_esp32_c3.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_VALTRACK_V4_MFW_ESP32_C3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32c3", - "variant": "VALTRACK_V4_MFW_ESP32_C3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Valetron Systems VALTRACK-V4MVF", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.valetron.com/", - "vendor": "Valetron Systems" -} diff --git a/builder/valtrack_v4_vts_esp32_c3.json b/builder/valtrack_v4_vts_esp32_c3.json deleted file mode 100644 index 8197b0bf0..000000000 --- a/builder/valtrack_v4_vts_esp32_c3.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_VALTRACK_V4_VTS_ESP32_C3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" - ], - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32c3", - "variant": "VALTRACK_V4_VTS_ESP32_C3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Valetron Systems VALTRACK-V4VTS", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.valetron.com/", - "vendor": "Valetron Systems" -} diff --git a/builder/vintlabs-devkit-v1.json b/builder/vintlabs-devkit-v1.json deleted file mode 100644 index 4ba1fa16e..000000000 --- a/builder/vintlabs-devkit-v1.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "vintlabsdevkitv1" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "VintLabs ESP32 Devkit", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.vintlabs.com/product/vintlabs-esp32-wroom32-iot-8x2a-pwm-driver-development-kit-4mb-flash-wifi-bluetooth/", - "vendor": "VintLabs" -} diff --git a/builder/watchy.json b/builder/watchy.json deleted file mode 100644 index f91eed072..000000000 --- a/builder/watchy.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld", - "partitions": "huge_app.csv" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_WATCHY", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "watchy" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "SQFMI Watchy v2.0", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://watchy.sqfmi.com/", - "vendor": "SQFMI" -} diff --git a/builder/wemos_d1_mini32.json b/builder/wemos_d1_mini32.json deleted file mode 100644 index 90b1d6b95..000000000 --- a/builder/wemos_d1_mini32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_D1_MINI32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "d1_mini32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS D1 MINI ESP32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.wemos.cc", - "vendor": "WEMOS" -} diff --git a/builder/wemos_d1_uno32.json b/builder/wemos_d1_uno32.json deleted file mode 100644 index 2a38aa423..000000000 --- a/builder/wemos_d1_uno32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_D1_UNO32", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "d1_uno32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WEMOS D1 R32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.wemos.cc", - "vendor": "WEMOS" -} diff --git a/builder/wemosbat.json b/builder/wemosbat.json deleted file mode 100644 index 1312abbb9..000000000 --- a/builder/wemosbat.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_Pocket32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "pocket_32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "WeMos WiFi and Bluetooth Battery", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://www.wemos.cc", - "vendor": "WEMOS" -} diff --git a/builder/wesp32.json b/builder/wesp32.json deleted file mode 100644 index 9f924ba9d..000000000 --- a/builder/wesp32.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_WESP32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "wesp32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Silicognition wESP32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://wesp32.com/", - "vendor": "Silicognition" -} diff --git a/builder/widora-air.json b/builder/widora-air.json deleted file mode 100644 index 4dfda2764..000000000 --- a/builder/widora-air.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_WIDORA_AIR", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "widora-air" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Widora AIR", - "upload": { - "flash_size": "16MB", - "maximum_ram_size": 327680, - "maximum_size": 16777216, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://widora.io", - "vendor": "Widora" -} diff --git a/builder/wifiduino32.json b/builder/wifiduino32.json deleted file mode 100644 index 53ca00942..000000000 --- a/builder/wifiduino32.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_Wifiduino32", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "wifiduino32" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Blinker WiFiduino32", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://diandeng.tech", - "vendor": "Blinker" -} diff --git a/builder/wifiduino32c3.json b/builder/wifiduino32c3.json deleted file mode 100644 index 5b5b61675..000000000 --- a/builder/wifiduino32c3.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32c3_out.ld" - }, - "core": "esp32", - "f_cpu": "160000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "extra_flags": [ - "-DARDUINO_WiFiduinoV2", - "-DARDUINO_USB_MODE=1" - ], - "mcu": "esp32c3", - "variant": "wifiduinov2" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32c3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Blinker WiFiduinoV2 (ESP32-C3)", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://diandeng.tech", - "vendor": "Blinker" -} diff --git a/builder/wifiduino32s3.json b/builder/wifiduino32s3.json deleted file mode 100644 index fa8989469..000000000 --- a/builder/wifiduino32s3.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32s3_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_WiFiduino32S3", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "hwids": [ - [ - "0x303A", - "0x1001" - ] - ], - "mcu": "esp32s3", - "variant": "wifiduino32s3" - }, - "connectivity": [ - "wifi" - ], - "debug": { - "openocd_target": "esp32s3.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Blinker WiFiduino32S3", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 8388608, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://diandeng.tech", - "vendor": "Blinker" -} diff --git a/builder/wipy3.json b/builder/wipy3.json deleted file mode 100644 index b9e5419b1..000000000 --- a/builder/wipy3.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_WIPY3", - "f_cpu": "240000000L", - "f_flash": "40000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "wipy3" - }, - "connectivity": [ - "wifi", - "bluetooth", - "can", - "ethernet" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Pycom WiPy3", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 1310720, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://pycom.io/", - "vendor": "Pycom Ltd." -} diff --git a/builder/wt32-eth01.json b/builder/wt32-eth01.json deleted file mode 100644 index 3fddb34a5..000000000 --- a/builder/wt32-eth01.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "build": { - "arduino": { - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": [ - "-DARDUINO_WT32_ETH01" - ], - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "wt32-eth01" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "Wireless-Tag WT32-ETH01 Ethernet Module", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "http://www.wireless-tag.com/portfolio/wt32-eth01/", - "vendor": "Wireless-Tag" -} diff --git a/builder/xinabox_cw02.json b/builder/xinabox_cw02.json deleted file mode 100644 index 527956b1e..000000000 --- a/builder/xinabox_cw02.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "esp32", - "extra_flags": "-DARDUINO_ESP32_DEV", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "qio", - "mcu": "esp32", - "variant": "xinabox" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino", - "espidf" - ], - "name": "XinaBox CW02", - "upload": { - "flash_size": "4MB", - "maximum_ram_size": 327680, - "maximum_size": 4194304, - "require_upload_port": true, - "speed": 460800 - }, - "url": "https://xinabox.cc/products/cw02", - "vendor": "XinaBox" -} From d20015298e04cc955cf7dbfcf7a5692de0effa46 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 3 Aug 2023 18:02:53 +0200 Subject: [PATCH 401/666] update boards from upstream --- boards/adafruit_feather_esp32_v2.json | 44 +++++++++++++ .../adafruit_feather_esp32s2_reversetft.json | 63 ++++++++++++++++++ boards/adafruit_feather_esp32s2_tft.json | 64 ++++++++++++++++++ boards/adafruit_feather_esp32s3.json | 57 ++++++++++++++++ boards/adafruit_feather_esp32s3_nopsram.json | 65 +++++++++++++++++++ .../adafruit_feather_esp32s3_reversetft.json | 65 +++++++++++++++++++ boards/adafruit_feather_esp32s3_tft.json | 64 ++++++++++++++++++ boards/adafruit_funhouse_esp32s2.json | 55 ++++++++++++++++ boards/adafruit_itsybitsy_esp32.json | 45 +++++++++++++ boards/adafruit_magtag29_esp32s2.json | 55 ++++++++++++++++ boards/adafruit_matrixportal_esp32s3.json | 65 +++++++++++++++++++ boards/adafruit_metro_esp32s2.json | 55 ++++++++++++++++ boards/adafruit_qtpy_esp32.json | 44 +++++++++++++ boards/adafruit_qtpy_esp32c3.json | 44 +++++++++++++ boards/adafruit_qtpy_esp32s2.json | 55 ++++++++++++++++ boards/adafruit_qtpy_esp32s3_nopsram.json | 64 ++++++++++++++++++ boards/airm2m_core_esp32c3.json | 37 +++++++++++ boards/alksesp32.json | 36 ++++++++++ boards/arduino_nano_esp32.json | 53 +++++++++++++++ boards/atmegazero_esp32s2.json | 46 +++++++++++++ boards/az-delivery-devkit-v4.json | 37 +++++++++++ boards/bee_motion.json | 45 +++++++++++++ boards/bee_motion_mini.json | 38 +++++++++++ boards/bee_motion_s3.json | 47 ++++++++++++++ boards/bee_s3.json | 47 ++++++++++++++ boards/bpi-bit.json | 34 ++++++++++ boards/bpi_leaf_s3.json | 48 ++++++++++++++ boards/briki_abc_esp32.json | 41 ++++++++++++ boards/briki_mbc-wb_esp32.json | 41 ++++++++++++ boards/cnrs_aw2eth.json | 36 ++++++++++ boards/connaxio_espoir.json | 47 ++++++++++++++ boards/cytron_maker_feather_aiot_s3.json | 56 ++++++++++++++++ boards/d-duino-32.json | 37 +++++++++++ boards/deneyapkart.json | 42 ++++++++++++ boards/deneyapkart1A.json | 42 ++++++++++++ boards/deneyapkart1Av2.json | 51 +++++++++++++++ boards/deneyapkartg.json | 39 +++++++++++ boards/deneyapmini.json | 45 +++++++++++++ boards/deneyapminiv2.json | 46 +++++++++++++ boards/denky32.json | 39 +++++++++++ boards/denky_d4.json | 37 +++++++++++ boards/dfrobot_beetle_esp32c3.json | 48 ++++++++++++++ boards/dfrobot_firebeetle2_esp32e.json | 39 +++++++++++ boards/dfrobot_firebeetle2_esp32s3.json | 49 ++++++++++++++ boards/dfrobot_romeo_esp32s3.json | 47 ++++++++++++++ boards/dpu_esp32.json | 43 ++++++++++++ boards/edgebox-esp-100.json | 40 ++++++++++++ boards/esp-wrover-kit.json | 52 +++++++++++++++ boards/esp32-c3-devkitc-02.json | 35 ++++++++++ boards/esp32-c3-devkitm-1.json | 35 ++++++++++ boards/esp32-c3-m1i-kit.json | 37 +++++++++++ boards/esp32-devkitlipo.json | 38 +++++++++++ boards/esp32-evb.json | 38 +++++++++++ boards/esp32-gateway.json | 38 +++++++++++ boards/esp32-poe-iso.json | 35 ++++++++++ boards/esp32-poe.json | 35 ++++++++++ boards/esp32-pro.json | 34 ++++++++++ boards/esp32-s2-franzininho.json | 32 +++++++++ boards/esp32-s2-kaluga-1.json | 37 +++++++++++ boards/esp32-s2-saola-1.json | 34 ++++++++++ boards/esp32-s3-devkitc-1.json | 50 ++++++++++++++ boards/esp320.json | 34 ++++++++++ boards/esp32cam.json | 38 +++++++++++ boards/esp32dev.json | 37 +++++++++++ boards/esp32doit-devkit-v1.json | 37 +++++++++++ boards/esp32doit-espduino.json | 37 +++++++++++ boards/esp32s3box.json | 47 ++++++++++++++ boards/esp32s3camlcd.json | 49 ++++++++++++++ boards/esp32thing.json | 37 +++++++++++ boards/esp32thing_plus.json | 38 +++++++++++ boards/esp32vn-iot-uno.json | 37 +++++++++++ boards/espea32.json | 34 ++++++++++ boards/espectro32.json | 37 +++++++++++ boards/espino32.json | 37 +++++++++++ boards/etboard.json | 34 ++++++++++ boards/featheresp32-s2.json | 62 ++++++++++++++++++ boards/featheresp32.json | 37 +++++++++++ boards/firebeetle32.json | 35 ++++++++++ boards/fm-devkit.json | 37 +++++++++++ boards/franzininho_wifi_esp32s2.json | 45 +++++++++++++ boards/franzininho_wifi_msc_esp32s2.json | 47 ++++++++++++++ boards/frogboard.json | 37 +++++++++++ boards/healthypi4.json | 34 ++++++++++ boards/heltec_wifi_kit_32.json | 34 ++++++++++ boards/heltec_wifi_kit_32_V3.json | 47 ++++++++++++++ boards/heltec_wifi_kit_32_v2.json | 35 ++++++++++ boards/heltec_wifi_lora_32.json | 37 +++++++++++ boards/heltec_wifi_lora_32_V2.json | 38 +++++++++++ boards/heltec_wifi_lora_32_V3.json | 48 ++++++++++++++ boards/heltec_wireless_stick.json | 38 +++++++++++ boards/heltec_wireless_stick_lite.json | 34 ++++++++++ boards/honeylemon.json | 37 +++++++++++ boards/hornbill32dev.json | 37 +++++++++++ boards/hornbill32minima.json | 37 +++++++++++ boards/imbrios-logsens-v1p1.json | 34 ++++++++++ boards/inex_openkb.json | 34 ++++++++++ boards/intorobot.json | 34 ++++++++++ boards/iotaap_magnolia.json | 36 ++++++++++ boards/iotbusio.json | 39 +++++++++++ boards/iotbusproteus.json | 39 +++++++++++ boards/kb32-ft.json | 42 ++++++++++++ boards/kits-edu.json | 34 ++++++++++ boards/labplus_mpython.json | 35 ++++++++++ boards/lilygo-t-display-s3.json | 48 ++++++++++++++ boards/lionbit.json | 45 +++++++++++++ boards/lolin32.json | 37 +++++++++++ boards/lolin32_lite.json | 34 ++++++++++ boards/lolin_c3_mini.json | 44 +++++++++++++ boards/lolin_d32.json | 37 +++++++++++ boards/lolin_d32_pro.json | 37 +++++++++++ boards/lolin_s2_mini.json | 46 +++++++++++++ boards/lolin_s2_pico.json | 46 +++++++++++++ boards/lolin_s3.json | 49 ++++++++++++++ boards/lolin_s3_mini.json | 46 +++++++++++++ boards/lopy.json | 37 +++++++++++ boards/lopy4.json | 37 +++++++++++ boards/m5stack-atom.json | 34 ++++++++++ boards/m5stack-atoms3.json | 46 +++++++++++++ boards/m5stack-core-esp32.json | 34 ++++++++++ boards/m5stack-core2.json | 35 ++++++++++ boards/m5stack-coreink.json | 34 ++++++++++ boards/m5stack-cores3.json | 46 +++++++++++++ boards/m5stack-fire.json | 40 ++++++++++++ boards/m5stack-grey.json | 34 ++++++++++ boards/m5stack-stamps3.json | 46 +++++++++++++ boards/m5stack-station.json | 34 ++++++++++ boards/m5stack-timer-cam.json | 39 +++++++++++ boards/m5stamp-pico.json | 34 ++++++++++ boards/m5stick-c.json | 34 ++++++++++ boards/magicbit.json | 34 ++++++++++ boards/mgbot-iotik32a.json | 34 ++++++++++ boards/mgbot-iotik32b.json | 34 ++++++++++ boards/mhetesp32devkit.json | 37 +++++++++++ boards/mhetesp32minikit.json | 37 +++++++++++ boards/microduino-core-esp32.json | 34 ++++++++++ boards/micros2.json | 48 ++++++++++++++ boards/minimain_esp32s2.json | 50 ++++++++++++++ boards/nano32.json | 34 ++++++++++ boards/nebulas3.json | 47 ++++++++++++++ boards/nina_w10.json | 35 ++++++++++ boards/node32s.json | 37 +++++++++++ boards/nodemcu-32s.json | 37 +++++++++++ boards/nodemcu-32s2.json | 34 ++++++++++ boards/nscreen-32.json | 40 ++++++++++++ boards/odroid_esp32.json | 34 ++++++++++ boards/onehorse32dev.json | 34 ++++++++++ boards/oroca_edubot.json | 35 ++++++++++ boards/pico32.json | 37 +++++++++++ boards/piranha_esp32.json | 34 ++++++++++ boards/pocket_32.json | 37 +++++++++++ boards/pycom_gpy.json | 34 ++++++++++ boards/qchip.json | 34 ++++++++++ boards/quantum.json | 34 ++++++++++ boards/redpill_esp32s3.json | 55 ++++++++++++++++ boards/roboheart_hercules.json | 39 +++++++++++ boards/s_odi_ultra.json | 34 ++++++++++ boards/seeed_xiao_esp32c3.json | 48 ++++++++++++++ boards/seeed_xiao_esp32s3.json | 53 +++++++++++++++ boards/sensesiot_weizen.json | 37 +++++++++++ boards/sg-o_airMon.json | 40 ++++++++++++ boards/sparkfun_esp32_iot_redboard.json | 41 ++++++++++++ boards/sparkfun_esp32micromod.json | 34 ++++++++++ boards/sparkfun_esp32s2_thing_plus.json | 42 ++++++++++++ boards/sparkfun_esp32s2_thing_plus_c.json | 38 +++++++++++ boards/sparkfun_lora_gateway_1-channel.json | 37 +++++++++++ boards/tamc_termod_s3.json | 48 ++++++++++++++ boards/tinypico.json | 39 +++++++++++ boards/trueverit-iot-driver-mk2.json | 37 +++++++++++ boards/trueverit-iot-driver-mk3.json | 38 +++++++++++ boards/trueverit-iot-driver.json | 37 +++++++++++ boards/ttgo-lora32-v1.json | 37 +++++++++++ boards/ttgo-lora32-v2.json | 37 +++++++++++ boards/ttgo-lora32-v21.json | 37 +++++++++++ boards/ttgo-t-beam.json | 37 +++++++++++ boards/ttgo-t-oi-plus.json | 34 ++++++++++ boards/ttgo-t-watch.json | 40 ++++++++++++ boards/ttgo-t1.json | 37 +++++++++++ boards/ttgo-t7-v13-mini32.json | 34 ++++++++++ boards/ttgo-t7-v14-mini32.json | 37 +++++++++++ boards/turta_iot_node.json | 34 ++++++++++ boards/um_feathers2.json | 46 +++++++++++++ boards/um_feathers2_neo.json | 46 +++++++++++++ boards/um_feathers3.json | 50 ++++++++++++++ boards/um_pros3.json | 50 ++++++++++++++ boards/um_rmp.json | 46 +++++++++++++ boards/um_tinys2.json | 46 +++++++++++++ boards/um_tinys3.json | 50 ++++++++++++++ boards/unphone7.json | 40 ++++++++++++ boards/unphone8.json | 44 +++++++++++++ boards/unphone9.json | 50 ++++++++++++++ boards/upesy_wroom.json | 37 +++++++++++ boards/upesy_wrover.json | 42 ++++++++++++ boards/valtrack_v4_mfw_esp32_c3.json | 44 +++++++++++++ boards/valtrack_v4_vts_esp32_c3.json | 44 +++++++++++++ boards/vintlabs-devkit-v1.json | 37 +++++++++++ boards/watchy.json | 38 +++++++++++ boards/wemos_d1_mini32.json | 37 +++++++++++ boards/wemos_d1_uno32.json | 37 +++++++++++ boards/wemosbat.json | 37 +++++++++++ boards/wesp32.json | 37 +++++++++++ boards/widora-air.json | 34 ++++++++++ boards/wifiduino32.json | 34 ++++++++++ boards/wifiduino32c3.json | 37 +++++++++++ boards/wifiduino32s3.json | 45 +++++++++++++ boards/wipy3.json | 37 +++++++++++ boards/wt32-eth01.json | 39 +++++++++++ boards/xinabox_cw02.json | 37 +++++++++++ 207 files changed, 8483 insertions(+) create mode 100644 boards/adafruit_feather_esp32_v2.json create mode 100644 boards/adafruit_feather_esp32s2_reversetft.json create mode 100644 boards/adafruit_feather_esp32s2_tft.json create mode 100644 boards/adafruit_feather_esp32s3.json create mode 100644 boards/adafruit_feather_esp32s3_nopsram.json create mode 100644 boards/adafruit_feather_esp32s3_reversetft.json create mode 100644 boards/adafruit_feather_esp32s3_tft.json create mode 100644 boards/adafruit_funhouse_esp32s2.json create mode 100644 boards/adafruit_itsybitsy_esp32.json create mode 100644 boards/adafruit_magtag29_esp32s2.json create mode 100644 boards/adafruit_matrixportal_esp32s3.json create mode 100644 boards/adafruit_metro_esp32s2.json create mode 100644 boards/adafruit_qtpy_esp32.json create mode 100644 boards/adafruit_qtpy_esp32c3.json create mode 100644 boards/adafruit_qtpy_esp32s2.json create mode 100644 boards/adafruit_qtpy_esp32s3_nopsram.json create mode 100644 boards/airm2m_core_esp32c3.json create mode 100644 boards/alksesp32.json create mode 100644 boards/arduino_nano_esp32.json create mode 100644 boards/atmegazero_esp32s2.json create mode 100644 boards/az-delivery-devkit-v4.json create mode 100644 boards/bee_motion.json create mode 100644 boards/bee_motion_mini.json create mode 100644 boards/bee_motion_s3.json create mode 100644 boards/bee_s3.json create mode 100644 boards/bpi-bit.json create mode 100644 boards/bpi_leaf_s3.json create mode 100644 boards/briki_abc_esp32.json create mode 100644 boards/briki_mbc-wb_esp32.json create mode 100644 boards/cnrs_aw2eth.json create mode 100644 boards/connaxio_espoir.json create mode 100644 boards/cytron_maker_feather_aiot_s3.json create mode 100644 boards/d-duino-32.json create mode 100644 boards/deneyapkart.json create mode 100644 boards/deneyapkart1A.json create mode 100644 boards/deneyapkart1Av2.json create mode 100644 boards/deneyapkartg.json create mode 100644 boards/deneyapmini.json create mode 100644 boards/deneyapminiv2.json create mode 100644 boards/denky32.json create mode 100644 boards/denky_d4.json create mode 100644 boards/dfrobot_beetle_esp32c3.json create mode 100644 boards/dfrobot_firebeetle2_esp32e.json create mode 100644 boards/dfrobot_firebeetle2_esp32s3.json create mode 100644 boards/dfrobot_romeo_esp32s3.json create mode 100644 boards/dpu_esp32.json create mode 100644 boards/edgebox-esp-100.json create mode 100644 boards/esp-wrover-kit.json create mode 100644 boards/esp32-c3-devkitc-02.json create mode 100644 boards/esp32-c3-devkitm-1.json create mode 100644 boards/esp32-c3-m1i-kit.json create mode 100644 boards/esp32-devkitlipo.json create mode 100644 boards/esp32-evb.json create mode 100644 boards/esp32-gateway.json create mode 100644 boards/esp32-poe-iso.json create mode 100644 boards/esp32-poe.json create mode 100644 boards/esp32-pro.json create mode 100644 boards/esp32-s2-franzininho.json create mode 100644 boards/esp32-s2-kaluga-1.json create mode 100644 boards/esp32-s2-saola-1.json create mode 100644 boards/esp32-s3-devkitc-1.json create mode 100644 boards/esp320.json create mode 100644 boards/esp32cam.json create mode 100644 boards/esp32dev.json create mode 100644 boards/esp32doit-devkit-v1.json create mode 100644 boards/esp32doit-espduino.json create mode 100644 boards/esp32s3box.json create mode 100644 boards/esp32s3camlcd.json create mode 100644 boards/esp32thing.json create mode 100644 boards/esp32thing_plus.json create mode 100644 boards/esp32vn-iot-uno.json create mode 100644 boards/espea32.json create mode 100644 boards/espectro32.json create mode 100644 boards/espino32.json create mode 100644 boards/etboard.json create mode 100644 boards/featheresp32-s2.json create mode 100644 boards/featheresp32.json create mode 100644 boards/firebeetle32.json create mode 100644 boards/fm-devkit.json create mode 100644 boards/franzininho_wifi_esp32s2.json create mode 100644 boards/franzininho_wifi_msc_esp32s2.json create mode 100644 boards/frogboard.json create mode 100644 boards/healthypi4.json create mode 100644 boards/heltec_wifi_kit_32.json create mode 100644 boards/heltec_wifi_kit_32_V3.json create mode 100644 boards/heltec_wifi_kit_32_v2.json create mode 100644 boards/heltec_wifi_lora_32.json create mode 100644 boards/heltec_wifi_lora_32_V2.json create mode 100644 boards/heltec_wifi_lora_32_V3.json create mode 100644 boards/heltec_wireless_stick.json create mode 100644 boards/heltec_wireless_stick_lite.json create mode 100644 boards/honeylemon.json create mode 100644 boards/hornbill32dev.json create mode 100644 boards/hornbill32minima.json create mode 100644 boards/imbrios-logsens-v1p1.json create mode 100644 boards/inex_openkb.json create mode 100644 boards/intorobot.json create mode 100644 boards/iotaap_magnolia.json create mode 100644 boards/iotbusio.json create mode 100644 boards/iotbusproteus.json create mode 100644 boards/kb32-ft.json create mode 100644 boards/kits-edu.json create mode 100644 boards/labplus_mpython.json create mode 100644 boards/lilygo-t-display-s3.json create mode 100644 boards/lionbit.json create mode 100644 boards/lolin32.json create mode 100644 boards/lolin32_lite.json create mode 100644 boards/lolin_c3_mini.json create mode 100644 boards/lolin_d32.json create mode 100644 boards/lolin_d32_pro.json create mode 100644 boards/lolin_s2_mini.json create mode 100644 boards/lolin_s2_pico.json create mode 100644 boards/lolin_s3.json create mode 100644 boards/lolin_s3_mini.json create mode 100644 boards/lopy.json create mode 100644 boards/lopy4.json create mode 100644 boards/m5stack-atom.json create mode 100644 boards/m5stack-atoms3.json create mode 100644 boards/m5stack-core-esp32.json create mode 100644 boards/m5stack-core2.json create mode 100644 boards/m5stack-coreink.json create mode 100644 boards/m5stack-cores3.json create mode 100644 boards/m5stack-fire.json create mode 100644 boards/m5stack-grey.json create mode 100644 boards/m5stack-stamps3.json create mode 100644 boards/m5stack-station.json create mode 100644 boards/m5stack-timer-cam.json create mode 100644 boards/m5stamp-pico.json create mode 100644 boards/m5stick-c.json create mode 100644 boards/magicbit.json create mode 100644 boards/mgbot-iotik32a.json create mode 100644 boards/mgbot-iotik32b.json create mode 100644 boards/mhetesp32devkit.json create mode 100644 boards/mhetesp32minikit.json create mode 100644 boards/microduino-core-esp32.json create mode 100644 boards/micros2.json create mode 100644 boards/minimain_esp32s2.json create mode 100644 boards/nano32.json create mode 100644 boards/nebulas3.json create mode 100644 boards/nina_w10.json create mode 100644 boards/node32s.json create mode 100644 boards/nodemcu-32s.json create mode 100644 boards/nodemcu-32s2.json create mode 100644 boards/nscreen-32.json create mode 100644 boards/odroid_esp32.json create mode 100644 boards/onehorse32dev.json create mode 100644 boards/oroca_edubot.json create mode 100644 boards/pico32.json create mode 100644 boards/piranha_esp32.json create mode 100644 boards/pocket_32.json create mode 100644 boards/pycom_gpy.json create mode 100644 boards/qchip.json create mode 100644 boards/quantum.json create mode 100644 boards/redpill_esp32s3.json create mode 100644 boards/roboheart_hercules.json create mode 100644 boards/s_odi_ultra.json create mode 100644 boards/seeed_xiao_esp32c3.json create mode 100644 boards/seeed_xiao_esp32s3.json create mode 100644 boards/sensesiot_weizen.json create mode 100644 boards/sg-o_airMon.json create mode 100644 boards/sparkfun_esp32_iot_redboard.json create mode 100644 boards/sparkfun_esp32micromod.json create mode 100644 boards/sparkfun_esp32s2_thing_plus.json create mode 100644 boards/sparkfun_esp32s2_thing_plus_c.json create mode 100644 boards/sparkfun_lora_gateway_1-channel.json create mode 100644 boards/tamc_termod_s3.json create mode 100644 boards/tinypico.json create mode 100644 boards/trueverit-iot-driver-mk2.json create mode 100644 boards/trueverit-iot-driver-mk3.json create mode 100644 boards/trueverit-iot-driver.json create mode 100644 boards/ttgo-lora32-v1.json create mode 100644 boards/ttgo-lora32-v2.json create mode 100644 boards/ttgo-lora32-v21.json create mode 100644 boards/ttgo-t-beam.json create mode 100644 boards/ttgo-t-oi-plus.json create mode 100644 boards/ttgo-t-watch.json create mode 100644 boards/ttgo-t1.json create mode 100644 boards/ttgo-t7-v13-mini32.json create mode 100644 boards/ttgo-t7-v14-mini32.json create mode 100644 boards/turta_iot_node.json create mode 100644 boards/um_feathers2.json create mode 100644 boards/um_feathers2_neo.json create mode 100644 boards/um_feathers3.json create mode 100644 boards/um_pros3.json create mode 100644 boards/um_rmp.json create mode 100644 boards/um_tinys2.json create mode 100644 boards/um_tinys3.json create mode 100644 boards/unphone7.json create mode 100644 boards/unphone8.json create mode 100644 boards/unphone9.json create mode 100644 boards/upesy_wroom.json create mode 100644 boards/upesy_wrover.json create mode 100644 boards/valtrack_v4_mfw_esp32_c3.json create mode 100644 boards/valtrack_v4_vts_esp32_c3.json create mode 100644 boards/vintlabs-devkit-v1.json create mode 100644 boards/watchy.json create mode 100644 boards/wemos_d1_mini32.json create mode 100644 boards/wemos_d1_uno32.json create mode 100644 boards/wemosbat.json create mode 100644 boards/wesp32.json create mode 100644 boards/widora-air.json create mode 100644 boards/wifiduino32.json create mode 100644 boards/wifiduino32c3.json create mode 100644 boards/wifiduino32s3.json create mode 100644 boards/wipy3.json create mode 100644 boards/wt32-eth01.json create mode 100644 boards/xinabox_cw02.json diff --git a/boards/adafruit_feather_esp32_v2.json b/boards/adafruit_feather_esp32_v2.json new file mode 100644 index 000000000..9414b995c --- /dev/null +++ b/boards/adafruit_feather_esp32_v2.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32_V2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "adafruit_feather_esp32_v2" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32 V2", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5400", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s2_reversetft.json b/boards/adafruit_feather_esp32s2_reversetft.json new file mode 100644 index 000000000..bd1f3ca8c --- /dev/null +++ b/boards/adafruit_feather_esp32s2_reversetft.json @@ -0,0 +1,63 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_REVTFT", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80ED" + ], + [ + "0x239A", + "0x00ED" + ], + [ + "0x239A", + "0x80EE" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_feather_esp32s2_reversetft" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S2 Reverse TFT", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2_reversetft/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5345", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s2_tft.json b/boards/adafruit_feather_esp32s2_tft.json new file mode 100644 index 000000000..e1e948144 --- /dev/null +++ b/boards/adafruit_feather_esp32s2_tft.json @@ -0,0 +1,64 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x810F" + ], + [ + "0x239A", + "0x010F" + ], + [ + "0x239A", + "0x8110" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_feather_esp32s2_tft" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S2 TFT", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2_tft/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5300", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json new file mode 100644 index 000000000..5796b0559 --- /dev/null +++ b/boards/adafruit_feather_esp32s3.json @@ -0,0 +1,57 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x811B" + ], + [ + "0x239A", + "0x011B" + ], + [ + "0x239A", + "0x811C" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S3 2MB PSRAM", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5477", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3_nopsram.json b/boards/adafruit_feather_esp32s3_nopsram.json new file mode 100644 index 000000000..79ee24d1d --- /dev/null +++ b/boards/adafruit_feather_esp32s3_nopsram.json @@ -0,0 +1,65 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-8MB-tinyuf2.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x811B" + ], + [ + "0x239A", + "0x011B" + ], + [ + "0x239A", + "0x811C" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3_nopsram" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S3 No PSRAM", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s3_nopsram/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5323", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3_reversetft.json b/boards/adafruit_feather_esp32s3_reversetft.json new file mode 100644 index 000000000..fc3b8bc36 --- /dev/null +++ b/boards/adafruit_feather_esp32s3_reversetft.json @@ -0,0 +1,65 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_REVTFT", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8123" + ], + [ + "0x239A", + "0x0123" + ], + [ + "0x239A", + "0x8124" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3_reversetft" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S3 Reverse TFT", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s3_reversetft/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5691", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3_tft.json b/boards/adafruit_feather_esp32s3_tft.json new file mode 100644 index 000000000..dbf7612bd --- /dev/null +++ b/boards/adafruit_feather_esp32s3_tft.json @@ -0,0 +1,64 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x811D" + ], + [ + "0x239A", + "0x011D" + ], + [ + "0x239A", + "0x811E" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_feather_esp32s3_tft" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Feather ESP32-S3 TFT", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s3_tft/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5483", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_funhouse_esp32s2.json b/boards/adafruit_funhouse_esp32s2.json new file mode 100644 index 000000000..eb5ee1d52 --- /dev/null +++ b/boards/adafruit_funhouse_esp32s2.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FUNHOUSE_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80F9" + ], + [ + "0x239A", + "0x00F9" + ], + [ + "0x239A", + "0x80FA" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_funhouse_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit FunHouse", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4985", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_itsybitsy_esp32.json b/boards/adafruit_itsybitsy_esp32.json new file mode 100644 index 000000000..dd87bfccc --- /dev/null +++ b/boards/adafruit_itsybitsy_esp32.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_ITSYBITSY_ESP32", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "adafruit_itsybitsy_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit ItsyBitsy ESP32", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4363", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_magtag29_esp32s2.json b/boards/adafruit_magtag29_esp32s2.json new file mode 100644 index 000000000..fc51f6101 --- /dev/null +++ b/boards/adafruit_magtag29_esp32s2.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_MAGTAG29_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80E5" + ], + [ + "0x239A", + "0x00E5" + ], + [ + "0x239A", + "0x80E6" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_magtag29_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit MagTag 2.9", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4800", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_matrixportal_esp32s3.json b/boards/adafruit_matrixportal_esp32s3.json new file mode 100644 index 000000000..3446cd217 --- /dev/null +++ b/boards/adafruit_matrixportal_esp32s3.json @@ -0,0 +1,65 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-8MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8125" + ], + [ + "0x239A", + "0x0125" + ], + [ + "0x239A", + "0x8126" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_matrixportal_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit MatrixPortal ESP32-S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_matrixportal_esp32s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5778", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_metro_esp32s2.json b/boards/adafruit_metro_esp32s2.json new file mode 100644 index 000000000..7f75dfbe4 --- /dev/null +++ b/boards/adafruit_metro_esp32s2.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_METRO_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80DF" + ], + [ + "0x239A", + "0x00DF" + ], + [ + "0x239A", + "0x80E0" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_metro_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Metro ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4775", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32.json b/boards/adafruit_qtpy_esp32.json new file mode 100644 index 000000000..d2371f7e3 --- /dev/null +++ b/boards/adafruit_qtpy_esp32.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32_PICO", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "adafruit_qtpy_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5395", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32c3.json b/boards/adafruit_qtpy_esp32c3.json new file mode 100644 index 000000000..7c870e019 --- /dev/null +++ b/boards/adafruit_qtpy_esp32c3.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32C3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "adafruit_qtpy_esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5405", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32s2.json b/boards/adafruit_qtpy_esp32s2.json new file mode 100644 index 000000000..51beac63e --- /dev/null +++ b/boards/adafruit_qtpy_esp32s2.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32S2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8111" + ], + [ + "0x239A", + "0x0111" + ], + [ + "0x239A", + "0x8112" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_qtpy_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5325", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32s3_nopsram.json b/boards/adafruit_qtpy_esp32s3_nopsram.json new file mode 100644 index 000000000..15589da92 --- /dev/null +++ b/boards/adafruit_qtpy_esp32s3_nopsram.json @@ -0,0 +1,64 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-8MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8119" + ], + [ + "0x239A", + "0x0119" + ], + [ + "0x239A", + "0x811A" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_qtpy_esp32s3_nopsram" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit QT Py ESP32-S3 No PSRAM", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_qtpy_esp32s3_nopsram/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5426", + "vendor": "Adafruit" +} diff --git a/boards/airm2m_core_esp32c3.json b/boards/airm2m_core_esp32c3.json new file mode 100644 index 000000000..e227fadd8 --- /dev/null +++ b/boards/airm2m_core_esp32c3.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "extra_flags": [ + "-DARDUINO_AirM2M_CORE_ESP32C3", + "-DARDUINO_USB_MODE=1" + ], + "mcu": "esp32c3", + "variant": "AirM2M_CORE_ESP32C3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "AirM2M CORE ESP32C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.luatos.com/chips/esp32c3/board.html", + "vendor": "AirM2M" +} diff --git a/boards/alksesp32.json b/boards/alksesp32.json new file mode 100644 index 000000000..d94ec71fa --- /dev/null +++ b/boards/alksesp32.json @@ -0,0 +1,36 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ALKS", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "alksesp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "ALKS ESP32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/RoboticsBrno/ArduinoLearningKitStarter.git", + "vendor": "RoboticsBrno" +} diff --git a/boards/arduino_nano_esp32.json b/boards/arduino_nano_esp32.json new file mode 100644 index 000000000..c6da4e227 --- /dev/null +++ b/boards/arduino_nano_esp32.json @@ -0,0 +1,53 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "app3M_fat9M_fact512k_16MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_NANO_ESP32", + "-DBOARD_HAS_PIN_REMAP", + "-DBOARD_HAS_PSRAM", + "-DUSB_MANUFACTURER=\\\"Arduino\\\"", + "-DUSB_PRODUCT=\\\"NanoESP32\\\"", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_DFU_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x2341", + "0x0070" + ] + ], + "mcu": "esp32s3", + "variant": "arduino_nano_nora" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Arduino Nano ESP32", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800, + "protocol": "dfu" + }, + "url": "https://docs.arduino.cc/hardware/nano-esp32", + "vendor": "Arduino" +} diff --git a/boards/atmegazero_esp32s2.json b/boards/atmegazero_esp32s2.json new file mode 100644 index 000000000..a23a6ce9d --- /dev/null +++ b/boards/atmegazero_esp32s2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-16MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_atmegazero_esp32s2", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x800A" + ] + ], + "mcu": "esp32s2", + "variant": "atmegazero_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "EspinalLab ATMegaZero ESP32-S2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://shop.atmegazero.com/", + "vendor": "EspinalLab" +} diff --git a/boards/az-delivery-devkit-v4.json b/boards/az-delivery-devkit-v4.json new file mode 100644 index 000000000..93237d723 --- /dev/null +++ b/boards/az-delivery-devkit-v4.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "AZ-Delivery ESP-32 Dev Kit C V4", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 532480, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.az-delivery.com/products/esp-32-dev-kit-c-v4", + "vendor": "AZ-Delivery" +} diff --git a/boards/bee_motion.json b/boards/bee_motion.json new file mode 100644 index 000000000..c8577902b --- /dev/null +++ b/boards/bee_motion.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_Bee_Motion", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x810D" + ] + ], + "mcu": "esp32s2", + "variant": "Bee_Motion" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Smart Bee Motion", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/strid3r21/Bee-Motion", + "vendor": "Smart Bee" +} diff --git a/boards/bee_motion_mini.json b/boards/bee_motion_mini.json new file mode 100644 index 000000000..d24163ec8 --- /dev/null +++ b/boards/bee_motion_mini.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": [ + "-DARDUINO_Bee_Motion_Mini", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "mcu": "esp32c3", + "variant": "Bee_Motion_Mini" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Smart Bee Motion Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/strid3r21/BeeMotionMini", + "vendor": "Smart Bee" +} diff --git a/boards/bee_motion_s3.json b/boards/bee_motion_s3.json new file mode 100644 index 000000000..c620b80c3 --- /dev/null +++ b/boards/bee_motion_s3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_BeeMotionS3", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8113" + ] + ], + "mcu": "esp32s3", + "variant": "Bee_Motion_S3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Smart Bee Motion S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/strid3r21/BeeMotionS3/", + "vendor": "Smart Bee" +} diff --git a/boards/bee_s3.json b/boards/bee_s3.json new file mode 100644 index 000000000..16e47ee79 --- /dev/null +++ b/boards/bee_s3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_Bee_S3", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8110" + ] + ], + "mcu": "esp32s3", + "variant": "Bee_S3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Smart Bee S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/strid3r21/BeeS3", + "vendor": "Smart Bee" +} diff --git a/boards/bpi-bit.json b/boards/bpi-bit.json new file mode 100644 index 000000000..ec5c0dc73 --- /dev/null +++ b/boards/bpi-bit.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_BPI_BIT", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "bpi-bit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "BPI-Bit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "BPI Tech" +} diff --git a/boards/bpi_leaf_s3.json b/boards/bpi_leaf_s3.json new file mode 100644 index 000000000..c1d8a154c --- /dev/null +++ b/boards/bpi_leaf_s3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_BPI_LEAF_S3", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80DF" + ] + ], + "mcu": "esp32s3", + "variant": "bpi_leaf_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "BPI-Leaf-S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.banana-pi.org/BPI-Leaf-S3", + "vendor": "BPI Tech" +} diff --git a/boards/briki_abc_esp32.json b/boards/briki_abc_esp32.json new file mode 100644 index 000000000..429514895 --- /dev/null +++ b/boards/briki_abc_esp32.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "mbcwb", + "extra_flags": "-DBRIKI_MBC_WB_ESP -DBRIKI_ABC -w", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "briki_mbcwb_esp32", + "partitions": "8MB_ffat.csv" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "Briki ABC (MBC-WB) - ESP32", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 3407872, + "protocol": "mbctool", + "protocols": [ + "mbctool" + ], + "require_upload_port": true, + "speed": 1500000 + }, + "url": "https://briki.org", + "vendor": "meteca" +} diff --git a/boards/briki_mbc-wb_esp32.json b/boards/briki_mbc-wb_esp32.json new file mode 100644 index 000000000..df5c3756a --- /dev/null +++ b/boards/briki_mbc-wb_esp32.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "mbcwb", + "extra_flags": "-DBRIKI_MBC_WB_ESP -DBRIKI_MBC_WB -w", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "briki_mbcwb_esp32", + "partitions": "8MB_ffat.csv" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "Briki MBC-WB - ESP32", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 3407872, + "protocol": "mbctool", + "protocols": [ + "mbctool" + ], + "require_upload_port": true, + "speed": 1500000 + }, + "url": "https://briki.org", + "vendor": "meteca" +} diff --git a/boards/cnrs_aw2eth.json b/boards/cnrs_aw2eth.json new file mode 100644 index 000000000..3669347a4 --- /dev/null +++ b/boards/cnrs_aw2eth.json @@ -0,0 +1,36 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_PICO" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "cnrs_aw2eth" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "CNRS AW2ETH", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "CNRS" +} diff --git a/boards/connaxio_espoir.json b/boards/connaxio_espoir.json new file mode 100644 index 000000000..e9e7265bf --- /dev/null +++ b/boards/connaxio_espoir.json @@ -0,0 +1,47 @@ + +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_CONNAXIO_ESPOIR", + "-DCONFIG_FREERTOS_UNICORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "connaxio_espoir", + "hwids": [ + [ + "0x10C4", + "0x8D9A" + ] + ] + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-solo-1.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Connaxio's Espoir", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.connaxio.com/electronics/espoir/", + "vendor": "Connaxio" +} diff --git a/boards/cytron_maker_feather_aiot_s3.json b/boards/cytron_maker_feather_aiot_s3.json new file mode 100644 index 000000000..4b7a2704c --- /dev/null +++ b/boards/cytron_maker_feather_aiot_s3.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "partitions-8MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_CYTRON_MAKER_FEATHER_AIOT_S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80F8" + ] + ], + "mcu": "esp32s3", + "variant": "cytron_maker_feather_aiot_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Cytron Maker Feather AIoT S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/cytron_maker_feather_aiot_s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://sg.cytron.io/c-development-tools/c-maker-series/p-v-maker-feather-aiot-s3-simplifying-aiot-with-esp32", + "vendor": "Cytron Technologies" +} diff --git a/boards/d-duino-32.json b/boards/d-duino-32.json new file mode 100644 index 000000000..e4d92e3df --- /dev/null +++ b/boards/d-duino-32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_D_DUINO_32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "d-duino-32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "D-duino-32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.tindie.com/products/lspoplove/dstike-d-duino-32-v3/", + "vendor": "DSTIKE" +} diff --git a/boards/deneyapkart.json b/boards/deneyapkart.json new file mode 100644 index 000000000..7d499bd4b --- /dev/null +++ b/boards/deneyapkart.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYDK", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "deneyapkart" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart", + "vendor": "T3 Foundation" +} diff --git a/boards/deneyapkart1A.json b/boards/deneyapkart1A.json new file mode 100644 index 000000000..46f513fac --- /dev/null +++ b/boards/deneyapkart1A.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYDK1A", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "deneyapkart1A" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart 1A", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart-1a", + "vendor": "T3 Foundation" +} diff --git a/boards/deneyapkart1Av2.json b/boards/deneyapkart1Av2.json new file mode 100644 index 000000000..e57a00846 --- /dev/null +++ b/boards/deneyapkart1Av2.json @@ -0,0 +1,51 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYDK1Av2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8147" + ] + ], + "mcu": "esp32s3", + "variant": "deneyapkart1Av2" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart 1A v2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart-1a-v2-type-c", + "vendor": "T3 Foundation" +} diff --git a/boards/deneyapkartg.json b/boards/deneyapkartg.json new file mode 100644 index 000000000..19f1b0415 --- /dev/null +++ b/boards/deneyapkartg.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYG", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c3", + "variant": "deneyapkartg" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Kart G", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-kart-g-type-c", + "vendor": "T3 Foundation" +} diff --git a/boards/deneyapmini.json b/boards/deneyapmini.json new file mode 100644 index 000000000..5a358cdb5 --- /dev/null +++ b/boards/deneyapmini.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8141" + ] + ], + "mcu": "esp32s2", + "variant": "deneyapmini" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-mini", + "vendor": "T3 Foundation" +} diff --git a/boards/deneyapminiv2.json b/boards/deneyapminiv2.json new file mode 100644 index 000000000..42058a81b --- /dev/null +++ b/boards/deneyapminiv2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DYMv2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8144" + ] + ], + "mcu": "esp32s2", + "variant": "deneyapminiv2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deneyap Mini v2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://magaza.deneyapkart.org/tr/product/detail/deneyap-mini-v2-type-c", + "vendor": "T3 Foundation" +} diff --git a/boards/denky32.json b/boards/denky32.json new file mode 100644 index 000000000..3b2c40762 --- /dev/null +++ b/boards/denky32.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DENKY_WROOM32", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ch_denky" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Denky32 (WROOM32)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Denky" +} diff --git a/boards/denky_d4.json b/boards/denky_d4.json new file mode 100644 index 000000000..7846bf1d8 --- /dev/null +++ b/boards/denky_d4.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DENKY_PICOV3", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "ch_denky" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Denky D4 (PICO-V3-02)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 2000000 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Denky" +} diff --git a/boards/dfrobot_beetle_esp32c3.json b/boards/dfrobot_beetle_esp32c3.json new file mode 100644 index 000000000..ab0b4c92c --- /dev/null +++ b/boards/dfrobot_beetle_esp32c3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32C3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x3343", + "0x8364" + ], + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "dfrobot_beetle_esp32c3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DFRobot Beetle ESP32-C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.dfrobot.com/product-2566.html", + "vendor": "DFRobot" +} diff --git a/boards/dfrobot_firebeetle2_esp32e.json b/boards/dfrobot_firebeetle2_esp32e.json new file mode 100644 index 000000000..0d3790cf1 --- /dev/null +++ b/boards/dfrobot_firebeetle2_esp32e.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DFROBOT_FIREBEETLE_2_ESP32E", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "dfrobot_firebeetle2_esp32e" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DFRobot Firebeetle 2 ESP32-E", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.dfrobot.com/FireBeetle_Board_ESP32_E_SKU_DFR0654", + "vendor": "DFRobot" +} diff --git a/boards/dfrobot_firebeetle2_esp32s3.json b/boards/dfrobot_firebeetle2_esp32s3.json new file mode 100644 index 000000000..0f87150d6 --- /dev/null +++ b/boards/dfrobot_firebeetle2_esp32s3.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x83CF" + ], + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "dfrobot_firebeetle2_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DFRobot Firebeetle 2 ESP32-S3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.dfrobot.com/product-1590.html", + "vendor": "DFRobot" +} diff --git a/boards/dfrobot_romeo_esp32s3.json b/boards/dfrobot_romeo_esp32s3.json new file mode 100644 index 000000000..63a7cb472 --- /dev/null +++ b/boards/dfrobot_romeo_esp32s3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "app3M_fat9M_16MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DFROBOT_ROMEO_ESP32S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "dfrobot_romeo_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DFRobot Romeo ESP32-S3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.dfrobot.com/", + "vendor": "DFRobot" +} diff --git a/boards/dpu_esp32.json b/boards/dpu_esp32.json new file mode 100644 index 000000000..1f5b89a67 --- /dev/null +++ b/boards/dpu_esp32.json @@ -0,0 +1,43 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DPU_ESP32", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "dpu_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TAMC DPU ESP32", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/TAMCTec/dpu-esp32", + "vendor": "TAMC" +} diff --git a/boards/edgebox-esp-100.json b/boards/edgebox-esp-100.json new file mode 100644 index 000000000..22aee2f8b --- /dev/null +++ b/boards/edgebox-esp-100.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_Edgebox_ESP_100", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s3", + "variant": "Edgebox-ESP-100" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Seeed Studio Edgebox-ESP-100", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.seeedstudio.com/EdgeBox-ESP-100-p-5490.html", + "vendor": "Seeed Studio" +} diff --git a/boards/esp-wrover-kit.json b/boards/esp-wrover-kit.json new file mode 100644 index 000000000..50d66a7fb --- /dev/null +++ b/boards/esp-wrover-kit.json @@ -0,0 +1,52 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x0403", + "0x6010" + ] + ], + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "default_tool": "ftdi", + "onboard_tools": [ + "ftdi" + ], + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP-WROVER-KIT", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "protocols": [ + "esptool", + "espota", + "ftdi" + ], + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://espressif.com/en/products/hardware/esp-wrover-kit/overview", + "vendor": "Espressif" +} diff --git a/boards/esp32-c3-devkitc-02.json b/boards/esp32-c3-devkitc-02.json new file mode 100644 index 000000000..320b763a0 --- /dev/null +++ b/boards/esp32-c3-devkitc-02.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": "-DARDUINO_ESP32C3_DEV", + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-C3-DevKitC-02", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitc-02.html", + "vendor": "Espressif" +} diff --git a/boards/esp32-c3-devkitm-1.json b/boards/esp32-c3-devkitm-1.json new file mode 100644 index 000000000..cf1a5736a --- /dev/null +++ b/boards/esp32-c3-devkitm-1.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": "-DARDUINO_ESP32C3_DEV", + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-C3-DevKitM-1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html", + "vendor": "Espressif" +} diff --git a/boards/esp32-c3-m1i-kit.json b/boards/esp32-c3-m1i-kit.json new file mode 100644 index 000000000..8e7d7cb08 --- /dev/null +++ b/boards/esp32-c3-m1i-kit.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": [ + "-DARDUINO_ESP32C3_M1_I_KIT", + "-DARDUINO_USB_MODE=1" + ], + "mcu": "esp32c3", + "variant": "esp_c3_m1_i_kit" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Ai-Thinker ESP-C3-M1-I-Kit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.ai-thinker.com/en/esp32c3", + "vendor": "Ai-Thinker" +} diff --git a/boards/esp32-devkitlipo.json b/boards/esp32-devkitlipo.json new file mode 100644 index 000000000..419edfd79 --- /dev/null +++ b/boards/esp32-devkitlipo.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEVKIT_LIPO", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [["0x1A86", "0x7523"]], + "mcu": "esp32", + "variant": "esp32-devkit-lipo" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "OLIMEX ESP32-DevKit-LiPo", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.olimex.com/Products/IoT/ESP32/ESP32-DevKit-LiPo/open-source-hardware", + "vendor": "OLIMEX" +} diff --git a/boards/esp32-evb.json b/boards/esp32-evb.json new file mode 100644 index 000000000..c821386ae --- /dev/null +++ b/boards/esp32-evb.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_EVB", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], + "mcu": "esp32", + "variant": "esp32-evb" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "OLIMEX ESP32-EVB", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.olimex.com/Products/IoT/ESP32-EVB/open-source-hardware", + "vendor": "OLIMEX" +} diff --git a/boards/esp32-gateway.json b/boards/esp32-gateway.json new file mode 100644 index 000000000..33f0f2f2a --- /dev/null +++ b/boards/esp32-gateway.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_GATEWAY", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], + "mcu": "esp32", + "variant": "esp32-gateway" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "OLIMEX ESP32-GATEWAY", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.olimex.com/Products/IoT/ESP32-GATEWAY/open-source-hardware", + "vendor": "OLIMEX" +} diff --git a/boards/esp32-poe-iso.json b/boards/esp32-poe-iso.json new file mode 100644 index 000000000..4412f9466 --- /dev/null +++ b/boards/esp32-poe-iso.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_POE_ISO", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], + "mcu": "esp32", + "variant": "esp32-poe-iso" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "OLIMEX ESP32-PoE-ISO", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.olimex.com/Products/IoT/ESP32/ESP32-POE-ISO/open-source-hardware", + "vendor": "OLIMEX" +} diff --git a/boards/esp32-poe.json b/boards/esp32-poe.json new file mode 100644 index 000000000..0cf9bd46e --- /dev/null +++ b/boards/esp32-poe.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_POE", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [["0x1A86", "0x7523"]], + "mcu": "esp32", + "variant": "esp32-poe" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "OLIMEX ESP32-PoE", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.olimex.com/Products/IoT/ESP32/ESP32-POE/open-source-hardware", + "vendor": "OLIMEX" +} diff --git a/boards/esp32-pro.json b/boards/esp32-pro.json new file mode 100644 index 000000000..ab1957206 --- /dev/null +++ b/boards/esp32-pro.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_PRO", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-evb" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "OLIMEX ESP32-PRO", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.olimex.com/Products/IoT/ESP32/ESP32-PRO/open-source-hardware", + "vendor": "OLIMEX" +} diff --git a/boards/esp32-s2-franzininho.json b/boards/esp32-s2-franzininho.json new file mode 100644 index 000000000..206456339 --- /dev/null +++ b/boards/esp32-s2-franzininho.json @@ -0,0 +1,32 @@ +{ + "build": { + "arduino":{ + "ld": "esp32s2_out.ld" + }, + "core": "esp32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32s2", + "variant": "esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "espidf" + ], + "name": "Franzininho WiFi Board", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/Franzininho/Franzininho-WIFI", + "vendor": "Franzininho" +} diff --git a/boards/esp32-s2-kaluga-1.json b/boards/esp32-s2-kaluga-1.json new file mode 100644 index 000000000..1f1653351 --- /dev/null +++ b/boards/esp32-s2-kaluga-1.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s2", + "variant": "esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "default_tool": "ftdi", + "onboard_tools": [ + "ftdi" + ], + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S2-Kaluga-1 Kit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-esp32-s2-kaluga-1-kit.html", + "vendor": "Espressif" +} diff --git a/boards/esp32-s2-saola-1.json b/boards/esp32-s2-saola-1.json new file mode 100644 index 000000000..f264131f9 --- /dev/null +++ b/boards/esp32-s2-saola-1.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32S2_DEV", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s2", + "variant": "esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S2-Saola-1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html", + "vendor": "Espressif" +} diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json new file mode 100644 index 000000000..a2f8b22f5 --- /dev/null +++ b/boards/esp32-s3-devkitc-1.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html", + "vendor": "Espressif" +} diff --git a/boards/esp320.json b/boards/esp320.json new file mode 100644 index 000000000..dfa8720e1 --- /dev/null +++ b/boards/esp320.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP320", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "esp320" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Electronic SweetPeas ESP320", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.sweetpeas.se/controller-modules/10-esp210.html", + "vendor": "Electronic SweetPeas" +} diff --git a/boards/esp32cam.json b/boards/esp32cam.json new file mode 100644 index 000000000..f7129392c --- /dev/null +++ b/boards/esp32cam.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "huge_app.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "AI Thinker ESP32-CAM", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.ai-thinker.com/esp32-cam", + "vendor": "AI Thinker" +} diff --git a/boards/esp32dev.json b/boards/esp32dev.json new file mode 100644 index 000000000..53c81b656 --- /dev/null +++ b/boards/esp32dev.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32 Dev Module", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Espressif" +} diff --git a/boards/esp32doit-devkit-v1.json b/boards/esp32doit-devkit-v1.json new file mode 100644 index 000000000..5aff5de64 --- /dev/null +++ b/boards/esp32doit-devkit-v1.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "doitESP32devkitV1" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DOIT ESP32 DEVKIT V1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.doit.am/", + "vendor": "DOIT" +} diff --git a/boards/esp32doit-espduino.json b/boards/esp32doit-espduino.json new file mode 100644 index 000000000..1cadd7e9a --- /dev/null +++ b/boards/esp32doit-espduino.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "doitESPduino32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DOIT ESPduino32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.doit.am/", + "vendor": "DOIT" +} diff --git a/boards/esp32s3box.json b/boards/esp32s3box.json new file mode 100644 index 000000000..8a7bfa907 --- /dev/null +++ b/boards/esp32s3box.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_ESP32_S3_BOX", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3box" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S3-Box", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.adafruit.com/product/5290", + "vendor": "Espressif" +} diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json new file mode 100644 index 000000000..5a807a858 --- /dev/null +++ b/boards/esp32s3camlcd.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "memory_type": "opi_opi" + }, + "boot": "opi", + "core": "esp32", + "extra_flags": [ + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_ESP32S3_CAM_LCD", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dout", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3camlcd" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ESP32S3 CAM LCD", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.espressif.com/en/news/Maple_Eye_ESP32-S3", + "vendor": "Espressif" +} diff --git a/boards/esp32thing.json b/boards/esp32thing.json new file mode 100644 index 000000000..4c168e395 --- /dev/null +++ b/boards/esp32thing.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_THING", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32thing" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32 Thing", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/13907", + "vendor": "SparkFun Electronics" +} diff --git a/boards/esp32thing_plus.json b/boards/esp32thing_plus.json new file mode 100644 index 000000000..cf1a74d68 --- /dev/null +++ b/boards/esp32thing_plus.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_THING_PLUS", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32thing_plus" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32 Thing Plus", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/15663", + "vendor": "SparkFun Electronics" +} diff --git a/boards/esp32vn-iot-uno.json b/boards/esp32vn-iot-uno.json new file mode 100644 index 000000000..83e794ee8 --- /dev/null +++ b/boards/esp32vn-iot-uno.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_esp32vn_iot_uno", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32vn-iot-uno" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ESP32vn IoT Uno", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://esp32.vn/", + "vendor": "ESP32vn" +} diff --git a/boards/espea32.json b/boards/espea32.json new file mode 100644 index 000000000..d995b8bb6 --- /dev/null +++ b/boards/espea32.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESPea32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "espea32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "April Brother ESPea32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://blog.aprbrother.com/product/espea", + "vendor": "April Brother" +} diff --git a/boards/espectro32.json b/boards/espectro32.json new file mode 100644 index 000000000..973c6080e --- /dev/null +++ b/boards/espectro32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESPECTRO32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "espectro32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ESPectro32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://shop.makestro.com/product/espectro32", + "vendor": "DycodeX" +} diff --git a/boards/espino32.json b/boards/espino32.json new file mode 100644 index 000000000..162d97929 --- /dev/null +++ b/boards/espino32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESPino32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "espino32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ESPino32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://thaieasyelec.com/products/development-boards/espino-wifi-development-board-detail.html", + "vendor": "ThaiEasyElec" +} diff --git a/boards/etboard.json b/boards/etboard.json new file mode 100644 index 000000000..8ae9775d0 --- /dev/null +++ b/boards/etboard.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ETBoard", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ET-Board" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ETBoard", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://et.ketri.re.kr", + "vendor": "ETBoard" +} diff --git a/boards/featheresp32-s2.json b/boards/featheresp32-s2.json new file mode 100644 index 000000000..6933ccb57 --- /dev/null +++ b/boards/featheresp32-s2.json @@ -0,0 +1,62 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_FEATHER_ESP32S2_NOPSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x80EB" + ], + [ + "0x239A", + "0x00EB" + ], + [ + "0x239A", + "0x80EC" + ] + ], + "mcu": "esp32s2", + "variant": "adafruit_feather_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit ESP32-S2 Feather Development Board", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_feather_esp32s2/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/4769", + "vendor": "Adafruit" +} diff --git a/boards/featheresp32.json b/boards/featheresp32.json new file mode 100644 index 000000000..ac922db5a --- /dev/null +++ b/boards/featheresp32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_FEATHER_ESP32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "feather_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit ESP32 Feather", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/3405", + "vendor": "Adafruit" +} diff --git a/boards/firebeetle32.json b/boards/firebeetle32.json new file mode 100644 index 000000000..3463fa131 --- /dev/null +++ b/boards/firebeetle32.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "firebeetle32" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "FireBeetle-ESP32", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 532480, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.dfrobot.com/FireBeetle_ESP32_IOT_Microcontroller(V3.0)__Supports_Wi-Fi_&_Bluetooth__SKU__DFR0478", + "vendor": "DFRobot" +} diff --git a/boards/fm-devkit.json b/boards/fm-devkit.json new file mode 100644 index 000000000..322975ac8 --- /dev/null +++ b/boards/fm-devkit.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_fm_devkit", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "fm-devkit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ESP32 FM DevKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/dragon-engineer/esp32_fmdevkit", + "vendor": "Unknown" +} diff --git a/boards/franzininho_wifi_esp32s2.json b/boards/franzininho_wifi_esp32s2.json new file mode 100644 index 000000000..df3a5651f --- /dev/null +++ b/boards/franzininho_wifi_esp32s2.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FRANZININHO_WIFI", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80A9" + ] + ], + "mcu": "esp32s2", + "variant": "franzininho_wifi_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Franzininho WiFi", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.franzininho.com.br/docs/franzininho-wifi/franzininho-wifi/", + "vendor": "Franzininho" +} diff --git a/boards/franzininho_wifi_msc_esp32s2.json b/boards/franzininho_wifi_msc_esp32s2.json new file mode 100644 index 000000000..163587b4f --- /dev/null +++ b/boards/franzininho_wifi_msc_esp32s2.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FRANZININHO_WIFI_MSC", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MSC_ON_BOOT=1", + "-DARDUINO_USB_DFU_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80A9" + ] + ], + "mcu": "esp32s2", + "variant": "franzininho_wifi_msc_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Franzininho WiFi MSC", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.franzininho.com.br/docs/franzininho-wifi/franzininho-wifi/", + "vendor": "Franzininho" +} diff --git a/boards/frogboard.json b/boards/frogboard.json new file mode 100644 index 000000000..93a772920 --- /dev/null +++ b/boards/frogboard.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_FROG_ESP32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "frog32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Frog Board ESP32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.tindie.com/products/fred_IOT/esp32s-esp-wroom32-frogopins-development-board/", + "vendor": "Fred" +} diff --git a/boards/healthypi4.json b/boards/healthypi4.json new file mode 100644 index 000000000..bfebc98a8 --- /dev/null +++ b/boards/healthypi4.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HEALTHYPI_4", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "healthypi4" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ProtoCentral HealthyPi 4", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://healthypi.protocentral.com", + "vendor": "ProtoCentral" +} diff --git a/boards/heltec_wifi_kit_32.json b/boards/heltec_wifi_kit_32.json new file mode 100644 index 000000000..0960dd454 --- /dev/null +++ b/boards/heltec_wifi_kit_32.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HELTEC_WIFI_KIT_32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "heltec_wifi_kit_32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec WiFi Kit 32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.heltec.cn/project/wifi-kit-32/?lang=en", + "vendor": "Heltec Automation" +} diff --git a/boards/heltec_wifi_kit_32_V3.json b/boards/heltec_wifi_kit_32_V3.json new file mode 100644 index 000000000..d10631917 --- /dev/null +++ b/boards/heltec_wifi_kit_32_V3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_heltec_wifi_kit_32_V3", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "heltec_wifi_kit_32_v3" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec WiFi Kit 32 (V3)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://heltec.org/project/wifi-kit-32-v3/", + "vendor": "Heltec" +} diff --git a/boards/heltec_wifi_kit_32_v2.json b/boards/heltec_wifi_kit_32_v2.json new file mode 100644 index 000000000..eb80db671 --- /dev/null +++ b/boards/heltec_wifi_kit_32_v2.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HELTEC_WIFI_KIT_32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "heltec_wifi_kit_32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec WiFi Kit 32 (V2)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.heltec.cn/project/wifi-kit-32/?lang=en", + "vendor": "Heltec Automation" +} diff --git a/boards/heltec_wifi_lora_32.json b/boards/heltec_wifi_lora_32.json new file mode 100644 index 000000000..39371182d --- /dev/null +++ b/boards/heltec_wifi_lora_32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HELTEC_WIFI_LORA_32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "heltec_wifi_lora_32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec WiFi LoRa 32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.heltec.cn", + "vendor": "Heltec Automation" +} diff --git a/boards/heltec_wifi_lora_32_V2.json b/boards/heltec_wifi_lora_32_V2.json new file mode 100644 index 000000000..c2a0f950a --- /dev/null +++ b/boards/heltec_wifi_lora_32_V2.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HELTEC_WIFI_LORA_32_V2", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "heltec_wifi_lora_32_V2" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec WiFi LoRa 32 (V2)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.heltec.cn/project/wifi-lora-32/?lang=en", + "vendor": "Heltec Automation" +} diff --git a/boards/heltec_wifi_lora_32_V3.json b/boards/heltec_wifi_lora_32_V3.json new file mode 100644 index 000000000..09a8e1c74 --- /dev/null +++ b/boards/heltec_wifi_lora_32_V3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_heltec_wifi_lora_32_V3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "heltec_wifi_lora_32_V3" + }, + "connectivity": [ + "wifi", + "bluetooth", + "lora" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec WiFi LoRa 32 (V3)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://heltec.org/project/wifi-lora-32-v3/", + "vendor": "Heltec" +} diff --git a/boards/heltec_wireless_stick.json b/boards/heltec_wireless_stick.json new file mode 100644 index 000000000..1f09ca497 --- /dev/null +++ b/boards/heltec_wireless_stick.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HELTEC_WIRELESS_STICK", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "heltec_wireless_stick" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec Wireless Stick", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.heltec.cn/project/wireless-stick/?lang=en", + "vendor": "Heltec Automation" +} diff --git a/boards/heltec_wireless_stick_lite.json b/boards/heltec_wireless_stick_lite.json new file mode 100644 index 000000000..6ffac9acf --- /dev/null +++ b/boards/heltec_wireless_stick_lite.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HELTEC_WIRELESS_STICK_LITE", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "heltec_wireless_stick_lite" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Heltec Wireless Stick Lite", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://heltec.org/project/wireless-stick-lite/", + "vendor": "Heltec Automation" +} diff --git a/boards/honeylemon.json b/boards/honeylemon.json new file mode 100644 index 000000000..c3796dfe0 --- /dev/null +++ b/boards/honeylemon.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HONEYLEMON", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "honeylemon" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "HONEYLemon", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "HONEYLemon" +} diff --git a/boards/hornbill32dev.json b/boards/hornbill32dev.json new file mode 100644 index 000000000..6d96e58b5 --- /dev/null +++ b/boards/hornbill32dev.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HORNBILL_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "hornbill32dev" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Hornbill ESP32 Dev", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://hackaday.io/project/18997-hornbill", + "vendor": "Hornbill" +} diff --git a/boards/hornbill32minima.json b/boards/hornbill32minima.json new file mode 100644 index 000000000..fce2579de --- /dev/null +++ b/boards/hornbill32minima.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HORNBILL_ESP32_MINIMA", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "hornbill32minima" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Hornbill ESP32 Minima", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://hackaday.io/project/18997-hornbill", + "vendor": "Hornbill" +} diff --git a/boards/imbrios-logsens-v1p1.json b/boards/imbrios-logsens-v1p1.json new file mode 100644 index 000000000..a65362f98 --- /dev/null +++ b/boards/imbrios-logsens-v1p1.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_IMBRIOS_LOGSENS_V1P1", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "imbrios-logsens-v1p1" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Imbrios LogSens V1P1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.imbrios.com/products/logsens", + "vendor": "Imbrios" +} diff --git a/boards/inex_openkb.json b/boards/inex_openkb.json new file mode 100644 index 000000000..8f326d5f3 --- /dev/null +++ b/boards/inex_openkb.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_openkb", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "openkb" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "INEX OpenKB", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://inex.co.th/home/product/openkb/", + "vendor": "INEX" +} diff --git a/boards/intorobot.json b/boards/intorobot.json new file mode 100644 index 000000000..6149bce8b --- /dev/null +++ b/boards/intorobot.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_INTOROBOT_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "intorobot-fig" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "IntoRobot Fig", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://docs.intorobot.com/zh/hardware/fig/hardware/", + "vendor": "IntoRobot" +} diff --git a/boards/iotaap_magnolia.json b/boards/iotaap_magnolia.json new file mode 100644 index 000000000..47c1ebad6 --- /dev/null +++ b/boards/iotaap_magnolia.json @@ -0,0 +1,36 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino" + ], + "name": "IoTaaP Magnolia", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.iotaap.io", + "vendor": "IoTaaP" +} diff --git a/boards/iotbusio.json b/boards/iotbusio.json new file mode 100644 index 000000000..11c4264ae --- /dev/null +++ b/boards/iotbusio.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "certified": true, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "default_tool": "iot-bus-jtag", + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "oddWires IoT-Bus Io", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.oddwires.com/iot-bus-io-esp32-processor-with-wifi-and-bluetooth/", + "vendor": "oddWires" +} diff --git a/boards/iotbusproteus.json b/boards/iotbusproteus.json new file mode 100644 index 000000000..3859504f7 --- /dev/null +++ b/boards/iotbusproteus.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "certified": true, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "default_tool": "iot-bus-jtag", + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "oddWires IoT-Bus Proteus", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.oddwires.com/proteus-iot-bus-esp32-microprocessor-wi-fi-and-bluetooth-with-prototype-board-form-factor/", + "vendor": "oddWires" +} diff --git a/boards/kb32-ft.json b/boards/kb32-ft.json new file mode 100644 index 000000000..4bfab5e8d --- /dev/null +++ b/boards/kb32-ft.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_DEV", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MakerAsia KB32-FT", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://kb32ft.makerasia.com/", + "vendor": "MakerAsia" +} diff --git a/boards/kits-edu.json b/boards/kits-edu.json new file mode 100644 index 000000000..6ec72aef9 --- /dev/null +++ b/boards/kits-edu.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_PICO", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "pico32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "KITS ESP32 EDU", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.koreaits.com/new/product/summary.htm?goods_no=468&mid_no=103&no=17", + "vendor": "KITS" +} diff --git a/boards/labplus_mpython.json b/boards/labplus_mpython.json new file mode 100644 index 000000000..3d3a4ff4e --- /dev/null +++ b/boards/labplus_mpython.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "huge_app.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "mpython" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Labplus mPython", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/labplus-cn/mpython", + "vendor": "Labplus" +} diff --git a/boards/lilygo-t-display-s3.json b/boards/lilygo-t-display-s3.json new file mode 100644 index 000000000..7230d3bd2 --- /dev/null +++ b/boards/lilygo-t-display-s3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LILYGO_T_DISPLAY_S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "lilygo_t_display_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "LilyGo T-Display-S3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.lilygo.cc/products/t-display-s3", + "vendor": "LilyGo" +} diff --git a/boards/lionbit.json b/boards/lionbit.json new file mode 100644 index 000000000..c8186d0b2 --- /dev/null +++ b/boards/lionbit.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LIONBIT", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "flags" : "-DCORE_DEBUG_LEVEL=5", + "mcu": "esp32", + "variant": "lionbit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Lion:Bit Dev Board", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 115200 + }, + "monitor": { + "speed" : 115200 + }, + "url": "http://lionbit.lk/", + "vendor": "Lion:Bit" +} diff --git a/boards/lolin32.json b/boards/lolin32.json new file mode 100644 index 000000000..446b2cd44 --- /dev/null +++ b/boards/lolin32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_LOLIN32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "lolin32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.wemos.cc/products:lolin32:lolin32", + "vendor": "WEMOS" +} diff --git a/boards/lolin32_lite.json b/boards/lolin32_lite.json new file mode 100644 index 000000000..5e16bc85a --- /dev/null +++ b/boards/lolin32_lite.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_LOLIN32_LITE", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "lolin32-lite" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN32 Lite", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://diyprojects.io/wemos-lolin32-lite-compact-revision-lolin32-4-90/", + "vendor": "WEMOS" +} diff --git a/boards/lolin_c3_mini.json b/boards/lolin_c3_mini.json new file mode 100644 index 000000000..63afade2c --- /dev/null +++ b/boards/lolin_c3_mini.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LOLIN_C3_MINI", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "lolin_c3_mini" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN C3 Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc/en/latest/c3/c3_mini.html", + "vendor": "WEMOS" +} diff --git a/boards/lolin_d32.json b/boards/lolin_d32.json new file mode 100644 index 000000000..bde02b347 --- /dev/null +++ b/boards/lolin_d32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_LOLIN_D32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "d32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN D32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.wemos.cc/products:d32:d32", + "vendor": "WEMOS" +} diff --git a/boards/lolin_d32_pro.json b/boards/lolin_d32_pro.json new file mode 100644 index 000000000..732b07318 --- /dev/null +++ b/boards/lolin_d32_pro.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_LOLIN_D32_PRO -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "d32_pro" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN D32 PRO", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc/en/latest/d32/d32_pro.html", + "vendor": "WEMOS" +} diff --git a/boards/lolin_s2_mini.json b/boards/lolin_s2_mini.json new file mode 100644 index 000000000..59832f8cb --- /dev/null +++ b/boards/lolin_s2_mini.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LOLIN_S2_MINI", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x80C2" + ] + ], + "mcu": "esp32s2", + "variant": "lolin_s2_mini" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S2 Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.wemos.cc/en/latest/s2/s2_mini.html", + "vendor": "WEMOS" +} diff --git a/boards/lolin_s2_pico.json b/boards/lolin_s2_pico.json new file mode 100644 index 000000000..0214a0eea --- /dev/null +++ b/boards/lolin_s2_pico.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LOLIN_S2_PICO", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x80C5" + ] + ], + "mcu": "esp32s2", + "variant": "lolin_s2_pico" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S2 PICO", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.wemos.cc/en/latest/s2/s2_pico.html", + "vendor": "WEMOS" +} diff --git a/boards/lolin_s3.json b/boards/lolin_s3.json new file mode 100644 index 000000000..30f360e0c --- /dev/null +++ b/boards/lolin_s3.json @@ -0,0 +1,49 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_LOLIN_S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "lolin_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc/en/latest/s3/index.html", + "vendor": "WEMOS" +} diff --git a/boards/lolin_s3_mini.json b/boards/lolin_s3_mini.json new file mode 100644 index 000000000..ad3794bcb --- /dev/null +++ b/boards/lolin_s3_mini.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_LOLIN_S3_MINI", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8167" + ] + ], + "mcu": "esp32s3", + "variant": "lolin_s3_mini" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS LOLIN S3 Mini", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc/en/latest/s3/index.html", + "vendor": "WEMOS" +} + \ No newline at end of file diff --git a/boards/lopy.json b/boards/lopy.json new file mode 100644 index 000000000..307d06a1a --- /dev/null +++ b/boards/lopy.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_LoPy", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "lopy" + }, + "connectivity": [ + "wifi", + "bluetooth", + "can", + "ethernet" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Pycom LoPy", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://pycom.io/", + "vendor": "Pycom Ltd." +} diff --git a/boards/lopy4.json b/boards/lopy4.json new file mode 100644 index 000000000..29062f0fa --- /dev/null +++ b/boards/lopy4.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_LoPy4", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "lopy4" + }, + "connectivity": [ + "wifi", + "bluetooth", + "can", + "ethernet" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Pycom LoPy4", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 1310720, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://pycom.io/", + "vendor": "Pycom Ltd." +} diff --git a/boards/m5stack-atom.json b/boards/m5stack-atom.json new file mode 100644 index 000000000..fd704b0d1 --- /dev/null +++ b/boards/m5stack-atom.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5Stack_ATOM", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stack_atom" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack-ATOM", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 1500000 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-atoms3.json b/boards/m5stack-atoms3.json new file mode 100644 index 000000000..f5e87d3ab --- /dev/null +++ b/boards/m5stack-atoms3.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_M5Stack_ATOMS3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "m5stack_atoms3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack AtomS3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.m5stack.com/en/core/AtomS3", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-core-esp32.json b/boards/m5stack-core-esp32.json new file mode 100644 index 000000000..8d015f417 --- /dev/null +++ b/boards/m5stack-core-esp32.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5Stack_Core_ESP32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "m5stack_core_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack Core ESP32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-core2.json b/boards/m5stack-core2.json new file mode 100644 index 000000000..2c3b95154 --- /dev/null +++ b/boards/m5stack-core2.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5STACK_Core2 -DBOARD_HAS_PSRAM", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stack_core2" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack Core2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 4521984, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-coreink.json b/boards/m5stack-coreink.json new file mode 100644 index 000000000..e7b3cbb1c --- /dev/null +++ b/boards/m5stack-coreink.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5Stack_CoreInk", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stack_coreink" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack-Core Ink", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-cores3.json b/boards/m5stack-cores3.json new file mode 100644 index 000000000..72571e0b7 --- /dev/null +++ b/boards/m5stack-cores3.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_M5STACK_CORES3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8119" + ] + ], + "mcu": "esp32s3", + "variant": "m5stack_cores3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack CoreS3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://docs.m5stack.com/en/core/CoreS3", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-fire.json b/boards/m5stack-fire.json new file mode 100644 index 000000000..1a500ab87 --- /dev/null +++ b/boards/m5stack-fire.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_M5STACK_FIRE", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stack_fire" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack FIRE", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 4521984, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-grey.json b/boards/m5stack-grey.json new file mode 100644 index 000000000..886208ee4 --- /dev/null +++ b/boards/m5stack-grey.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5Stack_Core_ESP32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stack_core_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack GREY ESP32", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 532480, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-stamps3.json b/boards/m5stack-stamps3.json new file mode 100644 index 000000000..6c92e3b5d --- /dev/null +++ b/boards/m5stack-stamps3.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_M5Stack_StampS3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "m5stack_stamp_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack StampS3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.m5stack.com/en/core/StampS3", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-station.json b/boards/m5stack-station.json new file mode 100644 index 000000000..31693d501 --- /dev/null +++ b/boards/m5stack-station.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5Stack_Station", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stack_station" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack Station", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 4521984, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/m5stack-timer-cam.json b/boards/m5stack-timer-cam.json new file mode 100644 index 000000000..5f76a861e --- /dev/null +++ b/boards/m5stack-timer-cam.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_M5Stack_Timer_CAM", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stack_timer_cam" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack Timer CAM", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/m5stamp-pico.json b/boards/m5stamp-pico.json new file mode 100644 index 000000000..8f39fe5ce --- /dev/null +++ b/boards/m5stamp-pico.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5Stamp_Pico", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stack_stamp_pico" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stamp-Pico", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 1500000 + }, + "url": "https://shop.m5stack.com/products/m5stamp-pico-mate-with-pin-headers", + "vendor": "M5Stack" +} diff --git a/boards/m5stick-c.json b/boards/m5stick-c.json new file mode 100644 index 000000000..5c96d7e86 --- /dev/null +++ b/boards/m5stick-c.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5Stick_C", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stick_c" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stick-C", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 1500000 + }, + "url": "http://www.m5stack.com", + "vendor": "M5Stack" +} diff --git a/boards/magicbit.json b/boards/magicbit.json new file mode 100644 index 000000000..53b939e2a --- /dev/null +++ b/boards/magicbit.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "magicbit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MagicBit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://magicblocks.io/", + "vendor": "Magicblocks.io" +} diff --git a/boards/mgbot-iotik32a.json b/boards/mgbot-iotik32a.json new file mode 100644 index 000000000..b4dc416f5 --- /dev/null +++ b/boards/mgbot-iotik32a.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_MGBOT_IOTIK32A", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "mgbot-iotik32a" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MGBOT IOTIK 32A", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://iotik.ru/en/iotik32a/", + "vendor": "MGBOT" +} diff --git a/boards/mgbot-iotik32b.json b/boards/mgbot-iotik32b.json new file mode 100644 index 000000000..15f3d8535 --- /dev/null +++ b/boards/mgbot-iotik32b.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_MGBOT_IOTIK32B", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "mgbot-iotik32b" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MGBOT IOTIK 32B", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://iotik.ru/en/iotik32b/", + "vendor": "MGBOT" +} diff --git a/boards/mhetesp32devkit.json b/boards/mhetesp32devkit.json new file mode 100644 index 000000000..7b677c905 --- /dev/null +++ b/boards/mhetesp32devkit.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_MH_ET_LIVE_ESP32DEVKIT", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "mhetesp32devkit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MH ET LIVE ESP32DevKIT", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://forum.mhetlive.com", + "vendor": "MH-ET Live" +} diff --git a/boards/mhetesp32minikit.json b/boards/mhetesp32minikit.json new file mode 100644 index 000000000..67f451e4a --- /dev/null +++ b/boards/mhetesp32minikit.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_MH_ET_LIVE_ESP32MINIKIT", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "mhetesp32minikit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MH ET LIVE ESP32MiniKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://forum.mhetlive.com", + "vendor": "MH-ET Live" +} diff --git a/boards/microduino-core-esp32.json b/boards/microduino-core-esp32.json new file mode 100644 index 000000000..f1dddb727 --- /dev/null +++ b/boards/microduino-core-esp32.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_CoreESP32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "Microduino-esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Microduino Core ESP32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://microduinoinc.com", + "vendor": "Microduino" +} diff --git a/boards/micros2.json b/boards/micros2.json new file mode 100644 index 000000000..93243bdba --- /dev/null +++ b/boards/micros2.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld", + "partitions": "ffat.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_MICROS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MSC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80C5" + ] + ], + "mcu": "esp32s2", + "variant": "micro_s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "microS2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/MicroDev1/microS2", + "vendor": "microS2" +} diff --git a/boards/minimain_esp32s2.json b/boards/minimain_esp32s2.json new file mode 100644 index 000000000..5502a6aff --- /dev/null +++ b/boards/minimain_esp32s2.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld", + "partitions": "partitions-4MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DEPARTMENT_OF_ALCHEMY_MINIMAIN_ESP32S2", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80FF" + ] + ], + "mcu": "esp32s2", + "variant": "department_of_alchemy_minimain_esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Deparment of Alchemy MiniMain ESP32-S2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/DepartmentOfAlchemy/minimain-esp32-s2", + "vendor": "Deparment of Alchemy" +} diff --git a/boards/nano32.json b/boards/nano32.json new file mode 100644 index 000000000..2e1f5568c --- /dev/null +++ b/boards/nano32.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_NANO32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "nano32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "MakerAsia Nano32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://iot-bits.com/nano32-esp32-development-board", + "vendor": "MakerAsia" +} diff --git a/boards/nebulas3.json b/boards/nebulas3.json new file mode 100644 index 000000000..dc6236494 --- /dev/null +++ b/boards/nebulas3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_NEBULAS3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "Nebula_S3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Kinetic Dynamics Nebula S3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://kineticdynamics.in/product/nebula-s3/", + "vendor": "Kinetic Dynamics" +} diff --git a/boards/nina_w10.json b/boards/nina_w10.json new file mode 100644 index 000000000..a0041df2f --- /dev/null +++ b/boards/nina_w10.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "minimal.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_UBLOX_NINA_W10", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "nina_w10" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "u-blox NINA-W10 series", + "upload": { + "flash_size": "2MB", + "maximum_ram_size": 327680, + "maximum_size": 2097152, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.u-blox.com/en/product/nina-w10-series", + "vendor": "u-blox" +} diff --git a/boards/node32s.json b/boards/node32s.json new file mode 100644 index 000000000..192bda36a --- /dev/null +++ b/boards/node32s.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Node32s", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Node32s", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.ayarafun.com", + "vendor": "Aiyarafun" +} diff --git a/boards/nodemcu-32s.json b/boards/nodemcu-32s.json new file mode 100644 index 000000000..5d30f2c2e --- /dev/null +++ b/boards/nodemcu-32s.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_NodeMCU_32S", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "nodemcu-32s" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "NodeMCU-32S", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.nodemcu.com/", + "vendor": "NodeMCU" +} diff --git a/boards/nodemcu-32s2.json b/boards/nodemcu-32s2.json new file mode 100644 index 000000000..984b90d2b --- /dev/null +++ b/boards/nodemcu-32s2.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32S2_DEV", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s2", + "variant": "esp32s2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Ai-Thinker NodeMCU-32S2 (ESP-12K)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.ai-thinker.com/en/esp32s2", + "vendor": "Ai-Thinker" +} diff --git a/boards/nscreen-32.json b/boards/nscreen-32.json new file mode 100644 index 000000000..d9b3a40af --- /dev/null +++ b/boards/nscreen-32.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x0403", + "0x6010" + ] + ], + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "YeaCreate NSCREEN-32", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://yeacreate.com", + "vendor": "YeaCreate" +} diff --git a/boards/odroid_esp32.json b/boards/odroid_esp32.json new file mode 100644 index 000000000..0634df32a --- /dev/null +++ b/boards/odroid_esp32.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ODROID_ESP32 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "odroid_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ODROID-GO", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.hardkernel.com/main/products/prdt_info.php?g_code=G152875062626", + "vendor": "Hardkernel" +} diff --git a/boards/onehorse32dev.json b/boards/onehorse32dev.json new file mode 100644 index 000000000..4b2364100 --- /dev/null +++ b/boards/onehorse32dev.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ONEHORSE_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dout", + "mcu": "esp32", + "variant": "onehorse32dev" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Onehorse ESP32 Dev Module", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.tindie.com/products/onehorse/esp32-development-board/", + "vendor": "Onehorse" +} diff --git a/boards/oroca_edubot.json b/boards/oroca_edubot.json new file mode 100644 index 000000000..2a99c8c6c --- /dev/null +++ b/boards/oroca_edubot.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "huge_app.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_OROCA_EDUBOT", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "oroca_edubot" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "OROCA EduBot", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/oroca/OROCA-EduBot", + "vendor": "OROCA" +} diff --git a/boards/pico32.json b/boards/pico32.json new file mode 100644 index 000000000..5580b07e0 --- /dev/null +++ b/boards/pico32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_PICO", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "pico32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ESP32 Pico Kit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://esp-idf.readthedocs.io/en/latest/get-started/get-started-pico-kit.html", + "vendor": "Espressif" +} diff --git a/boards/piranha_esp32.json b/boards/piranha_esp32.json new file mode 100644 index 000000000..acd8a231a --- /dev/null +++ b/boards/piranha_esp32.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Piranha", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "piranha_esp-32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Fishino Piranha ESP-32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://fishino.it/boards.html", + "vendor": "Fishino" +} diff --git a/boards/pocket_32.json b/boards/pocket_32.json new file mode 100644 index 000000000..153ac2322 --- /dev/null +++ b/boards/pocket_32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Pocket32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "pocket_32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Dongsen Tech Pocket 32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://dong-sen.com", + "vendor": "Dongsen Technology" +} diff --git a/boards/pycom_gpy.json b/boards/pycom_gpy.json new file mode 100644 index 000000000..37cc507e1 --- /dev/null +++ b/boards/pycom_gpy.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_PYCOM_GPY", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "gpy" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Pycom GPy", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://pycom.io/product/gpy/", + "vendor": "Pycom Ltd." +} diff --git a/boards/qchip.json b/boards/qchip.json new file mode 100644 index 000000000..11f4c9259 --- /dev/null +++ b/boards/qchip.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_HELTEC_WIFI_KIT_32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "heltec_wifi_kit_32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Qchip", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://qmobot.com/", + "vendor": "Qmobot LLP" + } \ No newline at end of file diff --git a/boards/quantum.json b/boards/quantum.json new file mode 100644 index 000000000..ea5ae279f --- /dev/null +++ b/boards/quantum.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_QUANTUM", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "quantum" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Noduino Quantum", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://wiki.jackslab.org/Noduino", + "vendor": "Noduino" +} diff --git a/boards/redpill_esp32s3.json b/boards/redpill_esp32s3.json new file mode 100644 index 000000000..8dff2ff49 --- /dev/null +++ b/boards/redpill_esp32s3.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_REDPILL_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x80F8" + ] + ], + "mcu": "esp32s3", + "variant": "redpill_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Munich Labs RedPill ESP32-S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/redpill_esp32s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://munich-labs.com/index.php/redpill-esp32-s3/", + "vendor": "Munich Labs" +} diff --git a/boards/roboheart_hercules.json b/boards/roboheart_hercules.json new file mode 100644 index 000000000..46740d2e9 --- /dev/null +++ b/boards/roboheart_hercules.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_roboheart_hercules", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "roboheart_hercules" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "RoboHeart Hercules", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://roboheart.de/en_gb/", + "vendor": "RoboHeart" +} diff --git a/boards/s_odi_ultra.json b/boards/s_odi_ultra.json new file mode 100644 index 000000000..3a0307867 --- /dev/null +++ b/boards/s_odi_ultra.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "S_ODI_Ultra_v1" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "S.ODI Ultra v1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.espressif.com/en/products/socs/esp32", + "vendor": "S.ODI" +} diff --git a/boards/seeed_xiao_esp32c3.json b/boards/seeed_xiao_esp32c3.json new file mode 100644 index 000000000..24b167120 --- /dev/null +++ b/boards/seeed_xiao_esp32c3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_XIAO_ESP32C3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x2886", + "0x0046" + ], + [ + "0x303a", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "XIAO_ESP32C3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Seeed Studio XIAO ESP32C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/", + "vendor": "Seeed Studio" +} diff --git a/boards/seeed_xiao_esp32s3.json b/boards/seeed_xiao_esp32s3.json new file mode 100644 index 000000000..cf98a6aa4 --- /dev/null +++ b/boards/seeed_xiao_esp32s3.json @@ -0,0 +1,53 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_XIAO_ESP32S3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x2886", + "0x0056" + ], + [ + "0x2886", + "0x8056" + ] + ], + "mcu": "esp32s3", + "variant": "XIAO_ESP32S3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Seeed Studio XIAO ESP32S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.seeedstudio.com/XIAO-ESP32S3-p-5627.html", + "vendor": "Seeed Studio" +} diff --git a/boards/sensesiot_weizen.json b/boards/sensesiot_weizen.json new file mode 100644 index 000000000..4492655c4 --- /dev/null +++ b/boards/sensesiot_weizen.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_sensesiot_weizen", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "LOGISENSES Senses Weizen", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.logisenses.com/index.php/product/senses-weizen/", + "vendor": "LOGISENSES" +} diff --git a/boards/sg-o_airMon.json b/boards/sg-o_airMon.json new file mode 100644 index 000000000..53e254435 --- /dev/null +++ b/boards/sg-o_airMon.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_SG_O_AIRMON_ESP32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "platforms": [ + "espressif32" + ], + "name": "SG-O AirMon", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/SG-O/airMon", + "vendor": "SG-O" +} diff --git a/boards/sparkfun_esp32_iot_redboard.json b/boards/sparkfun_esp32_iot_redboard.json new file mode 100644 index 000000000..e97c2d886 --- /dev/null +++ b/boards/sparkfun_esp32_iot_redboard.json @@ -0,0 +1,41 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_IOT_REDBOARD", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "sparkfun_esp32_iot_redboard" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32 IoT RedBoard", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/19177", + "vendor": "SparkFun" +} diff --git a/boards/sparkfun_esp32micromod.json b/boards/sparkfun_esp32micromod.json new file mode 100644 index 000000000..16fb0f168 --- /dev/null +++ b/boards/sparkfun_esp32micromod.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_MICROMOD", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "esp32micromod" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32 MicroMod", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/16781", + "vendor": "SparkFun" +} diff --git a/boards/sparkfun_esp32s2_thing_plus.json b/boards/sparkfun_esp32s2_thing_plus.json new file mode 100644 index 000000000..f8697e73a --- /dev/null +++ b/boards/sparkfun_esp32s2_thing_plus.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32S2_THING_PLUS", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x1B4F", + "0x0027" + ] + ], + "mcu": "esp32s2", + "variant": "esp32s2thing_plus" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32-S2 Thing Plus", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/17743", + "vendor": "SparkFun" +} diff --git a/boards/sparkfun_esp32s2_thing_plus_c.json b/boards/sparkfun_esp32s2_thing_plus_c.json new file mode 100644 index 000000000..01aaed7cb --- /dev/null +++ b/boards/sparkfun_esp32s2_thing_plus_c.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_THING_PLUS_C", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32thing_plus_c" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun ESP32 Thing Plus C", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/18018", + "vendor": "SparkFun" +} diff --git a/boards/sparkfun_lora_gateway_1-channel.json b/boards/sparkfun_lora_gateway_1-channel.json new file mode 100644 index 000000000..16eb8438c --- /dev/null +++ b/boards/sparkfun_lora_gateway_1-channel.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "sparkfun_lora_gateway_1-channel" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SparkFun LoRa Gateway 1-Channel", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.sparkfun.com/products/15006", + "vendor": "SparkFun" +} diff --git a/boards/tamc_termod_s3.json b/boards/tamc_termod_s3.json new file mode 100644 index 000000000..934c15fb1 --- /dev/null +++ b/boards/tamc_termod_s3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TAMC_TERMOD_S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "tamc_termod_s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TAMC Termod S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://termod-s3.readthedocs.io/en/latest/", + "vendor": "TAMC" +} diff --git a/boards/tinypico.json b/boards/tinypico.json new file mode 100644 index 000000000..0b1302e8a --- /dev/null +++ b/boards/tinypico.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TINYPICO", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "um_tinypico" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker TinyPICO", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.tinypico.com", + "vendor": "Unexpected Maker" +} diff --git a/boards/trueverit-iot-driver-mk2.json b/boards/trueverit-iot-driver-mk2.json new file mode 100644 index 000000000..22e3eca79 --- /dev/null +++ b/boards/trueverit-iot-driver-mk2.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver_MK_II", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver-mkii" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver MK II", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} diff --git a/boards/trueverit-iot-driver-mk3.json b/boards/trueverit-iot-driver-mk3.json new file mode 100644 index 000000000..0b394a723 --- /dev/null +++ b/boards/trueverit-iot-driver-mk3.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver_MK_III", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver-mkiii" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver MK III", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} + diff --git a/boards/trueverit-iot-driver.json b/boards/trueverit-iot-driver.json new file mode 100644 index 000000000..7f808ec32 --- /dev/null +++ b/boards/trueverit-iot-driver.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Trueverit_ESP32_Universal_IoT_Driver", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-trueverit-iot-driver" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Trueverit ESP32 Universal IoT Driver", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://trueverit.com/", + "vendor": "Trueverit" +} diff --git a/boards/ttgo-lora32-v1.json b/boards/ttgo-lora32-v1.json new file mode 100644 index 000000000..339a8b61b --- /dev/null +++ b/boards/ttgo-lora32-v1.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_TTGO_LoRa32_V1", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ttgo-lora32-v1" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO LoRa32-OLED V1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/Xinyuan-LilyGO/TTGO-LoRa-Series", + "vendor": "TTGO" +} diff --git a/boards/ttgo-lora32-v2.json b/boards/ttgo-lora32-v2.json new file mode 100644 index 000000000..502c3576f --- /dev/null +++ b/boards/ttgo-lora32-v2.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_TTGO_LoRa32_V2", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ttgo-lora32-v2" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO LoRa32-OLED V2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/LilyGO/TTGO-LORA32-V2.0", + "vendor": "TTGO" +} diff --git a/boards/ttgo-lora32-v21.json b/boards/ttgo-lora32-v21.json new file mode 100644 index 000000000..c2fb118b3 --- /dev/null +++ b/boards/ttgo-lora32-v21.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_TTGO_LoRa32_v21new", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "ttgo-lora32-v21new" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO LoRa32-OLED v2.1.6", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/LilyGO/TTGO-LoRa32-V2.1", + "vendor": "TTGO" +} diff --git a/boards/ttgo-t-beam.json b/boards/ttgo-t-beam.json new file mode 100644 index 000000000..f2d144aa2 --- /dev/null +++ b/boards/ttgo-t-beam.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_T_Beam -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "tbeam" + }, + "connectivity": [ + "wifi", + "bluetooth", + "can", + "ethernet" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO T-Beam", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 1310720, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/LilyGO/TTGO-T-Beam", + "vendor": "TTGO" +} diff --git a/boards/ttgo-t-oi-plus.json b/boards/ttgo-t-oi-plus.json new file mode 100644 index 000000000..3b05918ef --- /dev/null +++ b/boards/ttgo-t-oi-plus.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": "-DARDUINO_TTGO_T_OI_PLUS_DEV", + "mcu": "esp32c3", + "variant": "ttgo-t-oi-plus" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO T-OI PLUS RISC-V ESP32-C3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.lilygo.cn/prod_view.aspx?TypeId=50044&Id=1361&FId=t3:50044:3", + "vendor": "TTGO" +} diff --git a/boards/ttgo-t-watch.json b/boards/ttgo-t-watch.json new file mode 100644 index 000000000..354f54f14 --- /dev/null +++ b/boards/ttgo-t-watch.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TWATCH_BASE", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "twatch" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO T-Watch", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 2000000 + }, + "url": "https://github.com/Xinyuan-LilyGO/TTGO-T-Watch", + "vendor": "TTGO" +} diff --git a/boards/ttgo-t1.json b/boards/ttgo-t1.json new file mode 100644 index 000000000..4f428cd08 --- /dev/null +++ b/boards/ttgo-t1.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_TTGO_T1", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "ttgo-t1" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO T1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/LilyGO/ESP32-TTGO-T1", + "vendor": "TTGO" +} diff --git a/boards/ttgo-t7-v13-mini32.json b/boards/ttgo-t7-v13-mini32.json new file mode 100644 index 000000000..21552df94 --- /dev/null +++ b/boards/ttgo-t7-v13-mini32.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_TTGO_T7_V13_Mini32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "ttgo-t7-v13-mini32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "can", + "ethernet" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO T7 V1.3 Mini32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 1310720, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/LilyGO/ESP32-MINI-32-V1.3", + "vendor": "TTGO" +} diff --git a/boards/ttgo-t7-v14-mini32.json b/boards/ttgo-t7-v14-mini32.json new file mode 100644 index 000000000..23d327196 --- /dev/null +++ b/boards/ttgo-t7-v14-mini32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_TTGO_T7_V14_Mini32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "ttgo-t7-v14-mini32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "can", + "ethernet" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "TTGO T7 V1.4 Mini32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 1310720, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.lilygo.cn/prod_view.aspx?TypeId=50033&Id=978&FId=t3:50033:3", + "vendor": "TTGO" +} diff --git a/boards/turta_iot_node.json b/boards/turta_iot_node.json new file mode 100644 index 000000000..3f3482510 --- /dev/null +++ b/boards/turta_iot_node.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_PICO", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "pico32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Turta IoT Node", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.turta.io/en/iotnode", + "vendor": "Turta" +} diff --git a/boards/um_feathers2.json b/boards/um_feathers2.json new file mode 100644 index 000000000..7434f195e --- /dev/null +++ b/boards/um_feathers2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x239A", + "0x80AB" + ] + ], + "mcu": "esp32s2", + "variant": "um_feathers2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker FeatherS2", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://feathers2.io", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_feathers2_neo.json b/boards/um_feathers2_neo.json new file mode 100644 index 000000000..7277d45ff --- /dev/null +++ b/boards/um_feathers2_neo.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS2NEO", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x80B4" + ] + ], + "mcu": "esp32s2", + "variant": "um_feathers2neo" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker FeatherS2 Neo", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://unexpectedmaker.com/feathers2-neo", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_feathers3.json b/boards/um_feathers3.json new file mode 100644 index 000000000..4430f59b0 --- /dev/null +++ b/boards/um_feathers3.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_FEATHERS3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x80D0" + ] + ], + "mcu": "esp32s3", + "variant": "um_feathers3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker FeatherS3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/feathers3", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_pros3.json b/boards/um_pros3.json new file mode 100644 index 000000000..b0b379834 --- /dev/null +++ b/boards/um_pros3.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_PROS3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "um_pros3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker PROS3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/pros3", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_rmp.json b/boards/um_rmp.json new file mode 100644 index 000000000..c5e547acc --- /dev/null +++ b/boards/um_rmp.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_RMP", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0X303A", + "0x80F6" + ] + ], + "mcu": "esp32s2", + "variant": "um_rmp" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker RMP", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://unexpectedmaker.com/esp32s2", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_tinys2.json b/boards/um_tinys2.json new file mode 100644 index 000000000..8a57216ac --- /dev/null +++ b/boards/um_tinys2.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s2_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TINYS2", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x303A", + "0x8001" + ] + ], + "mcu": "esp32s2", + "variant": "um_tinys2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s2.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker TinyS2", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://tinys2.io", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_tinys3.json b/boards/um_tinys3.json new file mode 100644 index 000000000..6a9e3c14c --- /dev/null +++ b/boards/um_tinys3.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TINYS3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x80D0" + ] + ], + "mcu": "esp32s3", + "variant": "um_tinys3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker TinyS3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/ttinys3-esp32s3", + "vendor": "Unexpected Maker" +} diff --git a/boards/unphone7.json b/boards/unphone7.json new file mode 100644 index 000000000..4204c79da --- /dev/null +++ b/boards/unphone7.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DUNPHONE_SPIN=7", + "-DARDUINO_FEATHER_ESP32" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "feather_esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "unPhone 7", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unphone.net/", + "vendor": "University of Sheffield" +} diff --git a/boards/unphone8.json b/boards/unphone8.json new file mode 100644 index 000000000..3ee0955d9 --- /dev/null +++ b/boards/unphone8.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DUNPHONE_SPIN=8", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=0", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s3", + "variant": "unphone8" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_board": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "unPhone 8", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 2424832, + "maximum_size": 8323072, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unphone.net/", + "vendor": "University of Sheffield" +} diff --git a/boards/unphone9.json b/boards/unphone9.json new file mode 100644 index 000000000..e269a9662 --- /dev/null +++ b/boards/unphone9.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DUNPHONE_SPIN=9", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x16D0", + "0x1178" + ] + ], + "mcu": "esp32s3", + "variant": "unphone9" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_board": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "unPhone 9", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 8716288, + "maximum_size": 8323072, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unphone.net/", + "vendor": "University of Sheffield" +} diff --git a/boards/upesy_wroom.json b/boards/upesy_wroom.json new file mode 100644 index 000000000..5d2553225 --- /dev/null +++ b/boards/upesy_wroom.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_uPesy_WROOM", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "uPesy_esp32_wroom_devkit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "uPesy ESP32 Wroom DevKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.upesy.fr/products/upesy-esp32-wroom-devkit-board", + "vendor": "uPesy" +} diff --git a/boards/upesy_wrover.json b/boards/upesy_wrover.json new file mode 100644 index 000000000..5eb0e0fd3 --- /dev/null +++ b/boards/upesy_wrover.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_uPesy_WROVER", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "uPesy_esp32_wrover_devkit" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp32-wrover.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "uPesy ESP32 Wrover DevKit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.upesy.fr/products/upesy-esp32-wrover-devkit-board", + "vendor": "uPesy" +} diff --git a/boards/valtrack_v4_mfw_esp32_c3.json b/boards/valtrack_v4_mfw_esp32_c3.json new file mode 100644 index 000000000..c910f152e --- /dev/null +++ b/boards/valtrack_v4_mfw_esp32_c3.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_VALTRACK_V4_MFW_ESP32_C3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "VALTRACK_V4_MFW_ESP32_C3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Valetron Systems VALTRACK-V4MVF", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.valetron.com/", + "vendor": "Valetron Systems" +} diff --git a/boards/valtrack_v4_vts_esp32_c3.json b/boards/valtrack_v4_vts_esp32_c3.json new file mode 100644 index 000000000..8197b0bf0 --- /dev/null +++ b/boards/valtrack_v4_vts_esp32_c3.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_VALTRACK_V4_VTS_ESP32_C3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32c3", + "variant": "VALTRACK_V4_VTS_ESP32_C3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Valetron Systems VALTRACK-V4VTS", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.valetron.com/", + "vendor": "Valetron Systems" +} diff --git a/boards/vintlabs-devkit-v1.json b/boards/vintlabs-devkit-v1.json new file mode 100644 index 000000000..4ba1fa16e --- /dev/null +++ b/boards/vintlabs-devkit-v1.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "vintlabsdevkitv1" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "VintLabs ESP32 Devkit", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.vintlabs.com/product/vintlabs-esp32-wroom32-iot-8x2a-pwm-driver-development-kit-4mb-flash-wifi-bluetooth/", + "vendor": "VintLabs" +} diff --git a/boards/watchy.json b/boards/watchy.json new file mode 100644 index 000000000..f91eed072 --- /dev/null +++ b/boards/watchy.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld", + "partitions": "huge_app.csv" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_WATCHY", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "watchy" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "SQFMI Watchy v2.0", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://watchy.sqfmi.com/", + "vendor": "SQFMI" +} diff --git a/boards/wemos_d1_mini32.json b/boards/wemos_d1_mini32.json new file mode 100644 index 000000000..90b1d6b95 --- /dev/null +++ b/boards/wemos_d1_mini32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_D1_MINI32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "d1_mini32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS D1 MINI ESP32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc", + "vendor": "WEMOS" +} diff --git a/boards/wemos_d1_uno32.json b/boards/wemos_d1_uno32.json new file mode 100644 index 000000000..2a38aa423 --- /dev/null +++ b/boards/wemos_d1_uno32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_D1_UNO32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "d1_uno32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WEMOS D1 R32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc", + "vendor": "WEMOS" +} diff --git a/boards/wemosbat.json b/boards/wemosbat.json new file mode 100644 index 000000000..1312abbb9 --- /dev/null +++ b/boards/wemosbat.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Pocket32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "pocket_32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "WeMos WiFi and Bluetooth Battery", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.wemos.cc", + "vendor": "WEMOS" +} diff --git a/boards/wesp32.json b/boards/wesp32.json new file mode 100644 index 000000000..9f924ba9d --- /dev/null +++ b/boards/wesp32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_WESP32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "wesp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Silicognition wESP32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wesp32.com/", + "vendor": "Silicognition" +} diff --git a/boards/widora-air.json b/boards/widora-air.json new file mode 100644 index 000000000..4dfda2764 --- /dev/null +++ b/boards/widora-air.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_WIDORA_AIR", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "widora-air" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Widora AIR", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://widora.io", + "vendor": "Widora" +} diff --git a/boards/wifiduino32.json b/boards/wifiduino32.json new file mode 100644 index 000000000..53ca00942 --- /dev/null +++ b/boards/wifiduino32.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_Wifiduino32", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "wifiduino32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Blinker WiFiduino32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://diandeng.tech", + "vendor": "Blinker" +} diff --git a/boards/wifiduino32c3.json b/boards/wifiduino32c3.json new file mode 100644 index 000000000..5b5b61675 --- /dev/null +++ b/boards/wifiduino32c3.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": [ + "-DARDUINO_WiFiduinoV2", + "-DARDUINO_USB_MODE=1" + ], + "mcu": "esp32c3", + "variant": "wifiduinov2" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Blinker WiFiduinoV2 (ESP32-C3)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://diandeng.tech", + "vendor": "Blinker" +} diff --git a/boards/wifiduino32s3.json b/boards/wifiduino32s3.json new file mode 100644 index 000000000..fa8989469 --- /dev/null +++ b/boards/wifiduino32s3.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_WiFiduino32S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "wifiduino32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Blinker WiFiduino32S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://diandeng.tech", + "vendor": "Blinker" +} diff --git a/boards/wipy3.json b/boards/wipy3.json new file mode 100644 index 000000000..b9e5419b1 --- /dev/null +++ b/boards/wipy3.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_WIPY3", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "wipy3" + }, + "connectivity": [ + "wifi", + "bluetooth", + "can", + "ethernet" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Pycom WiPy3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 1310720, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://pycom.io/", + "vendor": "Pycom Ltd." +} diff --git a/boards/wt32-eth01.json b/boards/wt32-eth01.json new file mode 100644 index 000000000..3fddb34a5 --- /dev/null +++ b/boards/wt32-eth01.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_WT32_ETH01" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "wt32-eth01" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Wireless-Tag WT32-ETH01 Ethernet Module", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "http://www.wireless-tag.com/portfolio/wt32-eth01/", + "vendor": "Wireless-Tag" +} diff --git a/boards/xinabox_cw02.json b/boards/xinabox_cw02.json new file mode 100644 index 000000000..527956b1e --- /dev/null +++ b/boards/xinabox_cw02.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "xinabox" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "XinaBox CW02", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://xinabox.cc/products/cw02", + "vendor": "XinaBox" +} From 004fe13c39db95c10e8c5dc4973f79ff4bfc88ed Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 3 Aug 2023 18:10:46 +0200 Subject: [PATCH 402/666] Create esp32-solo1.json --- boards/esp32-solo1.json | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 boards/esp32-solo1.json diff --git a/boards/esp32-solo1.json b/boards/esp32-solo1.json new file mode 100644 index 000000000..e87b7e13d --- /dev/null +++ b/boards/esp32-solo1.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV -DARDUINO_USB_CDC_ON_BOOT=0 -DCORE32SOLO1", + "f_cpu": "80000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_target": "esp32-solo-1.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif Generic ESP32-solo1 4M Flash", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Espressif" +} From a7c8cf3b5c65505258a0ebcb2d1307346d8defff Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 3 Aug 2023 18:18:59 +0200 Subject: [PATCH 403/666] dfu uploader --- platform.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform.json b/platform.json index 0a6b17534..88adc59bd 100644 --- a/platform.json +++ b/platform.json @@ -88,6 +88,12 @@ "owner": "tasmota", "version": "https://github.com/tasmota/esptool/releases/download/v4.6.2/esptool-4.6.2.zip" }, + "tool-dfuutil-arduino": { + "type": "uploader", + "optional": true, + "owner": "platformio", + "version": "~1.11.0" + }, "tool-openocd-esp32": { "type": "debugger", "optional": true, From 1ca8129f38f5d598d6fbf1af806546646ff7f0bc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 6 Aug 2023 13:00:21 +0200 Subject: [PATCH 404/666] revert max_upload_size changes --- builder/main.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/builder/main.py b/builder/main.py index 6f7eb18e7..8b19773af 100644 --- a/builder/main.py +++ b/builder/main.py @@ -162,20 +162,12 @@ def _parse_partitions(env): def _update_max_upload_size(env): if not env.get("PARTITIONS_TABLE_CSV"): return - sizes = { - p["subtype"]: _parse_size(p["size"]) for p in _parse_partitions(env) + sizes = [ + _parse_size(p["size"]) for p in _parse_partitions(env) if p["type"] in ("0", "app") - } - - # One of the `factory` or `ota_0` partitions is used to determine available memory - # size. If both partitions are set, we should prefer the `factory`, but there are - # cases (e.g. Adafruit's `partitions-4MB-tinyuf2.csv`) that uses the `factory` - # partition for their UF2 bootloader. So let's use the first match - # https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html#subtype - for p in _parse_partitions(env): - if p["type"] in ("0", "app") and p["subtype"] in ("factory", "ota_0"): - board.update("upload.maximum_size", _parse_size(p["size"])) - break + ] + if sizes: + board.update("upload.maximum_size", max(sizes)) def _to_unix_slashes(path): From 21111e90982ddf8a5ccf00cfc00cdb0e3f4f9dda Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 9 Aug 2023 18:06:43 +0200 Subject: [PATCH 405/666] Build 1481 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 88adc59bd..6df8be120 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1448/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1481/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1448/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1481/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1448/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1481/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" }, "framework-espidf": { "type": "framework", From ef4dbfb476d15efdf37c731a4d81052b2c21df28 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 17 Aug 2023 18:05:33 +0200 Subject: [PATCH 406/666] Update arduino.py --- builder/frameworks/arduino.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 4a0bfbcfc..36cd206b5 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -77,7 +77,9 @@ def _get_installed_pip_packages(): return result deps = { - "zopfli": ">=0.2.2" + "wheel": ">=0.35.1", + "zopfli": ">=0.2.2", + "tasmota-metrics": ">=0.3.3" } installed_packages = _get_installed_pip_packages() From c42383507a6f823e67c533aec33c54452ddb6e34 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 17 Aug 2023 20:24:44 +0200 Subject: [PATCH 407/666] Update examples.yml --- .github/workflows/examples.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 1702eddd1..c30c8229e 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -14,7 +14,6 @@ jobs: matrix: os: [ubuntu-22.04, windows-2022, macOS-12] example: - - "examples/arduino-ble5-advertising" - "examples/arduino-blink" - "examples/arduino-rmt-blink" - "examples/arduino-usb-keyboard" From a5cc693989baffde52d90e17a4cfa047c6f87a99 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 17 Aug 2023 20:25:07 +0200 Subject: [PATCH 408/666] Delete examples/arduino-ble5-advertising directory --- examples/arduino-ble5-advertising/.gitignore | 1 - examples/arduino-ble5-advertising/README.md | 27 ------- .../arduino-ble5-advertising/include/README | 39 ---------- examples/arduino-ble5-advertising/lib/README | 46 ------------ .../arduino-ble5-advertising/platformio.ini | 14 ---- .../src/BLE5_periodic_advertising.ino | 72 ------------------- examples/arduino-ble5-advertising/test/README | 11 --- 7 files changed, 210 deletions(-) delete mode 100644 examples/arduino-ble5-advertising/.gitignore delete mode 100644 examples/arduino-ble5-advertising/README.md delete mode 100644 examples/arduino-ble5-advertising/include/README delete mode 100644 examples/arduino-ble5-advertising/lib/README delete mode 100644 examples/arduino-ble5-advertising/platformio.ini delete mode 100644 examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino delete mode 100644 examples/arduino-ble5-advertising/test/README diff --git a/examples/arduino-ble5-advertising/.gitignore b/examples/arduino-ble5-advertising/.gitignore deleted file mode 100644 index 03f4a3c19..000000000 --- a/examples/arduino-ble5-advertising/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/arduino-ble5-advertising/README.md b/examples/arduino-ble5-advertising/README.md deleted file mode 100644 index f34cc0db8..000000000 --- a/examples/arduino-ble5-advertising/README.md +++ /dev/null @@ -1,27 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/arduino-ble5-advertising - -# Build project -$ pio run - -# Upload firmware -$ pio run --target upload - -# Build specific environment -$ pio run -e esp32-c3-devkitm-1 - -# Upload firmware for the specific environment -$ pio run -e esp32-c3-devkitm-1 --target upload - -# Clean build files -$ pio run --target clean -``` \ No newline at end of file diff --git a/examples/arduino-ble5-advertising/include/README b/examples/arduino-ble5-advertising/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/arduino-ble5-advertising/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/arduino-ble5-advertising/lib/README b/examples/arduino-ble5-advertising/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/arduino-ble5-advertising/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/arduino-ble5-advertising/platformio.ini b/examples/arduino-ble5-advertising/platformio.ini deleted file mode 100644 index 638c205b6..000000000 --- a/examples/arduino-ble5-advertising/platformio.ini +++ /dev/null @@ -1,14 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[env:esp32-c3-devkitm-1] -platform = espressif32 -board = esp32-c3-devkitm-1 -framework = arduino -monitor_speed = 115200 diff --git a/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino b/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino deleted file mode 100644 index 1b36bbb8b..000000000 --- a/examples/arduino-ble5-advertising/src/BLE5_periodic_advertising.ino +++ /dev/null @@ -1,72 +0,0 @@ -/* - Simple BLE5 multi advertising example on esp32 C3/S3 - only ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED can be used for periodic advertising - - author: chegewara -*/ - -#include -#include - - -esp_ble_gap_ext_adv_params_t ext_adv_params_2M = { - .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED, - .interval_min = 0x40, - .interval_max = 0x40, - .channel_map = ADV_CHNL_ALL, - .own_addr_type = BLE_ADDR_TYPE_RANDOM, - .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, - .primary_phy = ESP_BLE_GAP_PHY_1M, - .max_skip = 0, - .secondary_phy = ESP_BLE_GAP_PHY_2M, - .sid = 1, - .scan_req_notif = false, -}; - -static uint8_t raw_scan_rsp_data_2m[] = { - 0x02, 0x01, 0x06, - 0x02, 0x0a, 0xeb, - 0x12, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', - 'D', 'V', '_', '2', 'M', 0X0 -}; - -static esp_ble_gap_periodic_adv_params_t periodic_adv_params = { - .interval_min = 0x320, // 1000 ms interval - .interval_max = 0x640, - .properties = 0, // Do not include TX power -}; - -static uint8_t periodic_adv_raw_data[] = { - 0x02, 0x01, 0x06, - 0x02, 0x0a, 0xeb, - 0x03, 0x03, 0xab, 0xcd, - 0x11, 0x09, 'E', 'S', 'P', '_', 'P', 'E', 'R', 'I', 'O', 'D', 'I', - 'C', '_', 'A', 'D', 'V' -}; - - -uint8_t addr_2m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x02}; - -BLEMultiAdvertising advert(1); // max number of advertisement data - -void setup() { - Serial.begin(115200); - Serial.println("Multi-Advertising..."); - - BLEDevice::init(""); - - advert.setAdvertisingParams(0, &ext_adv_params_2M); - advert.setAdvertisingData(0, sizeof(raw_scan_rsp_data_2m), &raw_scan_rsp_data_2m[0]); - advert.setInstanceAddress(0, addr_2m); - advert.setDuration(0, 0, 0); - - delay(100); - advert.start(); - advert.setPeriodicAdvertisingParams(0, &periodic_adv_params); - advert.setPeriodicAdvertisingData(0, sizeof(periodic_adv_raw_data), &periodic_adv_raw_data[0]); - advert.startPeriodicAdvertising(0); -} - -void loop() { - delay(2000); -} diff --git a/examples/arduino-ble5-advertising/test/README b/examples/arduino-ble5-advertising/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/arduino-ble5-advertising/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html From 0fbd91828cf9ad2cf38773a7caddddd6a47d6ea4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 17 Aug 2023 20:35:17 +0200 Subject: [PATCH 409/666] build 1510 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 6df8be120..111904478 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.07.01", + "version": "2023.08.01", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1481/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1510/framework-arduinoespressif32-release_v5.1-eeffb386ad.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1481/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1510/framework-arduinoespressif32-release_v5.1-eeffb386ad.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1481/framework-arduinoespressif32-release_v5.1-69cdc81680.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1510/framework-arduinoespressif32-release_v5.1-eeffb386ad.zip" }, "framework-espidf": { "type": "framework", From d1c31d2b5c355d17f09bc6bee1cacecc70775f7b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 18 Aug 2023 11:19:13 +0200 Subject: [PATCH 410/666] Create esp32-c6-devkitm-1.json --- boards/esp32-c6-devkitm-1.json | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 boards/esp32-c6-devkitm-1.json diff --git a/boards/esp32-c6-devkitm-1.json b/boards/esp32-c6-devkitm-1.json new file mode 100644 index 000000000..069d0d791 --- /dev/null +++ b/boards/esp32-c6-devkitm-1.json @@ -0,0 +1,30 @@ +{ + "build": { + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6", + "variant": "esp32c6" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-C6-DevKitM-1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitm-1/index.html", + "vendor": "Espressif" +} From 91e876ff31ec1e9d41f53313ea8873a033e0ec49 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 19 Aug 2023 15:44:20 +0200 Subject: [PATCH 411/666] "tasmota-metrics": ">=0.4.2" --- builder/frameworks/arduino.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 36cd206b5..ff1ce2946 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -79,7 +79,7 @@ def _get_installed_pip_packages(): deps = { "wheel": ">=0.35.1", "zopfli": ">=0.2.2", - "tasmota-metrics": ">=0.3.3" + "tasmota-metrics": ">=0.4.2" } installed_packages = _get_installed_pip_packages() From 9c620566e9d3d14fd97dbc1dba15dbdcde8c6939 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 19 Aug 2023 20:50:50 +0200 Subject: [PATCH 412/666] v0.4.3 --- builder/frameworks/arduino.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index ff1ce2946..94cd2f982 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -79,7 +79,7 @@ def _get_installed_pip_packages(): deps = { "wheel": ">=0.35.1", "zopfli": ">=0.2.2", - "tasmota-metrics": ">=0.4.2" + "tasmota-metrics": ">=0.4.3" } installed_packages = _get_installed_pip_packages() From be68be66ecfad17d2769639c9a0162ba235dce72 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:44:48 +0200 Subject: [PATCH 413/666] Switch IDF projects to a standalone GDB packages --- builder/main.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index 8b19773af..b3c231d47 100644 --- a/builder/main.py +++ b/builder/main.py @@ -229,7 +229,16 @@ def __fetch_fs_size(target, source, env): AS="%s-elf-as" % toolchain_arch, CC="%s-elf-gcc" % toolchain_arch, CXX="%s-elf-g++" % toolchain_arch, - GDB="%s-elf-gdb" % toolchain_arch, + GDB=join( + platform.get_package_dir( + "tool-riscv32-esp-elf-gdb" + if mcu in ("esp32c3", "esp32c6") + else "tool-xtensa-esp-elf-gdb" + ) + or "", + "bin", + "%s-elf-gdb" % toolchain_arch, + ) if env.get("PIOFRAMEWORK") == ["espidf"] else "%s-elf-gdb" % toolchain_arch, OBJCOPY=join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), RANLIB="%s-elf-gcc-ranlib" % toolchain_arch, SIZETOOL="%s-elf-size" % toolchain_arch, From 442fa483241cc10b76f83930504b54260ad476d5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:45:33 +0200 Subject: [PATCH 414/666] rm comment --- builder/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index b3c231d47..afff72327 100644 --- a/builder/main.py +++ b/builder/main.py @@ -458,7 +458,6 @@ def __fetch_fs_size(target, source, env): ] elif upload_protocol == "dfu": - # C:\Users\ROOT\AppData\Local\Arduino15\packages\arduino\tools\dfu-util\0.11.0-arduino5/dfu-util --device 0x2341:0x0070 -D C:\Users\ROOT\AppData\Local\Temp\arduino_build_789426/sketch_jul31a.ino.bin -Q hwids = board.get("build.hwids", [["0x2341", "0x0070"]]) vid = hwids[0][0] From 6893a3cfb9be25ffc84e8d229420eb2b6728fe0b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:47:18 +0200 Subject: [PATCH 415/666] Update espidf.py --- builder/frameworks/espidf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index dbd92ade3..143d9c275 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -27,6 +27,7 @@ import shutil import os import pkg_resources +import platform as sys_platform import click import semantic_version @@ -1109,6 +1110,9 @@ def _get_installed_pip_packages(python_exe_path): "esp-idf-kconfig": "~=1.2.0" } + if sys_platform.system() == "Darwin" and "arm" in sys_platform.machine().lower(): + deps["chardet"] = ">=3.0.2,<4" + python_exe_path = get_python_exe() installed_packages = _get_installed_pip_packages(python_exe_path) packages_to_install = [] From d53000494e1e304173b828e7ed70ec21b9a07d42 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:49:49 +0200 Subject: [PATCH 416/666] GDB packages 12x --- platform.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/platform.json b/platform.json index 111904478..49cadbebf 100644 --- a/platform.json +++ b/platform.json @@ -82,6 +82,18 @@ "optional": true, "owner": "platformio", "version": "~1.23500.0" + }, + "tool-xtensa-esp-elf-gdb": { + "type": "debugger", + "optional": true, + "owner": "espressif", + "version": "~12.1.0" + }, + "tool-riscv32-esp-elf-gdb": { + "type": "debugger", + "optional": true, + "owner": "espressif", + "version": "~12.1.0" }, "tool-esptoolpy": { "type": "uploader", From 03aa8990c9868c3fdaa2750345b506cb2bec26fc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:55:35 +0200 Subject: [PATCH 417/666] tool-riscv32-esp-elf-gdb for C2 too --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index afff72327..47c700b60 100644 --- a/builder/main.py +++ b/builder/main.py @@ -232,7 +232,7 @@ def __fetch_fs_size(target, source, env): GDB=join( platform.get_package_dir( "tool-riscv32-esp-elf-gdb" - if mcu in ("esp32c3", "esp32c6") + if mcu in ("esp32c2", "esp32c3", "esp32c6") else "tool-xtensa-esp-elf-gdb" ) or "", From 3fba6114cd86f47ab55cbfa93e87270ae744e3b9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:59:13 +0200 Subject: [PATCH 418/666] "platformio": ">=6.1.10" --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 49cadbebf..7faf52f19 100644 --- a/platform.json +++ b/platform.json @@ -12,7 +12,7 @@ "RISC-V" ], "engines": { - "platformio": ">=6.1.9" + "platformio": ">=6.1.10" }, "repository": { "type": "git", From e6508ac3ce75c69d575e6da5fb516d3366955e0c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Aug 2023 14:15:12 +0200 Subject: [PATCH 419/666] Update frameworks --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 7faf52f19..73372a71a 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1510/framework-arduinoespressif32-release_v5.1-eeffb386ad.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1551/framework-arduinoespressif32-ITEAD-release_v5.1-707b703985.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1510/framework-arduinoespressif32-release_v5.1-eeffb386ad.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1550/framework-arduinoespressif32-solo1-release_v5.1-707b703985.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1510/framework-arduinoespressif32-release_v5.1-eeffb386ad.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1548/framework-arduinoespressif32-release_v5.1-707b703985.zip" }, "framework-espidf": { "type": "framework", From 799c419e33fae047bcbd229217000d3cb9ac2c6c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Aug 2023 14:50:20 +0200 Subject: [PATCH 420/666] IDF 5.5.1 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 73372a71a..5dc43e014 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1551/framework-arduinoespressif32-ITEAD-release_v5.1-707b703985.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1548/framework-arduinoespressif32-release_v5.1-707b703985.zip" }, "framework-arduino-solo1": { "type": "framework", @@ -45,13 +45,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1548/framework-arduinoespressif32-release_v5.1-707b703985.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1551/framework-arduinoespressif32-ITEAD-release_v5.1-707b703985.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.0.20230722/esp-idf-v5.1.0.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.230820/esp-idf-v5.1.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From b3911f06d9cd0c3b58c19ce274dcb0ca93056449 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 30 Aug 2023 14:04:02 +0200 Subject: [PATCH 421/666] Use refactored Arduino ETH driver --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 5dc43e014..64643d91f 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1548/framework-arduinoespressif32-release_v5.1-707b703985.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1557/framework-arduinoespressif32-release_v5.1-707b703985.zip" }, "framework-arduino-solo1": { "type": "framework", From e1ab5489b2928b0e763532a2d284f4a4e207a1cb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 30 Aug 2023 14:38:54 +0200 Subject: [PATCH 422/666] new ETH for all frameworks --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 64643d91f..a00e64356 100644 --- a/platform.json +++ b/platform.json @@ -39,13 +39,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1550/framework-arduinoespressif32-solo1-release_v5.1-707b703985.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1559/framework-arduinoespressif32-solo1-release_v5.1-707b703985.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1551/framework-arduinoespressif32-ITEAD-release_v5.1-707b703985.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1558/framework-arduinoespressif32-ITEAD-release_v5.1-707b703985.zip" }, "framework-espidf": { "type": "framework", From 94dbda20588776962a80b9fc15079c0f1b036ee0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 31 Aug 2023 19:02:44 +0200 Subject: [PATCH 423/666] core 6.1.11 required from GDB --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index a00e64356..7bdc8b7d2 100644 --- a/platform.json +++ b/platform.json @@ -12,7 +12,7 @@ "RISC-V" ], "engines": { - "platformio": ">=6.1.10" + "platformio": ">=6.1.11" }, "repository": { "type": "git", From 916d192e635d92254af37f219f36399b28daa1f3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 2 Sep 2023 13:42:46 +0200 Subject: [PATCH 424/666] add c2 c6 --- examples/espidf-arduino-blink/platformio.ini | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index b92c49577..6b4558f92 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -17,8 +17,8 @@ monitor_speed = 115200 [env:esp32dev] board = esp32dev -[env:espea32] -board = espea32 - -[env:esp320] -board = esp320 +[env:esp32-c2-devkitm-1] +board = esp32-c2-devkitm-1 + +[env:esp32-c6-devkitc-1] +board = esp32-c6-devkitc-1 From b6bff82978ca1cd0625d93046ea7fd55d893f6e6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 4 Sep 2023 14:11:37 +0200 Subject: [PATCH 425/666] Update frameworks --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 7bdc8b7d2..84a0791c3 100644 --- a/platform.json +++ b/platform.json @@ -33,25 +33,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1557/framework-arduinoespressif32-release_v5.1-707b703985.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1568/framework-arduinoespressif32-release_v5.1-8dd5efbde4.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1559/framework-arduinoespressif32-solo1-release_v5.1-707b703985.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1570/framework-arduinoespressif32-solo1-release_v5.1-8dd5efbde4.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1558/framework-arduinoespressif32-ITEAD-release_v5.1-707b703985.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1569/framework-arduinoespressif32-ITEAD-release_v5.1-8dd5efbde4.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.230820/esp-idf-v5.1.1.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.230901/esp-idf-v5.1.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 8d59e4e367b97558708fc044778805f6891eab85 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 4 Sep 2023 14:24:51 +0200 Subject: [PATCH 426/666] revert to 1564 since patched Nimble does fail to compile with C2/C6/H2 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 84a0791c3..7a0517efb 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1568/framework-arduinoespressif32-release_v5.1-8dd5efbde4.zip" + "version": " https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1564/framework-arduinoespressif32-release_v5.1-8dd5efbde4.zip" }, "framework-arduino-solo1": { "type": "framework", From fdc48a5014a91ca61a16c3aa886548d3e70dfd0c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 4 Sep 2023 16:15:37 +0200 Subject: [PATCH 427/666] build 1571 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 7a0517efb..a6a201fd4 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": " https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1564/framework-arduinoespressif32-release_v5.1-8dd5efbde4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1571/framework-arduinoespressif32-v5.1.1.230820-707b703985.zip" }, "framework-arduino-solo1": { "type": "framework", From 8bbf4fe3492c7daff58d1046c7ac607defba2649 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 5 Sep 2023 13:40:00 +0200 Subject: [PATCH 428/666] Latest IDF 5.1 and Arduino --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index a6a201fd4..a6917a01d 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1571/framework-arduinoespressif32-v5.1.1.230820-707b703985.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1576/framework-arduinoespressif32-release_v5.1-5f7e313159.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1570/framework-arduinoespressif32-solo1-release_v5.1-8dd5efbde4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1577/framework-arduinoespressif32-solo1-release_v5.1-5f7e313159.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1569/framework-arduinoespressif32-ITEAD-release_v5.1-8dd5efbde4.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1578/framework-arduinoespressif32-ITEAD-release_v5.1-5f7e313159.zip" }, "framework-espidf": { "type": "framework", From 0d8c95dc6945cf8aa5cd07b51f9329c815702005 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 6 Sep 2023 14:28:13 +0200 Subject: [PATCH 429/666] IPv6 fix --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index a6917a01d..1cae3e952 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1576/framework-arduinoespressif32-release_v5.1-5f7e313159.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1587/framework-arduinoespressif32-release_v5.1-5f7e313159.zip" }, "framework-arduino-solo1": { "type": "framework", From 7406ae3ace61ff82231a9d6498b430de29f40e7e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 6 Sep 2023 19:10:41 +0200 Subject: [PATCH 430/666] Update platform.json --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 1cae3e952..5d2ca21a5 100644 --- a/platform.json +++ b/platform.json @@ -39,13 +39,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1577/framework-arduinoespressif32-solo1-release_v5.1-5f7e313159.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1588/framework-arduinoespressif32-solo1-release_v5.1-5f7e313159.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1578/framework-arduinoespressif32-ITEAD-release_v5.1-5f7e313159.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1589/framework-arduinoespressif32-ITEAD-release_v5.1-5f7e313159.zip" }, "framework-espidf": { "type": "framework", From bae99151f53f01a8f7f7d9a34b9f539b95351eea Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 7 Sep 2023 17:32:30 +0200 Subject: [PATCH 431/666] Add a warning if an IDF component doesn't register any source files --- builder/frameworks/espidf.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 143d9c275..4063b3127 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -609,7 +609,11 @@ def _fix_component_relative_include(config, build_flags, source_index): def prepare_build_envs(config, default_env, debug_allowed=True): build_envs = [] - target_compile_groups = config.get("compileGroups") + target_compile_groups = config.get("compileGroups", []) + if not target_compile_groups: + print("Warning! The `%s` component doesn't register any source files. " + "Check if sources are set in component's CMakeLists.txt!" % config["name"] + ) is_build_type_debug = "debug" in env.GetBuildType() and debug_allowed for cg in target_compile_groups: From 28361814946c9d7822d7ec2b49167a0e1f2ff184 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 21 Sep 2023 20:43:57 +0200 Subject: [PATCH 432/666] build 1612 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 5d2ca21a5..16f9a2b65 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1587/framework-arduinoespressif32-release_v5.1-5f7e313159.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1612/framework-arduinoespressif32-release_v5.1-fab1aca036.zip" }, "framework-arduino-solo1": { "type": "framework", From 7cd569b54406fab9981f3df31bf606df575a34b6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 21 Sep 2023 21:24:20 +0200 Subject: [PATCH 433/666] IDF v5.1.1.230920 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 16f9a2b65..497adba22 100644 --- a/platform.json +++ b/platform.json @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.230901/esp-idf-v5.1.1.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.230920/esp-idf-v5.1.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From cd7eac846c79b9fa3b6f38bf708902e1ecda8ff4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 23 Sep 2023 13:46:15 +0200 Subject: [PATCH 434/666] build 1614 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 497adba22..8c98715e5 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1612/framework-arduinoespressif32-release_v5.1-fab1aca036.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1614/framework-arduinoespressif32-release_v5.1-fab1aca036.zip" }, "framework-arduino-solo1": { "type": "framework", From aff0c3a1f5ebe2567a4cbf183c758cc1478d7edc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:36:01 +0200 Subject: [PATCH 435/666] esptool v4.7 dev --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 8c98715e5..d4f5802cd 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.6.2/esptool-4.6.2.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev/esptool-4.7.0.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From aa63977133d0bbd3bddd97796eda2f7865219199 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 1 Oct 2023 21:18:22 +0200 Subject: [PATCH 436/666] Delete examples/espidf-storage-spiffs directory --- examples/espidf-storage-spiffs/.gitignore | 1 - examples/espidf-storage-spiffs/CMakeLists.txt | 6 - examples/espidf-storage-spiffs/README.md | 24 ---- examples/espidf-storage-spiffs/data/hello.txt | 1 - examples/espidf-storage-spiffs/include/README | 39 ------ examples/espidf-storage-spiffs/lib/README | 46 ------- .../partitions_example.csv | 6 - examples/espidf-storage-spiffs/platformio.ini | 15 --- .../espidf-storage-spiffs/sdkconfig.defaults | 3 - .../espidf-storage-spiffs/src/CMakeLists.txt | 2 - .../src/Kconfig.projbuild | 9 -- .../src/spiffs_example_main.c | 127 ------------------ examples/espidf-storage-spiffs/test/README | 11 -- 13 files changed, 290 deletions(-) delete mode 100644 examples/espidf-storage-spiffs/.gitignore delete mode 100644 examples/espidf-storage-spiffs/CMakeLists.txt delete mode 100644 examples/espidf-storage-spiffs/README.md delete mode 100644 examples/espidf-storage-spiffs/data/hello.txt delete mode 100644 examples/espidf-storage-spiffs/include/README delete mode 100644 examples/espidf-storage-spiffs/lib/README delete mode 100644 examples/espidf-storage-spiffs/partitions_example.csv delete mode 100644 examples/espidf-storage-spiffs/platformio.ini delete mode 100644 examples/espidf-storage-spiffs/sdkconfig.defaults delete mode 100644 examples/espidf-storage-spiffs/src/CMakeLists.txt delete mode 100644 examples/espidf-storage-spiffs/src/Kconfig.projbuild delete mode 100644 examples/espidf-storage-spiffs/src/spiffs_example_main.c delete mode 100644 examples/espidf-storage-spiffs/test/README diff --git a/examples/espidf-storage-spiffs/.gitignore b/examples/espidf-storage-spiffs/.gitignore deleted file mode 100644 index 03f4a3c19..000000000 --- a/examples/espidf-storage-spiffs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pio diff --git a/examples/espidf-storage-spiffs/CMakeLists.txt b/examples/espidf-storage-spiffs/CMakeLists.txt deleted file mode 100644 index 1894b31ca..000000000 --- a/examples/espidf-storage-spiffs/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(spiffs) diff --git a/examples/espidf-storage-spiffs/README.md b/examples/espidf-storage-spiffs/README.md deleted file mode 100644 index 214f9ba67..000000000 --- a/examples/espidf-storage-spiffs/README.md +++ /dev/null @@ -1,24 +0,0 @@ -How to build PlatformIO based project -===================================== - -1. [Install PlatformIO Core](https://docs.platformio.org/page/core.html) -2. Download [development platform with examples](https://github.com/platformio/platform-espressif32/archive/develop.zip) -3. Extract ZIP archive -4. Run these commands: - -```shell -# Change directory to example -$ cd platform-espressif32/examples/espidf-storage-spiffs - -# Build project -$ pio run - -# Upload firmware -$ pio run --target upload - -# Upload SPIFFS image -$ pio run --target uploadfs - -# Clean build files -$ pio run --target clean -``` diff --git a/examples/espidf-storage-spiffs/data/hello.txt b/examples/espidf-storage-spiffs/data/hello.txt deleted file mode 100644 index 5a8367719..000000000 --- a/examples/espidf-storage-spiffs/data/hello.txt +++ /dev/null @@ -1 +0,0 @@ -Hello World from SPIFFS. diff --git a/examples/espidf-storage-spiffs/include/README b/examples/espidf-storage-spiffs/include/README deleted file mode 100644 index 194dcd432..000000000 --- a/examples/espidf-storage-spiffs/include/README +++ /dev/null @@ -1,39 +0,0 @@ - -This directory is intended for project header files. - -A header file is a file containing C declarations and macro definitions -to be shared between several project source files. You request the use of a -header file in your project source file (C, C++, etc) located in `src` folder -by including it, with the C preprocessing directive `#include'. - -```src/main.c - -#include "header.h" - -int main (void) -{ - ... -} -``` - -Including a header file produces the same results as copying the header file -into each source file that needs it. Such copying would be time-consuming -and error-prone. With a header file, the related declarations appear -in only one place. If they need to be changed, they can be changed in one -place, and programs that include the header file will automatically use the -new version when next recompiled. The header file eliminates the labor of -finding and changing all the copies as well as the risk that a failure to -find one copy will result in inconsistencies within a program. - -In C, the usual convention is to give header files names that end with `.h'. -It is most portable to use only letters, digits, dashes, and underscores in -header file names, and at most one dot. - -Read more about using header files in official GCC documentation: - -* Include Syntax -* Include Operation -* Once-Only Headers -* Computed Includes - -https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-storage-spiffs/lib/README b/examples/espidf-storage-spiffs/lib/README deleted file mode 100644 index 6debab1e8..000000000 --- a/examples/espidf-storage-spiffs/lib/README +++ /dev/null @@ -1,46 +0,0 @@ - -This directory is intended for project specific (private) libraries. -PlatformIO will compile them to static libraries and link into executable file. - -The source code of each library should be placed in a an own separate directory -("lib/your_library_name/[here are source files]"). - -For example, see a structure of the following two libraries `Foo` and `Bar`: - -|--lib -| | -| |--Bar -| | |--docs -| | |--examples -| | |--src -| | |- Bar.c -| | |- Bar.h -| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html -| | -| |--Foo -| | |- Foo.c -| | |- Foo.h -| | -| |- README --> THIS FILE -| -|- platformio.ini -|--src - |- main.c - -and a contents of `src/main.c`: -``` -#include -#include - -int main (void) -{ - ... -} - -``` - -PlatformIO Library Dependency Finder will find automatically dependent -libraries scanning project source files. - -More information about PlatformIO Library Dependency Finder -- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-storage-spiffs/partitions_example.csv b/examples/espidf-storage-spiffs/partitions_example.csv deleted file mode 100644 index 92db904e0..000000000 --- a/examples/espidf-storage-spiffs/partitions_example.csv +++ /dev/null @@ -1,6 +0,0 @@ -# Name, Type, SubType, Offset, Size, Flags -# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap -nvs, data, nvs, 0x9000, 0x6000, -phy_init, data, phy, 0xf000, 0x1000, -factory, app, factory, 0x10000, 1M, -spiffs, data, spiffs, , 0xF0000, diff --git a/examples/espidf-storage-spiffs/platformio.ini b/examples/espidf-storage-spiffs/platformio.ini deleted file mode 100644 index 9185e89ba..000000000 --- a/examples/espidf-storage-spiffs/platformio.ini +++ /dev/null @@ -1,15 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[env:esp32dev] -platform = espressif32 -framework = espidf -board = esp32dev -monitor_speed = 115200 -board_build.partitions = partitions_example.csv diff --git a/examples/espidf-storage-spiffs/sdkconfig.defaults b/examples/espidf-storage-spiffs/sdkconfig.defaults deleted file mode 100644 index b9bb0c0a5..000000000 --- a/examples/espidf-storage-spiffs/sdkconfig.defaults +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv" diff --git a/examples/espidf-storage-spiffs/src/CMakeLists.txt b/examples/espidf-storage-spiffs/src/CMakeLists.txt deleted file mode 100644 index c480915ab..000000000 --- a/examples/espidf-storage-spiffs/src/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "spiffs_example_main.c" - INCLUDE_DIRS ".") diff --git a/examples/espidf-storage-spiffs/src/Kconfig.projbuild b/examples/espidf-storage-spiffs/src/Kconfig.projbuild deleted file mode 100644 index eadd67909..000000000 --- a/examples/espidf-storage-spiffs/src/Kconfig.projbuild +++ /dev/null @@ -1,9 +0,0 @@ -menu "SPIFFS Example menu" - - config EXAMPLE_SPIFFS_CHECK_ON_START - bool "Run SPIFFS_check on every start-up" - default y - help - If this config item is set, esp_spiffs_check() will be run on every start-up. - Slow on large flash sizes. -endmenu diff --git a/examples/espidf-storage-spiffs/src/spiffs_example_main.c b/examples/espidf-storage-spiffs/src/spiffs_example_main.c deleted file mode 100644 index 32cc17686..000000000 --- a/examples/espidf-storage-spiffs/src/spiffs_example_main.c +++ /dev/null @@ -1,127 +0,0 @@ -/* SPIFFS filesystem example. - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include "esp_err.h" -#include "esp_log.h" -#include "esp_spiffs.h" - -static const char *TAG = "example"; - -void app_main(void) -{ - ESP_LOGI(TAG, "Initializing SPIFFS"); - - esp_vfs_spiffs_conf_t conf = { - .base_path = "/spiffs", - .partition_label = NULL, - .max_files = 5, - .format_if_mount_failed = true - }; - - // Use settings defined above to initialize and mount SPIFFS filesystem. - // Note: esp_vfs_spiffs_register is an all-in-one convenience function. - esp_err_t ret = esp_vfs_spiffs_register(&conf); - - if (ret != ESP_OK) { - if (ret == ESP_FAIL) { - ESP_LOGE(TAG, "Failed to mount or format filesystem"); - } else if (ret == ESP_ERR_NOT_FOUND) { - ESP_LOGE(TAG, "Failed to find SPIFFS partition"); - } else { - ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); - } - return; - } - -#ifdef CONFIG_EXAMPLE_SPIFFS_CHECK_ON_START - ESP_LOGI(TAG, "Performing SPIFFS_check()."); - ret = esp_spiffs_check(conf.partition_label); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "SPIFFS_check() failed (%s)", esp_err_to_name(ret)); - return; - } else { - ESP_LOGI(TAG, "SPIFFS_check() successful"); - } -#endif - - size_t total = 0, used = 0; - ret = esp_spiffs_info(conf.partition_label, &total, &used); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s). Formatting...", esp_err_to_name(ret)); - esp_spiffs_format(conf.partition_label); - return; - } else { - ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used); - } - -# - // Check consistency of reported partiton size info. - if (used > total) { - ESP_LOGW(TAG, "Number of used bytes cannot be larger than total. Performing SPIFFS_check()."); - ret = esp_spiffs_check(conf.partition_label); - // Could be also used to mend broken files, to clean unreferenced pages, etc. - // More info at https://github.com/pellepl/spiffs/wiki/FAQ#powerlosses-contd-when-should-i-run-spiffs_check - if (ret != ESP_OK) { - ESP_LOGE(TAG, "SPIFFS_check() failed (%s)", esp_err_to_name(ret)); - return; - } else { - ESP_LOGI(TAG, "SPIFFS_check() successful"); - } - } - - // Use POSIX and C standard library functions to work with files. - // First create a file. - ESP_LOGI(TAG, "Opening file"); - FILE* f = fopen("/spiffs/hello.txt", "w"); - if (f == NULL) { - ESP_LOGE(TAG, "Failed to open file for writing"); - return; - } - fprintf(f, "Hello World!\n"); - fclose(f); - ESP_LOGI(TAG, "File written"); - - // Check if destination file exists before renaming - struct stat st; - if (stat("/spiffs/foo.txt", &st) == 0) { - // Delete it if it exists - unlink("/spiffs/foo.txt"); - } - - // Rename original file - ESP_LOGI(TAG, "Renaming file"); - if (rename("/spiffs/hello.txt", "/spiffs/foo.txt") != 0) { - ESP_LOGE(TAG, "Rename failed"); - return; - } - - // Open renamed file for reading - ESP_LOGI(TAG, "Reading file"); - f = fopen("/spiffs/foo.txt", "r"); - if (f == NULL) { - ESP_LOGE(TAG, "Failed to open file for reading"); - return; - } - char line[64]; - fgets(line, sizeof(line), f); - fclose(f); - // strip newline - char* pos = strchr(line, '\n'); - if (pos) { - *pos = '\0'; - } - ESP_LOGI(TAG, "Read from file: '%s'", line); - - // All done, unmount partition and disable SPIFFS - esp_vfs_spiffs_unregister(conf.partition_label); - ESP_LOGI(TAG, "SPIFFS unmounted"); -} diff --git a/examples/espidf-storage-spiffs/test/README b/examples/espidf-storage-spiffs/test/README deleted file mode 100644 index df5066e64..000000000 --- a/examples/espidf-storage-spiffs/test/README +++ /dev/null @@ -1,11 +0,0 @@ - -This directory is intended for PIO Unit Testing and project tests. - -Unit Testing is a software testing method by which individual units of -source code, sets of one or more MCU program modules together with associated -control data, usage procedures, and operating procedures, are tested to -determine whether they are fit for use. Unit testing finds problems early -in the development cycle. - -More information about PIO Unit Testing: -- https://docs.platformio.org/page/plus/unit-testing.html From 95c238048872e75220868102f8c121f276db2c5f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 1 Oct 2023 21:26:48 +0200 Subject: [PATCH 437/666] Update sdkconfig.defaults --- examples/espidf-arduino-blink/sdkconfig.defaults | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index 1af06b975..e46aac67f 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -3,3 +3,5 @@ CONFIG_AUTOSTART_ARDUINO=y CONFIG_FREERTOS_HZ=1000 CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y From 4bde8644a11d5ba7ac4fcfe2e4cf0596b784c0f4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 1 Oct 2023 21:28:07 +0200 Subject: [PATCH 438/666] Update sdkconfig.defaults --- examples/espidf-arduino-wifiscan/sdkconfig.defaults | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/espidf-arduino-wifiscan/sdkconfig.defaults b/examples/espidf-arduino-wifiscan/sdkconfig.defaults index f67b30bf1..65a147e68 100644 --- a/examples/espidf-arduino-wifiscan/sdkconfig.defaults +++ b/examples/espidf-arduino-wifiscan/sdkconfig.defaults @@ -3,6 +3,8 @@ CONFIG_AUTOSTART_ARDUINO=y CONFIG_FREERTOS_HZ=1000 CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y # Example config CONFIG_EXAMPLE_WIFI_SSID="MYSSID" CONFIG_EXAMPLE_WIFI_PASSWORD="MYPASS" From a4178c513693ee71ce2b12175acd76986db02365 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:13:40 +0200 Subject: [PATCH 439/666] add espidf-arduino-blink to CI --- .github/workflows/examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index c30c8229e..8b04190f5 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -18,6 +18,7 @@ jobs: - "examples/arduino-rmt-blink" - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" + - "examples/espidf-arduino-blink" - "examples/espidf-blink" - "examples/espidf-coap-server" - "examples/espidf-exceptions" From 06aa5ba26e2d434b0baa7ac92faaf93903a6ad0f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:20:27 +0200 Subject: [PATCH 440/666] Create .keep.me --- examples/espidf-arduino-blink/managed_components/.keep.me | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/espidf-arduino-blink/managed_components/.keep.me diff --git a/examples/espidf-arduino-blink/managed_components/.keep.me b/examples/espidf-arduino-blink/managed_components/.keep.me new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/espidf-arduino-blink/managed_components/.keep.me @@ -0,0 +1 @@ + From 724990051e29a58ab7adb7cd9e5cc259a5d7b0f2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:22:39 +0200 Subject: [PATCH 441/666] Update CMakeLists.txt --- examples/espidf-arduino-blink/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/espidf-arduino-blink/CMakeLists.txt b/examples/espidf-arduino-blink/CMakeLists.txt index 650d1b97d..0066d3962 100644 --- a/examples/espidf-arduino-blink/CMakeLists.txt +++ b/examples/espidf-arduino-blink/CMakeLists.txt @@ -1,3 +1,4 @@ cmake_minimum_required(VERSION 3.16.0) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(espidf-arduino-wifiscan) +list(APPEND EXTRA_COMPONENT_DIRS managed_components) +project(espidf-arduino-blink) From ce42a2e1d755cf2a32475a8c8f74de4efb67c0f7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:24:27 +0200 Subject: [PATCH 442/666] Create idf_component.yml --- .../src/idf_component.yml | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 examples/espidf-arduino-blink/src/idf_component.yml diff --git a/examples/espidf-arduino-blink/src/idf_component.yml b/examples/espidf-arduino-blink/src/idf_component.yml new file mode 100644 index 000000000..19907c020 --- /dev/null +++ b/examples/espidf-arduino-blink/src/idf_component.yml @@ -0,0 +1,51 @@ +dependencies: + # Required IDF version + idf: ">=4.4" + + esp_littlefs: + git: https://github.com/joltwallet/esp_littlefs.git + version: lfs2.8 + + mdns: "^1.2.1" + # nghttp: "^1.50.0" + # esp_jpeg: "^1.0.4" + # esp-dsp: "^1.2.0" + # esp-sr: "^1.0.3" + # esp32-camera: "^2.0.3" + # esp-dl: + # git: https://github.com/espressif/esp-dl.git + # arduino: + # path: components/arduino + + # # Defining a dependency from the registry: + # # https://components.espressif.com/component/example/cmp + # example/cmp: "^3.3.3" # Automatically update minor releases + # + # # Other ways to define dependencies + # + # # For components maintained by Espressif only name can be used. + # # Same as `espressif/cmp` + # component: "~1.0.0" # Automatically update bugfix releases + # + # # Or in a longer form with extra parameters + # component2: + # version: ">=2.0.0" + # + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't have an effect for the `main` component. + # # All dependencies of `main` are public by default. + # public: true + # + # # For components hosted on non-default registry: + # service_url: "https://componentregistry.company.com" + # + # # For components in git repository: + # test_component: + # path: test_component + # git: ssh://git@gitlab.com/user/components.git + # + # # For test projects during component development + # # components can be used from a local directory + # # with relative or absolute path + # some_local_component: + # path: ../../projects/component From 0c3d7a9cd3e3c98d1a1f6ec1638a660540d1197b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:38:33 +0200 Subject: [PATCH 443/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 6b4558f92..223cc469d 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -14,11 +14,11 @@ build_flags = -D CONFIG_BLINK_GPIO=2 monitor_speed = 115200 -[env:esp32dev] -board = esp32dev +;[env:esp32dev] +;board = esp32dev -[env:esp32-c2-devkitm-1] -board = esp32-c2-devkitm-1 +;[env:esp32-c2-devkitm-1] +;board = esp32-c2-devkitm-1 [env:esp32-c6-devkitc-1] board = esp32-c6-devkitc-1 From cfa16d2bf7f394a7f87a1665035fe07bb4159e19 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:45:41 +0200 Subject: [PATCH 444/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 223cc469d..64f2569f6 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -14,11 +14,11 @@ build_flags = -D CONFIG_BLINK_GPIO=2 monitor_speed = 115200 -;[env:esp32dev] -;board = esp32dev +[env:esp32dev] +board = esp32dev ;[env:esp32-c2-devkitm-1] ;board = esp32-c2-devkitm-1 -[env:esp32-c6-devkitc-1] -board = esp32-c6-devkitc-1 +;[env:esp32-c6-devkitc-1] +;board = esp32-c6-devkitc-1 From 674236821169ad8936f4d0d62be45df368c17d53 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 11:48:04 +0200 Subject: [PATCH 445/666] Update sdkconfig.defaults --- examples/espidf-arduino-blink/sdkconfig.defaults | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index e46aac67f..a8f9a5467 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -5,3 +5,5 @@ CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y From 9b5478f0671fd688c199ddad5163b7fd51cc0564 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 11:49:55 +0200 Subject: [PATCH 446/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 64f2569f6..223cc469d 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -14,11 +14,11 @@ build_flags = -D CONFIG_BLINK_GPIO=2 monitor_speed = 115200 -[env:esp32dev] -board = esp32dev +;[env:esp32dev] +;board = esp32dev ;[env:esp32-c2-devkitm-1] ;board = esp32-c2-devkitm-1 -;[env:esp32-c6-devkitc-1] -;board = esp32-c6-devkitc-1 +[env:esp32-c6-devkitc-1] +board = esp32-c6-devkitc-1 From 1f97a48fb7ff9b4758f48d5616def53d6f31cb06 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 11:52:57 +0200 Subject: [PATCH 447/666] Update sdkconfig.defaults --- examples/espidf-arduino-wifiscan/sdkconfig.defaults | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/espidf-arduino-wifiscan/sdkconfig.defaults b/examples/espidf-arduino-wifiscan/sdkconfig.defaults index 65a147e68..b902509e1 100644 --- a/examples/espidf-arduino-wifiscan/sdkconfig.defaults +++ b/examples/espidf-arduino-wifiscan/sdkconfig.defaults @@ -5,6 +5,8 @@ CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y # Example config CONFIG_EXAMPLE_WIFI_SSID="MYSSID" CONFIG_EXAMPLE_WIFI_PASSWORD="MYPASS" From e91fafd5c10d33c343234fc957decf6a012c44fa Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 11:58:45 +0200 Subject: [PATCH 448/666] Update sdkconfig.defaults --- examples/espidf-arduino-wifiscan/sdkconfig.defaults | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/espidf-arduino-wifiscan/sdkconfig.defaults b/examples/espidf-arduino-wifiscan/sdkconfig.defaults index b902509e1..ad8548abb 100644 --- a/examples/espidf-arduino-wifiscan/sdkconfig.defaults +++ b/examples/espidf-arduino-wifiscan/sdkconfig.defaults @@ -6,7 +6,6 @@ CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y # Example config CONFIG_EXAMPLE_WIFI_SSID="MYSSID" CONFIG_EXAMPLE_WIFI_PASSWORD="MYPASS" From ed0525ba5d7eadf7a99edf0185eac5b4219d9043 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 12:02:20 +0200 Subject: [PATCH 449/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 223cc469d..3a2fcf41c 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -19,6 +19,6 @@ monitor_speed = 115200 ;[env:esp32-c2-devkitm-1] ;board = esp32-c2-devkitm-1 - -[env:esp32-c6-devkitc-1] -board = esp32-c6-devkitc-1 + +[env:esp32-c6-devkitm-1] +board = esp32-c6-devkitm-1 From 6b6a6eb3d73dc1a1b44b5b71ffaea0aa5940152a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 12:04:21 +0200 Subject: [PATCH 450/666] Update sdkconfig.defaults --- examples/espidf-arduino-wifiscan/sdkconfig.defaults | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/espidf-arduino-wifiscan/sdkconfig.defaults b/examples/espidf-arduino-wifiscan/sdkconfig.defaults index ad8548abb..b902509e1 100644 --- a/examples/espidf-arduino-wifiscan/sdkconfig.defaults +++ b/examples/espidf-arduino-wifiscan/sdkconfig.defaults @@ -6,6 +6,7 @@ CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y # Example config CONFIG_EXAMPLE_WIFI_SSID="MYSSID" CONFIG_EXAMPLE_WIFI_PASSWORD="MYPASS" From 4ec4ca99776c69d72659a02348f4ba31d5dc0910 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 12:10:21 +0200 Subject: [PATCH 451/666] update mklittlefs --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index d4f5802cd..49b226d7f 100644 --- a/platform.json +++ b/platform.json @@ -119,8 +119,8 @@ }, "tool-mklittlefs": { "type": "uploader", - "owner": "platformio", - "version": "~1.203.0" + "owner": "tasmota", + "version": "^3.2.0" }, "tool-mkfatfs": { "type": "uploader", From cebe060fce128a31c7b046d7794d4037da80887a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 12:12:25 +0200 Subject: [PATCH 452/666] rm travis --- examples/espidf-arduino-blink/.travis.yml | 67 -------------------- examples/espidf-arduino-wifiscan/.travis.yml | 67 -------------------- examples/espidf-blink/.travis.yml | 67 -------------------- examples/espidf-coap-server/.travis.yml | 67 -------------------- examples/espidf-exceptions/.travis.yml | 67 -------------------- examples/espidf-hello-world/.travis.yml | 67 -------------------- examples/espidf-http-request/.travis.yml | 67 -------------------- examples/espidf-peripherals-uart/.travis.yml | 67 -------------------- examples/espidf-peripherals-usb/.travis.yml | 67 -------------------- examples/espidf-storage-sdcard/.travis.yml | 67 -------------------- 10 files changed, 670 deletions(-) delete mode 100644 examples/espidf-arduino-blink/.travis.yml delete mode 100644 examples/espidf-arduino-wifiscan/.travis.yml delete mode 100644 examples/espidf-blink/.travis.yml delete mode 100644 examples/espidf-coap-server/.travis.yml delete mode 100644 examples/espidf-exceptions/.travis.yml delete mode 100644 examples/espidf-hello-world/.travis.yml delete mode 100644 examples/espidf-http-request/.travis.yml delete mode 100644 examples/espidf-peripherals-uart/.travis.yml delete mode 100644 examples/espidf-peripherals-usb/.travis.yml delete mode 100644 examples/espidf-storage-sdcard/.travis.yml diff --git a/examples/espidf-arduino-blink/.travis.yml b/examples/espidf-arduino-blink/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-arduino-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-arduino-wifiscan/.travis.yml b/examples/espidf-arduino-wifiscan/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-arduino-wifiscan/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-blink/.travis.yml b/examples/espidf-blink/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-blink/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-coap-server/.travis.yml b/examples/espidf-coap-server/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-coap-server/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-exceptions/.travis.yml b/examples/espidf-exceptions/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-exceptions/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-hello-world/.travis.yml b/examples/espidf-hello-world/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-hello-world/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-http-request/.travis.yml b/examples/espidf-http-request/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-http-request/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-peripherals-uart/.travis.yml b/examples/espidf-peripherals-uart/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-peripherals-uart/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-peripherals-usb/.travis.yml b/examples/espidf-peripherals-usb/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-peripherals-usb/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-storage-sdcard/.travis.yml b/examples/espidf-storage-sdcard/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/examples/espidf-storage-sdcard/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N From 5d94517b97149548b620a593a22aeb439c671693 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 12:24:02 +0200 Subject: [PATCH 453/666] add example --- examples/espidf-arduino-littlefs/.gitignore | 2 + .../espidf-arduino-littlefs/CMakeLists.txt | 4 + examples/espidf-arduino-littlefs/README.md | 1 + .../espidf-arduino-littlefs/data/file1.txt | 1 + .../data/testfolder/test2.txt | 1 + .../espidf-arduino-littlefs/include/README | 39 +++ examples/espidf-arduino-littlefs/lib/README | 46 +++ .../littlefsbuilder.py | 3 + .../managed_components/.keep.me | 0 .../partitions_custom.csv | 6 + .../espidf-arduino-littlefs/platformio.ini | 19 ++ .../sdkconfig.defaults | 9 + .../src/CMakeLists.txt | 6 + .../src/idf_component.yml | 51 ++++ examples/espidf-arduino-littlefs/src/main.cpp | 282 ++++++++++++++++++ 15 files changed, 470 insertions(+) create mode 100644 examples/espidf-arduino-littlefs/.gitignore create mode 100644 examples/espidf-arduino-littlefs/CMakeLists.txt create mode 100644 examples/espidf-arduino-littlefs/README.md create mode 100644 examples/espidf-arduino-littlefs/data/file1.txt create mode 100644 examples/espidf-arduino-littlefs/data/testfolder/test2.txt create mode 100644 examples/espidf-arduino-littlefs/include/README create mode 100644 examples/espidf-arduino-littlefs/lib/README create mode 100644 examples/espidf-arduino-littlefs/littlefsbuilder.py create mode 100644 examples/espidf-arduino-littlefs/managed_components/.keep.me create mode 100644 examples/espidf-arduino-littlefs/partitions_custom.csv create mode 100644 examples/espidf-arduino-littlefs/platformio.ini create mode 100644 examples/espidf-arduino-littlefs/sdkconfig.defaults create mode 100644 examples/espidf-arduino-littlefs/src/CMakeLists.txt create mode 100644 examples/espidf-arduino-littlefs/src/idf_component.yml create mode 100644 examples/espidf-arduino-littlefs/src/main.cpp diff --git a/examples/espidf-arduino-littlefs/.gitignore b/examples/espidf-arduino-littlefs/.gitignore new file mode 100644 index 000000000..b9f3806a2 --- /dev/null +++ b/examples/espidf-arduino-littlefs/.gitignore @@ -0,0 +1,2 @@ +.pio +.vscode diff --git a/examples/espidf-arduino-littlefs/CMakeLists.txt b/examples/espidf-arduino-littlefs/CMakeLists.txt new file mode 100644 index 000000000..f5c097f0f --- /dev/null +++ b/examples/espidf-arduino-littlefs/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16.0) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +list(APPEND EXTRA_COMPONENT_DIRS managed_components) +project(espidf-arduino-littlefs) \ No newline at end of file diff --git a/examples/espidf-arduino-littlefs/README.md b/examples/espidf-arduino-littlefs/README.md new file mode 100644 index 000000000..8e58b4a04 --- /dev/null +++ b/examples/espidf-arduino-littlefs/README.md @@ -0,0 +1 @@ +# Arduino_IDF_LittleFS diff --git a/examples/espidf-arduino-littlefs/data/file1.txt b/examples/espidf-arduino-littlefs/data/file1.txt new file mode 100644 index 000000000..7c4a013e5 --- /dev/null +++ b/examples/espidf-arduino-littlefs/data/file1.txt @@ -0,0 +1 @@ +aaa \ No newline at end of file diff --git a/examples/espidf-arduino-littlefs/data/testfolder/test2.txt b/examples/espidf-arduino-littlefs/data/testfolder/test2.txt new file mode 100644 index 000000000..01f02e32c --- /dev/null +++ b/examples/espidf-arduino-littlefs/data/testfolder/test2.txt @@ -0,0 +1 @@ +bbb \ No newline at end of file diff --git a/examples/espidf-arduino-littlefs/include/README b/examples/espidf-arduino-littlefs/include/README new file mode 100644 index 000000000..194dcd432 --- /dev/null +++ b/examples/espidf-arduino-littlefs/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-arduino-littlefs/lib/README b/examples/espidf-arduino-littlefs/lib/README new file mode 100644 index 000000000..6debab1e8 --- /dev/null +++ b/examples/espidf-arduino-littlefs/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-arduino-littlefs/littlefsbuilder.py b/examples/espidf-arduino-littlefs/littlefsbuilder.py new file mode 100644 index 000000000..7adbd6f96 --- /dev/null +++ b/examples/espidf-arduino-littlefs/littlefsbuilder.py @@ -0,0 +1,3 @@ +Import("env") +platform = env.PioPlatform() +env.Replace( MKSPIFFSTOOL=platform.get_package_dir("tool-mklittlefs") + '/mklittlefs' ) # PlatformIO now believes it has actually created a SPIFFS diff --git a/examples/espidf-arduino-littlefs/managed_components/.keep.me b/examples/espidf-arduino-littlefs/managed_components/.keep.me new file mode 100644 index 000000000..e69de29bb diff --git a/examples/espidf-arduino-littlefs/partitions_custom.csv b/examples/espidf-arduino-littlefs/partitions_custom.csv new file mode 100644 index 000000000..643161620 --- /dev/null +++ b/examples/espidf-arduino-littlefs/partitions_custom.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x80000, +app1, app, ota_1, 0x90000, 0x110000, +spiffs, data, spiffs, 0x1A0000,0x260000, diff --git a/examples/espidf-arduino-littlefs/platformio.ini b/examples/espidf-arduino-littlefs/platformio.ini new file mode 100644 index 000000000..6f30eba07 --- /dev/null +++ b/examples/espidf-arduino-littlefs/platformio.ini @@ -0,0 +1,19 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env] +platform = espressif32 +framework = arduino, espidf +monitor_speed = 115200 + +[env:esp32-s3] +board = esp32-s3-devkitc-1 +extra_scripts = ./littlefsbuilder.py +board_build.partitions = partitions_custom.csv \ No newline at end of file diff --git a/examples/espidf-arduino-littlefs/sdkconfig.defaults b/examples/espidf-arduino-littlefs/sdkconfig.defaults new file mode 100644 index 000000000..a8f9a5467 --- /dev/null +++ b/examples/espidf-arduino-littlefs/sdkconfig.defaults @@ -0,0 +1,9 @@ +CONFIG_AUTOSTART_ARDUINO=y +# CONFIG_WS2812_LED_ENABLE is not set +CONFIG_FREERTOS_HZ=1000 +CONFIG_MBEDTLS_PSK_MODES=y +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y diff --git a/examples/espidf-arduino-littlefs/src/CMakeLists.txt b/examples/espidf-arduino-littlefs/src/CMakeLists.txt new file mode 100644 index 000000000..483bc0cfc --- /dev/null +++ b/examples/espidf-arduino-littlefs/src/CMakeLists.txt @@ -0,0 +1,6 @@ +# This file was automatically generated for projects +# without default 'CMakeLists.txt' file. + +FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*) + +idf_component_register(SRCS ${app_sources}) diff --git a/examples/espidf-arduino-littlefs/src/idf_component.yml b/examples/espidf-arduino-littlefs/src/idf_component.yml new file mode 100644 index 000000000..19907c020 --- /dev/null +++ b/examples/espidf-arduino-littlefs/src/idf_component.yml @@ -0,0 +1,51 @@ +dependencies: + # Required IDF version + idf: ">=4.4" + + esp_littlefs: + git: https://github.com/joltwallet/esp_littlefs.git + version: lfs2.8 + + mdns: "^1.2.1" + # nghttp: "^1.50.0" + # esp_jpeg: "^1.0.4" + # esp-dsp: "^1.2.0" + # esp-sr: "^1.0.3" + # esp32-camera: "^2.0.3" + # esp-dl: + # git: https://github.com/espressif/esp-dl.git + # arduino: + # path: components/arduino + + # # Defining a dependency from the registry: + # # https://components.espressif.com/component/example/cmp + # example/cmp: "^3.3.3" # Automatically update minor releases + # + # # Other ways to define dependencies + # + # # For components maintained by Espressif only name can be used. + # # Same as `espressif/cmp` + # component: "~1.0.0" # Automatically update bugfix releases + # + # # Or in a longer form with extra parameters + # component2: + # version: ">=2.0.0" + # + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't have an effect for the `main` component. + # # All dependencies of `main` are public by default. + # public: true + # + # # For components hosted on non-default registry: + # service_url: "https://componentregistry.company.com" + # + # # For components in git repository: + # test_component: + # path: test_component + # git: ssh://git@gitlab.com/user/components.git + # + # # For test projects during component development + # # components can be used from a local directory + # # with relative or absolute path + # some_local_component: + # path: ../../projects/component diff --git a/examples/espidf-arduino-littlefs/src/main.cpp b/examples/espidf-arduino-littlefs/src/main.cpp new file mode 100644 index 000000000..f20ad4e5c --- /dev/null +++ b/examples/espidf-arduino-littlefs/src/main.cpp @@ -0,0 +1,282 @@ +#include +#include "FS.h" +#include +#include + +/* You only need to format LittleFS the first time you run a + test or else use the LITTLEFS plugin to create a partition + https://github.com/lorol/arduino-esp32littlefs-plugin */ + +#define FORMAT_LITTLEFS_IF_FAILED true + +void listDir(fs::FS &fs, const char * dirname, uint8_t levels){ + Serial.printf("Listing directory: %s\r\n", dirname); + + File root = fs.open(dirname); + if(!root){ + Serial.println("- failed to open directory"); + return; + } + if(!root.isDirectory()){ + Serial.println(" - not a directory"); + return; + } + + File file = root.openNextFile(); + while(file){ + if(file.isDirectory()){ + Serial.print(" DIR : "); + + Serial.print(file.name()); + time_t t= file.getLastWrite(); + struct tm * tmstruct = localtime(&t); + Serial.printf(" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct->tm_year)+1900,( tmstruct->tm_mon)+1, tmstruct->tm_mday,tmstruct->tm_hour , tmstruct->tm_min, tmstruct->tm_sec); + + if(levels){ + listDir(fs, file.name(), levels -1); + } + } else { + Serial.print(" FILE: "); + Serial.print(file.name()); + Serial.print(" SIZE: "); + + Serial.print(file.size()); + time_t t= file.getLastWrite(); + struct tm * tmstruct = localtime(&t); + Serial.printf(" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct->tm_year)+1900,( tmstruct->tm_mon)+1, tmstruct->tm_mday,tmstruct->tm_hour , tmstruct->tm_min, tmstruct->tm_sec); + } + file = root.openNextFile(); + } +} + +void createDir(fs::FS &fs, const char * path){ + Serial.printf("Creating Dir: %s\n", path); + if(fs.mkdir(path)){ + Serial.println("Dir created"); + } else { + Serial.println("mkdir failed"); + } +} + +void removeDir(fs::FS &fs, const char * path){ + Serial.printf("Removing Dir: %s\n", path); + if(fs.rmdir(path)){ + Serial.println("Dir removed"); + } else { + Serial.println("rmdir failed"); + } +} + +void readFile(fs::FS &fs, const char * path){ + Serial.printf("Reading file: %s\r\n", path); + + File file = fs.open(path); + if(!file || file.isDirectory()){ + Serial.println("- failed to open file for reading"); + return; + } + + Serial.println("- read from file:"); + while(file.available()){ + Serial.write(file.read()); + } + file.close(); +} + +void writeFile(fs::FS &fs, const char * path, const char * message){ + Serial.printf("Writing file: %s\r\n", path); + + File file = fs.open(path, FILE_WRITE); + if(!file){ + Serial.println("- failed to open file for writing"); + return; + } + if(file.print(message)){ + Serial.println("- file written"); + } else { + Serial.println("- write failed"); + } + file.close(); +} + +void appendFile(fs::FS &fs, const char * path, const char * message){ + Serial.printf("Appending to file: %s\r\n", path); + + File file = fs.open(path, FILE_APPEND); + if(!file){ + Serial.println("- failed to open file for appending"); + return; + } + if(file.print(message)){ + Serial.println("- message appended"); + } else { + Serial.println("- append failed"); + } + file.close(); +} + +void renameFile(fs::FS &fs, const char * path1, const char * path2){ + Serial.printf("Renaming file %s to %s\r\n", path1, path2); + if (fs.rename(path1, path2)) { + Serial.println("- file renamed"); + } else { + Serial.println("- rename failed"); + } +} + +void deleteFile(fs::FS &fs, const char * path){ + Serial.printf("Deleting file: %s\r\n", path); + if(fs.remove(path)){ + Serial.println("- file deleted"); + } else { + Serial.println("- delete failed"); + } +} + +// SPIFFS-like write and delete file + +// See: https://github.com/esp8266/Arduino/blob/master/libraries/LittleFS/src/LittleFS.cpp#L60 +void writeFile2(fs::FS &fs, const char * path, const char * message){ + if(!fs.exists(path)){ + if (strchr(path, '/')) { + Serial.printf("Create missing folders of: %s\r\n", path); + char *pathStr = strdup(path); + if (pathStr) { + char *ptr = strchr(pathStr, '/'); + while (ptr) { + *ptr = 0; + fs.mkdir(pathStr); + *ptr = '/'; + ptr = strchr(ptr+1, '/'); + } + } + free(pathStr); + } + } + + Serial.printf("Writing file to: %s\r\n", path); + File file = fs.open(path, FILE_WRITE); + if(!file){ + Serial.println("- failed to open file for writing"); + return; + } + if(file.print(message)){ + Serial.println("- file written"); + } else { + Serial.println("- write failed"); + } + file.close(); +} + +// See: https://github.com/esp8266/Arduino/blob/master/libraries/LittleFS/src/LittleFS.h#L149 +void deleteFile2(fs::FS &fs, const char * path){ + Serial.printf("Deleting file and empty folders on path: %s\r\n", path); + + if(fs.remove(path)){ + Serial.println("- file deleted"); + } else { + Serial.println("- delete failed"); + } + + char *pathStr = strdup(path); + if (pathStr) { + char *ptr = strrchr(pathStr, '/'); + if (ptr) { + Serial.printf("Removing all empty folders on path: %s\r\n", path); + } + while (ptr) { + *ptr = 0; + fs.rmdir(pathStr); + ptr = strrchr(pathStr, '/'); + } + free(pathStr); + } +} + +void testFileIO(fs::FS &fs, const char * path){ + Serial.printf("Testing file I/O with %s\r\n", path); + + static uint8_t buf[512]; + size_t len = 0; + File file = fs.open(path, FILE_WRITE); + if(!file){ + Serial.println("- failed to open file for writing"); + return; + } + + size_t i; + Serial.print("- writing" ); + uint32_t start = millis(); + for(i=0; i<2048; i++){ + if ((i & 0x001F) == 0x001F){ + Serial.print("."); + } + file.write(buf, 512); + } + Serial.println(""); + uint32_t end = millis() - start; + //Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, end); + file.close(); + + file = fs.open(path); + start = millis(); + end = start; + i = 0; + if(file && !file.isDirectory()){ + len = file.size(); + size_t flen = len; + start = millis(); + Serial.print("- reading" ); + while(len){ + size_t toRead = len; + if(toRead > 512){ + toRead = 512; + } + file.read(buf, toRead); + if ((i++ & 0x001F) == 0x001F){ + Serial.print("."); + } + len -= toRead; + } + Serial.println(""); + end = millis() - start; + //Serial.printf("- %u bytes read in %u ms\r\n", flen, end); + file.close(); + } else { + Serial.println("- failed to open file for reading"); + } +} + +void setup(){ + Serial.begin(115200); + if(!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)){ + Serial.println("LittleFS Mount Failed"); + return; + } + + listDir(LittleFS, "/", 0); + createDir(LittleFS, "/mydir"); + writeFile(LittleFS, "/mydir/hello2.txt", "Hello2"); + //writeFile(LittleFS, "/mydir/newdir2/newdir3/hello3.txt", "Hello3"); + writeFile2(LittleFS, "/mydir/newdir2/newdir3/hello3.txt", "Hello3"); + listDir(LittleFS, "/", 3); + deleteFile(LittleFS, "/mydir/hello2.txt"); + //deleteFile(LittleFS, "/mydir/newdir2/newdir3/hello3.txt"); + deleteFile2(LittleFS, "/mydir/newdir2/newdir3/hello3.txt"); + removeDir(LittleFS, "/mydir"); + listDir(LittleFS, "/", 3); + writeFile(LittleFS, "/hello.txt", "Hello "); + appendFile(LittleFS, "/hello.txt", "World!\r\n"); + readFile(LittleFS, "/hello.txt"); + renameFile(LittleFS, "/hello.txt", "/foo.txt"); + readFile(LittleFS, "/foo.txt"); + deleteFile(LittleFS, "/foo.txt"); + testFileIO(LittleFS, "/test.txt"); + deleteFile(LittleFS, "/test.txt"); + + Serial.println( "Test complete" ); +} + +void loop(){ + +} From 72a2a717be9bc3f60c9ee152bc90177ab6c0f5dc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 12:28:09 +0200 Subject: [PATCH 454/666] add espidf-arduino-littlefs example --- .github/workflows/examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 8b04190f5..43a832c53 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -19,6 +19,7 @@ jobs: - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/espidf-arduino-blink" + - "examples/espidf-arduino-littlefs" - "examples/espidf-blink" - "examples/espidf-coap-server" - "examples/espidf-exceptions" From b35a7614f5251ad640a639fa03671dcdef045a27 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:57:19 +0200 Subject: [PATCH 455/666] build 1629 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 49b226d7f..7529e8434 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1614/framework-arduinoespressif32-release_v5.1-fab1aca036.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1629/framework-arduinoespressif32-release_v5.1-f45a4361b2.zip" }, "framework-arduino-solo1": { "type": "framework", From 8c8ffc7f2bd2da6cf6169940f192cd09c20b1b08 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:47:26 +0200 Subject: [PATCH 456/666] build 1638 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 7529e8434..3fda4cbe7 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1629/framework-arduinoespressif32-release_v5.1-f45a4361b2.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1638/framework-arduinoespressif32-release_v5.1-f45a4361b2.zip" }, "framework-arduino-solo1": { "type": "framework", From d328ab197e92574b70c459fdf2c11d5636ec27f5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 3 Oct 2023 21:55:28 +0200 Subject: [PATCH 457/666] Update idf_component.yml --- examples/espidf-arduino-littlefs/src/idf_component.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/espidf-arduino-littlefs/src/idf_component.yml b/examples/espidf-arduino-littlefs/src/idf_component.yml index 19907c020..d2f58209d 100644 --- a/examples/espidf-arduino-littlefs/src/idf_component.yml +++ b/examples/espidf-arduino-littlefs/src/idf_component.yml @@ -4,7 +4,6 @@ dependencies: esp_littlefs: git: https://github.com/joltwallet/esp_littlefs.git - version: lfs2.8 mdns: "^1.2.1" # nghttp: "^1.50.0" From 04c64b3e49ff21569b1da0bad9224f5a54596930 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 3 Oct 2023 23:26:22 +0200 Subject: [PATCH 458/666] Update idf_component.yml --- examples/espidf-arduino-blink/src/idf_component.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/espidf-arduino-blink/src/idf_component.yml b/examples/espidf-arduino-blink/src/idf_component.yml index 19907c020..d2f58209d 100644 --- a/examples/espidf-arduino-blink/src/idf_component.yml +++ b/examples/espidf-arduino-blink/src/idf_component.yml @@ -4,7 +4,6 @@ dependencies: esp_littlefs: git: https://github.com/joltwallet/esp_littlefs.git - version: lfs2.8 mdns: "^1.2.1" # nghttp: "^1.50.0" From 4744a1d09480c1334011b7ac5fd51ef22037bd9d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 4 Oct 2023 18:07:55 +0200 Subject: [PATCH 459/666] 1638 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 3fda4cbe7..bdb630a02 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1638/framework-arduinoespressif32-release_v5.1-f45a4361b2.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1643/framework-arduinoespressif32-release_v5.1-f45a4361b2.zip" }, "framework-arduino-solo1": { "type": "framework", From 0f63d240b5568948d50de433a3b343a3b40e9526 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:31:11 +0200 Subject: [PATCH 460/666] re add printf --- examples/espidf-arduino-littlefs/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/espidf-arduino-littlefs/src/main.cpp b/examples/espidf-arduino-littlefs/src/main.cpp index f20ad4e5c..67bbc3234 100644 --- a/examples/espidf-arduino-littlefs/src/main.cpp +++ b/examples/espidf-arduino-littlefs/src/main.cpp @@ -215,7 +215,7 @@ void testFileIO(fs::FS &fs, const char * path){ } Serial.println(""); uint32_t end = millis() - start; - //Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, end); + Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, (unsigned int)end); file.close(); file = fs.open(path); @@ -240,7 +240,7 @@ void testFileIO(fs::FS &fs, const char * path){ } Serial.println(""); end = millis() - start; - //Serial.printf("- %u bytes read in %u ms\r\n", flen, end); + Serial.printf("- %u bytes read in %u ms\r\n", flen, (unsigned int)end); file.close(); } else { Serial.println("- failed to open file for reading"); From ae949bcf416213717662095f67cd76d85a810529 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:32:31 +0200 Subject: [PATCH 461/666] add FS type --- examples/espidf-arduino-littlefs/platformio.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/espidf-arduino-littlefs/platformio.ini b/examples/espidf-arduino-littlefs/platformio.ini index 6f30eba07..3b15a9fd9 100644 --- a/examples/espidf-arduino-littlefs/platformio.ini +++ b/examples/espidf-arduino-littlefs/platformio.ini @@ -15,5 +15,6 @@ monitor_speed = 115200 [env:esp32-s3] board = esp32-s3-devkitc-1 +board_build.filesystem = littlefs extra_scripts = ./littlefsbuilder.py -board_build.partitions = partitions_custom.csv \ No newline at end of file +board_build.partitions = partitions_custom.csv From 5f5cd6e539f0d082e13ca4b9fe4d9ca183226779 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 5 Oct 2023 19:11:09 +0200 Subject: [PATCH 462/666] build 1650 1651 1652 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index bdb630a02..5be34c7d6 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1643/framework-arduinoespressif32-release_v5.1-f45a4361b2.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1650/framework-arduinoespressif32-release_v5.1-f45a4361b2.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1588/framework-arduinoespressif32-solo1-release_v5.1-5f7e313159.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1652/framework-arduinoespressif32-solo1-release_v5.1-f45a4361b2.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1589/framework-arduinoespressif32-ITEAD-release_v5.1-5f7e313159.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1651/framework-arduinoespressif32-ITEAD-release_v5.1-f45a4361b2.zip" }, "framework-espidf": { "type": "framework", From eb41041635c190c72daa0416950c9f7ebe94574b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 6 Oct 2023 17:56:18 +0200 Subject: [PATCH 463/666] Arduino 3.0.0-alpha1 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index bdb630a02..a669a3d4e 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.08.01", + "version": "2023.10.10", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1643/framework-arduinoespressif32-release_v5.1-f45a4361b2.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0-alpha1/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1588/framework-arduinoespressif32-solo1-release_v5.1-5f7e313159.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0-alpha1/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1589/framework-arduinoespressif32-ITEAD-release_v5.1-5f7e313159.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0-alpha1/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", From 66b56557501e2ccb34fcda5fd87c1771065524f1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 7 Oct 2023 16:24:04 +0200 Subject: [PATCH 464/666] IDF v5.1.1.231006 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index a669a3d4e..294644b62 100644 --- a/platform.json +++ b/platform.json @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.230920/esp-idf-v5.1.1.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.231006/esp-idf-v5.1.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 3bbc1963b8b20667e745b8b6c47c2c42335eca56 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:17:04 +0200 Subject: [PATCH 465/666] 1661 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 5be34c7d6..fa2813ffc 100644 --- a/platform.json +++ b/platform.json @@ -33,25 +33,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1650/framework-arduinoespressif32-release_v5.1-f45a4361b2.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1661/framework-arduinoespressif32-release_v5.1-600e70fe7a.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1652/framework-arduinoespressif32-solo1-release_v5.1-f45a4361b2.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0-alpha1/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1651/framework-arduinoespressif32-ITEAD-release_v5.1-f45a4361b2.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0-alpha1/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.230920/esp-idf-v5.1.1.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.231006/esp-idf-v5.1.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 96682a03fb07fdebb4f2c68023c091d9e2bec382 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:28:19 +0200 Subject: [PATCH 466/666] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 812d6b1d6..75fee35d9 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -### Stable Release supporting Arduino and IDF 5.0 -based on Arduino Core 2.0.6 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C3, ESP32S2 and ESP32S3 +### Development build supporting Arduino 3.0.0 and IDF 5.1 +alpha Arduino Core 3.0.0 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32S2, ESP32S3 and ESP32-H2 ``` [platformio] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.01.00/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.10/platform-espressif32.zip framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env From 3da5dfc3cfcf39707d8b2576207e09512a068977 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:31:14 +0200 Subject: [PATCH 467/666] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 75fee35d9..cd077f7f8 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,8 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -### Development build supporting Arduino 3.0.0 and IDF 5.1 -alpha Arduino Core 3.0.0 and can be used with Platformio for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32S2, ESP32S3 and ESP32-H2 +### Development build supporting Arduino 3.0.0-alpha1 and IDF 5.1 +Support for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32S2, ESP32S3 and ESP32-H2 ``` [platformio] platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.10/platform-espressif32.zip From c65c135a1218d5335683512fab135ac22fd6c857 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:32:31 +0200 Subject: [PATCH 468/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cd077f7f8..7338024ca 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -### Development build supporting Arduino 3.0.0-alpha1 and IDF 5.1 +### Development build Arduino 3.0.0-alpha1 and IDF 5.1 Support for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32S2, ESP32S3 and ESP32-H2 ``` [platformio] From 63098d123b8fa4485d8a6f8911c392d99a3481ca Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 9 Oct 2023 19:02:25 +0200 Subject: [PATCH 469/666] Update idf_component.yml --- examples/espidf-arduino-littlefs/src/idf_component.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/espidf-arduino-littlefs/src/idf_component.yml b/examples/espidf-arduino-littlefs/src/idf_component.yml index d2f58209d..a120bdbec 100644 --- a/examples/espidf-arduino-littlefs/src/idf_component.yml +++ b/examples/espidf-arduino-littlefs/src/idf_component.yml @@ -1,6 +1,6 @@ dependencies: # Required IDF version - idf: ">=4.4" + idf: ">=5.1" esp_littlefs: git: https://github.com/joltwallet/esp_littlefs.git From 7bb2628b53b0746fc9cfd8b70c9bad05d665bf9d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 9 Oct 2023 19:03:12 +0200 Subject: [PATCH 470/666] Update idf_component.yml --- examples/espidf-arduino-blink/src/idf_component.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/espidf-arduino-blink/src/idf_component.yml b/examples/espidf-arduino-blink/src/idf_component.yml index d2f58209d..a120bdbec 100644 --- a/examples/espidf-arduino-blink/src/idf_component.yml +++ b/examples/espidf-arduino-blink/src/idf_component.yml @@ -1,6 +1,6 @@ dependencies: # Required IDF version - idf: ">=4.4" + idf: ">=5.1" esp_littlefs: git: https://github.com/joltwallet/esp_littlefs.git From 22578f48f315943be998e38e7a1c59918a99201c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 11 Oct 2023 19:36:24 +0200 Subject: [PATCH 471/666] 1685 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index fa2813ffc..f9e858a56 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1661/framework-arduinoespressif32-release_v5.1-600e70fe7a.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1685/framework-arduinoespressif32-v5.1.1.231007-57b0b16dc7.zip" }, "framework-arduino-solo1": { "type": "framework", From 7c70aa12bf7eab3426376e01811b304d0f1beb6b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 13 Oct 2023 14:28:47 +0200 Subject: [PATCH 472/666] Build 1700 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index f9e858a56..bb0ac7a42 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1685/framework-arduinoespressif32-v5.1.1.231007-57b0b16dc7.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1700/framework-arduinoespressif32-v5.1.1.231007-57b0b16dc7.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0-alpha1/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1702/framework-arduinoespressif32-solo1-release_v5.1-ea8d2298ab.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0-alpha1/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1701/framework-arduinoespressif32-ITEAD-release_v5.1-ea8d2298ab.zip" }, "framework-espidf": { "type": "framework", From f2852d7ba03c9add08477ae39d3bc106af2dfc0f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 19 Oct 2023 15:19:58 +0200 Subject: [PATCH 473/666] install `gdb` packages --- platform.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platform.py b/platform.py index b661d650f..d4a14f898 100644 --- a/platform.py +++ b/platform.py @@ -58,6 +58,17 @@ def configure_default_packages(self, variables, targets): self.packages["toolchain-esp32ulp"]["optional"] = False if "espidf" in frameworks: + if frameworks == ["espidf"]: + # Starting from v12, Espressif's toolchains are shipped without + # bundled GDB. Instead, it's distributed as separate packages for Xtensa + # and RISC-V targets. Currently only IDF depends on the latest toolchain + for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"): + self.packages[gdb_package]["optional"] = False + if IS_WINDOWS: + # Note: On Windows GDB v12 is not able to + # launch a GDB server in pipe mode while v11 works fine + self.packages[gdb_package]["version"] = "~11.2.0" + # Common packages for IDF and mixed Arduino+IDF projects self.packages["toolchain-esp32ulp"]["optional"] = False for p in self.packages: From 34a0f2a8abb2d12ddbe1eb8ce6e41410d074b552 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 19 Oct 2023 15:29:33 +0200 Subject: [PATCH 474/666] `gdb` for Arduino as component too --- platform.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/platform.py b/platform.py index d4a14f898..f88c8d0f9 100644 --- a/platform.py +++ b/platform.py @@ -58,16 +58,15 @@ def configure_default_packages(self, variables, targets): self.packages["toolchain-esp32ulp"]["optional"] = False if "espidf" in frameworks: - if frameworks == ["espidf"]: - # Starting from v12, Espressif's toolchains are shipped without - # bundled GDB. Instead, it's distributed as separate packages for Xtensa - # and RISC-V targets. Currently only IDF depends on the latest toolchain - for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"): - self.packages[gdb_package]["optional"] = False - if IS_WINDOWS: - # Note: On Windows GDB v12 is not able to - # launch a GDB server in pipe mode while v11 works fine - self.packages[gdb_package]["version"] = "~11.2.0" + # Starting from v12, Espressif's toolchains are shipped without + # bundled GDB. Instead, it's distributed as separate packages for Xtensa + # and RISC-V targets. + for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"): + self.packages[gdb_package]["optional"] = False + if IS_WINDOWS: + # Note: On Windows GDB v12 is not able to + # launch a GDB server in pipe mode while v11 works fine + self.packages[gdb_package]["version"] = "~11.2.0" # Common packages for IDF and mixed Arduino+IDF projects self.packages["toolchain-esp32ulp"]["optional"] = False From a09fbaffd4ce90f2b1a6b110c4227cec921a9ec4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 19 Oct 2023 16:12:48 +0200 Subject: [PATCH 475/666] Use always new gdb --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index 47c700b60..29ffde6a8 100644 --- a/builder/main.py +++ b/builder/main.py @@ -238,7 +238,7 @@ def __fetch_fs_size(target, source, env): or "", "bin", "%s-elf-gdb" % toolchain_arch, - ) if env.get("PIOFRAMEWORK") == ["espidf"] else "%s-elf-gdb" % toolchain_arch, + ), OBJCOPY=join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), RANLIB="%s-elf-gcc-ranlib" % toolchain_arch, SIZETOOL="%s-elf-size" % toolchain_arch, From e0e5f49d620a27c0b84ceb05962da47770c9c3d7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 19 Oct 2023 17:26:16 +0200 Subject: [PATCH 476/666] esptool.py v4.7.0-dev2 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index bb0ac7a42..f36687779 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev/esptool-4.7.0.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev2/esptool-4.7.0.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From 101b8c7eb12a0be476b7c85627569616d831db4e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 19 Oct 2023 17:27:11 +0200 Subject: [PATCH 477/666] Update platform to 2023.10.20 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index f36687779..5843424f6 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.08.01", + "version": "2023.10.20", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From 09dfb6166427d1897afc472706cbdf3e292a0131 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 19 Oct 2023 18:01:15 +0200 Subject: [PATCH 478/666] Build 1733 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 5843424f6..977fde18f 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1700/framework-arduinoespressif32-v5.1.1.231007-57b0b16dc7.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1733/framework-arduinoespressif32-v5.1.1.231007-57b0b16dc7.zip" }, "framework-arduino-solo1": { "type": "framework", From 2f530c7518102c3312a280368dc0ce658fe78678 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 14:21:27 +0200 Subject: [PATCH 479/666] use real flash size when flashing --- builder/main.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/builder/main.py b/builder/main.py index 29ffde6a8..110609cf5 100644 --- a/builder/main.py +++ b/builder/main.py @@ -428,7 +428,8 @@ def __fetch_fs_size(target, source, env): "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", board.get("upload.flash_size", "detect") + "--flash_size", "detect" + #"--flash_size", board.get("upload.flash_size", "detect") ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE' ) @@ -446,7 +447,8 @@ def __fetch_fs_size(target, source, env): "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", - "--flash_size", board.get("upload.flash_size", "detect"), + "--flash_size", "detect", + #"--flash_size", board.get("upload.flash_size", "detect") "$FS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', From 5bc4731e278abd837c974b66a3a80daa63c77283 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 17:56:00 +0200 Subject: [PATCH 480/666] Build 1743 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 977fde18f..f644f928e 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1733/framework-arduinoespressif32-v5.1.1.231007-57b0b16dc7.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1743/framework-arduinoespressif32-v5.1.1.231007-57b0b16dc7.zip" }, "framework-arduino-solo1": { "type": "framework", From a28b90dbce92c37aed50712fe1204335ddfcf59b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 17:59:44 +0200 Subject: [PATCH 481/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index f644f928e..e342ae996 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.10.20", + "version": "2023.10.11", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" From b7b96633d5feca4456a3b6708d8cd60c44c60c78 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 18:00:44 +0200 Subject: [PATCH 482/666] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7338024ca..1dcebf259 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -### Development build Arduino 3.0.0-alpha1 and IDF 5.1 +### Development build Arduino 3.0.0-alpha2 and IDF 5.1.1 Support for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32S2, ESP32S3 and ESP32-H2 ``` [platformio] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.10/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.11/platform-espressif32.zip framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env From 55ef32614092e1a1795d62f0f35efe3c6b3ff502 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:03:22 +0200 Subject: [PATCH 483/666] Update platformio.ini --- examples/arduino-usb-keyboard/platformio.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/arduino-usb-keyboard/platformio.ini b/examples/arduino-usb-keyboard/platformio.ini index 3f51b8378..434e1a6f3 100644 --- a/examples/arduino-usb-keyboard/platformio.ini +++ b/examples/arduino-usb-keyboard/platformio.ini @@ -14,6 +14,3 @@ monitor_speed = 115200 [env:esp32-s2-saola-1] board = esp32-s2-saola-1 - -[env:esp32-s2-kaluga-1] -board = esp32-s2-kaluga-1 \ No newline at end of file From ad56b8026ea4c78aeb71473471f41da69b6df2fb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:04:20 +0200 Subject: [PATCH 484/666] Update platformio.ini --- examples/arduino-wifiscan/platformio.ini | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/examples/arduino-wifiscan/platformio.ini b/examples/arduino-wifiscan/platformio.ini index bc9223323..38cd6b894 100644 --- a/examples/arduino-wifiscan/platformio.ini +++ b/examples/arduino-wifiscan/platformio.ini @@ -7,26 +7,8 @@ ; Please visit documentation for the other options and examples ; http://docs.platformio.org/page/projectconf.html -[env:esp32dev] -platform = espressif32 -framework = arduino -board = esp32dev -monitor_speed = 115200 - [env:esp-wrover-kit] platform = espressif32 framework = arduino board = esp-wrover-kit monitor_speed = 115200 - -[env:espea32] -platform = espressif32 -framework = arduino -board = espea32 -monitor_speed = 115200 - -[env:esp320] -platform = espressif32 -framework = arduino -board = esp320 -monitor_speed = 115200 From 754821477d4a65902b232788fd7545a80bf31d16 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:05:13 +0200 Subject: [PATCH 485/666] Update platformio.ini --- examples/espidf-arduino-wifiscan/platformio.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/espidf-arduino-wifiscan/platformio.ini b/examples/espidf-arduino-wifiscan/platformio.ini index 6f6d15335..28bfc100d 100644 --- a/examples/espidf-arduino-wifiscan/platformio.ini +++ b/examples/espidf-arduino-wifiscan/platformio.ini @@ -12,8 +12,5 @@ platform = espressif32 framework = arduino, espidf monitor_speed = 115200 -[env:esp32dev] -board = esp32dev - [env:esp-wrover-kit] board = esp-wrover-kit From 6308e3009bc1f014d234c087f45754153b7b933e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:05:58 +0200 Subject: [PATCH 486/666] Update platformio.ini --- examples/espidf-coap-server/platformio.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/espidf-coap-server/platformio.ini b/examples/espidf-coap-server/platformio.ini index 78383c341..5184d0659 100644 --- a/examples/espidf-coap-server/platformio.ini +++ b/examples/espidf-coap-server/platformio.ini @@ -21,6 +21,3 @@ board = nano32 [env:esp-wrover-kit] board = esp-wrover-kit - -[env:esp32dev] -board = esp32dev From 73706ad0e6d85b11300f4138d3cf220d9cbfb4d1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:06:35 +0200 Subject: [PATCH 487/666] Update platformio.ini --- examples/espidf-exceptions/platformio.ini | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/espidf-exceptions/platformio.ini b/examples/espidf-exceptions/platformio.ini index a6c3cff92..a4031d38f 100644 --- a/examples/espidf-exceptions/platformio.ini +++ b/examples/espidf-exceptions/platformio.ini @@ -12,11 +12,5 @@ platform = espressif32 framework = espidf monitor_speed = 115200 -[env:esp32dev] -board = esp32dev - [env:esp-wrover-kit] board = esp-wrover-kit - -[env:lolin32] -board = lolin32 From 71cedd31a95d2469669d6c65c00c40a83cdbc657 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:07:26 +0200 Subject: [PATCH 488/666] Update platformio.ini --- examples/espidf-http-request/platformio.ini | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/espidf-http-request/platformio.ini b/examples/espidf-http-request/platformio.ini index 38756e618..75537f7a6 100644 --- a/examples/espidf-http-request/platformio.ini +++ b/examples/espidf-http-request/platformio.ini @@ -15,11 +15,5 @@ monitor_speed = 115200 [env:esp32dev] board = esp32dev -[env:nano32] -board = nano32 - -[env:espea32] -board = espea32 - [env:esp32-s2-saola-1] board = esp32-s2-saola-1 From f4482e022a9b6b2e532bc7348d7fd1a40ef3e1ab Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:08:20 +0200 Subject: [PATCH 489/666] Update platformio.ini --- examples/espidf-peripherals-uart/platformio.ini | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/espidf-peripherals-uart/platformio.ini b/examples/espidf-peripherals-uart/platformio.ini index 84e7f72d8..b004a1b2f 100644 --- a/examples/espidf-peripherals-uart/platformio.ini +++ b/examples/espidf-peripherals-uart/platformio.ini @@ -12,11 +12,5 @@ platform = espressif32 framework = espidf monitor_speed = 115200 -[env:pocket_32] -board = pocket_32 - [env:odroid_esp32] board = odroid_esp32 - -[env:featheresp32] -board = featheresp32 From 5d5ff15b73ca4c92819c159020c8a20ed8828ef8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:08:46 +0200 Subject: [PATCH 490/666] Update platformio.ini --- examples/espidf-peripherals-usb/platformio.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/espidf-peripherals-usb/platformio.ini b/examples/espidf-peripherals-usb/platformio.ini index 438ef31be..a1883d5a1 100644 --- a/examples/espidf-peripherals-usb/platformio.ini +++ b/examples/espidf-peripherals-usb/platformio.ini @@ -14,6 +14,3 @@ monitor_speed = 115200 [env:esp32-s2-saola-1] board = esp32-s2-saola-1 - -[env:esp32-s2-kaluga-1] -board = esp32-s2-kaluga-1 From 97273c5c55305966489e2dba885e2c477f35f7bd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:09:23 +0200 Subject: [PATCH 491/666] Update platformio.ini --- examples/espidf-storage-sdcard/platformio.ini | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/espidf-storage-sdcard/platformio.ini b/examples/espidf-storage-sdcard/platformio.ini index 112293123..66f1b78d2 100644 --- a/examples/espidf-storage-sdcard/platformio.ini +++ b/examples/espidf-storage-sdcard/platformio.ini @@ -12,11 +12,5 @@ platform = espressif32 framework = espidf monitor_speed = 115200 -[env:esp32thing] -board = esp32thing - -[env:esp32-gateway] -board = esp32-gateway - [env:heltec_wifi_kit_32] board = heltec_wifi_kit_32 From 9e29b72202cc25f0eb21b499b9ab1b5a9147dcde Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:20:39 +0200 Subject: [PATCH 492/666] Update platformio.ini --- examples/espidf-coap-server/platformio.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/espidf-coap-server/platformio.ini b/examples/espidf-coap-server/platformio.ini index 5184d0659..c26b3222a 100644 --- a/examples/espidf-coap-server/platformio.ini +++ b/examples/espidf-coap-server/platformio.ini @@ -16,8 +16,5 @@ board_build.embed_txtfiles = src/certs/coap_server.crt src/certs/coap_server.key -[env:nano32] -board = nano32 - [env:esp-wrover-kit] board = esp-wrover-kit From f2494be40ca26ad48a5d55652ac5b97f298f0401 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 23 Oct 2023 11:50:26 +0200 Subject: [PATCH 493/666] add c6 to RMT blink --- examples/arduino-rmt-blink/platformio.ini | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/arduino-rmt-blink/platformio.ini b/examples/arduino-rmt-blink/platformio.ini index 14244480d..1d31cf14c 100644 --- a/examples/arduino-rmt-blink/platformio.ini +++ b/examples/arduino-rmt-blink/platformio.ini @@ -15,3 +15,9 @@ platform = espressif32 framework = arduino board = esp32-c3-devkitm-1 build_flags = -DBUILTIN_RGBLED_PIN=8 + +[env:esp32-c6] +platform = espressif32 +framework = arduino +board = esp32-c6-devkitm-1 +build_flags = -DBUILTIN_RGBLED_PIN=8 From 54b0978bb9b62914e45c284eb0d2f41cd2585438 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 23 Oct 2023 11:58:16 +0200 Subject: [PATCH 494/666] Update RMTWriteNeoPixel.ino --- examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino b/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino index 300b60419..dbc183884 100644 --- a/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino +++ b/examples/arduino-rmt-blink/src/RMTWriteNeoPixel.ino @@ -30,7 +30,7 @@ //#define BUILTIN_RGBLED_PIN 21 // ESP32 has no builtin RGB LED //#endif -#define NR_OF_LEDS 8*4 +//#define NR_OF_LEDS 8*4 #define NR_OF_ALL_BITS 24*NR_OF_LEDS // From ce0c9ae69c36caf6d900c38143ebf4ac412948fb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 23 Oct 2023 11:59:42 +0200 Subject: [PATCH 495/666] Update platformio.ini --- examples/arduino-rmt-blink/platformio.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/arduino-rmt-blink/platformio.ini b/examples/arduino-rmt-blink/platformio.ini index 1d31cf14c..e3c6beacd 100644 --- a/examples/arduino-rmt-blink/platformio.ini +++ b/examples/arduino-rmt-blink/platformio.ini @@ -3,21 +3,25 @@ platform = espressif32 framework = arduino board = esp32-s2-saola-1 build_flags = -DBUILTIN_RGBLED_PIN=18 + -DNR_OF_LEDS=1 [env:esp32-s3] platform = espressif32 framework = arduino board = esp32-s3-devkitc-1 build_flags = -DBUILTIN_RGBLED_PIN=48 + -DNR_OF_LEDS=1 [env:esp32-c3] platform = espressif32 framework = arduino board = esp32-c3-devkitm-1 build_flags = -DBUILTIN_RGBLED_PIN=8 + -DNR_OF_LEDS=1 [env:esp32-c6] platform = espressif32 framework = arduino board = esp32-c6-devkitm-1 build_flags = -DBUILTIN_RGBLED_PIN=8 + -DNR_OF_LEDS=1 From fa6db7c20e02e36d0616a165fde393c9c4d8fb7d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 27 Oct 2023 18:55:55 +0200 Subject: [PATCH 496/666] Build 1761 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index e342ae996..33643fb2c 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1743/framework-arduinoespressif32-v5.1.1.231007-57b0b16dc7.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1761/framework-arduinoespressif32-release_v5.1_no_SECP256R1-e97d377907.zip" }, "framework-arduino-solo1": { "type": "framework", From e434a84b1dfa2da6869e84e9ae0443f936b8921a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 28 Oct 2023 11:14:42 +0200 Subject: [PATCH 497/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 33643fb2c..cfa68b3b1 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1761/framework-arduinoespressif32-release_v5.1_no_SECP256R1-e97d377907.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1768/framework-arduinoespressif32-release_v5.1-e97d377907.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1702/framework-arduinoespressif32-solo1-release_v5.1-ea8d2298ab.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1766/framework-arduinoespressif32-solo1-release_v5.1-e97d377907.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1701/framework-arduinoespressif32-ITEAD-release_v5.1-ea8d2298ab.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1767/framework-arduinoespressif32-ITEAD-release_v5.1-e97d377907.zip" }, "framework-espidf": { "type": "framework", From cc863f0e51f4ee3a2082d49f73ad129c30d1a1ff Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 28 Oct 2023 12:25:43 +0200 Subject: [PATCH 498/666] 2023.10.12 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index cfa68b3b1..65a24bc9c 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.10.11", + "version": "2023.10.12", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1768/framework-arduinoespressif32-release_v5.1-e97d377907.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231024/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1766/framework-arduinoespressif32-solo1-release_v5.1-e97d377907.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231024/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1767/framework-arduinoespressif32-ITEAD-release_v5.1-e97d377907.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231024/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", From d076cd6e7c5c8702a6e9378f8c853e161479e77a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 1 Nov 2023 15:15:47 +0100 Subject: [PATCH 499/666] install `gdb` packages always --- platform.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/platform.py b/platform.py index f88c8d0f9..620cf1b1b 100644 --- a/platform.py +++ b/platform.py @@ -57,16 +57,15 @@ def configure_default_packages(self, variables, targets): if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False - if "espidf" in frameworks: - # Starting from v12, Espressif's toolchains are shipped without - # bundled GDB. Instead, it's distributed as separate packages for Xtensa - # and RISC-V targets. - for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"): - self.packages[gdb_package]["optional"] = False - if IS_WINDOWS: - # Note: On Windows GDB v12 is not able to - # launch a GDB server in pipe mode while v11 works fine - self.packages[gdb_package]["version"] = "~11.2.0" + # Starting from v12, Espressif's toolchains are shipped without + # bundled GDB. Instead, it's distributed as separate packages for Xtensa + # and RISC-V targets. + for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"): + self.packages[gdb_package]["optional"] = False + if IS_WINDOWS: + # Note: On Windows GDB v12 is not able to + # launch a GDB server in pipe mode while v11 works fine + self.packages[gdb_package]["version"] = "~11.2.0" # Common packages for IDF and mixed Arduino+IDF projects self.packages["toolchain-esp32ulp"]["optional"] = False From cd7ab756f43a9545b1e40d5466bc630156bfe313 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:24:52 +0100 Subject: [PATCH 500/666] 2023.11.10 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 65a24bc9c..62b33b3a3 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.10.12", + "version": "2023.11.10", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231024/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231113/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231024/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231113/framework-arduinoespressif32-ITEAD.zip" }, "framework-arduino-ITEAD": { "type": "framework", @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.231006/esp-idf-v5.1.1.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.231113/esp-idf-v5.1.1.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From d1e7e268321868296eb6f52e978cedb108a09498 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:37:48 +0100 Subject: [PATCH 501/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 62b33b3a3..336a91ec0 100644 --- a/platform.json +++ b/platform.json @@ -39,7 +39,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231113/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231113/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", From 4b75ccff851d36e9eb7aca8b820d84d0f7053fd9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 13 Nov 2023 14:32:19 +0100 Subject: [PATCH 502/666] Properly handle precompiled static archives located outside IDF proje --- builder/frameworks/espidf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 4063b3127..720150a82 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -364,8 +364,8 @@ def _add_archive(archive_path, link_args): elif fragment.endswith(".a"): archive_path = fragment # process static archives - if archive_path.startswith(FRAMEWORK_DIR): - # In case of precompiled archives from framework package + if os.path.isabs(archive_path): + # In case of precompiled archives _add_archive(archive_path, link_args) else: # In case of archives within project From 8cf2b30899c999228af7913ea6cd4aa8fd310566 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 13 Nov 2023 14:39:44 +0100 Subject: [PATCH 503/666] optic changes --- builder/frameworks/espidf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 720150a82..54989aaf9 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -38,7 +38,7 @@ DefaultEnvironment, ) -from platformio import fs +from platformio import fs, __version__ from platformio.compat import IS_WINDOWS from platformio.proc import exec_command from platformio.builder.tools.piolib import ProjectAsLibBuilder @@ -63,7 +63,7 @@ IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" % ("riscv32-esp" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2") else ("xtensa-%s" % mcu)) + "toolchain-%s" % ("riscv32-esp" if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2") else ("xtensa-%s" % mcu)) ) From 69200ceffa9a9abcf80d8032ec55f7f252d7f282 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 18 Nov 2023 18:35:51 +0100 Subject: [PATCH 504/666] 2023.11.11 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 336a91ec0..7caa2f49d 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.11.10", + "version": "2023.11.11", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231113/framework-arduinoespressif32.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231118/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231113/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231118/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231024/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231118/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", From 1447bfbdbf80d12658d5e2d7e92d1fdbf3fccd15 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 18 Nov 2023 18:46:13 +0100 Subject: [PATCH 505/666] IDF v5.1.2 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 7caa2f49d..2fc0aa658 100644 --- a/platform.json +++ b/platform.json @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.1.231113/esp-idf-v5.1.1.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.231118/esp-idf-v5.1.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 2a9e06fd5d195c1f8714b25b151738343d2dc600 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 28 Nov 2023 14:54:15 +0100 Subject: [PATCH 506/666] newer builds --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 2fc0aa658..4d5efc449 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231118/framework-arduinoespressif32.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1831/framework-arduinoespressif32-release_v5.1-29db12e32f.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231118/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1833/framework-arduinoespressif32-solo1-release_v5.1-29db12e32f.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231118/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1832/framework-arduinoespressif32-ITEAD-release_v5.1-29db12e32f.zip" }, "framework-espidf": { "type": "framework", From d21c1387f87bd4b5081431e5a97f8e376bd9e3db Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Nov 2023 13:45:02 +0100 Subject: [PATCH 507/666] esptool v4.7 dev3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 4d5efc449..eaddd6861 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev2/esptool-4.7.0.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev3/esptool-4.7.0.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From 235cf3c25f7e9bd6ef0a3957ea3ac33fd43b692f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Nov 2023 13:49:23 +0100 Subject: [PATCH 508/666] back to esptool v4.7 dev2 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index eaddd6861..4d5efc449 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev3/esptool-4.7.0.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev2/esptool-4.7.0.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From db0041367994429f84cbb6a176394f39693e7b94 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:43:20 +0100 Subject: [PATCH 509/666] pip install Intel hex --- builder/frameworks/arduino.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 94cd2f982..f7f538ae7 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -79,7 +79,8 @@ def _get_installed_pip_packages(): deps = { "wheel": ">=0.35.1", "zopfli": ">=0.2.2", - "tasmota-metrics": ">=0.4.3" + "tasmota-metrics": ">=0.4.3", + "intelhex": ">=2.3.0" # newest esptool.py needs } installed_packages = _get_installed_pip_packages() From 9e60945d30794b1626be7e896b8e2e975e39a5dd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:46:11 +0100 Subject: [PATCH 510/666] pip install intelhex --- builder/frameworks/espidf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 54989aaf9..c902d7595 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1111,7 +1111,8 @@ def _get_installed_pip_packages(python_exe_path): "pyparsing": "~=3.0.9" if IDF5 else ">=2.0.3,<2.4.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", "idf-component-manager": "~=1.2.3" if IDF5 else "~=1.0", - "esp-idf-kconfig": "~=1.2.0" + "esp-idf-kconfig": "~=1.2.0", + "intelhex": ">=2.3.0" # newest esptool.py needs } if sys_platform.system() == "Darwin" and "arm" in sys_platform.machine().lower(): From bbd5a59a99fbe2a0a9793cd40bceacd96ef9cb97 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:47:05 +0100 Subject: [PATCH 511/666] esptool.py 4.7 dev3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 4d5efc449..eaddd6861 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev2/esptool-4.7.0.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev3/esptool-4.7.0.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From a9756ed71ceb9673d89658b625cfc5aec1cf6c50 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:02:43 +0100 Subject: [PATCH 512/666] Update espidf.py --- builder/frameworks/espidf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index c902d7595..e32e98b1d 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1112,7 +1112,8 @@ def _get_installed_pip_packages(python_exe_path): "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", "idf-component-manager": "~=1.2.3" if IDF5 else "~=1.0", "esp-idf-kconfig": "~=1.2.0", - "intelhex": ">=2.3.0" # newest esptool.py needs + # newest esptool.py needs this + "intelhex": ">=2.3.0" } if sys_platform.system() == "Darwin" and "arm" in sys_platform.machine().lower(): From 7f830022f594b22c60baff18321954593f7342c0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:12:51 +0100 Subject: [PATCH 513/666] Update espidf.py --- builder/frameworks/espidf.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index e32e98b1d..54989aaf9 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1111,9 +1111,7 @@ def _get_installed_pip_packages(python_exe_path): "pyparsing": "~=3.0.9" if IDF5 else ">=2.0.3,<2.4.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", "idf-component-manager": "~=1.2.3" if IDF5 else "~=1.0", - "esp-idf-kconfig": "~=1.2.0", - # newest esptool.py needs this - "intelhex": ">=2.3.0" + "esp-idf-kconfig": "~=1.2.0" } if sys_platform.system() == "Darwin" and "arm" in sys_platform.machine().lower(): From e131506995b2497953df941e3e08c60de87a8027 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:13:20 +0100 Subject: [PATCH 514/666] Update arduino.py --- builder/frameworks/arduino.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index f7f538ae7..94cd2f982 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -79,8 +79,7 @@ def _get_installed_pip_packages(): deps = { "wheel": ">=0.35.1", "zopfli": ">=0.2.2", - "tasmota-metrics": ">=0.4.3", - "intelhex": ">=2.3.0" # newest esptool.py needs + "tasmota-metrics": ">=0.4.3" } installed_packages = _get_installed_pip_packages() From 98b5dba83dbef540e755848bdb350b85ddc6d111 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:13:49 +0100 Subject: [PATCH 515/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index eaddd6861..4d5efc449 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev3/esptool-4.7.0.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev2/esptool-4.7.0.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From 3c9772c2701cb7a8e14892529e9f52921c2e40b9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 29 Nov 2023 16:05:31 +0100 Subject: [PATCH 516/666] esptool v4.7 dev3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 4d5efc449..eaddd6861 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev2/esptool-4.7.0.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev3/esptool-4.7.0.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From 7d55ad420d1a8c0e1062e1b39f25ab2d442f5bad Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 4 Dec 2023 18:42:22 +0100 Subject: [PATCH 517/666] esptool.py speed up s3 CDC flash read --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index eaddd6861..4c8f1bd3f 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0-dev3/esptool-4.7.0.zip" + "version": "https://github.com/Jason2866/esptool/releases/download/v4.7.0-dev4/esptool-4.7.0.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From 1f769717e3a220483eda1cc3b81cd72036884aca Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 5 Dec 2023 13:42:01 +0100 Subject: [PATCH 518/666] always "--flash_freq", "${__get_board_img_freq(__env__)}", (#53) --- builder/main.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/builder/main.py b/builder/main.py index 110609cf5..0374fe8b6 100644 --- a/builder/main.py +++ b/builder/main.py @@ -427,9 +427,8 @@ def __fetch_fs_size(target, source, env): "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_freq", "${__get_board_img_freq(__env__)}", "--flash_size", "detect" - #"--flash_size", board.get("upload.flash_size", "detect") ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE' ) @@ -446,9 +445,8 @@ def __fetch_fs_size(target, source, env): "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_f_flash(__env__)}", + "--flash_freq", "${__get_board_img_freq(__env__)}", "--flash_size", "detect", - #"--flash_size", board.get("upload.flash_size", "detect") "$FS_START" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', From 4fa881f8442e7e092dd416df70ab0abf79a5fe75 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 5 Dec 2023 13:55:20 +0100 Subject: [PATCH 519/666] Arduino 3.0.0-alpha3 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 4c8f1bd3f..6796410d3 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.11.11", + "version": "2023.12.10", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1831/framework-arduinoespressif32-release_v5.1-29db12e32f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1850/framework-arduinoespressif32-release_v5.1-29db12e.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1833/framework-arduinoespressif32-solo1-release_v5.1-29db12e32f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1851/framework-arduinoespressif32-solo1-release_v5.1-29db12e32f.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1832/framework-arduinoespressif32-ITEAD-release_v5.1-29db12e32f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1852/framework-arduinoespressif32-ITEAD-release_v5.1-29db12e32f.zip" }, "framework-espidf": { "type": "framework", From dfabb0a82e14ad096cddadb0bde11ec98d16bde2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 5 Dec 2023 13:59:36 +0100 Subject: [PATCH 520/666] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1dcebf259..84ddf78fc 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -### Development build Arduino 3.0.0-alpha2 and IDF 5.1.1 +### Development build Arduino 3.0.0-alpha3 and IDF 5.1.2 Support for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32S2, ESP32S3 and ESP32-H2 ``` [platformio] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.11/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.12.10/platform-espressif32.zip framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env From 2a8838709e9f4b178dcad849aa6cd60402a677c4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:07:48 +0100 Subject: [PATCH 521/666] update boards from upstream --- boards/4d_systems_esp32s3_gen4_r8n16.json | 50 ++++++++++++++ boards/adafruit_camera_esp32s3.json | 66 ++++++++++++++++++ boards/adafruit_feather_esp32s3.json | 1 + boards/adafruit_feather_esp32s3_nopsram.json | 1 + .../adafruit_feather_esp32s3_reversetft.json | 1 + boards/adafruit_feather_esp32s3_tft.json | 1 + boards/adafruit_matrixportal_esp32s3.json | 1 + boards/adafruit_metro_esp32s3.json | 67 +++++++++++++++++++ boards/adafruit_qtpy_esp32s3_nopsram.json | 1 + boards/adafruit_qualia_s3_rgb666.json | 67 +++++++++++++++++++ boards/arduino_nano_esp32.json | 1 + boards/atd147_s3.json | 48 +++++++++++++ boards/aventen_s3_sync.json | 50 ++++++++++++++ boards/bee_motion_s3.json | 3 +- boards/bee_s3.json | 1 + boards/bpi_leaf_s3.json | 1 + boards/cytron_maker_feather_aiot_s3.json | 1 + boards/dfrobot_firebeetle2_esp32s3.json | 1 + boards/dfrobot_romeo_esp32s3.json | 1 + boards/edgebox-esp-100.json | 1 + boards/esp32-s3-devkitc-1.json | 1 + boards/esp32-s3-devkitm-1.json | 50 ++++++++++++++ boards/esp32s3camlcd.json | 2 +- boards/ioxesp32.json | 37 ++++++++++ boards/ioxesp32ps.json | 42 ++++++++++++ boards/lilygo-t-display-s3.json | 1 + boards/lilygo-t-display.json | 44 ++++++++++++ boards/lolin_s3.json | 3 +- boards/lolin_s3_mini.json | 1 + boards/m5stack-atoms3.json | 1 + boards/m5stack-cores3.json | 3 + boards/m5stack-stamps3.json | 1 + boards/nebulas3.json | 1 + boards/redpill_esp32s3.json | 1 + boards/seeed_xiao_esp32s3.json | 1 + boards/tamc_termod_s3.json | 1 + boards/um_feathers3.json | 1 + boards/um_nanos3.json | 51 ++++++++++++++ boards/um_pros3.json | 1 + boards/um_tinys3.json | 1 + boards/unphone8.json | 1 + boards/unphone9.json | 1 + boards/wifiduino32s3.json | 1 + 43 files changed, 608 insertions(+), 3 deletions(-) create mode 100644 boards/4d_systems_esp32s3_gen4_r8n16.json create mode 100644 boards/adafruit_camera_esp32s3.json create mode 100644 boards/adafruit_metro_esp32s3.json create mode 100644 boards/adafruit_qualia_s3_rgb666.json create mode 100644 boards/atd147_s3.json create mode 100644 boards/aventen_s3_sync.json create mode 100644 boards/esp32-s3-devkitm-1.json create mode 100644 boards/ioxesp32.json create mode 100644 boards/ioxesp32ps.json create mode 100644 boards/lilygo-t-display.json create mode 100644 boards/um_nanos3.json diff --git a/boards/4d_systems_esp32s3_gen4_r8n16.json b/boards/4d_systems_esp32s3_gen4_r8n16.json new file mode 100644 index 000000000..4418be557 --- /dev/null +++ b/boards/4d_systems_esp32s3_gen4_r8n16.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_S3R8N16", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32_s3r8n16" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "4D Systems GEN4-ESP32 16MB (ESP32S3-R8N16)", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://4dsystems.com.au/products", + "vendor": "4D Systems" +} diff --git a/boards/adafruit_camera_esp32s3.json b/boards/adafruit_camera_esp32s3.json new file mode 100644 index 000000000..2693d8649 --- /dev/null +++ b/boards/adafruit_camera_esp32s3.json @@ -0,0 +1,66 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-4MB-1ota.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_CAMERA_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x0117" + ], + [ + "0x239A", + "0x8117" + ], + [ + "0x239A", + "0x8118" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_camera_esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit pyCamera S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x2d0000", + "variants/adafruit_camera_esp32s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_feather_esp32s3.json b/boards/adafruit_feather_esp32s3.json index 5796b0559..f668544b9 100644 --- a/boards/adafruit_feather_esp32s3.json +++ b/boards/adafruit_feather_esp32s3.json @@ -33,6 +33,7 @@ "variant": "adafruit_feather_esp32s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/adafruit_feather_esp32s3_nopsram.json b/boards/adafruit_feather_esp32s3_nopsram.json index 79ee24d1d..b38d0f808 100644 --- a/boards/adafruit_feather_esp32s3_nopsram.json +++ b/boards/adafruit_feather_esp32s3_nopsram.json @@ -33,6 +33,7 @@ "variant": "adafruit_feather_esp32s3_nopsram" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/adafruit_feather_esp32s3_reversetft.json b/boards/adafruit_feather_esp32s3_reversetft.json index fc3b8bc36..de9a8e53f 100644 --- a/boards/adafruit_feather_esp32s3_reversetft.json +++ b/boards/adafruit_feather_esp32s3_reversetft.json @@ -33,6 +33,7 @@ "variant": "adafruit_feather_esp32s3_reversetft" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/adafruit_feather_esp32s3_tft.json b/boards/adafruit_feather_esp32s3_tft.json index dbf7612bd..0b1d9433f 100644 --- a/boards/adafruit_feather_esp32s3_tft.json +++ b/boards/adafruit_feather_esp32s3_tft.json @@ -32,6 +32,7 @@ "variant": "adafruit_feather_esp32s3_tft" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/adafruit_matrixportal_esp32s3.json b/boards/adafruit_matrixportal_esp32s3.json index 3446cd217..df10505ad 100644 --- a/boards/adafruit_matrixportal_esp32s3.json +++ b/boards/adafruit_matrixportal_esp32s3.json @@ -33,6 +33,7 @@ "variant": "adafruit_matrixportal_esp32s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/adafruit_metro_esp32s3.json b/boards/adafruit_metro_esp32s3.json new file mode 100644 index 000000000..7b5b77d2f --- /dev/null +++ b/boards/adafruit_metro_esp32s3.json @@ -0,0 +1,67 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "partitions-16MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_METRO_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8145" + ], + [ + "0x239A", + "0x0145" + ], + [ + "0x239A", + "0x8146" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_metro_esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Metro ESP32-S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_metro_esp32s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5500", + "vendor": "Adafruit" +} diff --git a/boards/adafruit_qtpy_esp32s3_nopsram.json b/boards/adafruit_qtpy_esp32s3_nopsram.json index 15589da92..989ca7837 100644 --- a/boards/adafruit_qtpy_esp32s3_nopsram.json +++ b/boards/adafruit_qtpy_esp32s3_nopsram.json @@ -32,6 +32,7 @@ "variant": "adafruit_qtpy_esp32s3_nopsram" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/adafruit_qualia_s3_rgb666.json b/boards/adafruit_qualia_s3_rgb666.json new file mode 100644 index 000000000..e1607a913 --- /dev/null +++ b/boards/adafruit_qualia_s3_rgb666.json @@ -0,0 +1,67 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "partitions-16MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_QUALIA_S3_RGB666", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8147" + ], + [ + "0x239A", + "0x0147" + ], + [ + "0x239A", + "0x8148" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_qualia_s3_rgb666" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit Qualia ESP32-S3 RGB666", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_qualia_s3_rgb666/tinyuf2.bin" + ] + ] + }, + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5800", + "vendor": "Adafruit" +} diff --git a/boards/arduino_nano_esp32.json b/boards/arduino_nano_esp32.json index c6da4e227..e1bf757d5 100644 --- a/boards/arduino_nano_esp32.json +++ b/boards/arduino_nano_esp32.json @@ -30,6 +30,7 @@ "variant": "arduino_nano_nora" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/atd147_s3.json b/boards/atd147_s3.json new file mode 100644 index 000000000..8fb9d0e00 --- /dev/null +++ b/boards/atd147_s3.json @@ -0,0 +1,48 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ATD143_S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "atd147_s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ArtronShop ATD1.47-S3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/ArtronShop", + "vendor": "ArtronShop" +} diff --git a/boards/aventen_s3_sync.json b/boards/aventen_s3_sync.json new file mode 100644 index 000000000..83cda02d4 --- /dev/null +++ b/boards/aventen_s3_sync.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_AVENTEN_S3_SYNC", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "Aventen_S3_Sync" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Aventen S3 Sync", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.linkedin.com/company/aventen/", + "vendor": "Aventen" +} diff --git a/boards/bee_motion_s3.json b/boards/bee_motion_s3.json index c620b80c3..505986103 100644 --- a/boards/bee_motion_s3.json +++ b/boards/bee_motion_s3.json @@ -1,7 +1,7 @@ { "build": { "arduino": { - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s3_out.ld" }, "core": "esp32", "extra_flags": [ @@ -23,6 +23,7 @@ "variant": "Bee_Motion_S3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/bee_s3.json b/boards/bee_s3.json index 16e47ee79..98e966369 100644 --- a/boards/bee_s3.json +++ b/boards/bee_s3.json @@ -23,6 +23,7 @@ "variant": "Bee_S3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/bpi_leaf_s3.json b/boards/bpi_leaf_s3.json index c1d8a154c..62cc90ee9 100644 --- a/boards/bpi_leaf_s3.json +++ b/boards/bpi_leaf_s3.json @@ -24,6 +24,7 @@ "variant": "bpi_leaf_s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/cytron_maker_feather_aiot_s3.json b/boards/cytron_maker_feather_aiot_s3.json index 4b7a2704c..839a54be3 100644 --- a/boards/cytron_maker_feather_aiot_s3.json +++ b/boards/cytron_maker_feather_aiot_s3.json @@ -26,6 +26,7 @@ "variant": "cytron_maker_feather_aiot_s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/dfrobot_firebeetle2_esp32s3.json b/boards/dfrobot_firebeetle2_esp32s3.json index 0f87150d6..c1997db4e 100644 --- a/boards/dfrobot_firebeetle2_esp32s3.json +++ b/boards/dfrobot_firebeetle2_esp32s3.json @@ -27,6 +27,7 @@ "variant": "dfrobot_firebeetle2_esp32s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/dfrobot_romeo_esp32s3.json b/boards/dfrobot_romeo_esp32s3.json index 63a7cb472..55e69db5c 100644 --- a/boards/dfrobot_romeo_esp32s3.json +++ b/boards/dfrobot_romeo_esp32s3.json @@ -25,6 +25,7 @@ "variant": "dfrobot_romeo_esp32s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/edgebox-esp-100.json b/boards/edgebox-esp-100.json index 22aee2f8b..d00074d0c 100644 --- a/boards/edgebox-esp-100.json +++ b/boards/edgebox-esp-100.json @@ -18,6 +18,7 @@ "variant": "Edgebox-ESP-100" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/esp32-s3-devkitc-1.json b/boards/esp32-s3-devkitc-1.json index a2f8b22f5..b9c184c4b 100644 --- a/boards/esp32-s3-devkitc-1.json +++ b/boards/esp32-s3-devkitc-1.json @@ -24,6 +24,7 @@ "variant": "esp32s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/esp32-s3-devkitm-1.json b/boards/esp32-s3-devkitm-1.json new file mode 100644 index 000000000..a7a1d5e88 --- /dev/null +++ b/boards/esp32-s3-devkitm-1.json @@ -0,0 +1,50 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-S3-DevKitM-1", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitm-1.html", + "vendor": "Espressif" +} diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index 5a807a858..1d7e0c497 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -1,7 +1,7 @@ { "build": { "arduino":{ - "ldscript": "esp32_out.ld", + "ldscript": "esp32s3_out.ld", "memory_type": "opi_opi" }, "boot": "opi", diff --git a/boards/ioxesp32.json b/boards/ioxesp32.json new file mode 100644 index 000000000..e1575422e --- /dev/null +++ b/boards/ioxesp32.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_IOXESP32", + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "ioxesp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ArtronShop IOXESP32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.ioxesp32.com/", + "vendor": "ArtronShop" +} diff --git a/boards/ioxesp32ps.json b/boards/ioxesp32ps.json new file mode 100644 index 000000000..443f1c4c0 --- /dev/null +++ b/boards/ioxesp32ps.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_IOXESP32PS" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32", + "variant": "ioxesp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "ArtronShop IOXESP32", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.ioxesp32.com/", + "vendor": "ArtronShop" +} diff --git a/boards/lilygo-t-display-s3.json b/boards/lilygo-t-display-s3.json index 7230d3bd2..f7647271c 100644 --- a/boards/lilygo-t-display-s3.json +++ b/boards/lilygo-t-display-s3.json @@ -26,6 +26,7 @@ "variant": "lilygo_t_display_s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/lilygo-t-display.json b/boards/lilygo-t-display.json new file mode 100644 index 000000000..c55bdb152 --- /dev/null +++ b/boards/lilygo-t-display.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LILYGO_T_DISPLAY", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "hwids": [ + [ + "0x1A86", + "0x55D4" + ] + ], + "mcu": "esp32", + "variant": "lilygo_t_display" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "LilyGo T-Display", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "hhttps://www.lilygo.cc/products/lilygo%C2%AE-ttgo-t-display-1-14-inch-lcd-esp32-control-board", + "vendor": "LilyGo" +} diff --git a/boards/lolin_s3.json b/boards/lolin_s3.json index 30f360e0c..9daea1796 100644 --- a/boards/lolin_s3.json +++ b/boards/lolin_s3.json @@ -25,7 +25,8 @@ "variant": "lolin_s3" }, "connectivity": [ - "wifi" + "wifi", + "bluetooth" ], "debug": { "openocd_target": "esp32s3.cfg" diff --git a/boards/lolin_s3_mini.json b/boards/lolin_s3_mini.json index ad3794bcb..7f55f0bde 100644 --- a/boards/lolin_s3_mini.json +++ b/boards/lolin_s3_mini.json @@ -23,6 +23,7 @@ "variant": "lolin_s3_mini" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/m5stack-atoms3.json b/boards/m5stack-atoms3.json index f5e87d3ab..c80ded069 100644 --- a/boards/m5stack-atoms3.json +++ b/boards/m5stack-atoms3.json @@ -24,6 +24,7 @@ "variant": "m5stack_atoms3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/m5stack-cores3.json b/boards/m5stack-cores3.json index 72571e0b7..96bc6864e 100644 --- a/boards/m5stack-cores3.json +++ b/boards/m5stack-cores3.json @@ -7,7 +7,9 @@ "core": "esp32", "extra_flags": [ "-DARDUINO_M5STACK_CORES3", + "-DBOARD_HAS_PSRAM", "-DARDUINO_USB_MODE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1", "-DARDUINO_RUNNING_CORE=1", "-DARDUINO_EVENT_RUNNING_CORE=1" ], @@ -24,6 +26,7 @@ "variant": "m5stack_cores3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/m5stack-stamps3.json b/boards/m5stack-stamps3.json index 6c92e3b5d..31c7f25cd 100644 --- a/boards/m5stack-stamps3.json +++ b/boards/m5stack-stamps3.json @@ -24,6 +24,7 @@ "variant": "m5stack_stamp_s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/nebulas3.json b/boards/nebulas3.json index dc6236494..5dd922bea 100644 --- a/boards/nebulas3.json +++ b/boards/nebulas3.json @@ -25,6 +25,7 @@ "variant": "Nebula_S3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/redpill_esp32s3.json b/boards/redpill_esp32s3.json index 8dff2ff49..c9991e7f2 100644 --- a/boards/redpill_esp32s3.json +++ b/boards/redpill_esp32s3.json @@ -25,6 +25,7 @@ "variant": "redpill_esp32s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/seeed_xiao_esp32s3.json b/boards/seeed_xiao_esp32s3.json index cf98a6aa4..5c7171c88 100644 --- a/boards/seeed_xiao_esp32s3.json +++ b/boards/seeed_xiao_esp32s3.json @@ -31,6 +31,7 @@ "variant": "XIAO_ESP32S3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/tamc_termod_s3.json b/boards/tamc_termod_s3.json index 934c15fb1..0ddc5277e 100644 --- a/boards/tamc_termod_s3.json +++ b/boards/tamc_termod_s3.json @@ -26,6 +26,7 @@ "variant": "tamc_termod_s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/um_feathers3.json b/boards/um_feathers3.json index 4430f59b0..1a851fab5 100644 --- a/boards/um_feathers3.json +++ b/boards/um_feathers3.json @@ -26,6 +26,7 @@ "variant": "um_feathers3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/um_nanos3.json b/boards/um_nanos3.json new file mode 100644 index 000000000..921a36e3f --- /dev/null +++ b/boards/um_nanos3.json @@ -0,0 +1,51 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_NANOS3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8179" + ] + ], + "mcu": "esp32s3", + "variant": "um_nanos3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Unexpected Maker NanoS3", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://unexpectedmaker.com/shop/nanoS3", + "vendor": "Unexpected Maker" +} diff --git a/boards/um_pros3.json b/boards/um_pros3.json index b0b379834..8edcefac3 100644 --- a/boards/um_pros3.json +++ b/boards/um_pros3.json @@ -26,6 +26,7 @@ "variant": "um_pros3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/um_tinys3.json b/boards/um_tinys3.json index 6a9e3c14c..ed7b2a028 100644 --- a/boards/um_tinys3.json +++ b/boards/um_tinys3.json @@ -26,6 +26,7 @@ "variant": "um_tinys3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/unphone8.json b/boards/unphone8.json index 3ee0955d9..8dd371a07 100644 --- a/boards/unphone8.json +++ b/boards/unphone8.json @@ -20,6 +20,7 @@ "variant": "unphone8" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/unphone9.json b/boards/unphone9.json index e269a9662..1b4e8eed4 100644 --- a/boards/unphone9.json +++ b/boards/unphone9.json @@ -26,6 +26,7 @@ "variant": "unphone9" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { diff --git a/boards/wifiduino32s3.json b/boards/wifiduino32s3.json index fa8989469..6bef2bd51 100644 --- a/boards/wifiduino32s3.json +++ b/boards/wifiduino32s3.json @@ -23,6 +23,7 @@ "variant": "wifiduino32s3" }, "connectivity": [ + "bluetooth", "wifi" ], "debug": { From a7411b504e04ba48a01754bea41f8fc7954c18c7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:47:55 +0100 Subject: [PATCH 522/666] Use released alpha3 frameworks --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 6796410d3..f5516cfa8 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1850/framework-arduinoespressif32-release_v5.1-29db12e.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231205/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1851/framework-arduinoespressif32-solo1-release_v5.1-29db12e32f.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231205/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1852/framework-arduinoespressif32-ITEAD-release_v5.1-29db12e32f.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231205/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", From a21547edf6c1fbf5786f1a0077545f9acb280919 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 8 Dec 2023 13:08:37 +0100 Subject: [PATCH 523/666] Add a warning if there is a flash size mismatch with IDF config --- builder/frameworks/espidf.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 54989aaf9..1b62dbd67 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1574,6 +1574,22 @@ def _skip_prj_source_files(node): if sdk_config.get("MBEDTLS_CERTIFICATE_BUNDLE", False): generate_mbedtls_bundle(sdk_config) +# +# Check if flash size is set correctly in the IDF configuration file +# + +board_flash_size = board.get("upload.flash_size", "4MB") +idf_flash_size = sdk_config.get("ESPTOOLPY_FLASHSIZE", "4MB") +if board_flash_size != idf_flash_size: + print( + "Warning! Flash memory size mismatch detected. Expected %s, found %s!" + % (board_flash_size, idf_flash_size) + ) + print( + "Please select a proper value in your `sdkconfig.defaults` " + "or via the `menuconfig` target!" + ) + # # To embed firmware checksum a special argument for esptool.py is required # From 73fcf3a8f1f7b8c10a84345768acdfafcd8208f0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 8 Dec 2023 13:16:32 +0100 Subject: [PATCH 524/666] Add optional MMU page size flag to elf2bin if it's configurable --- builder/frameworks/espidf.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 1b62dbd67..34b4c21d6 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1594,9 +1594,24 @@ def _skip_prj_source_files(node): # To embed firmware checksum a special argument for esptool.py is required # +extra_elf2bin_flags = "--elf-sha256-offset 0xb0" +# https://github.com/espressif/esp-idf/blob/master/components/esptool_py/project_include.cmake#L58 +# For chips that support configurable MMU page size feature +# If page size is configured to values other than the default "64KB" in menuconfig, +mmu_page_size = "64KB" +if sdk_config.get("SOC_MMU_PAGE_SIZE_CONFIGURABLE", False): + if board_flash_size == "2MB": + mmu_page_size = "32KB" + elif board_flash_size == "1MB": + mmu_page_size = "16KB" + +if mmu_page_size != "64KB": + extra_elf2bin_flags += " --flash-mmu-page-size %s" % mmu_page_size + action = copy.deepcopy(env["BUILDERS"]["ElfToBin"].action) + action.cmd_list = env["BUILDERS"]["ElfToBin"].action.cmd_list.replace( - "-o", "--elf-sha256-offset 0xb0 -o" + "-o", extra_elf2bin_flags + " -o" ) env["BUILDERS"]["ElfToBin"].action = action From 52ce4af0d98d81934877a56d1d35ff969af93b9d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 8 Dec 2023 13:22:39 +0100 Subject: [PATCH 525/666] ident --- builder/frameworks/espidf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 34b4c21d6..f55f903e5 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -88,8 +88,8 @@ PROJECT_SRC_DIR = env.subst("$PROJECT_SRC_DIR") CMAKE_API_REPLY_PATH = os.path.join(".cmake", "api", "v1", "reply") SDKCONFIG_PATH = os.path.expandvars(board.get( - "build.esp-idf.sdkconfig_path", - os.path.join(PROJECT_DIR, "sdkconfig.%s" % env.subst("$PIOENV")), + "build.esp-idf.sdkconfig_path", + os.path.join(PROJECT_DIR, "sdkconfig.%s" % env.subst("$PIOENV")), )) @@ -1204,7 +1204,7 @@ def _create_venv(venv_dir): env.Execute( env.VerboseAction( '"$PYTHONEXE" -m venv --clear "%s"' % venv_dir, - "Creating a new virtual environment for IDF Python dependencies", + "Creating a new virtual environment for IDF Python dependencies", ) ) From bc0568e694efd4b056f005dd8193a8680f27e184 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 8 Dec 2023 14:44:05 +0100 Subject: [PATCH 526/666] Install Arduino framework only for Arduino or mixed Projects (#54) --- platform.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/platform.py b/platform.py index 620cf1b1b..f500fd7bd 100644 --- a/platform.py +++ b/platform.py @@ -37,12 +37,13 @@ def configure_default_packages(self, variables, targets): core_variant_build = (''.join(variables.get("build_flags", []))).replace("-D", " ") frameworks = variables.get("pioframework", []) - if "CORE32SOLO1" in core_variant_board or "FRAMEWORK_ARDUINO_SOLO1" in core_variant_build: - self.packages["framework-arduino-solo1"]["optional"] = False - elif "CORE32ITEAD" in core_variant_board or "FRAMEWORK_ARDUINO_ITEAD" in core_variant_build: - self.packages["framework-arduino-ITEAD"]["optional"] = False - else: - self.packages["framework-arduinoespressif32"]["optional"] = False + if "arduino" in frameworks: + if "CORE32SOLO1" in core_variant_board or "FRAMEWORK_ARDUINO_SOLO1" in core_variant_build: + self.packages["framework-arduino-solo1"]["optional"] = False + elif "CORE32ITEAD" in core_variant_board or "FRAMEWORK_ARDUINO_ITEAD" in core_variant_build: + self.packages["framework-arduino-ITEAD"]["optional"] = False + else: + self.packages["framework-arduinoespressif32"]["optional"] = False if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "spiffs") From cfb5a7ae91886945a0be16ce34ccdf1e24351026 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 8 Dec 2023 15:13:40 +0100 Subject: [PATCH 527/666] remove dead code --- platform.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/platform.py b/platform.py index f500fd7bd..0d3cfa22f 100644 --- a/platform.py +++ b/platform.py @@ -76,15 +76,6 @@ def configure_default_packages(self, variables, targets): elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: self.packages[p]["optional"] = False - # Use the latest toolchains available for IDF v5.1 - for target in ( - "xtensa-esp32", - "xtensa-esp32s2", - "xtensa-esp32s3", - "riscv32-esp" - ): - self.packages["toolchain-%s" % target]["version"] = "12.2.0+20230208" - for available_mcu in ("esp32", "esp32s2", "esp32s3"): if available_mcu == mcu: self.packages["toolchain-xtensa-%s" % mcu]["optional"] = False From ce3f0ba751df0a093ddc649dc5c74d75debe86aa Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 8 Dec 2023 15:26:24 +0100 Subject: [PATCH 528/666] C2 has no USB jtag --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index 0d3cfa22f..4a3b6e391 100644 --- a/platform.py +++ b/platform.py @@ -125,7 +125,7 @@ def _add_dynamic_options(self, board): "tumpa", ] - if board.get("build.mcu", "") in ("esp32c2", "esp32c3", "esp32c6", "esp32s3", "esp32h2"): + if board.get("build.mcu", "") in ("esp32c3", "esp32c6", "esp32s3", "esp32h2"): supported_debug_tools.append("esp-builtin") upload_protocol = board.manifest.get("upload", {}).get("protocol") From 25f008ee90d2727d45d7b9498c56a798d8261634 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 8 Dec 2023 16:37:29 +0100 Subject: [PATCH 529/666] Latest framework builds --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index f5516cfa8..e11ea929a 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.12.10", + "version": "2023.12.11", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231205/framework-arduinoespressif32.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1857/framework-arduinoespressif32-release_v5.1-7f2f56a.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231205/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1856/framework-arduinoespressif32-solo1-release_v5.1-7f2f56a.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.231205/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1855/framework-arduinoespressif32-ITEAD-release_v5.1-7f2f56a.zip" }, "framework-espidf": { "type": "framework", From a4322edad9b139404882e8549dc98470e9638172 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 9 Dec 2023 18:01:48 +0100 Subject: [PATCH 530/666] Latest IDF 5.1 and try esptool.py from git source --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index e11ea929a..e9011ad77 100644 --- a/platform.json +++ b/platform.json @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.231118/esp-idf-v5.1.2.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.231209/esp-idf-v5.1.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/Jason2866/esptool/releases/download/v4.7.0-dev4/esptool-4.7.0.zip" + "version": "https://github.com/Jason2866/esptool.git#release/v4.7.0-dev" }, "tool-dfuutil-arduino": { "type": "uploader", From 6fdccd672e0b3754329edcb21682dcef5c52fae2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 9 Dec 2023 18:07:03 +0100 Subject: [PATCH 531/666] back to esptool.py without `intelhex` --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index e9011ad77..cd0c22cf6 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/Jason2866/esptool.git#release/v4.7.0-dev" + "version": "https://github.com/Jason2866/esptool/releases/download/v4.7.0-dev4/esptool-4.7.0.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From ce1e250870e5ba81be1264333558f7e2cd8ee085 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Dec 2023 21:18:14 +0100 Subject: [PATCH 532/666] idf comp manager 1.4.1 --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index f55f903e5..aee61611c 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1110,7 +1110,7 @@ def _get_installed_pip_packages(python_exe_path): "future": ">=0.18.3", "pyparsing": "~=3.0.9" if IDF5 else ">=2.0.3,<2.4.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", - "idf-component-manager": "~=1.2.3" if IDF5 else "~=1.0", + "idf-component-manager": "~=1.4.1" if IDF5 else "~=1.0", "esp-idf-kconfig": "~=1.2.0" } From 31bfadb4afc038648360b51c03b8ee7f4ae720a7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:11:52 +0100 Subject: [PATCH 533/666] Tasmota tool-mklittlefs v4.0.0 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index cd0c22cf6..720e07447 100644 --- a/platform.json +++ b/platform.json @@ -120,7 +120,7 @@ "tool-mklittlefs": { "type": "uploader", "owner": "tasmota", - "version": "^3.2.0" + "version": "^4.0.0" }, "tool-mkfatfs": { "type": "uploader", From 9592d85e517debb3d7f29b24d08a7e9860d86bff Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:30:41 +0100 Subject: [PATCH 534/666] add C6 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 84ddf78fc..534ee2491 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: ### Development build Arduino 3.0.0-alpha3 and IDF 5.1.2 -Support for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32S2, ESP32S3 and ESP32-H2 +Support for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32C6, ESP32S2, ESP32S3 and ESP32-H2 ``` [platformio] platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.12.10/platform-espressif32.zip From c74d960700f3265edf38eb7729da1366cb8030a0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Dec 2023 20:39:15 +0100 Subject: [PATCH 535/666] back to mklittlefs v3.2.0 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 720e07447..cd0c22cf6 100644 --- a/platform.json +++ b/platform.json @@ -120,7 +120,7 @@ "tool-mklittlefs": { "type": "uploader", "owner": "tasmota", - "version": "^4.0.0" + "version": "^3.2.0" }, "tool-mkfatfs": { "type": "uploader", From e9b1b3ab2f73ce4d5471987f20c813df1d2b0cc7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:27:23 +0100 Subject: [PATCH 536/666] Update lolin_s2_mini.json --- boards/lolin_s2_mini.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boards/lolin_s2_mini.json b/boards/lolin_s2_mini.json index 59832f8cb..1282c1fa2 100644 --- a/boards/lolin_s2_mini.json +++ b/boards/lolin_s2_mini.json @@ -7,7 +7,8 @@ "extra_flags": [ "-DARDUINO_LOLIN_S2_MINI", "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MODE=0" ], "f_cpu": "240000000L", "f_flash": "80000000L", From ff4118c72abe6c629d794d9d0f697e0746e95616 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:13:19 +0100 Subject: [PATCH 537/666] Update lolin_s3.json --- boards/lolin_s3.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/boards/lolin_s3.json b/boards/lolin_s3.json index 9daea1796..8124b938a 100644 --- a/boards/lolin_s3.json +++ b/boards/lolin_s3.json @@ -7,10 +7,12 @@ }, "core": "esp32", "extra_flags": [ - "-DBOARD_HAS_PSRAM", "-DARDUINO_LOLIN_S3", + "-DBOARD_HAS_PSRAM", "-DARDUINO_USB_MODE=1", - "-DARDUINO_USB_CDC_ON_BOOT=1" + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", @@ -39,9 +41,7 @@ "upload": { "flash_size": "16MB", "maximum_ram_size": 327680, - "maximum_size": 16777216, - "use_1200bps_touch": true, - "wait_for_upload_port": true, + "maximum_size": 16777216, "require_upload_port": true, "speed": 460800 }, From a09da8f69f6196b862249f2f15f62441f1a832a7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:10:32 +0100 Subject: [PATCH 538/666] install ninja and make only for IDF --- platform.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/platform.py b/platform.py index 4a3b6e391..811a484dd 100644 --- a/platform.py +++ b/platform.py @@ -46,7 +46,7 @@ def configure_default_packages(self, variables, targets): self.packages["framework-arduinoespressif32"]["optional"] = False if "buildfs" in targets: - filesystem = variables.get("board_build.filesystem", "spiffs") + filesystem = variables.get("board_build.filesystem", "littlefs") if filesystem == "littlefs": self.packages["tool-mklittlefs"]["optional"] = False elif filesystem == "fatfs": @@ -69,12 +69,13 @@ def configure_default_packages(self, variables, targets): self.packages[gdb_package]["version"] = "~11.2.0" # Common packages for IDF and mixed Arduino+IDF projects - self.packages["toolchain-esp32ulp"]["optional"] = False - for p in self.packages: - if p in ("tool-cmake", "tool-ninja"): - self.packages[p]["optional"] = False - elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: - self.packages[p]["optional"] = False + if "espidf" in frameworks: + self.packages["toolchain-esp32ulp"]["optional"] = False + for p in self.packages: + if p in ("tool-cmake", "tool-ninja"): + self.packages[p]["optional"] = False + elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: + self.packages[p]["optional"] = False for available_mcu in ("esp32", "esp32s2", "esp32s3"): if available_mcu == mcu: From 4dd2366cc7ab28ea79e5f9f655fd8c67395ca2f0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 15 Dec 2023 17:55:17 +0100 Subject: [PATCH 539/666] Update IDF esptool framework Arduino --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index cd0c22cf6..c2232f31d 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1857/framework-arduinoespressif32-release_v5.1-7f2f56a.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1861/framework-arduinoespressif32-release_v5.1-6663f53.zip" }, "framework-arduino-solo1": { "type": "framework", @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.231209/esp-idf-v5.1.2.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.231214/esp-idf-v5.1.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/Jason2866/esptool/releases/download/v4.7.0-dev4/esptool-4.7.0.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0/esptool-4.7.0.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From 7b6e2c26b6789d5e576bf84bb8627dae39648a83 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 15 Dec 2023 18:01:35 +0100 Subject: [PATCH 540/666] no need to install mkspiffs tool --- platform.json | 1 + 1 file changed, 1 insertion(+) diff --git a/platform.json b/platform.json index c2232f31d..a60de6c4b 100644 --- a/platform.json +++ b/platform.json @@ -114,6 +114,7 @@ }, "tool-mkspiffs": { "type": "uploader", + "optional": true, "owner": "platformio", "version": "~2.230.0" }, From daba20e50367ae84bd7733059d8ed432691c3e3c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 22 Dec 2023 15:51:25 +0100 Subject: [PATCH 541/666] use mklittlefs v4.0.0 for unpacking FS image (#55) --- examples/espidf-arduino-blink/CMakeLists.txt | 1 - .../managed_components/.keep.me | 1 - .../src/idf_component.yml | 50 ------------------- .../espidf-arduino-littlefs/CMakeLists.txt | 3 +- .../managed_components/.keep.me | 0 .../src/idf_component.yml | 50 ------------------- platform.json | 2 +- platform.py | 6 +++ 8 files changed, 8 insertions(+), 105 deletions(-) delete mode 100644 examples/espidf-arduino-blink/managed_components/.keep.me delete mode 100644 examples/espidf-arduino-blink/src/idf_component.yml delete mode 100644 examples/espidf-arduino-littlefs/managed_components/.keep.me delete mode 100644 examples/espidf-arduino-littlefs/src/idf_component.yml diff --git a/examples/espidf-arduino-blink/CMakeLists.txt b/examples/espidf-arduino-blink/CMakeLists.txt index 0066d3962..6d4f2430b 100644 --- a/examples/espidf-arduino-blink/CMakeLists.txt +++ b/examples/espidf-arduino-blink/CMakeLists.txt @@ -1,4 +1,3 @@ cmake_minimum_required(VERSION 3.16.0) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -list(APPEND EXTRA_COMPONENT_DIRS managed_components) project(espidf-arduino-blink) diff --git a/examples/espidf-arduino-blink/managed_components/.keep.me b/examples/espidf-arduino-blink/managed_components/.keep.me deleted file mode 100644 index 8b1378917..000000000 --- a/examples/espidf-arduino-blink/managed_components/.keep.me +++ /dev/null @@ -1 +0,0 @@ - diff --git a/examples/espidf-arduino-blink/src/idf_component.yml b/examples/espidf-arduino-blink/src/idf_component.yml deleted file mode 100644 index a120bdbec..000000000 --- a/examples/espidf-arduino-blink/src/idf_component.yml +++ /dev/null @@ -1,50 +0,0 @@ -dependencies: - # Required IDF version - idf: ">=5.1" - - esp_littlefs: - git: https://github.com/joltwallet/esp_littlefs.git - - mdns: "^1.2.1" - # nghttp: "^1.50.0" - # esp_jpeg: "^1.0.4" - # esp-dsp: "^1.2.0" - # esp-sr: "^1.0.3" - # esp32-camera: "^2.0.3" - # esp-dl: - # git: https://github.com/espressif/esp-dl.git - # arduino: - # path: components/arduino - - # # Defining a dependency from the registry: - # # https://components.espressif.com/component/example/cmp - # example/cmp: "^3.3.3" # Automatically update minor releases - # - # # Other ways to define dependencies - # - # # For components maintained by Espressif only name can be used. - # # Same as `espressif/cmp` - # component: "~1.0.0" # Automatically update bugfix releases - # - # # Or in a longer form with extra parameters - # component2: - # version: ">=2.0.0" - # - # # For transient dependencies `public` flag can be set. - # # `public` flag doesn't have an effect for the `main` component. - # # All dependencies of `main` are public by default. - # public: true - # - # # For components hosted on non-default registry: - # service_url: "https://componentregistry.company.com" - # - # # For components in git repository: - # test_component: - # path: test_component - # git: ssh://git@gitlab.com/user/components.git - # - # # For test projects during component development - # # components can be used from a local directory - # # with relative or absolute path - # some_local_component: - # path: ../../projects/component diff --git a/examples/espidf-arduino-littlefs/CMakeLists.txt b/examples/espidf-arduino-littlefs/CMakeLists.txt index f5c097f0f..1c734fcfb 100644 --- a/examples/espidf-arduino-littlefs/CMakeLists.txt +++ b/examples/espidf-arduino-littlefs/CMakeLists.txt @@ -1,4 +1,3 @@ cmake_minimum_required(VERSION 3.16.0) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -list(APPEND EXTRA_COMPONENT_DIRS managed_components) -project(espidf-arduino-littlefs) \ No newline at end of file +project(espidf-arduino-littlefs) diff --git a/examples/espidf-arduino-littlefs/managed_components/.keep.me b/examples/espidf-arduino-littlefs/managed_components/.keep.me deleted file mode 100644 index e69de29bb..000000000 diff --git a/examples/espidf-arduino-littlefs/src/idf_component.yml b/examples/espidf-arduino-littlefs/src/idf_component.yml deleted file mode 100644 index a120bdbec..000000000 --- a/examples/espidf-arduino-littlefs/src/idf_component.yml +++ /dev/null @@ -1,50 +0,0 @@ -dependencies: - # Required IDF version - idf: ">=5.1" - - esp_littlefs: - git: https://github.com/joltwallet/esp_littlefs.git - - mdns: "^1.2.1" - # nghttp: "^1.50.0" - # esp_jpeg: "^1.0.4" - # esp-dsp: "^1.2.0" - # esp-sr: "^1.0.3" - # esp32-camera: "^2.0.3" - # esp-dl: - # git: https://github.com/espressif/esp-dl.git - # arduino: - # path: components/arduino - - # # Defining a dependency from the registry: - # # https://components.espressif.com/component/example/cmp - # example/cmp: "^3.3.3" # Automatically update minor releases - # - # # Other ways to define dependencies - # - # # For components maintained by Espressif only name can be used. - # # Same as `espressif/cmp` - # component: "~1.0.0" # Automatically update bugfix releases - # - # # Or in a longer form with extra parameters - # component2: - # version: ">=2.0.0" - # - # # For transient dependencies `public` flag can be set. - # # `public` flag doesn't have an effect for the `main` component. - # # All dependencies of `main` are public by default. - # public: true - # - # # For components hosted on non-default registry: - # service_url: "https://componentregistry.company.com" - # - # # For components in git repository: - # test_component: - # path: test_component - # git: ssh://git@gitlab.com/user/components.git - # - # # For test projects during component development - # # components can be used from a local directory - # # with relative or absolute path - # some_local_component: - # path: ../../projects/component diff --git a/platform.json b/platform.json index a60de6c4b..e9140f563 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1861/framework-arduinoespressif32-release_v5.1-6663f53.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1879/framework-arduinoespressif32-release_v5.1-72811e9.zip" }, "framework-arduino-solo1": { "type": "framework", diff --git a/platform.py b/platform.py index 811a484dd..5c1072bc7 100644 --- a/platform.py +++ b/platform.py @@ -58,6 +58,12 @@ def configure_default_packages(self, variables, targets): if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False + if "downloadfs" in targets: + filesystem = variables.get("board_build.filesystem", "littlefs") + if filesystem == "littlefs": + # Use Tasmota mklittlefs v4.0.0 to unpack, older version is incompatible + self.packages["tool-mklittlefs"]["version"] = "~4.0.0" + # Starting from v12, Espressif's toolchains are shipped without # bundled GDB. Instead, it's distributed as separate packages for Xtensa # and RISC-V targets. From 2d80dc4292965142b06a4d266bfedd89ff862cf9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 22 Dec 2023 17:00:09 +0100 Subject: [PATCH 542/666] add Arduino Nano --- platform.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform.py b/platform.py index 5c1072bc7..b22a1a2a1 100644 --- a/platform.py +++ b/platform.py @@ -64,6 +64,12 @@ def configure_default_packages(self, variables, targets): # Use Tasmota mklittlefs v4.0.0 to unpack, older version is incompatible self.packages["tool-mklittlefs"]["version"] = "~4.0.0" + # Currently only Arduino Nano ESP32 uses the dfuutil tool as uploader + if variables.get("board") == "arduino_nano_esp32": + self.packages["tool-dfuutil-arduino"]["optional"] = False + else: + del self.packages["tool-dfuutil-arduino"] + # Starting from v12, Espressif's toolchains are shipped without # bundled GDB. Instead, it's distributed as separate packages for Xtensa # and RISC-V targets. From ee3a9179ff9dfd2ad87594495e3653cc3c948a67 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 23 Dec 2023 12:50:51 +0100 Subject: [PATCH 543/666] build 1881 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index e9140f563..42d5f3637 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1879/framework-arduinoespressif32-release_v5.1-72811e9.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1881/framework-arduinoespressif32-release_v5.1-0e3c97b.zip" }, "framework-arduino-solo1": { "type": "framework", From 6d800b6ac5ddbd910ce5a19ff3a15b2b8742a57d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 28 Dec 2023 13:15:08 +0100 Subject: [PATCH 544/666] build 1882 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 42d5f3637..ad5a05c82 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1881/framework-arduinoespressif32-release_v5.1-0e3c97b.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1882/framework-arduinoespressif32-release_v5.1-cd18a10.zip" }, "framework-arduino-solo1": { "type": "framework", From 6b311e14115357eca244b7daf7439e9ec546d4af Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 28 Dec 2023 21:24:16 +0100 Subject: [PATCH 545/666] build 1883 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index ad5a05c82..a08d8e766 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1882/framework-arduinoespressif32-release_v5.1-cd18a10.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1883/framework-arduinoespressif32-release_v5.1-cd18a10.zip" }, "framework-arduino-solo1": { "type": "framework", From c3fcc6008b83a2f0980ecd553cf2ae13fbeee410 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 Jan 2024 15:56:51 +0100 Subject: [PATCH 546/666] 240110 --- platform.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform.json b/platform.json index a08d8e766..469a0be33 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2023.12.11", + "version": "2024.01.10", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,25 +33,25 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1883/framework-arduinoespressif32-release_v5.1-cd18a10.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240109/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1856/framework-arduinoespressif32-solo1-release_v5.1-7f2f56a.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240109/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1855/framework-arduinoespressif32-ITEAD-release_v5.1-7f2f56a.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240109/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", "optional": true, "owner": "platformio", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.231214/esp-idf-v5.1.2.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.240106/esp-idf-v5.1.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 8daa615ef6f21aba5717a7bbf6f5a3bfd82584e1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 Jan 2024 16:27:59 +0100 Subject: [PATCH 547/666] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 534ee2491..e4d98441d 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ Espressif Systems is a privately held fabless semiconductor company. They provid 1. [Install PlatformIO](http://platformio.org) 2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: -### Development build Arduino 3.0.0-alpha3 and IDF 5.1.2 +### Development build Arduino 3.0.0-alpha and IDF 5.1.2 Support for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32C6, ESP32S2, ESP32S3 and ESP32-H2 ``` [platformio] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.12.10/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.10/platform-espressif32.zip framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env From 77f5c0100cb3a4efa3e32558585d2fb992bf169b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 14 Jan 2024 16:53:44 +0100 Subject: [PATCH 548/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 469a0be33..10625a02c 100644 --- a/platform.json +++ b/platform.json @@ -50,7 +50,7 @@ "framework-espidf": { "type": "framework", "optional": true, - "owner": "platformio", + "owner": "tasmota", "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.240106/esp-idf-v5.1.2.zip" }, "toolchain-xtensa-esp32": { From e045f8b49afddd31e02087f623e1a3c3adf8f802 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:06:41 +0100 Subject: [PATCH 549/666] espressif ipv6 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 10625a02c..9367afb62 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240109/framework-arduinoespressif32.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1925/framework-arduinoespressif32-release_v5.1-d4d5f8a.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240109/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1927/framework-arduinoespressif32-solo1-release_v5.1-d4d5f8a.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240109/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1926/framework-arduinoespressif32-ITEAD-release_v5.1-d4d5f8a.zip" }, "framework-espidf": { "type": "framework", From 3bd1c9552894acc8857d6c432fb3a07905e976a7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:53:25 +0100 Subject: [PATCH 550/666] 2024.01.11 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 9367afb62..eed7f76d8 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2024.01.10", + "version": "2024.01.11", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1925/framework-arduinoespressif32-release_v5.1-d4d5f8a.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240115/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1927/framework-arduinoespressif32-solo1-release_v5.1-d4d5f8a.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240115/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1926/framework-arduinoespressif32-ITEAD-release_v5.1-d4d5f8a.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240115/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", From 883f9833bd085af4237513ee950ed2171c73ef6f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:56:30 +0100 Subject: [PATCH 551/666] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e4d98441d..ba2b0a6d4 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Espressif Systems is a privately held fabless semiconductor company. They provid Support for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32C6, ESP32S2, ESP32S3 and ESP32-H2 ``` [platformio] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.10/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.11/platform-espressif32.zip framework = arduino ``` to use the ESP32 Solo1 Arduino framework add in your env From 21ef9f075b7500e449b8711f2e20d1db94b4460f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 17 Jan 2024 14:25:06 +0100 Subject: [PATCH 552/666] IDF: Get rid of deprecated "pkg_resources" dependency --- builder/frameworks/espidf.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index aee61611c..2983387a3 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -26,7 +26,6 @@ import sys import shutil import os -import pkg_resources import platform as sys_platform import click @@ -1149,9 +1148,7 @@ def _get_installed_pip_packages(python_exe_path): # A special "esp-windows-curses" python package is required on Windows # for Menuconfig on IDF <5 - if not IDF5 and "esp-windows-curses" not in { - pkg.key for pkg in pkg_resources.working_set - }: + if not IDF5 and "esp-windows-curses" not in installed_packages: env.Execute( env.VerboseAction( '"%s" -m pip install "file://%s/tools/kconfig_new/esp-windows-curses"' From 12441e1ab7fe8ec674096713f460254b6d9eabba Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 19 Jan 2024 11:52:39 +0100 Subject: [PATCH 553/666] rm `tool-mkspiffs` --- platform.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/platform.json b/platform.json index eed7f76d8..4a4fb3de5 100644 --- a/platform.json +++ b/platform.json @@ -112,12 +112,6 @@ "owner": "platformio", "version": "~2.1100.0" }, - "tool-mkspiffs": { - "type": "uploader", - "optional": true, - "owner": "platformio", - "version": "~2.230.0" - }, "tool-mklittlefs": { "type": "uploader", "owner": "tasmota", From 356cd1db716f9cdeceb6f89e3e816599ae822927 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 19 Jan 2024 11:55:13 +0100 Subject: [PATCH 554/666] Update platform.py --- platform.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform.py b/platform.py index b22a1a2a1..7462bac2c 100644 --- a/platform.py +++ b/platform.py @@ -51,8 +51,6 @@ def configure_default_packages(self, variables, targets): self.packages["tool-mklittlefs"]["optional"] = False elif filesystem == "fatfs": self.packages["tool-mkfatfs"]["optional"] = False - else: - self.packages["tool-mkspiffs"]["optional"] = False if variables.get("upload_protocol"): self.packages["tool-openocd-esp32"]["optional"] = False if os.path.isdir("ulp"): From db63f4ea275f1644e0527a955da4b5b633a66793 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:24:44 +0100 Subject: [PATCH 555/666] remove `SPIFFS` --- builder/main.py | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/builder/main.py b/builder/main.py index 0374fe8b6..8c9e5dd42 100644 --- a/builder/main.py +++ b/builder/main.py @@ -211,7 +211,7 @@ def __fetch_fs_size(target, source, env): board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") toolchain_arch = "xtensa-%s" % mcu -filesystem = board.get("build.filesystem", "spiffs") +filesystem = board.get("build.filesystem", "littlefs") if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2"): toolchain_arch = "riscv32-esp" @@ -256,20 +256,8 @@ def __fetch_fs_size(target, source, env): ], ERASECMD='"$PYTHONEXE" "$OBJCOPY" $ERASEFLAGS erase_flash', - # mkspiffs package contains two different binaries for IDF and Arduino - MKFSTOOL="mk%s" % filesystem - + ( - ( - "_${PIOPLATFORM}_" - + ( - "espidf" - if "espidf" in env.subst("$PIOFRAMEWORK") - else "${PIOFRAMEWORK}" - ) - ) - if filesystem == "spiffs" - else "" - ), + MKFSTOOL="mk%s" % filesystem, + # Legacy `ESP32_SPIFFS_IMAGE_NAME` is used as the second fallback value for # backward compatibility ESP32_FS_IMAGE_NAME=env.get( @@ -310,7 +298,7 @@ def __fetch_fs_size(target, source, env): "-b", "$FS_BLOCK", ] - if filesystem in ("spiffs", "littlefs") + if filesystem in ("littlefs") else [] ) + ["$TARGET"] @@ -363,9 +351,6 @@ def __fetch_fs_size(target, source, env): env.VerboseAction( lambda source, target, env: _update_max_upload_size(env), "Retrieving maximum program size $SOURCES")) -# remove after PIO Core 3.6 release -elif set(["checkprogsize", "upload"]) & set(COMMAND_LINE_TARGETS): - _update_max_upload_size(env) # # Target: Print binary size From 3c809d56e33e8b185bc18feea209be3e701b749e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 20 Jan 2024 13:14:42 +0100 Subject: [PATCH 556/666] build 1932 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 4a4fb3de5..f1dada1ef 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240115/framework-arduinoespressif32.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1932/framework-arduinoespressif32-release_v5.1-713e54c.zip" }, "framework-arduino-solo1": { "type": "framework", From f0d95856ce73b0423ffc48a343c2feb09fa9362b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 20 Jan 2024 13:18:50 +0100 Subject: [PATCH 557/666] Delete examples/espidf-arduino-littlefs/littlefsbuilder.py --- examples/espidf-arduino-littlefs/littlefsbuilder.py | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 examples/espidf-arduino-littlefs/littlefsbuilder.py diff --git a/examples/espidf-arduino-littlefs/littlefsbuilder.py b/examples/espidf-arduino-littlefs/littlefsbuilder.py deleted file mode 100644 index 7adbd6f96..000000000 --- a/examples/espidf-arduino-littlefs/littlefsbuilder.py +++ /dev/null @@ -1,3 +0,0 @@ -Import("env") -platform = env.PioPlatform() -env.Replace( MKSPIFFSTOOL=platform.get_package_dir("tool-mklittlefs") + '/mklittlefs' ) # PlatformIO now believes it has actually created a SPIFFS From f23df1dd5ebd3d12e80580846c99a32f16e5a59b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 20 Jan 2024 13:19:12 +0100 Subject: [PATCH 558/666] Update platformio.ini --- examples/espidf-arduino-littlefs/platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/espidf-arduino-littlefs/platformio.ini b/examples/espidf-arduino-littlefs/platformio.ini index 3b15a9fd9..ec6e9e2f8 100644 --- a/examples/espidf-arduino-littlefs/platformio.ini +++ b/examples/espidf-arduino-littlefs/platformio.ini @@ -16,5 +16,4 @@ monitor_speed = 115200 [env:esp32-s3] board = esp32-s3-devkitc-1 board_build.filesystem = littlefs -extra_scripts = ./littlefsbuilder.py board_build.partitions = partitions_custom.csv From 8d35098a93a4cabe1b090b0e8c90841dd349adb4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 23 Jan 2024 18:26:50 +0100 Subject: [PATCH 559/666] Build 1934 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index f1dada1ef..9091d3cfc 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1932/framework-arduinoespressif32-release_v5.1-713e54c.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1934/framework-arduinoespressif32-release_v5.1-a98667c.zip" }, "framework-arduino-solo1": { "type": "framework", From 527b1891fe4ea2f1bc33092780e5f08d13db7df0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 24 Jan 2024 14:11:20 +0100 Subject: [PATCH 560/666] 24.01.12 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 9091d3cfc..a72b4f182 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2024.01.11", + "version": "2024.01.12", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1934/framework-arduinoespressif32-release_v5.1-a98667c.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240124/framework-arduinoespressif32.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240115/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240124/framework-arduinoespressif32-solo1.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240115/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240124/framework-arduinoespressif32-ITEAD.zip" }, "framework-espidf": { "type": "framework", From 4d49219a0ae374b75425e141a723dbf8b825d3cc Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 27 Jan 2024 18:15:51 +0100 Subject: [PATCH 561/666] build 1944 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index a72b4f182..361c1b508 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240124/framework-arduinoespressif32.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1944/framework-arduinoespressif32-release_v5.1-561aaa3.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240124/framework-arduinoespressif32-solo1.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1947/framework-arduinoespressif32-solo1-release_v5.1-561aaa3.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/arduino-esp32/releases/download/3.0.0.240124/framework-arduinoespressif32-ITEAD.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1946/framework-arduinoespressif32-ITEAD-release_v5.1-561aaa3.zip" }, "framework-espidf": { "type": "framework", From 39364ddb20fea4e7ff2e53b09622262a3b2b261d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 29 Jan 2024 18:34:38 +0100 Subject: [PATCH 562/666] Update examples.yml --- .github/workflows/examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 43a832c53..0afbce7cc 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -32,11 +32,11 @@ jobs: - "examples/espidf-ulp-riscv" runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: "recursive" - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install dependencies From 7f79dc4e576ab4475b7f670e6b69cccd32763d80 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 30 Jan 2024 13:10:54 +0100 Subject: [PATCH 563/666] Build 1951 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 361c1b508..0f16f2683 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1944/framework-arduinoespressif32-release_v5.1-561aaa3.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1951/framework-arduinoespressif32-release_v5.1-bf089e0.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1947/framework-arduinoespressif32-solo1-release_v5.1-561aaa3.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1954/framework-arduinoespressif32-solo1-release_v5.1-bf089e0.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1946/framework-arduinoespressif32-ITEAD-release_v5.1-561aaa3.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1953/framework-arduinoespressif32-ITEAD-release_v5.1-bf089e0.zip" }, "framework-espidf": { "type": "framework", From 31160dea99f1d9df2d05b0ab0b5c63c4c1a10827 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 31 Jan 2024 17:57:37 +0100 Subject: [PATCH 564/666] Build 1966 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 0f16f2683..c11ecbca5 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2024.01.12", + "version": "2024.01.13", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1951/framework-arduinoespressif32-release_v5.1-bf089e0.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1966/framework-arduinoespressif32-release_v5.1-b8e2640.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1954/framework-arduinoespressif32-solo1-release_v5.1-bf089e0.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1964/framework-arduinoespressif32-solo1-release_v5.1-b8e2640.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1953/framework-arduinoespressif32-ITEAD-release_v5.1-bf089e0.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1965/framework-arduinoespressif32-ITEAD-release_v5.1-b8e2640.zip" }, "framework-espidf": { "type": "framework", From a48e6f47e5854533024c9f5cbd28d0d0a7fd29f0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 31 Jan 2024 20:26:21 +0100 Subject: [PATCH 565/666] Update examples.yml --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 0afbce7cc..a9e035290 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, windows-2022, macOS-12] + os: [ubuntu-22.04, windows-2022, macos-14] example: - "examples/arduino-blink" - "examples/arduino-rmt-blink" From 9ec1837e76c6cca52f3962e1c6d18227ea828dbb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:43:10 +0100 Subject: [PATCH 566/666] Update platform.json --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index c11ecbca5..50ff2fe92 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1966/framework-arduinoespressif32-release_v5.1-b8e2640.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1976/framework-arduinoespressif32-release_v5.1-b8e2640.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1964/framework-arduinoespressif32-solo1-release_v5.1-b8e2640.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1978/framework-arduinoespressif32-solo1-release_v5.1-b8e2640.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1965/framework-arduinoespressif32-ITEAD-release_v5.1-b8e2640.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1977/framework-arduinoespressif32-ITEAD-release_v5.1-b8e2640.zip" }, "framework-espidf": { "type": "framework", From bf96bf154f2dc077a61f921463cb60798a8f1377 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 2 Feb 2024 18:50:45 +0100 Subject: [PATCH 567/666] esptool.py dev --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 50ff2fe92..16224f51c 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.0/esptool-4.7.0.zip" + "version": "https://github.com/Jason2866/esptool/releases/download/v4.7.0-240202/esptool-4.7.0-240202.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From e0a9a58a11082e1bc72ba39232cd7426954ece37 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 2 Feb 2024 18:52:40 +0100 Subject: [PATCH 568/666] Fix path --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 16224f51c..0b7cd5ee7 100644 --- a/platform.json +++ b/platform.json @@ -98,7 +98,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/Jason2866/esptool/releases/download/v4.7.0-240202/esptool-4.7.0-240202.zip" + "version": "https://github.com/Jason2866/esptool/releases/download/v4.7.0+240202/esptool-4.7.0-240202.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From a3907da7070a5cf6b67b1e9e096ecb033ec1ba5f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 7 Feb 2024 12:06:45 +0100 Subject: [PATCH 569/666] Update platform.py (#58) --- platform.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/platform.py b/platform.py index 7462bac2c..b9de8ac97 100644 --- a/platform.py +++ b/platform.py @@ -78,14 +78,14 @@ def configure_default_packages(self, variables, targets): # launch a GDB server in pipe mode while v11 works fine self.packages[gdb_package]["version"] = "~11.2.0" - # Common packages for IDF and mixed Arduino+IDF projects - if "espidf" in frameworks: - self.packages["toolchain-esp32ulp"]["optional"] = False - for p in self.packages: - if p in ("tool-cmake", "tool-ninja"): - self.packages[p]["optional"] = False - elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: - self.packages[p]["optional"] = False + # Common packages for IDF and mixed Arduino+IDF projects + if "espidf" in frameworks: + self.packages["toolchain-esp32ulp"]["optional"] = False + for p in self.packages: + if p in ("tool-cmake", "tool-ninja"): + self.packages[p]["optional"] = False + elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS: + self.packages[p]["optional"] = False for available_mcu in ("esp32", "esp32s2", "esp32s3"): if available_mcu == mcu: From e8dad14ef7848feb14f93da44567a1ffcb558a04 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:09:46 +0100 Subject: [PATCH 570/666] Build 1992 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 0b7cd5ee7..16d001d21 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1976/framework-arduinoespressif32-release_v5.1-b8e2640.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1992/framework-arduinoespressif32-release_v5.1-7f28f1f.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1978/framework-arduinoespressif32-solo1-release_v5.1-b8e2640.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1994/framework-arduinoespressif32-solo1-release_v5.1-7f28f1f.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1977/framework-arduinoespressif32-ITEAD-release_v5.1-b8e2640.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1993/framework-arduinoespressif32-ITEAD-release_v5.1-7f28f1f.zip" }, "framework-espidf": { "type": "framework", From 2f88831bf23e5d52be5bdbfe3a81733c536e7f03 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:24:59 +0100 Subject: [PATCH 571/666] Update IDF 5.1.2.240206 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 16d001d21..1eb635412 100644 --- a/platform.json +++ b/platform.json @@ -51,7 +51,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.240106/esp-idf-v5.1.2.zip" + "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.240206/esp-idf-v5.1.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From c38efd617c0a0cd538ec62ad6236160478d4ddbf Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:43:15 +0100 Subject: [PATCH 572/666] Create sdkconfig.defaults --- examples/espidf-blink/sdkconfig.defaults | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 examples/espidf-blink/sdkconfig.defaults diff --git a/examples/espidf-blink/sdkconfig.defaults b/examples/espidf-blink/sdkconfig.defaults new file mode 100644 index 000000000..eda3b11f3 --- /dev/null +++ b/examples/espidf-blink/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y From f68b42d3f5cec385606c798e51543626e5247f93 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:38:10 +0100 Subject: [PATCH 573/666] Update examples.yml --- .github/workflows/examples.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index a9e035290..05a9703db 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -30,6 +30,7 @@ jobs: - "examples/espidf-storage-sdcard" - "examples/espidf-ulp" - "examples/espidf-ulp-riscv" + - "examples/tasmota" runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -45,6 +46,11 @@ jobs: pip install wheel pip install -U https://github.com/platformio/platformio/archive/develop.zip pio pkg install --global --platform symlink://. + - name: git clone Tasmota and add to examples + if: matrix.example == 'examples/tasmota' + run: | + git clone https://github.com/arendst/Tasmota.git examples/tasmota + cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini - name: Build examples run: | pio run -d ${{ matrix.example }} From a7b1d67a785bff95401a1f6f859986ab47bfb687 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:40:09 +0100 Subject: [PATCH 574/666] add Tasmota to CI examplea --- examples/tasmota_platformio_override.ini | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 examples/tasmota_platformio_override.ini diff --git a/examples/tasmota_platformio_override.ini b/examples/tasmota_platformio_override.ini new file mode 100644 index 000000000..1eb73850c --- /dev/null +++ b/examples/tasmota_platformio_override.ini @@ -0,0 +1,5 @@ +[platformio] +default_envs = tasmota32 + +[env:tasmota32_base] +platform = symlink://. From 935b487f81c64061a9e21a77409f09c458db1909 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 8 Feb 2024 14:29:20 +0100 Subject: [PATCH 575/666] Build 2000 --- platform.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform.json b/platform.json index 1eb635412..017fa7a94 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2024.01.13", + "version": "2024.02.10", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1992/framework-arduinoespressif32-release_v5.1-7f28f1f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2000/framework-arduinoespressif32-release_v5.1-4c5ed1f.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1994/framework-arduinoespressif32-solo1-release_v5.1-7f28f1f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1999/framework-arduinoespressif32-solo1-release_v5.1-4c5ed1f.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1993/framework-arduinoespressif32-ITEAD-release_v5.1-7f28f1f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1998/framework-arduinoespressif32-ITEAD-release_v5.1-4c5ed1f.zip" }, "framework-espidf": { "type": "framework", From 1d792dc6a8737c0b7449725fd499a783680fd963 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 8 Feb 2024 14:43:07 +0100 Subject: [PATCH 576/666] check with Tasmota example frameworks "solo1" "ITEAD" too --- examples/tasmota_platformio_override.ini | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/tasmota_platformio_override.ini b/examples/tasmota_platformio_override.ini index 1eb73850c..46a8bc25e 100644 --- a/examples/tasmota_platformio_override.ini +++ b/examples/tasmota_platformio_override.ini @@ -1,5 +1,8 @@ [platformio] -default_envs = tasmota32 +default_envs = + tasmota32 + tasmota32solo1 + tasmota32-nspanel [env:tasmota32_base] platform = symlink://. From 33e80d116913f4c6ff143d58d2a4df9144ce63f1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 8 Feb 2024 14:45:00 +0100 Subject: [PATCH 577/666] Update platformio.ini --- examples/arduino-blink/platformio.ini | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 7a5ae6a81..5a053204e 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -32,16 +32,3 @@ platform = espressif32 framework = arduino board = esp32-h2-devkitm-1 monitor_speed = 115200 - -[env:esp32-solo1] -platform = espressif32 -framework = arduino -board = esp32-solo1 -build_flags = -DFRAMEWORK_ARDUINO_SOLO1 - -DLED_BUILTIN=23 - -[env:esp32-ITEAD] -platform = espressif32 -framework = arduino -board = esp32doit-devkit-v1 -build_flags = -DFRAMEWORK_ARDUINO_ITEAD From ce40bcfd2dfedf2459aa952f4b0f7bf7a2c554a9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 11:32:56 +0100 Subject: [PATCH 578/666] Add c2 Tas,ota --- examples/tasmota_platformio_override.ini | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/examples/tasmota_platformio_override.ini b/examples/tasmota_platformio_override.ini index 46a8bc25e..a2bcf5056 100644 --- a/examples/tasmota_platformio_override.ini +++ b/examples/tasmota_platformio_override.ini @@ -3,6 +3,16 @@ default_envs = tasmota32 tasmota32solo1 tasmota32-nspanel + tasmota32c2 [env:tasmota32_base] platform = symlink://. + +[env:tasmota32c2] +extends = env:tasmota32_base +board = esp32c2 +build_unflags = ${env:tasmota32_base.build_unflags + -mtarget-align +build_flags = ${env:tasmota32_base.build_flags} + -DFIRMWARE_TASMOTA32 + -DOTA_URL='""' From d47645b49f8bee16e7dc98fc6a27b8692e03f0bf Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 11:50:49 +0100 Subject: [PATCH 579/666] c2 no-lto --- examples/tasmota_platformio_override.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/tasmota_platformio_override.ini b/examples/tasmota_platformio_override.ini index a2bcf5056..dc80a73c6 100644 --- a/examples/tasmota_platformio_override.ini +++ b/examples/tasmota_platformio_override.ini @@ -13,6 +13,8 @@ extends = env:tasmota32_base board = esp32c2 build_unflags = ${env:tasmota32_base.build_unflags -mtarget-align + -flto build_flags = ${env:tasmota32_base.build_flags} + -fno-lto -DFIRMWARE_TASMOTA32 -DOTA_URL='""' From 7965f55d9e83d2ab0bcc76518f3448b0e46fa4cd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 13:28:14 +0100 Subject: [PATCH 580/666] Build 2004 --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 017fa7a94..ff7b492e3 100644 --- a/platform.json +++ b/platform.json @@ -33,19 +33,19 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2000/framework-arduinoespressif32-release_v5.1-4c5ed1f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2004/framework-arduinoespressif32-release_v5.1-4c5ed1f.zip" }, "framework-arduino-solo1": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1999/framework-arduinoespressif32-solo1-release_v5.1-4c5ed1f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2005/framework-arduinoespressif32-solo1-release_v5.1-4c5ed1f.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1998/framework-arduinoespressif32-ITEAD-release_v5.1-4c5ed1f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2006/framework-arduinoespressif32-ITEAD-release_v5.1-4c5ed1f.zip" }, "framework-espidf": { "type": "framework", From 79d8e63f9e7da505cefadb6e6676c95b8df092b5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 14:39:21 +0100 Subject: [PATCH 581/666] No big examples with Windows --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 05a9703db..665e0edac 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -47,7 +47,7 @@ jobs: pip install -U https://github.com/platformio/platformio/archive/develop.zip pio pkg install --global --platform symlink://. - name: git clone Tasmota and add to examples - if: matrix.example == 'examples/tasmota' + if: matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022' run: | git clone https://github.com/arendst/Tasmota.git examples/tasmota cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini From 1494b515affeb2df60fd0ef33cbb1b0cade9fc83 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 16:35:50 +0100 Subject: [PATCH 582/666] Update examples.yml --- .github/workflows/examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 665e0edac..1309f8414 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -52,5 +52,6 @@ jobs: git clone https://github.com/arendst/Tasmota.git examples/tasmota cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini - name: Build examples + if: matrix.example != 'examples/tasmota' && matrix.os != 'windows-2022' run: | pio run -d ${{ matrix.example }} From 7eceb64616c4dc8d3d63224dd52bcf166515565f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 16:39:35 +0100 Subject: [PATCH 583/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index ff7b492e3..3e3f0cca8 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2004/framework-arduinoespressif32-release_v5.1-4c5ed1f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2008/framework-arduinoespressif32-release_v5.1-4c5ed1f.zip" }, "framework-arduino-solo1": { "type": "framework", From cb3e625f5ec4189b7bc12b95a9298236520f2022 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:32:00 +0100 Subject: [PATCH 584/666] Update examples.yml --- .github/workflows/examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 1309f8414..7c1578934 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -47,11 +47,11 @@ jobs: pip install -U https://github.com/platformio/platformio/archive/develop.zip pio pkg install --global --platform symlink://. - name: git clone Tasmota and add to examples - if: matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022' + if: ${{ matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022' }} run: | git clone https://github.com/arendst/Tasmota.git examples/tasmota cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini - name: Build examples - if: matrix.example != 'examples/tasmota' && matrix.os != 'windows-2022' + if: ${{ matrix.example != 'examples/tasmota' && matrix.os != 'windows-2022' }} run: | pio run -d ${{ matrix.example }} From ab232b2c62e4b081f90ebc4c1311d78c0484bdfd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:33:14 +0100 Subject: [PATCH 585/666] Build 2010 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 3e3f0cca8..43fde9eb8 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2008/framework-arduinoespressif32-release_v5.1-4c5ed1f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2010/framework-arduinoespressif32-release_v5.1-4c5ed1f.zip" }, "framework-arduino-solo1": { "type": "framework", From ffa32ba3477a9f4dd7246480371736875818dbac Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 18:45:05 +0100 Subject: [PATCH 586/666] Update examples.yml --- .github/workflows/examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 7c1578934..fd85de332 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -47,11 +47,11 @@ jobs: pip install -U https://github.com/platformio/platformio/archive/develop.zip pio pkg install --global --platform symlink://. - name: git clone Tasmota and add to examples - if: ${{ matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022' }} + if: "matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022'" run: | git clone https://github.com/arendst/Tasmota.git examples/tasmota cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini - name: Build examples - if: ${{ matrix.example != 'examples/tasmota' && matrix.os != 'windows-2022' }} + if: "matrix.example != 'examples/tasmota' && matrix.os != 'windows-2022'" run: | pio run -d ${{ matrix.example }} From 55283c2ce46c22827be1a3b56a1f7be56f04158f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 19:10:08 +0100 Subject: [PATCH 587/666] Update examples.yml --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index fd85de332..d3b78af3e 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -52,6 +52,6 @@ jobs: git clone https://github.com/arendst/Tasmota.git examples/tasmota cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini - name: Build examples - if: "matrix.example != 'examples/tasmota' && matrix.os != 'windows-2022'" + if: "matrix.example != 'examples/tasmota' || matrix.os != 'windows-2022'" run: | pio run -d ${{ matrix.example }} From 7f6937c81a14b0f5589092a45c04ee8d54fae882 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 10 Feb 2024 11:21:29 +0100 Subject: [PATCH 588/666] debug speed default 5000khz --- platform.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform.py b/platform.py index b9de8ac97..9722a8fa8 100644 --- a/platform.py +++ b/platform.py @@ -213,6 +213,11 @@ def configure_debug_session(self, debug_config): build_extra_data = debug_config.build_data.get("extra", {}) flash_images = build_extra_data.get("flash_images", []) + if "openocd" in (debug_config.server or {}).get("executable", ""): + debug_config.server["arguments"].extend( + ["-c", "adapter speed %s" % (debug_config.speed or "5000")] + ) + ignore_conds = [ debug_config.load_cmds != ["load"], not flash_images, From f166dfb4a0655e64389f4706d06807f83cec5e7a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 10 Feb 2024 11:46:11 +0100 Subject: [PATCH 589/666] debug 5000khz default --- builder/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builder/main.py b/builder/main.py index 8c9e5dd42..6d98bfa48 100644 --- a/builder/main.py +++ b/builder/main.py @@ -471,6 +471,8 @@ def __fetch_fs_size(target, source, env): debug_tools.get(upload_protocol).get("server").get("arguments", [])) openocd_args.extend( [ + "-c", + "adapter speed %s" % env.GetProjectOption("debug_speed", "5000"), "-c", "program_esp {{$SOURCE}} %s verify" % ( From e1fbe0883c127ab0d32f8029c06ca99f2cd4906b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 11 Feb 2024 19:06:13 +0100 Subject: [PATCH 590/666] fixed ITEAD and solo1 frameworks --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 43fde9eb8..48ecf7c76 100644 --- a/platform.json +++ b/platform.json @@ -39,13 +39,13 @@ "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2005/framework-arduinoespressif32-solo1-release_v5.1-4c5ed1f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2013/framework-arduinoespressif32-solo1-release_v5.1-4c5ed1f.zip" }, "framework-arduino-ITEAD": { "type": "framework", "optional": true, "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2006/framework-arduinoespressif32-ITEAD-release_v5.1-4c5ed1f.zip" + "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2014/framework-arduinoespressif32-ITEAD-release_v5.1-4c5ed1f.zip" }, "framework-espidf": { "type": "framework", From 9e73b1deda6b7ac6ff2ee1198ac932ad0f0eceb6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 11 Feb 2024 19:20:05 +0100 Subject: [PATCH 591/666] test build tasmota with windows --- .github/workflows/examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index d3b78af3e..7cf16e699 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -47,11 +47,11 @@ jobs: pip install -U https://github.com/platformio/platformio/archive/develop.zip pio pkg install --global --platform symlink://. - name: git clone Tasmota and add to examples - if: "matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022'" + #if: "matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022'" run: | git clone https://github.com/arendst/Tasmota.git examples/tasmota cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini - name: Build examples - if: "matrix.example != 'examples/tasmota' || matrix.os != 'windows-2022'" + #if: "matrix.example != 'examples/tasmota' || matrix.os != 'windows-2022'" run: | pio run -d ${{ matrix.example }} From 7eed2075116b6a61b76b7e49628a6992306e117e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 11 Feb 2024 20:20:25 +0100 Subject: [PATCH 592/666] no CI example Tasmota wirh --- .github/workflows/examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 7cf16e699..d3b78af3e 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -47,11 +47,11 @@ jobs: pip install -U https://github.com/platformio/platformio/archive/develop.zip pio pkg install --global --platform symlink://. - name: git clone Tasmota and add to examples - #if: "matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022'" + if: "matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022'" run: | git clone https://github.com/arendst/Tasmota.git examples/tasmota cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini - name: Build examples - #if: "matrix.example != 'examples/tasmota' || matrix.os != 'windows-2022'" + if: "matrix.example != 'examples/tasmota' || matrix.os != 'windows-2022'" run: | pio run -d ${{ matrix.example }} From 106b1a5d606d22fc5a434e30af869777158c265b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 12 Feb 2024 18:41:41 +0100 Subject: [PATCH 593/666] Print full path to missing part table --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 2983387a3..963b8ff91 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -962,7 +962,7 @@ def generate_empty_partition_image(binary_path, image_size): def get_partition_info(pt_path, pt_offset, pt_params): if not os.path.isfile(pt_path): sys.stderr.write( - "Missing partition table file `%s`\n" % os.path.basename(pt_path) + "Missing partition table file `%s`\n" % pt_path ) env.Exit(1) From 94a9725be7c12602ffcaab39d1e36a84ac8ac35b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:26:26 +0100 Subject: [PATCH 594/666] Arduino core 3.0.0 based on IDF 5.1 --- .github/workflows/examples.yml | 7 -- README.md | 38 ++++----- builder/frameworks/arduino.py | 81 +------------------ builder/main.py | 30 ++++--- examples/arduino-blink/platformio.ini | 17 ++-- examples/espidf-arduino-blink/platformio.ini | 11 ++- .../partitions_custom.csv | 7 +- .../espidf-arduino-littlefs/platformio.ini | 10 ++- .../espidf-arduino-wifiscan/platformio.ini | 6 ++ examples/tasmota_platformio_override.ini | 20 ----- platform.json | 30 +++---- platform.py | 13 +-- 12 files changed, 86 insertions(+), 184 deletions(-) delete mode 100644 examples/tasmota_platformio_override.ini diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index d3b78af3e..a9e035290 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -30,7 +30,6 @@ jobs: - "examples/espidf-storage-sdcard" - "examples/espidf-ulp" - "examples/espidf-ulp-riscv" - - "examples/tasmota" runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -46,12 +45,6 @@ jobs: pip install wheel pip install -U https://github.com/platformio/platformio/archive/develop.zip pio pkg install --global --platform symlink://. - - name: git clone Tasmota and add to examples - if: "matrix.example == 'examples/tasmota' && matrix.os != 'windows-2022'" - run: | - git clone https://github.com/arendst/Tasmota.git examples/tasmota - cp examples/tasmota_platformio_override.ini examples/tasmota/platformio_override.ini - name: Build examples - if: "matrix.example != 'examples/tasmota' || matrix.os != 'windows-2022'" run: | pio run -d ${{ matrix.example }} diff --git a/README.md b/README.md index ba2b0a6d4..61f6b6314 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,27 @@ -[![Build_special_firmware](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md) +# Espressif 32: development platform for [PlatformIO](https://platformio.org) +[![Build Status](https://github.com/platformio/platform-espressif32/workflows/Examples/badge.svg)](https://github.com/platformio/platform-espressif32/actions) -# Tasmota Espressif 32: development platform for [PlatformIO](http://platformio.org) +ESP32 is a series of low-cost, low-power system on a chip microcontrollers with integrated Wi-Fi and Bluetooth. ESP32 integrates an antenna switch, RF balun, power amplifier, low-noise receive amplifier, filters, and power management modules. -[![Examples](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml/badge.svg)](https://github.com/Jason2866/platform-espressif32/actions/workflows/examples.yml)[![GitHub Releases](https://img.shields.io/github/downloads/tasmota/platform-espressif32/total?label=downloads)](https://github.com/tasmota/platform-espressif32/releases/latest) +* [Home](https://registry.platformio.org/platforms/platformio/espressif32) (home page in the PlatformIO Registry) +* [Documentation](https://docs.platformio.org/page/platforms/espressif32.html) (advanced usage, packages, boards, frameworks, etc.) -Espressif Systems is a privately held fabless semiconductor company. They provide wireless communications and Wi-Fi chips which are widely used in mobile devices and the Internet of Things applications. +# Usage -* [Home](http://platformio.org/platforms/espressif32) (home page in PlatformIO Platform Registry) -* [Documentation](http://docs.platformio.org/page/platforms/espressif32.html) (advanced usage, packages, boards, frameworks, etc.) +1. [Install PlatformIO](https://platformio.org) +2. Create PlatformIO project and configure a platform option in [platformio.ini](https://docs.platformio.org/page/projectconf.html) file: -# Usage +## Development version -1. [Install PlatformIO](http://platformio.org) -2. Create PlatformIO project and configure a platform option in [platformio.ini](http://docs.platformio.org/page/projectconf.html) file: +```ini +[env:development] +platform = https://github.com/jason2866/platform-espressif32.git#Arduino/IDF5_org -### Development build Arduino 3.0.0-alpha and IDF 5.1.2 -Support for the ESP32/ESP32solo1, ESP32C2, ESP32C3, ESP32C6, ESP32S2, ESP32S3 and ESP32-H2 -``` -[platformio] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.11/platform-espressif32.zip -framework = arduino -``` -to use the ESP32 Solo1 Arduino framework add in your env -``` -[env:esp32solo1] -board = esp32-solo1 -build_flags = -DFRAMEWORK_ARDUINO_SOLO1 +board = ... +... ``` -The frameworks are here [https://github.com/tasmota/arduino-esp32/releases](https://github.com/tasmota/arduino-esp32/releases) # Configuration -Please navigate to [documentation](http://docs.platformio.org/page/platforms/espressif32.html). +Please navigate to [documentation](https://docs.platformio.org/page/platforms/espressif32.html). diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 94cd2f982..4af76df8b 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -22,90 +22,17 @@ http://arduino.cc/en/Reference/HomePage """ -import subprocess -import json -import semantic_version from os.path import join -from SCons.Script import COMMAND_LINE_TARGETS, DefaultEnvironment, SConscript -from platformio.package.version import pepver_to_semver +from SCons.Script import DefaultEnvironment, SConscript env = DefaultEnvironment() - -extra_flags = ''.join([element.replace("-D", " ") for element in env.BoardConfig().get("build.extra_flags", "")]) -build_flags = ''.join([element.replace("-D", " ") for element in env.GetProjectOption("build_flags")]) +board = env.BoardConfig() +build_core = board.get("build.core", "").lower() SConscript("_embed_files.py", exports="env") -if ("CORE32SOLO1" in extra_flags or "FRAMEWORK_ARDUINO_SOLO1" in build_flags) and ("arduino" in env.subst("$PIOFRAMEWORK") and "espidf" not in env.subst("$PIOFRAMEWORK")): - SConscript( - join(DefaultEnvironment().PioPlatform().get_package_dir( - "framework-arduino-solo1"), "tools", "platformio-build.py")) - -elif ("CORE32ITEAD" in extra_flags or "FRAMEWORK_ARDUINO_ITEAD" in build_flags) and ("arduino" in env.subst("$PIOFRAMEWORK") and "espidf" not in env.subst("$PIOFRAMEWORK")): - SConscript( - join(DefaultEnvironment().PioPlatform().get_package_dir( - "framework-arduino-ITEAD"), "tools", "platformio-build.py")) - -elif "arduino" in env.subst("$PIOFRAMEWORK") and "CORE32SOLO1" not in extra_flags and "FRAMEWORK_ARDUINO_SOLO1" not in build_flags and "CORE32ITEAD" not in extra_flags and "FRAMEWORK_ARDUINO_ITEAD" not in build_flags and "espidf" not in env.subst("$PIOFRAMEWORK"): +if "espidf" not in env.subst("$PIOFRAMEWORK"): SConscript( join(DefaultEnvironment().PioPlatform().get_package_dir( "framework-arduinoespressif32"), "tools", "platformio-build.py")) - -def install_python_deps(): - def _get_installed_pip_packages(): - result = {} - packages = {} - pip_output = subprocess.check_output( - [ - env.subst("$PYTHONEXE"), - "-m", - "pip", - "list", - "--format=json", - "--disable-pip-version-check", - ] - ) - try: - packages = json.loads(pip_output) - except: - print("Warning! Couldn't extract the list of installed Python packages.") - return {} - for p in packages: - result[p["name"]] = pepver_to_semver(p["version"]) - - return result - - deps = { - "wheel": ">=0.35.1", - "zopfli": ">=0.2.2", - "tasmota-metrics": ">=0.4.3" - } - - installed_packages = _get_installed_pip_packages() - packages_to_install = [] - for package, spec in deps.items(): - if package not in installed_packages: - packages_to_install.append(package) - else: - version_spec = semantic_version.Spec(spec) - if not version_spec.match(installed_packages[package]): - packages_to_install.append(package) - - if packages_to_install: - env.Execute( - env.VerboseAction( - ( - '"$PYTHONEXE" -m pip install -U ' - + " ".join( - [ - '"%s%s"' % (p, deps[p]) - for p in packages_to_install - ] - ) - ), - "Installing Python dependencies", - ) - ) - -install_python_deps() diff --git a/builder/main.py b/builder/main.py index 6d98bfa48..28117dc88 100644 --- a/builder/main.py +++ b/builder/main.py @@ -29,15 +29,7 @@ # Helpers # -extra_flags = ''.join([element.replace("-D", " ") for element in env.BoardConfig().get("build.extra_flags", "")]) -build_flags = ''.join([element.replace("-D", " ") for element in env.GetProjectOption("build_flags")]) - -if "CORE32SOLO1" in extra_flags or "FRAMEWORK_ARDUINO_SOLO1" in build_flags: - FRAMEWORK_DIR = platform.get_package_dir("framework-arduino-solo1") -elif "CORE32ITEAD" in extra_flags or "FRAMEWORK_ARDUINO_ITEAD" in build_flags: - FRAMEWORK_DIR = platform.get_package_dir("framework-arduino-ITEAD") -else: - FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") +FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") def BeforeUpload(target, source, env): upload_options = {} @@ -211,7 +203,7 @@ def __fetch_fs_size(target, source, env): board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") toolchain_arch = "xtensa-%s" % mcu -filesystem = board.get("build.filesystem", "littlefs") +filesystem = board.get("build.filesystem", "spiffs") if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2"): toolchain_arch = "riscv32-esp" @@ -256,8 +248,20 @@ def __fetch_fs_size(target, source, env): ], ERASECMD='"$PYTHONEXE" "$OBJCOPY" $ERASEFLAGS erase_flash', - MKFSTOOL="mk%s" % filesystem, - + # mkspiffs package contains two different binaries for IDF and Arduino + MKFSTOOL="mk%s" % filesystem + + ( + ( + "_${PIOPLATFORM}_" + + ( + "espidf" + if "espidf" in env.subst("$PIOFRAMEWORK") + else "${PIOFRAMEWORK}" + ) + ) + if filesystem == "spiffs" + else "" + ), # Legacy `ESP32_SPIFFS_IMAGE_NAME` is used as the second fallback value for # backward compatibility ESP32_FS_IMAGE_NAME=env.get( @@ -298,7 +302,7 @@ def __fetch_fs_size(target, source, env): "-b", "$FS_BLOCK", ] - if filesystem in ("littlefs") + if filesystem in ("spiffs", "littlefs") else [] ) + ["$TARGET"] diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 5a053204e..c821ed35c 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -14,12 +14,6 @@ board = esp-wrover-kit monitor_speed = 115200 build_flags = -DLED_BUILTIN=2 - -[env:esp32-c2-devkitm-1] -platform = espressif32 -framework = arduino -board = esp32-c2-devkitm-1 -monitor_speed = 115200 [env:esp32-c6-devkitc-1] platform = espressif32 @@ -27,8 +21,9 @@ framework = arduino board = esp32-c6-devkitc-1 monitor_speed = 115200 -[env:esp32-h2-devkitm-1] -platform = espressif32 -framework = arduino -board = esp32-h2-devkitm-1 -monitor_speed = 115200 +; changes needed in Arduino code: https://github.com/espressif/arduino-esp32/issues/9237 +;[env:esp32-h2-devkitm-1] +;platform = espressif32 +;framework = arduino +;board = esp32-h2-devkitm-1 +;monitor_speed = 115200 diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 3a2fcf41c..6a8cdb961 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -11,14 +11,17 @@ platform = espressif32 framework = arduino, espidf build_flags = - -D CONFIG_BLINK_GPIO=2 + -DCONFIG_BLINK_GPIO=2 monitor_speed = 115200 +board_build.esp-idf.preserve_source_file_extension = yes +board_build.embed_txtfiles = + managed_components/espressif__esp_insights/server_certs/https_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt ;[env:esp32dev] ;board = esp32dev -;[env:esp32-c2-devkitm-1] -;board = esp32-c2-devkitm-1 - [env:esp32-c6-devkitm-1] board = esp32-c6-devkitm-1 diff --git a/examples/espidf-arduino-littlefs/partitions_custom.csv b/examples/espidf-arduino-littlefs/partitions_custom.csv index 643161620..960469b82 100644 --- a/examples/espidf-arduino-littlefs/partitions_custom.csv +++ b/examples/espidf-arduino-littlefs/partitions_custom.csv @@ -1,6 +1,7 @@ # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x5000, otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x80000, -app1, app, ota_1, 0x90000, 0x110000, -spiffs, data, spiffs, 0x1A0000,0x260000, +app0, app, ota_0, 0x10000, 0x140000, +app1, app, ota_1, 0x150000,0x140000, +spiffs, data, spiffs, 0x290000,0x160000, +coredump, data, coredump,0x3F0000,0x10000, diff --git a/examples/espidf-arduino-littlefs/platformio.ini b/examples/espidf-arduino-littlefs/platformio.ini index ec6e9e2f8..a23e3ef25 100644 --- a/examples/espidf-arduino-littlefs/platformio.ini +++ b/examples/espidf-arduino-littlefs/platformio.ini @@ -12,8 +12,14 @@ platform = espressif32 framework = arduino, espidf monitor_speed = 115200 +board_build.esp-idf.preserve_source_file_extension = yes +board_build.embed_txtfiles = + managed_components/espressif__esp_insights/server_certs/https_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt -[env:esp32-s3] -board = esp32-s3-devkitc-1 +[env:esp32dev] +board = esp32dev board_build.filesystem = littlefs board_build.partitions = partitions_custom.csv diff --git a/examples/espidf-arduino-wifiscan/platformio.ini b/examples/espidf-arduino-wifiscan/platformio.ini index 28bfc100d..3dea0eabf 100644 --- a/examples/espidf-arduino-wifiscan/platformio.ini +++ b/examples/espidf-arduino-wifiscan/platformio.ini @@ -11,6 +11,12 @@ platform = espressif32 framework = arduino, espidf monitor_speed = 115200 +board_build.esp-idf.preserve_source_file_extension = yes +board_build.embed_txtfiles = + managed_components/espressif__esp_insights/server_certs/https_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt + managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt [env:esp-wrover-kit] board = esp-wrover-kit diff --git a/examples/tasmota_platformio_override.ini b/examples/tasmota_platformio_override.ini deleted file mode 100644 index dc80a73c6..000000000 --- a/examples/tasmota_platformio_override.ini +++ /dev/null @@ -1,20 +0,0 @@ -[platformio] -default_envs = - tasmota32 - tasmota32solo1 - tasmota32-nspanel - tasmota32c2 - -[env:tasmota32_base] -platform = symlink://. - -[env:tasmota32c2] -extends = env:tasmota32_base -board = esp32c2 -build_unflags = ${env:tasmota32_base.build_unflags - -mtarget-align - -flto -build_flags = ${env:tasmota32_base.build_flags} - -fno-lto - -DFIRMWARE_TASMOTA32 - -DOTA_URL='""' diff --git a/platform.json b/platform.json index 48ecf7c76..1ad015170 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/tasmota/platform-espressif32.git" }, - "version": "2024.02.10", + "version": "2024.00.99", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -32,26 +32,20 @@ "framework-arduinoespressif32": { "type": "framework", "optional": true, - "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2010/framework-arduinoespressif32-release_v5.1-4c5ed1f.zip" - }, - "framework-arduino-solo1": { - "type": "framework", - "optional": true, - "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2013/framework-arduinoespressif32-solo1-release_v5.1-4c5ed1f.zip" + "owner": "espressif", + "version": "https://github.com/espressif/arduino-esp32/archive/48072ee09802739cf4883c044e65bd1a77823038.zip" }, - "framework-arduino-ITEAD": { + "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, - "owner": "tasmota", - "version": "https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2014/framework-arduinoespressif32-ITEAD-release_v5.1-4c5ed1f.zip" + "owner": "espressif", + "version": "https://github.com/espressif/esp32-arduino-libs/archive/bef34d984ad9348f2055653b62998a023273dece.zip" }, "framework-espidf": { "type": "framework", "optional": true, - "owner": "tasmota", - "version": "https://github.com/tasmota/esp-idf/releases/download/v5.1.2.240206/esp-idf-v5.1.2.zip" + "owner": "espressif", + "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.2.240206/esp-idf-v5.1.2.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", @@ -98,7 +92,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/Jason2866/esptool/releases/download/v4.7.0+240202/esptool-4.7.0-240202.zip" + "version": "https://github.com/Jason2866/esptool/releases/download/v4.7.0.240211/esptool.zip" }, "tool-dfuutil-arduino": { "type": "uploader", @@ -123,6 +117,12 @@ "owner": "platformio", "version": "~2.0.0" }, + "tool-mkspiffs": { + "type": "uploader", + "optional": true, + "owner": "platformio", + "version": "~2.230.0" + }, "tool-cmake": { "optional": true, "owner": "platformio", diff --git a/platform.py b/platform.py index 9722a8fa8..ff3397b00 100644 --- a/platform.py +++ b/platform.py @@ -32,18 +32,11 @@ def configure_default_packages(self, variables, targets): board_config = self.board_config(variables.get("board")) mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32")) - core_variant_board = ''.join(variables.get("board_build.extra_flags", board_config.get("build.extra_flags", ""))) - core_variant_board = core_variant_board.replace("-D", " ") - core_variant_build = (''.join(variables.get("build_flags", []))).replace("-D", " ") frameworks = variables.get("pioframework", []) if "arduino" in frameworks: - if "CORE32SOLO1" in core_variant_board or "FRAMEWORK_ARDUINO_SOLO1" in core_variant_build: - self.packages["framework-arduino-solo1"]["optional"] = False - elif "CORE32ITEAD" in core_variant_board or "FRAMEWORK_ARDUINO_ITEAD" in core_variant_build: - self.packages["framework-arduino-ITEAD"]["optional"] = False - else: - self.packages["framework-arduinoespressif32"]["optional"] = False + self.packages["framework-arduinoespressif32"]["optional"] = False + self.packages["framework-arduinoespressif32-libs"]["optional"] = False if "buildfs" in targets: filesystem = variables.get("board_build.filesystem", "littlefs") @@ -51,6 +44,8 @@ def configure_default_packages(self, variables, targets): self.packages["tool-mklittlefs"]["optional"] = False elif filesystem == "fatfs": self.packages["tool-mkfatfs"]["optional"] = False + else: + self.packages["tool-mkspiffs"]["optional"] = False if variables.get("upload_protocol"): self.packages["tool-openocd-esp32"]["optional"] = False if os.path.isdir("ulp"): From bbbe5760870828171e8ab054de5a412a9fa36395 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Feb 2024 15:31:55 +0100 Subject: [PATCH 595/666] Update esp32-h2-devkitm-1.json --- boards/esp32-h2-devkitm-1.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/esp32-h2-devkitm-1.json b/boards/esp32-h2-devkitm-1.json index 8e8ca1f3e..8aedb337b 100644 --- a/boards/esp32-h2-devkitm-1.json +++ b/boards/esp32-h2-devkitm-1.json @@ -6,7 +6,7 @@ "core": "esp32", "f_cpu": "96000000L", "f_flash": "64000000L", - "img_freq": "48000000L", + "f_image": "48000000L", "flash_mode": "qio", "mcu": "esp32h2", "variant": "esp32h2", From 82190a73e29a35e96bdc90aa44e55d66f94e317c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 14 Feb 2024 15:51:37 +0100 Subject: [PATCH 596/666] `f_image` --- builder/main.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/builder/main.py b/builder/main.py index 28117dc88..eec4d64ec 100644 --- a/builder/main.py +++ b/builder/main.py @@ -62,20 +62,23 @@ def _get_board_memory_type(env): ), ) -def _get_board_img_freq(env): - board_config = env.BoardConfig() - img_freq = board_config.get("build.img_freq", "") - if img_freq =="": - img_freq = board_config.get("build.f_flash", "") - img_freq = str(img_freq).replace("L", "") - return str(int(int(img_freq) / 1000000)) + "m" + +def _normalize_frequency(frequency): + frequency = str(frequency).replace("L", "") + return str(int(int(frequency) / 1000000)) + "m" def _get_board_f_flash(env): + frequency = env.subst("$BOARD_F_FLASH") + return _normalize_frequency(frequency) + + +def _get_board_f_image(env): board_config = env.BoardConfig() - frequency = board_config.get("build.f_flash", "") - frequency = str(frequency).replace("L", "") - return str(int(int(frequency) / 1000000)) + "m" + if "build.f_image" in board_config: + return _normalize_frequency(board_config.get("build.f_image")) + + return _get_board_f_flash(env) def _get_board_flash_mode(env): @@ -213,7 +216,7 @@ def __fetch_fs_size(target, source, env): env.Replace( __get_board_boot_mode=_get_board_boot_mode, __get_board_f_flash=_get_board_f_flash, - __get_board_img_freq=_get_board_img_freq, + __get_board_f_image=_get_board_f_image, __get_board_flash_mode=_get_board_flash_mode, __get_board_memory_type=_get_board_memory_type, @@ -285,7 +288,7 @@ def __fetch_fs_size(target, source, env): "--chip", mcu, "elf2image", "--dont-append-digest", "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_img_freq(__env__)}", + "--flash_freq", "${__get_board_f_image(__env__)}", "--flash_size", board.get("upload.flash_size", "4MB"), "-o", "$TARGET", "$SOURCES" ]), "Building $TARGET"), @@ -416,7 +419,7 @@ def __fetch_fs_size(target, source, env): "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_img_freq(__env__)}", + "--flash_freq", "${__get_board_f_image(__env__)}", "--flash_size", "detect" ], UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE' @@ -434,7 +437,7 @@ def __fetch_fs_size(target, source, env): "--after", board.get("upload.after_reset", "hard_reset"), "write_flash", "-z", "--flash_mode", "${__get_board_flash_mode(__env__)}", - "--flash_freq", "${__get_board_img_freq(__env__)}", + "--flash_freq", "${__get_board_f_image(__env__)}", "--flash_size", "detect", "$FS_START" ], From 4e798b72c40f80a08c33baf204ed4c64c1802b09 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 15 Feb 2024 18:10:03 +0100 Subject: [PATCH 597/666] Latest Arduino commit --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 1ad015170..1413c042a 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/archive/48072ee09802739cf4883c044e65bd1a77823038.zip" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/698b78a538cdad6a6b32d7419e083d77db866ddb" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/esp32-arduino-libs/archive/bef34d984ad9348f2055653b62998a023273dece.zip" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/bef34d984ad9348f2055653b62998a023273dece" }, "framework-espidf": { "type": "framework", From 2adb691ea01c871cd71b491d7d8cfee46db882e5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 15 Feb 2024 20:43:38 +0100 Subject: [PATCH 598/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 1413c042a..183b7b8e3 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/698b78a538cdad6a6b32d7419e083d77db866ddb" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/bc769fd35a1d4ee26f453e9965412b7e3a8d2dc8" }, "framework-arduinoespressif32-libs": { "type": "framework", From 56537ba524d87fbe0dd9363a129c232cb5dbb422 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 15 Feb 2024 20:58:17 +0100 Subject: [PATCH 599/666] enable H2 build --- examples/arduino-blink/platformio.ini | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index c821ed35c..03eaf2cbd 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -21,9 +21,8 @@ framework = arduino board = esp32-c6-devkitc-1 monitor_speed = 115200 -; changes needed in Arduino code: https://github.com/espressif/arduino-esp32/issues/9237 -;[env:esp32-h2-devkitm-1] -;platform = espressif32 -;framework = arduino -;board = esp32-h2-devkitm-1 -;monitor_speed = 115200 +[env:esp32-h2-devkitm-1] +platform = espressif32 +framework = arduino +board = esp32-h2-devkitm-1 +monitor_speed = 115200 From 9d497b264f951969e690f1e0d323e4f2160e2221 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 16 Feb 2024 20:59:29 +0100 Subject: [PATCH 600/666] Delete boards/briki_abc_esp32.json --- boards/briki_abc_esp32.json | 41 ------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 boards/briki_abc_esp32.json diff --git a/boards/briki_abc_esp32.json b/boards/briki_abc_esp32.json deleted file mode 100644 index 429514895..000000000 --- a/boards/briki_abc_esp32.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "mbcwb", - "extra_flags": "-DBRIKI_MBC_WB_ESP -DBRIKI_ABC -w", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "briki_mbcwb_esp32", - "partitions": "8MB_ffat.csv" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino" - ], - "name": "Briki ABC (MBC-WB) - ESP32", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 3407872, - "protocol": "mbctool", - "protocols": [ - "mbctool" - ], - "require_upload_port": true, - "speed": 1500000 - }, - "url": "https://briki.org", - "vendor": "meteca" -} From e704bc4c9854b83d5b69a78be9b9fee6effd9990 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 16 Feb 2024 20:59:44 +0100 Subject: [PATCH 601/666] Delete boards/briki_mbc-wb_esp32.json --- boards/briki_mbc-wb_esp32.json | 41 ---------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 boards/briki_mbc-wb_esp32.json diff --git a/boards/briki_mbc-wb_esp32.json b/boards/briki_mbc-wb_esp32.json deleted file mode 100644 index df5c3756a..000000000 --- a/boards/briki_mbc-wb_esp32.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "build": { - "arduino":{ - "ldscript": "esp32_out.ld" - }, - "core": "mbcwb", - "extra_flags": "-DBRIKI_MBC_WB_ESP -DBRIKI_MBC_WB -w", - "f_cpu": "240000000L", - "f_flash": "80000000L", - "flash_mode": "dio", - "mcu": "esp32", - "variant": "briki_mbcwb_esp32", - "partitions": "8MB_ffat.csv" - }, - "connectivity": [ - "wifi", - "bluetooth", - "ethernet", - "can" - ], - "debug": { - "openocd_board": "esp-wroom-32.cfg" - }, - "frameworks": [ - "arduino" - ], - "name": "Briki MBC-WB - ESP32", - "upload": { - "flash_size": "8MB", - "maximum_ram_size": 327680, - "maximum_size": 3407872, - "protocol": "mbctool", - "protocols": [ - "mbctool" - ], - "require_upload_port": true, - "speed": 1500000 - }, - "url": "https://briki.org", - "vendor": "meteca" -} From 0141fe46fe22028f20ab95e9f770d77c2376be66 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Feb 2024 10:55:06 +0100 Subject: [PATCH 602/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 6a8cdb961..4b04a640d 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -20,8 +20,8 @@ board_build.embed_txtfiles = managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt -;[env:esp32dev] -;board = esp32dev +[env:esp32dev] +board = esp32dev [env:esp32-c6-devkitm-1] board = esp32-c6-devkitm-1 From e8f458b6ca76ced557a0d55b1f63bc35f350fd0f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Feb 2024 10:57:01 +0100 Subject: [PATCH 603/666] Update sdkconfig.defaults --- examples/espidf-arduino-blink/sdkconfig.defaults | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index a8f9a5467..5ef23a055 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -7,3 +7,16 @@ CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y + +# +# SPI RAM config +# +CONFIG_SPIRAM_MODE_QUAD=y +CONFIG_SPIRAM_TYPE_AUTO=y +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_SPEED=80 +CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096 +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=0 From 857149a997853af7c72d7ae8b3c353ba6e3a146f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 20 Feb 2024 12:26:23 +0100 Subject: [PATCH 604/666] Update Arduino libs --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 183b7b8e3..dd3cec9d8 100644 --- a/platform.json +++ b/platform.json @@ -39,7 +39,7 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/bef34d984ad9348f2055653b62998a023273dece" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/1e2d85899b736f4bd5920c9702c34b8e049e5377" }, "framework-espidf": { "type": "framework", From 23f1833169946945433a5a9935f06ff8592a90ea Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 21 Feb 2024 10:35:20 +0100 Subject: [PATCH 605/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index dd3cec9d8..12d2445fe 100644 --- a/platform.json +++ b/platform.json @@ -39,7 +39,7 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/1e2d85899b736f4bd5920c9702c34b8e049e5377" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/86e4fbbff4374330585949f17603fa0bba7e5a3c" }, "framework-espidf": { "type": "framework", From 1a55d5a2d6b04c8bee12596c73dc7ca8846f3fab Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:16:24 +0100 Subject: [PATCH 606/666] Update espidf.py --- builder/frameworks/espidf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 963b8ff91..aedbd1988 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -421,7 +421,7 @@ def _extract_flags(config): # Flags are sorted because CMake randomly populates build flags in code model return { - "ASFLAGS": sorted(app_flags.get("ASM", default_flags.get("ASM"))), + "ASPPFLAGS": sorted(app_flags.get("ASM", default_flags.get("ASM"))), "CFLAGS": sorted(app_flags.get("C", default_flags.get("C"))), "CXXFLAGS": sorted(app_flags.get("CXX", default_flags.get("CXX"))), } @@ -639,7 +639,7 @@ def prepare_build_envs(config, default_env, debug_allowed=True): parsed_flags = build_env.ParseFlags(build_flags) build_env.AppendUnique(**parsed_flags) if cg.get("language", "") == "ASM": - build_env.AppendUnique(ASFLAGS=parsed_flags.get("CCFLAGS", [])) + build_env.AppendUnique(ASPPFLAGS=parsed_flags.get("CCFLAGS", [])) build_env.AppendUnique(CPPDEFINES=defines, CPPPATH=includes) if sys_includes: build_env.Append(CCFLAGS=[("-isystem", inc) for inc in sys_includes]) From 6e7c68fc37fca37fdb7bce07825d1f54351a0ea8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 29 Feb 2024 20:23:10 +0100 Subject: [PATCH 607/666] idf-component-manager v1.5.2 --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index aedbd1988..377a56929 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -1109,7 +1109,7 @@ def _get_installed_pip_packages(python_exe_path): "future": ">=0.18.3", "pyparsing": "~=3.0.9" if IDF5 else ">=2.0.3,<2.4.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", - "idf-component-manager": "~=1.4.1" if IDF5 else "~=1.0", + "idf-component-manager": "~=1.5.2" if IDF5 else "~=1.0", "esp-idf-kconfig": "~=1.2.0" } From e06e2b1848121f1d8fa95f3fa076f7659f217169 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:02:33 +0100 Subject: [PATCH 608/666] IDF 5.1.3 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 12d2445fe..a9e12d33f 100644 --- a/platform.json +++ b/platform.json @@ -45,7 +45,7 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.2.240206/esp-idf-v5.1.2.zip" + "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.3/esp-idf-v5.1.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 4e5b0cbbc3ada8386a2790a96481935070fa5d5e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 1 Mar 2024 13:03:30 +0100 Subject: [PATCH 609/666] Update to latest lib and Arduino commit --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index a9e12d33f..49f41e180 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/bc769fd35a1d4ee26f453e9965412b7e3a8d2dc8" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/ebca505fef55a2978db7607ced21a2700ef340e1" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/86e4fbbff4374330585949f17603fa0bba7e5a3c" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/9fdac0a1b265bee4f7fa2904382bf89fd150e527" }, "framework-espidf": { "type": "framework", From 1f09f95c2d28c03d4667c9a5b14c4ebb7ec3e241 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:22:07 +0100 Subject: [PATCH 610/666] Update ulp.py --- builder/frameworks/ulp.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 5af8f87d1..9faf8c6e1 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -124,14 +124,19 @@ def compile_ulp_binary(): "build", ) - return ulp_env.Command( + # The `build.ninja` dependency is always generated with the same content + # so a cloned environment with a decider that depends on a timestamp is used + ulp_binary_env = ulp_env.Clone() + ulp_binary_env.Decider("timestamp-newer") + + return ulp_binary_env.Command( [ os.path.join(ULP_BUILD_DIR, "ulp_main.h"), os.path.join(ULP_BUILD_DIR, "ulp_main.ld"), os.path.join(ULP_BUILD_DIR, "ulp_main.bin"), ], None, - ulp_env.VerboseAction(" ".join(cmd), "Generating ULP project files $TARGETS"), + ulp_binary_env.VerboseAction(" ".join(cmd), "Generating ULP project files $TARGETS"), ) From 6223a657628011182d48406ef0faaf3c75b69d6c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 7 Mar 2024 13:50:25 +0100 Subject: [PATCH 611/666] Tasmota esptool.py v4.7.1 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 49f41e180..9d86b173b 100644 --- a/platform.json +++ b/platform.json @@ -92,7 +92,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/Jason2866/esptool/releases/download/v4.7.0.240211/esptool.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.1/esptool.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From 2c21d10f19cd9a370dd5f4e927e89757bd13627e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 7 Mar 2024 13:57:51 +0100 Subject: [PATCH 612/666] append-digest --- builder/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index eec4d64ec..3e3bd9971 100644 --- a/builder/main.py +++ b/builder/main.py @@ -286,7 +286,6 @@ def __fetch_fs_size(target, source, env): action=env.VerboseAction(" ".join([ '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", - "--dont-append-digest", "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_image(__env__)}", "--flash_size", board.get("upload.flash_size", "4MB"), From 5c69cfce6471950dc5637ce3d671419dfc7b932a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 7 Mar 2024 15:23:24 +0100 Subject: [PATCH 613/666] commits from 240307 --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 9d86b173b..486134976 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/ebca505fef55a2978db7607ced21a2700ef340e1" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/4123e20a2ca28db70ffeb4db3d5157c8e5b1a058" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/9fdac0a1b265bee4f7fa2904382bf89fd150e527" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/e517adb6d2fedc42686935bcf77556701a81f3bc" }, "framework-espidf": { "type": "framework", From 2e1cf70a8b38acf9804beeffad193e8b3037cf9a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 19 Mar 2024 09:55:11 +0100 Subject: [PATCH 614/666] add `f_boot' --- builder/main.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/builder/main.py b/builder/main.py index 3e3bd9971..c14d1f46b 100644 --- a/builder/main.py +++ b/builder/main.py @@ -62,7 +62,6 @@ def _get_board_memory_type(env): ), ) - def _normalize_frequency(frequency): frequency = str(frequency).replace("L", "") return str(int(int(frequency) / 1000000)) + "m" @@ -81,6 +80,14 @@ def _get_board_f_image(env): return _get_board_f_flash(env) +def _get_board_f_boot(env): + board_config = env.BoardConfig() + if "build.f_boot" in board_config: + return _normalize_frequency(board_config.get("build.f_boot")) + + return _get_board_f_flash(env) + + def _get_board_flash_mode(env): if _get_board_memory_type(env) in ( "opi_opi", @@ -88,6 +95,7 @@ def _get_board_flash_mode(env): ): return "dout" + mode = env.subst("$BOARD_FLASH_MODE") if mode in ("qio", "qout"): return "dio" @@ -217,6 +225,7 @@ def __fetch_fs_size(target, source, env): __get_board_boot_mode=_get_board_boot_mode, __get_board_f_flash=_get_board_f_flash, __get_board_f_image=_get_board_f_image, + __get_board_f_boot=_get_board_f_boot, __get_board_flash_mode=_get_board_flash_mode, __get_board_memory_type=_get_board_memory_type, @@ -304,7 +313,7 @@ def __fetch_fs_size(target, source, env): "-b", "$FS_BLOCK", ] - if filesystem in ("spiffs", "littlefs") + if filesystem in ("littlefs", "spiffs") else [] ) + ["$TARGET"] @@ -532,7 +541,7 @@ def __fetch_fs_size(target, source, env): "erase_upload", target_firm, [ - env.VerboseAction(env.AutodetectUploadPort, "Looking for serial port..."), + env.VerboseAction(BeforeUpload, "Looking for upload port..."), env.VerboseAction("$ERASECMD", "Erasing..."), env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE") ], @@ -547,7 +556,7 @@ def __fetch_fs_size(target, source, env): "erase", None, [ - env.VerboseAction(env.AutodetectUploadPort, "Looking for serial port..."), + env.VerboseAction(BeforeUpload, "Looking for upload port..."), env.VerboseAction("$ERASECMD", "Erasing...") ], "Erase Flash", From db342e3f9a19be2d247d102fca823c1de9c88b99 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 19 Mar 2024 09:59:42 +0100 Subject: [PATCH 615/666] latest --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 486134976..9af7ecb69 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/4123e20a2ca28db70ffeb4db3d5157c8e5b1a058" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/c17a688b628ac80fc997c9cedf16bdd37085de20" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/e517adb6d2fedc42686935bcf77556701a81f3bc" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/8c275fe9b4d1850ab142d9b8b6f25dfb3880a039" }, "framework-espidf": { "type": "framework", From 1802bd58bade81fbf7599b5b670495917f2610a8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 23 Mar 2024 12:52:03 +0100 Subject: [PATCH 616/666] Update pypi packages --- builder/frameworks/espidf.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 377a56929..693f89dfe 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -69,6 +69,15 @@ assert os.path.isdir(FRAMEWORK_DIR) assert os.path.isdir(TOOLCHAIN_DIR) +# The latest IDF uses a standalone GDB package which requires at least PlatformIO 6.1.11 +if ( + ["espidf"] == env.get("PIOFRAMEWORK") + and semantic_version.Version.coerce(__version__) + <= semantic_version.Version("6.1.10") + and "__debug" in COMMAND_LINE_TARGETS +): + print("Warning! Debugging an IDF project requires PlatformIO Core >= 6.1.11!") + # Arduino framework as a component is not compatible with ESP-IDF >=4.1 if "arduino" in env.subst("$PIOFRAMEWORK"): ARDUINO_FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") @@ -1100,6 +1109,10 @@ def _get_installed_pip_packages(python_exe_path): return result + skip_python_packages = os.path.join(FRAMEWORK_DIR, ".pio_skip_pypackages") + if os.path.isfile(skip_python_packages): + return + deps = { "wheel": ">=0.35.1", # https://github.com/platformio/platformio-core/issues/4614 @@ -1107,10 +1120,10 @@ def _get_installed_pip_packages(python_exe_path): # https://github.com/platformio/platform-espressif32/issues/635 "cryptography": "~=41.0.1" if IDF5 else ">=2.1.4,<35.0.0", "future": ">=0.18.3", - "pyparsing": "~=3.0.9" if IDF5 else ">=2.0.3,<2.4.0", + "pyparsing": ">=3.1.0,<4" if IDF5 else ">=2.0.3,<2.4.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", "idf-component-manager": "~=1.5.2" if IDF5 else "~=1.0", - "esp-idf-kconfig": "~=1.2.0" + "esp-idf-kconfig": ">=1.4.2,<2.0.0" } if sys_platform.system() == "Darwin" and "arm" in sys_platform.machine().lower(): From 17764a2aba22f365411775b88be4b5ae5519055b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 28 Mar 2024 11:43:13 +0100 Subject: [PATCH 617/666] Better handling of IDF source files when preparing build env --- builder/frameworks/espidf.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 693f89dfe..ab09718cf 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -680,7 +680,7 @@ def compile_source_files( src_path = os.path.join(project_src_dir, src_path) obj_path = os.path.join("$BUILD_DIR", prepend_dir or "") - if src_path.startswith(components_dir): + if src_path.lower().startswith(components_dir.lower()): obj_path = os.path.join( obj_path, os.path.relpath(src_path, components_dir) ) @@ -1170,6 +1170,7 @@ def _get_installed_pip_packages(python_exe_path): ) ) + def get_idf_venv_dir(): # The name of the IDF venv contains the IDF version to avoid possible conflicts and # unnecessary reinstallation of Python dependencies in cases when Arduino @@ -1180,6 +1181,7 @@ def get_idf_venv_dir(): env.subst("$PROJECT_CORE_DIR"), "penv", ".espidf-" + idf_version ) + def ensure_python_venv_available(): def _is_venv_outdated(venv_data_file): @@ -1222,7 +1224,6 @@ def _create_venv(venv_dir): pip_path ), "Error: Failed to create a proper virtual environment. Missing the `pip` binary!" - venv_dir = get_idf_venv_dir() venv_data_file = os.path.join(venv_dir, "pio-idf-venv.json") if not os.path.isfile(venv_data_file) or _is_venv_outdated(venv_data_file): From ec30a4c5ea2359b644282024d67cd70dcd401ae0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 28 Mar 2024 12:11:18 +0100 Subject: [PATCH 618/666] Update ulp.py --- builder/frameworks/ulp.py | 67 ++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 9faf8c6e1..8cc922179 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -16,7 +16,7 @@ from platformio import fs from platformio.util import get_systype -from platformio.proc import where_is_program +from platformio.proc import where_is_program, exec_command from SCons.Script import Import @@ -77,41 +77,50 @@ def get_component_includes(target_config): def generate_ulp_config(target_config): - riscv_ulp_enabled = sdk_config.get("ULP_COPROC_TYPE_RISCV", False) + def _generate_ulp_configuration_action(env, target, source): + riscv_ulp_enabled = sdk_config.get("ULP_COPROC_TYPE_RISCV", False) + + cmd = ( + os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), + "-DCMAKE_GENERATOR=Ninja", + "-DCMAKE_TOOLCHAIN_FILE=" + + os.path.join( + FRAMEWORK_DIR, + "components", + "ulp", + "cmake", + "toolchain-%sulp%s.cmake" + % ( + "" if riscv_ulp_enabled else idf_variant + "-", + "-riscv" if riscv_ulp_enabled else "", + ), + ), + "-DULP_S_SOURCES=%s" % ";".join([s.get_abspath() for s in source]), + "-DULP_APP_NAME=ulp_main", + "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), + "-DCOMPONENT_INCLUDES=%s" % ";".join(get_component_includes(target_config)), + "-DIDF_TARGET=%s" % idf_variant, + "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), + "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), + "-DPYTHON=" + env.subst("$PYTHONEXE"), + "-DULP_COCPU_IS_RISCV=%s" % ("ON" if riscv_ulp_enabled else "OFF"), + "-GNinja", + "-B", + ULP_BUILD_DIR, + os.path.join(FRAMEWORK_DIR, "components", "ulp", "cmake"), + ) + + exec_command(cmd) ulp_sources = collect_ulp_sources() ulp_sources.sort() - cmd = ( - os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), - "-DCMAKE_GENERATOR=Ninja", - "-DCMAKE_TOOLCHAIN_FILE=" - + os.path.join( - FRAMEWORK_DIR, - "components", - "ulp", - "cmake", - "toolchain-%sulp%s.cmake" - % ("" if riscv_ulp_enabled else idf_variant + "-", "-riscv" if riscv_ulp_enabled else ""), - ), - '-DULP_S_SOURCES="%s"' % ";".join(ulp_sources), - "-DULP_APP_NAME=ulp_main", - "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), - '-DCOMPONENT_INCLUDES="%s"' % ";".join(get_component_includes(target_config)), - "-DIDF_TARGET=%s" % idf_variant, - "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), - "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), - "-DPYTHON=" + env.subst("$PYTHONEXE"), - "-DULP_COCPU_IS_RISCV=%s" % ("ON" if riscv_ulp_enabled else "OFF"), - "-GNinja", - "-B", - ULP_BUILD_DIR, - os.path.join(FRAMEWORK_DIR, "components", "ulp", "cmake"), - ) return ulp_env.Command( os.path.join(ULP_BUILD_DIR, "build.ninja"), ulp_sources, - ulp_env.VerboseAction(" ".join(cmd), "Generating ULP configuration"), + ulp_env.VerboseAction( + _generate_ulp_configuration_action, "Generating ULP configuration" + ), ) From 0dd22a63b63ac0770ea4928bc4033c6f522080df Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:52:09 +0200 Subject: [PATCH 619/666] esptool v4.7.2 --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 9af7ecb69..086d283f4 100644 --- a/platform.json +++ b/platform.json @@ -12,7 +12,7 @@ "RISC-V" ], "engines": { - "platformio": ">=6.1.11" + "platformio": ">=6.1.14" }, "repository": { "type": "git", @@ -92,7 +92,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.1/esptool.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.2/esptool.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From 5dabb3691d6170dc790883e454ceaa4d74939eb1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 18 Apr 2024 14:25:27 +0200 Subject: [PATCH 620/666] Update filter_exception_decoder.py --- monitor/filter_exception_decoder.py | 146 ++++++++++++++-------------- 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index ecb4ef7cd..d0f4a39b3 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -32,76 +32,57 @@ class Esp32ExceptionDecoder(DeviceMonitorFilterBase): NAME = "esp32_exception_decoder" + ADDR_PATTERN = re.compile(r"((?:0x[0-9a-fA-F]{8}[: ]?)+)\s?$") + ADDR_SPLIT = re.compile(r"[ :]") + PREFIX_RE = re.compile(r"^ *") + def __call__(self): self.buffer = "" - # regex matches potential PC value (0x4xxxxxxx) - # Logic identical to https://github.com/espressif/esp-idf/blob/master/tools/idf_monitor_base/constants.py#L56 - self.pcaddr_re = re.compile(r'0x4[0-9a-f]{7}', re.IGNORECASE) self.firmware_path = None self.addr2line_path = None self.enabled = self.setup_paths() - return self - - def setup_paths(self): - self.project_dir = os.path.abspath(self.project_dir) - - self.project_strip_dir = os.environ.get("esp32_exception_decoder_project_strip_dir") - self.firmware_path = os.environ.get("esp32_exception_decoder_firmware_path") - self.addr2line_path = os.environ.get("esp32_exception_decoder_addr2line_path") - - if self.project_strip_dir is None: - self.project_strip_dir = self.project_dir - - try: - if self.firmware_path is None or self.addr2line_path is None: - # Only load if necessary, as the call is expensive - data = load_build_metadata(self.project_dir, self.environment) - - if self.firmware_path is None: - # Only do this check when the firmware path is not externally provided - if self.config.get("env:" + self.environment, "build_type") != "debug": - print( + if self.config.get("env:" + self.environment, "build_type") != "debug": + print( """ Please build project in debug configuration to get more details about an exception. See https://docs.platformio.org/page/projectconf/build_configurations.html """ - ) - self.firmware_path = data["prog_path"] + ) + + return self + def setup_paths(self): + self.project_dir = os.path.abspath(self.project_dir) + try: + data = load_build_metadata(self.project_dir, self.environment, cache=True) + + self.firmware_path = data["prog_path"] if not os.path.isfile(self.firmware_path): sys.stderr.write( - "%s: disabling, firmware at %s does not exist, rebuild the project?\n" + "%s: firmware at %s does not exist, rebuild the project?\n" % (self.__class__.__name__, self.firmware_path) ) return False - if self.addr2line_path is None: - cc_path = data.get("cc_path", "") - if "-gcc" in cc_path: - self.addr2line_path = cc_path.replace("-gcc", "-addr2line") - else: - sys.stderr.write( - "%s: disabling, failed to find addr2line.\n" % self.__class__.__name__ - ) - return False - - if not os.path.isfile(self.addr2line_path): - sys.stderr.write( - "%s: disabling, addr2line at %s does not exist\n" - % (self.__class__.__name__, self.addr2line_path) - ) - return False - - return True + cc_path = data.get("cc_path", "") + if "-gcc" in cc_path: + path = cc_path.replace("-gcc", "-addr2line") + if os.path.isfile(path): + self.addr2line_path = path + return True except PlatformioException as e: sys.stderr.write( "%s: disabling, exception while looking for addr2line: %s\n" % (self.__class__.__name__, e) ) return False + sys.stderr.write( + "%s: disabling, failed to find addr2line.\n" % self.__class__.__name__ + ) + return False def rx(self, text): if not self.enabled: @@ -121,47 +102,70 @@ def rx(self, text): self.buffer = "" last = idx + 1 - # Output each trace on a separate line below ours - # Logic identical to https://github.com/espressif/esp-idf/blob/master/tools/idf_monitor_base/logger.py#L131 - for m in re.finditer(self.pcaddr_re, line): - if m is None: - continue - - trace = self.get_backtrace(m) - if len(trace) != "": - text = text[: last] + trace + text[last :] - last += len(trace) + m = self.ADDR_PATTERN.search(line) + if m is None: + continue + trace = self.build_backtrace(line, m.group(1)) + if trace: + text = text[: idx + 1] + trace + text[idx + 1 :] + last += len(trace) return text - def get_backtrace(self, match): + def is_address_ignored(self, address): + return address in ("", "0x00000000") + + def filter_addresses(self, adresses_str): + addresses = self.ADDR_SPLIT.split(adresses_str) + size = len(addresses) + while size > 1 and self.is_address_ignored(addresses[size-1]): + size -= 1 + return addresses[:size] + + def build_backtrace(self, line, address_match): + addresses = self.filter_addresses(address_match) + if not addresses: + return "" + + prefix_match = self.PREFIX_RE.match(line) + prefix = prefix_match.group(0) if prefix_match is not None else "" + trace = "" enc = "mbcs" if IS_WINDOWS else "utf-8" args = [self.addr2line_path, u"-fipC", u"-e", self.firmware_path] try: - addr = match.group() - output = ( - subprocess.check_output(args + [addr]) - .decode(enc) - .strip() - ) - output = output.replace( - "\n", "\n " - ) # newlines happen with inlined methods - output = self.strip_project_dir(output) - # Output the trace in yellow color so that it is easier to spot - trace += "\033[33m=> %s: %s\033[0m\n" % (addr, output) + i = 0 + for addr in addresses: + output = ( + subprocess.check_output(args + [addr]) + .decode(enc) + .strip() + ) + + # newlines happen with inlined methods + output = output.replace( + "\n", "\n " + ) + + # throw out addresses not from ELF + if output == "?? ??:0": + continue + + output = self.strip_project_dir(output) + trace += "%s #%-2d %s in %s\n" % (prefix, i, addr, output) + i += 1 except subprocess.CalledProcessError as e: sys.stderr.write( "%s: failed to call %s: %s\n" % (self.__class__.__name__, self.addr2line_path, e) ) - return trace + + return trace + "\n" if trace else "" def strip_project_dir(self, trace): while True: - idx = trace.find(self.project_strip_dir) + idx = trace.find(self.project_dir) if idx == -1: break - trace = trace[:idx] + trace[idx + len(self.project_strip_dir) + 1 :] + trace = trace[:idx] + trace[idx + len(self.project_dir) + 1 :] return trace From bd8d1059a4a5124f8b89f91852d7c7874eae0101 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 18 Apr 2024 15:51:31 +0200 Subject: [PATCH 621/666] Update platform.json --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 086d283f4..1ee9223ad 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/c17a688b628ac80fc997c9cedf16bdd37085de20" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/4070a8799f7167bb627ff14504cd01d4df076b98" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/8c275fe9b4d1850ab142d9b8b6f25dfb3880a039" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/ad1f97a1623c5c41a0db40a1def6d3fb8548a37d" }, "framework-espidf": { "type": "framework", From c3b010155ca8311d892d3f6bcba8ba0521cb2453 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 18 Apr 2024 17:00:34 +0200 Subject: [PATCH 622/666] IDF v5.1.3.240418 --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 1ee9223ad..4340a3a0c 100644 --- a/platform.json +++ b/platform.json @@ -44,8 +44,8 @@ "framework-espidf": { "type": "framework", "optional": true, - "owner": "espressif", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.3/esp-idf-v5.1.3.zip" + "owner": "jason2866", + "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.3.240418/esp-idf-v5.1.3.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From ee9e266f336078f7297ef5e63228bd1b34551d64 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 20 Apr 2024 21:10:12 +0200 Subject: [PATCH 623/666] Update espidf.py --- builder/frameworks/espidf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index ab09718cf..a214aa542 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -691,7 +691,7 @@ def compile_source_files( obj_path = os.path.join(obj_path, os.path.basename(src_path)) preserve_source_file_extension = board.get( - "build.esp-idf.preserve_source_file_extension", False + "build.esp-idf.preserve_source_file_extension", True ) objects.append( From 2b64c8d3ba3088440a2692f68e7d62f775591746 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:25:46 +0200 Subject: [PATCH 624/666] Update arduino --- platform.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform.json b/platform.json index 4340a3a0c..977564878 100644 --- a/platform.json +++ b/platform.json @@ -12,7 +12,7 @@ "RISC-V" ], "engines": { - "platformio": ">=6.1.14" + "platformio": ">=6.1.15" }, "repository": { "type": "git", @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/4070a8799f7167bb627ff14504cd01d4df076b98" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/7e7c01aadf81af799ab296574827d16ddfe8621f" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/ad1f97a1623c5c41a0db40a1def6d3fb8548a37d" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/b0850286f4be64cb08eeedcf1594cbd5b59ea7f1" }, "framework-espidf": { "type": "framework", From b071e97e7fc076329af965d9d078e8c39ad555f1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 10 May 2024 17:19:22 +0200 Subject: [PATCH 625/666] Update espidf.py --- builder/frameworks/espidf.py | 63 +++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index a214aa542..0042acd81 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -26,6 +26,7 @@ import sys import shutil import os +import re import platform as sys_platform import click @@ -58,7 +59,11 @@ idf_variant = mcu.lower() # Required until Arduino switches to v5 -IDF5 = platform.get_package_version("framework-espidf").split(".")[1].startswith("5") +IDF5 = ( + platform.get_package_version("framework-espidf") + .split(".")[1] + .startswith("5") +) IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( @@ -482,7 +487,7 @@ def _scan_components_from_framework(): return components or _scan_components_from_framework() -def extract_linker_script_fragments(framework_components_dir, sdk_config): +def extract_linker_script_fragments_backup(framework_components_dir, sdk_config): # Hardware-specific components are excluded from search and added manually below project_components = load_component_paths( framework_components_dir, ignored_component_prefixes=("esp32", "riscv") @@ -530,6 +535,52 @@ def extract_linker_script_fragments(framework_components_dir, sdk_config): return result +def extract_linker_script_fragments( + ninja_buildfile, framework_components_dir, sdk_config +): + def _normalize_fragment_path(base_dir, fragment_path): + if not os.path.isabs(fragment_path): + fragment_path = os.path.abspath( + os.path.join(base_dir, fragment_path) + ) + if not os.path.isfile(fragment_path): + print("Warning! The `%s` fragment is not found!" % fragment_path) + + return fragment_path + + assert os.path.isfile( + ninja_buildfile + ), "Cannot extract linker fragments! Ninja build file is missing!" + + result = [] + with open(ninja_buildfile, encoding="utf8") as fp: + for line in fp.readlines(): + if "sections.ld: CUSTOM_COMMAND" not in line: + continue + for fragment_match in re.finditer(r"(\S+\.lf\b)+", line): + result.append(_normalize_fragment_path( + BUILD_DIR, fragment_match.group(0).replace("$:", ":") + )) + + break + + # Fall back option if the new algorithm didn't work + if not result: + result = extract_linker_script_fragments_backup( + framework_components_dir, sdk_config + ) + + if board.get("build.esp-idf.extra_lf_files", ""): + for fragment_path in board.get( + "build.esp-idf.extra_lf_files" + ).splitlines(): + if not fragment_path.strip(): + continue + result.append(_normalize_fragment_path(PROJECT_DIR, fragment_path)) + + return result + + def create_custom_libraries_list(ldgen_libraries_file, ignore_targets): if not os.path.isfile(ldgen_libraries_file): sys.stderr.write("Error: Couldn't find the list of framework libraries\n") @@ -558,11 +609,13 @@ def create_custom_libraries_list(ldgen_libraries_file, ignore_targets): def generate_project_ld_script(sdk_config, ignore_targets=None): ignore_targets = ignore_targets or [] linker_script_fragments = extract_linker_script_fragments( - os.path.join(FRAMEWORK_DIR, "components"), sdk_config + os.path.join(BUILD_DIR, "build.ninja"), + os.path.join(FRAMEWORK_DIR, "components"), + sdk_config ) - # Create a new file to avoid automatically generated library entry as files from - # this library are built internally by PlatformIO + # Create a new file to avoid automatically generated library entry as files + # from this library are built internally by PlatformIO libraries_list = create_custom_libraries_list( os.path.join(BUILD_DIR, "ldgen_libraries"), ignore_targets ) From e7f37babc17582c13b1f94279af36306ddeeaa87 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 27 May 2024 20:43:02 +0200 Subject: [PATCH 626/666] Update platform.json --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 977564878..33ca9d032 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/7e7c01aadf81af799ab296574827d16ddfe8621f" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.0/esp32-3.0.0.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/b0850286f4be64cb08eeedcf1594cbd5b59ea7f1" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.0/esp32-arduino-libs-3.0.0.zip" }, "framework-espidf": { "type": "framework", From 4b5f545a6464f57b6f45c3c6c71e1cd7aec706eb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 27 May 2024 20:56:02 +0200 Subject: [PATCH 627/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 33ca9d032..226a34625 100644 --- a/platform.json +++ b/platform.json @@ -45,7 +45,7 @@ "type": "framework", "optional": true, "owner": "jason2866", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.3.240418/esp-idf-v5.1.3.zip" + "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.4.240525/esp-idf-v5.1.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 6723af2e6ae53d36c1be564d84ea9ae28db71fc6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 27 May 2024 21:42:21 +0200 Subject: [PATCH 628/666] Update main.py --- builder/main.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/builder/main.py b/builder/main.py index c14d1f46b..91aa97eea 100644 --- a/builder/main.py +++ b/builder/main.py @@ -79,7 +79,6 @@ def _get_board_f_image(env): return _get_board_f_flash(env) - def _get_board_f_boot(env): board_config = env.BoardConfig() if "build.f_boot" in board_config: @@ -95,7 +94,6 @@ def _get_board_flash_mode(env): ): return "dout" - mode = env.subst("$BOARD_FLASH_MODE") if mode in ("qio", "qout"): return "dio" @@ -165,12 +163,31 @@ def _parse_partitions(env): def _update_max_upload_size(env): if not env.get("PARTITIONS_TABLE_CSV"): return - sizes = [ - _parse_size(p["size"]) for p in _parse_partitions(env) + sizes = { + p["subtype"]: _parse_size(p["size"]) for p in _parse_partitions(env) if p["type"] in ("0", "app") - ] - if sizes: - board.update("upload.maximum_size", max(sizes)) + } + + partitions = {p["name"]: p for p in _parse_partitions(env)} + + # User-specified partition name has the highest priority + custom_app_partition_name = board.get("build.app_partition_name", "") + if custom_app_partition_name: + selected_partition = partitions.get(custom_app_partition_name, {}) + if selected_partition: + board.update("upload.maximum_size", _parse_size(selected_partition["size"])) + return + else: + print( + "Warning! Selected partition `%s` is not available in the partition " \ + "table! Default partition will be used!" % custom_app_partition_name + ) + + for p in partitions.values(): + if p["type"] in ("0", "app") and p["subtype"] in ("ota_0"): + board.update("upload.maximum_size", _parse_size(p["size"])) + break + def _to_unix_slashes(path): From 91e0f9e963f233b1d5978068ce071028ba9265dd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 27 May 2024 22:35:20 +0200 Subject: [PATCH 629/666] Update platform.json --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 226a34625..d6b2a5aa9 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.0/esp32-3.0.0.zip" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/d45f35a2c8fd6e1ebe11ffecbd9eb5e13e26edd8" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.0/esp32-arduino-libs-3.0.0.zip" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/b692a53c52f960457583b0f1646df9f80998be4b" }, "framework-espidf": { "type": "framework", From 86d89c6b4520fef7e568a9cd24a1cb834659b1e4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 28 May 2024 12:15:19 +0200 Subject: [PATCH 630/666] Update platformio.ini --- examples/espidf-arduino-littlefs/platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/espidf-arduino-littlefs/platformio.ini b/examples/espidf-arduino-littlefs/platformio.ini index a23e3ef25..d0c70385c 100644 --- a/examples/espidf-arduino-littlefs/platformio.ini +++ b/examples/espidf-arduino-littlefs/platformio.ini @@ -12,7 +12,6 @@ platform = espressif32 framework = arduino, espidf monitor_speed = 115200 -board_build.esp-idf.preserve_source_file_extension = yes board_build.embed_txtfiles = managed_components/espressif__esp_insights/server_certs/https_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt From 0fbf5443ffc4c1375d5ade6ba52f53fd9a7153d1 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 28 May 2024 12:15:57 +0200 Subject: [PATCH 631/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 4b04a640d..2fef2f4a2 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -13,7 +13,6 @@ framework = arduino, espidf build_flags = -DCONFIG_BLINK_GPIO=2 monitor_speed = 115200 -board_build.esp-idf.preserve_source_file_extension = yes board_build.embed_txtfiles = managed_components/espressif__esp_insights/server_certs/https_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_mqtt_server.crt From 86d878282fe86c66f3c0806770e2c04932f1e76f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 28 May 2024 12:24:05 +0200 Subject: [PATCH 632/666] update example --- .../components/esp_tinyusb/.gitattributes | 25 - .../components/esp_tinyusb/.gitignore | 30 - .../components/esp_tinyusb/.readthedocs.yaml | 18 - .../components/esp_tinyusb/CHANGELOG.md | 53 + .../components/esp_tinyusb/CMakeLists.txt | 98 +- .../esp_tinyusb/CODE_OF_CONDUCT.rst | 88 - .../components/esp_tinyusb/CONTRIBUTORS.rst | 192 - .../components/esp_tinyusb/Kconfig | 115 +- .../components/esp_tinyusb/LICENSE | 223 +- .../components/esp_tinyusb/README.md | 32 + .../components/esp_tinyusb/README.rst | 145 - .../additions/include/tinyusb_types.h | 24 - .../additions/include/vfs_tinyusb.h | 34 - .../include_private/descriptors_control.h | 23 - .../include_private/usb_descriptors.h | 27 - .../additions/src/descriptors_control.c | 150 - .../esp_tinyusb/additions/src/tusb_tasks.c | 46 - .../esp_tinyusb/{additions/src => }/cdc.c | 0 .../esp_tinyusb/descriptors_control.c | 294 ++ .../esp_tinyusb/hw/bsp/ansi_escape.h | 97 - .../components/esp_tinyusb/hw/bsp/board.c | 149 - .../components/esp_tinyusb/hw/bsp/board.h | 147 - .../components/esp_tinyusb/hw/bsp/board_mcu.h | 157 - .../hw/bsp/esp32s2/boards/CMakeLists.txt | 12 - .../adafruit_feather_esp32s2/board.cmake | 17 - .../boards/adafruit_feather_esp32s2/board.h | 45 - .../boards/adafruit_magtag_29gray/board.cmake | 17 - .../boards/adafruit_magtag_29gray/board.h | 45 - .../boards/adafruit_metro_esp32s2/board.cmake | 17 - .../boards/adafruit_metro_esp32s2/board.h | 43 - .../hw/bsp/esp32s2/boards/esp32s2.c | 148 - .../boards/espressif_kaluga_1/board.cmake | 17 - .../esp32s2/boards/espressif_kaluga_1/board.h | 44 - .../boards/espressif_saola_1/board.cmake | 17 - .../esp32s2/boards/espressif_saola_1/board.h | 45 - .../components/led_strip/CMakeLists.txt | 8 - .../components/led_strip/include/led_strip.h | 126 - .../led_strip/src/led_strip_rmt_ws2812.c | 171 - .../esp_tinyusb/hw/bsp/esp32s2/family.cmake | 7 - .../esp_tinyusb/hw/bsp/esp32s2/family.mk | 23 - .../hw/bsp/esp32s3/boards/CMakeLists.txt | 14 - .../hw/bsp/esp32s3/boards/esp32s3.c | 148 - .../boards/espressif_addax_1/board.cmake | 7 - .../esp32s3/boards/espressif_addax_1/board.h | 44 - .../boards/espressif_s3_devkitc/board.cmake | 7 - .../boards/espressif_s3_devkitc/board.h | 43 - .../boards/espressif_s3_devkitm/board.cmake | 7 - .../boards/espressif_s3_devkitm/board.h | 43 - .../components/led_strip/CMakeLists.txt | 8 - .../components/led_strip/include/led_strip.h | 126 - .../led_strip/src/led_strip_rmt_ws2812.c | 171 - .../esp_tinyusb/hw/bsp/esp32s3/family.cmake | 7 - .../esp_tinyusb/hw/bsp/esp32s3/family.mk | 26 - .../esp_tinyusb/hw/bsp/family_support.cmake | 100 - .../components/esp_tinyusb/idf_component.yml | 20 +- .../{additions => }/include/tinyusb.h | 25 +- .../esp_tinyusb/include/tinyusb_net.h | 99 + .../esp_tinyusb/include/tinyusb_types.h | 21 + .../{additions => }/include/tusb_cdc_acm.h | 93 +- .../{additions => }/include/tusb_config.h | 56 +- .../{additions => }/include/tusb_console.h | 0 .../esp_tinyusb/include/tusb_msc_storage.h | 188 + .../{additions => }/include/tusb_tasks.h | 5 +- .../esp_tinyusb/include/vfs_tinyusb.h | 69 + .../{additions => }/include_private/cdc.h | 0 .../include_private/descriptors_control.h | 47 + .../include_private/usb_descriptors.h | 62 + .../esp_tinyusb/lib/SEGGER_RTT/License.txt | 34 - .../esp_tinyusb/lib/SEGGER_RTT/README.txt | 20 - .../lib/SEGGER_RTT/RTT/SEGGER_RTT.c | 2005 -------- .../lib/SEGGER_RTT/RTT/SEGGER_RTT.h | 321 -- .../SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S | 235 - .../lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h | 384 -- .../lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c | 500 -- .../Syscalls/SEGGER_RTT_Syscalls_GCC.c | 120 - .../Syscalls/SEGGER_RTT_Syscalls_IAR.c | 115 - .../Syscalls/SEGGER_RTT_Syscalls_KEIL.c | 386 -- .../Syscalls/SEGGER_RTT_Syscalls_SES.c | 247 - .../esp_tinyusb/lib/fatfs/00readme.txt | 138 - .../components/esp_tinyusb/lib/fatfs/ccsbcs.c | 543 --- .../components/esp_tinyusb/lib/fatfs/diskio.c | 193 - .../components/esp_tinyusb/lib/fatfs/diskio.h | 95 - .../components/esp_tinyusb/lib/fatfs/ff.c | 4330 ----------------- .../components/esp_tinyusb/lib/fatfs/ff.h | 342 -- .../components/esp_tinyusb/lib/fatfs/ffconf.h | 193 - .../esp_tinyusb/lib/fatfs/integer.h | 36 - .../esp_tinyusb/lib/networking/dhserver.c | 348 -- .../esp_tinyusb/lib/networking/dhserver.h | 62 - .../esp_tinyusb/lib/networking/dnserver.c | 200 - .../esp_tinyusb/lib/networking/dnserver.h | 47 - .../esp_tinyusb/lib/networking/ndis.h | 266 - .../lib/networking/rndis_protocol.h | 307 -- .../lib/networking/rndis_reports.c | 303 -- .../components/esp_tinyusb/pkg.yml | 14 - .../components/esp_tinyusb/repository.yml | 15 - .../components/esp_tinyusb/sbom.yml | 2 + .../components/esp_tinyusb/sdkconfig.rename | 22 - .../esp_tinyusb/src/class/audio/audio.h | 933 ---- .../src/class/audio/audio_device.c | 2294 --------- .../src/class/audio/audio_device.h | 637 --- .../esp_tinyusb/src/class/bth/bth_device.c | 258 - .../esp_tinyusb/src/class/bth/bth_device.h | 109 - .../esp_tinyusb/src/class/cdc/cdc.h | 409 -- .../esp_tinyusb/src/class/cdc/cdc_device.c | 486 -- .../esp_tinyusb/src/class/cdc/cdc_device.h | 260 - .../esp_tinyusb/src/class/cdc/cdc_host.c | 249 - .../esp_tinyusb/src/class/cdc/cdc_host.h | 134 - .../esp_tinyusb/src/class/cdc/cdc_rndis.h | 301 -- .../src/class/cdc/cdc_rndis_host.c | 279 -- .../src/class/cdc/cdc_rndis_host.h | 63 - .../esp_tinyusb/src/class/dfu/dfu.h | 119 - .../esp_tinyusb/src/class/dfu/dfu_device.c | 458 -- .../esp_tinyusb/src/class/dfu/dfu_device.h | 98 - .../esp_tinyusb/src/class/dfu/dfu_rt_device.c | 128 - .../esp_tinyusb/src/class/dfu/dfu_rt_device.h | 54 - .../esp_tinyusb/src/class/hid/hid.h | 1119 ----- .../esp_tinyusb/src/class/hid/hid_device.c | 417 -- .../esp_tinyusb/src/class/hid/hid_device.h | 393 -- .../esp_tinyusb/src/class/hid/hid_host.c | 636 --- .../esp_tinyusb/src/class/hid/hid_host.h | 152 - .../esp_tinyusb/src/class/midi/midi.h | 212 - .../esp_tinyusb/src/class/midi/midi_device.c | 545 --- .../esp_tinyusb/src/class/midi/midi_device.h | 173 - .../esp_tinyusb/src/class/msc/msc.h | 382 -- .../esp_tinyusb/src/class/msc/msc_device.c | 939 ---- .../esp_tinyusb/src/class/msc/msc_device.h | 159 - .../esp_tinyusb/src/class/msc/msc_host.c | 491 -- .../esp_tinyusb/src/class/msc/msc_host.h | 119 - .../src/class/net/ecm_rndis_device.c | 445 -- .../esp_tinyusb/src/class/net/ncm.h | 69 - .../esp_tinyusb/src/class/net/ncm_device.c | 510 -- .../esp_tinyusb/src/class/net/net_device.h | 118 - .../esp_tinyusb/src/class/usbtmc/usbtmc.h | 316 -- .../src/class/usbtmc/usbtmc_device.c | 858 ---- .../src/class/usbtmc/usbtmc_device.h | 116 - .../src/class/vendor/vendor_device.c | 257 - .../src/class/vendor/vendor_device.h | 136 - .../src/class/vendor/vendor_host.c | 146 - .../src/class/vendor/vendor_host.h | 67 - .../esp_tinyusb/src/class/video/video.h | 480 -- .../src/class/video/video_device.c | 1149 ----- .../src/class/video/video_device.h | 97 - .../esp_tinyusb/src/common/tusb_common.h | 406 -- .../esp_tinyusb/src/common/tusb_compiler.h | 258 - .../esp_tinyusb/src/common/tusb_error.h | 75 - .../esp_tinyusb/src/common/tusb_fifo.c | 1007 ---- .../esp_tinyusb/src/common/tusb_fifo.h | 151 - .../esp_tinyusb/src/common/tusb_timeout.h | 80 - .../esp_tinyusb/src/common/tusb_types.h | 546 --- .../esp_tinyusb/src/common/tusb_verify.h | 181 - .../components/esp_tinyusb/src/device/dcd.h | 193 - .../esp_tinyusb/src/device/dcd_attr.h | 221 - .../components/esp_tinyusb/src/device/usbd.c | 1419 ------ .../components/esp_tinyusb/src/device/usbd.h | 853 ---- .../esp_tinyusb/src/device/usbd_control.c | 233 - .../esp_tinyusb/src/device/usbd_pvt.h | 115 - .../components/esp_tinyusb/src/host/hcd.h | 179 - .../esp_tinyusb/src/host/hcd_attr.h | 105 - .../components/esp_tinyusb/src/host/hub.c | 388 -- .../components/esp_tinyusb/src/host/hub.h | 196 - .../components/esp_tinyusb/src/host/usbh.c | 1204 ----- .../components/esp_tinyusb/src/host/usbh.h | 99 - .../esp_tinyusb/src/host/usbh_classdriver.h | 83 - .../esp_tinyusb/src/host/usbh_control.c | 138 - .../components/esp_tinyusb/src/osal/osal.h | 111 - .../esp_tinyusb/src/osal/osal_freertos.h | 172 - .../esp_tinyusb/src/osal/osal_mynewt.h | 174 - .../esp_tinyusb/src/osal/osal_none.h | 204 - .../esp_tinyusb/src/osal/osal_pico.h | 187 - .../esp_tinyusb/src/osal/osal_rtthread.h | 130 - .../portable/espressif/esp32sx/dcd_esp32sx.c | 854 ---- .../components/esp_tinyusb/src/tusb.c | 245 - .../components/esp_tinyusb/src/tusb.h | 140 - .../components/esp_tinyusb/src/tusb_option.h | 382 -- .../esp_tinyusb/test/local/CMakeLists.txt | 8 + .../esp_tinyusb/test/local/libusb_test.c | 121 + .../esp_tinyusb/test_app/CMakeLists.txt | 11 + .../components/esp_tinyusb/test_app/README.md | 4 + .../esp_tinyusb/test_app/main/CMakeLists.txt | 6 + .../test_app/main/idf_component.yml | 7 + .../esp_tinyusb/test_app/main/test_app_main.c | 57 + .../test_app/main/test_bvalid_sig.c | 103 + .../test_app/main/test_bvalid_sig.h | 18 + .../test_app/main/test_descriptors_config.c | 235 + .../test_app/main/test_descriptors_config.h | 18 + .../test_app/main/test_esp_tinyusb.c | 132 + .../esp_tinyusb/test_app/main/test_tud_cb.c | 28 + .../test_app/pytest_usb_device_cdc.py | 73 + .../test_app/pytest_usb_device_esp_tinyusb.py | 12 + .../esp_tinyusb/test_app/sdkconfig.defaults | 19 + .../esp_tinyusb/{additions/src => }/tinyusb.c | 46 +- .../components/esp_tinyusb/tinyusb_net.c | 174 + .../esp_tinyusb/tools/build_board.py | 100 - .../esp_tinyusb/tools/build_esp32sx.py | 101 - .../esp_tinyusb/tools/build_family.py | 113 - .../esp_tinyusb/tools/build_utils.py | 61 - .../components/esp_tinyusb/tools/iar_gen.py | 51 - .../esp_tinyusb/tools/iar_template.ipcf | 145 - .../components/esp_tinyusb/tools/top.mk | 30 - .../tools/usb_drivers/tinyusb_win_usbser.inf | 108 - .../{additions/src => }/tusb_cdc_acm.c | 191 +- .../{additions/src => }/tusb_console.c | 2 +- .../components/esp_tinyusb/tusb_msc_storage.c | 640 +++ .../components/esp_tinyusb/tusb_tasks.c | 77 + .../{additions/src => }/usb_descriptors.c | 159 +- .../components/esp_tinyusb/version.yml | 3 - .../{additions/src => }/vfs_tinyusb.c | 126 +- .../espidf-peripherals-usb/platformio.ini | 3 + 208 files changed, 3362 insertions(+), 44347 deletions(-) delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/CHANGELOG.md delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/README.md delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions/src => }/cdc.c (100%) create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/descriptors_control.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions => }/include/tinyusb.h (65%) create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_net.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_types.h rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions => }/include/tusb_cdc_acm.h (68%) rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions => }/include/tusb_config.h (65%) rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions => }/include/tusb_console.h (100%) create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_msc_storage.h rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions => }/include/tusb_tasks.h (80%) create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/include/vfs_tinyusb.h rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions => }/include_private/cdc.h (100%) create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/descriptors_control.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/usb_descriptors.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/sbom.yml delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.h delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb_option.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/CMakeLists.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/libusb_test.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/CMakeLists.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/README.md create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/CMakeLists.txt create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/idf_component.yml create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_app_main.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.h create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_esp_tinyusb.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_tud_cb.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_cdc.py create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_esp_tinyusb.py create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/sdkconfig.defaults rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions/src => }/tinyusb.c (53%) create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb_net.c delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions/src => }/tusb_cdc_acm.c (65%) rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions/src => }/tusb_console.c (97%) create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_msc_storage.c create mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_tasks.c rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions/src => }/usb_descriptors.c (50%) delete mode 100644 examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml rename examples/espidf-peripherals-usb/components/esp_tinyusb/{additions/src => }/vfs_tinyusb.c (66%) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes b/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes deleted file mode 100644 index 2342decc3..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitattributes +++ /dev/null @@ -1,25 +0,0 @@ -# Set the default behavior, in case people don't have core.autocrlf set. -* text=auto - -*.c text -*.cpp text -*.h text -*.icf text -*.js text -*.json text -*.ld text -*.md text -*.mk text -*.py text -*.rst text -*.s text -*.txt text -*.xml text -*.yml text - -Makefile text - -# Windows-only Visual Studio things - -*.sln text eol=crlf -*.csproj text eol=crlf diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore b/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore deleted file mode 100644 index 87a5faa80..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -html -latex -*.d -*.o -*.P -*.map -*.axf -*.bin -*.jlink -*.emSession -*.elf -*.ind -.env -.settings/ -.idea/ -.gdb_history -/examples/*/*/build* -test_old/ -tests_obsolete/ -_build -/examples/*/*/ses -/examples/*/*/ozone -/examples/obsolete -# coverity intermediate files -cov-int -# cppcheck build directories -*-build-dir -/_bin/ -__pycache__ - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml b/examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml deleted file mode 100644 index e83cd90fd..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/.readthedocs.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# .readthedocs.yaml -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -version: 2 - -sphinx: - configuration: docs/conf.py - -python: - version: 3.8 - install: - - requirements: docs/requirements.txt - -submodules: - include: [] - recursive: false - \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CHANGELOG.md b/examples/espidf-peripherals-usb/components/esp_tinyusb/CHANGELOG.md new file mode 100644 index 000000000..78608a7a4 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/CHANGELOG.md @@ -0,0 +1,53 @@ +## 1.4.4 + +- esp_tinyusb: Added HighSpeed and Qualifier device descriptors in tinyusb configuration +- CDC-ACM: Removed MIN() definition if already defined +- MSC: Fixed EP size selecting in default configuration descriptor + +## 1.4.3 + +- esp_tinyusb: Added ESP32P4 support (HS only) + +## 1.4.2 + +- MSC: Fixed maximum files open +- Added uninstall function + +## 1.4.0 + +- MSC: Fixed integer overflows +- CDC-ACM: Removed intermediate RX ringbuffer +- CDC-ACM: Increased default FIFO size to 512 bytes +- CDC-ACM: Fixed Virtual File System binding + +## 1.3.0 + +- Added NCM extension + +## 1.2.1 - 1.2.2 + +- Minor bugfixes + +## 1.2.0 + +- Added MSC extension for accessing SPI Flash on memory card https://github.com/espressif/idf-extra-components/commit/a8c00d7707ba4ceeb0970c023d702c7768dba3dc + +## 1.1.0 + +- Added support for NCM, ECM/RNDIS, DFU and Bluetooth TinyUSB drivers https://github.com/espressif/idf-extra-components/commit/79f35c9b047b583080f93a63310e2ee7d82ef17b + +## 1.0.4 + +- Cleaned up string descriptors handling https://github.com/espressif/idf-extra-components/commit/046cc4b02f524d5c7e3e56480a473cfe844dc3d6 + +## 1.0.2 - 1.0.3 + +- Minor bugfixes + +## 1.0.1 + +- CDC-ACM: Return ESP_OK if there is nothing to flush https://github.com/espressif/idf-extra-components/commit/388ff32eb09aa572d98c54cb355f1912ce42707c + +## 1.0.0 + +- Initial version based on [esp-idf v4.4.3](https://github.com/espressif/esp-idf/tree/v4.4.3/components/tinyusb) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt index 019a6f489..98fc960e7 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/CMakeLists.txt @@ -1,73 +1,53 @@ -idf_build_get_property(target IDF_TARGET) - -if(target STREQUAL "esp32s3") - set(tusb_mcu "OPT_MCU_ESP32S3") - set(tusb_family "esp32sx") -elseif(target STREQUAL "esp32s2") - set(tusb_mcu "OPT_MCU_ESP32S2") - set(tusb_family "esp32sx") -else() - message(FATAL_ERROR "TinyUSB is not support on ${target}.") - return() -endif() - -set(compile_options - "-DCFG_TUSB_MCU=${tusb_mcu}" - "-DCFG_TUSB_DEBUG=${CONFIG_TINYUSB_DEBUG_LEVEL}" - ) - -idf_component_get_property(freertos_component_dir freertos COMPONENT_DIR) - -set(includes_private - "hw/bsp/" - "src/" - "src/device" - "additions/include_private" - ) - -set(includes_public - "src/" - "additions/include" - # The FreeRTOS API include convention in tinyusb is different from esp-idf - "${freertos_component_dir}/FreeRTOS-Kernel/include/freertos" - ) - set(srcs - "src/portable/espressif/${tusb_family}/dcd_${tusb_family}.c" - "src/class/cdc/cdc_device.c" - "src/class/hid/hid_device.c" - "src/class/midi/midi_device.c" - "src/class/msc/msc_device.c" - "src/class/vendor/vendor_device.c" - "src/common/tusb_fifo.c" - "src/device/usbd_control.c" - "src/device/usbd.c" - "src/tusb.c" - "additions/src/descriptors_control.c" - "additions/src/tinyusb.c" - "additions/src/usb_descriptors.c" + "descriptors_control.c" + "tinyusb.c" + "usb_descriptors.c" ) if(NOT CONFIG_TINYUSB_NO_DEFAULT_TASK) - list(APPEND srcs "additions/src/tusb_tasks.c") -endif() + list(APPEND srcs "tusb_tasks.c") +endif() # CONFIG_TINYUSB_NO_DEFAULT_TASK if(CONFIG_TINYUSB_CDC_ENABLED) list(APPEND srcs - "additions/src/cdc.c" - "additions/src/tusb_cdc_acm.c" - "additions/src/tusb_console.c" - "additions/src/vfs_tinyusb.c" + "cdc.c" + "tusb_cdc_acm.c" ) + if(CONFIG_VFS_SUPPORT_IO) + list(APPEND srcs + "tusb_console.c" + "vfs_tinyusb.c" + ) + endif() # CONFIG_VFS_SUPPORT_IO endif() # CONFIG_TINYUSB_CDC_ENABLED +if(CONFIG_TINYUSB_MSC_ENABLED) + list(APPEND srcs + tusb_msc_storage.c + ) +endif() # CONFIG_TINYUSB_MSC_ENABLED + +if(CONFIG_TINYUSB_NET_MODE_NCM) + list(APPEND srcs + tinyusb_net.c + ) +endif() # CONFIG_TINYUSB_NET_MODE_NCM + idf_component_register(SRCS ${srcs} - INCLUDE_DIRS ${includes_public} - PRIV_INCLUDE_DIRS ${includes_private} - PRIV_REQUIRES "vfs" "usb" "driver" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "include_private" + PRIV_REQUIRES usb + REQUIRES fatfs vfs ) -target_compile_options(${COMPONENT_LIB} PRIVATE ${compile_options}) +# Determine whether tinyusb is fetched from component registry or from local path +idf_build_get_property(build_components BUILD_COMPONENTS) +if(tinyusb IN_LIST build_components) + set(tinyusb_name tinyusb) # Local component +else() + set(tinyusb_name espressif__tinyusb) # Managed component +endif() -# when no builtin class driver is enabled, an uint8_t data compared with `BUILTIN_DRIVER_COUNT` will always be false -set_source_files_properties("src/device/usbd.c" PROPERTIES COMPILE_FLAGS "-Wno-type-limits") +# Pass tusb_config.h from this component to TinyUSB +idf_component_get_property(tusb_lib ${tinyusb_name} COMPONENT_LIB) +target_include_directories(${tusb_lib} PRIVATE "include") diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst b/examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst deleted file mode 100644 index 4035c528f..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/CODE_OF_CONDUCT.rst +++ /dev/null @@ -1,88 +0,0 @@ -*************** -Code of Conduct -*************** - -Our Pledge ----------- - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our -project and our community a harassment-free experience for everyone, -regardless of age, body size, disability, ethnicity, sex -characteristics, gender identity and expression, level of experience, -education, socio-economic status, nationality, personal appearance, -race, religion, or sexual identity and orientation. - -Our Standards -------------- - -Examples of behavior that contributes to creating a positive environment -include: - -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Gracefully accepting constructive criticism -- Focusing on what is best for the community -- Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -- The use of sexualized language or imagery and unwelcome sexual - attention or advances -- Trolling, insulting/derogatory comments, and personal or political - attacks -- Public or private harassment -- Publishing others' private information, such as a physical or - electronic address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -Our Responsibilities --------------------- - -Project maintainers are responsible for clarifying the standards of -acceptable behavior and are expected to take appropriate and fair -corrective action in response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, -or reject comments, commits, code, wiki edits, issues, and other -contributions that are not aligned to this Code of Conduct, or to ban -temporarily or permanently any contributor for other behaviors that they -deem inappropriate, threatening, offensive, or harmful. - -Scope ------ - -This Code of Conduct applies both within project spaces and in public -spaces when an individual is representing the project or its community. -Examples of representing a project or community include using an -official project e-mail address, posting via an official social media -account, or acting as an appointed representative at an online or -offline event. Representation of a project may be further defined and -clarified by project maintainers. - -Enforcement ------------ - -Instances of abusive, harassing, or otherwise unacceptable behavior may -be reported by contacting the project team at thach@tinyusb.org. All -complaints will be reviewed and investigated and will result in a -response that is deemed necessary and appropriate to the circumstances. -The project team is obligated to maintain confidentiality with regard to -the reporter of an incident. Further details of specific enforcement -policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in -good faith may face temporary or permanent repercussions as determined -by other members of the project's leadership. - -Attribution ------------ - -This Code of Conduct is adapted from the `Contributor -Covenant `__, version 1.4, -available at -https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst b/examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst deleted file mode 100644 index e3186f086..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/CONTRIBUTORS.rst +++ /dev/null @@ -1,192 +0,0 @@ -************ -Contributors -************ - -Special thanks to all the people who spent their precious time and effort to help this project so far. -list contributors and their awesome work for the stack: - -Notable contributors -==================== - -(sorted alphabetically) - -`Adafruit Team `__ ------------------------------------------------ - -- Main supporter and sponsor for hardware boards and kits -- Discussion and suggestion for feature and improvement -- Design the project logo - - -`Ha Thach `__ ------------------------------------------ - -- *Author and maintainer* -- Most features development - - -`Hristo Gochkov `__ -------------------------------------------------- - -- Improve ESP32s2 DCD - - -`Jacob Berg Potter `__ ------------------------------------------------- - -- Add new class driver for network CDC-NCM - - -`Jan Dümpelmann `__ ------------------------------------------------ - -- Improve transfer performance for Synopsys DCD for STM32 MCUs - - -`Jeff Epler `__ ------------------------------------------- - -- Improve MIDI class driver - - -`Jerzy Kasenberg `__ ------------------------------------------------ - -- Add new DCD port for Dialog DA1469x -- Add new class driver for Bluetooth HCI -- Add ISO transfer for STM32 Synopsys, Nordic nRF, Dialog DA1469x -- Improve Audio driver and add uac2\_headset example -- Improve STM32 Synopsys DCD with various PRs - - -`J McCarthy `__ --------------------------------------------------- - -- Add new DFU 1.1 class driver -- Add new example for dfu - - -`Kamil Tomaszewski `__ ----------------------------------------------------- - -- Add new DCD port for Sony CXD56 (spresnese board) - - -`Kay Sievers `__ ------------------------------------------------ - -- Improve MIDI driver with packet API - - -`Koji KITAYAMA `__ ------------------------------------------------ - -- Add new DCD port for NXP Kinetis KL25 -- Add new DCD port for Renesas RX family (RX600, RX700 ..) with GR-CITRUS, RX65n target board -- Add new class driver for USB Video Class (UVC 1.5) - - -`Nathan Conrad `__ ---------------------------------------------- - -- Add new DCD port for STM32 fsdev Fullspeed device for STM32 L0, - F0, F1, F3 etc ... -- Add new class driver for USB Test and Measurement Class (USBTMC) -- Various improvement e.g Zero-length packet, Lint setup -- Board support for STM32F070RB Nucleo, STM32F303 Discovery - - -`Peter Lawrence `__ ------------------------------------------------- - -- Add new DCD port for Nuvoton NUC 120, 121, 125, 126, 505 -- Add new class driver for network RNDIS, CDC-ECM -- Enhance CDC-NCM network driver to compatible with RNDIS/ECM -- Add *net\_lwip\_webserver* example for demonstration of usbnet with lwip -- Board support for NuTiny NUC120, NUC121s, NUC125s, NUC126V, NUC505 -- Improve multiple cdc interfaces API & add cdc\_dual\_ports example - - -`Rafael Silva `__ ----------------------------------------------- - -- Port DCD Synopsys to support Silabs EFM32GG12 with SLTB009A board -- Rewrite documentation in rst and setup for readthedocs - - -`Raspberry Pi Team `__ ------------------------------------------------------- - -- Add new DCD port for Raspberry Pi RP2040 -- Add new HCD port for Raspberry Pi RP2040 - - -`Reinhard Panhuber `__ ------------------------------------------------- - -- Add new class driver for USB Audio Class 2.0 (UAC2) -- Rework tu\_fifo with unmasked pointer, add DMA support, and constant address support -- Add new DCD/USBD edpt\_xfer\_fifo() API for optimizing endpoint transfer -- Add and greatly improve Isochronous transfer -- Add new audio examples: audio\_test and audio\_4\_channel\_mic - - -`Scott Shawcroft `__ ------------------------------------------------- - -- Add new DCD port for SAMD21 and SAMD51 -- Add new class driver for Musical Instrument Digital Interface (MIDI) -- Improve USBD control transfer, MSC, CDC class driver -- Board support for Metro M0 & M4 express -- Write the excellent porting.md documentation -- Add initial Makefile - -`Sean Cross `__ ----------------------------------------- - -- Add new DCD port for ValentyUSB eptri (fomu board) - - -`Sylvain "tnt" Munaut `__ ------------------------------------------------------ - -- Add new class driver for DFU Runtime - - -`Timon Skerutsch `__ ----------------------------------------------- - -- Add hid\_test.js script and extensive test for bi-directional raw HID - - -`Tod E. Kurt `__ -------------------------------------------- - -- Add hid\_test.js script and extensive test for bi-directional raw HID - - -`Uwe Bonnes `__ ---------------------------------------------- - -- Improve STM32 Synopsys highspeed DCD - - -`William D. Jones `__ ------------------------------------------------- - -- Add new DCD port for Synopsys DesignWare for STM32 L4, F2, F4, - F7, H7 etc ... -- Add new DCD port for TI MSP430 -- Board support for STM32F407 Discovery, STM32H743 Nucleo, pyboard v1.1, msp\_exp430f5529lp etc ... - - -`Zixun Li `__ -------------------------------------------- - -- Add new DCD port for Microchip SAMx7x -- Add IAR compiler support -- Improve UAC2, CDC, DFU class driver - - -`Full contributors list `__ -============================================================================ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig b/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig index 324fe70ec..7b01f4c37 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/Kconfig @@ -1,11 +1,22 @@ menu "TinyUSB Stack" config TINYUSB_DEBUG_LEVEL int "TinyUSB log level (0-3)" - default 0 + default 1 range 0 3 help Specify verbosity of TinyUSB log output. + choice TINYUSB_RHPORT + depends on IDF_TARGET_ESP32P4 + prompt "TinyUSB PHY" + default TINYUSB_RHPORT_HS + help + Allows set the USB PHY Controller for TinyUSB: HS (USB OTG2.0 PHY for HighSpeed) + + config TINYUSB_RHPORT_HS + bool "HS" + endchoice + menu "TinyUSB task configuration" config TINYUSB_NO_DEFAULT_TASK bool "Do not create a TinyUSB task" @@ -27,9 +38,43 @@ menu "TinyUSB Stack" depends on !TINYUSB_NO_DEFAULT_TASK help Set the stack size of the default TinyUSB main task. + + choice TINYUSB_TASK_AFFINITY + prompt "TinyUSB task affinity" + default TINYUSB_TASK_AFFINITY_NO_AFFINITY + depends on !TINYUSB_NO_DEFAULT_TASK + help + Allows setting TinyUSB tasks affinity, i.e. whether the task is pinned to + CPU0, pinned to CPU1, or allowed to run on any CPU. + + config TINYUSB_TASK_AFFINITY_NO_AFFINITY + bool "No affinity" + config TINYUSB_TASK_AFFINITY_CPU0 + bool "CPU0" + config TINYUSB_TASK_AFFINITY_CPU1 + bool "CPU1" + depends on !FREERTOS_UNICORE + endchoice + + config TINYUSB_TASK_AFFINITY + hex + default FREERTOS_NO_AFFINITY if TINYUSB_TASK_AFFINITY_NO_AFFINITY + default 0x0 if TINYUSB_TASK_AFFINITY_CPU0 + default 0x1 if TINYUSB_TASK_AFFINITY_CPU1 + + config TINYUSB_INIT_IN_DEFAULT_TASK + bool "Initialize TinyUSB stack within the default TinyUSB task" + default n + depends on !TINYUSB_NO_DEFAULT_TASK + help + Run TinyUSB stack initialization just after starting the default TinyUSB task. + This is especially useful in multicore scenarios, when we need to pin the task + to a specific core and, at the same time initialize TinyUSB stack + (i.e. install interrupts) on the same core. endmenu menu "Descriptor configuration" + comment "You can provide your custom descriptors via tinyusb_driver_install()" config TINYUSB_DESC_USE_ESPRESSIF_VID bool "VID: Use Espressif's vendor ID" default y @@ -110,6 +155,13 @@ menu "TinyUSB Stack" range 64 10000 help MSC FIFO size, in bytes. + + config TINYUSB_MSC_MOUNT_PATH + depends on TINYUSB_MSC_ENABLED + string "Mount Path" + default "/data" + help + MSC Mount Path of storage. endmenu # "Massive Storage Class" menu "Communication Device Class (CDC)" @@ -130,7 +182,7 @@ menu "TinyUSB Stack" config TINYUSB_CDC_RX_BUFSIZE depends on TINYUSB_CDC_ENABLED int "CDC FIFO size of RX channel" - default 64 + default 512 range 64 10000 help CDC FIFO size of RX channel. @@ -138,7 +190,7 @@ menu "TinyUSB Stack" config TINYUSB_CDC_TX_BUFSIZE depends on TINYUSB_CDC_ENABLED int "CDC FIFO size of TX channel" - default 64 + default 512 help CDC FIFO size of TX channel. endmenu # "Communication Device Class" @@ -160,4 +212,61 @@ menu "TinyUSB Stack" help Setting value greater than 0 will enable TinyUSB HID feature. endmenu # "HID Device Class (HID)" + + menu "Device Firmware Upgrade (DFU)" + choice TINYUSB_DFU_MODE + prompt "DFU mode" + default TINYUSB_DFU_MODE_NONE + help + Select which DFU driver you want to use. + + config TINYUSB_DFU_MODE_DFU + bool "DFU" + + config TINYUSB_DFU_MODE_DFU_RUNTIME + bool "DFU Runtime" + + config TINYUSB_DFU_MODE_NONE + bool "None" + endchoice + config TINYUSB_DFU_BUFSIZE + depends on TINYUSB_DFU_MODE_DFU + int "DFU XFER BUFFSIZE" + default 512 + help + DFU XFER BUFFSIZE. + endmenu # Device Firmware Upgrade (DFU) + + menu "Bluetooth Host Class (BTH)" + config TINYUSB_BTH_ENABLED + bool "Enable TinyUSB BTH feature" + default n + help + Enable TinyUSB BTH feature. + + config TINYUSB_BTH_ISO_ALT_COUNT + depends on TINYUSB_BTH_ENABLED + int "BTH ISO ALT COUNT" + default 0 + help + BTH ISO ALT COUNT. + endmenu # "Bluetooth Host Device Class" + + menu "Network driver (ECM/NCM/RNDIS)" + choice TINYUSB_NET_MODE + prompt "Network mode" + default TINYUSB_NET_MODE_NONE + help + Select network driver you want to use. + + config TINYUSB_NET_MODE_ECM_RNDIS + bool "ECM/RNDIS" + + config TINYUSB_NET_MODE_NCM + bool "NCM" + + config TINYUSB_NET_MODE_NONE + bool "None" + endchoice + endmenu # "Network driver (ECM/NCM/RNDIS)" endmenu # "TinyUSB Stack" diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE b/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE index ddd4ab410..d64569567 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/LICENSE @@ -1,21 +1,202 @@ -The MIT License (MIT) - -Copyright (c) 2018, hathach (tinyusb.org) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/README.md b/examples/espidf-peripherals-usb/components/esp_tinyusb/README.md new file mode 100644 index 000000000..478f206a5 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/README.md @@ -0,0 +1,32 @@ +# Espressif's additions to TinyUSB + +[![Component Registry](https://components.espressif.com/components/espressif/esp_tinyusb/badge.svg)](https://components.espressif.com/components/espressif/esp_tinyusb) + +This component adds features to TinyUSB that help users with integrating TinyUSB with their ESP-IDF application. + +It contains: +* Configuration of USB device and string descriptors +* USB Serial Device (CDC-ACM) with optional Virtual File System support +* Input and output streams through USB Serial Device. This feature is available only when Virtual File System support is enabled. +* Other USB classes (MIDI, MSC, HID…) support directly via TinyUSB +* VBUS monitoring for self-powered devices +* SPI Flash or sd-card access via MSC USB device Class. + +## Documentation and examples +You can find documentation in [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/usb_device.html). + +You can find examples in [ESP-IDF on GitHub](https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb/device). +## How to use? + +This component is distributed via [IDF component manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html). Just add `idf_component.yml` file to your main component with the following content: + +``` yaml +## IDF Component Manager Manifest File +dependencies: + esp_tinyusb: "~1.0.0" +``` + +Or simply run: +``` +idf.py add-dependency esp_tinyusb~1.0.0 +``` diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst b/examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst deleted file mode 100644 index 4946e997e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/README.rst +++ /dev/null @@ -1,145 +0,0 @@ -.. figure:: docs/assets/logo.svg - :alt: TinyUSB - -|Build Status| |Documentation Status| |License| - -TinyUSB is an open-source cross-platform USB Host/Device stack for -embedded system, designed to be memory-safe with no dynamic allocation -and thread-safe with all interrupt events are deferred then handled in -the non-ISR task function. - -Please take a look at the online `documentation `__. - -.. figure:: docs/assets/stack.svg - :width: 500px - :alt: stackup - -:: - - . - ├── docs # Documentation - ├── examples # Sample with Makefile build support - ├── hw - │   ├── bsp # Supported boards source files - │   └── mcu # Low level mcu core & peripheral drivers - ├── lib # Sources from 3rd party such as freeRTOS, fatfs ... - ├── src # All sources files for TinyUSB stack itself. - ├── test # Unit tests for the stack - └── tools # Files used internally - -Supported MCUs -============== - -The stack supports the following MCUs: - -- **Broadcom:** BCM2837, BCM2711 -- **Dialog:** DA1469x -- **Espressif:** ESP32-S2, ESP32-S3 -- **GigaDevice:** GD32VF103 -- **Infineon:** XMC4500 -- **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG55, SAML21, SAML22, SAME7x -- **NordicSemi:** nRF52833, nRF52840, nRF5340 -- **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505 -- **NXP:** - - - iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064 - - Kinetis: KL25, K32L2 - - LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55 - -- **Raspberry Pi:** RP2040 -- **Renesas:** RX63N, RX65N, RX72N -- **Silabs:** EFM32GG -- **Sony:** CXD56 -- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, G4, L0, L1, L4, L4+ -- **TI:** MSP430, MSP432E4, TM4C123 -- **ValentyUSB:** eptri - -Here is the list of `Supported Devices`_ that can be used with provided examples. - -Device Stack -============ - -Supports multiple device configurations by dynamically changing USB descriptors, low power functions such like suspend, resume, and remote wakeup. The following device classes are supported: - -- Audio Class 2.0 (UAC2) -- Bluetooth Host Controller Interface (BTH HCI) -- Communication Device Class (CDC) -- Device Firmware Update (DFU): DFU mode (WIP) and Runtinme -- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ... -- Mass Storage Class (MSC): with multiple LUNs -- Musical Instrument Digital Interface (MIDI) -- Network with RNDIS, Ethernet Control Model (ECM), Network Control Model (NCM) -- Test and Measurement Class (USBTMC) -- Video class 1.5 (UVC): work in progress -- Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file. -- `WebUSB `__ with vendor-specific class - -If you have a special requirement, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how the RPi team added their reset interface `raspberrypi/pico-sdk#197 `_ - -Host Stack -========== - -- Human Interface Device (HID): Keyboard, Mouse, Generic -- Mass Storage Class (MSC) -- Hub currently only supports 1 level of hub (due to my laziness) - -OS Abstraction layer -==================== - -TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) events into a central queue, then processing them later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as Communication Device Class (CDC) FIFO. Therefore the stack needs to use some of the OS's basic APIs. Following OSes are already supported out of the box. - -- **No OS** -- **FreeRTOS** -- `RT-Thread `_ -- **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its `own repo `_ - -Local Docs -========== - -- Info - - - `Uses`_ - - `Changelog`_ - - `Contributors`_ - -- `Reference`_ - - - `Supported Devices`_ - - `Getting Started`_ - - `Concurrency`_ - -- `Contributing`_ - - - `Code of Conduct`_ - - `Structure`_ - - `Porting`_ - -License -======= - -All TinyUSB sources in the ``src`` folder are licensed under MIT -license, the `Full license is here `__. However, each file can be -individually licensed especially those in ``lib`` and ``hw/mcu`` folder. -Please make sure you understand all the license term for files you use -in your project. - - -.. |Build Status| image:: https://github.com/hathach/tinyusb/workflows/Build/badge.svg - :target: https://github.com/hathach/tinyusb/actions -.. |Documentation Status| image:: https://readthedocs.org/projects/tinyusb/badge/?version=latest - :target: https://docs.tinyusb.org/en/latest/?badge=latest -.. |License| image:: https://img.shields.io/badge/license-MIT-brightgreen.svg - :target: https://opensource.org/licenses/MIT - - -.. _Uses: docs/info/uses.rst -.. _Changelog: docs/info/changelog.rst -.. _Contributors: CONTRIBUTORS.rst -.. _Reference: docs/reference/index.rst -.. _Supported Devices: docs/reference/supported.rst -.. _Getting Started: docs/reference/getting_started.rst -.. _Concurrency: docs/reference/concurrency.rst -.. _Contributing: docs/contributing/index.rst -.. _Code of Conduct: CODE_OF_CONDUCT.rst -.. _Structure: docs/contributing/structure.rst -.. _Porting: docs/contributing/porting.rst diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h deleted file mode 100644 index 1f01fe132..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb_types.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#define USB_ESPRESSIF_VID 0x303A -#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 8 // (4 + TINYUSB_STR_DESC_LEN) - -typedef enum{ - TINYUSB_USBDEV_0, -} tinyusb_usbdev_t; - -typedef const char *tusb_desc_strarray_device_t[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h deleted file mode 100644 index 79c69bd72..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/vfs_tinyusb.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Register TinyUSB CDC at VFS with path - * @param cdc_intf - interface number of TinyUSB's CDC - * @param path - path where the CDC will be registered, `/dev/tusb_cdc` will be used if left NULL. - * - * @return esp_err_t ESP_OK or ESP_FAIL - */ -esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path); - -/** - * @brief Unregister TinyUSB CDC from VFS - * @param path - path where the CDC will be unregistered if NULL will be used `/dev/tusb_cdc` - * - * @return esp_err_t ESP_OK or ESP_FAIL - */ -esp_err_t esp_vfs_tusb_cdc_unregister(char const *path); - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h deleted file mode 100644 index b6516e1a7..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/descriptors_control.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "tusb.h" -#include "tinyusb_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void tusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, const uint8_t *cfg_desc); -tusb_desc_device_t *tusb_get_active_desc(void); -char **tusb_get_active_str_desc(void); -void tusb_clear_descriptor(void); - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h deleted file mode 100644 index 215010c94..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/usb_descriptors.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "tusb.h" -#include "tinyusb_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) - -extern tusb_desc_device_t descriptor_tinyusb; -extern tusb_desc_strarray_device_t descriptor_str_tinyusb; - -extern const tusb_desc_device_t descriptor_dev_kconfig; -extern tusb_desc_strarray_device_t descriptor_str_kconfig; -extern const uint8_t descriptor_cfg_kconfig[]; - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c deleted file mode 100644 index 7e9ed4cbe..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/descriptors_control.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "esp_log.h" -#include "descriptors_control.h" - -static const char *TAG = "tusb_desc"; -static tusb_desc_device_t s_device_descriptor; -static const uint8_t *s_configuration_descriptor; -static char *s_str_descriptor[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; -#define MAX_DESC_BUF_SIZE 32 - -// ============================================================================= -// CALLBACKS -// ============================================================================= - -/** - * @brief Invoked when received GET DEVICE DESCRIPTOR. - * Application returns pointer to descriptor - * - * @return uint8_t const* - */ -uint8_t const *tud_descriptor_device_cb(void) -{ - return (uint8_t const *)&s_device_descriptor; -} - -/** - * @brief Invoked when received GET CONFIGURATION DESCRIPTOR. - * Descriptor contents must exist long enough for transfer to complete - * - * @param index - * @return uint8_t const* Application return pointer to descriptor - */ -uint8_t const *tud_descriptor_configuration_cb(uint8_t index) -{ - (void)index; // for multiple configurations - return s_configuration_descriptor; -} - -static uint16_t _desc_str[MAX_DESC_BUF_SIZE]; - -// Invoked when received GET STRING DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) -{ - (void) langid; - - uint8_t chr_count; - - if ( index == 0) { - memcpy(&_desc_str[1], s_str_descriptor[0], 2); - chr_count = 1; - } else { - // Convert ASCII string into UTF-16 - - if ( index >= sizeof(s_str_descriptor) / sizeof(s_str_descriptor[0]) ) { - ESP_LOGE(TAG, "String index (%u) is out of bounds, check your string descriptor", index); - return NULL; - } - - if (s_str_descriptor[index] == NULL) { - ESP_LOGE(TAG, "String index (%u) points to NULL, check your string descriptor", index); - return NULL; - } - - const char *str = s_str_descriptor[index]; - - // Cap at max char - chr_count = strlen(str); - if ( chr_count > MAX_DESC_BUF_SIZE - 1 ) { - chr_count = MAX_DESC_BUF_SIZE - 1; - } - - for (uint8_t i = 0; i < chr_count; i++) { - _desc_str[1 + i] = str[i]; - } - } - - // first byte is length (including header), second byte is string type - _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * chr_count + 2); - - return _desc_str; -} - -// ============================================================================= -// Driver functions -// ============================================================================= - -void tusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, const uint8_t *cfg_desc) -{ - ESP_LOGI(TAG, "\n" - "┌─────────────────────────────────┐\n" - "│ USB Device Descriptor Summary │\n" - "├───────────────────┬─────────────┤\n" - "│bDeviceClass │ %-4u │\n" - "├───────────────────┼─────────────┤\n" - "│bDeviceSubClass │ %-4u │\n" - "├───────────────────┼─────────────┤\n" - "│bDeviceProtocol │ %-4u │\n" - "├───────────────────┼─────────────┤\n" - "│bMaxPacketSize0 │ %-4u │\n" - "├───────────────────┼─────────────┤\n" - "│idVendor │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│idProduct │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│bcdDevice │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│iManufacturer │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│iProduct │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│iSerialNumber │ %-#10x │\n" - "├───────────────────┼─────────────┤\n" - "│bNumConfigurations │ %-#10x │\n" - "└───────────────────┴─────────────┘", - dev_desc->bDeviceClass, dev_desc->bDeviceSubClass, - dev_desc->bDeviceProtocol, dev_desc->bMaxPacketSize0, - dev_desc->idVendor, dev_desc->idProduct, dev_desc->bcdDevice, - dev_desc->iManufacturer, dev_desc->iProduct, dev_desc->iSerialNumber, - dev_desc->bNumConfigurations); - s_device_descriptor = *dev_desc; - s_configuration_descriptor = cfg_desc; - - if (str_desc != NULL) { - memcpy(s_str_descriptor, str_desc, - sizeof(s_str_descriptor[0])*USB_STRING_DESCRIPTOR_ARRAY_SIZE); - } -} - -tusb_desc_device_t *tusb_get_active_desc(void) -{ - return &s_device_descriptor; -} - -char **tusb_get_active_str_desc(void) -{ - return s_str_descriptor; -} - -void tusb_clear_descriptor(void) -{ - memset(&s_device_descriptor, 0, sizeof(s_device_descriptor)); - memset(&s_str_descriptor, 0, sizeof(s_str_descriptor)); -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c deleted file mode 100644 index bf0681db5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_tasks.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_log.h" -#include "esp_check.h" -#include "tinyusb.h" -#include "tusb_tasks.h" - -const static char *TAG = "tusb_tsk"; -static TaskHandle_t s_tusb_tskh; - -/** - * @brief This top level thread processes all usb events and invokes callbacks - */ -static void tusb_device_task(void *arg) -{ - ESP_LOGD(TAG, "tinyusb task started"); - while (1) { // RTOS forever loop - tud_task(); - } -} - -esp_err_t tusb_run_task(void) -{ - // This function is not garanteed to be thread safe, if invoked multiple times without calling `tusb_stop_task`, will cause memory leak - // doing a sanity check anyway - ESP_RETURN_ON_FALSE(!s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task already started"); - // Create a task for tinyusb device stack: - xTaskCreate(tusb_device_task, "TinyUSB", CONFIG_TINYUSB_TASK_STACK_SIZE, NULL, CONFIG_TINYUSB_TASK_PRIORITY, &s_tusb_tskh); - ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_FAIL, TAG, "create TinyUSB main task failed"); - return ESP_OK; -} - -esp_err_t tusb_stop_task(void) -{ - ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task not started yet"); - vTaskDelete(s_tusb_tskh); - s_tusb_tskh = NULL; - return ESP_OK; -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/cdc.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/cdc.c similarity index 100% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/cdc.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/cdc.c diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/descriptors_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/descriptors_control.c new file mode 100644 index 000000000..67b6cb3e2 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/descriptors_control.c @@ -0,0 +1,294 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_log.h" +#include "esp_check.h" +#include "esp_err.h" +#include "descriptors_control.h" +#include "usb_descriptors.h" + +#define MAX_DESC_BUF_SIZE 32 // Max length of string descriptor (can be extended, USB supports lengths up to 255 bytes) + +static const char *TAG = "tusb_desc"; + +// ============================================================================= +// STRUCTS +// ============================================================================= + +/** + * @brief Descriptor pointers for tinyusb descriptor requests callbacks + * + */ +typedef struct { + const tusb_desc_device_t *dev; /*!< Pointer to device descriptor */ + union { + const uint8_t *cfg; /*!< Pointer to FullSpeed configuration descriptor when device one-speed only */ + const uint8_t *fs_cfg; /*!< Pointer to FullSpeed configuration descriptor when device support HighSpeed */ + }; +#if (TUD_OPT_HIGH_SPEED) + const uint8_t *hs_cfg; /*!< Pointer to HighSpeed configuration descriptor */ + const tusb_desc_device_qualifier_t *qualifier; /*!< Pointer to Qualifier descriptor */ + uint8_t *other_speed; /*!< Pointer for other speed configuration descriptor */ +#endif // TUD_OPT_HIGH_SPEED + const char *str[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; /*!< Pointer to array of UTF-8 strings */ + int str_count; /*!< Number of descriptors in str */ +} tinyusb_descriptor_config_t; + +static tinyusb_descriptor_config_t s_desc_cfg; + +// ============================================================================= +// CALLBACKS +// ============================================================================= + +/** + * @brief Invoked when received GET DEVICE DESCRIPTOR. + * Descriptor contents must exist long enough for transfer to complete + * + * @return Pointer to device descriptor + */ +uint8_t const *tud_descriptor_device_cb(void) +{ + assert(s_desc_cfg.dev); + return (uint8_t const *)s_desc_cfg.dev; +} + +/** + * @brief Invoked when received GET CONFIGURATION DESCRIPTOR. + * Descriptor contents must exist long enough for transfer to complete + * + * @param[in] index Index of required configuration + * @return Pointer to configuration descriptor + */ +uint8_t const *tud_descriptor_configuration_cb(uint8_t index) +{ + (void)index; // Unused, this driver supports only 1 configuration + assert(s_desc_cfg.cfg); + +#if (TUD_OPT_HIGH_SPEED) + // HINT: cfg and fs_cfg are union, no need to assert(fs_cfg) + assert(s_desc_cfg.hs_cfg); + // Return configuration descriptor based on Host speed + return (TUSB_SPEED_HIGH == tud_speed_get()) + ? s_desc_cfg.hs_cfg + : s_desc_cfg.fs_cfg; +#else + return s_desc_cfg.cfg; +#endif // TUD_OPT_HIGH_SPEED +} + +#if (TUD_OPT_HIGH_SPEED) +/** + * @brief Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request + * Descriptor contents must exist long enough for transfer to complete + * If not highspeed capable stall this request + */ +uint8_t const *tud_descriptor_device_qualifier_cb(void) +{ + assert(s_desc_cfg.qualifier); + return (uint8_t const *)s_desc_cfg.qualifier; +} + +/** + * @brief Invoked when received GET OTHER SPEED CONFIGURATION DESCRIPTOR request + * Descriptor contents must exist long enough for transfer to complete + * Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa + */ +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) +{ + assert(s_desc_cfg.other_speed); + + const uint8_t *other_speed = (TUSB_SPEED_HIGH == tud_speed_get()) + ? s_desc_cfg.fs_cfg + : s_desc_cfg.hs_cfg; + + memcpy(s_desc_cfg.other_speed, + other_speed, + ((tusb_desc_configuration_t *)other_speed)->wTotalLength); + + ((tusb_desc_configuration_t *)s_desc_cfg.other_speed)->bDescriptorType = TUSB_DESC_OTHER_SPEED_CONFIG; + return s_desc_cfg.other_speed; +} +#endif // TUD_OPT_HIGH_SPEED + +/** + * @brief Invoked when received GET STRING DESCRIPTOR request + * + * @param[in] index Index of required descriptor + * @param[in] langid Language of the descriptor + * @return Pointer to UTF-16 string descriptor + */ +uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; // Unused, this driver supports only one language in string descriptors + assert(s_desc_cfg.str); + uint8_t chr_count; + static uint16_t _desc_str[MAX_DESC_BUF_SIZE]; + + if (index == 0) { + memcpy(&_desc_str[1], s_desc_cfg.str[0], 2); + chr_count = 1; + } else { + if (index >= USB_STRING_DESCRIPTOR_ARRAY_SIZE) { + ESP_LOGW(TAG, "String index (%u) is out of bounds, check your string descriptor", index); + return NULL; + } + + if (s_desc_cfg.str[index] == NULL) { + ESP_LOGW(TAG, "String index (%u) points to NULL, check your string descriptor", index); + return NULL; + } + + const char *str = s_desc_cfg.str[index]; + chr_count = strnlen(str, MAX_DESC_BUF_SIZE - 1); // Buffer len - header + + // Convert ASCII string into UTF-16 + for (uint8_t i = 0; i < chr_count; i++) { + _desc_str[1 + i] = str[i]; + } + } + + // First byte is length in bytes (including header), second byte is descriptor type (TUSB_DESC_STRING) + _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * chr_count + 2); + + return _desc_str; +} + +// ============================================================================= +// Driver functions +// ============================================================================= +esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config) +{ + esp_err_t ret = ESP_FAIL; + assert(config); + const char **pstr_desc; + // Flush descriptors control struct + memset(&s_desc_cfg, 0x00, sizeof(tinyusb_descriptor_config_t)); + // Parse configuration and save descriptors's pointer + // Select Device Descriptor + if (config->device_descriptor == NULL) { + ESP_LOGW(TAG, "No Device descriptor provided, using default."); + s_desc_cfg.dev = &descriptor_dev_default; + } else { + s_desc_cfg.dev = config->device_descriptor; + } + + // Select FullSpeed configuration descriptor + if (config->configuration_descriptor == NULL) { + // Default configuration descriptor is provided only for CDC, MSC and NCM classes +#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 0 || CFG_TUD_CUSTOM_CLASS > 0 || CFG_TUD_ECM_RNDIS > 0 || CFG_TUD_DFU > 0 || CFG_TUD_DFU_RUNTIME > 0 || CFG_TUD_BTH > 0) + ESP_GOTO_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, fail, TAG, "Configuration descriptor must be provided for this device"); +#else + ESP_LOGW(TAG, "No FullSpeed configuration descriptor provided, using default."); + s_desc_cfg.cfg = descriptor_fs_cfg_default; +#endif + } else { + s_desc_cfg.cfg = config->configuration_descriptor; + } + +#if (TUD_OPT_HIGH_SPEED) + // High Speed + if (config->hs_configuration_descriptor == NULL) { + // Default configuration descriptor is provided only for CDC, MSC and NCM classes +#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 0 || CFG_TUD_CUSTOM_CLASS > 0 || CFG_TUD_ECM_RNDIS > 0 || CFG_TUD_DFU > 0 || CFG_TUD_DFU_RUNTIME > 0 || CFG_TUD_BTH > 0) + ESP_GOTO_ON_FALSE(config->hs_configuration_descriptor, ESP_ERR_INVALID_ARG, fail, TAG, "HighSpeed configuration descriptor must be provided for this device"); +#else + ESP_LOGW(TAG, "No HighSpeed configuration descriptor provided, using default."); + s_desc_cfg.hs_cfg = descriptor_hs_cfg_default; +#endif + } else { + s_desc_cfg.hs_cfg = config->hs_configuration_descriptor; + } + + // HS and FS cfg desc should be equal length + ESP_GOTO_ON_FALSE(((tusb_desc_configuration_t *)s_desc_cfg.hs_cfg)->wTotalLength == + ((tusb_desc_configuration_t *)s_desc_cfg.fs_cfg)->wTotalLength, + ESP_ERR_INVALID_ARG, fail, TAG, "HighSpeed and FullSpeed configuration descriptors must be same length"); + + // Qualifier Descriptor + if (config->qualifier_descriptor == NULL) { + ESP_GOTO_ON_FALSE((s_desc_cfg.dev == &descriptor_dev_default), ESP_ERR_INVALID_ARG, fail, TAG, "Qualifier descriptor must be present (Device Descriptor not default)."); + // Get default qualifier if device descriptor is default + ESP_LOGW(TAG, "No Qulifier descriptor provided, using default."); + s_desc_cfg.qualifier = &descriptor_qualifier_default; + } else { + s_desc_cfg.qualifier = config->qualifier_descriptor; + } + + // Other Speed buffer allocate + s_desc_cfg.other_speed = calloc(1, ((tusb_desc_configuration_t *)s_desc_cfg.hs_cfg)->wTotalLength); + ESP_GOTO_ON_FALSE(s_desc_cfg.other_speed, ESP_ERR_NO_MEM, fail, TAG, "Other speed memory allocation error"); +#endif // TUD_OPT_HIGH_SPEED + + // Select String Descriptors and count them + if (config->string_descriptor == NULL) { + ESP_LOGW(TAG, "No String descriptors provided, using default."); + pstr_desc = descriptor_str_default; + while (descriptor_str_default[++s_desc_cfg.str_count] != NULL); + } else { + pstr_desc = config->string_descriptor; + s_desc_cfg.str_count = (config->string_descriptor_count != 0) + ? config->string_descriptor_count + : 8; // '8' is for backward compatibility with esp_tinyusb v1.0.0. Do NOT remove! + } + + ESP_GOTO_ON_FALSE(s_desc_cfg.str_count <= USB_STRING_DESCRIPTOR_ARRAY_SIZE, ESP_ERR_NOT_SUPPORTED, fail, TAG, "String descriptors exceed limit"); + memcpy(s_desc_cfg.str, pstr_desc, s_desc_cfg.str_count * sizeof(pstr_desc[0])); + + ESP_LOGI(TAG, "\n" + "┌─────────────────────────────────┐\n" + "│ USB Device Descriptor Summary │\n" + "├───────────────────┬─────────────┤\n" + "│bDeviceClass │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│bDeviceSubClass │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│bDeviceProtocol │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│bMaxPacketSize0 │ %-4u │\n" + "├───────────────────┼─────────────┤\n" + "│idVendor │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│idProduct │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│bcdDevice │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│iManufacturer │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│iProduct │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│iSerialNumber │ %-#10x │\n" + "├───────────────────┼─────────────┤\n" + "│bNumConfigurations │ %-#10x │\n" + "└───────────────────┴─────────────┘", + s_desc_cfg.dev->bDeviceClass, s_desc_cfg.dev->bDeviceSubClass, + s_desc_cfg.dev->bDeviceProtocol, s_desc_cfg.dev->bMaxPacketSize0, + s_desc_cfg.dev->idVendor, s_desc_cfg.dev->idProduct, s_desc_cfg.dev->bcdDevice, + s_desc_cfg.dev->iManufacturer, s_desc_cfg.dev->iProduct, s_desc_cfg.dev->iSerialNumber, + s_desc_cfg.dev->bNumConfigurations); + + return ESP_OK; + +fail: +#if (TUD_OPT_HIGH_SPEED) + free(s_desc_cfg.other_speed); +#endif // TUD_OPT_HIGH_SPEED + return ret; +} + +void tinyusb_set_str_descriptor(const char *str, int str_idx) +{ + assert(str_idx < USB_STRING_DESCRIPTOR_ARRAY_SIZE); + s_desc_cfg.str[str_idx] = str; +} + +void tinyusb_free_descriptors(void) +{ +#if (TUD_OPT_HIGH_SPEED) + assert(s_desc_cfg.other_speed); + free(s_desc_cfg.other_speed); +#endif // TUD_OPT_HIGH_SPEED +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h deleted file mode 100644 index 35342cfe5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/ansi_escape.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_board - * \defgroup group_ansi_esc ANSI Esacpe Code - * @{ */ - -#ifndef _TUSB_ANSI_ESC_CODE_H_ -#define _TUSB_ANSI_ESC_CODE_H_ - - -#ifdef __cplusplus - extern "C" { -#endif - -#define CSI_CODE(seq) "\33[" seq -#define CSI_SGR(x) CSI_CODE(#x) "m" - -//------------- Cursor movement -------------// -/** \defgroup group_ansi_cursor Cursor Movement - * @{ */ -#define ANSI_CURSOR_UP(n) CSI_CODE(#n "A") ///< Move cursor up -#define ANSI_CURSOR_DOWN(n) CSI_CODE(#n "B") ///< Move cursor down -#define ANSI_CURSOR_FORWARD(n) CSI_CODE(#n "C") ///< Move cursor forward -#define ANSI_CURSOR_BACKWARD(n) CSI_CODE(#n "D") ///< Move cursor backward -#define ANSI_CURSOR_LINE_DOWN(n) CSI_CODE(#n "E") ///< Move cursor to the beginning of the line (n) down -#define ANSI_CURSOR_LINE_UP(n) CSI_CODE(#n "F") ///< Move cursor to the beginning of the line (n) up -#define ANSI_CURSOR_POSITION(n, m) CSI_CODE(#n ";" #m "H") ///< Move cursor to position (n, m) -/** @} */ - -//------------- Screen -------------// -/** \defgroup group_ansi_screen Screen Control - * @{ */ -#define ANSI_ERASE_SCREEN(n) CSI_CODE(#n "J") ///< Erase the screen -#define ANSI_ERASE_LINE(n) CSI_CODE(#n "K") ///< Erase the line (n) -#define ANSI_SCROLL_UP(n) CSI_CODE(#n "S") ///< Scroll the whole page up (n) lines -#define ANSI_SCROLL_DOWN(n) CSI_CODE(#n "T") ///< Scroll the whole page down (n) lines -/** @} */ - -//------------- Text Color -------------// -/** \defgroup group_ansi_text Text Color - * @{ */ -#define ANSI_TEXT_BLACK CSI_SGR(30) -#define ANSI_TEXT_RED CSI_SGR(31) -#define ANSI_TEXT_GREEN CSI_SGR(32) -#define ANSI_TEXT_YELLOW CSI_SGR(33) -#define ANSI_TEXT_BLUE CSI_SGR(34) -#define ANSI_TEXT_MAGENTA CSI_SGR(35) -#define ANSI_TEXT_CYAN CSI_SGR(36) -#define ANSI_TEXT_WHITE CSI_SGR(37) -#define ANSI_TEXT_DEFAULT CSI_SGR(39) -/** @} */ - -//------------- Background Color -------------// -/** \defgroup group_ansi_background Background Color - * @{ */ -#define ANSI_BG_BLACK CSI_SGR(40) -#define ANSI_BG_RED CSI_SGR(41) -#define ANSI_BG_GREEN CSI_SGR(42) -#define ANSI_BG_YELLOW CSI_SGR(43) -#define ANSI_BG_BLUE CSI_SGR(44) -#define ANSI_BG_MAGENTA CSI_SGR(45) -#define ANSI_BG_CYAN CSI_SGR(46) -#define ANSI_BG_WHITE CSI_SGR(47) -#define ANSI_BG_DEFAULT CSI_SGR(49) -/** @} */ - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_ANSI_ESC_CODE_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c deleted file mode 100644 index e208624ba..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018, hathach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#include "board.h" - -#if 0 -#define LED_PHASE_MAX 8 - -static struct -{ - uint32_t phase[LED_PHASE_MAX]; - uint8_t phase_count; - - bool led_state; - uint8_t current_phase; - uint32_t current_ms; -}led_pattern; - -void board_led_pattern(uint32_t const phase_ms[], uint8_t count) -{ - memcpy(led_pattern.phase, phase_ms, 4*count); - led_pattern.phase_count = count; - - // reset with 1st phase is on - led_pattern.current_ms = board_millis(); - led_pattern.current_phase = 0; - led_pattern.led_state = true; - board_led_on(); -} - -void board_led_task(void) -{ - if ( led_pattern.phase_count == 0 ) return; - - uint32_t const duration = led_pattern.phase[led_pattern.current_phase]; - - // return if not enough time - if (board_millis() - led_pattern.current_ms < duration) return; - - led_pattern.led_state = !led_pattern.led_state; - board_led_write(led_pattern.led_state); - - led_pattern.current_ms += duration; - led_pattern.current_phase++; - - if (led_pattern.current_phase == led_pattern.phase_count) - { - led_pattern.current_phase = 0; - led_pattern.led_state = true; - board_led_on(); - } -} -#endif - -//--------------------------------------------------------------------+ -// newlib read()/write() retarget -//--------------------------------------------------------------------+ - -#if defined(__MSP430__) || defined(__RX__) - #define sys_write write - #define sys_read read -#else - #define sys_write _write - #define sys_read _read -#endif - -#if defined(LOGGER_RTT) -// Logging with RTT - -// If using SES IDE, use the Syscalls/SEGGER_RTT_Syscalls_SES.c instead -#if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM) -#include "SEGGER_RTT.h" - -TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) -{ - (void) fhdl; - SEGGER_RTT_Write(0, (const char*) buf, (int) count); - return count; -} - -TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) -{ - (void) fhdl; - return SEGGER_RTT_Read(0, buf, count); -} -#endif - -#elif defined(LOGGER_SWO) -// Logging with SWO for ARM Cortex - -#include "board_mcu.h" - -TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) -{ - (void) fhdl; - uint8_t const* buf8 = (uint8_t const*) buf; - for(size_t i=0; i -#include - -#include "ansi_escape.h" -#include "tusb.h" - -#define CFG_BOARD_UART_BAUDRATE 115200 - -//--------------------------------------------------------------------+ -// Board Porting API -// For simplicity, only one LED and one Button are used -//--------------------------------------------------------------------+ - -// Initialize on-board peripherals : led, button, uart and USB -void board_init(void); - -// Turn LED on or off -void board_led_write(bool state); - -// Control led pattern using phase duration in ms. -// For each phase, LED is toggle then repeated, board_led_task() is required to be called -//void board_led_pattern(uint32_t const phase_ms[], uint8_t count); - -// Get the current state of button -// a '1' means active (pressed), a '0' means inactive. -uint32_t board_button_read(void); - -// Get characters from UART -int board_uart_read(uint8_t* buf, int len); - -// Send characters to UART -int board_uart_write(void const * buf, int len); - -#if CFG_TUSB_OS == OPT_OS_NONE - // Get current milliseconds, must be implemented when no RTOS is used - uint32_t board_millis(void); - -#elif CFG_TUSB_OS == OPT_OS_FREERTOS - static inline uint32_t board_millis(void) - { - return ( ( ((uint64_t) xTaskGetTickCount()) * 1000) / configTICK_RATE_HZ ); - } - -#elif CFG_TUSB_OS == OPT_OS_MYNEWT - static inline uint32_t board_millis(void) - { - return os_time_ticks_to_ms32( os_time_get() ); - } - -#elif CFG_TUSB_OS == OPT_OS_PICO - #include "pico/time.h" - static inline uint32_t board_millis(void) - { - return to_ms_since_boot(get_absolute_time()); - } - -#elif CFG_TUSB_OS == OPT_OS_RTTHREAD - static inline uint32_t board_millis(void) - { - return (((uint64_t)rt_tick_get()) * 1000 / RT_TICK_PER_SECOND); - } - -#else - #error "board_millis() is not implemented for this OS" -#endif - -//--------------------------------------------------------------------+ -// Helper functions -//--------------------------------------------------------------------+ -static inline void board_led_on(void) -{ - board_led_write(true); -} - -static inline void board_led_off(void) -{ - board_led_write(false); -} - -// TODO remove -static inline void board_delay(uint32_t ms) -{ - uint32_t start_ms = board_millis(); - while (board_millis() - start_ms < ms) - { - #if TUSB_OPT_DEVICE_ENABLED - // take chance to run usb background - tud_task(); - #endif - } -} - -static inline int board_uart_getchar(void) -{ - uint8_t c; - return board_uart_read(&c, 1) ? (int) c : (-1); -} - -static inline int board_uart_putchar(uint8_t c) -{ - return board_uart_write(&c, 1); -} - -#ifdef __cplusplus - } -#endif - -#endif /* _BSP_BOARD_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h deleted file mode 100644 index b911e1e53..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/board_mcu.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef BOARD_MCU_H_ -#define BOARD_MCU_H_ - -#include "tusb_option.h" - -//--------------------------------------------------------------------+ -// Low Level MCU header include. TinyUSB stack and example should be -// platform independent and mostly doesn't need to include this file. -// However there are still certain situation where this file is needed: -// - FreeRTOSConfig.h to set up correct clock and NVIC interrupts for ARM Cortex -// - SWO logging for Cortex M with ITM_SendChar() / ITM_ReceiveChar() -//--------------------------------------------------------------------+ - -// Include order follows OPT_MCU_ number -#if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC15XX || CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ - CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC40XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX - #include "chip.h" - -#elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX || CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || \ - CFG_TUSB_MCU == OPT_MCU_K32L2BXX - #include "fsl_device_registers.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NRF5X - #include "nrf.h" - -#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ - CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21 - #include "sam.h" - -#elif CFG_TUSB_MCU == OPT_MCU_SAMG - #undef LITTLE_ENDIAN // hack to suppress "LITTLE_ENDIAN" redefined - #include "sam.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F0 - #include "stm32f0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 - #include "stm32f1xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F2 - #include "stm32f2xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - #include "stm32f3xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F4 - #include "stm32f4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F7 - #include "stm32f7xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32H7 - #include "stm32h7xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 - #include "stm32l0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 - #include "stm32l1xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_CXD56 - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_MSP430x5xx - #include "msp430.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MSP432E4 - #include "msp.h" - -#elif CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX - #include "fsl_device_registers.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC120 - #include "NUC100Series.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC121 || CFG_TUSB_MCU == OPT_MCU_NUC126 - #include "NuMicro.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC505 - #include "NUC505Series.h" - -#elif CFG_TUSB_MCU == OPT_MCU_ESP32S2 - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_DA1469X - #include "DA1469xAB.h" - -#elif CFG_TUSB_MCU == OPT_MCU_RP2040 - #include "pico.h" - -#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG - #include "em_device.h" - -#elif CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_GD32VF103 - #include "gd32vf103.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MM32F327X - #include "mm32_device.h" - -#elif CFG_TUSB_MCU == OPT_MCU_XMC4000 - #include "xmc_device.h" - -#elif CFG_TUSB_MCU == OPT_MCU_TM4C123 - #include "TM4C123.h" - -#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) - // no header needed - -#else - #error "Missing MCU header" -#endif - - -#endif /* BOARD_MCU_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt deleted file mode 100644 index c3c687a70..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -idf_component_register(SRCS esp32s2.c - INCLUDE_DIRS "." "${BOARD}" - PRIV_REQUIRES "driver" - REQUIRES freertos src led_strip) - -# Apply board specific content -include("${BOARD}/board.cmake") - -target_include_directories(${COMPONENT_TARGET} PUBLIC - "${TOP}/hw" - "${TOP}/src" -) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake deleted file mode 100644 index d33962676..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -idf_build_get_property(idf_target IDF_TARGET) - -message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") - -if(NOT ${idf_target} STREQUAL "esp32s2") - message(FATAL_ERROR "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET}(${idf_target}), try to clean the build first." ) -endif() - -set(IDF_TARGET "esp32s2" FORCE) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h deleted file mode 100644 index 43e00901d..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 33 -#define NEOPIXEL_POWER_PIN 21 -#define NEOPIXEL_POWER_STATE 1 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake deleted file mode 100644 index d33962676..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -idf_build_get_property(idf_target IDF_TARGET) - -message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") - -if(NOT ${idf_target} STREQUAL "esp32s2") - message(FATAL_ERROR "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET}(${idf_target}), try to clean the build first." ) -endif() - -set(IDF_TARGET "esp32s2" FORCE) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h deleted file mode 100644 index 16e30b685..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 1 -#define NEOPIXEL_POWER_PIN 21 -#define NEOPIXEL_POWER_STATE 0 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake deleted file mode 100644 index d5c17b9be..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -idf_build_get_property(idf_target IDF_TARGET) - -message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") - -if(NOT ${idf_target} STREQUAL "esp32s2") - message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." ) -endif() - -set(IDF_TARGET "esp32s2" FORCE) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h deleted file mode 100644 index 49a2474bc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 45 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c deleted file mode 100644 index a81181672..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/esp32s2.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "../../board.h" -#include "board.h" - -#include "esp_rom_gpio.h" -#include "hal/gpio_ll.h" -#include "hal/usb_hal.h" -#include "soc/usb_periph.h" - -#include "driver/periph_ctrl.h" -#include "driver/rmt.h" - -#ifdef NEOPIXEL_PIN -#include "led_strip.h" -static led_strip_t *strip; -#endif - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -static void configure_pins(usb_hal_context_t *usb); - -// Initialize on-board peripherals : led, button, uart and USB -void board_init(void) -{ - -#ifdef NEOPIXEL_PIN - #ifdef NEOPIXEL_POWER_PIN - gpio_reset_pin(NEOPIXEL_POWER_PIN); - gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT); - gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE); - #endif - - // WS2812 Neopixel driver with RMT peripheral - rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0); - config.clk_div = 2; // set counter clock to 40MHz - - rmt_config(&config); - rmt_driver_install(config.channel, 0, 0); - - led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel); - strip = led_strip_new_rmt_ws2812(&strip_config); - strip->clear(strip, 100); // off led -#endif - - // Button - esp_rom_gpio_pad_select_gpio(BUTTON_PIN); - gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); - gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); - - // USB Controller Hal init - periph_module_reset(PERIPH_USB_MODULE); - periph_module_enable(PERIPH_USB_MODULE); - - usb_hal_context_t hal = { - .use_external_phy = false // use built-in PHY - }; - usb_hal_init(&hal); - configure_pins(&hal); -} - -static void configure_pins(usb_hal_context_t *usb) -{ - /* usb_periph_iopins currently configures USB_OTG as USB Device. - * Introduce additional parameters in usb_hal_context_t when adding support - * for USB Host. - */ - for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { - if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { - esp_rom_gpio_pad_select_gpio(iopin->pin); - if (iopin->is_output) { - esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false); - } else { - esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false); -#if ESP_IDF_VERSION_MAJOR > 4 - if ((iopin->pin != GPIO_MATRIX_CONST_ZERO_INPUT) && (iopin->pin != GPIO_MATRIX_CONST_ONE_INPUT)) -#else - if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) -#endif - { - gpio_ll_input_enable(&GPIO, iopin->pin); - } - } - esp_rom_gpio_pad_unhold(iopin->pin); - } - } - if (!usb->use_external_phy) { - gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); - gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); - } -} - -// Turn LED on or off -void board_led_write(bool state) -{ -#ifdef NEOPIXEL_PIN - strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00); - strip->refresh(strip, 100); -#endif -} - -// Get the current state of button -// a '1' means active (pressed), a '0' means inactive. -uint32_t board_button_read(void) -{ - return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE; -} - -// Get characters from UART -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -// Send characters to UART -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; - return 0; -} - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake deleted file mode 100644 index d5c17b9be..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -idf_build_get_property(idf_target IDF_TARGET) - -message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") - -if(NOT ${idf_target} STREQUAL "esp32s2") - message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." ) -endif() - -set(IDF_TARGET "esp32s2" FORCE) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h deleted file mode 100644 index 6bb44f76d..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// Note: need to insert jumper next to WS2812 pixel -#define NEOPIXEL_PIN 45 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake deleted file mode 100644 index d5c17b9be..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -idf_build_get_property(idf_target IDF_TARGET) - -message(STATUS "Apply ${BOARD}(${idf_target}) specific options for component: ${COMPONENT_TARGET}") - -if(NOT ${idf_target} STREQUAL "esp32s2") - message(FATAL_ERROR "Incorrect target for board ${BOARD}: (${idf_target}), try to clean the build first." ) -endif() - -set(IDF_TARGET "esp32s2" FORCE) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h deleted file mode 100644 index f450b9a8b..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/boards/espressif_saola_1/board.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// Note: On the production version (v1.2) WS2812 is connected to GPIO 18, -// however earlier revision v1.1 WS2812 is connected to GPIO 17 -#define NEOPIXEL_PIN 18 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt deleted file mode 100644 index 6d0fcbc86..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(component_srcs "src/led_strip_rmt_ws2812.c") - -idf_component_register(SRCS "${component_srcs}" - INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "" - PRIV_REQUIRES "driver" - REQUIRES "") - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h deleted file mode 100644 index a9dffc325..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/include/led_strip.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2019 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 "esp_err.h" - -/** -* @brief LED Strip Type -* -*/ -typedef struct led_strip_s led_strip_t; - -/** -* @brief LED Strip Device Type -* -*/ -typedef void *led_strip_dev_t; - -/** -* @brief Declare of LED Strip Type -* -*/ -struct led_strip_s { - /** - * @brief Set RGB for a specific pixel - * - * @param strip: LED strip - * @param index: index of pixel to set - * @param red: red part of color - * @param green: green part of color - * @param blue: blue part of color - * - * @return - * - ESP_OK: Set RGB for a specific pixel successfully - * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters - * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred - */ - esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); - - /** - * @brief Refresh memory colors to LEDs - * - * @param strip: LED strip - * @param timeout_ms: timeout value for refreshing task - * - * @return - * - ESP_OK: Refresh successfully - * - ESP_ERR_TIMEOUT: Refresh failed because of timeout - * - ESP_FAIL: Refresh failed because some other error occurred - * - * @note: - * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. - */ - esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Clear LED strip (turn off all LEDs) - * - * @param strip: LED strip - * @param timeout_ms: timeout value for clearing task - * - * @return - * - ESP_OK: Clear LEDs successfully - * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout - * - ESP_FAIL: Clear LEDs failed because some other error occurred - */ - esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Free LED strip resources - * - * @param strip: LED strip - * - * @return - * - ESP_OK: Free resources successfully - * - ESP_FAIL: Free resources failed because error occurred - */ - esp_err_t (*del)(led_strip_t *strip); -}; - -/** -* @brief LED Strip Configuration Type -* -*/ -typedef struct { - uint32_t max_leds; /*!< Maximum LEDs in a single strip */ - led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */ -} led_strip_config_t; - -/** - * @brief Default configuration for LED strip - * - */ -#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \ - { \ - .max_leds = number, \ - .dev = dev_hdl, \ - } - -/** -* @brief Install a new ws2812 driver (based on RMT peripheral) -* -* @param config: LED strip configuration -* @return -* LED strip instance or NULL -*/ -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c deleted file mode 100644 index 025d3c590..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2019 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. -#include -#include -#include -#include "esp_log.h" -#include "esp_attr.h" -#include "led_strip.h" -#include "driver/rmt.h" - -static const char *TAG = "ws2812"; -#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ - do \ - { \ - if (!(a)) \ - { \ - ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret = ret_value; \ - goto goto_tag; \ - } \ - } while (0) - -#define WS2812_T0H_NS (350) -#define WS2812_T0L_NS (1000) -#define WS2812_T1H_NS (1000) -#define WS2812_T1L_NS (350) -#define WS2812_RESET_US (280) - -static uint32_t ws2812_t0h_ticks = 0; -static uint32_t ws2812_t1h_ticks = 0; -static uint32_t ws2812_t0l_ticks = 0; -static uint32_t ws2812_t1l_ticks = 0; - -typedef struct { - led_strip_t parent; - rmt_channel_t rmt_channel; - uint32_t strip_len; - uint8_t buffer[0]; -} ws2812_t; - -/** - * @brief Conver RGB data to RMT format. - * - * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t) - * - * @param[in] src: source data, to converted to RMT format - * @param[in] dest: place where to store the convert result - * @param[in] src_size: size of source data - * @param[in] wanted_num: number of RMT items that want to get - * @param[out] translated_size: number of source data that got converted - * @param[out] item_num: number of RMT items which are converted from source data - */ -static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, - size_t wanted_num, size_t *translated_size, size_t *item_num) -{ - if (src == NULL || dest == NULL) { - *translated_size = 0; - *item_num = 0; - return; - } - const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0 - const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1 - size_t size = 0; - size_t num = 0; - uint8_t *psrc = (uint8_t *)src; - rmt_item32_t *pdest = dest; - while (size < src_size && num < wanted_num) { - for (int i = 0; i < 8; i++) { - // MSB first - if (*psrc & (1 << (7 - i))) { - pdest->val = bit1.val; - } else { - pdest->val = bit0.val; - } - num++; - pdest++; - } - size++; - psrc++; - } - *translated_size = size; - *item_num = num; -} - -static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG); - uint32_t start = index * 3; - // In thr order of GRB - ws2812->buffer[start + 0] = green & 0xFF; - ws2812->buffer[start + 1] = red & 0xFF; - ws2812->buffer[start + 2] = blue & 0xFF; - return ESP_OK; -err: - return ret; -} - -static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK, - "transmit RMT samples failed", err, ESP_FAIL); - return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms)); -err: - return ret; -} - -static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - // Write zero to turn off all leds - memset(ws2812->buffer, 0, ws2812->strip_len * 3); - return ws2812_refresh(strip, timeout_ms); -} - -static esp_err_t ws2812_del(led_strip_t *strip) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - free(ws2812); - return ESP_OK; -} - -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) -{ - led_strip_t *ret = NULL; - STRIP_CHECK(config, "configuration can't be null", err, NULL); - - // 24 bits per led - uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3; - ws2812_t *ws2812 = calloc(1, ws2812_size); - STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL); - - uint32_t counter_clk_hz = 0; - STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK, - "get rmt counter clock failed", err, NULL); - // ns -> ticks - float ratio = (float)counter_clk_hz / 1e9; - ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); - ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); - ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); - ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); - - // set ws2812 to rmt adapter - rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter); - - ws2812->rmt_channel = (rmt_channel_t)config->dev; - ws2812->strip_len = config->max_leds; - - ws2812->parent.set_pixel = ws2812_set_pixel; - ws2812->parent.refresh = ws2812_refresh; - ws2812->parent.clear = ws2812_clear; - ws2812->parent.del = ws2812_del; - - return &ws2812->parent; -err: - return ret; -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake deleted file mode 100644 index f3d41d041..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.cmake +++ /dev/null @@ -1,7 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -# Add example src and bsp directories -set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components") -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set(SUPPORTED_TARGETS esp32s2) -set(FAMILY_MCUS ESP32S2) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk deleted file mode 100644 index 4b9000a6a..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s2/family.mk +++ /dev/null @@ -1,23 +0,0 @@ -#DEPS_SUBMODULES += - -.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu - -all: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) -DIDF_TARGET=esp32s2 build - -build: all - -fullclean: - if test -f sdkconfig; then $(RM) -f sdkconfig ; fi - if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi - -clean flash bootloader-flash app-flash erase monitor dfu-flash dfu size size-components size-files: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ - -uf2: $(BUILD)/$(PROJECT).uf2 - -UF2_FAMILY_ID = 0xbfdd4eee -$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin - @echo CREATE $@ - $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^ - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt deleted file mode 100644 index e1b921ae9..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -idf_component_register(SRCS esp32s3.c - INCLUDE_DIRS "." "${BOARD}" - PRIV_REQUIRES "driver" - REQUIRES freertos src led_strip) - -# Apply board specific content -include("${BOARD}/board.cmake") - -idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) -target_include_directories(${COMPONENT_TARGET} PUBLIC - "${FREERTOS_ORIG_INCLUDE_PATH}" - "${TOP}/hw" - "${TOP}/src" -) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c deleted file mode 100644 index a81181672..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/esp32s3.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "../../board.h" -#include "board.h" - -#include "esp_rom_gpio.h" -#include "hal/gpio_ll.h" -#include "hal/usb_hal.h" -#include "soc/usb_periph.h" - -#include "driver/periph_ctrl.h" -#include "driver/rmt.h" - -#ifdef NEOPIXEL_PIN -#include "led_strip.h" -static led_strip_t *strip; -#endif - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -static void configure_pins(usb_hal_context_t *usb); - -// Initialize on-board peripherals : led, button, uart and USB -void board_init(void) -{ - -#ifdef NEOPIXEL_PIN - #ifdef NEOPIXEL_POWER_PIN - gpio_reset_pin(NEOPIXEL_POWER_PIN); - gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT); - gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE); - #endif - - // WS2812 Neopixel driver with RMT peripheral - rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0); - config.clk_div = 2; // set counter clock to 40MHz - - rmt_config(&config); - rmt_driver_install(config.channel, 0, 0); - - led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel); - strip = led_strip_new_rmt_ws2812(&strip_config); - strip->clear(strip, 100); // off led -#endif - - // Button - esp_rom_gpio_pad_select_gpio(BUTTON_PIN); - gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); - gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); - - // USB Controller Hal init - periph_module_reset(PERIPH_USB_MODULE); - periph_module_enable(PERIPH_USB_MODULE); - - usb_hal_context_t hal = { - .use_external_phy = false // use built-in PHY - }; - usb_hal_init(&hal); - configure_pins(&hal); -} - -static void configure_pins(usb_hal_context_t *usb) -{ - /* usb_periph_iopins currently configures USB_OTG as USB Device. - * Introduce additional parameters in usb_hal_context_t when adding support - * for USB Host. - */ - for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { - if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { - esp_rom_gpio_pad_select_gpio(iopin->pin); - if (iopin->is_output) { - esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false); - } else { - esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false); -#if ESP_IDF_VERSION_MAJOR > 4 - if ((iopin->pin != GPIO_MATRIX_CONST_ZERO_INPUT) && (iopin->pin != GPIO_MATRIX_CONST_ONE_INPUT)) -#else - if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) -#endif - { - gpio_ll_input_enable(&GPIO, iopin->pin); - } - } - esp_rom_gpio_pad_unhold(iopin->pin); - } - } - if (!usb->use_external_phy) { - gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); - gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); - } -} - -// Turn LED on or off -void board_led_write(bool state) -{ -#ifdef NEOPIXEL_PIN - strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00); - strip->refresh(strip, 100); -#endif -} - -// Get the current state of button -// a '1' means active (pressed), a '0' means inactive. -uint32_t board_button_read(void) -{ - return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE; -} - -// Get characters from UART -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -// Send characters to UART -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; - return 0; -} - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake deleted file mode 100644 index 8996ff9dc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h deleted file mode 100644 index fff24ba44..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_addax_1/board.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// Note: On the production version (v1.1) WS2812 is connected to GPIO 47 -#define NEOPIXEL_PIN 47 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake deleted file mode 100644 index 8996ff9dc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h deleted file mode 100644 index c7940c56e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitc/board.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 48 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake deleted file mode 100644 index 8996ff9dc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.cmake +++ /dev/null @@ -1,7 +0,0 @@ -# Apply board specific content here -target_include_directories(${COMPONENT_LIB} PRIVATE .) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h deleted file mode 100644 index c7940c56e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/boards/espressif_s3_devkitm/board.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 48 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt deleted file mode 100644 index 6d0fcbc86..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(component_srcs "src/led_strip_rmt_ws2812.c") - -idf_component_register(SRCS "${component_srcs}" - INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "" - PRIV_REQUIRES "driver" - REQUIRES "") - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h deleted file mode 100644 index a9dffc325..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/include/led_strip.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2019 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 "esp_err.h" - -/** -* @brief LED Strip Type -* -*/ -typedef struct led_strip_s led_strip_t; - -/** -* @brief LED Strip Device Type -* -*/ -typedef void *led_strip_dev_t; - -/** -* @brief Declare of LED Strip Type -* -*/ -struct led_strip_s { - /** - * @brief Set RGB for a specific pixel - * - * @param strip: LED strip - * @param index: index of pixel to set - * @param red: red part of color - * @param green: green part of color - * @param blue: blue part of color - * - * @return - * - ESP_OK: Set RGB for a specific pixel successfully - * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters - * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred - */ - esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); - - /** - * @brief Refresh memory colors to LEDs - * - * @param strip: LED strip - * @param timeout_ms: timeout value for refreshing task - * - * @return - * - ESP_OK: Refresh successfully - * - ESP_ERR_TIMEOUT: Refresh failed because of timeout - * - ESP_FAIL: Refresh failed because some other error occurred - * - * @note: - * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. - */ - esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Clear LED strip (turn off all LEDs) - * - * @param strip: LED strip - * @param timeout_ms: timeout value for clearing task - * - * @return - * - ESP_OK: Clear LEDs successfully - * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout - * - ESP_FAIL: Clear LEDs failed because some other error occurred - */ - esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Free LED strip resources - * - * @param strip: LED strip - * - * @return - * - ESP_OK: Free resources successfully - * - ESP_FAIL: Free resources failed because error occurred - */ - esp_err_t (*del)(led_strip_t *strip); -}; - -/** -* @brief LED Strip Configuration Type -* -*/ -typedef struct { - uint32_t max_leds; /*!< Maximum LEDs in a single strip */ - led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */ -} led_strip_config_t; - -/** - * @brief Default configuration for LED strip - * - */ -#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \ - { \ - .max_leds = number, \ - .dev = dev_hdl, \ - } - -/** -* @brief Install a new ws2812 driver (based on RMT peripheral) -* -* @param config: LED strip configuration -* @return -* LED strip instance or NULL -*/ -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); - -#ifdef __cplusplus -} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c deleted file mode 100644 index 025d3c590..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2019 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. -#include -#include -#include -#include "esp_log.h" -#include "esp_attr.h" -#include "led_strip.h" -#include "driver/rmt.h" - -static const char *TAG = "ws2812"; -#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ - do \ - { \ - if (!(a)) \ - { \ - ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret = ret_value; \ - goto goto_tag; \ - } \ - } while (0) - -#define WS2812_T0H_NS (350) -#define WS2812_T0L_NS (1000) -#define WS2812_T1H_NS (1000) -#define WS2812_T1L_NS (350) -#define WS2812_RESET_US (280) - -static uint32_t ws2812_t0h_ticks = 0; -static uint32_t ws2812_t1h_ticks = 0; -static uint32_t ws2812_t0l_ticks = 0; -static uint32_t ws2812_t1l_ticks = 0; - -typedef struct { - led_strip_t parent; - rmt_channel_t rmt_channel; - uint32_t strip_len; - uint8_t buffer[0]; -} ws2812_t; - -/** - * @brief Conver RGB data to RMT format. - * - * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t) - * - * @param[in] src: source data, to converted to RMT format - * @param[in] dest: place where to store the convert result - * @param[in] src_size: size of source data - * @param[in] wanted_num: number of RMT items that want to get - * @param[out] translated_size: number of source data that got converted - * @param[out] item_num: number of RMT items which are converted from source data - */ -static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, - size_t wanted_num, size_t *translated_size, size_t *item_num) -{ - if (src == NULL || dest == NULL) { - *translated_size = 0; - *item_num = 0; - return; - } - const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0 - const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1 - size_t size = 0; - size_t num = 0; - uint8_t *psrc = (uint8_t *)src; - rmt_item32_t *pdest = dest; - while (size < src_size && num < wanted_num) { - for (int i = 0; i < 8; i++) { - // MSB first - if (*psrc & (1 << (7 - i))) { - pdest->val = bit1.val; - } else { - pdest->val = bit0.val; - } - num++; - pdest++; - } - size++; - psrc++; - } - *translated_size = size; - *item_num = num; -} - -static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG); - uint32_t start = index * 3; - // In thr order of GRB - ws2812->buffer[start + 0] = green & 0xFF; - ws2812->buffer[start + 1] = red & 0xFF; - ws2812->buffer[start + 2] = blue & 0xFF; - return ESP_OK; -err: - return ret; -} - -static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK, - "transmit RMT samples failed", err, ESP_FAIL); - return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms)); -err: - return ret; -} - -static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - // Write zero to turn off all leds - memset(ws2812->buffer, 0, ws2812->strip_len * 3); - return ws2812_refresh(strip, timeout_ms); -} - -static esp_err_t ws2812_del(led_strip_t *strip) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - free(ws2812); - return ESP_OK; -} - -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) -{ - led_strip_t *ret = NULL; - STRIP_CHECK(config, "configuration can't be null", err, NULL); - - // 24 bits per led - uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3; - ws2812_t *ws2812 = calloc(1, ws2812_size); - STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL); - - uint32_t counter_clk_hz = 0; - STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK, - "get rmt counter clock failed", err, NULL); - // ns -> ticks - float ratio = (float)counter_clk_hz / 1e9; - ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); - ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); - ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); - ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); - - // set ws2812 to rmt adapter - rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter); - - ws2812->rmt_channel = (rmt_channel_t)config->dev; - ws2812->strip_len = config->max_leds; - - ws2812->parent.set_pixel = ws2812_set_pixel; - ws2812->parent.refresh = ws2812_refresh; - ws2812->parent.clear = ws2812_clear; - ws2812->parent.del = ws2812_del; - - return &ws2812->parent; -err: - return ret; -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake deleted file mode 100644 index 511dd58bb..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.cmake +++ /dev/null @@ -1,7 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -# Add example src and bsp directories -set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s3/boards" "${TOP}/hw/bsp/esp32s3/components") -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set(SUPPORTED_TARGETS esp32s3) -set(FAMILY_MCUS ESP32S3) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk deleted file mode 100644 index cf153ffc2..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/esp32s3/family.mk +++ /dev/null @@ -1,26 +0,0 @@ -#DEPS_SUBMODULES += - -.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu - -all: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) -DIDF_TARGET=esp32s3 build - -build: all - -clean: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) clean - -fullclean: - if test -f sdkconfig; then $(RM) -f sdkconfig ; fi - if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi - -flash bootloader-flash app-flash erase monitor dfu-flash dfu: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ - -uf2: $(BUILD)/$(PROJECT).uf2 - -UF2_FAMILY_ID = 0xc47e5767 -$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin - @echo CREATE $@ - $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^ - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake b/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake deleted file mode 100644 index a8cc1f363..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/hw/bsp/family_support.cmake +++ /dev/null @@ -1,100 +0,0 @@ -if (NOT TARGET _family_support_marker) - add_library(_family_support_marker INTERFACE) - - if (NOT FAMILY) - message(FATAL_ERROR "You must set a FAMILY variable for the build (e.g. rp2040, eps32s2, esp32s3). You can do this via -DFAMILY=xxx on the camke command line") - endif() - - if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake) - message(FATAL_ERROR "Family '${FAMILY}' is not known/supported") - endif() - - function(family_filter RESULT DIR) - get_filename_component(DIR ${DIR} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) - - if (EXISTS "${DIR}/only.txt") - file(READ "${DIR}/only.txt" ONLYS) - # Replace newlines with semicolon so that it is treated as a list by CMake - string(REPLACE "\n" ";" ONLYS_LINES ${ONLYS}) - # For each mcu - foreach(MCU IN LISTS FAMILY_MCUS) - # For each line in only.txt - foreach(_line ${ONLYS_LINES}) - # If mcu:xxx exists for this mcu then include - if (${_line} STREQUAL "mcu:${MCU}") - set(${RESULT} 1 PARENT_SCOPE) - return() - endif() - endforeach() - endforeach() - - # Didn't find it in only file so don't build - set(${RESULT} 0 PARENT_SCOPE) - - elseif (EXISTS "${DIR}/skip.txt") - file(READ "${DIR}/skip.txt" SKIPS) - # Replace newlines with semicolon so that it is treated as a list by CMake - string(REPLACE "\n" ";" SKIPS_LINES ${SKIPS}) - # For each mcu - foreach(MCU IN LISTS FAMILY_MCUS) - # For each line in only.txt - foreach(_line ${SKIPS_LINES}) - # If mcu:xxx exists for this mcu then skip - if (${_line} STREQUAL "mcu:${MCU}") - set(${RESULT} 0 PARENT_SCOPE) - return() - endif() - endforeach() - endforeach() - - # Didn't find in skip file so build - set(${RESULT} 1 PARENT_SCOPE) - - else() - - # Didn't find skip or only file so build - set(${RESULT} 1 PARENT_SCOPE) - - endif() - - endfunction() - - function(family_add_subdirectory DIR) - family_filter(SHOULD_ADD "${DIR}") - if (SHOULD_ADD) - add_subdirectory(${DIR}) - endif() - endfunction() - - function(family_get_project_name OUTPUT_NAME DIR) - get_filename_component(SHORT_NAME ${DIR} NAME) - set(${OUTPUT_NAME} ${TINYUSB_FAMILY_PROJECT_NAME_PREFIX}${SHORT_NAME} PARENT_SCOPE) - endfunction() - - function(family_initialize_project PROJECT DIR) - family_filter(ALLOWED "${DIR}") - if (NOT ALLOWED) - get_filename_component(SHORT_NAME ${DIR} NAME) - message(FATAL_ERROR "${SHORT_NAME} is not supported on FAMILY=${FAMILY}") - endif() - endfunction() - - # configure an executable target to link to tinyusb in device mode, and add the board implementation - function(family_configure_device_example TARGET) - # default implentation is empty, the function should be redefined in the FAMILY/family.cmake - endfunction() - - # configure an executable target to link to tinyusb in host mode, and add the board implementation - function(family_configure_host_example TARGET) - # default implentation is empty, the function should be redefined in the FAMILY/family.cmake - endfunction() - - include(${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake) - - if (NOT FAMILY_MCUS) - set(FAMILY_MCUS ${FAMILY}) - endif() - - # save it in case of re-inclusion - set(FAMILY_MCUS ${FAMILY_MCUS} CACHE INTERNAL "") -endif() \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml index f9bc726e5..45421d9d1 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/idf_component.yml @@ -1,8 +1,14 @@ dependencies: - idf: '>=5.0' -description: TinyUSB ported to Espressif's SoCs -targets: -- esp32s2 -- esp32s3 -url: https://github.com/espressif/tinyusb -version: 0.0.1 + idf: + version: '>=5.0' + tinyusb: + public: true + version: '>=0.14.2' +description: Espressif's additions to TinyUSB +documentation: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/usb_device.html +repository: git://github.com/espressif/esp-usb.git +repository_info: + commit_sha: 4b6a798d0bed444fff48147c8dcdbbd038e92892 + path: device/esp_tinyusb +url: https://github.com/espressif/esp-usb/tree/master/device/esp_tinyusb +version: 1.4.4 diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb.h similarity index 65% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb.h index 255cf3bed..484c86e6a 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tinyusb.h +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,11 +9,8 @@ #include #include "esp_err.h" #include "tusb.h" -#include "tusb_option.h" -#include "tusb_config.h" #include "tinyusb_types.h" - #ifdef __cplusplus extern "C" { #endif @@ -31,9 +28,23 @@ typedef struct { const tusb_desc_device_t *device_descriptor; /*!< Pointer to a device descriptor. If set to NULL, the TinyUSB device will use a default device descriptor whose values are set in Kconfig */ const tusb_desc_device_t *descriptor __attribute__((deprecated)); /*!< Alias to `device_descriptor` for backward compatibility */ }; - const char **string_descriptor; /*!< Pointer to an array of string descriptors */ + const char **string_descriptor; /*!< Pointer to array of string descriptors. If set to NULL, TinyUSB device will use a default string descriptors whose values are set in Kconfig */ + int string_descriptor_count; /*!< Number of descriptors in above array */ bool external_phy; /*!< Should USB use an external PHY */ - const uint8_t *configuration_descriptor; /*!< Pointer to a configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + union { + struct { + const uint8_t *configuration_descriptor; /*!< Pointer to a configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + }; +#if (TUD_OPT_HIGH_SPEED) + struct { + const uint8_t *fs_configuration_descriptor; /*!< Pointer to a FullSpeed configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + }; + }; + const uint8_t *hs_configuration_descriptor; /*!< Pointer to a HighSpeed configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + const tusb_desc_device_qualifier_t *qualifier_descriptor; /*!< Pointer to a qualifier descriptor */ +#else + }; +#endif // TUD_OPT_HIGH_SPEED bool self_powered; /*!< This is a self-powered USB device. USB VBUS must be monitored. */ int vbus_monitor_io; /*!< GPIO for VBUS monitoring. Ignored if not self_powered. */ } tinyusb_config_t; @@ -57,7 +68,7 @@ typedef struct { */ esp_err_t tinyusb_driver_install(const tinyusb_config_t *config); -// TODO esp_err_t tinyusb_driver_uninstall(void); (IDF-1474) +esp_err_t tinyusb_driver_uninstall(void); #ifdef __cplusplus } diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_net.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_net.h new file mode 100644 index 000000000..19e53c4da --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_net.h @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "tinyusb_types.h" +#include "esp_err.h" +#include "sdkconfig.h" + +#if (CONFIG_TINYUSB_NET_MODE_NONE != 1) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief On receive callback type + */ +typedef esp_err_t (*tusb_net_rx_cb_t)(void *buffer, uint16_t len, void *ctx); + +/** + * @brief Free Tx buffer callback type + */ +typedef void (*tusb_net_free_tx_cb_t)(void *buffer, void *ctx); + +/** + * @brief On init callback type + */ +typedef void (*tusb_net_init_cb_t)(void *ctx); + +/** + * @brief ESP TinyUSB NCM driver configuration structure + */ +typedef struct { + uint8_t mac_addr[6]; /*!< MAC address. Must be 6 bytes long. */ + tusb_net_rx_cb_t on_recv_callback; /*!< TinyUSB receive data callbeck */ + tusb_net_free_tx_cb_t free_tx_buffer; /*!< User function for freeing the Tx buffer. + * - could be NULL, if user app is responsible for freeing the buffer + * - must be used in asynchronous send mode + * - is only called if the used tinyusb_net_send...() function returns ESP_OK + * - in sync mode means that the packet was accepted by TinyUSB + * - in async mode means that the packet was queued to be processed in TinyUSB task + */ + tusb_net_init_cb_t on_init_callback; /*!< TinyUSB init network callback */ + void *user_context; /*!< User context to be passed to any of the callback */ +} tinyusb_net_config_t; + +/** + * @brief Initialize TinyUSB NET driver + * + * @param[in] usb_dev USB device to use + * @param[in] cfg Configuration of the driver + * @return esp_err_t + */ +esp_err_t tinyusb_net_init(tinyusb_usbdev_t usb_dev, const tinyusb_net_config_t *cfg); + +/** + * @brief TinyUSB NET driver send data synchronously + * + * @note It is possible to use sync and async send interchangeably. + * This function needs some synchronization primitives, so using sync mode (even once) uses more heap + * + * @param[in] buffer USB send data + * @param[in] len Send data len + * @param[in] buff_free_arg Pointer to be passed to the free_tx_buffer() callback + * @param[in] timeout Send data len + * @return ESP_OK on success == packet has been consumed by tusb and would be eventually freed + * by free_tx_buffer() callback (if non null) + * ESP_ERR_TIMEOUT on timeout + * ESP_ERR_INVALID_STATE if tusb not initialized, ESP_ERR_NO_MEM on alloc failure + */ +esp_err_t tinyusb_net_send_sync(void *buffer, uint16_t len, void *buff_free_arg, TickType_t timeout); + +/** + * @brief TinyUSB NET driver send data asynchronously + * + * @note If using asynchronous sends, you must free the buffer using free_tx_buffer() callback. + * @note It is possible to use sync and async send interchangeably. + * @note Async flavor of the send is useful when the USB stack runs faster than the caller, + * since we have no control over the transmitted packets, if they get accepted or discarded. + * + * @param[in] buffer USB send data + * @param[in] len Send data len + * @param[in] buff_free_arg Pointer to be passed to the free_tx_buffer() callback + * @return ESP_OK on success == packet has been consumed by tusb and will be freed + * by free_tx_buffer() callback (if non null) + * ESP_ERR_INVALID_STATE if tusb not initialized + */ +esp_err_t tinyusb_net_send_async(void *buffer, uint16_t len, void *buff_free_arg); + +#endif // (CONFIG_TINYUSB_NET_MODE_NONE != 1) + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_types.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_types.h new file mode 100644 index 000000000..106aaaf15 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tinyusb_types.h @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define USB_ESPRESSIF_VID 0x303A + +typedef enum { + TINYUSB_USBDEV_0, +} tinyusb_usbdev_t; + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_cdc_acm.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_cdc_acm.h similarity index 68% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_cdc_acm.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_cdc_acm.h index 266ca86c8..8f64ba457 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_cdc_acm.h +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_cdc_acm.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,11 +11,16 @@ extern "C" { #endif #include -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "freertos/timers.h" -#include "tusb.h" -#include "tinyusb.h" +#include "sdkconfig.h" +#include "esp_err.h" + +#include "tinyusb_types.h" +#include "class/cdc/cdc.h" + +#if (CONFIG_TINYUSB_CDC_ENABLED != 1) +#error "TinyUSB CDC driver must be enabled in menuconfig" +#endif + /** * @brief CDC ports available to setup @@ -88,7 +93,7 @@ typedef void(*tusb_cdcacm_callback_t)(int itf, cdcacm_event_t *event); typedef struct { tinyusb_usbdev_t usb_dev; /*!< Usb device to set up */ tinyusb_cdcacm_itf_t cdc_port; /*!< CDC port */ - size_t rx_unread_buf_sz; /*!< Amount of data that can be passed to the ACM at once */ + size_t rx_unread_buf_sz __attribute__((deprecated("This parameter is not used any more. Configure RX buffer in menuconfig."))); tusb_cdcacm_callback_t callback_rx; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ tusb_cdcacm_callback_t callback_rx_wanted_char; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ tusb_cdcacm_callback_t callback_line_state_changed; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ @@ -102,89 +107,95 @@ typedef struct { * @brief Initialize CDC ACM. Initialization will be finished with * the `tud_cdc_line_state_cb` callback * - * @param cfg - init configuration structure + * @param[in] cfg Configuration structure * @return esp_err_t */ esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg); +/** + * @brief De-initialize CDC ACM. + * + * @param[in] itf Index of CDC interface + * @return esp_err_t + */ +esp_err_t tusb_cdc_acm_deinit(int itf); /** * @brief Register a callback invoking on CDC event. If the callback had been * already registered, it will be overwritten * - * @param itf - number of a CDC object - * @param event_type - type of registered event for a callback - * @param callback - callback function + * @param[in] itf Index of CDC interface + * @param[in] event_type Type of registered event for a callback + * @param[in] callback Callback function * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG */ esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type, tusb_cdcacm_callback_t callback); - /** - * @brief Unregister a callback invoking on CDC event. + * @brief Unregister a callback invoking on CDC event * - * @param itf - number of a CDC object - * @param event_type - type of registered event for a callback + * @param[in] itf Index of CDC interface + * @param[in] event_type Type of registered event for a callback * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG */ esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type); - /** * @brief Sent one character to a write buffer * - * @param itf - number of a CDC object - * @param ch - character to send + * @param[in] itf Index of CDC interface + * @param[in] ch Character to send * @return size_t - amount of queued bytes */ size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch); - /** - * @brief Write data to write buffer from a byte array + * @brief Write data to write buffer * - * @param itf - number of a CDC object - * @param in_buf - a source array - * @param in_size - size to write from arr_src + * @param[in] itf Index of CDC interface + * @param[in] in_buf Data + * @param[in] in_size Data size in bytes * @return size_t - amount of queued bytes */ size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size); /** - * @brief Send all data from a write buffer. Use `tinyusb_cdcacm_write_queue` to add data to the buffer. + * @brief Flush data in write buffer of CDC interface + * + * Use `tinyusb_cdcacm_write_queue` to add data to the buffer * * WARNING! TinyUSB can block output Endpoint for several RX callbacks, after will do additional flush - * after the each trasfer. That can leads to the situation when you requested a flush, but it will fail until - * ont of the next callbacks ends. - * SO USING OF THE FLUSH WITH TIMEOUTS IN CALLBACKS IS NOT RECOMENDED - YOU CAN GET A LOCK FOR THE TIMEOUT + * after the each transfer. That can leads to the situation when you requested a flush, but it will fail until + * one of the next callbacks ends. + * SO USING OF THE FLUSH WITH TIMEOUTS IN CALLBACKS IS NOT RECOMMENDED - YOU CAN GET A LOCK FOR THE TIMEOUT * - * @param itf - number of a CDC object - * @param timeout_ticks - waiting until flush will be considered as failed - * @return esp_err_t - ESP_OK if (timeout_ticks > 0) and and flush was successful, - * ESP_ERR_TIMEOUT if timeout occurred3 or flush was successful with (timeout_ticks == 0) - * ESP_FAIL if flush was unsuccessful + * @param[in] itf Index of CDC interface + * @param[in] timeout_ticks Transfer timeout. Set to zero for non-blocking mode + * @return - ESP_OK All data flushed + * - ESP_ERR_TIMEOUT Time out occurred in blocking mode + * - ESP_NOT_FINISHED The transfer is still in progress in non-blocking mode */ esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks); /** - * @brief Read a content to the array, and defines it's size to the sz_store + * @brief Receive data from CDC interface * - * @param itf - number of a CDC object - * @param out_buf - to this array will be stored the object from a CDC buffer - * @param out_buf_sz - size of buffer for results - * @param rx_data_size - to this address will be stored the object's size + * @param[in] itf Index of CDC interface + * @param[out] out_buf Data buffer + * @param[in] out_buf_sz Data buffer size in bytes + * @param[out] rx_data_size Number of bytes written to out_buf * @return esp_err_t ESP_OK, ESP_FAIL or ESP_ERR_INVALID_STATE */ esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size); - /** - * @brief Check if the ACM initialized + * @brief Check if the CDC interface is initialized * - * @param itf - number of a CDC object - * @return true or false + * @param[in] itf Index of CDC interface + * @return - true Initialized + * - false Not Initialized */ bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf); diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_config.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_config.h similarity index 65% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_config.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_config.h index da2a5f9e7..adcea7c3e 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_config.h +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_config.h @@ -1,5 +1,7 @@ /* - * The MIT License (MIT) + * SPDX-FileCopyrightText: 2019 Ha Thach (tinyusb.org), + * SPDX-FileContributor: 2020 Espressif Systems (Shanghai) CO LTD + * SPDX-License-Identifier: MIT * * Copyright (c) 2019 Ha Thach (tinyusb.org), * Additions Copyright (c) 2020, Espressif Systems (Shanghai) PTE LTD @@ -57,7 +59,37 @@ extern "C" { # define CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED 0 #endif -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED +#ifndef CONFIG_TINYUSB_NET_MODE_ECM_RNDIS +# define CONFIG_TINYUSB_NET_MODE_ECM_RNDIS 0 +#endif + +#ifndef CONFIG_TINYUSB_NET_MODE_NCM +# define CONFIG_TINYUSB_NET_MODE_NCM 0 +#endif + +#ifndef CONFIG_TINYUSB_DFU_MODE_DFU +# define CONFIG_TINYUSB_DFU_MODE_DFU 0 +#endif + +#ifndef CONFIG_TINYUSB_DFU_MODE_DFU_RUNTIME +# define CONFIG_TINYUSB_DFU_MODE_DFU_RUNTIME 0 +#endif + +#ifndef CONFIG_TINYUSB_BTH_ENABLED +# define CONFIG_TINYUSB_BTH_ENABLED 0 +# define CONFIG_TINYUSB_BTH_ISO_ALT_COUNT 0 +#endif + +#ifndef CONFIG_TINYUSB_DEBUG_LEVEL +# define CONFIG_TINYUSB_DEBUG_LEVEL 0 +#endif + +#ifdef CONFIG_TINYUSB_RHPORT_HS +# define CFG_TUSB_RHPORT1_MODE OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED +#else +# define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED +#endif + #define CFG_TUSB_OS OPT_OS_FREERTOS /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. @@ -79,6 +111,9 @@ extern "C" { #define CFG_TUD_ENDPOINT0_SIZE 64 #endif +// Debug Level +#define CFG_TUSB_DEBUG CONFIG_TINYUSB_DEBUG_LEVEL + // CDC FIFO size of TX and RX #define CFG_TUD_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE #define CFG_TUD_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE @@ -86,17 +121,34 @@ extern "C" { // MSC Buffer size of Device Mass storage #define CFG_TUD_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE +// MIDI macros #define CFG_TUD_MIDI_EP_BUFSIZE 64 #define CFG_TUD_MIDI_EPSIZE CFG_TUD_MIDI_EP_BUFSIZE #define CFG_TUD_MIDI_RX_BUFSIZE 64 #define CFG_TUD_MIDI_TX_BUFSIZE 64 +// Vendor FIFO size of TX and RX +// If not configured vendor endpoints will not be buffered +#define CFG_TUD_VENDOR_RX_BUFSIZE 64 +#define CFG_TUD_VENDOR_TX_BUFSIZE 64 + +// DFU macros +#define CFG_TUD_DFU_XFER_BUFSIZE CONFIG_TINYUSB_DFU_BUFSIZE + +// Number of BTH ISO alternatives +#define CFG_TUD_BTH_ISO_ALT_COUNT CONFIG_TINYUSB_BTH_ISO_ALT_COUNT + // Enabled device class driver #define CFG_TUD_CDC CONFIG_TINYUSB_CDC_COUNT #define CFG_TUD_MSC CONFIG_TINYUSB_MSC_ENABLED #define CFG_TUD_HID CONFIG_TINYUSB_HID_COUNT #define CFG_TUD_MIDI CONFIG_TINYUSB_MIDI_COUNT #define CFG_TUD_CUSTOM_CLASS CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED +#define CFG_TUD_ECM_RNDIS CONFIG_TINYUSB_NET_MODE_ECM_RNDIS +#define CFG_TUD_NCM CONFIG_TINYUSB_NET_MODE_NCM +#define CFG_TUD_DFU CONFIG_TINYUSB_DFU_MODE_DFU +#define CFG_TUD_DFU_RUNTIME CONFIG_TINYUSB_DFU_MODE_DFU_RUNTIME +#define CFG_TUD_BTH CONFIG_TINYUSB_BTH_ENABLED #ifdef __cplusplus } diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_console.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_console.h similarity index 100% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_console.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_console.h diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_msc_storage.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_msc_storage.h new file mode 100644 index 000000000..35e3fb3f1 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_msc_storage.h @@ -0,0 +1,188 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "esp_err.h" +#include "wear_levelling.h" +#include "esp_vfs_fat.h" +#if SOC_SDMMC_HOST_SUPPORTED +#include "driver/sdmmc_host.h" +#endif + +/** + * @brief Data provided to the input of the `callback_mount_changed` and `callback_premount_changed` callback + */ +typedef struct { + bool is_mounted; /*!< Flag if storage is mounted or not */ +} tinyusb_msc_event_mount_changed_data_t; + +/** + * @brief Types of MSC events + */ +typedef enum { + TINYUSB_MSC_EVENT_MOUNT_CHANGED, /*!< Event type AFTER mount/unmount operation is successfully finished */ + TINYUSB_MSC_EVENT_PREMOUNT_CHANGED /*!< Event type BEFORE mount/unmount operation is started */ +} tinyusb_msc_event_type_t; + +/** + * @brief Describes an event passing to the input of a callbacks + */ +typedef struct { + tinyusb_msc_event_type_t type; /*!< Event type */ + union { + tinyusb_msc_event_mount_changed_data_t mount_changed_data; /*!< Data input of the callback */ + }; +} tinyusb_msc_event_t; + +/** + * @brief MSC callback that is delivered whenever a specific event occurs. + */ +typedef void(*tusb_msc_callback_t)(tinyusb_msc_event_t *event); + +#if SOC_SDMMC_HOST_SUPPORTED +/** + * @brief Configuration structure for sdmmc initialization + * + * User configurable parameters that are used while + * initializing the sdmmc media. + */ +typedef struct { + sdmmc_card_t *card; /*!< Pointer to sdmmc card configuration structure */ + tusb_msc_callback_t callback_mount_changed; /*!< Pointer to the function callback that will be delivered AFTER mount/unmount operation is successfully finished */ + tusb_msc_callback_t callback_premount_changed; /*!< Pointer to the function callback that will be delivered BEFORE mount/unmount operation is started */ + const esp_vfs_fat_mount_config_t mount_config; /*!< FATFS mount config */ +} tinyusb_msc_sdmmc_config_t; +#endif + +/** + * @brief Configuration structure for spiflash initialization + * + * User configurable parameters that are used while + * initializing the SPI Flash media. + */ +typedef struct { + wl_handle_t wl_handle; /*!< Pointer to spiflash wera-levelling handle */ + tusb_msc_callback_t callback_mount_changed; /*!< Pointer to the function callback that will be delivered AFTER mount/unmount operation is successfully finished */ + tusb_msc_callback_t callback_premount_changed; /*!< Pointer to the function callback that will be delivered BEFORE mount/unmount operation is started */ + const esp_vfs_fat_mount_config_t mount_config; /*!< FATFS mount config */ +} tinyusb_msc_spiflash_config_t; + +/** + * @brief Register storage type spiflash with tinyusb driver + * + * @param config pointer to the spiflash configuration + * @return esp_err_t + * - ESP_OK, if success; + * - ESP_ERR_NO_MEM, if there was no memory to allocate storage components; + */ +esp_err_t tinyusb_msc_storage_init_spiflash(const tinyusb_msc_spiflash_config_t *config); + +#if SOC_SDMMC_HOST_SUPPORTED +/** + * @brief Register storage type sd-card with tinyusb driver + * + * @param config pointer to the sd card configuration + * @return esp_err_t + * - ESP_OK, if success; + * - ESP_ERR_NO_MEM, if there was no memory to allocate storage components; + */ +esp_err_t tinyusb_msc_storage_init_sdmmc(const tinyusb_msc_sdmmc_config_t *config); +#endif +/** + * @brief Deregister storage with tinyusb driver and frees the memory + * + */ +void tinyusb_msc_storage_deinit(void); + +/** + * @brief Register a callback invoking on MSC event. If the callback had been + * already registered, it will be overwritten + * + * @param event_type - type of registered event for a callback + * @param callback - callback function + * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG + */ +esp_err_t tinyusb_msc_register_callback(tinyusb_msc_event_type_t event_type, + tusb_msc_callback_t callback); + + +/** + * @brief Unregister a callback invoking on MSC event. + * + * @param event_type - type of registered event for a callback + * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG + */ +esp_err_t tinyusb_msc_unregister_callback(tinyusb_msc_event_type_t event_type); + +/** + * @brief Mount the storage partition locally on the firmware application. + * + * Get the available drive number. Register spi flash partition. + * Connect POSIX and C standard library IO function with FATFS. + * Mounts the partition. + * This API is used by the firmware application. If the storage partition is + * mounted by this API, host (PC) can't access the storage via MSC. + * When this function is called from the tinyusb callback functions, care must be taken + * so as to make sure that user callbacks must be completed within a + * specific time. Otherwise, MSC device may re-appear again on Host. + * + * @param base_path path prefix where FATFS should be registered + * @return esp_err_t + * - ESP_OK, if success; + * - ESP_ERR_NOT_FOUND if the maximum count of volumes is already mounted + * - ESP_ERR_NO_MEM if not enough memory or too many VFSes already registered; + */ +esp_err_t tinyusb_msc_storage_mount(const char *base_path); + +/** + * @brief Unmount the storage partition from the firmware application. + * + * Unmount the partition. Unregister diskio driver. + * Unregister the SPI flash partition. + * Finally, Un-register FATFS from VFS. + * After this function is called, storage device can be seen (recognized) by host (PC). + * When this function is called from the tinyusb callback functions, care must be taken + * so as to make sure that user callbacks must be completed within a specific time. + * Otherwise, MSC device may not appear on Host. + * + * @return esp_err_t + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS + */ +esp_err_t tinyusb_msc_storage_unmount(void); + +/** + * @brief Get number of sectors in storage media + * + * @return usable size, in bytes + */ +uint32_t tinyusb_msc_storage_get_sector_count(void); + +/** + * @brief Get sector size of storage media + * + * @return sector count + */ +uint32_t tinyusb_msc_storage_get_sector_size(void); + +/** + * @brief Get status if storage media is exposed over USB to Host + * + * @return bool + * - true, if the storage media is exposed to Host + * - false, if the stoarge media is mounted on application (not exposed to Host) + */ +bool tinyusb_msc_storage_in_use_by_usb_host(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_tasks.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_tasks.h similarity index 80% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_tasks.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_tasks.h index 22b6df6c2..38bd7dea7 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include/tusb_tasks.h +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/tusb_tasks.h @@ -20,7 +20,8 @@ extern "C" { * If you have more requirements for this task, you can create your own task which calls tud_task as the last step. * * @retval ESP_OK run tinyusb main task successfully - * @retval ESP_FAIL run tinyusb main task failed of internal error + * @retval ESP_FAIL run tinyusb main task failed of internal error or initialization within the task failed when TINYUSB_INIT_IN_DEFAULT_TASK=y + * @retval ESP_FAIL initialization within the task failed if CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK is enabled * @retval ESP_ERR_INVALID_STATE tinyusb main task has been created before */ esp_err_t tusb_run_task(void); @@ -28,7 +29,7 @@ esp_err_t tusb_run_task(void); /** * @brief This helper function stops and destroys the task created by `tusb_run_task()` * - * @retval ESP_OK stop and destory tinyusb main task successfully + * @retval ESP_OK stop and destroy tinyusb main task successfully * @retval ESP_ERR_INVALID_STATE tinyusb main task hasn't been created yet */ esp_err_t tusb_stop_task(void); diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include/vfs_tinyusb.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/vfs_tinyusb.h new file mode 100644 index 000000000..9c9ba910b --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include/vfs_tinyusb.h @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_err.h" +#include "esp_vfs_common.h" // For esp_line_endings_t definitions + +#ifdef __cplusplus +extern "C" { +#endif + +#define VFS_TUSB_MAX_PATH 16 +#define VFS_TUSB_PATH_DEFAULT "/dev/tusb_cdc" + +/** + * @brief Register TinyUSB CDC at VFS with path + * + * Know limitation: + * In case there are multiple CDC interfaces in the system, only one of them can be registered to VFS. + * + * @param[in] cdc_intf Interface number of TinyUSB's CDC + * @param[in] path Path where the CDC will be registered, `/dev/tusb_cdc` will be used if left NULL. + * @return esp_err_t ESP_OK or ESP_FAIL + */ +esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path); + +/** + * @brief Unregister TinyUSB CDC from VFS + * + * @param[in] path Path where the CDC will be unregistered if NULL will be used `/dev/tusb_cdc` + * @return esp_err_t ESP_OK or ESP_FAIL + */ +esp_err_t esp_vfs_tusb_cdc_unregister(char const *path); + +/** + * @brief Set the line endings to sent + * + * This specifies the conversion between newlines ('\n', LF) on stdout and line + * endings sent: + * + * - ESP_LINE_ENDINGS_CRLF: convert LF to CRLF + * - ESP_LINE_ENDINGS_CR: convert LF to CR + * - ESP_LINE_ENDINGS_LF: no modification + * + * @param[in] mode line endings to send + */ +void esp_vfs_tusb_cdc_set_tx_line_endings(esp_line_endings_t mode); + +/** + * @brief Set the line endings expected to be received + * + * This specifies the conversion between line endings received and + * newlines ('\n', LF) passed into stdin: + * + * - ESP_LINE_ENDINGS_CRLF: convert CRLF to LF + * - ESP_LINE_ENDINGS_CR: convert CR to LF + * - ESP_LINE_ENDINGS_LF: no modification + * + * @param[in] mode line endings expected + */ +void esp_vfs_tusb_cdc_set_rx_line_endings(esp_line_endings_t mode); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/cdc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/cdc.h similarity index 100% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/include_private/cdc.h rename to examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/cdc.h diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/descriptors_control.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/descriptors_control.h new file mode 100644 index 000000000..fcf352226 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/descriptors_control.h @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "tinyusb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 8 // Max 8 string descriptors for a device. LANGID, Manufacturer, Product, Serial number + 4 user defined + +/** + * @brief Parse tinyusb configuration and prepare the device configuration pointer list to configure tinyusb driver + * + * @attention All descriptors passed to this function must exist for the duration of USB device lifetime + * + * @param[in] config tinyusb stack specific configuration + * @retval ESP_ERR_INVALID_ARG Default configuration descriptor is provided only for CDC, MSC and NCM classes + * @retval ESP_ERR_NO_MEM Memory allocation error + * @retval ESP_OK Descriptors configured without error + */ +esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config); + +/** + * @brief Set specific string descriptor + * + * @attention The descriptor passed to this function must exist for the duration of USB device lifetime + * + * @param[in] str UTF-8 string + * @param[in] str_idx String descriptor index + */ +void tinyusb_set_str_descriptor(const char *str, int str_idx); + +/** + * @brief Free memory allocated during tinyusb_set_descriptors + * + */ +void tinyusb_free_descriptors(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/usb_descriptors.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/usb_descriptors.h new file mode 100644 index 000000000..be1979ab7 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/include_private/usb_descriptors.h @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "tusb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Device descriptor generated from Kconfig + * + * This descriptor is used by default. + * The user can provide their own device descriptor via tinyusb_driver_install() call + */ +extern const tusb_desc_device_t descriptor_dev_default; + +#if (TUD_OPT_HIGH_SPEED) +/** + * @brief Qualifier Device descriptor generated from Kconfig + * + * This descriptor is used by default. + * The user can provide their own descriptor via tinyusb_driver_install() call + */ +extern const tusb_desc_device_qualifier_t descriptor_qualifier_default; +#endif // TUD_OPT_HIGH_SPEED + +/** + * @brief Array of string descriptors generated from Kconfig + * + * This descriptor is used by default. + * The user can provide their own descriptor via tinyusb_driver_install() call + */ +extern const char *descriptor_str_default[]; + +/** + * @brief FullSpeed configuration descriptor generated from Kconfig + * This descriptor is used by default. + * The user can provide their own FullSpeed configuration descriptor via tinyusb_driver_install() call + */ +extern const uint8_t descriptor_fs_cfg_default[]; + +#if (TUD_OPT_HIGH_SPEED) +/** + * @brief HighSpeed Configuration descriptor generated from Kconfig + * + * This descriptor is used by default. + * The user can provide their own HighSpeed configuration descriptor via tinyusb_driver_install() call + */ +extern const uint8_t descriptor_hs_cfg_default[]; +#endif // TUD_OPT_HIGH_SPEED + +uint8_t tusb_get_mac_string_id(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt deleted file mode 100644 index e1f5f89ff..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/License.txt +++ /dev/null @@ -1,34 +0,0 @@ -Important - Read carefully: - -SEGGER RTT - Real Time Transfer for embedded targets - -All rights reserved. - -SEGGER strongly recommends to not make any changes -to or modify the source code of this software in order to stay -compatible with the RTT protocol and J-Link. - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the following -condition is met: - -o Redistributions of source code must retain the above copyright - notice, this condition and the following disclaimer. - -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 SEGGER Microcontroller 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. - - -(c) 2014 - 2016 SEGGER Microcontroller GmbH -www.segger.com diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt deleted file mode 100644 index 49ec655c4..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/README.txt +++ /dev/null @@ -1,20 +0,0 @@ -README.txt for the SEGGER RTT Implementation Pack. - -Included files: -=============== -Root Directory - - Examples - - Main_RTT_InputEchoApp.c - Sample application which echoes input on Channel 0. - - Main_RTT_MenuApp.c - Sample application to demonstrate RTT bi-directional functionality. - - Main_RTT_PrintfTest.c - Sample application to test RTT small printf implementation. - - Main_RTT_SpeedTestApp.c - Sample application for measuring RTT performance. embOS needed. - - RTT - - SEGGER_RTT.c - The RTT implementation. - - SEGGER_RTT.h - Header for RTT implementation. - - SEGGER_RTT_Conf.h - Pre-processor configuration for the RTT implementation. - - SEGGER_RTT_Printf.c - Simple implementation of printf to write formatted strings via RTT. - - Syscalls - - RTT_Syscalls_GCC.c - Low-level syscalls to retarget printf() to RTT with GCC / Newlib. - - RTT_Syscalls_IAR.c - Low-level syscalls to retarget printf() to RTT with IAR compiler. - - RTT_Syscalls_KEIL.c - Low-level syscalls to retarget printf() to RTT with KEIL/uVision compiler. - - RTT_Syscalls_SES.c - Low-level syscalls to retarget printf() to RTT with SEGGER Embedded Studio. diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c deleted file mode 100644 index 3ad2b1a12..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.c +++ /dev/null @@ -1,2005 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* 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 SEGGER Microcontroller 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. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.c -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. -Revision: $Rev: 17697 $ - -Additional information: - Type "int" is assumed to be 32-bits in size - H->T Host to target communication - T->H Target to host communication - - RTT channel 0 is always present and reserved for Terminal usage. - Name is fixed to "Terminal" - - Effective buffer size: SizeOfBuffer - 1 - - WrOff == RdOff: Buffer is empty - WrOff == (RdOff - 1): Buffer is full - WrOff > RdOff: Free space includes wrap-around - WrOff < RdOff: Used space includes wrap-around - (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): - Buffer full and wrap-around after next byte - - ----------------------------------------------------------------------- -*/ - -#include "SEGGER_RTT.h" - -#include // for memcpy - -/********************************************************************* -* -* Configuration, default values -* -********************************************************************** -*/ - -#ifndef BUFFER_SIZE_UP - #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host -#endif - -#ifndef BUFFER_SIZE_DOWN - #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) -#endif - -#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS - #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target -#endif - -#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS - #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target -#endif - -#ifndef SEGGER_RTT_BUFFER_SECTION - #if defined(SEGGER_RTT_SECTION) - #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION - #endif -#endif - -#ifndef SEGGER_RTT_ALIGNMENT - #define SEGGER_RTT_ALIGNMENT 0 -#endif - -#ifndef SEGGER_RTT_BUFFER_ALIGNMENT - #define SEGGER_RTT_BUFFER_ALIGNMENT 0 -#endif - -#ifndef SEGGER_RTT_MODE_DEFAULT - #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP -#endif - -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() -#endif - -#ifndef STRLEN - #define STRLEN(a) strlen((a)) -#endif - -#ifndef STRCPY - #define STRCPY(pDest, pSrc, NumBytes) strcpy((pDest), (pSrc)) -#endif - -#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP - #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 -#endif - -#ifndef SEGGER_RTT_MEMCPY - #ifdef MEMCPY - #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes)) - #else - #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) - #endif -#endif - -#ifndef MIN - #define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef MAX - #define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif -// -// For some environments, NULL may not be defined until certain headers are included -// -#ifndef NULL - #define NULL 0 -#endif - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ -#if (defined __ICCARM__) || (defined __ICCRX__) - #define RTT_PRAGMA(P) _Pragma(#P) -#endif - -#if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT - #if (defined __GNUC__) - #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) - #elif (defined __ICCARM__) || (defined __ICCRX__) - #define PRAGMA(A) _Pragma(#A) -#define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ - Var - #elif (defined __CC_ARM) - #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) - #else - #error "Alignment not supported for this compiler." - #endif -#else - #define SEGGER_RTT_ALIGN(Var, Alignment) Var -#endif - -#if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) - #if (defined __GNUC__) - #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var - #elif (defined __ICCARM__) || (defined __ICCRX__) -#define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ - Var - #elif (defined __CC_ARM) - #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var - #else - #error "Section placement not supported for this compiler." - #endif -#else - #define SEGGER_RTT_PUT_SECTION(Var, Section) Var -#endif - - -#if SEGGER_RTT_ALIGNMENT - #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) -#else - #define SEGGER_RTT_CB_ALIGN(Var) Var -#endif - -#if SEGGER_RTT_BUFFER_ALIGNMENT - #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) -#else - #define SEGGER_RTT_BUFFER_ALIGN(Var) Var -#endif - - -#if defined(SEGGER_RTT_SECTION) - #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) -#else - #define SEGGER_RTT_PUT_CB_SECTION(Var) Var -#endif - -#if defined(SEGGER_RTT_BUFFER_SECTION) - #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) -#else - #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var -#endif - -/********************************************************************* -* -* Static const data -* -********************************************************************** -*/ - -static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - -/********************************************************************* -* -* Static data -* -********************************************************************** -*/ -// -// RTT Control Block and allocate buffers for channel 0 -// -SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); - -SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP])); -SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN])); - -static unsigned char _ActiveTerminal; - -/********************************************************************* -* -* Static functions -* -********************************************************************** -*/ - -/********************************************************************* -* -* _DoInit() -* -* Function description -* Initializes the control block an buffers. -* May only be called via INIT() to avoid overriding settings. -* -*/ -#define INIT() do { \ - if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ - } while (0) -static void _DoInit(void) { - SEGGER_RTT_CB* p; - // - // Initialize control block - // - p = &_SEGGER_RTT; - p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; - p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; - // - // Initialize up buffer 0 - // - p->aUp[0].sName = "Terminal"; - p->aUp[0].pBuffer = _acUpBuffer; - p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); - p->aUp[0].RdOff = 0u; - p->aUp[0].WrOff = 0u; - p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Initialize down buffer 0 - // - p->aDown[0].sName = "Terminal"; - p->aDown[0].pBuffer = _acDownBuffer; - p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); - p->aDown[0].RdOff = 0u; - p->aDown[0].WrOff = 0u; - p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Finish initialization of the control block. - // Copy Id string in three steps to make sure "SEGGER RTT" is not found - // in initializer memory (usually flash) by J-Link - // - STRCPY(&p->acID[7], "RTT", 9); - STRCPY(&p->acID[0], "SEGGER", 7); - p->acID[6] = ' '; -} - -/********************************************************************* -* -* _WriteBlocking() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* The caller is responsible for managing the write chunk sizes as -* _WriteBlocking() will block until all data has been posted successfully. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* >= 0 - Number of bytes written into buffer. -*/ -static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { - unsigned NumBytesToWrite; - unsigned NumBytesWritten; - unsigned RdOff; - unsigned WrOff; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - char* pDst; -#endif - // - // Write data to buffer and handle wrap-around if necessary - // - NumBytesWritten = 0u; - WrOff = pRing->WrOff; - do { - RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime - if (RdOff > WrOff) { - NumBytesToWrite = RdOff - WrOff - 1u; - } else { - NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); - } - NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around - NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - NumBytesWritten += NumBytesToWrite; - NumBytes -= NumBytesToWrite; - WrOff += NumBytesToWrite; - while (NumBytesToWrite--) { - *pDst++ = *pBuffer++; - }; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); - NumBytesWritten += NumBytesToWrite; - pBuffer += NumBytesToWrite; - NumBytes -= NumBytesToWrite; - WrOff += NumBytesToWrite; -#endif - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0u; - } - pRing->WrOff = WrOff; - } while (NumBytes); - // - return NumBytesWritten; -} - -/********************************************************************* -* -* _WriteNoCheck() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* It is callers responsibility to make sure data actually fits in buffer. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking -*/ -static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { - unsigned NumBytesAtOnce; - unsigned WrOff; - unsigned Rem; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - char* pDst; -#endif - - WrOff = pRing->WrOff; - Rem = pRing->SizeOfBuffer - WrOff; - if (Rem > NumBytes) { - // - // All data fits before wrap around - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - WrOff += NumBytes; - while (NumBytes--) { - *pDst++ = *pData++; - }; - pRing->WrOff = WrOff; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; -#endif - } else { - // - // We reach the end of the buffer, so need to wrap around - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + WrOff; - NumBytesAtOnce = Rem; - while (NumBytesAtOnce--) { - *pDst++ = *pData++; - }; - pDst = pRing->pBuffer; - NumBytesAtOnce = NumBytes - Rem; - while (NumBytesAtOnce--) { - *pDst++ = *pData++; - }; - pRing->WrOff = NumBytes - Rem; -#else - NumBytesAtOnce = Rem; - SEGGER_RTT_MEMCPY(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); - NumBytesAtOnce = NumBytes - Rem; - SEGGER_RTT_MEMCPY(pRing->pBuffer, pData + Rem, NumBytesAtOnce); - pRing->WrOff = NumBytesAtOnce; -#endif - } -} - -/********************************************************************* -* -* _PostTerminalSwitch() -* -* Function description -* Switch terminal to the given terminal ID. It is the caller's -* responsibility to ensure the terminal ID is correct and there is -* enough space in the buffer for this to complete successfully. -* -* Parameters -* pRing Ring buffer to post to. -* TerminalId Terminal ID to switch to. -*/ -static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { - unsigned char ac[2]; - - ac[0] = 0xFFu; - ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit - _WriteBlocking(pRing, (const char*)ac, 2u); -} - -/********************************************************************* -* -* _GetAvailWriteSpace() -* -* Function description -* Returns the number of bytes that can be written to the ring -* buffer without blocking. -* -* Parameters -* pRing Ring buffer to check. -* -* Return value -* Number of bytes that are free in the buffer. -*/ -static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { - unsigned RdOff; - unsigned WrOff; - unsigned r; - // - // Avoid warnings regarding volatile access order. It's not a problem - // in this case, but dampen compiler enthusiasm. - // - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - if (RdOff <= WrOff) { - r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; - } else { - r = RdOff - WrOff - 1u; - } - return r; -} - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ -/********************************************************************* -* -* SEGGER_RTT_ReadUpBufferNoLock() -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the application. -* Do not lock against interrupts and multiple access. -* Used to do the same operation that J-Link does, to transfer -* RTT data via other channels, such as TCP/IP or UART. -* -* Parameters -* BufferIndex Index of Up-buffer to be used. -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -* -* Additional information -* This function must not be called when J-Link might also do RTT. -*/ -unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { - unsigned NumBytesRem; - unsigned NumBytesRead; - unsigned RdOff; - unsigned WrOff; - unsigned char* pBuffer; - SEGGER_RTT_BUFFER_UP* pRing; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - const char* pSrc; -#endif - // - INIT(); - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - pBuffer = (unsigned char*)pData; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - NumBytesRead = 0u; - // - // Read from current read position to wrap-around of buffer, first - // - if (RdOff > WrOff) { - NumBytesRem = pRing->SizeOfBuffer - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pSrc = pRing->pBuffer + RdOff; - NumBytesRead += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - while (NumBytesRem--) { - *pBuffer++ = *pSrc++; - }; -#else - SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; -#endif - // - // Handle wrap-around of buffer - // - if (RdOff == pRing->SizeOfBuffer) { - RdOff = 0u; - } - } - // - // Read remaining items of buffer - // - NumBytesRem = WrOff - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - if (NumBytesRem > 0u) { -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pSrc = pRing->pBuffer + RdOff; - NumBytesRead += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - while (NumBytesRem--) { - *pBuffer++ = *pSrc++; - }; -#else - SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; -#endif - } - // - // Update read offset of buffer - // - if (NumBytesRead) { - pRing->RdOff = RdOff; - } - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_ReadNoLock() -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* Do not lock against interrupts and multiple access. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { - unsigned NumBytesRem; - unsigned NumBytesRead; - unsigned RdOff; - unsigned WrOff; - unsigned char* pBuffer; - SEGGER_RTT_BUFFER_DOWN* pRing; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - const char* pSrc; -#endif - // - INIT(); - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - pBuffer = (unsigned char*)pData; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - NumBytesRead = 0u; - // - // Read from current read position to wrap-around of buffer, first - // - if (RdOff > WrOff) { - NumBytesRem = pRing->SizeOfBuffer - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pSrc = pRing->pBuffer + RdOff; - NumBytesRead += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - while (NumBytesRem--) { - *pBuffer++ = *pSrc++; - }; -#else - SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; -#endif - // - // Handle wrap-around of buffer - // - if (RdOff == pRing->SizeOfBuffer) { - RdOff = 0u; - } - } - // - // Read remaining items of buffer - // - NumBytesRem = WrOff - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - if (NumBytesRem > 0u) { -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pSrc = pRing->pBuffer + RdOff; - NumBytesRead += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - while (NumBytesRem--) { - *pBuffer++ = *pSrc++; - }; -#else - SEGGER_RTT_MEMCPY(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; -#endif - } - if (NumBytesRead) { - pRing->RdOff = RdOff; - } - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_ReadUpBuffer -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the application. -* Used to do the same operation that J-Link does, to transfer -* RTT data via other channels, such as TCP/IP or UART. -* -* Parameters -* BufferIndex Index of Up-buffer to be used. -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -* -* Additional information -* This function must not be called when J-Link might also do RTT. -* This function locks against all other RTT operations. I.e. during -* the read operation, writing is also locked. -* If only one consumer reads from the up buffer, -* call sEGGER_RTT_ReadUpBufferNoLock() instead. -*/ -unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { - unsigned NumBytesRead; - // - SEGGER_RTT_LOCK(); - // - // Call the non-locking read function - // - NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_Read -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { - unsigned NumBytesRead; - // - SEGGER_RTT_LOCK(); - // - // Call the non-locking read function - // - NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteWithOverwriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block. -* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application -* and overwrites data if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, data is overwritten. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link -* connection reads RTT data. -*/ -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - char* pDst; -#endif - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer and copy some elements into local variables. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Check if we will overwrite data and need to adjust the RdOff. - // - if (pRing->WrOff == pRing->RdOff) { - Avail = pRing->SizeOfBuffer - 1u; - } else if ( pRing->WrOff < pRing->RdOff) { - Avail = pRing->RdOff - pRing->WrOff - 1u; - } else { - Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; - } - if (NumBytes > Avail) { - pRing->RdOff += (NumBytes - Avail); - while (pRing->RdOff >= pRing->SizeOfBuffer) { - pRing->RdOff -= pRing->SizeOfBuffer; - } - } - // - // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds - // - Avail = pRing->SizeOfBuffer - pRing->WrOff; - do { - if (Avail > NumBytes) { - // - // Last round - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + pRing->WrOff; - Avail = NumBytes; - while (NumBytes--) { - *pDst++ = *pData++; - }; - pRing->WrOff += Avail; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, NumBytes); - pRing->WrOff += NumBytes; -#endif - break; - } else { - // - // Wrap-around necessary, write until wrap-around and reset WrOff - // -#if SEGGER_RTT_MEMCPY_USE_BYTELOOP - pDst = pRing->pBuffer + pRing->WrOff; - NumBytes -= Avail; - while (Avail--) { - *pDst++ = *pData++; - }; - pRing->WrOff = 0; -#else - SEGGER_RTT_MEMCPY(pRing->pBuffer + pRing->WrOff, pData, Avail); - pData += Avail; - pRing->WrOff = 0; - NumBytes -= Avail; -#endif - Avail = (pRing->SizeOfBuffer - 1); - } - } while (NumBytes); -} - -/********************************************************************* -* -* SEGGER_RTT_WriteSkipNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteSkipNoLock does not lock the application and -* skips all data, if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* MUST be > 0!!! -* This is done for performance reasons, so no initial check has do be done. -* -* Return value -* 1: Data has been copied -* 0: No space, data has not been copied -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, all data is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -#if (RTT_USE_ASM == 0) -unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - unsigned RdOff; - unsigned WrOff; - unsigned Rem; - // - // Cases: - // 1) RdOff <= WrOff => Space until wrap-around is sufficient - // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) - // 3) RdOff < WrOff => No space in buf - // 4) RdOff > WrOff => Space is sufficient - // 5) RdOff > WrOff => No space in buf - // - // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough - // - pData = (const char *)pBuffer; - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - if (RdOff <= WrOff) { // Case 1), 2) or 3) - Avail = pRing->SizeOfBuffer - WrOff - 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) - if (Avail >= NumBytes) { // Case 1)? -CopyStraight: - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - return 1; - } - Avail += RdOff; // Space incl. wrap-around - if (Avail >= NumBytes) { // Case 2? => If not, we have case 3) (does not fit) - Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer - memcpy(pRing->pBuffer + WrOff, pData, Rem); // Copy 1st chunk - NumBytes -= Rem; - // - // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used - // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element - // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks - // Therefore, check if 2nd memcpy is necessary at all - // - if (NumBytes) { - memcpy(pRing->pBuffer, pData + Rem, NumBytes); - } - pRing->WrOff = NumBytes; - return 1; - } - } else { // Potential case 4) - Avail = RdOff - WrOff - 1u; - if (Avail >= NumBytes) { // Case 4)? => If not, we have case 5) (does not fit) - goto CopyStraight; - } - } - return 0; // No space in buffer -} -#endif - -/********************************************************************* -* -* SEGGER_RTT_WriteDownBufferNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block inside a buffer. -* SEGGER_RTT_WriteDownBufferNoLock does not lock the application. -* Used to do the same operation that J-Link does, to transfer -* RTT data from other channels, such as TCP/IP or UART. -* -* Parameters -* BufferIndex Index of "Down"-buffer to be used. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Down"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -* -* Additional information -* This function must not be called when J-Link might also do RTT. -*/ -unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - unsigned Avail; - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - - pData = (const char *)pBuffer; - // - // Get "to-target" ring buffer. - // It is save to cast that to a "to-host" buffer. Up and Down buffer differ in volatility of offsets that might be modified by J-Link. - // - pRing = (SEGGER_RTT_BUFFER_UP*)&_SEGGER_RTT.aDown[BufferIndex]; - // - // How we output depends upon the mode... - // - switch (pRing->Flags) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother. - // - Avail = _GetAvailWriteSpace(pRing); - if (Avail < NumBytes) { - Status = 0u; - } else { - Status = NumBytes; - _WriteNoCheck(pRing, pData, NumBytes); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode, trim to what we can output without blocking. - // - Avail = _GetAvailWriteSpace(pRing); - Status = Avail < NumBytes ? Avail : NumBytes; - _WriteNoCheck(pRing, pData, Status); - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - Status = _WriteBlocking(pRing, pData, NumBytes); - break; - default: - Status = 0u; - break; - } - // - // Finish up. - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteNoLock does not lock the application. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - unsigned Avail; - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // How we output depends upon the mode... - // - switch (pRing->Flags) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother. - // - Avail = _GetAvailWriteSpace(pRing); - if (Avail < NumBytes) { - Status = 0u; - } else { - Status = NumBytes; - _WriteNoCheck(pRing, pData, NumBytes); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode, trim to what we can output without blocking. - // - Avail = _GetAvailWriteSpace(pRing); - Status = Avail < NumBytes ? Avail : NumBytes; - _WriteNoCheck(pRing, pData, Status); - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - Status = _WriteBlocking(pRing, pData, NumBytes); - break; - default: - Status = 0u; - break; - } - // - // Finish up. - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteDownBuffer -* -* Function description -* Stores a specified number of characters in SEGGER RTT control block in a buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Down"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -* -* Additional information -* This function must not be called when J-Link might also do RTT. -* This function locks against all other RTT operations. I.e. during -* the write operation, writing from the application is also locked. -* If only one consumer writes to the down buffer, -* call SEGGER_RTT_WriteDownBufferNoLock() instead. -*/ -unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Call the non-locking write function - // - Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_Write -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -*/ -unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Call the non-locking write function - // - Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteString -* -* Function description -* Stores string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* s Pointer to string. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -* (2) String passed to this function has to be \0 terminated -* (3) \0 termination character is *not* stored in RTT buffer -*/ -unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { - unsigned Len; - - Len = STRLEN(s); - return SEGGER_RTT_Write(BufferIndex, s, Len); -} - -/********************************************************************* -* -* SEGGER_RTT_PutCharSkipNoLock -* -* Function description -* Stores a single character/byte in SEGGER RTT buffer. -* SEGGER_RTT_PutCharSkipNoLock does not lock the application and -* skips the byte, if it does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* c Byte to be stored. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, the character is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ - -unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned WrOff; - unsigned Status; - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Get write position and handle wrap-around if necessary - // - WrOff = pRing->WrOff + 1; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0; - } - // - // Output byte if free space is available - // - if (WrOff != pRing->RdOff) { - pRing->pBuffer[pRing->WrOff] = c; - pRing->WrOff = WrOff; - Status = 1; - } else { - Status = 0; - } - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_PutCharSkip -* -* Function description -* Stores a single character/byte in SEGGER RTT buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* c Byte to be stored. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, the character is dropped. -*/ - -unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned WrOff; - unsigned Status; - // - // Prepare - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Get write position and handle wrap-around if necessary - // - WrOff = pRing->WrOff + 1; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0; - } - // - // Output byte if free space is available - // - if (WrOff != pRing->RdOff) { - pRing->pBuffer[pRing->WrOff] = c; - pRing->WrOff = WrOff; - Status = 1; - } else { - Status = 0; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - - /********************************************************************* -* -* SEGGER_RTT_PutChar -* -* Function description -* Stores a single character/byte in SEGGER RTT buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* c Byte to be stored. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) Data is stored according to buffer flags. -*/ - -unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned WrOff; - unsigned Status; - // - // Prepare - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Get write position and handle wrap-around if necessary - // - WrOff = pRing->WrOff + 1; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0; - } - // - // Wait for free space if mode is set to blocking - // - if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { - while (WrOff == pRing->RdOff) { - ; - } - } - // - // Output byte if free space is available - // - if (WrOff != pRing->RdOff) { - pRing->pBuffer[pRing->WrOff] = c; - pRing->WrOff = WrOff; - Status = 1; - } else { - Status = 0; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_GetKey -* -* Function description -* Reads one character from the SEGGER RTT buffer. -* Host has previously stored data there. -* -* Return value -* < 0 - No character available (buffer empty). -* >= 0 - Character which has been read. (Possible values: 0 - 255) -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0. -*/ -int SEGGER_RTT_GetKey(void) { - char c; - int r; - - r = (int)SEGGER_RTT_Read(0u, &c, 1u); - if (r == 1) { - r = (int)(unsigned char)c; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_WaitKey -* -* Function description -* Waits until at least one character is avaible in the SEGGER RTT buffer. -* Once a character is available, it is read and this function returns. -* -* Return value -* >=0 - Character which has been read. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -* (2) This function is blocking if no character is present in RTT buffer -*/ -int SEGGER_RTT_WaitKey(void) { - int r; - - do { - r = SEGGER_RTT_GetKey(); - } while (r < 0); - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasKey -* -* Function description -* Checks if at least one character for reading is available in the SEGGER RTT buffer. -* -* Return value -* == 0 - No characters are available to read. -* == 1 - At least one character is available. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -*/ -int SEGGER_RTT_HasKey(void) { - unsigned RdOff; - int r; - - INIT(); - RdOff = _SEGGER_RTT.aDown[0].RdOff; - if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { - r = 1; - } else { - r = 0; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasData -* -* Function description -* Check if there is data from the host in the given buffer. -* -* Return value: -* ==0: No data -* !=0: Data in buffer -* -*/ -unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { - SEGGER_RTT_BUFFER_DOWN* pRing; - unsigned v; - - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - v = pRing->WrOff; - return v - pRing->RdOff; -} - -/********************************************************************* -* -* SEGGER_RTT_HasDataUp -* -* Function description -* Check if there is data remaining to be sent in the given buffer. -* -* Return value: -* ==0: No data -* !=0: Data in buffer -* -*/ -unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) { - SEGGER_RTT_BUFFER_UP* pRing; - unsigned v; - - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - v = pRing->RdOff; - return pRing->WrOff - v; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocDownBuffer -* -* Function description -* Run-time configuration of the next down-buffer (H->T). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocUpBuffer -* -* Function description -* Run-time configuration of the next up-buffer (T->H). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer (T->H). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. -* < 0 - Error -* -* Additional information -* Buffer 0 is configured on compile-time. -* May only be called once per buffer. -* Buffer name and flags can be reconfigured using the appropriate functions. -*/ -int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigDownBuffer -* -* Function description -* Run-time configuration of a specific down-buffer (H->T). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 O.K. -* < 0 Error -* -* Additional information -* Buffer 0 is configured on compile-time. -* May only be called once per buffer. -* Buffer name and flags can be reconfigured using the appropriate functions. -*/ -int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = (char*)pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameDownBuffer -* -* Function description -* Run-time configuration of a specific Down-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetFlagsUpBuffer -* -* Function description -* Run-time configuration of specific up-buffer flags (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer. -* Flags Flags to set for the buffer. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetFlagsDownBuffer -* -* Function description -* Run-time configuration of specific Down-buffer flags (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* Flags Flags to set for the buffer. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_Init -* -* Function description -* Initializes the RTT Control Block. -* Should be used in RAM targets, at start of the application. -* -*/ -void SEGGER_RTT_Init (void) { - _DoInit(); -} - -/********************************************************************* -* -* SEGGER_RTT_SetTerminal -* -* Function description -* Sets the terminal to be used for output on channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* -* Return value -* >= 0 O.K. -* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) -*/ -int SEGGER_RTT_SetTerminal (unsigned char TerminalId) { - unsigned char ac[2]; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - int r; - // - INIT(); - // - r = 0; - ac[0] = 0xFFu; - if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels - ac[1] = _aTerminalId[TerminalId]; - pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed - SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing - if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { - _ActiveTerminal = TerminalId; - _WriteBlocking(pRing, (const char*)ac, 2u); - } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes - Avail = _GetAvailWriteSpace(pRing); - if (Avail >= 2) { - _ActiveTerminal = TerminalId; // Only change active terminal in case of success - _WriteNoCheck(pRing, (const char*)ac, 2u); - } else { - r = -1; - } - } - SEGGER_RTT_UNLOCK(); - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_TerminalOut -* -* Function description -* Writes a string to the given terminal -* without changing the terminal for channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* s String to be printed on the terminal. -* -* Return value -* >= 0 - Number of bytes written. -* < 0 - Error. -* -*/ -int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) { - int Status; - unsigned FragLen; - unsigned Avail; - SEGGER_RTT_BUFFER_UP* pRing; - // - INIT(); - // - // Validate terminal ID. - // - if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[0]; - // - // Need to be able to change terminal, write data, change back. - // Compute the fixed and variable sizes. - // - FragLen = STRLEN(s); - // - // How we output depends upon the mode... - // - SEGGER_RTT_LOCK(); - Avail = _GetAvailWriteSpace(pRing); - switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother switching terminals at all. - // - if (Avail < (FragLen + 4u)) { - Status = 0; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode and there is not enough space for everything, - // trim the output but always include the terminal switch. If no room - // for terminal switch, skip that totally. - // - if (Avail < 4u) { - Status = -1; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - break; - default: - Status = -1; - break; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - } else { - Status = -1; - } - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_GetAvailWriteSpace -* -* Function description -* Returns the number of bytes available in the ring buffer. -* -* Parameters -* BufferIndex Index of the up buffer. -* -* Return value -* Number of bytes that are free in the selected up buffer. -*/ -unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex){ - return _GetAvailWriteSpace(&_SEGGER_RTT.aUp[BufferIndex]); -} - - -/********************************************************************* -* -* SEGGER_RTT_GetBytesInBuffer() -* -* Function description -* Returns the number of bytes currently used in the up buffer. -* -* Parameters -* BufferIndex Index of the up buffer. -* -* Return value -* Number of bytes that are used in the buffer. -*/ -unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex) { - unsigned RdOff; - unsigned WrOff; - unsigned r; - // - // Avoid warnings regarding volatile access order. It's not a problem - // in this case, but dampen compiler enthusiasm. - // - RdOff = _SEGGER_RTT.aUp[BufferIndex].RdOff; - WrOff = _SEGGER_RTT.aUp[BufferIndex].WrOff; - if (RdOff <= WrOff) { - r = WrOff - RdOff; - } else { - r = _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff); - } - return r; -} - -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h deleted file mode 100644 index 3c04df55f..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT.h +++ /dev/null @@ -1,321 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* 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 SEGGER Microcontroller 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. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.h -Purpose : Implementation of SEGGER real-time transfer which allows - real-time communication on targets which support debugger - memory accesses while the CPU is running. -Revision: $Rev: 17697 $ ----------------------------------------------------------------------- -*/ - -#ifndef SEGGER_RTT_H -#define SEGGER_RTT_H - -#include "SEGGER_RTT_Conf.h" - - - -/********************************************************************* -* -* Defines, defaults -* -********************************************************************** -*/ -#ifndef RTT_USE_ASM - #if (defined __SES_ARM) // SEGGER Embedded Studio - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __CROSSWORKS_ARM) // Rowley Crossworks - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __GNUC__) // GCC - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __clang__) // Clang compiler - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __IASMARM__) // IAR assembler - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ICCARM__) // IAR compiler - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #else - #define _CC_HAS_RTT_ASM_SUPPORT 0 - #endif - #if (defined __ARM_ARCH_7M__) // Cortex-M3/4 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ARM_ARCH_7EM__) // Cortex-M7 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ARM7M__) // IAR Cortex-M3/4 - #if (__CORE__ == __ARM7M__) - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #else - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #endif - #elif (defined __ARM7EM__) // IAR Cortex-M7 - #if (__CORE__ == __ARM7EM__) - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #else - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #endif - #else - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #endif - // - // If IDE and core support the ASM version, enable ASM version by default - // - #if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT) - #define RTT_USE_ASM (1) - #else - #define RTT_USE_ASM (0) - #endif -#endif - -#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file -#include -#include - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as up-buffer (T->H) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - unsigned WrOff; // Position of next item to be written by either target. - volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_UP; - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as down-buffer (H->T) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. - unsigned RdOff; // Position of next item to be read by target (down-buffer). - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_DOWN; - -// -// RTT control block which describes the number of buffers available -// as well as the configuration for each buffer -// -// -typedef struct { - char acID[16]; // Initialized to "SEGGER RTT" - int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) - int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) - SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host - SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target -} SEGGER_RTT_CB; - -/********************************************************************* -* -* Global data -* -********************************************************************** -*/ -extern SEGGER_RTT_CB _SEGGER_RTT; - -/********************************************************************* -* -* RTT API functions -* -********************************************************************** -*/ -#ifdef __cplusplus - extern "C" { -#endif -int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_GetKey (void); -unsigned SEGGER_RTT_HasData (unsigned BufferIndex); -int SEGGER_RTT_HasKey (void); -unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex); -void SEGGER_RTT_Init (void); -unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); -unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); -int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); -int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); -int SEGGER_RTT_WaitKey (void); -unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); -unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); -// -// Function macro for performance optimization -// -#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) - -#if RTT_USE_ASM - #define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock -#endif - -/********************************************************************* -* -* RTT transfer functions to send RTT data via other channels. -* -********************************************************************** -*/ -unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); -unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); -unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); - -#define SEGGER_RTT_HASDATA_UP(n) (_SEGGER_RTT.aUp[n].WrOff - _SEGGER_RTT.aUp[n].RdOff) - -/********************************************************************* -* -* RTT "Terminal" API functions -* -********************************************************************** -*/ -int SEGGER_RTT_SetTerminal (unsigned char TerminalId); -int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s); - -/********************************************************************* -* -* RTT printf functions (require SEGGER_RTT_printf.c) -* -********************************************************************** -*/ -int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); -int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); - -#ifdef __cplusplus - } -#endif - -#endif // ifndef(SEGGER_RTT_ASM) - -/********************************************************************* -* -* Defines -* -********************************************************************** -*/ - -// -// Operating modes. Define behavior if buffer is full (not enough space for entire message) -// -#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default) -#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits. -#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer. -#define SEGGER_RTT_MODE_MASK (3) - -// -// Control sequences, based on ANSI. -// Can be used to control color, and clear the screen -// -#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors -#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left - -#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" -#define RTT_CTRL_TEXT_RED "\x1B[2;31m" -#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" -#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" -#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" -#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" -#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" -#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" - -#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" -#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" -#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" -#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" -#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" -#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" -#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" -#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" - -#define RTT_CTRL_BG_BLACK "\x1B[24;40m" -#define RTT_CTRL_BG_RED "\x1B[24;41m" -#define RTT_CTRL_BG_GREEN "\x1B[24;42m" -#define RTT_CTRL_BG_YELLOW "\x1B[24;43m" -#define RTT_CTRL_BG_BLUE "\x1B[24;44m" -#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" -#define RTT_CTRL_BG_CYAN "\x1B[24;46m" -#define RTT_CTRL_BG_WHITE "\x1B[24;47m" - -#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" -#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" -#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" -#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" -#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" -#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" -#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" -#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" - - -#endif - -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S deleted file mode 100644 index 78cde4d75..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_ASM_ARMv7M.S +++ /dev/null @@ -1,235 +0,0 @@ -/********************************************************************* -* (c) SEGGER Microcontroller GmbH * -* The Embedded Experts * -* www.segger.com * -********************************************************************** - --------------------------- END-OF-HEADER ----------------------------- - -File : SEGGER_RTT_ASM_ARMv7M.S -Purpose : Assembler implementation of RTT functions for ARMv7M - -Additional information: - This module is written to be assembler-independent and works with - GCC and clang (Embedded Studio) and IAR. -*/ - -#define SEGGER_RTT_ASM // Used to control processed input from header file -#include "SEGGER_RTT.h" - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ -#define _CCIAR 0 -#define _CCCLANG 1 - -#if (defined __SES_ARM) || (defined __GNUC__) || (defined __clang__) - #define _CC_TYPE _CCCLANG - #define _PUB_SYM .global - #define _EXT_SYM .extern - #define _END .end - #define _WEAK .weak - #define _THUMB_FUNC .thumb_func - #define _THUMB_CODE .code 16 - #define _WORD .word - #define _SECTION(Sect, Type, AlignExp) .section Sect ##, "ax" - #define _ALIGN(Exp) .align Exp - #define _PLACE_LITS .ltorg - #define _DATA_SECT_START - #define _C_STARTUP _start - #define _STACK_END __stack_end__ - #define _RAMFUNC - // - // .text => Link to flash - // .fast => Link to RAM - // OtherSect => Usually link to RAM - // Alignment is 2^x - // -#elif defined (__IASMARM__) - #define _CC_TYPE _CCIAR - #define _PUB_SYM PUBLIC - #define _EXT_SYM EXTERN - #define _END END - #define _WEAK _WEAK - #define _THUMB_FUNC - #define _THUMB_CODE THUMB - #define _WORD DCD - #define _SECTION(Sect, Type, AlignExp) SECTION Sect ## : ## Type ## :REORDER:NOROOT ## (AlignExp) - #define _ALIGN(Exp) alignrom Exp - #define _PLACE_LITS - #define _DATA_SECT_START DATA - #define _C_STARTUP __iar_program_start - #define _STACK_END sfe(CSTACK) - #define _RAMFUNC SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR - // - // .text => Link to flash - // .textrw => Link to RAM - // OtherSect => Usually link to RAM - // NOROOT => Allows linker to throw away the function, if not referenced - // Alignment is 2^x - // -#endif - -#if (_CC_TYPE == _CCIAR) - NAME SEGGER_RTT_ASM_ARMv7M -#else - .syntax unified -#endif - -#if defined (RTT_USE_ASM) && (RTT_USE_ASM == 1) - #define SHT_PROGBITS 0x1 - -/********************************************************************* -* -* Public / external symbols -* -********************************************************************** -*/ - - _EXT_SYM __aeabi_memcpy - _EXT_SYM __aeabi_memcpy4 - _EXT_SYM _SEGGER_RTT - - _PUB_SYM SEGGER_RTT_ASM_WriteSkipNoLock - -/********************************************************************* -* -* SEGGER_RTT_WriteSkipNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteSkipNoLock does not lock the application and -* skips all data, if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* MUST be > 0!!! -* This is done for performance reasons, so no initial check has do be done. -* -* Return value -* 1: Data has been copied -* 0: No space, data has not been copied -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, all data is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ - _SECTION(.text, CODE, 2) - _ALIGN(2) - _THUMB_FUNC -SEGGER_RTT_ASM_WriteSkipNoLock: // unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pData, unsigned NumBytes) { - // - // Cases: - // 1) RdOff <= WrOff => Space until wrap-around is sufficient - // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) - // 3) RdOff < WrOff => No space in buf - // 4) RdOff > WrOff => Space is sufficient - // 5) RdOff > WrOff => No space in buf - // - // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough - // - // Register usage: - // R0 Temporary needed as RdOff, register later on - // R1 pData - // R2 - // R3 register. Hold free for subroutine calls - // R4 - // R5 pRing->pBuffer - // R6 pRing (Points to active struct SEGGER_RTT_BUFFER_DOWN) - // R7 WrOff - // - PUSH {R4-R7} - ADD R3,R0,R0, LSL #+1 - LDR.W R0,=_SEGGER_RTT // pRing = &_SEGGER_RTT.aUp[BufferIndex]; - ADD R0,R0,R3, LSL #+3 - ADD R6,R0,#+24 - LDR R0,[R6, #+16] // RdOff = pRing->RdOff; - LDR R7,[R6, #+12] // WrOff = pRing->WrOff; - LDR R5,[R6, #+4] // pRing->pBuffer - CMP R7,R0 - BCC.N _CheckCase4 // if (RdOff <= WrOff) { => Case 1), 2) or 3) - // - // Handling for case 1, later on identical to case 4 - // - LDR R3,[R6, #+8] // Avail = pRing->SizeOfBuffer - WrOff - 1u; => Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) - SUBS R4,R3,R7 // (Used in case we jump into case 2 afterwards) - SUBS R3,R4,#+1 // - CMP R3,R2 - BCC.N _CheckCase2 // if (Avail >= NumBytes) { => Case 1)? -_Case4: - ADDS R5,R7,R5 // pBuffer += WrOff - ADDS R0,R2,R7 // v = WrOff + NumBytes - // - // 2x unrolling for the copy loop that is used most of the time - // This is a special optimization for small SystemView packets and makes them even faster - // - _ALIGN(2) -_LoopCopyStraight: // memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - LDRB R3,[R1], #+1 - STRB R3,[R5], #+1 // *pDest++ = *pSrc++ - SUBS R2,R2,#+1 - BEQ _CSDone - LDRB R3,[R1], #+1 - STRB R3,[R5], #+1 // *pDest++ = *pSrc++ - SUBS R2,R2,#+1 - BNE _LoopCopyStraight -_CSDone: - STR R0,[R6, #+12] // pRing->WrOff = WrOff + NumBytes; - MOVS R0,#+1 - POP {R4-R7} - BX LR // Return 1 -_CheckCase2: - ADDS R0,R0,R3 // Avail += RdOff; => Space incl. wrap-around - CMP R0,R2 - BCC.N _Case3 // if (Avail >= NumBytes) { => Case 2? => If not, we have case 3) (does not fit) - // - // Handling for case 2 - // - ADDS R0,R7,R5 // v = pRing->pBuffer + WrOff => Do not change pRing->pBuffer here because 2nd chunk needs org. value - SUBS R2,R2,R4 // NumBytes -= Rem; (Rem = pRing->SizeOfBuffer - WrOff; => Space until end of buffer) -_LoopCopyBeforeWrapAround: // memcpy(pRing->pBuffer + WrOff, pData, Rem); => Copy 1st chunk - LDRB R3,[R1], #+1 - STRB R3,[R0], #+1 // *pDest++ = *pSrc++ - SUBS R4,R4,#+1 - BNE _LoopCopyBeforeWrapAround - // - // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used - // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element - // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks - // Therefore, check if 2nd memcpy is necessary at all - // - ADDS R4,R2,#+0 // Save (needed as counter in loop but must be written to after the loop). Also use this inst to update the flags to skip 2nd loop if possible - BEQ.N _No2ChunkNeeded // if (NumBytes) { -_LoopCopyAfterWrapAround: // memcpy(pRing->pBuffer, pData + Rem, NumBytes); - LDRB R3,[R1], #+1 // pData already points to the next src byte due to copy loop increment before this loop - STRB R3,[R5], #+1 // *pDest++ = *pSrc++ - SUBS R2,R2,#+1 - BNE _LoopCopyAfterWrapAround -_No2ChunkNeeded: - STR R4,[R6, #+12] // pRing->WrOff = NumBytes; => Must be written after copying data because J-Link may read control block asynchronously while writing into buffer - MOVS R0,#+1 - POP {R4-R7} - BX LR // Return 1 -_CheckCase4: - SUBS R0,R0,R7 - SUBS R0,R0,#+1 // Avail = RdOff - WrOff - 1u; - CMP R0,R2 - BCS.N _Case4 // if (Avail >= NumBytes) { => Case 4) == 1) ? => If not, we have case 5) == 3) (does not fit) -_Case3: - MOVS R0,#+0 - POP {R4-R7} - BX LR // Return 0 - _PLACE_LITS - -#endif // defined (RTT_USE_ASM) && (RTT_USE_ASM == 1) - _END - -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h deleted file mode 100644 index 5e79d7e67..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_Conf.h +++ /dev/null @@ -1,384 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* 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 SEGGER Microcontroller 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. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Conf.h -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. -Revision: $Rev: 18601 $ - -*/ - -#ifndef SEGGER_RTT_CONF_H -#define SEGGER_RTT_CONF_H - -#ifdef __IAR_SYSTEMS_ICC__ - #include -#endif - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ -#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS - #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3) -#endif - -#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS - #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3) -#endif - -#ifndef BUFFER_SIZE_UP - #define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) -#endif - -#ifndef BUFFER_SIZE_DOWN - #define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) -#endif - -#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE - #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) -#endif - -#ifndef SEGGER_RTT_MODE_DEFAULT - #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) -#endif - -/********************************************************************* -* -* RTT memcpy configuration -* -* memcpy() is good for large amounts of data, -* but the overhead is big for small amounts, which are usually stored via RTT. -* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead. -* -* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions. -* This is may be required with memory access restrictions, -* such as on Cortex-A devices with MMU. -*/ -#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP - #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop -#endif -// -// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets -// -//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__)) -// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes)) -//#endif - -// -// Target is not allowed to perform other RTT operations while string still has not been stored completely. -// Otherwise we would probably end up with a mixed string in the buffer. -// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. -// -// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. -// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. -// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. -// (Higher priority = lower priority number) -// Default value for embOS: 128u -// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC -// or define SEGGER_RTT_LOCK() to completely disable interrupts. -// -#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) -#endif - -/********************************************************************* -* -* RTT lock configuration for SEGGER Embedded Studio, -* Rowley CrossStudio and GCC -*/ -#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32)) - #if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, primask \n\t" \ - "movs r1, $1 \n\t" \ - "msr primask, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, basepri \n\t" \ - "mov r1, %1 \n\t" \ - "msr basepri, r1 \n\t" \ - : "=r" (LockState) \ - : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - - #elif defined(__ARM_ARCH_7A__) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs r1, CPSR \n\t" \ - "mov %0, r1 \n\t" \ - "orr r1, r1, #0xC0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ - "mrs r1, CPSR \n\t" \ - "bic r1, r1, #0xC0 \n\t" \ - "and r0, r0, #0xC0 \n\t" \ - "orr r1, r1, r0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : \ - : "r" (LockState) \ - : "r0", "r1" \ - ); \ - } - #elif defined(__riscv) || defined(__riscv_xlen) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("csrr %0, mstatus \n\t" \ - "csrci mstatus, 8 \n\t" \ - "andi %0, %0, 8 \n\t" \ - : "=r" (LockState) \ - : \ - : \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \ - "or %0, %0, a1 \n\t" \ - "csrs mstatus, %0 \n\t" \ - : \ - : "r" (LockState) \ - : "a1" \ - ); \ - } - #else - #define SEGGER_RTT_LOCK() - #define SEGGER_RTT_UNLOCK() - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR EWARM -*/ -#ifdef __ICCARM__ - #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \ - (defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ - } - #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \ - (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \ - (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \ - (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_BASEPRI(); \ - __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR RX -*/ -#ifdef __ICCRX__ - #define SEGGER_RTT_LOCK() { \ - unsigned long LockState; \ - LockState = __get_interrupt_state(); \ - __disable_interrupt(); - - #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR RL78 -*/ -#ifdef __ICCRL78__ - #define SEGGER_RTT_LOCK() { \ - __istate_t LockState; \ - LockState = __get_interrupt_state(); \ - __disable_interrupt(); - - #define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for KEIL ARM -*/ -#ifdef __CC_ARM - #if (defined __TARGET_ARCH_6S_M) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char PRIMASK __asm( "primask"); \ - LockState = PRIMASK; \ - PRIMASK = 1u; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ - __schedule_barrier(); \ - } - #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char BASEPRI __asm( "basepri"); \ - LockState = BASEPRI; \ - BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ - __schedule_barrier(); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for TI ARM -*/ -#ifdef __TI_ARM__ - #if defined (__TI_ARM_V6M0__) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ - } - #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() _set_interrupt_priority(LockState); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for CCRX -*/ -#ifdef __RX - #define SEGGER_RTT_LOCK() { \ - unsigned long LockState; \ - LockState = get_psw() & 0x010000; \ - clrpsw_i(); - - #define SEGGER_RTT_UNLOCK() set_psw(get_psw() | LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for embOS Simulation on Windows -* (Can also be used for generic RTT locking with embOS) -*/ -#if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS) - -void OS_SIM_EnterCriticalSection(void); -void OS_SIM_LeaveCriticalSection(void); - -#define SEGGER_RTT_LOCK() { \ - OS_SIM_EnterCriticalSection(); - -#define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration fallback -*/ -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) -#endif - -#endif -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c deleted file mode 100644 index 4c996b408..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c +++ /dev/null @@ -1,500 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* 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 SEGGER Microcontroller 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. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_printf.c -Purpose : Replacement for printf to write formatted data via RTT -Revision: $Rev: 17697 $ ----------------------------------------------------------------------- -*/ -#include "SEGGER_RTT.h" -#include "SEGGER_RTT_Conf.h" - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ - -#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE - #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) -#endif - -#include -#include - - -#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) -#define FORMAT_FLAG_PAD_ZERO (1u << 1) -#define FORMAT_FLAG_PRINT_SIGN (1u << 2) -#define FORMAT_FLAG_ALTERNATE (1u << 3) - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -typedef struct { - char* pBuffer; - unsigned BufferSize; - unsigned Cnt; - - int ReturnValue; - - unsigned RTTBufferIndex; -} SEGGER_RTT_PRINTF_DESC; - -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ - -/********************************************************************* -* -* Static code -* -********************************************************************** -*/ -/********************************************************************* -* -* _StoreChar -*/ -static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { - unsigned Cnt; - - Cnt = p->Cnt; - if ((Cnt + 1u) <= p->BufferSize) { - *(p->pBuffer + Cnt) = c; - p->Cnt = Cnt + 1u; - p->ReturnValue++; - } - // - // Write part of string, when the buffer is full - // - if (p->Cnt == p->BufferSize) { - if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { - p->ReturnValue = -1; - } else { - p->Cnt = 0u; - } - } -} - -/********************************************************************* -* -* _PrintUnsigned -*/ -static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { - static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - unsigned Div; - unsigned Digit; - unsigned Number; - unsigned Width; - char c; - - Number = v; - Digit = 1u; - // - // Get actual field width - // - Width = 1u; - while (Number >= Base) { - Number = (Number / Base); - Width++; - } - if (NumDigits > Width) { - Width = NumDigits; - } - // - // Print leading chars if necessary - // - if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { - if (FieldWidth != 0u) { - if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { - c = '0'; - } else { - c = ' '; - } - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, c); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - if (pBufferDesc->ReturnValue >= 0) { - // - // Compute Digit. - // Loop until Digit has the value of the highest digit required. - // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. - // - while (1) { - if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) - NumDigits--; - } else { - Div = v / Digit; - if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done - break; - } - } - Digit *= Base; - } - // - // Output digits - // - do { - Div = v / Digit; - v -= Div * Digit; - _StoreChar(pBufferDesc, _aV2C[Div]); - if (pBufferDesc->ReturnValue < 0) { - break; - } - Digit /= Base; - } while (Digit); - // - // Print trailing spaces if necessary - // - if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, ' '); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - } -} - -/********************************************************************* -* -* _PrintInt -*/ -static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { - unsigned Width; - int Number; - - Number = (v < 0) ? -v : v; - - // - // Get actual field width - // - Width = 1u; - while (Number >= (int)Base) { - Number = (Number / (int)Base); - Width++; - } - if (NumDigits > Width) { - Width = NumDigits; - } - if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { - FieldWidth--; - } - - // - // Print leading spaces if necessary - // - if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, ' '); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - // - // Print sign if necessary - // - if (pBufferDesc->ReturnValue >= 0) { - if (v < 0) { - v = -v; - _StoreChar(pBufferDesc, '-'); - } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { - _StoreChar(pBufferDesc, '+'); - } else { - - } - if (pBufferDesc->ReturnValue >= 0) { - // - // Print leading zeros if necessary - // - if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, '0'); - if (pBufferDesc->ReturnValue < 0) { - break; - } - } - } - } - if (pBufferDesc->ReturnValue >= 0) { - // - // Print number without sign - // - _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); - } - } - } -} - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ -/********************************************************************* -* -* SEGGER_RTT_vprintf -* -* Function description -* Stores a formatted string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") -* sFormat Pointer to format string -* pParamList Pointer to the list of arguments for the format string -* -* Return values -* >= 0: Number of bytes which have been stored in the "Up"-buffer. -* < 0: Error -*/ -int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { - char c; - SEGGER_RTT_PRINTF_DESC BufferDesc; - int v; - unsigned NumDigits; - unsigned FormatFlags; - unsigned FieldWidth; - char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; - - BufferDesc.pBuffer = acBuffer; - BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; - BufferDesc.Cnt = 0u; - BufferDesc.RTTBufferIndex = BufferIndex; - BufferDesc.ReturnValue = 0; - - do { - c = *sFormat; - sFormat++; - if (c == 0u) { - break; - } - if (c == '%') { - // - // Filter out flags - // - FormatFlags = 0u; - v = 1; - do { - c = *sFormat; - switch (c) { - case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; - case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; - case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; - case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; - default: v = 0; break; - } - } while (v); - // - // filter out field with - // - FieldWidth = 0u; - do { - c = *sFormat; - if ((c < '0') || (c > '9')) { - break; - } - sFormat++; - FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); - } while (1); - - // - // Filter out precision (number of digits to display) - // - NumDigits = 0u; - c = *sFormat; - if (c == '.') { - sFormat++; - do { - c = *sFormat; - if ((c < '0') || (c > '9')) { - break; - } - sFormat++; - NumDigits = NumDigits * 10u + ((unsigned)c - '0'); - } while (1); - } - // - // Filter out length modifier - // - c = *sFormat; - do { - if ((c == 'l') || (c == 'h')) { - sFormat++; - c = *sFormat; - } else { - break; - } - } while (1); - // - // Handle specifiers - // - switch (c) { - case 'c': { - char c0; - v = va_arg(*pParamList, int); - c0 = (char)v; - _StoreChar(&BufferDesc, c0); - break; - } - case 'd': - v = va_arg(*pParamList, int); - _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); - break; - case 'u': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); - break; - case 'x': - case 'X': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); - break; - case 's': - { - const char * s = va_arg(*pParamList, const char *); - do { - c = *s; - s++; - if (c == '\0') { - break; - } - _StoreChar(&BufferDesc, c); - } while (BufferDesc.ReturnValue >= 0); - } - break; - case 'p': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); - break; - case '%': - _StoreChar(&BufferDesc, '%'); - break; - default: - break; - } - sFormat++; - } else { - _StoreChar(&BufferDesc, c); - } - } while (BufferDesc.ReturnValue >= 0); - - if (BufferDesc.ReturnValue > 0) { - // - // Write remaining data, if any - // - if (BufferDesc.Cnt != 0u) { - SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); - } - BufferDesc.ReturnValue += (int)BufferDesc.Cnt; - } - return BufferDesc.ReturnValue; -} - -/********************************************************************* -* -* SEGGER_RTT_printf -* -* Function description -* Stores a formatted string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") -* sFormat Pointer to format string, followed by the arguments for conversion -* -* Return values -* >= 0: Number of bytes which have been stored in the "Up"-buffer. -* < 0: Error -* -* Notes -* (1) Conversion specifications have following syntax: -* %[flags][FieldWidth][.Precision]ConversionSpecifier -* (2) Supported flags: -* -: Left justify within the field width -* +: Always print sign extension for signed conversions -* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision -* Supported conversion specifiers: -* c: Print the argument as one char -* d: Print the argument as a signed integer -* u: Print the argument as an unsigned integer -* x: Print the argument as an hexadecimal integer -* s: Print the string pointed to by the argument -* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) -*/ -int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { - int r; - va_list ParamList; - - va_start(ParamList, sFormat); - r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); - va_end(ParamList); - return r; -} -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c deleted file mode 100644 index da4a4b5f5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_GCC.c +++ /dev/null @@ -1,120 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* 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 SEGGER Microcontroller 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. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Syscalls_GCC.c -Purpose : Low-level functions for using printf() via RTT in GCC. - To use RTT for printf output, include this file in your - application. -Revision: $Rev: 17697 $ ----------------------------------------------------------------------- -*/ -#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) - -#include // required for _write_r -#include "SEGGER_RTT.h" - - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ -// -// If necessary define the _reent struct -// to match the one passed by the used standard library. -// -struct _reent; - -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ -int _write(int file, char *ptr, int len); -int _write_r(struct _reent *r, int file, const void *ptr, int len); - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ - -/********************************************************************* -* -* _write() -* -* Function description -* Low-level write function. -* libc subroutines will use this system routine for output to all files, -* including stdout. -* Write data via RTT. -*/ -int _write(int file, char *ptr, int len) { - (void) file; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, ptr, len); - return len; -} - -/********************************************************************* -* -* _write_r() -* -* Function description -* Low-level reentrant write function. -* libc subroutines will use this system routine for output to all files, -* including stdout. -* Write data via RTT. -*/ -int _write_r(struct _reent *r, int file, const void *ptr, int len) { - (void) file; /* Not used, avoid warning */ - (void) r; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, ptr, len); - return len; -} - -#endif -/****** End Of File *************************************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c deleted file mode 100644 index 4c76752b3..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c +++ /dev/null @@ -1,115 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* 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 SEGGER Microcontroller 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. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Syscalls_IAR.c -Purpose : Low-level functions for using printf() via RTT in IAR. - To use RTT for printf output, include this file in your - application and set the Library Configuration to Normal. -Revision: $Rev: 17697 $ ----------------------------------------------------------------------- -*/ -#ifdef __IAR_SYSTEMS_ICC__ - -// -// Since IAR EWARM V8 and EWRX V4, yfuns.h is considered as deprecated and LowLevelIOInterface.h -// shall be used instead. To not break any compatibility with older compiler versions, we have a -// version check in here. -// -#if ((defined __ICCARM__) && (__VER__ >= 8000000)) || ((defined __ICCRX__) && (__VER__ >= 400)) - #include -#else - #include -#endif - -#include "SEGGER_RTT.h" -#pragma module_name = "?__write" - -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ -size_t __write(int handle, const unsigned char * buffer, size_t size); - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ -/********************************************************************* -* -* __write() -* -* Function description -* Low-level write function. -* Standard library subroutines will use this system routine -* for output to all files, including stdout. -* Write data via RTT. -*/ -size_t __write(int handle, const unsigned char * buffer, size_t size) { - (void) handle; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, (const char*)buffer, size); - return size; -} - -/********************************************************************* -* -* __write_buffered() -* -* Function description -* Low-level write function. -* Standard library subroutines will use this system routine -* for output to all files, including stdout. -* Write data via RTT. -*/ -size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) { - (void) handle; /* Not used, avoid warning */ - SEGGER_RTT_Write(0, (const char*)buffer, size); - return size; -} - -#endif -/****** End Of File *************************************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c deleted file mode 100644 index f7f5aed48..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_KEIL.c +++ /dev/null @@ -1,386 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* 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 SEGGER Microcontroller 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. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : RTT_Syscalls_KEIL.c -Purpose : Retargeting module for KEIL MDK-CM3. - Low-level functions for using printf() via RTT -Revision: $Rev: 17697 $ ----------------------------------------------------------------------- -*/ -#ifdef __CC_ARM - -#include -#include -#include -#include -#include - -#include "SEGGER_RTT.h" -/********************************************************************* -* -* #pragmas -* -********************************************************************** -*/ -#pragma import(__use_no_semihosting) - -#ifdef _MICROLIB - #pragma import(__use_full_stdio) -#endif - -/********************************************************************* -* -* Defines non-configurable -* -********************************************************************** -*/ - -/* Standard IO device handles - arbitrary, but any real file system handles must be - less than 0x8000. */ -#define STDIN 0x8001 // Standard Input Stream -#define STDOUT 0x8002 // Standard Output Stream -#define STDERR 0x8003 // Standard Error Stream - -/********************************************************************* -* -* Public const -* -********************************************************************** -*/ -#if __ARMCC_VERSION < 5000000 -//const char __stdin_name[] = "STDIN"; -const char __stdout_name[] = "STDOUT"; -const char __stderr_name[] = "STDERR"; -#endif - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ - -/********************************************************************* -* -* _ttywrch -* -* Function description: -* Outputs a character to the console -* -* Parameters: -* c - character to output -* -*/ -void _ttywrch(int c) { - fputc(c, stdout); // stdout - fflush(stdout); -} - -/********************************************************************* -* -* _sys_open -* -* Function description: -* Opens the device/file in order to do read/write operations -* -* Parameters: -* sName - sName of the device/file to open -* OpenMode - This parameter is currently ignored -* -* Return value: -* != 0 - Handle to the object to open, otherwise -* == 0 -"device" is not handled by this module -* -*/ -FILEHANDLE _sys_open(const char * sName, int OpenMode) { - (void)OpenMode; - // Register standard Input Output devices. - if (strcmp(sName, __stdout_name) == 0) { - return (STDOUT); - } else if (strcmp(sName, __stderr_name) == 0) { - return (STDERR); - } else - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_close -* -* Function description: -* Closes the handle to the open device/file -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* 0 - device/file closed -* -*/ -int _sys_close(FILEHANDLE hFile) { - (void)hFile; - return 0; // Not implemented -} - -/********************************************************************* -* -* _sys_write -* -* Function description: -* Writes the data to an open handle. -* Currently this function only outputs data to the console -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* pBuffer - Pointer to the data that shall be written -* NumBytes - Number of bytes to write -* Mode - The Mode that shall be used -* -* Return value: -* Number of bytes *not* written to the file/device -* -*/ -int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) { - int r = 0; - - (void)Mode; - if (hFile == STDOUT) { - SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes); - return 0; - } - return r; -} - -/********************************************************************* -* -* _sys_read -* -* Function description: -* Reads data from an open handle. -* Currently this modules does nothing. -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* pBuffer - Pointer to buffer to store the read data -* NumBytes - Number of bytes to read -* Mode - The Mode that shall be used -* -* Return value: -* Number of bytes read from the file/device -* -*/ -int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) { - (void)hFile; - (void)pBuffer; - (void)NumBytes; - (void)Mode; - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_istty -* -* Function description: -* This function shall return whether the opened file -* is a console device or not. -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* 1 - Device is a console -* 0 - Device is not a console -* -*/ -int _sys_istty(FILEHANDLE hFile) { - if (hFile > 0x8000) { - return (1); - } - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_seek -* -* Function description: -* Seeks via the file to a specific position -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* Pos - -* -* Return value: -* int - -* -*/ -int _sys_seek(FILEHANDLE hFile, long Pos) { - (void)hFile; - (void)Pos; - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_ensure -* -* Function description: -* -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* int - -* -*/ -int _sys_ensure(FILEHANDLE hFile) { - (void)hFile; - return (-1); // Not implemented -} - -/********************************************************************* -* -* _sys_flen -* -* Function description: -* Returns the length of the opened file handle -* -* Parameters: -* hFile - Handle to a file opened via _sys_open -* -* Return value: -* Length of the file -* -*/ -long _sys_flen(FILEHANDLE hFile) { - (void)hFile; - return (0); // Not implemented -} - -/********************************************************************* -* -* _sys_tmpnam -* -* Function description: -* This function converts the file number fileno for a temporary -* file to a unique filename, for example, tmp0001. -* -* Parameters: -* pBuffer - Pointer to a buffer to store the name -* FileNum - file number to convert -* MaxLen - Size of the buffer -* -* Return value: -* 1 - Error -* 0 - Success -* -*/ -int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) { - (void)pBuffer; - (void)FileNum; - (void)MaxLen; - return (1); // Not implemented -} - -/********************************************************************* -* -* _sys_command_string -* -* Function description: -* This function shall execute a system command. -* -* Parameters: -* cmd - Pointer to the command string -* len - Length of the string -* -* Return value: -* == NULL - Command was not successfully executed -* == sCmd - Command was passed successfully -* -*/ -char * _sys_command_string(char * cmd, int len) { - (void)len; - return cmd; // Not implemented -} - -/********************************************************************* -* -* _sys_exit -* -* Function description: -* This function is called when the application returns from main -* -* Parameters: -* ReturnCode - Return code from the main function -* -* -*/ -void _sys_exit(int ReturnCode) { - (void)ReturnCode; - while (1); // Not implemented -} - -#if __ARMCC_VERSION >= 5000000 -/********************************************************************* -* -* stdout_putchar -* -* Function description: -* Put a character to the stdout -* -* Parameters: -* ch - Character to output -* -* -*/ -int stdout_putchar(int ch) { - (void)ch; - return ch; // Not implemented -} -#endif - -#endif -/*************************** End of file ****************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c deleted file mode 100644 index 5ce8457e1..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_SES.c +++ /dev/null @@ -1,247 +0,0 @@ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2019 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the RTT protocol and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* 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 SEGGER Microcontroller 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. * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Syscalls_SES.c -Purpose : Reimplementation of printf, puts and __getchar using RTT - in SEGGER Embedded Studio. - To use RTT for printf output, include this file in your - application. -Revision: $Rev: 18539 $ ----------------------------------------------------------------------- -*/ -#if (defined __SES_ARM) || (defined __SES_RISCV) || (defined __CROSSWORKS_ARM) - -#include "SEGGER_RTT.h" -#include -#include -#include "limits.h" -#include "__libc.h" -#include "__vfprintf.h" - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ -// -// Select string formatting implementation. -// -// RTT printf formatting -// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h) -// - No maximum string length. -// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c) -// Standard library printf formatting -// - Configurable formatting capabilities. -// - Full conversion specifier and flag support. -// - Maximum string length has to be known or (slightly) slower character-wise output. -// -// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting -// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting -// -#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING - #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 -#endif -// -// If using standard library formatting, -// select maximum output string buffer size or character-wise output. -// -// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output -// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length -// -#ifndef PRINTF_BUFFER_SIZE - #define PRINTF_BUFFER_SIZE 128 -#endif - -#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation -/********************************************************************* -* -* Function prototypes -* -********************************************************************** -*/ -int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); - -/********************************************************************* -* -* Global functions, printf -* -********************************************************************** -*/ -/********************************************************************* -* -* printf() -* -* Function description -* print a formatted string using RTT and SEGGER RTT formatting. -*/ -int printf(const char *fmt,...) { - int n; - va_list args; - - va_start (args, fmt); - n = SEGGER_RTT_vprintf(0, fmt, &args); - va_end(args); - return n; -} - -#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output - -/********************************************************************* -* -* Static functions -* -********************************************************************** -*/ -static int _putchar(int x, __printf_tag_ptr ctx) { - (void)ctx; - SEGGER_RTT_Write(0, (char *)&x, 1); - return x; -} - -/********************************************************************* -* -* Global functions, printf -* -********************************************************************** -*/ -/********************************************************************* -* -* printf() -* -* Function description -* print a formatted string character-wise, using RTT and standard -* library formatting. -*/ -int printf(const char *fmt, ...) { - int n; - va_list args; - __printf_t iod; - - va_start(args, fmt); - iod.string = 0; - iod.maxchars = INT_MAX; - iod.output_fn = _putchar; - SEGGER_RTT_LOCK(); - n = __vfprintf(&iod, fmt, args); - SEGGER_RTT_UNLOCK(); - va_end(args); - return n; -} - -#else // Use standard library formatting with static buffer - -/********************************************************************* -* -* Global functions, printf -* -********************************************************************** -*/ -/********************************************************************* -* -* printf() -* -* Function description -* print a formatted string using RTT and standard library formatting. -*/ -int printf(const char *fmt,...) { - int n; - char aBuffer[PRINTF_BUFFER_SIZE]; - va_list args; - - va_start (args, fmt); - n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args); - if (n > (int)sizeof(aBuffer)) { - SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer)); - } else if (n > 0) { - SEGGER_RTT_Write(0, aBuffer, n); - } - va_end(args); - return n; -} -#endif - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ -/********************************************************************* -* -* puts() -* -* Function description -* print a string using RTT. -*/ -int puts(const char *s) { - return SEGGER_RTT_WriteString(0, s); -} - -/********************************************************************* -* -* __putchar() -* -* Function description -* Write one character via RTT. -*/ -int __putchar(int x, __printf_tag_ptr ctx) { - (void)ctx; - SEGGER_RTT_Write(0, (char *)&x, 1); - return x; -} - -/********************************************************************* -* -* __getchar() -* -* Function description -* Wait for and get a character via RTT. -*/ -int __getchar() { - return SEGGER_RTT_WaitKey(); -} - -#endif -/****** End Of File *************************************************/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt deleted file mode 100644 index f7330e924..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/00readme.txt +++ /dev/null @@ -1,138 +0,0 @@ -FatFs Module Source Files R0.09b (C)ChaN, 2013 - - -FILES - - ffconf.h Configuration file for FatFs module. - ff.h Common include file for FatFs and application module. - ff.c FatFs module. - diskio.h Common include file for FatFs and disk I/O module. - diskio.c An example of glue function to attach existing disk I/O module to FatFs. - integer.h Integer type definitions for FatFs. - option Optional external functions. - - Low level disk I/O module is not included in this archive because the FatFs - module is only a generic file system layer and not depend on any specific - storage device. You have to provide a low level disk I/O module that written - to control your storage device. - - - -AGREEMENTS - - FatFs module is an open source software to implement FAT file system to - small embedded systems. This is a free software and is opened for education, - research and commercial developments under license policy of following trems. - - Copyright (C) 2012, ChaN, all right reserved. - - * The FatFs module is a free software and there is NO WARRANTY. - * No restriction on use. You can use, modify and redistribute it for - personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. - * Redistributions of source code must retain the above copyright notice. - - - -REVISION HISTORY - - Feb 26, 2006 R0.00 Prototype - - Apr 29, 2006 R0.01 First release. - - Jun 01, 2006 R0.02 Added FAT12. - Removed unbuffered mode. - Fixed a problem on small (<32M) patition. - - Jun 10, 2006 R0.02a Added a configuration option _FS_MINIMUM. - - Sep 22, 2006 R0.03 Added f_rename. - Changed option _FS_MINIMUM to _FS_MINIMIZE. - - Dec 11, 2006 R0.03a Improved cluster scan algolithm to write files fast. - Fixed f_mkdir creates incorrect directory on FAT32. - - Feb 04, 2007 R0.04 Supported multiple drive system. (FatFs) - Changed some APIs for multiple drive system. - Added f_mkfs. (FatFs) - Added _USE_FAT32 option. (Tiny-FatFs) - - Apr 01, 2007 R0.04a Supported multiple partitions on a plysical drive. (FatFs) - Fixed an endian sensitive code in f_mkfs. (FatFs) - Added a capability of extending the file size to f_lseek. - Added minimization level 3. - Fixed a problem that can collapse a sector when recreate an - existing file in any sub-directory at non FAT32 cfg. (Tiny-FatFs) - - May 05, 2007 R0.04b Added _USE_NTFLAG option. - Added FSInfo support. - Fixed some problems corresponds to FAT32. (Tiny-FatFs) - Fixed DBCS name can result FR_INVALID_NAME. - Fixed short seek (0 < ofs <= csize) collapses the file object. - - Aug 25, 2007 R0.05 Changed arguments of f_read, f_write. - Changed arguments of f_mkfs. (FatFs) - Fixed f_mkfs on FAT32 creates incorrect FSInfo. (FatFs) - Fixed f_mkdir on FAT32 creates incorrect directory. (FatFs) - - Feb 03, 2008 R0.05a Added f_truncate(). - Added f_utime(). - Fixed off by one error at FAT sub-type determination. - Fixed btr in f_read() can be mistruncated. - Fixed cached sector is not flushed when create and close without write. - - Apr 01, 2008 R0.06 Added f_forward(). (Tiny-FatFs) - Added string functions: fputc(), fputs(), fprintf() and fgets(). - Improved performance of f_lseek() on move to the same or following cluster. - - Apr 01, 2009, R0.07 Merged Tiny-FatFs as a buffer configuration option. - Added long file name support. - Added multiple code page support. - Added re-entrancy for multitask operation. - Added auto cluster size selection to f_mkfs(). - Added rewind option to f_readdir(). - Changed result code of critical errors. - Renamed string functions to avoid name collision. - - Apr 14, 2009, R0.07a Separated out OS dependent code on reentrant cfg. - Added multiple sector size support. - - Jun 21, 2009, R0.07c Fixed f_unlink() may return FR_OK on error. - Fixed wrong cache control in f_lseek(). - Added relative path feature. - Added f_chdir(). - Added f_chdrive(). - Added proper case conversion for extended characters. - - Nov 03, 2009 R0.07e Separated out configuration options from ff.h to ffconf.h. - Added a configuration option, _LFN_UNICODE. - Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. - Fixed name matching error on the 13 char boundary. - Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. - - May 15, 2010, R0.08 Added a memory configuration option. (_USE_LFN) - Added file lock feature. (_FS_SHARE) - Added fast seek feature. (_USE_FASTSEEK) - Changed some types on the API, XCHAR->TCHAR. - Changed fname member in the FILINFO structure on Unicode cfg. - String functions support UTF-8 encoding files on Unicode cfg. - - Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2) - Added sector erase feature. (_USE_ERASE) - Moved file lock semaphore table from fs object to the bss. - Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. - Fixed f_mkfs() creates wrong FAT32 volume. - - Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). - f_lseek() reports required table size on creating CLMP. - Extended format syntax of f_printf function. - Ignores duplicated directory separators in given path names. - - Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. - Added f_fdisk(). (_MULTI_PARTITION = 2) - - Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16. - Changed f_open() and f_opendir() reject null object pointer to avoid crash. - Changed option name _FS_SHARE to _FS_LOCK. - - Jan 23,'13 R0.09b Added f_getlabel() and f_setlabel(). (_USE_LABEL == 1) - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c deleted file mode 100644 index 07d6f0983..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ccsbcs.c +++ /dev/null @@ -1,543 +0,0 @@ -/*------------------------------------------------------------------------*/ -/* Unicode - Local code bidirectional converter (C)ChaN, 2012 */ -/* (SBCS code pages) */ -/*------------------------------------------------------------------------*/ -/* 437 U.S. (OEM) -/ 720 Arabic (OEM) -/ 1256 Arabic (Windows) -/ 737 Greek (OEM) -/ 1253 Greek (Windows) -/ 1250 Central Europe (Windows) -/ 775 Baltic (OEM) -/ 1257 Baltic (Windows) -/ 850 Multilingual Latin 1 (OEM) -/ 852 Latin 2 (OEM) -/ 1252 Latin 1 (Windows) -/ 855 Cyrillic (OEM) -/ 1251 Cyrillic (Windows) -/ 866 Russian (OEM) -/ 857 Turkish (OEM) -/ 1254 Turkish (Windows) -/ 858 Multilingual Latin 1 + Euro (OEM) -/ 862 Hebrew (OEM) -/ 1255 Hebrew (Windows) -/ 874 Thai (OEM, Windows) -/ 1258 Vietnam (OEM, Windows) -*/ - -#include "ff.h" - -#if CFG_TUH_MSC - -#if _CODE_PAGE == 437 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, - 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, - 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, - 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 720 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */ - 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, - 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, - 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, - 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, - 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, - 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 737 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */ - 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, - 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, - 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, - 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, - 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, - 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, - 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, - 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 775 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */ - 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, - 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, - 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, - 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, - 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, - 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, - 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, - 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, - 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, - 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, - 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 850 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, - 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, - 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, - 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, - 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, - 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, - 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, - 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 852 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, - 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, - 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, - 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, - 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, - 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, - 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, - 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, - 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, - 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 855 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */ - 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, - 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, - 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, - 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, - 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, - 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, - 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, - 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, - 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, - 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, - 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, - 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 857 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, - 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, - 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, - 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, - 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, - 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, - 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, - 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 858 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, - 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, - 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, - 0x00A9, 0x2563, 0x2551, 0x2557, 0x2550, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE, - 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 0x00CC, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, - 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, - 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, - 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 862 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */ - 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, - 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, - 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, - 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, - 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 866 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */ - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 -}; - -#elif _CODE_PAGE == 874 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, - 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, - 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, - 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, - 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, - 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, - 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, - 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, - 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000 -}; - -#elif _CODE_PAGE == 1250 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, - 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, - 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, - 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, - 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, - 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, - 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, - 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, - 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, - 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, - 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 -}; - -#elif _CODE_PAGE == 1251 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */ - 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, - 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, - 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, - 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, - 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, - 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, - 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F -}; - -#elif _CODE_PAGE == 1252 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF -}; - -#elif _CODE_PAGE == 1253 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, - 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, - 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - 0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF, - 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000 -}; - -#elif _CODE_PAGE == 1254 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF -}; - -#elif _CODE_PAGE == 1255 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, - 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, - 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, - 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, - 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, - 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000 -}; - -#elif _CODE_PAGE == 1256 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, - 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, - 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, - 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, - 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, - 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, - 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643, - 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, - 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, - 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2 -} - -#elif _CODE_PAGE == 1257 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000, - 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7, - 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, - 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, - 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, - 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, - 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, - 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, - 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, - 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, - 0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9 -}; - -#elif _CODE_PAGE == 1258 -#define _TBLDEF 1 -static -const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, - 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, - 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF -}; - -#endif - - -#if !_TBLDEF || !_USE_LFN -#error This file is not needed in current configuration. Remove from the project. -#endif - - -WCHAR ff_convert ( /* Converted character, Returns zero on error */ - WCHAR chr, /* Character code to be converted */ - UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ -) -{ - WCHAR c; - - - if (chr < 0x80) { /* ASCII */ - c = chr; - - } else { - if (dir) { /* OEMCP to Unicode */ - c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80]; - - } else { /* Unicode to OEMCP */ - for (c = 0; c < 0x80; c++) { - if (chr == Tbl[c]) break; - } - c = (c + 0x80) & 0xFF; - } - } - - return c; -} - - -WCHAR ff_wtoupper ( /* Upper converted character */ - WCHAR chr /* Input character */ -) -{ - static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; - static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; - int i; - - - for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; - - return tbl_lower[i] ? tbl_upper[i] : chr; -} - -#endif // CFG_TUH_MSC diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c deleted file mode 100644 index a6132f27b..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb.h" - -#if CFG_TUH_MSC -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "ffconf.h" -#include "diskio.h" -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -// TODO change it to portable init -static DSTATUS disk_state[CFG_TUH_DEVICE_MAX]; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ -static DRESULT wait_for_io_complete(uint8_t usb_addr) -{ - // TODO with RTOS, this should use semaphore instead of blocking - while ( !tuh_msc_ready(usb_addr) ) - { - // TODO should have timeout here - #if CFG_TUSB_OS != OPT_OS_NONE - osal_task_delay(10); - #endif - } - - return RES_OK; -} - -void diskio_init(void) -{ - memset(disk_state, STA_NOINIT, CFG_TUH_DEVICE_MAX); -} - -//pdrv Specifies the physical drive number. -DSTATUS disk_initialize ( BYTE pdrv ) -{ - disk_state[pdrv] &= (~STA_NOINIT); // clear NOINIT bit - return disk_state[pdrv]; -} - -void disk_deinitialize ( BYTE pdrv ) -{ - disk_state[pdrv] |= STA_NOINIT; // set NOINIT bit -} - -DSTATUS disk_status (BYTE pdrv) -{ - return disk_state[pdrv]; -} - -//pdrv -// Specifies the physical drive number --> == dev_addr-1 -//buff -// Pointer to the byte array to store the read data. The size of buffer must be in sector size * sector count. -//sector -// Specifies the start sector number in logical block address (LBA). -//count -// Specifies number of sectors to read. The value can be 1 to 128. Generally, a multiple sector transfer request -// must not be split into single sector transactions to the device, or you may not get good read performance. -DRESULT disk_read (BYTE pdrv, BYTE*buff, DWORD sector, BYTE count) -{ - uint8_t usb_addr = pdrv+1; - - if ( TUSB_ERROR_NONE != tuh_msc_read10(usb_addr, 0, buff, sector, count) ) return RES_ERROR; - - return wait_for_io_complete(usb_addr); -} - - -DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, BYTE count) -{ - uint8_t usb_addr = pdrv+1; - - if ( TUSB_ERROR_NONE != tuh_msc_write10(usb_addr, 0, buff, sector, count) ) return RES_ERROR; - - return wait_for_io_complete(usb_addr); -} - -/* [IN] Drive number */ -/* [IN] Control command code */ -/* [I/O] Parameter and data buffer */ -DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff) -{ - (void) buff; (void) pdrv; // compiler warnings - - if (cmd != CTRL_SYNC) return RES_ERROR; - return RES_OK; -} - -static inline uint8_t month2number(char* p_ch) -{ - char const * const month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - - for(uint8_t i=0; i<12; i++) - { - if ( strncmp(p_ch, month_str[i], 3) == 0 ) return i+1; - } - - return 1; -} - -static inline uint8_t c2i(char ch) -{ - return ch - '0'; -} - -DWORD get_fattime (void) -{ - union { - struct { - DWORD second : 5; - DWORD minute : 6; - DWORD hour : 5; - DWORD day_in_month : 5; - DWORD month : 4; - DWORD year : 7; - }; - - DWORD value; - } timestamp; - - //------------- Date is compiled date-------------// - char compile_date[] = __DATE__; // eg. "Sep 26 2013" - char* p_ch; - - p_ch = strtok (compile_date, " "); - timestamp.month = month2number(p_ch); - - p_ch = strtok (NULL, " "); - timestamp.day_in_month = 10*c2i(p_ch[0])+ c2i(p_ch[1]); - - p_ch = strtok (NULL, " "); - timestamp.year = 1000*c2i(p_ch[0]) + 100*c2i(p_ch[1]) + 10*c2i(p_ch[2]) + c2i(p_ch[3]) - 1980; - - //------------- Time each time this function call --> sec ++ -------------// - static uint8_t sec = 0; - static uint8_t min = 0; - static uint8_t hour = 0; - - if (++sec >= 60) - { - sec = 0; - if (++min >= 60) - { - min = 0; - if (++hour >= 24) - { - hour = 0; // assume demo wont call this function more than 24*60*60 times - } - } - } - - timestamp.hour = hour; - timestamp.minute = min; - timestamp.second = sec; - - return timestamp.value; -} - -#endif // CFG_TUH_MSC diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h deleted file mode 100644 index f1f4bd327..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/diskio.h +++ /dev/null @@ -1,95 +0,0 @@ -/*----------------------------------------------------------------------- -/ Low level disk interface modlue include file (C)ChaN, 2013 -/-----------------------------------------------------------------------*/ - -#ifndef _DISKIO_DEFINED -#define _DISKIO_DEFINED - -#ifdef __cplusplus -extern "C" { -#endif - -#define _USE_WRITE 1 /* 1: Enable disk_write function */ -#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */ - -#include "integer.h" -#include - -/* Status of Disk Functions */ -typedef BYTE DSTATUS; - -/* Results of Disk Functions */ -typedef enum { - RES_OK = 0, /* 0: Successful */ - RES_ERROR, /* 1: R/W Error */ - RES_WRPRT, /* 2: Write Protected */ - RES_NOTRDY, /* 3: Not Ready */ - RES_PARERR /* 4: Invalid Parameter */ -} DRESULT; - - -/* Disk Status Bits (DSTATUS) */ -#define STA_NOINIT 0x01 /* Drive not initialized */ -#define STA_NODISK 0x02 /* No medium in the drive */ -#define STA_PROTECT 0x04 /* Write protected */ - - -/* Command code for disk_ioctrl fucntion */ - -/* Generic command (used by FatFs) */ -#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ -#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ -#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ -#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ -#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ - -/* Generic command (not used by FatFs) */ -#define CTRL_POWER 5 /* Get/Set power status */ -#define CTRL_LOCK 6 /* Lock/Unlock media removal */ -#define CTRL_EJECT 7 /* Eject media */ -#define CTRL_FORMAT 8 /* Create physical format on the media */ - -/* MMC/SDC specific ioctl command */ -#define MMC_GET_TYPE 10 /* Get card type */ -#define MMC_GET_CSD 11 /* Get CSD */ -#define MMC_GET_CID 12 /* Get CID */ -#define MMC_GET_OCR 13 /* Get OCR */ -#define MMC_GET_SDSTAT 14 /* Get SD status */ - -/* ATA/CF specific ioctl command */ -#define ATA_GET_REV 20 /* Get F/W revision */ -#define ATA_GET_MODEL 21 /* Get model name */ -#define ATA_GET_SN 22 /* Get serial number */ - - -/* MMC card type flags (MMC_GET_TYPE) */ -#define CT_MMC 0x01 /* MMC ver 3 */ -#define CT_SD1 0x02 /* SD ver 1 */ -#define CT_SD2 0x04 /* SD ver 2 */ -#define CT_SDC (CT_SD1|CT_SD2) /* SD */ -#define CT_BLOCK 0x08 /* Block addressing */ - -/*---------------------------------------*/ -/* Prototypes for disk control functions */ - -void diskio_init(void); -void disk_deinitialize ( BYTE pdrv ); -DSTATUS disk_initialize (BYTE pdrv); -DSTATUS disk_status (BYTE pdrv); -DRESULT disk_read (BYTE pdrv, BYTE*buff, DWORD sector, BYTE count); -DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, BYTE count); -DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); - -static inline bool disk_is_ready(BYTE pdrv); -static inline bool disk_is_ready(BYTE pdrv) -{ - return (pdrv < CFG_TUH_DEVICE_MAX) && - ( (disk_status(pdrv) & (STA_NOINIT | STA_NODISK)) == 0 ); -} - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c deleted file mode 100644 index 79414af07..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.c +++ /dev/null @@ -1,4330 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ FatFs - FAT file system module R0.09b (C)ChaN, 2013 -/-----------------------------------------------------------------------------/ -/ FatFs module is a generic FAT file system module for small embedded systems. -/ This is a free software that opened for education, research and commercial -/ developments under license policy of following terms. -/ -/ Copyright (C) 2013, ChaN, all right reserved. -/ -/ * The FatFs module is a free software and there is NO WARRANTY. -/ * No restriction on use. You can use, modify and redistribute it for -/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. -/ * Redistributions of source code must retain the above copyright notice. -/ -/-----------------------------------------------------------------------------/ -/ Feb 26,'06 R0.00 Prototype. -/ -/ Apr 29,'06 R0.01 First stable version. -/ -/ Jun 01,'06 R0.02 Added FAT12 support. -/ Removed unbuffered mode. -/ Fixed a problem on small (<32M) partition. -/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM). -/ -/ Sep 22,'06 R0.03 Added f_rename(). -/ Changed option _FS_MINIMUM to _FS_MINIMIZE. -/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast. -/ Fixed f_mkdir() creates incorrect directory on FAT32. -/ -/ Feb 04,'07 R0.04 Supported multiple drive system. -/ Changed some interfaces for multiple drive system. -/ Changed f_mountdrv() to f_mount(). -/ Added f_mkfs(). -/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive. -/ Added a capability of extending file size to f_lseek(). -/ Added minimization level 3. -/ Fixed an endian sensitive code in f_mkfs(). -/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG. -/ Added FSInfo support. -/ Fixed DBCS name can result FR_INVALID_NAME. -/ Fixed short seek (<= csize) collapses the file object. -/ -/ Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs(). -/ Fixed f_mkfs() on FAT32 creates incorrect FSInfo. -/ Fixed f_mkdir() on FAT32 creates incorrect directory. -/ Feb 03,'08 R0.05a Added f_truncate() and f_utime(). -/ Fixed off by one error at FAT sub-type determination. -/ Fixed btr in f_read() can be mistruncated. -/ Fixed cached sector is not flushed when create and close without write. -/ -/ Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets(). -/ Improved performance of f_lseek() on moving to the same or following cluster. -/ -/ Apr 01,'09 R0.07 Merged Tiny-FatFs as a configuration option. (_FS_TINY) -/ Added long file name feature. -/ Added multiple code page feature. -/ Added re-entrancy for multitask operation. -/ Added auto cluster size selection to f_mkfs(). -/ Added rewind option to f_readdir(). -/ Changed result code of critical errors. -/ Renamed string functions to avoid name collision. -/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg. -/ Added multiple sector size feature. -/ Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error. -/ Fixed wrong cache control in f_lseek(). -/ Added relative path feature. -/ Added f_chdir() and f_chdrive(). -/ Added proper case conversion to extended char. -/ Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h. -/ Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. -/ Fixed name matching error on the 13 char boundary. -/ Added a configuration option, _LFN_UNICODE. -/ Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. -/ -/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3) -/ Added file lock feature. (_FS_SHARE) -/ Added fast seek feature. (_USE_FASTSEEK) -/ Changed some types on the API, XCHAR->TCHAR. -/ Changed fname member in the FILINFO structure on Unicode cfg. -/ String functions support UTF-8 encoding files on Unicode cfg. -/ Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2) -/ Added sector erase feature. (_USE_ERASE) -/ Moved file lock semaphore table from fs object to the bss. -/ Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. -/ Fixed f_mkfs() creates wrong FAT32 volume. -/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). -/ f_lseek() reports required table size on creating CLMP. -/ Extended format syntax of f_printf function. -/ Ignores duplicated directory separators in given path name. -/ -/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. -/ Added f_fdisk(). (_MULTI_PARTITION = 2) -/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume. -/ Changed f_open() and f_opendir reject null object pointer to avoid crash. -/ Changed option name _FS_SHARE to _FS_LOCK. -/ Jan 24,'13 R0.09b Added f_setlabel() and f_getlabel(). (_USE_LABEL = 1) -/---------------------------------------------------------------------------*/ - -#include "ff.h" /* FatFs configurations and declarations */ -#include "diskio.h" /* Declarations of low level disk I/O functions */ - -#if CFG_TUH_MSC -/*-------------------------------------------------------------------------- - - Module Private Definitions - ----------------------------------------------------------------------------*/ - -#if _FATFS != 82786 /* Revision ID */ -#error Wrong include file (ff.h). -#endif - - -/* Definitions on sector size */ -#if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096 -#error Wrong sector size. -#endif -#if _MAX_SS != 512 -#define SS(fs) ((fs)->ssize) /* Variable sector size */ -#else -#define SS(fs) 512U /* Fixed sector size */ -#endif - - -/* Reentrancy related */ -#if _FS_REENTRANT -#if _USE_LFN == 1 -#error Static LFN work area must not be used in re-entrant configuration. -#endif -#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } -#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } -#else -#define ENTER_FF(fs) -#define LEAVE_FF(fs, res) return res -#endif - -#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } - - -/* File access control feature */ -#if _FS_LOCK -#if _FS_READONLY -#error _FS_LOCK must be 0 on read-only cfg. -#endif -typedef struct { - FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ - DWORD clu; /* File ID 2, directory */ - WORD idx; /* File ID 3, directory index */ - WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */ -} FILESEM; -#endif - - - -/* DBCS code ranges and SBCS extend char conversion table */ - -#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ -#define _DF1S 0x81 /* DBC 1st byte range 1 start */ -#define _DF1E 0x9F /* DBC 1st byte range 1 end */ -#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ -#define _DF2E 0xFC /* DBC 1st byte range 2 end */ -#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ -#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ -#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ -#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ - -#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0x80 -#define _DS2E 0xFE - -#elif _CODE_PAGE == 949 /* Korean */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x41 -#define _DS1E 0x5A -#define _DS2S 0x61 -#define _DS2E 0x7A -#define _DS3S 0x81 -#define _DS3E 0xFE - -#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0xA1 -#define _DS2E 0xFE - -#elif _CODE_PAGE == 437 /* U.S. (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 720 /* Arabic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 737 /* Greek (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ - 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 775 /* Baltic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} - -#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ - 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ - 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 857 /* Turkish (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 866 /* Russian (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} - -#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} - -#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} - -#elif _CODE_PAGE == 1253 /* Greek (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ - 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} - -#elif _CODE_PAGE == 1254 /* Turkish (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} - -#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1256 /* Arabic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1257 /* Baltic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} - -#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} - -#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ -#if _USE_LFN -#error Cannot use LFN feature without valid code page. -#endif -#define _DF1S 0 - -#else -#error Unknown code page - -#endif - - -/* Character code support macros */ -#define IsUpper(c) (((c)>='A')&&((c)<='Z')) -#define IsLower(c) (((c)>='a')&&((c)<='z')) -#define IsDigit(c) (((c)>='0')&&((c)<='9')) - -#if _DF1S /* Code page is DBCS */ - -#ifdef _DF2S /* Two 1st byte areas */ -#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) -#else /* One 1st byte area */ -#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) -#endif - -#ifdef _DS3S /* Three 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) -#else /* Two 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) -#endif - -#else /* Code page is SBCS */ - -#define IsDBCS1(c) 0 -#define IsDBCS2(c) 0 - -#endif /* _DF1S */ - - -/* Name status flags */ -#define NS 11 /* Index of name status byte in fn[] */ -#define NS_LOSS 0x01 /* Out of 8.3 format */ -#define NS_LFN 0x02 /* Force to create LFN entry */ -#define NS_LAST 0x04 /* Last segment */ -#define NS_BODY 0x08 /* Lower case flag (body) */ -#define NS_EXT 0x10 /* Lower case flag (ext) */ -#define NS_DOT 0x20 /* Dot entry */ - - -/* FAT sub-type boundaries */ -/* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */ -#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ -#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ - - -/* FatFs refers the members in the FAT structures as byte array instead of -/ structure member because the structure is not binary compatible between -/ different platforms */ - -#define BS_jmpBoot 0 /* Jump instruction (3) */ -#define BS_OEMName 3 /* OEM name (8) */ -#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */ -#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */ -#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */ -#define BPB_NumFATs 16 /* Number of FAT copies (1) */ -#define BPB_RootEntCnt 17 /* Number of root dir entries for FAT12/16 (2) */ -#define BPB_TotSec16 19 /* Volume size [sector] (2) */ -#define BPB_Media 21 /* Media descriptor (1) */ -#define BPB_FATSz16 22 /* FAT size [sector] (2) */ -#define BPB_SecPerTrk 24 /* Track size [sector] (2) */ -#define BPB_NumHeads 26 /* Number of heads (2) */ -#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */ -#define BPB_TotSec32 32 /* Volume size [sector] (4) */ -#define BS_DrvNum 36 /* Physical drive number (2) */ -#define BS_BootSig 38 /* Extended boot signature (1) */ -#define BS_VolID 39 /* Volume serial number (4) */ -#define BS_VolLab 43 /* Volume label (8) */ -#define BS_FilSysType 54 /* File system type (1) */ -#define BPB_FATSz32 36 /* FAT size [sector] (4) */ -#define BPB_ExtFlags 40 /* Extended flags (2) */ -#define BPB_FSVer 42 /* File system version (2) */ -#define BPB_RootClus 44 /* Root dir first cluster (4) */ -#define BPB_FSInfo 48 /* Offset of FSInfo sector (2) */ -#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */ -#define BS_DrvNum32 64 /* Physical drive number (2) */ -#define BS_BootSig32 66 /* Extended boot signature (1) */ -#define BS_VolID32 67 /* Volume serial number (4) */ -#define BS_VolLab32 71 /* Volume label (8) */ -#define BS_FilSysType32 82 /* File system type (1) */ -#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ -#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ -#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ -#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ -#define MBR_Table 446 /* MBR: Partition table offset (2) */ -#define SZ_PTE 16 /* MBR: Size of a partition table entry */ -#define BS_55AA 510 /* Boot sector signature (2) */ - -#define DIR_Name 0 /* Short file name (11) */ -#define DIR_Attr 11 /* Attribute (1) */ -#define DIR_NTres 12 /* NT flag (1) */ -#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */ -#define DIR_CrtTime 14 /* Created time (2) */ -#define DIR_CrtDate 16 /* Created date (2) */ -#define DIR_LstAccDate 18 /* Last accessed date (2) */ -#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ -#define DIR_WrtTime 22 /* Modified time (2) */ -#define DIR_WrtDate 24 /* Modified date (2) */ -#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */ -#define DIR_FileSize 28 /* File size (4) */ -#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */ -#define LDIR_Attr 11 /* LFN attribute (1) */ -#define LDIR_Type 12 /* LFN type (1) */ -#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */ -#define LDIR_FstClusLO 26 /* Filled by zero (0) */ -#define SZ_DIR 32 /* Size of a directory entry */ -#define LLE 0x40 /* Last long entry flag in LDIR_Ord */ -#define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */ -#define NDDE 0x05 /* Replacement of the character collides with DDE */ - - -/*------------------------------------------------------------*/ -/* Module private work area */ -/*------------------------------------------------------------*/ -/* Note that uninitialized variables with static duration are -/ zeroed/nulled at start-up. If not, the compiler or start-up -/ routine is out of ANSI-C standard. -*/ - -#if _VOLUMES -static -FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ -#else -#error Number of volumes must not be 0. -#endif - -static -WORD Fsid; /* File system mount ID */ - -#if _FS_RPATH -static -BYTE CurrVol; /* Current drive */ -#endif - -#if _FS_LOCK -static -FILESEM Files[_FS_LOCK]; /* File lock semaphores */ -#endif - -#if _USE_LFN == 0 /* No LFN feature */ -#define DEF_NAMEBUF BYTE sfn[12] -#define INIT_BUF(dobj) (dobj).fn = sfn -#define FREE_BUF() - -#elif _USE_LFN == 1 /* LFN feature with static working buffer */ -static WCHAR LfnBuf[_MAX_LFN+1]; -#define DEF_NAMEBUF BYTE sfn[12] -#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } -#define FREE_BUF() - -#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */ -#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] -#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } -#define FREE_BUF() - -#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */ -#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn -#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ - if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ - (dobj).lfn = lfn; (dobj).fn = sfn; } -#define FREE_BUF() ff_memfree(lfn) - -#else -#error Wrong LFN configuration. -#endif - - -#ifdef _EXCVT -static -const BYTE ExCvt[] = _EXCVT; /* Upper conversion table for extended chars */ -#endif - - - - - - -/*-------------------------------------------------------------------------- - - Module Private Functions - ----------------------------------------------------------------------------*/ - - -/*-----------------------------------------------------------------------*/ -/* String functions */ -/*-----------------------------------------------------------------------*/ - -/* Copy memory to memory */ -static -void mem_cpy (void* dst, const void* src, UINT cnt) { - BYTE *d = (BYTE*)dst; - const BYTE *s = (const BYTE*)src; - -#if _WORD_ACCESS == 1 - while (cnt >= sizeof (int)) { - *(int*)d = *(int*)s; - d += sizeof (int); s += sizeof (int); - cnt -= sizeof (int); - } -#endif - while (cnt--) - *d++ = *s++; -} - -/* Fill memory */ -static -void mem_set (void* dst, int val, UINT cnt) { - BYTE *d = (BYTE*)dst; - - while (cnt--) - *d++ = (BYTE)val; -} - -/* Compare memory to memory */ -static -int mem_cmp (const void* dst, const void* src, UINT cnt) { - const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; - int r = 0; - - while (cnt-- && (r = *d++ - *s++) == 0) ; - return r; -} - -/* Check if chr is contained in the string */ -static -int chk_chr (const char* str, int chr) { - while (*str && *str != chr) str++; - return *str; -} - - - -/*-----------------------------------------------------------------------*/ -/* Request/Release grant to access the volume */ -/*-----------------------------------------------------------------------*/ -#if _FS_REENTRANT - -static -int lock_fs ( - FATFS *fs /* File system object */ -) -{ - return ff_req_grant(fs->sobj); -} - - -static -void unlock_fs ( - FATFS *fs, /* File system object */ - FRESULT res /* Result code to be returned */ -) -{ - if (fs && - res != FR_NOT_ENABLED && - res != FR_INVALID_DRIVE && - res != FR_INVALID_OBJECT && - res != FR_TIMEOUT) { - ff_rel_grant(fs->sobj); - } -} -#endif - - - -/*-----------------------------------------------------------------------*/ -/* File lock control functions */ -/*-----------------------------------------------------------------------*/ -#if _FS_LOCK - -static -FRESULT chk_lock ( /* Check if the file can be accessed */ - DIR* dj, /* Directory object pointing the file to be checked */ - int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ -) -{ - UINT i, be; - - /* Search file semaphore table */ - for (i = be = 0; i < _FS_LOCK; i++) { - if (Files[i].fs) { /* Existing entry */ - if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */ - Files[i].clu == dj->sclust && - Files[i].idx == dj->index) break; - } else { /* Blank entry */ - be++; - } - } - if (i == _FS_LOCK) /* The file is not opened */ - return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ - - /* The file has been opened. Reject any open against writing file and all write mode open */ - return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; -} - - -static -int enq_lock (void) /* Check if an entry is available for a new file */ -{ - UINT i; - - for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; - return (i == _FS_LOCK) ? 0 : 1; -} - - -static -UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */ - DIR* dj, /* Directory object pointing the file to register or increment */ - int acc /* Desired access mode (0:Read, !0:Write) */ -) -{ - UINT i; - - - for (i = 0; i < _FS_LOCK; i++) { /* Find the file */ - if (Files[i].fs == dj->fs && - Files[i].clu == dj->sclust && - Files[i].idx == dj->index) break; - } - - if (i == _FS_LOCK) { /* Not opened. Register it as new. */ - for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; - if (i == _FS_LOCK) return 0; /* No space to register (int err) */ - Files[i].fs = dj->fs; - Files[i].clu = dj->sclust; - Files[i].idx = dj->index; - Files[i].ctr = 0; - } - - if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ - - Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ - - return i + 1; -} - - -static -FRESULT dec_lock ( /* Decrement file open counter */ - UINT i /* Semaphore index */ -) -{ - WORD n; - FRESULT res; - - - if (--i < _FS_LOCK) { - n = Files[i].ctr; - if (n == 0x100) n = 0; - if (n) n--; - Files[i].ctr = n; - if (!n) Files[i].fs = 0; - res = FR_OK; - } else { - res = FR_INT_ERR; - } - return res; -} - - -static -void clear_lock ( /* Clear lock entries of the volume */ - FATFS *fs -) -{ - UINT i; - - for (i = 0; i < _FS_LOCK; i++) { - if (Files[i].fs == fs) Files[i].fs = 0; - } -} -#endif - - - -/*-----------------------------------------------------------------------*/ -/* Move/Flush disk access window */ -/*-----------------------------------------------------------------------*/ - - -#if !_FS_READONLY -static -FRESULT sync_window ( - FATFS *fs /* File system object */ -) -{ - DWORD wsect; - UINT nf; - - - if (fs->wflag) { /* Write back the sector if it is dirty */ - wsect = fs->winsect; /* Current sector number */ - if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) - return FR_DISK_ERR; - fs->wflag = 0; - if (wsect >= fs->fatbase && wsect < (fs->fatbase + fs->fsize)) { /* In FAT area? */ - for (nf = fs->n_fats; nf >= 2; nf--) { /* Reflect the change to all FAT copies */ - wsect += fs->fsize; - disk_write(fs->drv, fs->win, wsect, 1); - } - } - } - return FR_OK; -} -#endif - - -static -FRESULT move_window ( - FATFS *fs, /* File system object */ - DWORD sector /* Sector number to make appearance in the fs->win[] */ -) -{ - if (sector != fs->winsect) { /* Changed current window */ -#if !_FS_READONLY - if (sync_window(fs) != FR_OK) - return FR_DISK_ERR; -#endif - if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) - return FR_DISK_ERR; - fs->winsect = sector; - } - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Synchronize file system and strage device */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */ - FATFS *fs /* File system object */ -) -{ - FRESULT res; - - - res = sync_window(fs); - if (res == FR_OK) { - /* Update FSInfo sector if needed */ - if (fs->fs_type == FS_FAT32 && fs->fsi_flag) { - fs->winsect = 0; - /* Create FSInfo structure */ - mem_set(fs->win, 0, 512); - ST_WORD(fs->win+BS_55AA, 0xAA55); - ST_DWORD(fs->win+FSI_LeadSig, 0x41615252); - ST_DWORD(fs->win+FSI_StrucSig, 0x61417272); - ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust); - ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust); - /* Write it into the FSInfo sector */ - disk_write(fs->drv, fs->win, fs->fsi_sector, 1); - fs->fsi_flag = 0; - } - /* Make sure that no pending write process in the physical drive */ - if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) - res = FR_DISK_ERR; - } - - return res; -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Get sector# from cluster# */ -/*-----------------------------------------------------------------------*/ - - -DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to be converted */ -) -{ - clst -= 2; - if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ - return clst * fs->csize + fs->database; -} - - - - -/*-----------------------------------------------------------------------*/ -/* FAT access - Read value of a FAT entry */ -/*-----------------------------------------------------------------------*/ - - -DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to get the link information */ -) -{ - UINT wc, bc; - BYTE *p; - - - if (clst < 2 || clst >= fs->n_fatent) /* Check range */ - return 1; - - switch (fs->fs_type) { - case FS_FAT12 : - bc = (UINT)clst; bc += bc / 2; - if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; - wc = fs->win[bc % SS(fs)]; bc++; - if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; - wc |= fs->win[bc % SS(fs)] << 8; - return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); - - case FS_FAT16 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break; - p = &fs->win[clst * 2 % SS(fs)]; - return LD_WORD(p); - - case FS_FAT32 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break; - p = &fs->win[clst * 4 % SS(fs)]; - return LD_DWORD(p) & 0x0FFFFFFF; - } - - return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* FAT access - Change value of a FAT entry */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY - -FRESULT put_fat ( - FATFS *fs, /* File system object */ - DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ - DWORD val /* New value to mark the cluster */ -) -{ - UINT bc; - BYTE *p; - FRESULT res; - - - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - res = FR_INT_ERR; - - } else { - switch (fs->fs_type) { - case FS_FAT12 : - bc = (UINT)clst; bc += bc / 2; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = &fs->win[bc % SS(fs)]; - *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; - bc++; - fs->wflag = 1; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = &fs->win[bc % SS(fs)]; - *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); - break; - - case FS_FAT16 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); - if (res != FR_OK) break; - p = &fs->win[clst * 2 % SS(fs)]; - ST_WORD(p, (WORD)val); - break; - - case FS_FAT32 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); - if (res != FR_OK) break; - p = &fs->win[clst * 4 % SS(fs)]; - val |= LD_DWORD(p) & 0xF0000000; - ST_DWORD(p, val); - break; - - default : - res = FR_INT_ERR; - } - fs->wflag = 1; - } - - return res; -} -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* FAT handling - Remove a cluster chain */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -FRESULT remove_chain ( - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to remove a chain from */ -) -{ - FRESULT res; - DWORD nxt; -#if _USE_ERASE - DWORD scl = clst, ecl = clst, rt[2]; -#endif - - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - res = FR_INT_ERR; - - } else { - res = FR_OK; - while (clst < fs->n_fatent) { /* Not a last link? */ - nxt = get_fat(fs, clst); /* Get cluster status */ - if (nxt == 0) break; /* Empty cluster? */ - if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ - if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */ - res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */ - if (res != FR_OK) break; - if (fs->free_clust != 0xFFFFFFFF) { /* Update FSInfo */ - fs->free_clust++; - fs->fsi_flag = 1; - } -#if _USE_ERASE - if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ - ecl = nxt; - } else { /* End of contiguous clusters */ - rt[0] = clust2sect(fs, scl); /* Start sector */ - rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ - disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt); /* Erase the block */ - scl = ecl = nxt; - } -#endif - clst = nxt; /* Next cluster */ - } - } - - return res; -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* FAT handling - Stretch or Create a cluster chain */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ -) -{ - DWORD cs, ncl, scl; - FRESULT res; - - - if (clst == 0) { /* Create a new chain */ - scl = fs->last_clust; /* Get suggested start point */ - if (!scl || scl >= fs->n_fatent) scl = 1; - } - else { /* Stretch the current chain */ - cs = get_fat(fs, clst); /* Check the cluster status */ - if (cs < 2) return 1; /* It is an invalid cluster */ - if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ - scl = clst; - } - - ncl = scl; /* Start cluster */ - for (;;) { - ncl++; /* Next cluster */ - if (ncl >= fs->n_fatent) { /* Wrap around */ - ncl = 2; - if (ncl > scl) return 0; /* No free cluster */ - } - cs = get_fat(fs, ncl); /* Get the cluster status */ - if (cs == 0) break; /* Found a free cluster */ - if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ - return cs; - if (ncl == scl) return 0; /* No free cluster */ - } - - res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */ - if (res == FR_OK && clst != 0) { - res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */ - } - if (res == FR_OK) { - fs->last_clust = ncl; /* Update FSINFO */ - if (fs->free_clust != 0xFFFFFFFF) { - fs->free_clust--; - fs->fsi_flag = 1; - } - } else { - ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; - } - - return ncl; /* Return new cluster number or error code */ -} -#endif /* !_FS_READONLY */ - - - -/*-----------------------------------------------------------------------*/ -/* FAT handling - Convert offset into cluster with link map table */ -/*-----------------------------------------------------------------------*/ - -#if _USE_FASTSEEK -static -DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ - FIL* fp, /* Pointer to the file object */ - DWORD ofs /* File offset to be converted to cluster# */ -) -{ - DWORD cl, ncl, *tbl; - - - tbl = fp->cltbl + 1; /* Top of CLMT */ - cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */ - for (;;) { - ncl = *tbl++; /* Number of cluters in the fragment */ - if (!ncl) return 0; /* End of table? (error) */ - if (cl < ncl) break; /* In this fragment? */ - cl -= ncl; tbl++; /* Next fragment */ - } - return cl + *tbl; /* Return the cluster number */ -} -#endif /* _USE_FASTSEEK */ - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Set directory index */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT dir_sdi ( - DIR *dj, /* Pointer to directory object */ - WORD idx /* Index of directory table */ -) -{ - DWORD clst; - WORD ic; - - - dj->index = idx; - clst = dj->sclust; - if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */ - return FR_INT_ERR; - if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ - clst = dj->fs->dirbase; - - if (clst == 0) { /* Static table (root-dir in FAT12/16) */ - dj->clust = clst; - if (idx >= dj->fs->n_rootdir) /* Index is out of range */ - return FR_INT_ERR; - dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ - } - else { /* Dynamic table (sub-dirs or root-dir in FAT32) */ - ic = SS(dj->fs) / SZ_DIR * dj->fs->csize; /* Entries per cluster */ - while (idx >= ic) { /* Follow cluster chain */ - clst = get_fat(dj->fs, clst); /* Get next cluster */ - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ - if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */ - return FR_INT_ERR; - idx -= ic; - } - dj->clust = clst; - dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ - } - - dj->dir = dj->fs->win + (idx % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; /* Ptr to the entry in the sector */ - - return FR_OK; /* Seek succeeded */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Move directory table index next */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ - DIR *dj, /* Pointer to the directory object */ - int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ -) -{ - DWORD clst; - WORD i; - - - stretch = stretch; /* To suppress warning on read-only cfg. */ - i = dj->index + 1; - if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ - return FR_NO_FILE; - - if (!(i % (SS(dj->fs) / SZ_DIR))) { /* Sector changed? */ - dj->sect++; /* Next sector */ - - if (dj->clust == 0) { /* Static table */ - if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */ - return FR_NO_FILE; - } - else { /* Dynamic table */ - if (((i / (SS(dj->fs) / SZ_DIR)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */ - clst = get_fat(dj->fs, dj->clust); /* Get next cluster */ - if (clst <= 1) return FR_INT_ERR; - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - if (clst >= dj->fs->n_fatent) { /* When it reached end of dynamic table */ -#if !_FS_READONLY - BYTE c; - if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */ - clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */ - if (clst == 0) return FR_DENIED; /* No free cluster */ - if (clst == 1) return FR_INT_ERR; - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - /* Clean-up stretched table */ - if (sync_window(dj->fs)) return FR_DISK_ERR; /* Flush active window */ - mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */ - dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */ - for (c = 0; c < dj->fs->csize; c++) { /* Fill the new cluster with 0 */ - dj->fs->wflag = 1; - if (sync_window(dj->fs)) return FR_DISK_ERR; - dj->fs->winsect++; - } - dj->fs->winsect -= c; /* Rewind window address */ -#else - return FR_NO_FILE; /* Report EOT */ -#endif - } - dj->clust = clst; /* Initialize data for new cluster */ - dj->sect = clust2sect(dj->fs, clst); - } - } - } - - dj->index = i; - dj->dir = dj->fs->win + (i % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Reserve directory entry */ -/*-----------------------------------------------------------------------*/ - -#if !_FS_READONLY -static -FRESULT dir_alloc ( - DIR* dj, /* Pointer to the directory object */ - UINT nent /* Number of contiguous entries to allocate (1-21) */ -) -{ - FRESULT res; - UINT n; - - - res = dir_sdi(dj, 0); - if (res == FR_OK) { - n = 0; - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - if (dj->dir[0] == DDE || dj->dir[0] == 0) { /* Is it a blank entry? */ - if (++n == nent) break; /* A block of contiguous entry is found */ - } else { - n = 0; /* Not a blank entry. Restart to search */ - } - res = dir_next(dj, 1); /* Next entry with table stretch enabled */ - } while (res == FR_OK); - } - return res; -} -#endif - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Load/Store start cluster number */ -/*-----------------------------------------------------------------------*/ - -static -DWORD ld_clust ( - FATFS *fs, /* Pointer to the fs object */ - BYTE *dir /* Pointer to the directory entry */ -) -{ - DWORD cl; - - cl = LD_WORD(dir+DIR_FstClusLO); - if (fs->fs_type == FS_FAT32) - cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16; - - return cl; -} - - -#if !_FS_READONLY -static -void st_clust ( - BYTE *dir, /* Pointer to the directory entry */ - DWORD cl /* Value to be set */ -) -{ - ST_WORD(dir+DIR_FstClusLO, cl); - ST_WORD(dir+DIR_FstClusHI, cl >> 16); -} -#endif - - - -/*-----------------------------------------------------------------------*/ -/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */ -/*-----------------------------------------------------------------------*/ -#if _USE_LFN -static -const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN chars in the directory entry */ - - -static -int cmp_lfn ( /* 1:Matched, 0:Not matched */ - WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ - BYTE *dir /* Pointer to the directory entry containing a part of LFN */ -) -{ - UINT i, s; - WCHAR wc, uc; - - - i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */ - s = 0; wc = 1; - do { - uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ - if (wc) { /* Last char has not been processed */ - wc = ff_wtoupper(uc); /* Convert it to upper case */ - if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */ - return 0; /* Not matched */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } while (++s < 13); /* Repeat until all chars in the entry are checked */ - - if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i]) /* Last segment matched but different length */ - return 0; - - return 1; /* The part of LFN matched */ -} - - - -static -int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ - WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */ - BYTE *dir /* Pointer to the directory entry */ -) -{ - UINT i, s; - WCHAR wc, uc; - - - i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ - - s = 0; wc = 1; - do { - uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ - if (wc) { /* Last char has not been processed */ - if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ - lfnbuf[i++] = wc = uc; /* Store it */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } while (++s < 13); /* Read all character in the entry */ - - if (dir[LDIR_Ord] & LLE) { /* Put terminator if it is the last LFN part */ - if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ - lfnbuf[i] = 0; - } - - return 1; -} - - -#if !_FS_READONLY -static -void fit_lfn ( - const WCHAR *lfnbuf, /* Pointer to the LFN buffer */ - BYTE *dir, /* Pointer to the directory entry */ - BYTE ord, /* LFN order (1-20) */ - BYTE sum /* SFN sum */ -) -{ - UINT i, s; - WCHAR wc; - - - dir[LDIR_Chksum] = sum; /* Set check sum */ - dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ - dir[LDIR_Type] = 0; - ST_WORD(dir+LDIR_FstClusLO, 0); - - i = (ord - 1) * 13; /* Get offset in the LFN buffer */ - s = wc = 0; - do { - if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective char */ - ST_WORD(dir+LfnOfs[s], wc); /* Put it */ - if (!wc) wc = 0xFFFF; /* Padding chars following last char */ - } while (++s < 13); - if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLE; /* Bottom LFN part is the start of LFN sequence */ - dir[LDIR_Ord] = ord; /* Set the LFN order */ -} - -#endif -#endif - - - -/*-----------------------------------------------------------------------*/ -/* Create numbered name */ -/*-----------------------------------------------------------------------*/ -#if _USE_LFN -void gen_numname ( - BYTE *dst, /* Pointer to generated SFN */ - const BYTE *src, /* Pointer to source SFN to be modified */ - const WCHAR *lfn, /* Pointer to LFN */ - WORD seq /* Sequence number */ -) -{ - BYTE ns[8], c; - UINT i, j; - - - mem_cpy(dst, src, 11); - - if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */ - do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn); - } - - /* itoa (hexdecimal) */ - i = 7; - do { - c = (seq % 16) + '0'; - if (c > '9') c += 7; - ns[i--] = c; - seq /= 16; - } while (seq); - ns[i] = '~'; - - /* Append the number */ - for (j = 0; j < i && dst[j] != ' '; j++) { - if (IsDBCS1(dst[j])) { - if (j == i - 1) break; - j++; - } - } - do { - dst[j++] = (i < 8) ? ns[i++] : ' '; - } while (j < 8); -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Calculate sum of an SFN */ -/*-----------------------------------------------------------------------*/ -#if _USE_LFN -static -BYTE sum_sfn ( - const BYTE *dir /* Ptr to directory entry */ -) -{ - BYTE sum = 0; - UINT n = 11; - - do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); - return sum; -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Find an object in the directory */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT dir_find ( - DIR *dj /* Pointer to the directory object linked to the file name */ -) -{ - FRESULT res; - BYTE c, *dir; -#if _USE_LFN - BYTE a, ord, sum; -#endif - - res = dir_sdi(dj, 0); /* Rewind directory object */ - if (res != FR_OK) return res; - -#if _USE_LFN - ord = sum = 0xFF; -#endif - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - dir = dj->dir; /* Ptr to the directory entry of current index */ - c = dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ -#if _USE_LFN /* LFN configuration */ - a = dir[DIR_Attr] & AM_MASK; - if (c == DDE || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ - ord = 0xFF; - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (dj->lfn) { - if (c & LLE) { /* Is it start of LFN sequence? */ - sum = dir[LDIR_Chksum]; - c &= ~LLE; ord = c; /* LFN start order */ - dj->lfn_idx = dj->index; - } - /* Check validity of the LFN entry and compare it with given name */ - ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; - } - } else { /* An SFN entry is found */ - if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */ - ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */ - if (!(dj->fn[NS] & NS_LOSS) && !mem_cmp(dir, dj->fn, 11)) break; /* SFN matched? */ - } - } -#else /* Non LFN configuration */ - if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ - break; -#endif - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK); - - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read an object from the directory */ -/*-----------------------------------------------------------------------*/ -#if _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 -static -FRESULT dir_read ( - DIR *dj, /* Pointer to the directory object */ - int vol /* Filtered by 0:file/dir or 1:volume label */ -) -{ - FRESULT res; - BYTE a, c, *dir; -#if _USE_LFN - BYTE ord = 0xFF, sum = 0xFF; -#endif - - res = FR_NO_FILE; - while (dj->sect) { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - dir = dj->dir; /* Ptr to the directory entry of current index */ - c = dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ - a = dir[DIR_Attr] & AM_MASK; -#if _USE_LFN /* LFN configuration */ - if (c == DDE || (!_FS_RPATH && c == '.') || (a == AM_VOL) != vol) { /* An entry without valid data */ - ord = 0xFF; - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (c & LLE) { /* Is it start of LFN sequence? */ - sum = dir[LDIR_Chksum]; - c &= ~LLE; ord = c; - dj->lfn_idx = dj->index; - } - /* Check LFN validity and capture it */ - ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; - } else { /* An SFN entry is found */ - if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */ - dj->lfn_idx = 0xFFFF; /* It has no LFN. */ - break; - } - } -#else /* Non LFN configuration */ - if (c != DDE && (_FS_RPATH || c != '.') && a != AM_LFN && (a == AM_VOL) == vol) /* Is it a valid entry? */ - break; -#endif - res = dir_next(dj, 0); /* Next entry */ - if (res != FR_OK) break; - } - - if (res != FR_OK) dj->sect = 0; - - return res; -} -#endif /* _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 */ - - - -/*-----------------------------------------------------------------------*/ -/* Register an object to the directory */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ - DIR *dj /* Target directory with object name to be created */ -) -{ - FRESULT res; -#if _USE_LFN /* LFN configuration */ - WORD n, ne; - BYTE sn[12], *fn, sum; - WCHAR *lfn; - - - fn = dj->fn; lfn = dj->lfn; - mem_cpy(sn, fn, 12); - - if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */ - return FR_INVALID_NAME; - - if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ - fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ - for (n = 1; n < 100; n++) { - gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ - res = dir_find(dj); /* Check if the name collides with existing SFN */ - if (res != FR_OK) break; - } - if (n == 100) return FR_DENIED; /* Abort if too many collisions */ - if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ - fn[NS] = sn[NS]; dj->lfn = lfn; - } - - if (sn[NS] & NS_LFN) { /* When LFN is to be created, allocate entries for an SFN + LFNs. */ - for (n = 0; lfn[n]; n++) ; - ne = (n + 25) / 13; - } else { /* Otherwise allocate an entry for an SFN */ - ne = 1; - } - res = dir_alloc(dj, ne); /* Allocate entries */ - - if (res == FR_OK && --ne) { /* Set LFN entry if needed */ - res = dir_sdi(dj, (WORD)(dj->index - ne)); - if (res == FR_OK) { - sum = sum_sfn(dj->fn); /* Sum value of the SFN tied to the LFN */ - do { /* Store LFN entries in bottom first */ - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum); - dj->fs->wflag = 1; - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK && --ne); - } - } -#else /* Non LFN configuration */ - res = dir_alloc(dj, 1); /* Allocate an entry for SFN */ -#endif - - if (res == FR_OK) { /* Set SFN entry */ - res = move_window(dj->fs, dj->sect); - if (res == FR_OK) { - mem_set(dj->dir, 0, SZ_DIR); /* Clean the entry */ - mem_cpy(dj->dir, dj->fn, 11); /* Put SFN */ -#if _USE_LFN - dj->dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */ -#endif - dj->fs->wflag = 1; - } - } - - return res; -} -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Remove an object from the directory */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY && !_FS_MINIMIZE -static -FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ - DIR *dj /* Directory object pointing the entry to be removed */ -) -{ - FRESULT res; -#if _USE_LFN /* LFN configuration */ - WORD i; - - i = dj->index; /* SFN index */ - res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */ - if (res == FR_OK) { - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - *dj->dir = DDE; /* Mark the entry "deleted" */ - dj->fs->wflag = 1; - if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR; - } - -#else /* Non LFN configuration */ - res = dir_sdi(dj, dj->index); - if (res == FR_OK) { - res = move_window(dj->fs, dj->sect); - if (res == FR_OK) { - *dj->dir = DDE; /* Mark the entry "deleted" */ - dj->fs->wflag = 1; - } - } -#endif - - return res; -} -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Pick a segment and create the object name in directory form */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT create_name ( - DIR *dj, /* Pointer to the directory object */ - const TCHAR **path /* Pointer to pointer to the segment in the path string */ -) -{ -#if _USE_LFN /* LFN configuration */ - BYTE b, cf; - WCHAR w, *lfn; - UINT i, ni, si, di; - const TCHAR *p; - - /* Create LFN in Unicode */ - for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ - lfn = dj->lfn; - si = di = 0; - for (;;) { - w = p[si++]; /* Get a character */ - if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ - if (di >= _MAX_LFN) /* Reject too long name */ - return FR_INVALID_NAME; -#if !_LFN_UNICODE - w &= 0xFF; - if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ - b = (BYTE)p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(b)) - return FR_INVALID_NAME; /* Reject invalid sequence */ - w = (w << 8) + b; /* Create a DBC */ - } - w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ - if (!w) return FR_INVALID_NAME; /* Reject invalid code */ -#endif - if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */ - return FR_INVALID_NAME; - lfn[di++] = w; /* Store the Unicode char */ - } - *path = &p[si]; /* Return pointer to the next segment */ - cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ -#if _FS_RPATH - if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */ - (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) { - lfn[di] = 0; - for (i = 0; i < 11; i++) - dj->fn[i] = (i < di) ? '.' : ' '; - dj->fn[i] = cf | NS_DOT; /* This is a dot entry */ - return FR_OK; - } -#endif - while (di) { /* Strip trailing spaces and dots */ - w = lfn[di-1]; - if (w != ' ' && w != '.') break; - di--; - } - if (!di) return FR_INVALID_NAME; /* Reject nul string */ - - lfn[di] = 0; /* LFN is created */ - - /* Create SFN in directory form */ - mem_set(dj->fn, ' ', 11); - for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ - if (si) cf |= NS_LOSS | NS_LFN; - while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ - - b = i = 0; ni = 8; - for (;;) { - w = lfn[si++]; /* Get an LFN char */ - if (!w) break; /* Break on end of the LFN */ - if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ - cf |= NS_LOSS | NS_LFN; continue; - } - - if (i >= ni || si == di) { /* Extension or end of SFN */ - if (ni == 11) { /* Long extension */ - cf |= NS_LOSS | NS_LFN; break; - } - if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ - if (si > di) break; /* No extension */ - si = di; i = 8; ni = 11; /* Enter extension section */ - b <<= 2; continue; - } - - if (w >= 0x80) { /* Non ASCII char */ -#ifdef _EXCVT - w = ff_convert(w, 0); /* Unicode -> OEM code */ - if (w) w = ExCvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ -#else - w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ -#endif - cf |= NS_LFN; /* Force create LFN entry */ - } - - if (_DF1S && w >= 0x100) { /* Double byte char (always false on SBCS cfg) */ - if (i >= ni - 1) { - cf |= NS_LOSS | NS_LFN; i = ni; continue; - } - dj->fn[i++] = (BYTE)(w >> 8); - } else { /* Single byte char */ - if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */ - w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ - } else { - if (IsUpper(w)) { /* ASCII large capital */ - b |= 2; - } else { - if (IsLower(w)) { /* ASCII small capital */ - b |= 1; w -= 0x20; - } - } - } - } - dj->fn[i++] = (BYTE)w; - } - - if (dj->fn[0] == DDE) dj->fn[0] = NDDE; /* If the first char collides with deleted mark, replace it with 0x05 */ - - if (ni == 8) b <<= 2; - if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ - cf |= NS_LFN; - if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended char, NT flags are created */ - if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ - if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ - } - - dj->fn[NS] = cf; /* SFN is created */ - - return FR_OK; - - -#else /* Non-LFN configuration */ - BYTE b, c, d, *sfn; - UINT ni, si, i; - const char *p; - - /* Create file name in directory form */ - for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ - sfn = dj->fn; - mem_set(sfn, ' ', 11); - si = i = b = 0; ni = 8; -#if _FS_RPATH - if (p[si] == '.') { /* Is this a dot entry? */ - for (;;) { - c = (BYTE)p[si++]; - if (c != '.' || si >= 3) break; - sfn[i++] = c; - } - if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; - *path = &p[si]; /* Return pointer to the next segment */ - sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ - return FR_OK; - } -#endif - for (;;) { - c = (BYTE)p[si++]; - if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ - if (c == '.' || i >= ni) { - if (ni != 8 || c != '.') return FR_INVALID_NAME; - i = 8; ni = 11; - b <<= 2; continue; - } - if (c >= 0x80) { /* Extended char? */ - b |= 3; /* Eliminate NT flag */ -#ifdef _EXCVT - c = ExCvt[c - 0x80]; /* To upper extended chars (SBCS cfg) */ -#else -#if !_DF1S - return FR_INVALID_NAME; /* Reject extended chars (ASCII cfg) */ -#endif -#endif - } - if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ - d = (BYTE)p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ - return FR_INVALID_NAME; - sfn[i++] = c; - sfn[i++] = d; - } else { /* Single byte code */ - if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ - return FR_INVALID_NAME; - if (IsUpper(c)) { /* ASCII large capital? */ - b |= 2; - } else { - if (IsLower(c)) { /* ASCII small capital? */ - b |= 1; c -= 0x20; - } - } - sfn[i++] = c; - } - } - *path = &p[si]; /* Return pointer to the next segment */ - c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ - - if (!i) return FR_INVALID_NAME; /* Reject nul string */ - if (sfn[0] == DDE) sfn[0] = NDDE; /* When first char collides with DDE, replace it with 0x05 */ - - if (ni == 8) b <<= 2; - if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ - if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */ - - sfn[NS] = c; /* Store NT flag, File name is created */ - - return FR_OK; -#endif -} - - - - -/*-----------------------------------------------------------------------*/ -/* Get file information from directory entry */ -/*-----------------------------------------------------------------------*/ -#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 -static -void get_fileinfo ( /* No return code */ - DIR *dj, /* Pointer to the directory object */ - FILINFO *fno /* Pointer to the file information to be filled */ -) -{ - UINT i; - BYTE nt, *dir; - TCHAR *p, c; - - - p = fno->fname; - if (dj->sect) { - dir = dj->dir; - nt = dir[DIR_NTres]; /* NT flag */ - for (i = 0; i < 8; i++) { /* Copy name body */ - c = dir[i]; - if (c == ' ') break; - if (c == NDDE) c = (TCHAR)DDE; - if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20; -#if _LFN_UNICODE - if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1])) - c = (c << 8) | dir[++i]; - c = ff_convert(c, 1); - if (!c) c = '?'; -#endif - *p++ = c; - } - if (dir[8] != ' ') { /* Copy name extension */ - *p++ = '.'; - for (i = 8; i < 11; i++) { - c = dir[i]; - if (c == ' ') break; - if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20; -#if _LFN_UNICODE - if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1])) - c = (c << 8) | dir[++i]; - c = ff_convert(c, 1); - if (!c) c = '?'; -#endif - *p++ = c; - } - } - fno->fattrib = dir[DIR_Attr]; /* Attribute */ - fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ - fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ - fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ - } - *p = 0; /* Terminate SFN str by a \0 */ - -#if _USE_LFN - if (fno->lfname && fno->lfsize) { - TCHAR *tp = fno->lfname; - WCHAR w, *lfn; - - i = 0; - if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */ - lfn = dj->lfn; - while ((w = *lfn++) != 0) { /* Get an LFN char */ -#if !_LFN_UNICODE - w = ff_convert(w, 0); /* Unicode -> OEM conversion */ - if (!w) { i = 0; break; } /* Could not convert, no LFN */ - if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ - tp[i++] = (TCHAR)(w >> 8); -#endif - if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overflow, no LFN */ - tp[i++] = (TCHAR)w; - } - } - tp[i] = 0; /* Terminate the LFN str by a \0 */ - } -#endif -} -#endif /* _FS_MINIMIZE <= 1 || _FS_RPATH >= 2*/ - - - - -/*-----------------------------------------------------------------------*/ -/* Follow a file path */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ - DIR *dj, /* Directory object to return last directory and found object */ - const TCHAR *path /* Full-path string to find a file or directory */ -) -{ - FRESULT res; - BYTE *dir, ns; - - -#if _FS_RPATH - if (*path == '/' || *path == '\\') { /* There is a heading separator */ - path++; dj->sclust = 0; /* Strip it and start from the root dir */ - } else { /* No heading separator */ - dj->sclust = dj->fs->cdir; /* Start from the current dir */ - } -#else - if (*path == '/' || *path == '\\') /* Strip heading separator if exist */ - path++; - dj->sclust = 0; /* Start from the root dir */ -#endif - - if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ - res = dir_sdi(dj, 0); - dj->dir = 0; - } else { /* Follow path */ - for (;;) { - res = create_name(dj, &path); /* Get a segment */ - if (res != FR_OK) break; - res = dir_find(dj); /* Find it */ - ns = *(dj->fn+NS); - if (res != FR_OK) { /* Failed to find the object */ - if (res != FR_NO_FILE) break; /* Abort if any hard error occurred */ - /* Object not found */ - if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */ - dj->sclust = 0; dj->dir = 0; /* It is the root dir */ - res = FR_OK; - if (!(ns & NS_LAST)) continue; - } else { /* Could not find the object */ - if (!(ns & NS_LAST)) res = FR_NO_PATH; - } - break; - } - if (ns & NS_LAST) break; /* Last segment match. Function completed. */ - dir = dj->dir; /* There is next segment. Follow the sub directory */ - if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ - res = FR_NO_PATH; break; - } - dj->sclust = ld_clust(dj->fs, dir); - } - } - - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Load a sector and check if it is an FAT Volume Boot Record */ -/*-----------------------------------------------------------------------*/ - -static -BYTE check_fs ( /* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */ - FATFS *fs, /* File system object */ - DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ -) -{ - if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) /* Load boot record */ - return 3; - if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ - return 2; - - if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ - return 0; - if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) - return 0; - - return 1; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Check if the file system object is valid or not */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ - const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ - FATFS **rfs, /* Pointer to pointer to the found file system object */ - BYTE wmode /* !=0: Check write protection for write access */ -) -{ - BYTE fmt, b, pi, *tbl; - UINT vol; - DSTATUS stat; - DWORD bsect, fasize, tsect, sysect, nclst, szbfat; - WORD nrsv; - const TCHAR *p = *path; - FATFS *fs; - - - /* Get logical drive number from the path name */ - vol = p[0] - '0'; /* Is there a drive number? */ - if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ - p += 2; *path = p; /* Return pointer to the path name */ - } else { /* No drive number, use default drive */ -#if _FS_RPATH - vol = CurrVol; /* Use current drive */ -#else - vol = 0; /* Use drive 0 */ -#endif - } - - /* Check if the file system object is valid or not */ - *rfs = 0; - if (vol >= _VOLUMES) /* Is the drive number valid? */ - return FR_INVALID_DRIVE; - fs = FatFs[vol]; /* Get corresponding file system object */ - if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ - - ENTER_FF(fs); /* Lock volume */ - - *rfs = fs; /* Return pointer to the corresponding file system object */ - if (fs->fs_type) { /* If the volume has been mounted */ - stat = disk_status(fs->drv); - if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ - if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */ - return FR_WRITE_PROTECTED; - return FR_OK; /* The file system object is valid */ - } - } - - /* The file system object is not valid. */ - /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ - - fs->fs_type = 0; /* Clear the file system object */ - fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->drv); /* Initialize the physical drive */ - if (stat & STA_NOINIT) /* Check if the initialization succeeded */ - return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ - if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */ - return FR_WRITE_PROTECTED; -#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ - if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) - return FR_DISK_ERR; -#endif - /* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */ - fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */ - if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */ - if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */ - /* Check the partition listed in the partition table */ - pi = LD2PT(vol); - if (pi) pi--; - tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */ - if (tbl[4]) { /* Is the partition existing? */ - bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ - fmt = check_fs(fs, bsect); /* Check the partition */ - } - } - if (fmt == 3) return FR_DISK_ERR; - if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ - - /* An FAT volume is found. Following code initializes the file system object */ - - if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ - return FR_NO_FILESYSTEM; - - fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */ - if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32); - fs->fsize = fasize; - - fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */ - if (b != 1 && b != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ - fasize *= b; /* Number of sectors for FAT area */ - - fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ - if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ - - fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */ - if (fs->n_rootdir % (SS(fs) / SZ_DIR)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ - - tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */ - if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32); - - nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */ - if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ - - /* Determine the FAT sub type */ - sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIR); /* RSV+FAT+DIR */ - if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ - if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - fmt = FS_FAT12; - if (nclst >= MIN_FAT16) fmt = FS_FAT16; - if (nclst >= MIN_FAT32) fmt = FS_FAT32; - - /* Boundaries and Limits */ - fs->n_fatent = nclst + 2; /* Number of FAT entries */ - fs->volbase = bsect; /* Volume start sector */ - fs->fatbase = bsect + nrsv; /* FAT start sector */ - fs->database = bsect + sysect; /* Data start sector */ - if (fmt == FS_FAT32) { - if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ - fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */ - szbfat = fs->n_fatent * 4; /* (Required FAT size) */ - } else { - if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ - fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ - szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */ - fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); - } - if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than required) */ - return FR_NO_FILESYSTEM; - -#if !_FS_READONLY - /* Initialize cluster allocation information */ - fs->free_clust = 0xFFFFFFFF; - fs->last_clust = 0; - - /* Get fsinfo if available */ - if (fmt == FS_FAT32) { - fs->fsi_flag = 0; - fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo); - if (disk_read(fs->drv, fs->win, fs->fsi_sector, 1) == RES_OK && - LD_WORD(fs->win+BS_55AA) == 0xAA55 && - LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 && - LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) { - fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free); - fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count); - } - } -#endif - fs->fs_type = fmt; /* FAT sub-type */ - fs->id = ++Fsid; /* File system mount ID */ - fs->winsect = 0; /* Invalidate sector cache */ - fs->wflag = 0; -#if _FS_RPATH - fs->cdir = 0; /* Current directory (root dir) */ -#endif -#if _FS_LOCK /* Clear file lock semaphores */ - clear_lock(fs); -#endif - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Check if the file/dir object is valid or not */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ - void* obj /* Pointer to the object FIL/DIR to check validity */ -) -{ - FIL *fil = (FIL*)obj; /* Assuming offset of fs and id in the FIL/DIR is identical */ - - - if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id) - return FR_INVALID_OBJECT; - - ENTER_FF(fil->fs); /* Lock file system */ - - if (disk_status(fil->fs->drv) & STA_NOINIT) - return FR_NOT_READY; - - return FR_OK; -} - - - - -/*-------------------------------------------------------------------------- - - Public Functions - ---------------------------------------------------------------------------*/ - - - -/*-----------------------------------------------------------------------*/ -/* Mount/Unmount a Logical Drive */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_mount ( - BYTE vol, /* Logical drive number to be mounted/unmounted */ - FATFS *fs /* Pointer to new file system object (NULL for unmount)*/ -) -{ - FATFS *rfs; - - - if (vol >= _VOLUMES) /* Check if the drive number is valid */ - return FR_INVALID_DRIVE; - rfs = FatFs[vol]; /* Get current fs object */ - - if (rfs) { -#if _FS_LOCK - clear_lock(rfs); -#endif -#if _FS_REENTRANT /* Discard sync object of the current volume */ - if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; -#endif - rfs->fs_type = 0; /* Clear old fs object */ - } - - if (fs) { - fs->fs_type = 0; /* Clear new fs object */ -#if _FS_REENTRANT /* Create sync object for the new volume */ - if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR; -#endif - } - FatFs[vol] = fs; /* Register new fs object */ - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Open or Create a File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_open ( - FIL *fp, /* Pointer to the blank file object */ - const TCHAR *path, /* Pointer to the file name */ - BYTE mode /* Access mode and file open mode flags */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; - - - if (!fp) return FR_INVALID_OBJECT; - fp->fs = 0; /* Clear file object */ - -#if !_FS_READONLY - mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; - res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ)); -#else - mode &= FA_READ; - res = chk_mounted(&path, &dj.fs, 0); -#endif - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - dir = dj.dir; -#if !_FS_READONLY /* R/W configuration */ - if (res == FR_OK) { - if (!dir) /* Current dir itself */ - res = FR_INVALID_NAME; -#if _FS_LOCK - else - res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); -#endif - } - /* Create or Open a file */ - if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { - DWORD dw, cl; - - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ -#if _FS_LOCK - res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; -#else - res = dir_register(&dj); -#endif - mode |= FA_CREATE_ALWAYS; /* File is created */ - dir = dj.dir; /* New entry */ - } - else { /* Any object is already existing */ - if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ - res = FR_DENIED; - } else { - if (mode & FA_CREATE_NEW) /* Cannot create as new file */ - res = FR_EXIST; - } - } - if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ - dw = get_fattime(); /* Created time */ - ST_DWORD(dir+DIR_CrtTime, dw); - dir[DIR_Attr] = 0; /* Reset attribute */ - ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ - cl = ld_clust(dj.fs, dir); /* Get start cluster */ - st_clust(dir, 0); /* cluster = 0 */ - dj.fs->wflag = 1; - if (cl) { /* Remove the cluster chain if exist */ - dw = dj.fs->winsect; - res = remove_chain(dj.fs, cl); - if (res == FR_OK) { - dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ - res = move_window(dj.fs, dw); - } - } - } - } - else { /* Open an existing file */ - if (res == FR_OK) { /* Follow succeeded */ - if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ - res = FR_NO_FILE; - } else { - if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ - res = FR_DENIED; - } - } - } - if (res == FR_OK) { - if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ - mode |= FA__WRITTEN; - fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ - fp->dir_ptr = dir; -#if _FS_LOCK - fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); - if (!fp->lockid) res = FR_INT_ERR; -#endif - } - -#else /* R/O configuration */ - if (res == FR_OK) { /* Follow succeeded */ - dir = dj.dir; - if (!dir) { /* Current dir itself */ - res = FR_INVALID_NAME; - } else { - if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ - res = FR_NO_FILE; - } - } -#endif - FREE_BUF(); - - if (res == FR_OK) { - fp->flag = mode; /* File access mode */ - fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */ - fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ - fp->fptr = 0; /* File pointer */ - fp->dsect = 0; -#if _USE_FASTSEEK - fp->cltbl = 0; /* Normal seek mode */ -#endif - fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ - } - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_read ( - FIL *fp, /* Pointer to the file object */ - void *buff, /* Pointer to data buffer */ - UINT btr, /* Number of bytes to read */ - UINT *br /* Pointer to number of bytes read */ -) -{ - FRESULT res; - DWORD clst, sect, remain; - UINT rcnt, cc; - BYTE csect, *rbuff = (BYTE*)buff; - - - *br = 0; /* Clear read byte counter */ - - res = validate(fp); /* Check validity */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Aborted file? */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_READ)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - remain = fp->fsize - fp->fptr; - if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ - - for ( ; btr; /* Repeat until all data read */ - rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->sclust; /* Follow from the origin */ - } else { /* Middle or end of the file */ -#if _USE_FASTSEEK - if (fp->cltbl) - clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - else -#endif - clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */ - } - if (clst < 2) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->clust = clst; /* Update current cluster */ - } - sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Read maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; - if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ -#if _FS_TINY - if (fp->fs->wflag && fp->fs->winsect - sect < cc) - mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); -#else - if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) - mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); -#endif -#endif - rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ - continue; - } -#if !_FS_TINY - if (fp->dsect != sect) { /* Load data sector if not in cache */ -#if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */ - ABORT(fp->fs, FR_DISK_ERR); - } -#endif - fp->dsect = sect; - } - rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ - if (rcnt > btr) rcnt = btr; -#if _FS_TINY - if (move_window(fp->fs, fp->dsect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ -#else - mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ -#endif - } - - LEAVE_FF(fp->fs, FR_OK); -} - - - - -#if !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Write File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_write ( - FIL *fp, /* Pointer to the file object */ - const void *buff, /* Pointer to the data to be written */ - UINT btw, /* Number of bytes to write */ - UINT *bw /* Pointer to number of bytes written */ -) -{ - FRESULT res; - DWORD clst, sect; - UINT wcnt, cc; - const BYTE *wbuff = (const BYTE*)buff; - BYTE csect; - - - *bw = 0; /* Clear write byte counter */ - - res = validate(fp); /* Check validity */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Aborted file? */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - if ((DWORD)(fp->fsize + btw) < fp->fsize) btw = 0; /* File size cannot reach 4GB */ - - for ( ; btw; /* Repeat until all data written */ - wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->sclust; /* Follow from the origin */ - if (clst == 0) /* When no cluster is allocated, */ - fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ - } else { /* Middle or end of the file */ -#if _USE_FASTSEEK - if (fp->cltbl) - clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - else -#endif - clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */ - } - if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->clust = clst; /* Update current cluster */ - } -#if _FS_TINY - if (fp->fs->winsect == fp->dsect && sync_window(fp->fs)) /* Write-back sector cache */ - ABORT(fp->fs, FR_DISK_ERR); -#else - if (fp->flag & FA__DIRTY) { /* Write-back sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Write maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; - if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#if _FS_TINY - if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ - mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); - fp->fs->wflag = 0; - } -#else - if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ - mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); - fp->flag &= ~FA__DIRTY; - } -#endif - wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ - continue; - } -#if _FS_TINY - if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */ - if (sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR); - fp->fs->winsect = sect; - } -#else - if (fp->dsect != sect) { /* Fill sector cache with file data */ - if (fp->fptr < fp->fsize && - disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - } -#endif - fp->dsect = sect; - } - wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ - if (wcnt > btw) wcnt = btw; -#if _FS_TINY - if (move_window(fp->fs, fp->dsect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ - fp->fs->wflag = 1; -#else - mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ - fp->flag |= FA__DIRTY; -#endif - } - - if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */ - fp->flag |= FA__WRITTEN; /* Set file change flag */ - - LEAVE_FF(fp->fs, FR_OK); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Synchronize the File Object */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_sync ( - FIL *fp /* Pointer to the file object */ -) -{ - FRESULT res; - DWORD tm; - BYTE *dir; - - - res = validate(fp); /* Check validity of the object */ - if (res == FR_OK) { - if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ -#if !_FS_TINY /* Write-back dirty buffer */ - if (fp->flag & FA__DIRTY) { - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - LEAVE_FF(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - /* Update the directory entry */ - res = move_window(fp->fs, fp->dir_sect); - if (res == FR_OK) { - dir = fp->dir_ptr; - dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ - ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ - st_clust(dir, fp->sclust); /* Update start cluster */ - tm = get_fattime(); /* Update updated time */ - ST_DWORD(dir+DIR_WrtTime, tm); - ST_WORD(dir+DIR_LstAccDate, 0); - fp->flag &= ~FA__WRITTEN; - fp->fs->wflag = 1; - res = sync_fs(fp->fs); - } - } - } - - LEAVE_FF(fp->fs, res); -} - -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Close File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_close ( - FIL *fp /* Pointer to the file object to be closed */ -) -{ - FRESULT res; - - -#if _FS_READONLY - res = validate(fp); - { -#if _FS_REENTRANT - FATFS *fs = fp->fs; -#endif - if (res == FR_OK) fp->fs = 0; /* Discard file object */ - LEAVE_FF(fs, res); - } -#else - res = f_sync(fp); /* Flush cached data */ -#if _FS_LOCK - if (res == FR_OK) { /* Decrement open counter */ -#if _FS_REENTRANT - FATFS *fs = fp->fs;; - res = validate(fp); - if (res == FR_OK) { - res = dec_lock(fp->lockid); - unlock_fs(fs, FR_OK); - } -#else - res = dec_lock(fp->lockid); -#endif - } -#endif - if (res == FR_OK) fp->fs = 0; /* Discard file object */ - return res; -#endif -} - - - - -/*-----------------------------------------------------------------------*/ -/* Current Drive/Directory Handlings */ -/*-----------------------------------------------------------------------*/ - -#if _FS_RPATH >= 1 - -FRESULT f_chdrive ( - BYTE drv /* Drive number */ -) -{ - if (drv >= _VOLUMES) return FR_INVALID_DRIVE; - - CurrVol = drv; - - return FR_OK; -} - -BYTE f_get_current_drive(void) -{ - return CurrVol; -} - -FRESULT f_chdir ( - const TCHAR *path /* Pointer to the directory path */ -) -{ - FRESULT res; - DIR dj; - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 0); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the path */ - FREE_BUF(); - if (res == FR_OK) { /* Follow completed */ - if (!dj.dir) { - dj.fs->cdir = dj.sclust; /* Start directory itself */ - } else { - if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ - dj.fs->cdir = ld_clust(dj.fs, dj.dir); - else - res = FR_NO_PATH; /* Reached but a file */ - } - } - if (res == FR_NO_FILE) res = FR_NO_PATH; - } - - LEAVE_FF(dj.fs, res); -} - - -#if _FS_RPATH >= 2 -FRESULT f_getcwd ( - TCHAR *buff, /* Pointer to the directory path */ - UINT len /* Size of path */ -) -{ - FRESULT res; - DIR dj; - UINT i, n; - DWORD ccl; - TCHAR *tp; - FILINFO fno; - DEF_NAMEBUF; - - - *buff = 0; - res = chk_mounted((const TCHAR**)&buff, &dj.fs, 0); /* Get current volume */ - if (res == FR_OK) { - INIT_BUF(dj); - i = len; /* Bottom of buffer (dir stack base) */ - dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */ - while ((ccl = dj.sclust) != 0) { /* Repeat while current dir is a sub-dir */ - res = dir_sdi(&dj, 1); /* Get parent dir */ - if (res != FR_OK) break; - res = dir_read(&dj, 0); - if (res != FR_OK) break; - dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent dir */ - res = dir_sdi(&dj, 0); - if (res != FR_OK) break; - do { /* Find the entry links to the child dir */ - res = dir_read(&dj, 0); - if (res != FR_OK) break; - if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */ - res = dir_next(&dj, 0); - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ - if (res != FR_OK) break; -#if _USE_LFN - fno.lfname = buff; - fno.lfsize = i; -#endif - get_fileinfo(&dj, &fno); /* Get the dir name and push it to the buffer */ - tp = fno.fname; - if (_USE_LFN && *buff) tp = buff; - for (n = 0; tp[n]; n++) ; - if (i < n + 3) { - res = FR_NOT_ENOUGH_CORE; break; - } - while (n) buff[--i] = tp[--n]; - buff[--i] = '/'; - } - tp = buff; - if (res == FR_OK) { - *tp++ = '0' + CurrVol; /* Put drive number */ - *tp++ = ':'; - if (i == len) { /* Root-dir */ - *tp++ = '/'; - } else { /* Sub-dir */ - do /* Add stacked path str */ - *tp++ = buff[i++]; - while (i < len); - } - } - *tp = 0; - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} -#endif /* _FS_RPATH >= 2 */ -#endif /* _FS_RPATH >= 1 */ - - - -#if _FS_MINIMIZE <= 2 -/*-----------------------------------------------------------------------*/ -/* Seek File R/W Pointer */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_lseek ( - FIL *fp, /* Pointer to the file object */ - DWORD ofs /* File pointer from top of file */ -) -{ - FRESULT res; - - - res = validate(fp); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - -#if _USE_FASTSEEK - if (fp->cltbl) { /* Fast seek */ - DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; - - if (ofs == CREATE_LINKMAP) { /* Create CLMT */ - tbl = fp->cltbl; - tlen = *tbl++; ulen = 2; /* Given table size and required table size */ - cl = fp->sclust; /* Top of the chain */ - if (cl) { - do { - /* Get a fragment */ - tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ - do { - pcl = cl; ncl++; - cl = get_fat(fp->fs, cl); - if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); - if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - } while (cl == pcl + 1); - if (ulen <= tlen) { /* Store the length and top of the fragment */ - *tbl++ = ncl; *tbl++ = tcl; - } - } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */ - } - *fp->cltbl = ulen; /* Number of items used */ - if (ulen <= tlen) - *tbl = 0; /* Terminate table */ - else - res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ - - } else { /* Fast seek */ - if (ofs > fp->fsize) /* Clip offset at the file size */ - ofs = fp->fsize; - fp->fptr = ofs; /* Set file pointer */ - if (ofs) { - fp->clust = clmt_clust(fp, ofs - 1); - dsc = clust2sect(fp->fs, fp->clust); - if (!dsc) ABORT(fp->fs, FR_INT_ERR); - dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1); - if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */ -#if !_FS_TINY -#if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */ - ABORT(fp->fs, FR_DISK_ERR); -#endif - fp->dsect = dsc; - } - } - } - } else -#endif - - /* Normal Seek */ - { - DWORD clst, bcs, nsect, ifptr; - - if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ -#if !_FS_READONLY - && !(fp->flag & FA_WRITE) -#endif - ) ofs = fp->fsize; - - ifptr = fp->fptr; - fp->fptr = nsect = 0; - if (ofs) { - bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ - if (ifptr > 0 && - (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ - fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ - ofs -= fp->fptr; - clst = fp->clust; - } else { /* When seek to back cluster, */ - clst = fp->sclust; /* start from the first cluster */ -#if !_FS_READONLY - if (clst == 0) { /* If no cluster chain, create a new chain */ - clst = create_chain(fp->fs, 0); - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->sclust = clst; - } -#endif - fp->clust = clst; - } - if (clst != 0) { - while (ofs > bcs) { /* Cluster following loop */ -#if !_FS_READONLY - if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ - clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */ - if (clst == 0) { /* When disk gets full, clip file size */ - ofs = bcs; break; - } - } else -#endif - clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); - fp->clust = clst; - fp->fptr += bcs; - ofs -= bcs; - } - fp->fptr += ofs; - if (ofs % SS(fp->fs)) { - nsect = clust2sect(fp->fs, clst); /* Current sector */ - if (!nsect) ABORT(fp->fs, FR_INT_ERR); - nsect += ofs / SS(fp->fs); - } - } - } - if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */ -#if !_FS_TINY -#if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */ - ABORT(fp->fs, FR_DISK_ERR); -#endif - fp->dsect = nsect; - } -#if !_FS_READONLY - if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */ - fp->fsize = fp->fptr; - fp->flag |= FA__WRITTEN; - } -#endif - } - - LEAVE_FF(fp->fs, res); -} - - - -#if _FS_MINIMIZE <= 1 -/*-----------------------------------------------------------------------*/ -/* Create a Directory Object */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_opendir ( - DIR *dj, /* Pointer to directory object to create */ - const TCHAR *path /* Pointer to the directory path */ -) -{ - FRESULT res; - FATFS *fs; - DEF_NAMEBUF; - - - if (!dj) return FR_INVALID_OBJECT; - - res = chk_mounted(&path, &dj->fs, 0); - fs = dj->fs; - if (res == FR_OK) { - INIT_BUF(*dj); - res = follow_path(dj, path); /* Follow the path to the directory */ - FREE_BUF(); - if (res == FR_OK) { /* Follow completed */ - if (dj->dir) { /* It is not the root dir */ - if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ - dj->sclust = ld_clust(fs, dj->dir); - } else { /* The object is not a directory */ - res = FR_NO_PATH; - } - } - if (res == FR_OK) { - dj->id = fs->id; - res = dir_sdi(dj, 0); /* Rewind dir */ - } - } - if (res == FR_NO_FILE) res = FR_NO_PATH; - if (res != FR_OK) dj->fs = 0; /* Invalidate the dir object if function faild */ - } else { - dj->fs = 0; - } - - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read Directory Entry in Sequence */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_readdir ( - DIR *dj, /* Pointer to the open directory object */ - FILINFO *fno /* Pointer to file information to return */ -) -{ - FRESULT res; - DEF_NAMEBUF; - - - res = validate(dj); /* Check validity of the object */ - if (res == FR_OK) { - if (!fno) { - res = dir_sdi(dj, 0); /* Rewind the directory object */ - } else { - INIT_BUF(*dj); - res = dir_read(dj, 0); /* Read an item */ - if (res == FR_NO_FILE) { /* Reached end of dir */ - dj->sect = 0; - res = FR_OK; - } - if (res == FR_OK) { /* A valid entry is found */ - get_fileinfo(dj, fno); /* Get the object information */ - res = dir_next(dj, 0); /* Increment index for next */ - if (res == FR_NO_FILE) { - dj->sect = 0; - res = FR_OK; - } - } - FREE_BUF(); - } - } - - LEAVE_FF(dj->fs, res); -} - - - -#if _FS_MINIMIZE == 0 -/*-----------------------------------------------------------------------*/ -/* Get File Status */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_stat ( - const TCHAR *path, /* Pointer to the file path */ - FILINFO *fno /* Pointer to file information to return */ -) -{ - FRESULT res; - DIR dj; - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 0); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) { /* Follow completed */ - if (dj.dir) /* Found an object */ - get_fileinfo(&dj, fno); - else /* It is root dir */ - res = FR_INVALID_NAME; - } - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} - - - -#if !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Get Number of Free Clusters */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_getfree ( - const TCHAR *path, /* Path name of the logical drive number */ - DWORD *nclst, /* Pointer to a variable to return number of free clusters */ - FATFS **fatfs /* Pointer to return pointer to corresponding file system object */ -) -{ - FRESULT res; - FATFS *fs; - DWORD n, clst, sect, stat; - UINT i; - BYTE fat, *p; - - - /* Get drive number */ - res = chk_mounted(&path, fatfs, 0); - fs = *fatfs; - if (res == FR_OK) { - /* If free_clust is valid, return it without full cluster scan */ - if (fs->free_clust <= fs->n_fatent - 2) { - *nclst = fs->free_clust; - } else { - /* Get number of free clusters */ - fat = fs->fs_type; - n = 0; - if (fat == FS_FAT12) { - clst = 2; - do { - stat = get_fat(fs, clst); - if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } - if (stat == 1) { res = FR_INT_ERR; break; } - if (stat == 0) n++; - } while (++clst < fs->n_fatent); - } else { - clst = fs->n_fatent; - sect = fs->fatbase; - i = 0; p = 0; - do { - if (!i) { - res = move_window(fs, sect++); - if (res != FR_OK) break; - p = fs->win; - i = SS(fs); - } - if (fat == FS_FAT16) { - if (LD_WORD(p) == 0) n++; - p += 2; i -= 2; - } else { - if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; - p += 4; i -= 4; - } - } while (--clst); - } - fs->free_clust = n; - if (fat == FS_FAT32) fs->fsi_flag = 1; - *nclst = n; - } - } - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Truncate File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_truncate ( - FIL *fp /* Pointer to the file object */ -) -{ - FRESULT res; - DWORD ncl; - - - res = validate(fp); /* Check validity of the object */ - if (res == FR_OK) { - if (fp->flag & FA__ERROR) { /* Check abort flag */ - res = FR_INT_ERR; - } else { - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - res = FR_DENIED; - } - } - if (res == FR_OK) { - if (fp->fsize > fp->fptr) { - fp->fsize = fp->fptr; /* Set file size to current R/W point */ - fp->flag |= FA__WRITTEN; - if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ - res = remove_chain(fp->fs, fp->sclust); - fp->sclust = 0; - } else { /* When truncate a part of the file, remove remaining clusters */ - ncl = get_fat(fp->fs, fp->clust); - res = FR_OK; - if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (ncl == 1) res = FR_INT_ERR; - if (res == FR_OK && ncl < fp->fs->n_fatent) { - res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF); - if (res == FR_OK) res = remove_chain(fp->fs, ncl); - } - } - } - if (res != FR_OK) fp->flag |= FA__ERROR; - } - - LEAVE_FF(fp->fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Delete a File or Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_unlink ( - const TCHAR *path /* Pointer to the file or directory path */ -) -{ - FRESULT res; - DIR dj, sdj; - BYTE *dir; - DWORD dclst; - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; /* Cannot remove dot entry */ -#if _FS_LOCK - if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ -#endif - if (res == FR_OK) { /* The object is accessible */ - dir = dj.dir; - if (!dir) { - res = FR_INVALID_NAME; /* Cannot remove the start directory */ - } else { - if (dir[DIR_Attr] & AM_RDO) - res = FR_DENIED; /* Cannot remove R/O object */ - } - dclst = ld_clust(dj.fs, dir); - if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ - if (dclst < 2) { - res = FR_INT_ERR; - } else { - mem_cpy(&sdj, &dj, sizeof (DIR)); /* Check if the sub-dir is empty or not */ - sdj.sclust = dclst; - res = dir_sdi(&sdj, 2); /* Exclude dot entries */ - if (res == FR_OK) { - res = dir_read(&sdj, 0); /* Read an item */ - if (res == FR_OK /* Not empty dir */ -#if _FS_RPATH - || dclst == dj.fs->cdir /* Current dir */ -#endif - ) res = FR_DENIED; - if (res == FR_NO_FILE) res = FR_OK; /* Empty */ - } - } - } - if (res == FR_OK) { - res = dir_remove(&dj); /* Remove the directory entry */ - if (res == FR_OK) { - if (dclst) /* Remove the cluster chain if exist */ - res = remove_chain(dj.fs, dclst); - if (res == FR_OK) res = sync_fs(dj.fs); - } - } - } - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Create a Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_mkdir ( - const TCHAR *path /* Pointer to the directory path */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir, n; - DWORD dsc, dcl, pcl, tm = get_fattime(); - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ - if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_NO_FILE) { /* Can create a new directory */ - dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */ - res = FR_OK; - if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ - if (dcl == 1) res = FR_INT_ERR; - if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (res == FR_OK) /* Flush FAT */ - res = sync_window(dj.fs); - if (res == FR_OK) { /* Initialize the new directory table */ - dsc = clust2sect(dj.fs, dcl); - dir = dj.fs->win; - mem_set(dir, 0, SS(dj.fs)); - mem_set(dir+DIR_Name, ' ', 11); /* Create "." entry */ - dir[DIR_Name] = '.'; - dir[DIR_Attr] = AM_DIR; - ST_DWORD(dir+DIR_WrtTime, tm); - st_clust(dir, dcl); - mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */ - dir[33] = '.'; pcl = dj.sclust; - if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) - pcl = 0; - st_clust(dir+SZ_DIR, pcl); - for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ - dj.fs->winsect = dsc++; - dj.fs->wflag = 1; - res = sync_window(dj.fs); - if (res != FR_OK) break; - mem_set(dir, 0, SS(dj.fs)); - } - } - if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ - if (res != FR_OK) { - remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ - } else { - dir = dj.dir; - dir[DIR_Attr] = AM_DIR; /* Attribute */ - ST_DWORD(dir+DIR_WrtTime, tm); /* Created time */ - st_clust(dir, dcl); /* Table start cluster */ - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Change Attribute */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_chmod ( - const TCHAR *path, /* Pointer to the file path */ - BYTE value, /* Attribute bits */ - BYTE mask /* Attribute mask to change */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - FREE_BUF(); - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_OK) { - dir = dj.dir; - if (!dir) { /* Is it a root directory? */ - res = FR_INVALID_NAME; - } else { /* File or sub directory */ - mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ - dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Change Timestamp */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_utime ( - const TCHAR *path, /* Pointer to the file/directory name */ - const FILINFO *fno /* Pointer to the time stamp to be set */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; - - - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - FREE_BUF(); - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_OK) { - dir = dj.dir; - if (!dir) { /* Root directory */ - res = FR_INVALID_NAME; - } else { /* File or sub-directory */ - ST_WORD(dir+DIR_WrtTime, fno->ftime); - ST_WORD(dir+DIR_WrtDate, fno->fdate); - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Rename File/Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_rename ( - const TCHAR *path_old, /* Pointer to the old name */ - const TCHAR *path_new /* Pointer to the new name */ -) -{ - FRESULT res; - DIR djo, djn; - BYTE buf[21], *dir; - DWORD dw; - DEF_NAMEBUF; - - - res = chk_mounted(&path_old, &djo.fs, 1); - if (res == FR_OK) { - djn.fs = djo.fs; - INIT_BUF(djo); - res = follow_path(&djo, path_old); /* Check old object */ - if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; -#if _FS_LOCK - if (res == FR_OK) res = chk_lock(&djo, 2); -#endif - if (res == FR_OK) { /* Old object is found */ - if (!djo.dir) { /* Is root dir? */ - res = FR_NO_FILE; - } else { - mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ - mem_cpy(&djn, &djo, sizeof (DIR)); /* Check new object */ - res = follow_path(&djn, path_new); - if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ - if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ -/* Start critical section that any interruption can cause a cross-link */ - res = dir_register(&djn); /* Register the new entry */ - if (res == FR_OK) { - dir = djn.dir; /* Copy object information except for name */ - mem_cpy(dir+13, buf+2, 19); - dir[DIR_Attr] = buf[0] | AM_ARC; - djo.fs->wflag = 1; - if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ - dw = clust2sect(djo.fs, ld_clust(djo.fs, dir)); - if (!dw) { - res = FR_INT_ERR; - } else { - res = move_window(djo.fs, dw); - dir = djo.fs->win+SZ_DIR; /* .. entry */ - if (res == FR_OK && dir[1] == '.') { - dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust; - st_clust(dir, dw); - djo.fs->wflag = 1; - } - } - } - if (res == FR_OK) { - res = dir_remove(&djo); /* Remove old entry */ - if (res == FR_OK) - res = sync_fs(djo.fs); - } - } -/* End critical section */ - } - } - } - FREE_BUF(); - } - - LEAVE_FF(djo.fs, res); -} - -#endif /* !_FS_READONLY */ -#endif /* _FS_MINIMIZE == 0 */ -#endif /* _FS_MINIMIZE <= 1 */ -#endif /* _FS_MINIMIZE <= 2 */ - - - -#if _USE_LABEL -/*-----------------------------------------------------------------------*/ -/* Get volume label */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_getlabel ( - const TCHAR* path, /* Path name of the logical drive number */ - TCHAR* label, /* Pointer to a buffer to return the volume label */ - DWORD* sn /* Pointer to a variable to return the volume serial number */ -) -{ - FRESULT res; - DIR dj; - UINT i, j; - - - /* Get logical drive */ - res = chk_mounted(&path, &dj.fs, 0); - - /* Get volume label */ - if (res == FR_OK && label) { - dj.sclust = 0; /* Open root dir */ - res = dir_sdi(&dj, 0); - if (res == FR_OK) { - res = dir_read(&dj, 1); /* Get an entry with AM_VOL */ - if (res == FR_OK) { /* A volume label is exist */ -#if _LFN_UNICODE - WCHAR w; - i = j = 0; - do { - w = (i < 11) ? dj.dir[i++] : ' '; - if (IsDBCS1(w) && i < 11 && IsDBCS2(dj.dir[i])) - w = (w << 8) | dj.dir[i++]; - label[j++] = ff_convert(w, 1); - } while (j < 11); -#else - mem_cpy(label, dj.dir, 11); -#endif - j = 11; - do { - label[j] = 0; - if (!j) break; - } while (label[--j] == ' '); - } - if (res == FR_NO_FILE) { /* No label, return nul string */ - label[0] = 0; - res = FR_OK; - } - } - } - - /* Get volume serial number */ - if (res == FR_OK && sn) { - res = move_window(dj.fs, dj.fs->volbase); - if (res == FR_OK) { - i = dj.fs->fs_type == FS_FAT32 ? BS_VolID32 : BS_VolID; - *sn = LD_DWORD(&dj.fs->win[i]); - } - } - - LEAVE_FF(dj.fs, res); -} - - - -#if !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Set volume label */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_setlabel ( - const TCHAR* label /* Pointer to the volume label to set */ -) -{ - FRESULT res; - DIR dj; - BYTE vn[11]; - UINT i, j, sl; - WCHAR w; - DWORD tm; - - - /* Get logical drive */ - res = chk_mounted(&label, &dj.fs, 1); - if (res) LEAVE_FF(dj.fs, res); - - /* Create a volume label in directory form */ - vn[0] = 0; - for (sl = 0; label[sl]; sl++) ; /* Get name length */ - for ( ; sl && label[sl-1] == ' '; sl--) ; /* Remove trailing spaces */ - if (sl) { /* Create volume label in directory form */ - i = j = 0; - do { -#if _LFN_UNICODE - w = ff_convert(ff_wtoupper(label[i++]), 0); -#else - w = (BYTE)label[i++]; - if (IsDBCS1(w)) - w = (j < 10 && i < sl && IsDBCS2(label[i])) ? (w << 8) | (BYTE)label[i++] : 0; -#if _USE_LFN - w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0); -#else - if (IsLower(w)) w -= 0x20; /* To upper ASCII chars */ -#ifdef _EXCVT - if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended chars (SBCS cfg) */ -#else - if (!_DF1S && w >= 0x80) w = 0; /* Reject extended chars (ASCII cfg) */ -#endif -#endif -#endif - if (!w || chk_chr("\"*+,.:;<=>\?[]|\x7F", w) || j >= (UINT)((w >= 0x100) ? 10 : 11)) /* Reject invalid chars for volume label */ - LEAVE_FF(dj.fs, FR_INVALID_NAME); - if (w >= 0x100) vn[j++] = (BYTE)(w >> 8); - vn[j++] = (BYTE)w; - } while (i < sl); - while (j < 11) vn[j++] = ' '; - } - - /* Set volume label */ - dj.sclust = 0; /* Open root dir */ - res = dir_sdi(&dj, 0); - if (res == FR_OK) { - res = dir_read(&dj, 1); /* Get an entry with AM_VOL */ - if (res == FR_OK) { /* A volume label is found */ - if (vn[0]) { - mem_cpy(dj.dir, vn, 11); /* Change the volume label name */ - tm = get_fattime(); - ST_DWORD(dj.dir+DIR_WrtTime, tm); - } else { - dj.dir[0] = DDE; /* Remove the volume label */ - } - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } else { /* No volume label is found or error */ - if (res == FR_NO_FILE) { - res = FR_OK; - if (vn[0]) { /* Create volume label as new */ - res = dir_alloc(&dj, 1); /* Allocate an entry for volume label */ - if (res == FR_OK) { - mem_set(dj.dir, 0, SZ_DIR); /* Set volume label */ - mem_cpy(dj.dir, vn, 11); - dj.dir[DIR_Attr] = AM_VOL; - tm = get_fattime(); - ST_DWORD(dj.dir+DIR_WrtTime, tm); - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - } - } - } - - LEAVE_FF(dj.fs, res); -} - -#endif /* !_FS_READONLY */ -#endif /* _USE_LABEL */ - - - -/*-----------------------------------------------------------------------*/ -/* Forward data to the stream directly (available on only tiny cfg) */ -/*-----------------------------------------------------------------------*/ -#if _USE_FORWARD && _FS_TINY - -FRESULT f_forward ( - FIL *fp, /* Pointer to the file object */ - UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ - UINT btf, /* Number of bytes to forward */ - UINT *bf /* Pointer to number of bytes forwarded */ -) -{ - FRESULT res; - DWORD remain, clst, sect; - UINT rcnt; - BYTE csect; - - - *bf = 0; /* Clear transfer byte counter */ - - res = validate(fp); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check error flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_READ)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - - remain = fp->fsize - fp->fptr; - if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ - - for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ - fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - if (!csect) { /* On the cluster boundary? */ - clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->sclust : get_fat(fp->fs, fp->clust); - if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->clust = clst; /* Update current cluster */ - } - } - sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - if (move_window(fp->fs, sect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - fp->dsect = sect; - rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */ - if (rcnt > btf) rcnt = btf; - rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt); - if (!rcnt) ABORT(fp->fs, FR_INT_ERR); - } - - LEAVE_FF(fp->fs, FR_OK); -} -#endif /* _USE_FORWARD */ - - - -#if _USE_MKFS && !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Create File System on the Drive */ -/*-----------------------------------------------------------------------*/ -#define N_ROOTDIR 512 /* Number of root dir entries for FAT12/16 */ -#define N_FATS 1 /* Number of FAT copies (1 or 2) */ - - -FRESULT f_mkfs ( - BYTE vol, /* Logical drive number */ - BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ - UINT au /* Allocation unit size [bytes] */ -) -{ - static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; - static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; - BYTE fmt, md, sys, *tbl, pdrv, part; - DWORD n_clst, vs, n, wsect; - UINT i; - DWORD b_vol, b_fat, b_dir, b_data; /* LBA */ - DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ - FATFS *fs; - DSTATUS stat; - - - /* Check mounted drive and clear work area */ - if (vol >= _VOLUMES) return FR_INVALID_DRIVE; - if (sfd > 1) return FR_INVALID_PARAMETER; - if (au & (au - 1)) return FR_INVALID_PARAMETER; - fs = FatFs[vol]; - if (!fs) return FR_NOT_ENABLED; - fs->fs_type = 0; - pdrv = LD2PD(vol); /* Physical drive */ - part = LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/ - - /* Get disk statics */ - stat = disk_initialize(pdrv); - if (stat & STA_NOINIT) return FR_NOT_READY; - if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; -#if _MAX_SS != 512 /* Get disk sector size */ - if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) - return FR_DISK_ERR; -#endif - if (_MULTI_PARTITION && part) { - /* Get partition information from partition table in the MBR */ - if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; - if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; - tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; - if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */ - b_vol = LD_DWORD(tbl+8); /* Volume start sector */ - n_vol = LD_DWORD(tbl+12); /* Volume size */ - } else { - /* Create a partition in this function */ - if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) - return FR_DISK_ERR; - b_vol = (sfd) ? 0 : 63; /* Volume start sector */ - n_vol -= b_vol; /* Volume size */ - } - - if (!au) { /* AU auto selection */ - vs = n_vol / (2000 / (SS(fs) / 512)); - for (i = 0; vs < vst[i]; i++) ; - au = cst[i]; - } - au /= SS(fs); /* Number of sectors per cluster */ - if (au == 0) au = 1; - if (au > 128) au = 128; - - /* Pre-compute number of clusters and FAT sub-type */ - n_clst = n_vol / au; - fmt = FS_FAT12; - if (n_clst >= MIN_FAT16) fmt = FS_FAT16; - if (n_clst >= MIN_FAT32) fmt = FS_FAT32; - - /* Determine offset and size of FAT structure */ - if (fmt == FS_FAT32) { - n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); - n_rsv = 32; - n_dir = 0; - } else { - n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; - n_fat = (n_fat + SS(fs) - 1) / SS(fs); - n_rsv = 1; - n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs); - } - b_fat = b_vol + n_rsv; /* FAT area start sector */ - b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ - b_data = b_dir + n_dir; /* Data area start sector */ - if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ - - /* Align data start sector to erase block boundary (for flash memory media) */ - if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; - n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ - n = (n - b_data) / N_FATS; - if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ - n_rsv += n; - b_fat += n; - } else { /* FAT12/16: Expand FAT size */ - n_fat += n; - } - - /* Determine number of clusters and final check of validity of the FAT sub-type */ - n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; - if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) - || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) - return FR_MKFS_ABORTED; - - switch (fmt) { /* Determine system ID for partition table */ - case FS_FAT12: sys = 0x01; break; - case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break; - default: sys = 0x0C; - } - - if (_MULTI_PARTITION && part) { - /* Update system ID in the partition table */ - tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; - tbl[4] = sys; - if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; - md = 0xF8; - } else { - if (sfd) { /* No partition table (SFD) */ - md = 0xF0; - } else { /* Create partition table (FDISK) */ - mem_set(fs->win, 0, SS(fs)); - tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */ - tbl[1] = 1; /* Partition start head */ - tbl[2] = 1; /* Partition start sector */ - tbl[3] = 0; /* Partition start cylinder */ - tbl[4] = sys; /* System type */ - tbl[5] = 254; /* Partition end head */ - n = (b_vol + n_vol) / 63 / 255; - tbl[6] = (BYTE)((n >> 2) | 63); /* Partition end sector */ - tbl[7] = (BYTE)n; /* End cylinder */ - ST_DWORD(tbl+8, 63); /* Partition start in LBA */ - ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ - ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ - if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */ - return FR_DISK_ERR; - md = 0xF8; - } - } - - /* Create BPB in the VBR */ - tbl = fs->win; /* Clear sector */ - mem_set(tbl, 0, SS(fs)); - mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */ - i = SS(fs); /* Sector size */ - ST_WORD(tbl+BPB_BytsPerSec, i); - tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ - ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ - tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ - i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ - ST_WORD(tbl+BPB_RootEntCnt, i); - if (n_vol < 0x10000) { /* Number of total sectors */ - ST_WORD(tbl+BPB_TotSec16, n_vol); - } else { - ST_DWORD(tbl+BPB_TotSec32, n_vol); - } - tbl[BPB_Media] = md; /* Media descriptor */ - ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ - ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ - ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ - n = get_fattime(); /* Use current time as VSN */ - if (fmt == FS_FAT32) { - ST_DWORD(tbl+BS_VolID32, n); /* VSN */ - ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ - ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ - ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */ - ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ - tbl[BS_DrvNum32] = 0x80; /* Drive number */ - tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ - } else { - ST_DWORD(tbl+BS_VolID, n); /* VSN */ - ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ - tbl[BS_DrvNum] = 0x80; /* Drive number */ - tbl[BS_BootSig] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ - } - ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ - if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */ - return FR_DISK_ERR; - if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */ - disk_write(pdrv, tbl, b_vol + 6, 1); - - /* Initialize FAT area */ - wsect = b_fat; - for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */ - mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ - n = md; /* Media descriptor byte */ - if (fmt != FS_FAT32) { - n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; - ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */ - } else { - n |= 0xFFFFFF00; - ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */ - ST_DWORD(tbl+4, 0xFFFFFFFF); - ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ - } - if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ - for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ - if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - } - } - - /* Initialize root directory */ - i = (fmt == FS_FAT32) ? au : n_dir; - do { - if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - } while (--i); - -#if _USE_ERASE /* Erase data area if needed */ - { - DWORD eb[2]; - - eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; - disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb); - } -#endif - - /* Create FSInfo if needed */ - if (fmt == FS_FAT32) { - ST_DWORD(tbl+FSI_LeadSig, 0x41615252); - ST_DWORD(tbl+FSI_StrucSig, 0x61417272); - ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */ - ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */ - ST_WORD(tbl+BS_55AA, 0xAA55); - disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ - disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ - } - - return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; -} - - -#if _MULTI_PARTITION -/*-----------------------------------------------------------------------*/ -/* Divide Physical Drive */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_fdisk ( - BYTE pdrv, /* Physical drive number */ - const DWORD szt[], /* Pointer to the size table for each partitions */ - void* work /* Pointer to the working buffer */ -) -{ - UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; - BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; - DSTATUS stat; - DWORD sz_disk, sz_part, s_part; - - - stat = disk_initialize(pdrv); - if (stat & STA_NOINIT) return FR_NOT_READY; - if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; - if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; - - /* Determine CHS in the table regardless of the drive geometry */ - for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; - if (n == 256) n--; - e_hd = n - 1; - sz_cyl = 63 * n; - tot_cyl = sz_disk / sz_cyl; - - /* Create partition table */ - mem_set(buf, 0, _MAX_SS); - p = buf + MBR_Table; b_cyl = 0; - for (i = 0; i < 4; i++, p += SZ_PTE) { - p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; - if (!p_cyl) continue; - s_part = (DWORD)sz_cyl * b_cyl; - sz_part = (DWORD)sz_cyl * p_cyl; - if (i == 0) { /* Exclude first track of cylinder 0 */ - s_hd = 1; - s_part += 63; sz_part -= 63; - } else { - s_hd = 0; - } - e_cyl = b_cyl + p_cyl - 1; - if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; - - /* Set partition table */ - p[1] = s_hd; /* Start head */ - p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ - p[3] = (BYTE)b_cyl; /* Start cylinder */ - p[4] = 0x06; /* System type (temporary setting) */ - p[5] = e_hd; /* End head */ - p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ - p[7] = (BYTE)e_cyl; /* End cylinder */ - ST_DWORD(p + 8, s_part); /* Start sector in LBA */ - ST_DWORD(p + 12, sz_part); /* Partition size */ - - /* Next partition */ - b_cyl += p_cyl; - } - ST_WORD(p, 0xAA55); - - /* Write it to the MBR */ - return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK; -} - - -#endif /* _MULTI_PARTITION */ -#endif /* _USE_MKFS && !_FS_READONLY */ - - - - -#if _USE_STRFUNC -/*-----------------------------------------------------------------------*/ -/* Get a string from the file */ -/*-----------------------------------------------------------------------*/ - -TCHAR* f_gets ( - TCHAR* buff, /* Pointer to the string buffer to read */ - int len, /* Size of string buffer (characters) */ - FIL* fp /* Pointer to the file object */ -) -{ - int n = 0; - TCHAR c, *p = buff; - BYTE s[2]; - UINT rc; - - - while (n < len - 1) { /* Read bytes until buffer gets filled */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; /* Break on EOF or error */ - c = s[0]; -#if _LFN_UNICODE /* Read a character in UTF-8 encoding */ - if (c >= 0x80) { - if (c < 0xC0) continue; /* Skip stray trailer */ - if (c < 0xE0) { /* Two-byte sequence */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = ((c & 0x1F) << 6) | (s[0] & 0x3F); - if (c < 0x80) c = '?'; - } else { - if (c < 0xF0) { /* Three-byte sequence */ - f_read(fp, s, 2, &rc); - if (rc != 2) break; - c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F); - if (c < 0x800) c = '?'; - } else { /* Reject four-byte sequence */ - c = '?'; - } - } - } -#endif -#if _USE_STRFUNC >= 2 - if (c == '\r') continue; /* Strip '\r' */ -#endif - *p++ = c; - n++; - if (c == '\n') break; /* Break on EOL */ - } - *p = 0; - return n ? buff : 0; /* When no data read (eof or error), return with error. */ -} - - - -#if !_FS_READONLY -#include -/*-----------------------------------------------------------------------*/ -/* Put a character to the file */ -/*-----------------------------------------------------------------------*/ - -int f_putc ( - TCHAR c, /* A character to be output */ - FIL* fp /* Pointer to the file object */ -) -{ - UINT bw, btw; - BYTE s[3]; - - -#if _USE_STRFUNC >= 2 - if (c == '\n') f_putc ('\r', fp); /* LF -> CRLF conversion */ -#endif - -#if _LFN_UNICODE /* Write the character in UTF-8 encoding */ - if (c < 0x80) { /* 7-bit */ - s[0] = (BYTE)c; - btw = 1; - } else { - if (c < 0x800) { /* 11-bit */ - s[0] = (BYTE)(0xC0 | (c >> 6)); - s[1] = (BYTE)(0x80 | (c & 0x3F)); - btw = 2; - } else { /* 16-bit */ - s[0] = (BYTE)(0xE0 | (c >> 12)); - s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F)); - s[2] = (BYTE)(0x80 | (c & 0x3F)); - btw = 3; - } - } -#else /* Write the character without conversion */ - s[0] = (BYTE)c; - btw = 1; -#endif - f_write(fp, s, btw, &bw); /* Write the char to the file */ - return (bw == btw) ? 1 : EOF; /* Return the result */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Put a string to the file */ -/*-----------------------------------------------------------------------*/ - -int f_puts ( - const TCHAR* str, /* Pointer to the string to be output */ - FIL* fp /* Pointer to the file object */ -) -{ - int n; - - - for (n = 0; *str; str++, n++) { - if (f_putc(*str, fp) == EOF) return EOF; - } - return n; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Put a formatted string to the file */ -/*-----------------------------------------------------------------------*/ - -int f_printf ( - FIL* fp, /* Pointer to the file object */ - const TCHAR* str, /* Pointer to the format string */ - ... /* Optional arguments... */ -) -{ - va_list arp; - BYTE f, r; - UINT i, j, w; - ULONG v; - TCHAR c, d, s[16], *p; - int res, chc, cc; - - - va_start(arp, str); - - for (cc = res = 0; cc != EOF; res += cc) { - c = *str++; - if (c == 0) break; /* End of string */ - if (c != '%') { /* Non escape character */ - cc = f_putc(c, fp); - if (cc != EOF) cc = 1; - continue; - } - w = f = 0; - c = *str++; - if (c == '0') { /* Flag: '0' padding */ - f = 1; c = *str++; - } else { - if (c == '-') { /* Flag: left justified */ - f = 2; c = *str++; - } - } - while (IsDigit(c)) { /* Precision */ - w = w * 10 + c - '0'; - c = *str++; - } - if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ - f |= 4; c = *str++; - } - if (!c) break; - d = c; - if (IsLower(d)) d -= 0x20; - switch (d) { /* Type is... */ - case 'S' : /* String */ - p = va_arg(arp, TCHAR*); - for (j = 0; p[j]; j++) ; - chc = 0; - if (!(f & 2)) { - while (j++ < w) chc += (cc = f_putc(' ', fp)); - } - chc += (cc = f_puts(p, fp)); - while (j++ < w) chc += (cc = f_putc(' ', fp)); - if (cc != EOF) cc = chc; - continue; - case 'C' : /* Character */ - cc = f_putc((TCHAR)va_arg(arp, int), fp); continue; - case 'B' : /* Binary */ - r = 2; break; - case 'O' : /* Octal */ - r = 8; break; - case 'D' : /* Signed decimal */ - case 'U' : /* Unsigned decimal */ - r = 10; break; - case 'X' : /* Hexdecimal */ - r = 16; break; - default: /* Unknown type (pass-through) */ - cc = f_putc(c, fp); continue; - } - - /* Get an argument and put it in numeral */ - v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int)); - if (d == 'D' && (v & 0x80000000)) { - v = 0 - v; - f |= 8; - } - i = 0; - do { - d = (TCHAR)(v % r); v /= r; - if (d > 9) d += (c == 'x') ? 0x27 : 0x07; - s[i++] = d + '0'; - } while (v && i < sizeof s / sizeof s[0]); - if (f & 8) s[i++] = '-'; - j = i; d = (f & 1) ? '0' : ' '; - chc = 0; - while (!(f & 2) && j++ < w) chc += (cc = f_putc(d, fp)); - do chc += (cc = f_putc(s[--i], fp)); while(i); - while (j++ < w) chc += (cc = f_putc(' ', fp)); - if (cc != EOF) cc = chc; - } - - va_end(arp); - return (cc == EOF) ? cc : res; -} - -#endif /* !_FS_READONLY */ -#endif /* _USE_STRFUNC */ - -#endif // CFG_TUH_MSC diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h deleted file mode 100644 index 5c2a611ae..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ff.h +++ /dev/null @@ -1,342 +0,0 @@ -/*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module include file R0.09b (C)ChaN, 2013 -/----------------------------------------------------------------------------/ -/ FatFs module is a generic FAT file system module for small embedded systems. -/ This is a free software that opened for education, research and commercial -/ developments under license policy of following terms. -/ -/ Copyright (C) 2013, ChaN, all right reserved. -/ -/ * The FatFs module is a free software and there is NO WARRANTY. -/ * No restriction on use. You can use, modify and redistribute it for -/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. -/ * Redistributions of source code must retain the above copyright notice. -/ -/----------------------------------------------------------------------------*/ - -#ifndef _FATFS -#define _FATFS 82786 /* Revision ID */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "integer.h" /* Basic integer types */ -#include "ffconf.h" /* FatFs configuration options */ -#include "tusb_config.h" - -#if _FATFS != _FFCONF -#error Wrong configuration file (ffconf.h). -#endif - - - -/* Definitions of volume management */ - -#if _MULTI_PARTITION /* Multiple partition configuration */ -typedef struct { - BYTE pd; /* Physical drive number */ - BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ -} PARTITION; -extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ -#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ -#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ - -#else /* Single partition configuration */ -#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ -#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */ - -#endif - - - -/* Type of path name strings on FatFs API */ - -#if _LFN_UNICODE /* Unicode string */ -#if !_USE_LFN -#error _LFN_UNICODE must be 0 in non-LFN cfg. -#endif -#ifndef _INC_TCHAR -typedef WCHAR TCHAR; -#define _T(x) L ## x -#define _TEXT(x) L ## x -#endif - -#else /* ANSI/OEM string */ -#ifndef _INC_TCHAR -typedef char TCHAR; -#define _T(x) x -#define _TEXT(x) x -#endif - -#endif - - - -/* File system object structure (FATFS) */ - -typedef struct { - BYTE fs_type; /* FAT sub-type (0:Not mounted) */ - BYTE drv; /* Physical drive number */ - BYTE csize; /* Sectors per cluster (1,2,4...128) */ - BYTE n_fats; /* Number of FAT copies (1,2) */ - BYTE wflag; /* win[] dirty flag (1:must be written back) */ - BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ - WORD id; /* File system mount ID */ - WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ -#if _MAX_SS != 512 - WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ -#endif -#if _FS_REENTRANT - _SYNC_t sobj; /* Identifier of sync object */ -#endif -#if !_FS_READONLY - DWORD last_clust; /* Last allocated cluster */ - DWORD free_clust; /* Number of free clusters */ - DWORD fsi_sector; /* fsinfo sector (FAT32) */ -#endif -#if _FS_RPATH - DWORD cdir; /* Current directory start cluster (0:root) */ -#endif - DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ - DWORD fsize; /* Sectors per FAT */ - DWORD volbase; /* Volume start sector */ - DWORD fatbase; /* FAT start sector */ - DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ - DWORD database; /* Data start sector */ - DWORD winsect; /* Current sector appearing in the win[] */ - BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ -} FATFS; - - - -/* File object structure (FIL) */ - -typedef struct { - FATFS* fs; /* Pointer to the related file system object (**do not change order**) */ - WORD id; /* Owner file system mount ID (**do not change order**) */ - BYTE flag; /* File status flags */ - BYTE pad1; - DWORD fptr; /* File read/write pointer (0ed on file open) */ - DWORD fsize; /* File size */ - DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */ - DWORD clust; /* Current cluster of fpter */ - DWORD dsect; /* Current data sector of fpter */ -#if !_FS_READONLY - DWORD dir_sect; /* Sector containing the directory entry */ - BYTE* dir_ptr; /* Pointer to the directory entry in the window */ -#endif -#if _USE_FASTSEEK - DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ -#endif -#if _FS_LOCK - UINT lockid; /* File lock ID (index of file semaphore table Files[]) */ -#endif -#if !_FS_TINY - BYTE buf[_MAX_SS]; /* File data read/write buffer */ -#endif -} FIL; - - - -/* Directory object structure (DIR) */ - -typedef struct { - FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */ - WORD id; /* Owner file system mount ID (**do not change order**) */ - WORD index; /* Current read/write index number */ - DWORD sclust; /* Table start cluster (0:Root dir) */ - DWORD clust; /* Current cluster */ - DWORD sect; /* Current sector */ - BYTE* dir; /* Pointer to the current SFN entry in the win[] */ - BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ -#if _USE_LFN - WCHAR* lfn; /* Pointer to the LFN working buffer */ - WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ -#endif -} DIR; - - - -/* File status structure (FILINFO) */ - -typedef struct { - DWORD fsize; /* File size */ - WORD fdate; /* Last modified date */ - WORD ftime; /* Last modified time */ - BYTE fattrib; /* Attribute */ - TCHAR fname[13]; /* Short file name (8.3 format) */ -#if _USE_LFN - TCHAR* lfname; /* Pointer to the LFN buffer */ - UINT lfsize; /* Size of LFN buffer in TCHAR */ -#endif -} FILINFO; - - - -/* File function return code (FRESULT) */ - -typedef enum { - FR_OK = 0, /* (0) Succeeded */ - FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ - FR_INT_ERR, /* (2) Assertion failed */ - FR_NOT_READY, /* (3) The physical drive cannot work */ - FR_NO_FILE, /* (4) Could not find the file */ - FR_NO_PATH, /* (5) Could not find the path */ - FR_INVALID_NAME, /* (6) The path name format is invalid */ - FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ - FR_EXIST, /* (8) Access denied due to prohibited access */ - FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ - FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ - FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ - FR_NOT_ENABLED, /* (12) The volume has no work area */ - FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ - FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ - FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ - FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ - FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ - FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ - FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ -} FRESULT; - - - -/*--------------------------------------------------------------*/ -/* FatFs module application interface */ - -FRESULT f_mount (BYTE vol, FATFS* fs); /* Mount/Unmount a logical drive */ -FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ -FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */ -FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */ -FRESULT f_close (FIL* fp); /* Close an open file object */ -FRESULT f_opendir (DIR* dj, const TCHAR* path); /* Open an existing directory */ -FRESULT f_readdir (DIR* dj, FILINFO* fno); /* Read a directory item */ -FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ -FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */ -FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ -FRESULT f_truncate (FIL* fp); /* Truncate file */ -FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */ -FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ -FRESULT f_mkdir (const TCHAR* path); /* Create a new directory */ -FRESULT f_chmod (const TCHAR* path, BYTE value, BYTE mask); /* Change attribute of the file/dir */ -FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */ -FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ -FRESULT f_chdrive (BYTE drv); /* Change current drive */ -BYTE f_get_current_drive(void); -FRESULT f_chdir (const TCHAR* path); /* Change current directory */ -FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ -FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* sn); /* Get volume label */ -FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ -FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ -FRESULT f_mkfs (BYTE vol, BYTE sfd, UINT au); /* Create a file system on the drive */ -FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */ -int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ -int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ -int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ -TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ - -#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) -#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) -#define f_tell(fp) ((fp)->fptr) -#define f_size(fp) ((fp)->fsize) - -#ifndef EOF -#define EOF (-1) -#endif - - - - -/*--------------------------------------------------------------*/ -/* Additional user defined functions */ - -/* RTC function */ -#if !_FS_READONLY -DWORD get_fattime (void); -#endif - -/* Unicode support functions */ -#if _USE_LFN /* Unicode - OEM code conversion */ -WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ -WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */ -#if _USE_LFN == 3 /* Memory functions */ -void* ff_memalloc (UINT msize); /* Allocate memory block */ -void ff_memfree (void* mblock); /* Free memory block */ -#endif -#endif - -/* Sync functions */ -#if _FS_REENTRANT -int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */ -int ff_req_grant (_SYNC_t sobj); /* Lock sync object */ -void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */ -int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */ -#endif - - - - -/*--------------------------------------------------------------*/ -/* Flags and offset address */ - - -/* File access control and file status flags (FIL.flag) */ - -#define FA_READ 0x01 -#define FA_OPEN_EXISTING 0x00 -#define FA__ERROR 0x80 - -#if !_FS_READONLY -#define FA_WRITE 0x02 -#define FA_CREATE_NEW 0x04 -#define FA_CREATE_ALWAYS 0x08 -#define FA_OPEN_ALWAYS 0x10 -#define FA__WRITTEN 0x20 -#define FA__DIRTY 0x40 -#endif - - -/* FAT sub type (FATFS.fs_type) */ - -#define FS_FAT12 1 -#define FS_FAT16 2 -#define FS_FAT32 3 - - -/* File attribute bits for directory entry */ - -#define AM_RDO 0x01 /* Read only */ -#define AM_HID 0x02 /* Hidden */ -#define AM_SYS 0x04 /* System */ -#define AM_VOL 0x08 /* Volume label */ -#define AM_LFN 0x0F /* LFN entry */ -#define AM_DIR 0x10 /* Directory */ -#define AM_ARC 0x20 /* Archive */ -#define AM_MASK 0x3F /* Mask of defined bits */ - - -/* Fast seek feature */ -#define CREATE_LINKMAP 0xFFFFFFFF - - - -/*--------------------------------*/ -/* Multi-byte word access macros */ - -#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) -#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) -#else /* Use byte-by-byte access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) -#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _FATFS */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h deleted file mode 100644 index 782057ea4..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/ffconf.h +++ /dev/null @@ -1,193 +0,0 @@ -/*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module configuration file R0.09b (C)ChaN, 2013 -/----------------------------------------------------------------------------/ -/ -/ CAUTION! Do not forget to make clean the project after any changes to -/ the configuration options. -/ -/----------------------------------------------------------------------------*/ -#ifndef _FFCONF -#define _FFCONF 82786 /* Revision ID */ - -#include "tusb_config.h" - -/*---------------------------------------------------------------------------/ -/ Functions and Buffer Configurations -/----------------------------------------------------------------------------*/ - -#define _FS_TINY 0 /* 0:Normal or 1:Tiny */ -/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system -/ object instead of the sector buffer in the individual file object for file -/ data transfer. This reduces memory consumption 512 bytes each file object. */ - - -#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ -/* Setting _FS_READONLY to 1 defines read only configuration. This removes -/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, -/ f_truncate and useless f_getfree. */ - - -#define _FS_MINIMIZE 0 /* 0 to 3 */ -/* The _FS_MINIMIZE option defines minimization level to remove some functions. -/ -/ 0: Full function. -/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename -/ are removed. -/ 2: f_opendir and f_readdir are removed in addition to 1. -/ 3: f_lseek is removed in addition to 2. */ - - -#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */ -/* To enable string functions, set _USE_STRFUNC to 1 or 2. */ - - -#define _USE_MKFS 0 /* 0:Disable or 1:Enable */ -/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ - - -#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ -/* To enable fast seek feature, set _USE_FASTSEEK to 1. */ - - -#define _USE_LABEL 1 /* 0:Disable or 1:Enable */ -/* To enable volume label functions, set _USE_LAVEL to 1 */ - - -#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ -/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ - - -/*---------------------------------------------------------------------------/ -/ Locale and Namespace Configurations -/----------------------------------------------------------------------------*/ - -#define _CODE_PAGE 437 -/* The _CODE_PAGE specifies the OEM code page to be used on the target system. -/ Incorrect setting of the code page can cause a file open failure. -/ -/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows) -/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows) -/ 949 - Korean (DBCS, OEM, Windows) -/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) -/ 1250 - Central Europe (Windows) -/ 1251 - Cyrillic (Windows) -/ 1252 - Latin 1 (Windows) -/ 1253 - Greek (Windows) -/ 1254 - Turkish (Windows) -/ 1255 - Hebrew (Windows) -/ 1256 - Arabic (Windows) -/ 1257 - Baltic (Windows) -/ 1258 - Vietnam (OEM, Windows) -/ 437 - U.S. (OEM) -/ 720 - Arabic (OEM) -/ 737 - Greek (OEM) -/ 775 - Baltic (OEM) -/ 850 - Multilingual Latin 1 (OEM) -/ 858 - Multilingual Latin 1 + Euro (OEM) -/ 852 - Latin 2 (OEM) -/ 855 - Cyrillic (OEM) -/ 866 - Russian (OEM) -/ 857 - Turkish (OEM) -/ 862 - Hebrew (OEM) -/ 874 - Thai (OEM, Windows) -/ 1 - ASCII only (Valid for non LFN cfg.) -*/ - - -#define _USE_LFN 1 /* 0 to 3 */ -#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ -/* The _USE_LFN option switches the LFN support. -/ -/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect. -/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant. -/ 2: Enable LFN with dynamic working buffer on the STACK. -/ 3: Enable LFN with dynamic working buffer on the HEAP. -/ -/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN, -/ Unicode handling functions ff_convert() and ff_wtoupper() must be added -/ to the project. When enable to use heap, memory control functions -/ ff_memalloc() and ff_memfree() must be added to the project. */ - - -#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ -/* To switch the character code set on FatFs API to Unicode, -/ enable LFN feature and set _LFN_UNICODE to 1. */ - - -#define _FS_RPATH 2 /* 0 to 2 */ -/* The _FS_RPATH option configures relative path feature. -/ -/ 0: Disable relative path feature and remove related functions. -/ 1: Enable relative path. f_chdrive() and f_chdir() are available. -/ 2: f_getcwd() is available in addition to 1. -/ -/ Note that output of the f_readdir fnction is affected by this option. */ - - -/*---------------------------------------------------------------------------/ -/ Physical Drive Configurations -/----------------------------------------------------------------------------*/ - -#define _VOLUMES CFG_TUH_DEVICE_MAX -/* Number of volumes (logical drives) to be used. */ - - -#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ -/* Maximum sector size to be handled. -/ Always set 512 for memory card and hard disk but a larger value may be -/ required for on-board flash memory, floppy disk and optical disk. -/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size -/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */ - - -#define _MULTI_PARTITION 0 /* 0:Single partition, 1:Enable multiple partition */ -/* When set to 0, each volume is bound to the same physical drive number and -/ it can mount only first primaly partition. When it is set to 1, each volume -/ is tied to the partitions listed in VolToPart[]. */ - - -#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ -/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command -/ should be added to the disk_ioctl functio. */ - - - -/*---------------------------------------------------------------------------/ -/ System Configurations -/----------------------------------------------------------------------------*/ - -#define _WORD_ACCESS 0 /* 0 or 1 */ -/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS -/ option defines which access method is used to the word data on the FAT volume. -/ -/ 0: Byte-by-byte access. -/ 1: Word access. Do not choose this unless following condition is met. -/ -/ When the byte order on the memory is big-endian or address miss-aligned word -/ access results incorrect behavior, the _WORD_ACCESS must be set to 0. -/ If it is not the case, the value can also be set to 1 to improve the -/ performance and code size. -*/ - - -/* A header file that defines sync object types on the O/S, such as -/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */ - -#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ -#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ -#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ - -/* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module. -/ -/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. -/ 1: Enable reentrancy. Also user provided synchronization handlers, -/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj -/ function must be added to the project. */ - - -#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */ -/* To enable file lock control feature, set _FS_LOCK to 1 or greater. - The value defines how many files can be opened simultaneously. */ - - -#endif /* _FFCONFIG */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h deleted file mode 100644 index f34f56d92..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/fatfs/integer.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-------------------------------------------*/ -/* Integer type definitions for FatFs module */ -/*-------------------------------------------*/ - -#ifndef _INTEGER -#define _INTEGER - -#ifdef _WIN32 /* FatFs development platform */ - -#include -#include - -#else /* Embedded platform */ - -/* These types must be 16-bit, 32-bit or larger integer */ -typedef int INT; -typedef unsigned int UINT; - -/* These types must be 8-bit integer */ -typedef unsigned char UCHAR; -typedef unsigned char BYTE; - -/* These types must be 16-bit integer */ -typedef short SHORT; -typedef unsigned short USHORT; -typedef unsigned short WORD; -typedef unsigned short WCHAR; - -/* These types must be 32-bit integer */ -typedef long LONG; -typedef unsigned long ULONG; -typedef unsigned long DWORD; - -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c deleted file mode 100644 index 590739236..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 by Sergey Fetisov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "dhserver.h" - -/* DHCP message type */ -#define DHCP_DISCOVER 1 -#define DHCP_OFFER 2 -#define DHCP_REQUEST 3 -#define DHCP_DECLINE 4 -#define DHCP_ACK 5 -#define DHCP_NAK 6 -#define DHCP_RELEASE 7 -#define DHCP_INFORM 8 - -/* DHCP options */ -enum DHCP_OPTIONS -{ - DHCP_PAD = 0, - DHCP_SUBNETMASK = 1, - DHCP_ROUTER = 3, - DHCP_DNSSERVER = 6, - DHCP_HOSTNAME = 12, - DHCP_DNSDOMAIN = 15, - DHCP_MTU = 26, - DHCP_BROADCAST = 28, - DHCP_PERFORMROUTERDISC = 31, - DHCP_STATICROUTE = 33, - DHCP_NISDOMAIN = 40, - DHCP_NISSERVER = 41, - DHCP_NTPSERVER = 42, - DHCP_VENDOR = 43, - DHCP_IPADDRESS = 50, - DHCP_LEASETIME = 51, - DHCP_OPTIONSOVERLOADED = 52, - DHCP_MESSAGETYPE = 53, - DHCP_SERVERID = 54, - DHCP_PARAMETERREQUESTLIST = 55, - DHCP_MESSAGE = 56, - DHCP_MAXMESSAGESIZE = 57, - DHCP_RENEWALTIME = 58, - DHCP_REBINDTIME = 59, - DHCP_CLASSID = 60, - DHCP_CLIENTID = 61, - DHCP_USERCLASS = 77, /* RFC 3004 */ - DHCP_FQDN = 81, - DHCP_DNSSEARCH = 119, /* RFC 3397 */ - DHCP_CSR = 121, /* RFC 3442 */ - DHCP_MSCSR = 249, /* MS code for RFC 3442 */ - DHCP_END = 255 -}; - -typedef struct -{ - uint8_t dp_op; /* packet opcode type */ - uint8_t dp_htype; /* hardware addr type */ - uint8_t dp_hlen; /* hardware addr length */ - uint8_t dp_hops; /* gateway hops */ - uint32_t dp_xid; /* transaction ID */ - uint16_t dp_secs; /* seconds since boot began */ - uint16_t dp_flags; - uint8_t dp_ciaddr[4]; /* client IP address */ - uint8_t dp_yiaddr[4]; /* 'your' IP address */ - uint8_t dp_siaddr[4]; /* server IP address */ - uint8_t dp_giaddr[4]; /* gateway IP address */ - uint8_t dp_chaddr[16]; /* client hardware address */ - uint8_t dp_legacy[192]; - uint8_t dp_magic[4]; - uint8_t dp_options[275]; /* options area */ -} DHCP_TYPE; - -DHCP_TYPE dhcp_data; -static struct udp_pcb *pcb = NULL; -static const dhcp_config_t *config = NULL; - -char magic_cookie[] = {0x63,0x82,0x53,0x63}; - -static ip4_addr_t get_ip(const uint8_t *pnt) -{ - ip4_addr_t result; - memcpy(&result, pnt, sizeof(result)); - return result; -} - -static void set_ip(uint8_t *pnt, ip4_addr_t value) -{ - memcpy(pnt, &value.addr, sizeof(value.addr)); -} - -static dhcp_entry_t *entry_by_ip(ip4_addr_t ip) -{ - int i; - for (i = 0; i < config->num_entry; i++) - if (config->entries[i].addr.addr == ip.addr) - return &config->entries[i]; - return NULL; -} - -static dhcp_entry_t *entry_by_mac(uint8_t *mac) -{ - int i; - for (i = 0; i < config->num_entry; i++) - if (memcmp(config->entries[i].mac, mac, 6) == 0) - return &config->entries[i]; - return NULL; -} - -static __inline bool is_vacant(dhcp_entry_t *entry) -{ - return memcmp("\0\0\0\0\0", entry->mac, 6) == 0; -} - -static dhcp_entry_t *vacant_address(void) -{ - int i; - for (i = 0; i < config->num_entry; i++) - if (is_vacant(config->entries + i)) - return config->entries + i; - return NULL; -} - -static __inline void free_entry(dhcp_entry_t *entry) -{ - memset(entry->mac, 0, 6); -} - -uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) -{ - int i = 0; - while ((i + 1) < size) - { - int next = i + attrs[i + 1] + 2; - if (next > size) return NULL; - if (attrs[i] == attr) - return attrs + i; - i = next; - } - return NULL; -} - -int fill_options(void *dest, - uint8_t msg_type, - const char *domain, - ip4_addr_t dns, - int lease_time, - ip4_addr_t serverid, - ip4_addr_t router, - ip4_addr_t subnet) -{ - uint8_t *ptr = (uint8_t *)dest; - /* ACK message type */ - *ptr++ = 53; - *ptr++ = 1; - *ptr++ = msg_type; - - /* dhcp server identifier */ - *ptr++ = DHCP_SERVERID; - *ptr++ = 4; - set_ip(ptr, serverid); - ptr += 4; - - /* lease time */ - *ptr++ = DHCP_LEASETIME; - *ptr++ = 4; - *ptr++ = (lease_time >> 24) & 0xFF; - *ptr++ = (lease_time >> 16) & 0xFF; - *ptr++ = (lease_time >> 8) & 0xFF; - *ptr++ = (lease_time >> 0) & 0xFF; - - /* subnet mask */ - *ptr++ = DHCP_SUBNETMASK; - *ptr++ = 4; - set_ip(ptr, subnet); - ptr += 4; - - /* router */ - if (router.addr != 0) - { - *ptr++ = DHCP_ROUTER; - *ptr++ = 4; - set_ip(ptr, router); - ptr += 4; - } - - /* domain name */ - if (domain != NULL) - { - int len = strlen(domain); - *ptr++ = DHCP_DNSDOMAIN; - *ptr++ = len; - memcpy(ptr, domain, len); - ptr += len; - } - - /* domain name server (DNS) */ - if (dns.addr != 0) - { - *ptr++ = DHCP_DNSSERVER; - *ptr++ = 4; - set_ip(ptr, dns); - ptr += 4; - } - - /* end */ - *ptr++ = DHCP_END; - return ptr - (uint8_t *)dest; -} - -static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - uint8_t *ptr; - dhcp_entry_t *entry; - struct pbuf *pp; - struct netif *netif = netif_get_by_index(p->if_idx); - - (void)arg; - (void)addr; - - unsigned n = p->len; - if (n > sizeof(dhcp_data)) n = sizeof(dhcp_data); - memcpy(&dhcp_data, p->payload, n); - switch (dhcp_data.dp_options[2]) - { - case DHCP_DISCOVER: - entry = entry_by_mac(dhcp_data.dp_chaddr); - if (entry == NULL) entry = vacant_address(); - if (entry == NULL) break; - - dhcp_data.dp_op = 2; /* reply */ - dhcp_data.dp_secs = 0; - dhcp_data.dp_flags = 0; - set_ip(dhcp_data.dp_yiaddr, entry->addr); - memcpy(dhcp_data.dp_magic, magic_cookie, 4); - - memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); - - fill_options(dhcp_data.dp_options, - DHCP_OFFER, - config->domain, - config->dns, - entry->lease, - *netif_ip4_addr(netif), - config->router, - *netif_ip4_netmask(netif)); - - pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); - if (pp == NULL) break; - memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); - udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); - pbuf_free(pp); - break; - - case DHCP_REQUEST: - /* 1. find requested ipaddr in option list */ - ptr = find_dhcp_option(dhcp_data.dp_options, sizeof(dhcp_data.dp_options), DHCP_IPADDRESS); - if (ptr == NULL) break; - if (ptr[1] != 4) break; - ptr += 2; - - /* 2. does hw-address registered? */ - entry = entry_by_mac(dhcp_data.dp_chaddr); - if (entry != NULL) free_entry(entry); - - /* 3. find requested ipaddr */ - entry = entry_by_ip(get_ip(ptr)); - if (entry == NULL) break; - if (!is_vacant(entry)) break; - - /* 4. fill struct fields */ - memcpy(dhcp_data.dp_yiaddr, ptr, 4); - dhcp_data.dp_op = 2; /* reply */ - dhcp_data.dp_secs = 0; - dhcp_data.dp_flags = 0; - memcpy(dhcp_data.dp_magic, magic_cookie, 4); - - /* 5. fill options */ - memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); - - fill_options(dhcp_data.dp_options, - DHCP_ACK, - config->domain, - config->dns, - entry->lease, - *netif_ip4_addr(netif), - config->router, - *netif_ip4_netmask(netif)); - - /* 6. send ACK */ - pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); - if (pp == NULL) break; - memcpy(entry->mac, dhcp_data.dp_chaddr, 6); - memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); - udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); - pbuf_free(pp); - break; - - default: - break; - } - pbuf_free(p); -} - -err_t dhserv_init(const dhcp_config_t *c) -{ - err_t err; - udp_init(); - dhserv_free(); - pcb = udp_new(); - if (pcb == NULL) - return ERR_MEM; - err = udp_bind(pcb, IP_ADDR_ANY, c->port); - if (err != ERR_OK) - { - dhserv_free(); - return err; - } - udp_recv(pcb, udp_recv_proc, NULL); - config = c; - return ERR_OK; -} - -void dhserv_free(void) -{ - if (pcb == NULL) return; - udp_remove(pcb); - pcb = NULL; -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h deleted file mode 100644 index 2a0b15854..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dhserver.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 by Sergey Fetisov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * version: 1.0 demo (7.02.2015) - * brief: tiny dhcp ipv4 server using lwip (pcb) - * ref: https://lists.gnu.org/archive/html/lwip-users/2012-12/msg00016.html - */ - -#ifndef DHSERVER_H -#define DHSERVER_H - -#include -#include -#include -#include -#include "lwip/err.h" -#include "lwip/udp.h" -#include "netif/etharp.h" - -typedef struct dhcp_entry -{ - uint8_t mac[6]; - ip4_addr_t addr; - uint32_t lease; -} dhcp_entry_t; - -typedef struct dhcp_config -{ - ip4_addr_t router; - uint16_t port; - ip4_addr_t dns; - const char *domain; - int num_entry; - dhcp_entry_t *entries; -} dhcp_config_t; - -err_t dhserv_init(const dhcp_config_t *config); -void dhserv_free(void); - -#endif /* DHSERVER_H */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c deleted file mode 100644 index e4e7c3492..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 by Sergey Fetisov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * version: 1.0 demo (7.02.2015) - * brief: tiny dns ipv4 server using lwip (pcb) - */ - -#include "dnserver.h" - -#define DNS_MAX_HOST_NAME_LEN 128 - -static struct udp_pcb *pcb = NULL; -dns_query_proc_t query_proc = NULL; - -#pragma pack(push, 1) -typedef struct -{ -#if BYTE_ORDER == LITTLE_ENDIAN - uint8_t rd: 1, /* Recursion Desired */ - tc: 1, /* Truncation Flag */ - aa: 1, /* Authoritative Answer Flag */ - opcode: 4, /* Operation code */ - qr: 1; /* Query/Response Flag */ - uint8_t rcode: 4, /* Response Code */ - z: 3, /* Zero */ - ra: 1; /* Recursion Available */ -#else - uint8_t qr: 1, /* Query/Response Flag */ - opcode: 4, /* Operation code */ - aa: 1, /* Authoritative Answer Flag */ - tc: 1, /* Truncation Flag */ - rd: 1; /* Recursion Desired */ - uint8_t ra: 1, /* Recursion Available */ - z: 3, /* Zero */ - rcode: 4; /* Response Code */ -#endif -} dns_header_flags_t; - -typedef struct -{ - uint16_t id; - dns_header_flags_t flags; - uint16_t n_record[4]; -} dns_header_t; - -typedef struct dns_answer -{ - uint16_t name; - uint16_t type; - uint16_t Class; - uint32_t ttl; - uint16_t len; - uint32_t addr; -} dns_answer_t; -#pragma pack(pop) - -typedef struct dns_query -{ - char name[DNS_MAX_HOST_NAME_LEN]; - uint16_t type; - uint16_t Class; -} dns_query_t; - -static uint16_t get_uint16(const uint8_t *pnt) -{ - uint16_t result; - memcpy(&result, pnt, sizeof(result)); - return result; -} - -static int parse_next_query(void *data, int size, dns_query_t *query) -{ - int len; - int lables; - uint8_t *ptr; - - len = 0; - lables = 0; - ptr = (uint8_t *)data; - - while (true) - { - uint8_t lable_len; - if (size <= 0) return -1; - lable_len = *ptr++; - size--; - if (lable_len == 0) break; - if (lables > 0) - { - if (len == DNS_MAX_HOST_NAME_LEN) return -2; - query->name[len++] = '.'; - } - if (lable_len > size) return -1; - if (len + lable_len >= DNS_MAX_HOST_NAME_LEN) return -2; - memcpy(&query->name[len], ptr, lable_len); - len += lable_len; - ptr += lable_len; - size -= lable_len; - lables++; - } - - if (size < 4) return -1; - query->name[len] = 0; - query->type = get_uint16(ptr); - ptr += 2; - query->Class = get_uint16(ptr); - ptr += 2; - return ptr - (uint8_t *)data; -} - -static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - int len; - dns_header_t *header; - static dns_query_t query; - struct pbuf *out; - ip4_addr_t host_addr; - dns_answer_t *answer; - - (void)arg; - - if (p->len <= sizeof(dns_header_t)) goto error; - header = (dns_header_t *)p->payload; - if (header->flags.qr != 0) goto error; - if (ntohs(header->n_record[0]) != 1) goto error; - - len = parse_next_query(header + 1, p->len - sizeof(dns_header_t), &query); - if (len < 0) goto error; - if (!query_proc(query.name, &host_addr)) goto error; - - len += sizeof(dns_header_t); - out = pbuf_alloc(PBUF_TRANSPORT, len + 16, PBUF_POOL); - if (out == NULL) goto error; - - memcpy(out->payload, p->payload, len); - header = (dns_header_t *)out->payload; - header->flags.qr = 1; - header->n_record[1] = htons(1); - answer = (struct dns_answer *)((uint8_t *)out->payload + len); - answer->name = htons(0xC00C); - answer->type = htons(1); - answer->Class = htons(1); - answer->ttl = htonl(32); - answer->len = htons(4); - answer->addr = host_addr.addr; - - udp_sendto(upcb, out, addr, port); - pbuf_free(out); - -error: - pbuf_free(p); -} - -err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t qp) -{ - err_t err; - udp_init(); - dnserv_free(); - pcb = udp_new(); - if (pcb == NULL) - return ERR_MEM; - err = udp_bind(pcb, bind, port); - if (err != ERR_OK) - { - dnserv_free(); - return err; - } - udp_recv(pcb, udp_recv_proc, NULL); - query_proc = qp; - return ERR_OK; -} - -void dnserv_free() -{ - if (pcb == NULL) return; - udp_remove(pcb); - pcb = NULL; -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h deleted file mode 100644 index a062e3aa7..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/dnserver.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 by Sergey Fetisov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * version: 1.0 demo (7.02.2015) - * brief: tiny dns ipv4 server using lwip (pcb) - */ - -#ifndef DNSERVER -#define DNSERVER - -#include -#include -#include -#include -#include "lwip/def.h" -#include "lwip/err.h" -#include "lwip/udp.h" -#include "netif/etharp.h" - -typedef bool (*dns_query_proc_t)(const char *name, ip4_addr_t *addr); - -err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t query_proc); -void dnserv_free(void); - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h deleted file mode 100644 index 1c737574c..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/ndis.h +++ /dev/null @@ -1,266 +0,0 @@ -/* This file has been prepared for Doxygen automatic documentation generation.*/ -/*! \file ndis.h *************************************************************** - * - * \brief - * This file contains the possible external configuration of the USB. - * - * \addtogroup usbstick - * - * - ******************************************************************************/ - -/** - \ingroup usbstick - \defgroup RNDIS RNDIS Support - @{ - */ - -/* - * ndis.h - * - * Modified by Colin O'Flynn - * ntddndis.h modified by Benedikt Spranger - * - * Thanks to the cygwin development team, - * espacially to Casper S. Hornstrup - * - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#ifndef _LINUX_NDIS_H -#define _LINUX_NDIS_H - - -#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 -#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A -#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B - -/* from drivers/net/sk98lin/h/skgepnmi.h */ -#define OID_PNP_CAPABILITIES 0xFD010100 -#define OID_PNP_SET_POWER 0xFD010101 -#define OID_PNP_QUERY_POWER 0xFD010102 -#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 -#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 -#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 - -enum NDIS_DEVICE_POWER_STATE { - NdisDeviceStateUnspecified = 0, - NdisDeviceStateD0, - NdisDeviceStateD1, - NdisDeviceStateD2, - NdisDeviceStateD3, - NdisDeviceStateMaximum -}; - -struct NDIS_PM_WAKE_UP_CAPABILITIES { - enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; - enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp; - enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; -}; - -/* NDIS_PNP_CAPABILITIES.Flags constants */ -#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001 -#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 -#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 - -/* -struct NDIS_PNP_CAPABILITIES { - __le32 Flags; - struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; -}; - -struct NDIS_PM_PACKET_PATTERN { - __le32 Priority; - __le32 Reserved; - __le32 MaskSize; - __le32 PatternOffset; - __le32 PatternSize; - __le32 PatternFlags; -}; -*/ - -/* Required Object IDs (OIDs) */ -#define OID_GEN_SUPPORTED_LIST 0x00010101 -#define OID_GEN_HARDWARE_STATUS 0x00010102 -#define OID_GEN_MEDIA_SUPPORTED 0x00010103 -#define OID_GEN_MEDIA_IN_USE 0x00010104 -#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 -#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 -#define OID_GEN_LINK_SPEED 0x00010107 -#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 -#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 -#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A -#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B -#define OID_GEN_VENDOR_ID 0x0001010C -#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D -#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E -#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F -#define OID_GEN_DRIVER_VERSION 0x00010110 -#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 -#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 -#define OID_GEN_MAC_OPTIONS 0x00010113 -#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 -#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 -#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 -#define OID_GEN_SUPPORTED_GUIDS 0x00010117 -#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 -#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 -#define OID_GEN_MACHINE_NAME 0x0001021A -#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B -#define OID_GEN_VLAN_ID 0x0001021C - -/* Optional OIDs */ -#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 -#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 - -/* Required statistics OIDs */ -#define OID_GEN_XMIT_OK 0x00020101 -#define OID_GEN_RCV_OK 0x00020102 -#define OID_GEN_XMIT_ERROR 0x00020103 -#define OID_GEN_RCV_ERROR 0x00020104 -#define OID_GEN_RCV_NO_BUFFER 0x00020105 - -/* Optional statistics OIDs */ -#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 -#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 -#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 -#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 -#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 -#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 -#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 -#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 -#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 -#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A -#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B -#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C -#define OID_GEN_RCV_CRC_ERROR 0x0002020D -#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E -#define OID_GEN_GET_TIME_CAPS 0x0002020F -#define OID_GEN_GET_NETCARD_TIME 0x00020210 -#define OID_GEN_NETCARD_LOAD 0x00020211 -#define OID_GEN_DEVICE_PROFILE 0x00020212 -#define OID_GEN_INIT_TIME_MS 0x00020213 -#define OID_GEN_RESET_COUNTS 0x00020214 -#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215 -#define OID_GEN_FRIENDLY_NAME 0x00020216 -#define OID_GEN_MINIPORT_INFO 0x00020217 -#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218 - -/* IEEE 802.3 (Ethernet) OIDs */ -#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 - -#define OID_802_3_PERMANENT_ADDRESS 0x01010101 -#define OID_802_3_CURRENT_ADDRESS 0x01010102 -#define OID_802_3_MULTICAST_LIST 0x01010103 -#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 -#define OID_802_3_MAC_OPTIONS 0x01010105 -#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 -#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 -#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 -#define OID_802_3_XMIT_DEFERRED 0x01020201 -#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 -#define OID_802_3_RCV_OVERRUN 0x01020203 -#define OID_802_3_XMIT_UNDERRUN 0x01020204 -#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 -#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 -#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 - -/* Wireless LAN OIDs */ -/* Mandatory */ -#define OID_802_11_BSSID 0x0D010101 /* Q S */ -#define OID_802_11_SSID 0x0D010102 /* Q S */ -#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */ -#define OID_802_11_RSSI 0x0D010206 /* Q I */ -#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */ -#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */ -#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */ -#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */ -#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */ -#define OID_802_11_ADD_WEP 0x0D010113 /* S */ -#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */ -#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */ -#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */ -#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */ -#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */ - - - -/* OID_GEN_MINIPORT_INFO constants */ -#define NDIS_MINIPORT_BUS_MASTER 0x00000001 -#define NDIS_MINIPORT_WDM_DRIVER 0x00000002 -#define NDIS_MINIPORT_SG_LIST 0x00000004 -#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008 -#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010 -#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020 -#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040 -#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080 -#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100 -#define NDIS_MINIPORT_IS_NDIS_5 0x00000200 -#define NDIS_MINIPORT_IS_CO 0x00000400 -#define NDIS_MINIPORT_DESERIALIZE 0x00000800 -#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000 -#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000 -#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000 -#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000 -#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000 -#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000 -#define NDIS_MINIPORT_HIDDEN 0x00040000 -#define NDIS_MINIPORT_SWENUM 0x00080000 -#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000 -#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000 -#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000 -#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000 -#define NDIS_MINIPORT_64BITS_DMA 0x01000000 - -#define NDIS_MEDIUM_802_3 0x00000000 -#define NDIS_MEDIUM_802_5 0x00000001 -#define NDIS_MEDIUM_FDDI 0x00000002 -#define NDIS_MEDIUM_WAN 0x00000003 -#define NDIS_MEDIUM_LOCAL_TALK 0x00000004 -#define NDIS_MEDIUM_DIX 0x00000005 -#define NDIS_MEDIUM_ARCENT_RAW 0x00000006 -#define NDIS_MEDIUM_ARCENT_878_2 0x00000007 -#define NDIS_MEDIUM_ATM 0x00000008 -#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009 -#define NDIS_MEDIUM_IRDA 0x0000000A -#define NDIS_MEDIUM_BPC 0x0000000B -#define NDIS_MEDIUM_CO_WAN 0x0000000C -#define NDIS_MEDIUM_1394 0x0000000D - -#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 -#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 -#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 -#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 -#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 -#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 -#define NDIS_PACKET_TYPE_SMT 0x00000040 -#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 -#define NDIS_PACKET_TYPE_GROUP 0x00000100 -#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 -#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 -#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 - -#define NDIS_MEDIA_STATE_CONNECTED 0x00000000 -#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001 - -#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 -#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 -#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 -#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 -#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 -#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 -#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 -#define NDIS_MAC_OPTION_RESERVED 0x80000000 - -#endif /* _LINUX_NDIS_H */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h deleted file mode 100644 index b45860eeb..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_protocol.h +++ /dev/null @@ -1,307 +0,0 @@ -/** - * \file rndis_protocol.h - * RNDIS Defines - * - * \author - * Colin O'Flynn - * - * \addtogroup usbstick - */ - -/* Copyright (c) 2008 Colin O'Flynn - - 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 the copyright holders nor the names of - 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. -*/ - -#ifndef _RNDIS_H -#define _RNDIS_H - -/** - \addtogroup RNDIS - @{ - */ - -#include - -#define RNDIS_MAJOR_VERSION 1 -#define RNDIS_MINOR_VERSION 0 - -#define RNDIS_STATUS_SUCCESS 0X00000000 -#define RNDIS_STATUS_FAILURE 0XC0000001 -#define RNDIS_STATUS_INVALID_DATA 0XC0010015 -#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB -#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B -#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C - - -/* Message set for Connectionless (802.3) Devices */ -#define REMOTE_NDIS_PACKET_MSG 0x00000001 -#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002 -#define REMOTE_NDIS_HALT_MSG 0X00000003 -#define REMOTE_NDIS_QUERY_MSG 0X00000004 -#define REMOTE_NDIS_SET_MSG 0X00000005 -#define REMOTE_NDIS_RESET_MSG 0X00000006 -#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007 -#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008 -#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002 -#define REMOTE_NDIS_QUERY_CMPLT 0X80000004 -#define REMOTE_NDIS_SET_CMPLT 0X80000005 -#define REMOTE_NDIS_RESET_CMPLT 0X80000006 -#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008 - -typedef uint32_t rndis_MessageType_t; -typedef uint32_t rndis_MessageLength_t; -typedef uint32_t rndis_RequestId_t; -typedef uint32_t rndis_MajorVersion_t; -typedef uint32_t rndis_MinorVersion_t; -typedef uint32_t rndis_MaxTransferSize_t; -typedef uint32_t rndis_Status_t; - - -/* Device Flags */ -#define RNDIS_DF_CONNECTIONLESS 0x00000001 -#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 -typedef uint32_t rndis_DeviceFlags_t; - -/* Mediums */ -#define RNDIS_MEDIUM_802_3 0x00000000 -typedef uint32_t rndis_Medium_t; - - -typedef uint32_t rndis_MaxPacketsPerTransfer_t; -typedef uint32_t rndis_PacketAlignmentFactor_t; -typedef uint32_t rndis_AfListOffset_t; -typedef uint32_t rndis_AfListSize_t; - -/*** Remote NDIS Generic Message type ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - } rndis_generic_msg_t; - - -/*** Remote NDIS Initialize Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_MajorVersion_t MajorVersion; - rndis_MinorVersion_t MinorVersion; - rndis_MaxTransferSize_t MaxTransferSize; - } rndis_initialize_msg_t; - -/* Response: */ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Status_t Status; - rndis_MajorVersion_t MajorVersion; - rndis_MinorVersion_t MinorVersion; - rndis_DeviceFlags_t DeviceFlags; - rndis_Medium_t Medium; - rndis_MaxPacketsPerTransfer_t MaxPacketsPerTransfer; - rndis_MaxTransferSize_t MaxTransferSize; - rndis_PacketAlignmentFactor_t PacketAlignmentFactor; - rndis_AfListOffset_t AfListOffset; - rndis_AfListSize_t AfListSize; - } rndis_initialize_cmplt_t; - - -/*** Remote NDIS Halt Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - } rndis_halt_msg_t; - -typedef uint32_t rndis_Oid_t; -typedef uint32_t rndis_InformationBufferLength_t; -typedef uint32_t rndis_InformationBufferOffset_t; -typedef uint32_t rndis_DeviceVcHandle_t; - -/*** Remote NDIS Query Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Oid_t Oid; - rndis_InformationBufferLength_t InformationBufferLength; - rndis_InformationBufferOffset_t InformationBufferOffset; - rndis_DeviceVcHandle_t DeviceVcHandle; - } rndis_query_msg_t; - -/* Response: */ - -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Status_t Status; - rndis_InformationBufferLength_t InformationBufferLength; - rndis_InformationBufferOffset_t InformationBufferOffset; - } rndis_query_cmplt_t; - -/*** Remote NDIS Set Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Oid_t Oid; - rndis_InformationBufferLength_t InformationBufferLength; - rndis_InformationBufferOffset_t InformationBufferOffset; - rndis_DeviceVcHandle_t DeviceVcHandle; - } rndis_set_msg_t; - -/* Response */ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Status_t Status; - }rndis_set_cmplt_t; - -/* Information buffer layout for OID_GEN_RNDIS_CONFIG_PARAMETER */ -typedef uint32_t rndis_ParameterNameOffset_t; -typedef uint32_t rndis_ParameterNameLength_t; -typedef uint32_t rndis_ParameterType_t; -typedef uint32_t rndis_ParameterValueOffset_t; -typedef uint32_t rndis_ParameterValueLength_t; - -#define PARAMETER_TYPE_STRING 2 -#define PARAMETER_TYPE_NUMERICAL 0 - -typedef struct{ - rndis_ParameterNameOffset_t ParameterNameOffset; - rndis_ParameterNameLength_t ParameterNameLength; - rndis_ParameterType_t ParameterType; - rndis_ParameterValueOffset_t ParameterValueOffset; - rndis_ParameterValueLength_t ParameterValueLength; - }rndis_config_parameter_t; - -typedef uint32_t rndis_Reserved_t; - -/*** Remote NDIS Soft Reset Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_Reserved_t Reserved; - } rndis_reset_msg_t; - -typedef uint32_t rndis_AddressingReset_t; - -/* Response: */ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_Status_t Status; - rndis_AddressingReset_t AddressingReset; - } rndis_reset_cmplt_t; - -/*** Remote NDIS Indicate Status Message ***/ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_Status_t Status; - rndis_Status_t StatusBufferLength; - rndis_Status_t StatusBufferOffset; - } rndis_indicate_status_t; - -typedef uint32_t rndis_DiagStatus_t; -typedef uint32_t rndis_ErrorOffset_t; - -typedef struct { - rndis_DiagStatus_t DiagStatus; - rndis_ErrorOffset_t ErrorOffset; - }rndis_diagnostic_info_t; - -/*** Remote NDIS Keepalive Message */ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - }rndis_keepalive_msg_t; - -/* Response: */ -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_RequestId_t RequestId; - rndis_Status_t Status; - }rndis_keepalive_cmplt_t; - -/*** Remote NDIS Data Packet ***/ - -typedef uint32_t rndis_DataOffset_t; -typedef uint32_t rndis_DataLength_t; -typedef uint32_t rndis_OOBDataOffset_t; -typedef uint32_t rndis_OOBDataLength_t; -typedef uint32_t rndis_NumOOBDataElements_t; -typedef uint32_t rndis_PerPacketInfoOffset_t; -typedef uint32_t rndis_PerPacketInfoLength_t; - -typedef struct{ - rndis_MessageType_t MessageType; - rndis_MessageLength_t MessageLength; - rndis_DataOffset_t DataOffset; - rndis_DataLength_t DataLength; - rndis_OOBDataOffset_t OOBDataOffset; - rndis_OOBDataLength_t OOBDataLength; - rndis_NumOOBDataElements_t NumOOBDataElements; - rndis_PerPacketInfoOffset_t PerPacketInfoOffset; - rndis_PerPacketInfoLength_t PerPacketInfoLength; - rndis_DeviceVcHandle_t DeviceVcHandle; - rndis_Reserved_t Reserved; - }rndis_data_packet_t; - -typedef uint32_t rndis_ClassInformationOffset_t; -typedef uint32_t rndis_Size_t; -typedef uint32_t rndis_Type_t; - -typedef struct{ - rndis_Size_t Size; - rndis_Type_t Type; - rndis_ClassInformationOffset_t ClassInformationType; - }rndis_OOB_packet_t; - -#include "ndis.h" - -typedef enum rnids_state_e { - rndis_uninitialized, - rndis_initialized, - rndis_data_initialized - } rndis_state_t; - -typedef struct { - uint32_t txok; - uint32_t rxok; - uint32_t txbad; - uint32_t rxbad; -} usb_eth_stat_t; - -#endif /* _RNDIS_H */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c deleted file mode 100644 index ee611c883..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/lib/networking/rndis_reports.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - The original version of this code was lrndis/usbd_rndis_core.c from https://github.com/fetisov/lrndis - It has since been overhauled to suit this application -*/ - -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 by Sergey Fetisov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "class/net/net_device.h" -#include "rndis_protocol.h" -#include "netif/ethernet.h" - -#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */ -#define RNDIS_VENDOR "TinyUSB" /* NIC vendor name */ - -static const uint8_t *const station_hwaddr = tud_network_mac_address; -static const uint8_t *const permanent_hwaddr = tud_network_mac_address; - -static usb_eth_stat_t usb_eth_stat = { 0, 0, 0, 0 }; -static uint32_t oid_packet_filter = 0x0000000; -static rndis_state_t rndis_state; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t ndis_report[8] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - -static const uint32_t OIDSupportedList[] = -{ - OID_GEN_SUPPORTED_LIST, - OID_GEN_HARDWARE_STATUS, - OID_GEN_MEDIA_SUPPORTED, - OID_GEN_MEDIA_IN_USE, - OID_GEN_MAXIMUM_FRAME_SIZE, - OID_GEN_LINK_SPEED, - OID_GEN_TRANSMIT_BLOCK_SIZE, - OID_GEN_RECEIVE_BLOCK_SIZE, - OID_GEN_VENDOR_ID, - OID_GEN_VENDOR_DESCRIPTION, - OID_GEN_VENDOR_DRIVER_VERSION, - OID_GEN_CURRENT_PACKET_FILTER, - OID_GEN_MAXIMUM_TOTAL_SIZE, - OID_GEN_PROTOCOL_OPTIONS, - OID_GEN_MAC_OPTIONS, - OID_GEN_MEDIA_CONNECT_STATUS, - OID_GEN_MAXIMUM_SEND_PACKETS, - OID_802_3_PERMANENT_ADDRESS, - OID_802_3_CURRENT_ADDRESS, - OID_802_3_MULTICAST_LIST, - OID_802_3_MAXIMUM_LIST_SIZE, - OID_802_3_MAC_OPTIONS -}; - -#define OID_LIST_LENGTH TU_ARRAY_SIZE(OIDSupportedList) -#define ENC_BUF_SIZE (OID_LIST_LENGTH * 4 + 32) - -static void *encapsulated_buffer; - -static void rndis_report(void) -{ - netd_report(ndis_report, sizeof(ndis_report)); -} - -static void rndis_query_cmplt32(int status, uint32_t data) -{ - rndis_query_cmplt_t *c; - c = (rndis_query_cmplt_t *)encapsulated_buffer; - c->MessageType = REMOTE_NDIS_QUERY_CMPLT; - c->MessageLength = sizeof(rndis_query_cmplt_t) + 4; - c->InformationBufferLength = 4; - c->InformationBufferOffset = 16; - c->Status = status; - memcpy(c + 1, &data, sizeof(data)); - rndis_report(); -} - -static void rndis_query_cmplt(int status, const void *data, int size) -{ - rndis_query_cmplt_t *c; - c = (rndis_query_cmplt_t *)encapsulated_buffer; - c->MessageType = REMOTE_NDIS_QUERY_CMPLT; - c->MessageLength = sizeof(rndis_query_cmplt_t) + size; - c->InformationBufferLength = size; - c->InformationBufferOffset = 16; - c->Status = status; - memcpy(c + 1, data, size); - rndis_report(); -} - -#define MAC_OPT NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \ - NDIS_MAC_OPTION_RECEIVE_SERIALIZED | \ - NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | \ - NDIS_MAC_OPTION_NO_LOOPBACK - -static const char *rndis_vendor = RNDIS_VENDOR; - -static void rndis_query(void) -{ - switch (((rndis_query_msg_t *)encapsulated_buffer)->Oid) - { - case OID_GEN_SUPPORTED_LIST: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, OIDSupportedList, 4 * OID_LIST_LENGTH); return; - case OID_GEN_VENDOR_DRIVER_VERSION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00001000); return; - case OID_802_3_CURRENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, station_hwaddr, 6); return; - case OID_802_3_PERMANENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, permanent_hwaddr, 6); return; - case OID_GEN_MEDIA_SUPPORTED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; - case OID_GEN_MEDIA_IN_USE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; - case OID_GEN_PHYSICAL_MEDIUM: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; - case OID_GEN_HARDWARE_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - case OID_GEN_LINK_SPEED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, RNDIS_LINK_SPEED / 100); return; - case OID_GEN_VENDOR_ID: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00FFFFFF); return; - case OID_GEN_VENDOR_DESCRIPTION: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, rndis_vendor, strlen(rndis_vendor) + 1); return; - case OID_GEN_CURRENT_PACKET_FILTER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, oid_packet_filter); return; - case OID_GEN_MAXIMUM_FRAME_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU - SIZEOF_ETH_HDR); return; - case OID_GEN_MAXIMUM_TOTAL_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; - case OID_GEN_TRANSMIT_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; - case OID_GEN_RECEIVE_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; - case OID_GEN_MEDIA_CONNECT_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIA_STATE_CONNECTED); return; - case OID_GEN_RNDIS_CONFIG_PARAMETER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - case OID_802_3_MAXIMUM_LIST_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 1); return; - case OID_802_3_MULTICAST_LIST: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; - case OID_802_3_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; - case OID_GEN_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, /*MAC_OPT*/ 0); return; - case OID_802_3_RCV_ERROR_ALIGNMENT: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - case OID_802_3_XMIT_ONE_COLLISION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - case OID_802_3_XMIT_MORE_COLLISIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - case OID_GEN_XMIT_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txok); return; - case OID_GEN_RCV_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxok); return; - case OID_GEN_RCV_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxbad); return; - case OID_GEN_XMIT_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txbad); return; - case OID_GEN_RCV_NO_BUFFER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; - default: rndis_query_cmplt(RNDIS_STATUS_FAILURE, NULL, 0); return; - } -} - -#define INFBUF ((uint8_t *)&(m->RequestId) + m->InformationBufferOffset) - -static void rndis_handle_config_parm(const char *data, int keyoffset, int valoffset, int keylen, int vallen) -{ - (void)data; - (void)keyoffset; - (void)valoffset; - (void)keylen; - (void)vallen; -} - -static void rndis_packetFilter(uint32_t newfilter) -{ - (void)newfilter; -} - -static void rndis_handle_set_msg(void) -{ - rndis_set_cmplt_t *c; - rndis_set_msg_t *m; - rndis_Oid_t oid; - - c = (rndis_set_cmplt_t *)encapsulated_buffer; - m = (rndis_set_msg_t *)encapsulated_buffer; - - oid = m->Oid; - c->MessageType = REMOTE_NDIS_SET_CMPLT; - c->MessageLength = sizeof(rndis_set_cmplt_t); - c->Status = RNDIS_STATUS_SUCCESS; - - switch (oid) - { - /* Parameters set up in 'Advanced' tab */ - case OID_GEN_RNDIS_CONFIG_PARAMETER: - { - rndis_config_parameter_t *p; - char *ptr = (char *)m; - ptr += sizeof(rndis_generic_msg_t); - ptr += m->InformationBufferOffset; - p = (rndis_config_parameter_t *) ((void*) ptr); - rndis_handle_config_parm(ptr, p->ParameterNameOffset, p->ParameterValueOffset, p->ParameterNameLength, p->ParameterValueLength); - } - break; - - /* Mandatory general OIDs */ - case OID_GEN_CURRENT_PACKET_FILTER: - memcpy(&oid_packet_filter, INFBUF, 4); - if (oid_packet_filter) - { - rndis_packetFilter(oid_packet_filter); - rndis_state = rndis_data_initialized; - } - else - { - rndis_state = rndis_initialized; - } - break; - - case OID_GEN_CURRENT_LOOKAHEAD: - break; - - case OID_GEN_PROTOCOL_OPTIONS: - break; - - /* Mandatory 802_3 OIDs */ - case OID_802_3_MULTICAST_LIST: - break; - - /* Power Managment: fails for now */ - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - case OID_PNP_ENABLE_WAKE_UP: - default: - c->Status = RNDIS_STATUS_FAILURE; - break; - } - - /* c->MessageID is same as before */ - rndis_report(); - return; -} - -void rndis_class_set_handler(uint8_t *data, int size) -{ - encapsulated_buffer = data; - (void)size; - - switch (((rndis_generic_msg_t *)encapsulated_buffer)->MessageType) - { - case REMOTE_NDIS_INITIALIZE_MSG: - { - rndis_initialize_cmplt_t *m; - m = ((rndis_initialize_cmplt_t *)encapsulated_buffer); - /* m->MessageID is same as before */ - m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; - m->MessageLength = sizeof(rndis_initialize_cmplt_t); - m->MajorVersion = RNDIS_MAJOR_VERSION; - m->MinorVersion = RNDIS_MINOR_VERSION; - m->Status = RNDIS_STATUS_SUCCESS; - m->DeviceFlags = RNDIS_DF_CONNECTIONLESS; - m->Medium = RNDIS_MEDIUM_802_3; - m->MaxPacketsPerTransfer = 1; - m->MaxTransferSize = CFG_TUD_NET_MTU + sizeof(rndis_data_packet_t); - m->PacketAlignmentFactor = 0; - m->AfListOffset = 0; - m->AfListSize = 0; - rndis_state = rndis_initialized; - rndis_report(); - } - break; - - case REMOTE_NDIS_QUERY_MSG: - rndis_query(); - break; - - case REMOTE_NDIS_SET_MSG: - rndis_handle_set_msg(); - break; - - case REMOTE_NDIS_RESET_MSG: - { - rndis_reset_cmplt_t * m; - m = ((rndis_reset_cmplt_t *)encapsulated_buffer); - rndis_state = rndis_uninitialized; - m->MessageType = REMOTE_NDIS_RESET_CMPLT; - m->MessageLength = sizeof(rndis_reset_cmplt_t); - m->Status = RNDIS_STATUS_SUCCESS; - m->AddressingReset = 1; /* Make it look like we did something */ - /* m->AddressingReset = 0; - Windows halts if set to 1 for some reason */ - rndis_report(); - } - break; - - case REMOTE_NDIS_KEEPALIVE_MSG: - { - rndis_keepalive_cmplt_t * m; - m = (rndis_keepalive_cmplt_t *)encapsulated_buffer; - m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; - m->MessageLength = sizeof(rndis_keepalive_cmplt_t); - m->Status = RNDIS_STATUS_SUCCESS; - } - /* We have data to send back */ - rndis_report(); - break; - - default: - break; - } -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml deleted file mode 100644 index 331445024..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/pkg.yml +++ /dev/null @@ -1,14 +0,0 @@ -pkg.name: tinyusb -pkg.description: A silly USB stack for embedded -pkg.author: "Ha Thach " -pkg.homepage: "https://github.com/hathach/tinyusb" -pkg.keywords: - - usb - -pkg.type: sdk - -pkg.deps: - - "@apache-mynewt-core/kernel/os" - -pkg.include_dirs: - - src diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml deleted file mode 100644 index 21d092373..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/repository.yml +++ /dev/null @@ -1,15 +0,0 @@ -repo.name: tinyusb -repo.versions: - "0.0.0": "master" - "0.5.0": "0.5.0" - "0.6.0": "0.6.0" - "0.7.0": "0.7.0" - "0.8.0": "0.8.0" - "0.9.0": "0.9.0" - "0.10.0": "0.10.0" - "0.10.1": "0.10.1" - "0.11.0": "0.11.0" - - "0-dev": "0.0.0" # master - "0-latest": "0.11.0" # latest stable release - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/sbom.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/sbom.yml new file mode 100644 index 000000000..f1e805b9c --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/sbom.yml @@ -0,0 +1,2 @@ +supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' +originator: 'Organization: Espressif Systems (Shanghai) CO LTD' diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename b/examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename deleted file mode 100644 index 6aea8579a..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/sdkconfig.rename +++ /dev/null @@ -1,22 +0,0 @@ -# sdkconfig replacement configurations for deprecated options formatted as -# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION -CONFIG_USB_ENABLED CONFIG_TINYUSB -CONFIG_USB_DO_NOT_CREATE_TASK CONFIG_TINYUSB_NO_DEFAULT_TASK -CONFIG_USB_TASK_PRIORITY CONFIG_TINYUSB_TASK_PRIORITY -CONFIG_USB_DESC_USE_ESPRESSIF_VID CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID -CONFIG_USB_DESC_CUSTOM_VID CONFIG_TINYUSB_DESC_CUSTOM_VID -CONFIG_USB_DESC_USE_DEFAULT_PID CONFIG_TINYUSB_DESC_USE_DEFAULT_PID -CONFIG_USB_DESC_CUSTOM_PID CONFIG_TINYUSB_DESC_CUSTOM_PID -CONFIG_USB_DESC_BCDDEVICE CONFIG_TINYUSB_DESC_BCD_DEVICE -CONFIG_USB_DESC_MANUFACTURER_STRING CONFIG_TINYUSB_DESC_MANUFACTURER_STRING -CONFIG_USB_DESC_PRODUCT_STRING CONFIG_TINYUSB_DESC_PRODUCT_STRING -CONFIG_USB_DESC_SERIAL_STRING CONFIG_TINYUSB_DESC_SERIAL_STRING -CONFIG_USB_DESC_CDC_STRING CONFIG_TINYUSB_DESC_CDC_STRING -CONFIG_USB_DESC_MSC_STRING CONFIG_TINYUSB_DESC_MSC_STRING -CONFIG_USB_DESC_HID_STRING CONFIG_TINYUSB_DESC_HID_STRING -CONFIG_USB_MSC_ENABLED CONFIG_TINYUSB_MSC_ENABLED -CONFIG_USB_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE -CONFIG_USB_CDC_ENABLED CONFIG_TINYUSB_CDC_ENABLED -CONFIG_USB_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE -CONFIG_USB_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE -CONFIG_USB_DEBUG_LEVEL CONFIG_TINYUSB_DEBUG_LEVEL diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h deleted file mode 100644 index 6f9c1a6b5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio.h +++ /dev/null @@ -1,933 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_Audio Audio - * Currently only MIDI subclass is supported - * @{ */ - -#ifndef _TUSB_AUDIO_H__ -#define _TUSB_AUDIO_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/// Audio Device Class Codes - -/// A.2 - Audio Function Subclass Codes -typedef enum -{ - AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, -} audio_function_subclass_type_t; - -/// A.3 - Audio Function Protocol Codes -typedef enum -{ - AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 -} audio_function_protocol_code_t; - -/// A.5 - Audio Interface Subclass Codes -typedef enum -{ - AUDIO_SUBCLASS_UNDEFINED = 0x00, - AUDIO_SUBCLASS_CONTROL , ///< Audio Control - AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming - AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming -} audio_subclass_type_t; - -/// A.6 - Audio Interface Protocol Codes -typedef enum -{ - AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 -} audio_interface_protocol_code_t; - -/// A.7 - Audio Function Category Codes -typedef enum -{ - AUDIO_FUNC_UNDEF = 0x00, - AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, - AUDIO_FUNC_HOME_THEATER = 0x02, - AUDIO_FUNC_MICROPHONE = 0x03, - AUDIO_FUNC_HEADSET = 0x04, - AUDIO_FUNC_TELEPHONE = 0x05, - AUDIO_FUNC_CONVERTER = 0x06, - AUDIO_FUNC_SOUND_RECODER = 0x07, - AUDIO_FUNC_IO_BOX = 0x08, - AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, - AUDIO_FUNC_PRO_AUDIO = 0x0A, - AUDIO_FUNC_AUDIO_VIDEO = 0x0B, - AUDIO_FUNC_CONTROL_PANEL = 0x0C, - AUDIO_FUNC_OTHER = 0xFF, -} audio_function_code_t; - -/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AC_INTERFACE_HEADER = 0x01, - AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, - AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, - AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, - AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, - AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, - AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, - AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, - AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, - AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, - AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, - AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, - AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, -} audio_cs_ac_interface_subtype_t; - -/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, - AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, - AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, - AUDIO_CS_AS_INTERFACE_DECODER = 0x04, -} audio_cs_as_interface_subtype_t; - -/// A.11 - Effect Unit Effect Types -typedef enum -{ - AUDIO_EFFECT_TYPE_UNDEF = 0x00, - AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, - AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, - AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, - AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, -} audio_effect_unit_effect_type_t; - -/// A.12 - Processing Unit Process Types -typedef enum -{ - AUDIO_PROCESS_TYPE_UNDEF = 0x00, - AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, - AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, - AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, -} audio_processing_unit_process_type_t; - -/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, - AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, -} audio_cs_ep_subtype_t; - -/// A.14 - Audio Class-Specific Request Codes -typedef enum -{ - AUDIO_CS_REQ_UNDEF = 0x00, - AUDIO_CS_REQ_CUR = 0x01, - AUDIO_CS_REQ_RANGE = 0x02, - AUDIO_CS_REQ_MEM = 0x03, -} audio_cs_req_t; - -/// A.17 - Control Selector Codes - -/// A.17.1 - Clock Source Control Selectors -typedef enum -{ - AUDIO_CS_CTRL_UNDEF = 0x00, - AUDIO_CS_CTRL_SAM_FREQ = 0x01, - AUDIO_CS_CTRL_CLK_VALID = 0x02, -} audio_clock_src_control_selector_t; - -/// A.17.2 - Clock Selector Control Selectors -typedef enum -{ - AUDIO_CX_CTRL_UNDEF = 0x00, - AUDIO_CX_CTRL_CONTROL = 0x01, -} audio_clock_sel_control_selector_t; - -/// A.17.3 - Clock Multiplier Control Selectors -typedef enum -{ - AUDIO_CM_CTRL_UNDEF = 0x00, - AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, - AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, -} audio_clock_mul_control_selector_t; - -/// A.17.4 - Terminal Control Selectors -typedef enum -{ - AUDIO_TE_CTRL_UNDEF = 0x00, - AUDIO_TE_CTRL_COPY_PROTECT = 0x01, - AUDIO_TE_CTRL_CONNECTOR = 0x02, - AUDIO_TE_CTRL_OVERLOAD = 0x03, - AUDIO_TE_CTRL_CLUSTER = 0x04, - AUDIO_TE_CTRL_UNDERFLOW = 0x05, - AUDIO_TE_CTRL_OVERFLOW = 0x06, - AUDIO_TE_CTRL_LATENCY = 0x07, -} audio_terminal_control_selector_t; - -/// A.17.5 - Mixer Control Selectors -typedef enum -{ - AUDIO_MU_CTRL_UNDEF = 0x00, - AUDIO_MU_CTRL_MIXER = 0x01, - AUDIO_MU_CTRL_CLUSTER = 0x02, - AUDIO_MU_CTRL_UNDERFLOW = 0x03, - AUDIO_MU_CTRL_OVERFLOW = 0x04, - AUDIO_MU_CTRL_LATENCY = 0x05, -} audio_mixer_control_selector_t; - -/// A.17.6 - Selector Control Selectors -typedef enum -{ - AUDIO_SU_CTRL_UNDEF = 0x00, - AUDIO_SU_CTRL_SELECTOR = 0x01, - AUDIO_SU_CTRL_LATENCY = 0x02, -} audio_sel_control_selector_t; - -/// A.17.7 - Feature Unit Control Selectors -typedef enum -{ - AUDIO_FU_CTRL_UNDEF = 0x00, - AUDIO_FU_CTRL_MUTE = 0x01, - AUDIO_FU_CTRL_VOLUME = 0x02, - AUDIO_FU_CTRL_BASS = 0x03, - AUDIO_FU_CTRL_MID = 0x04, - AUDIO_FU_CTRL_TREBLE = 0x05, - AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, - AUDIO_FU_CTRL_AGC = 0x07, - AUDIO_FU_CTRL_DELAY = 0x08, - AUDIO_FU_CTRL_BASS_BOOST = 0x09, - AUDIO_FU_CTRL_LOUDNESS = 0x0A, - AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, - AUDIO_FU_CTRL_GAIN_PAD = 0x0C, - AUDIO_FU_CTRL_INVERTER = 0x0D, - AUDIO_FU_CTRL_UNDERFLOW = 0x0E, - AUDIO_FU_CTRL_OVERVLOW = 0x0F, - AUDIO_FU_CTRL_LATENCY = 0x10, -} audio_feature_unit_control_selector_t; - -/// A.17.8 Effect Unit Control Selectors - -/// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors -typedef enum -{ - AUDIO_PE_CTRL_UNDEF = 0x00, - AUDIO_PE_CTRL_ENABLE = 0x01, - AUDIO_PE_CTRL_CENTERFREQ = 0x02, - AUDIO_PE_CTRL_QFACTOR = 0x03, - AUDIO_PE_CTRL_GAIN = 0x04, - AUDIO_PE_CTRL_UNDERFLOW = 0x05, - AUDIO_PE_CTRL_OVERFLOW = 0x06, - AUDIO_PE_CTRL_LATENCY = 0x07, -} audio_parametric_equalizer_control_selector_t; - -/// A.17.8.2 Reverberation Effect Unit Control Selectors -typedef enum -{ - AUDIO_RV_CTRL_UNDEF = 0x00, - AUDIO_RV_CTRL_ENABLE = 0x01, - AUDIO_RV_CTRL_TYPE = 0x02, - AUDIO_RV_CTRL_LEVEL = 0x03, - AUDIO_RV_CTRL_TIME = 0x04, - AUDIO_RV_CTRL_FEEDBACK = 0x05, - AUDIO_RV_CTRL_PREDELAY = 0x06, - AUDIO_RV_CTRL_DENSITY = 0x07, - AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, - AUDIO_RV_CTRL_UNDERFLOW = 0x09, - AUDIO_RV_CTRL_OVERFLOW = 0x0A, - AUDIO_RV_CTRL_LATENCY = 0x0B, -} audio_reverberation_effect_control_selector_t; - -/// A.17.8.3 Modulation Delay Effect Unit Control Selectors -typedef enum -{ - AUDIO_MD_CTRL_UNDEF = 0x00, - AUDIO_MD_CTRL_ENABLE = 0x01, - AUDIO_MD_CTRL_BALANCE = 0x02, - AUDIO_MD_CTRL_RATE = 0x03, - AUDIO_MD_CTRL_DEPTH = 0x04, - AUDIO_MD_CTRL_TIME = 0x05, - AUDIO_MD_CTRL_FEEDBACK = 0x06, - AUDIO_MD_CTRL_UNDERFLOW = 0x07, - AUDIO_MD_CTRL_OVERFLOW = 0x08, - AUDIO_MD_CTRL_LATENCY = 0x09, -} audio_modulation_delay_control_selector_t; - -/// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors -typedef enum -{ - AUDIO_DR_CTRL_UNDEF = 0x00, - AUDIO_DR_CTRL_ENABLE = 0x01, - AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, - AUDIO_DR_CTRL_MAXAMPL = 0x03, - AUDIO_DR_CTRL_THRESHOLD = 0x04, - AUDIO_DR_CTRL_ATTACK_TIME = 0x05, - AUDIO_DR_CTRL_RELEASE_TIME = 0x06, - AUDIO_DR_CTRL_UNDERFLOW = 0x07, - AUDIO_DR_CTRL_OVERFLOW = 0x08, - AUDIO_DR_CTRL_LATENCY = 0x09, -} audio_dynamic_range_compression_control_selector_t; - -/// A.17.9 Processing Unit Control Selectors - -/// A.17.9.1 Up/Down-mix Processing Unit Control Selectors -typedef enum -{ - AUDIO_UD_CTRL_UNDEF = 0x00, - AUDIO_UD_CTRL_ENABLE = 0x01, - AUDIO_UD_CTRL_MODE_SELECT = 0x02, - AUDIO_UD_CTRL_CLUSTER = 0x03, - AUDIO_UD_CTRL_UNDERFLOW = 0x04, - AUDIO_UD_CTRL_OVERFLOW = 0x05, - AUDIO_UD_CTRL_LATENCY = 0x06, -} audio_up_down_mix_control_selector_t; - -/// A.17.9.2 Dolby Prologic ™ Processing Unit Control Selectors -typedef enum -{ - AUDIO_DP_CTRL_UNDEF = 0x00, - AUDIO_DP_CTRL_ENABLE = 0x01, - AUDIO_DP_CTRL_MODE_SELECT = 0x02, - AUDIO_DP_CTRL_CLUSTER = 0x03, - AUDIO_DP_CTRL_UNDERFLOW = 0x04, - AUDIO_DP_CTRL_OVERFLOW = 0x05, - AUDIO_DP_CTRL_LATENCY = 0x06, -} audio_dolby_prologic_control_selector_t; - -/// A.17.9.3 Stereo Extender Processing Unit Control Selectors -typedef enum -{ - AUDIO_ST_EXT_CTRL_UNDEF = 0x00, - AUDIO_ST_EXT_CTRL_ENABLE = 0x01, - AUDIO_ST_EXT_CTRL_WIDTH = 0x02, - AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, - AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, - AUDIO_ST_EXT_CTRL_LATENCY = 0x05, -} audio_stereo_extender_control_selector_t; - -/// A.17.10 Extension Unit Control Selectors -typedef enum -{ - AUDIO_XU_CTRL_UNDEF = 0x00, - AUDIO_XU_CTRL_ENABLE = 0x01, - AUDIO_XU_CTRL_CLUSTER = 0x02, - AUDIO_XU_CTRL_UNDERFLOW = 0x03, - AUDIO_XU_CTRL_OVERFLOW = 0x04, - AUDIO_XU_CTRL_LATENCY = 0x05, -} audio_extension_unit_control_selector_t; - -/// A.17.11 AudioStreaming Interface Control Selectors -typedef enum -{ - AUDIO_AS_CTRL_UNDEF = 0x00, - AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, - AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, - AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, -} audio_audiostreaming_interface_control_selector_t; - -/// A.17.12 Encoder Control Selectors -typedef enum -{ - AUDIO_EN_CTRL_UNDEF = 0x00, - AUDIO_EN_CTRL_BIT_RATE = 0x01, - AUDIO_EN_CTRL_QUALITY = 0x02, - AUDIO_EN_CTRL_VBR = 0x03, - AUDIO_EN_CTRL_TYPE = 0x04, - AUDIO_EN_CTRL_UNDERFLOW = 0x05, - AUDIO_EN_CTRL_OVERFLOW = 0x06, - AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, - AUDIO_EN_CTRL_PARAM1 = 0x08, - AUDIO_EN_CTRL_PARAM2 = 0x09, - AUDIO_EN_CTRL_PARAM3 = 0x0A, - AUDIO_EN_CTRL_PARAM4 = 0x0B, - AUDIO_EN_CTRL_PARAM5 = 0x0C, - AUDIO_EN_CTRL_PARAM6 = 0x0D, - AUDIO_EN_CTRL_PARAM7 = 0x0E, - AUDIO_EN_CTRL_PARAM8 = 0x0F, -} audio_encoder_control_selector_t; - -/// A.17.13 Decoder Control Selectors - -/// A.17.13.1 MPEG Decoder Control Selectors -typedef enum -{ - AUDIO_MPD_CTRL_UNDEF = 0x00, - AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, - AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, - AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, - AUDIO_MPD_CTRL_DYN_RANGE = 0x04, - AUDIO_MPD_CTRL_SCALING = 0x05, - AUDIO_MPD_CTRL_HILO_SCALING = 0x06, - AUDIO_MPD_CTRL_UNDERFLOW = 0x07, - AUDIO_MPD_CTRL_OVERFLOW = 0x08, - AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, -} audio_MPEG_decoder_control_selector_t; - -/// A.17.13.2 AC-3 Decoder Control Selectors -typedef enum -{ - AUDIO_AD_CTRL_UNDEF = 0x00, - AUDIO_AD_CTRL_MODE = 0x01, - AUDIO_AD_CTRL_DYN_RANGE = 0x02, - AUDIO_AD_CTRL_SCALING = 0x03, - AUDIO_AD_CTRL_HILO_SCALING = 0x04, - AUDIO_AD_CTRL_UNDERFLOW = 0x05, - AUDIO_AD_CTRL_OVERFLOW = 0x06, - AUDIO_AD_CTRL_DECODER_ERROR = 0x07, -} audio_AC3_decoder_control_selector_t; - -/// A.17.13.3 WMA Decoder Control Selectors -typedef enum -{ - AUDIO_WD_CTRL_UNDEF = 0x00, - AUDIO_WD_CTRL_UNDERFLOW = 0x01, - AUDIO_WD_CTRL_OVERFLOW = 0x02, - AUDIO_WD_CTRL_DECODER_ERROR = 0x03, -} audio_WMA_decoder_control_selector_t; - -/// A.17.13.4 DTS Decoder Control Selectors -typedef enum -{ - AUDIO_DD_CTRL_UNDEF = 0x00, - AUDIO_DD_CTRL_UNDERFLOW = 0x01, - AUDIO_DD_CTRL_OVERFLOW = 0x02, - AUDIO_DD_CTRL_DECODER_ERROR = 0x03, -} audio_DTS_decoder_control_selector_t; - -/// A.17.14 Endpoint Control Selectors -typedef enum -{ - AUDIO_EP_CTRL_UNDEF = 0x00, - AUDIO_EP_CTRL_PITCH = 0x01, - AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, - AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, -} audio_EP_control_selector_t; - -/// Terminal Types - -/// 2.1 - Audio Class-Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, - AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, - AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, -} audio_terminal_type_t; - -/// 2.2 - Audio Class-Input Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, - AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, - AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, - AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, - AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, - AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, - AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, -} audio_terminal_input_type_t; - -/// 2.3 - Audio Class-Output Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, - AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, - AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, - AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, - AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, - AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, - AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, - AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, -} audio_terminal_output_type_t; - -/// Rest is yet to be implemented - -/// Additional Audio Device Class Codes - Source: Audio Data Formats - -/// A.1 - Audio Class-Format Type Codes UAC2 -typedef enum -{ - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, -} audio_format_type_t; - -// A.2.1 - Audio Class-Audio Data Format Type I UAC2 -typedef enum -{ - AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), - AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), - AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, -} audio_data_format_type_I_t; - -/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification - -/// Audio Class-Control Values UAC2 -typedef enum -{ - AUDIO_CTRL_NONE = 0x00, ///< No Host access - AUDIO_CTRL_R = 0x01, ///< Host read access only - AUDIO_CTRL_RW = 0x03, ///< Host read write access -} audio_control_t; - -/// Audio Class-Specific AC Interface Descriptor Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, -} audio_cs_ac_interface_control_pos_t; - -/// Audio Class-Specific AS Interface Descriptor Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, - AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, -} audio_cs_as_interface_control_pos_t; - -/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, - AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, -} audio_cs_as_iso_data_ep_attribute_t; - -/// Audio Class-Specific AS Isochronous Data EP Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, -} audio_cs_as_iso_data_ep_control_pos_t; - -/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, -} audio_cs_as_iso_data_ep_lock_delay_unit_t; - -/// Audio Class-Clock Source Attributes UAC2 -typedef enum -{ - AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, - AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, - AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, - AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, - AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, -} audio_clock_source_attribute_t; - -/// Audio Class-Clock Source Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, - AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, -} audio_clock_source_control_pos_t; - -/// Audio Class-Clock Selector Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, -} audio_clock_selector_control_pos_t; - -/// Audio Class-Clock Multiplier Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, - AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, -} audio_clock_multiplier_control_pos_t; - -/// Audio Class-Input Terminal Controls UAC2 -typedef enum -{ - AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, - AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, - AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, -} audio_terminal_input_control_pos_t; - -/// Audio Class-Output Terminal Controls UAC2 -typedef enum -{ - AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, - AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, -} audio_terminal_output_control_pos_t; - -/// Audio Class-Feature Unit Controls UAC2 -typedef enum -{ - AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, - AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, - AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, - AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, - AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, - AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, - AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, - AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, - AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, - AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, - AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, - AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, - AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, -} audio_feature_unit_control_pos_t; - -/// Audio Class-Audio Channel Configuration UAC2 -typedef enum -{ - AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, - AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, - AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, - AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, - AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, - AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, - AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, - AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, - AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, - AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, - AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, - AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, - AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, -} audio_channel_config_t; - -/// AUDIO Channel Cluster Descriptor (4.1) -typedef struct TU_ATTR_PACKED { - uint8_t bNrChannels; ///< Number of channels currently connected. - audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. - uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. -} audio_desc_channel_cluster_t; - -/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes: 9. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. - uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). - uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. - uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. - uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. -} audio_desc_cs_ac_interface_t; - -/// AUDIO Clock Source Descriptor (4.7.2.1) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. - uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. - uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. -} audio_desc_clock_source_t; - -/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. - uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. - uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. -} audio_desc_clock_selector_t; - -/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins -#define audio_desc_clock_selector_n_t(source_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bClockID ; \ - uint8_t bNrInPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID ; \ - } sourceID[source_num] ; \ - uint8_t bmControls ; \ - uint8_t iClockSource ; \ -} - -/// AUDIO Clock Multiplier Descriptor (4.7.2.3) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. - uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. -} audio_desc_clock_multiplier_t; - -/// AUDIO Input Terminal Descriptor(4.7.2.4) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. - uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. - uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. - uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. -} audio_desc_input_terminal_t; - -/// AUDIO Output Terminal Descriptor(4.7.2.5) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. - uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. - uint16_t bmControls ; ///< See: audio_terminal_output_type_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. -} audio_desc_output_terminal_t; - -/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. - uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. - struct TU_ATTR_PACKED { - uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. - } controls[2] ; - uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. -} audio_desc_feature_unit_t; - -/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels -#define audio_desc_feature_unit_n_t(ch_num)\ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; /* 6+(ch_num+1)*4 */\ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bUnitID ; \ - uint8_t bSourceID ; \ - struct TU_ATTR_PACKED { \ - uint32_t bmaControls ; \ - } controls[ch_num+1] ; \ - uint8_t iTerminal ; \ -} - -/// AUDIO Class-Specific AS Interface Descriptor(4.9.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. - uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. - uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. - uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. - uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. -} audio_desc_cs_as_interface_t; - -/// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. - uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. - uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. -} audio_desc_type_I_format_t; - -/// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. - uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. - uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. - uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. - uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. -} audio_desc_cs_as_iso_data_ep_t; - -// 5.2.2 Control Request Layout -typedef struct TU_ATTR_PACKED -{ - union - { - struct TU_ATTR_PACKED - { - uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. - uint8_t type : 2; ///< Request type tusb_request_type_t. - uint8_t direction : 1; ///< Direction type. tusb_dir_t - } bmRequestType_bit; - - uint8_t bmRequestType; - }; - - uint8_t bRequest; ///< Request type audio_cs_req_t - uint8_t bChannelNumber; - uint8_t bControlSelector; - union - { - uint8_t bInterface; - uint8_t bEndpoint; - }; - uint8_t bEntityID; - uint16_t wLength; -} audio_control_request_t; - -//// 5.2.3 Control Request Parameter Block Layout - -// 5.2.3.1 1-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_1_t; - -// 5.2.3.2 2-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_2_t; - -// 5.2.3.3 4-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_4_t; - -// Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like -// 5.2.3.1 1-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_1_t; - -// 5.2.3.2 2-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_2_t; - -// 5.2.3.3 4-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_4_t; - -// 5.2.3.1 1-byte Control RANGE Parameter Block -#define audio_control_range_1_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ -} - -/// 5.2.3.2 2-byte Control RANGE Parameter Block -#define audio_control_range_2_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges]; \ -} - -// 5.2.3.3 4-byte Control RANGE Parameter Block -#define audio_control_range_4_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges]; \ -} - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c deleted file mode 100644 index d21980060..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.c +++ /dev/null @@ -1,2294 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Reinhard Panhuber, Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* - * This driver supports at most one out EP, one in EP, one control EP, and one feedback EP and one alternative interface other than zero. Hence, only one input terminal and one output terminal are support, if you need more adjust the driver! - * It supports multiple TX and RX channels. - * - * In case you need more alternate interfaces, you need to define additional defines for this specific alternate interface. Just define them and set them in the set_interface function. - * - * There are three data flow structures currently implemented, where at least one SW-FIFO is used to decouple the asynchronous processes MCU vs. host - * - * 1. Input data -> SW-FIFO -> MCU USB - * - * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_xfer_fifo() is available) - * - * 2. Input data -> SW-FIFO -> Linear buffer -> MCU USB - * - * In case the target MCU can not handle a SW-FIFO, a linear buffer is used. This uses the default function dcd_edpt_xfer(). In this case more memory is required. - * - * 3. (Input data 1 | Input data 2 | ... | Input data N) -> (SW-FIFO 1 | SW-FIFO 2 | ... | SW-FIFO N) -> Linear buffer -> MCU USB - * - * This case is used if you have more channels which need to be combined into one stream. Every channel has its own SW-FIFO. All data is encoded into an Linear buffer. - * - * The same holds in the RX case. - * - * */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "audio_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// Use ring buffer if it's available, some MCUs need extra RAM requirements -#ifndef TUD_AUDIO_PREFER_RING_BUFFER -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX -#define TUD_AUDIO_PREFER_RING_BUFFER 0 -#else -#define TUD_AUDIO_PREFER_RING_BUFFER 1 -#endif -#endif - -// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer -// is available or driver is would need to be changed dramatically - -// Only STM32 synopsys and dcd_transdimension use non-linear buffer for now -// Synopsys detection copied from dcd_synopsys.c (refactor later on) -#if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ - defined (STM32F107xB) || defined (STM32F107xC) -#define STM32F1_SYNOPSYS -#endif - -#if defined (STM32L475xx) || defined (STM32L476xx) || \ - defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ - defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ - defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) -#define STM32L4_SYNOPSYS -#endif - -#if (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ - CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_RX63X || \ - CFG_TUSB_MCU == OPT_MCU_RX65X || \ - CFG_TUSB_MCU == OPT_MCU_RX72N || \ - CFG_TUSB_MCU == OPT_MCU_GD32VF103 || \ - CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_MSP432E4 -#if TUD_AUDIO_PREFER_RING_BUFFER -#define USE_LINEAR_BUFFER 0 -#else -#define USE_LINEAR_BUFFER 1 -#endif -#else -#define USE_LINEAR_BUFFER 1 -#endif - -// Declaration of buffers - -// Check for maximum supported numbers -#if CFG_TUD_AUDIO > 3 -#error Maximum number of audio functions restricted to three! -#endif - -// EP IN software buffers and mutexes -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -// Linear buffer TX in case: -// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR -// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - -// EP OUT software buffers and mutexes -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -// Linear buffer RX in case: -// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR -// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - -// Control buffers -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; -#if CFG_TUD_AUDIO > 1 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; -#endif -#if CFG_TUD_AUDIO > 2 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; -#endif - -// Active alternate setting of interfaces -uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; -#endif - -// Software encoding/decoding support FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; -tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; -tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; -tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; -tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; -tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; -tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; -#if CFG_FIFO_MUTEX -osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO -#endif -#endif -#endif - -typedef struct -{ - uint8_t rhport; - uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - uint8_t ep_in; // TX audio data EP. - uint16_t ep_in_sz; // Current size of TX EP - uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - uint8_t ep_out; // Incoming (into uC) audio data EP. - uint16_t ep_out_sz; // Current size of RX EP - uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb; // Feedback EP. -#endif - -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - uint8_t ep_int_ctr; // Audio control interrupt EP. -#endif - - /*------------- From this point, data is not cleared by bus reset -------------*/ - - uint16_t desc_length; // Length of audio function descriptor - - // Buffer for control requests - uint8_t * ctrl_buf; - uint8_t ctrl_buf_sz; - - // Current active alternate settings - uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! - - // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_t ep_out_ff; -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_t ep_in_ff; -#endif - - // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; -#endif - - // Decoding parameters - parameters are set when alternate AS interface is set by host - // Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently. -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - audio_format_type_t format_type_rx; - uint8_t n_channels_rx; - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - audio_data_format_type_I_t format_type_I_rx; - uint8_t n_bytes_per_sampe_rx; - uint8_t n_channels_per_ff_rx; - uint8_t n_ff_used_rx; -#endif -#endif - - // Encoding parameters - parameters are set when alternate AS interface is set by host -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - audio_format_type_t format_type_tx; - uint8_t n_channels_tx; - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio_data_format_type_I_t format_type_I_tx; - uint8_t n_bytes_per_sampe_tx; - uint8_t n_channels_per_ff_tx; - uint8_t n_ff_used_tx; -#endif -#endif - - // Support FIFOs for software encoding and decoding -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_t * rx_supp_ff; - uint8_t n_rx_supp_ff; - uint16_t rx_supp_ff_sz_max; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_t * tx_supp_ff; - uint8_t n_tx_supp_ff; - uint16_t tx_supp_ff_sz_max; -#endif - - // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) - uint8_t * lin_buf_out; -#define USE_LINEAR_BUFFER_RX 1 -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) - uint8_t * lin_buf_in; -#define USE_LINEAR_BUFFER_TX 1 -#endif - -} audiod_function_t; - -#ifndef USE_LINEAR_BUFFER_TX -#define USE_LINEAR_BUFFER_TX 0 -#endif - -#ifndef USE_LINEAR_BUFFER_RX -#define USE_LINEAR_BUFFER_RX 0 -#endif - -#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ctrl_buf) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); -#endif - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t* audio); -#endif - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio); -#endif - -static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); - -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id); -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id); -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id); -static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); - -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); - -static inline uint8_t tu_desc_subtype(void const* desc) -{ - return ((uint8_t const*) desc)[2]; -} -#endif - -bool tud_audio_n_mounted(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO); - audiod_function_t* audio = &_audiod_fct[func_id]; - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (audio->ep_out == 0) return false; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (audio->ep_in == 0) return false; -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - if (audio->ep_int_ctr == 0) return false; -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (audio->ep_fb == 0) return false; -#endif - - return true; -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -uint16_t tud_audio_n_available(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_count(&_audiod_fct[func_id].ep_out_ff); -} - -uint16_t tud_audio_n_read(uint8_t func_id, void* buffer, uint16_t bufsize) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_read_n(&_audiod_fct[func_id].ep_out_ff, buffer, bufsize); -} - -bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); -} - -tu_fifo_t* tud_audio_n_get_ep_out_ff(uint8_t func_id) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_out_ff; - return NULL; -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -// Delete all content in the support RX FIFOs -bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); -} - -tu_fifo_t* tud_audio_n_get_rx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff) return &_audiod_fct[func_id].rx_supp_ff[ff_idx]; - return NULL; -} -#endif - -// This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_DECODING = 0. - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - -static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) -{ - uint8_t idxItf; - uint8_t const *dummy2; - uint8_t idx_audio_fct = 0; - - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); - } - - // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - - switch (audio->format_type_rx) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; - - case AUDIO_FORMAT_TYPE_I: - - switch (audio->format_type_I_tx) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); - break; - - default: - // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented!\r\n"); - TU_BREAKPOINT(); - break; - } - - // Prepare for next transmission - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); - -#else - -#if USE_LINEAR_BUFFER_RX - // Data currently is in linear buffer, copy into EP OUT FIFO - TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); - - // Schedule for next receive - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); -#else - // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); -#endif - -#endif - - // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - - return true; -} - -#endif //CFG_TUD_AUDIO_ENABLE_EP_OUT - -// The following functions are used in case CFG_TUD_AUDIO_ENABLE_DECODING != 0 -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - -// Decoding according to 2.3.1.5 Audio Streams - -// Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) -{ - - // This function is an optimized version of - // while((uint8_t *)dst < dst_end) - // { - // memcpy(dst, src, nBytesToCopy); - // dst = (uint8_t *)dst + nBytesToCopy; - // src += nBytesToCopy * n_ff_used; - // } - - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - - switch (nBytesToCopy) - { - case 1: - while((uint8_t *)dst < dst_end) - { - *(uint8_t *)dst++ = *src; - src += n_ff_used; - } - break; - - case 2: - while((uint8_t *)dst < dst_end) - { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - dst += 2; - src += 2 * n_ff_used; - } - break; - - case 3: - while((uint8_t *)dst < dst_end) - { - // memcpy(dst, src, 3); - // dst = (uint8_t *)dst + 3; - // src += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - - src += 3 * (n_ff_used - 1); - } - break; - - case 4: - while((uint8_t *)dst < dst_end) - { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; - dst += 4; - src += 4 * n_ff_used; - } - break; - } - - return src; -} - -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) -{ - (void) rhport; - - // Determine amount of samples - uint8_t const n_ff_used = audio->n_ff_used_rx; - uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; - uint8_t cnt_ff; - - // Decode - uint8_t * src; - uint8_t * dst_end; - - tu_fifo_buffer_info_t info; - - for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) - { - tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info); - - if (info.len_lin != 0) - { - info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); - src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used); - - // Handle wrapped part of FIFO - info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); - if (info.len_wrap != 0) - { - dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used); - } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); - } - } - - // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it - // TU_VERIFY(cnt != n_bytes); - - return true; -} -#endif //CFG_TUD_AUDIO_ENABLE_DECODING - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -/** - * \brief Write data to EP in buffer - * - * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). - * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. - * - * \param[in] func_id: Index of audio function interface - * \param[in] data: Pointer to data array to be copied from - * \param[in] len: # of array elements to copy - * \return Number of bytes actually written - */ -uint16_t tud_audio_n_write(uint8_t func_id, const void * data, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_write_n(&_audiod_fct[func_id].ep_in_ff, data, len); -} - -bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) // Delete all content in the EP IN FIFO -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); -} - -tu_fifo_t* tud_audio_n_get_ep_in_ff(uint8_t func_id) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_in_ff; - return NULL; -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN - -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - audiod_function_t* audio = &_audiod_fct[func_id]; - - uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); - - TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio)); - - n_bytes_copied -= tu_fifo_count(&audio->tx_supp_ff[0]); - n_bytes_copied = n_bytes_copied*audio->tx_supp_ff[0].item_size; - - return n_bytes_copied; -} - -bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); -} - -tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx) -{ - if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff) return &_audiod_fct[func_id].tx_supp_ff[ff_idx]; - return NULL; -} - -#endif - - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - -// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user -uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint16_t len) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr)); - - // Check length - TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); - - memcpy(_audiod_fct[func_id].ep_int_ctr_buf, buffer, len); - - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr, _audiod_fct[func_id].ep_int_ctr_buf, len)); - - return true; -} - -#endif - - -// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. - -// n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) -{ - uint8_t idxItf; - uint8_t const *dummy2; - - uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); - - // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications - if (audio->alt_setting[idxItf] == 0) return false; - - // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or - // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - - // Send everything in ISO EP FIFO - uint16_t n_bytes_tx; - - // If support FIFOs are used, encode and schedule transmit -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN - switch (audio->format_type_tx) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - - case AUDIO_FORMAT_TYPE_I: - - switch (audio->format_type_I_tx) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: - - n_bytes_tx = audiod_encode_type_I_pcm(rhport, audio); - break; - - default: - // YOUR ENCODING IS REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - } - - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - -#else - // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule - - n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO - -#if USE_LINEAR_BUFFER_TX - tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); -#else - // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); -#endif - -#endif - - // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - - return true; -} - -#endif //CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -// Take samples from the support buffer and encode them into the IN EP software FIFO -// Returns number of bytes written into linear buffer - -/* 2.3.1.7.1 PCM Format -The PCM (Pulse Coded Modulation) format is the most commonly used audio format to represent audio -data streams. The audio data is not compressed and uses a signed two’s-complement fixed point format. It -is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused -bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the -range [-1, +1) - */ - -/* - * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples - * in the support FIFOs according to 2.3.1.5 Audio Streams. It does not control justification (left or right) and - * does not change the number of bytes per sample. - * */ - -// Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) -{ - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - - switch (nBytesToCopy) - { - case 1: - while(src < src_end) - { - *dst = *src++; - dst += n_ff_used; - } - break; - - case 2: - while(src < src_end) - { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - src += 2; - dst += 2 * n_ff_used; - } - break; - - case 3: - while(src < src_end) - { - // memcpy(dst, src, 3); - // src = (uint8_t *)src + 3; - // dst += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - - dst += 3 * (n_ff_used - 1); - } - break; - - case 4: - while(src < src_end) - { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; - src += 4; - dst += 4 * n_ff_used; - } - break; - } - - return dst; -} - -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio) -{ - // This function relies on the fact that the length of the support FIFOs was configured to be a multiple of the active sample size in bytes s.t. no sample is split within a wrap - // This is ensured within set_interface, where the FIFOs are reconfigured according to this size - - // We encode directly into IN EP's linear buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); - - // Determine amount of samples - uint8_t const n_ff_used = audio->n_ff_used_tx; - uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; - uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes - uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); - uint8_t cnt_ff; - - for (cnt_ff = 1; cnt_ff < n_ff_used; cnt_ff++) - { - uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); - if (count < nBytesPerFFToSend) - { - nBytesPerFFToSend = count; - } - } - - // Check if there is enough - if (nBytesPerFFToSend == 0) return 0; - - // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); - - // Round to full number of samples (flooring) - nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; - - // Encode - uint8_t * dst; - uint8_t * src_end; - - tu_fifo_buffer_info_t info; - - for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) - { - dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - - tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - - if (info.len_lin != 0) - { - info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length - src_end = (uint8_t *)info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used); - - // Limit up to desired length - info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); - - // Handle wrapped part of FIFO - if (info.len_wrap != 0) - { - src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used); - } - - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); - } - } - - return nBytesPerFFToSend * n_ff_used; -} -#endif //CFG_TUD_AUDIO_ENABLE_ENCODING - -// This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) -{ - return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->fb_val, 4); -} -#endif - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void audiod_init(void) -{ - tu_memclr(_audiod_fct, sizeof(_audiod_fct)); - - for(uint8_t i=0; ictrl_buf = ctrl_buf_1; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; - break; -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 - case 1: - audio->ctrl_buf = ctrl_buf_2; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 - case 2: - audio->ctrl_buf = ctrl_buf_3; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; - break; -#endif - } - - // Initialize active alternate interface buffers - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 - case 0: - audio->alt_setting = alt_setting_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 - case 1: - audio->alt_setting = alt_setting_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 - case 2: - audio->alt_setting = alt_setting_3; - break; -#endif - } - - // Initialize IN EP FIFO if required -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - case 0: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_1), NULL); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - case 1: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_2), NULL); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 - case 2: - tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_3), NULL); -#endif - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - - // Initialize linear buffers -#if USE_LINEAR_BUFFER_TX - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 - case 0: - audio->lin_buf_in = lin_buf_in_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 - case 1: - audio->lin_buf_in = lin_buf_in_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 - case 2: - audio->lin_buf_in = lin_buf_in_3; - break; -#endif - } -#endif // USE_LINEAR_BUFFER_TX - - // Initialize OUT EP FIFO if required -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - case 0: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_1)); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - case 1: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_2)); -#endif - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 - case 2: - tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_3)); -#endif - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - - // Initialize linear buffers -#if USE_LINEAR_BUFFER_RX - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 - case 0: - audio->lin_buf_out = lin_buf_out_1; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 - case 1: - audio->lin_buf_out = lin_buf_out_2; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 - case 2: - audio->lin_buf_out = lin_buf_out_3; - break; -#endif - } -#endif // USE_LINEAR_BUFFER_TX - - // Initialize TX support FIFOs if required -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->tx_supp_ff = tx_supp_ff_1; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->tx_supp_ff = tx_supp_ff_2; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->tx_supp_ff = tx_supp_ff_3; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX; - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - - // Initialize RX support FIFOs if required -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->rx_supp_ff = rx_supp_ff_1; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->rx_supp_ff = rx_supp_ff_2; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->rx_supp_ff = rx_supp_ff_3; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) - { - tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); -#endif - } - - break; -#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - switch (i) - { -#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX; - break; -#endif -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX; - break; -#endif - } -#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - } -} - -void audiod_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; iep_in_ff); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_clear(&audio->ep_out_ff); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } -#endif - } -} - -uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) max_len; - - TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); - - // Verify version is correct - this check can be omitted - TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); - - // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted - if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed - { - TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); - } - - // Alternate setting MUST be zero - this check can be omitted - TU_VERIFY(itf_desc->bAlternateSetting == 0); - - // Find available audio driver interface - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (!_audiod_fct[i].p_desc) - { - _audiod_fct[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one - _audiod_fct[i].rhport = rhport; - - // Setup descriptor lengths - switch (i) - { - case 0: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_1_DESC_LEN; - break; -#if CFG_TUD_AUDIO > 1 - case 1: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; - break; -#endif -#if CFG_TUD_AUDIO > 2 - case 2: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; - break; -#endif - } - - break; - } - } - - // Verify we found a free one - TU_ASSERT( i < CFG_TUD_AUDIO ); - - // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - uint16_t drv_len = _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor - - return drv_len; -} - -static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) -{ - uint8_t const itf = tu_u16_low(p_request->wIndex); - - // Find index of audio streaming interface - uint8_t func_id, idxItf; - uint8_t const *dummy; - - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[func_id].alt_setting[idxItf], 1)); - - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[func_id].alt_setting[idxItf]); - - return true; -} - -static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - // Here we need to do the following: - - // 1. Find the audio driver assigned to the given interface to be set - // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. - // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching - - // 2. Close EPs which are currently open - // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them - - // 3. Open new EP - - uint8_t const itf = tu_u16_low(p_request->wIndex); - uint8_t const alt = tu_u16_low(p_request->wValue); - - TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); - - // Find index of audio streaming interface and index of interface - uint8_t func_id, idxItf; - uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc)); - - audiod_function_t* audio = &_audiod_fct[func_id]; - - // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (audio->ep_in_as_intf_num == itf) - { - audio->ep_in_as_intf_num = 0; - usbd_edpt_close(rhport, audio->ep_in); - - // Clear FIFOs, since data is no longer valid -#if !CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_clear(&audio->ep_in_ff); -#else - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } -#endif - - // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - - audio->ep_in = 0; // Necessary? - - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (audio->ep_out_as_intf_num == itf) - { - audio->ep_out_as_intf_num = 0; - usbd_edpt_close(rhport, audio->ep_out); - - // Clear FIFOs, since data is no longer valid -#if !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_clear(&audio->ep_out_ff); -#else - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } -#endif - - // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - - audio->ep_out = 0; // Necessary? - - // Close corresponding feedback EP -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - usbd_edpt_close(rhport, audio->ep_fb); - audio->ep_fb = 0; // Necessary? -#endif - } -#endif - - // Save current alternative interface setting - audio->alt_setting[idxItf] = alt; - - // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface - // Get pointer at end - uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; - - // p_desc starts at required interface with alternate setting zero - while (p_desc < p_desc_end) - { - // Find correct interface - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) - { -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING - uint8_t const * p_desc_parse_for_params = p_desc; -#endif - // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary - uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; - while (foundEPs < nEps && p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) - { - tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); - - uint8_t const ep_addr = desc_ep->bEndpointAddress; - - //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! - usbd_edpt_clear_stall(rhport, ep_addr); - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 0x00) // Check if usage is data EP - { - // Save address - audio->ep_in = ep_addr; - audio->ep_in_as_intf_num = itf; - audio->ep_in_sz = tu_edpt_packet_size(desc_ep); - - // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters -#if CFG_TUD_AUDIO_ENABLE_ENCODING - audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); - - // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - const uint16_t active_fifo_depth = (audio->tx_supp_ff_sz_max / audio->n_bytes_per_sampe_tx) * audio->n_bytes_per_sampe_tx; - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); - } - audio->n_ff_used_tx = audio->n_channels_tx / audio->n_channels_per_ff_tx; - TU_ASSERT( audio->n_ff_used_tx <= audio->n_tx_supp_ff ); -#endif - -#endif - // Invoke callback - can be used to trigger data sampling if not already running - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - - // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded - // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); - } -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary - { - // Save address - audio->ep_out = ep_addr; - audio->ep_out_as_intf_num = itf; - audio->ep_out_sz = tu_edpt_packet_size(desc_ep); - -#if CFG_TUD_AUDIO_ENABLE_DECODING - audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); - - // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sampe_rx) * audio->n_bytes_per_sampe_rx; - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); - } - audio->n_ff_used_rx = audio->n_channels_rx / audio->n_channels_per_ff_rx; - TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff ); -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // In case of asynchronous EP, call Cb after ep_fb is set - if ( !(desc_ep->bmAttributes.sync == 0x01 && audio->ep_fb == 0) ) - { - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - } -#else - // Invoke callback - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); -#endif - // Prepare for incoming data -#if USE_LINEAR_BUFFER_RX - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); -#else - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); -#endif - } - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) // Check if usage is explicit data feedback - { - audio->ep_fb = ep_addr; - - // Invoke callback after ep_out is set - if (audio->ep_out != 0) - { - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - } - } -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - - foundEPs += 1; - } - p_desc = tu_desc_next(p_desc); - } - - TU_VERIFY(foundEPs == nEps); - - // We are done - abort loop - break; - } - - // Moving forward - p_desc = tu_desc_next(p_desc); - } - - tud_control_status(rhport, p_request); - - return true; -} - -// Invoked when class request DATA stage is finished. -// return false to stall control EP (e.g Host send non-sense DATA) -static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) -{ - // Handle audio class specific set requests - if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) - { - uint8_t func_id; - - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - if (entityID != 0) - { - if (tud_audio_set_req_entity_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - else - { - if (tud_audio_set_req_itf_cb) - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - - // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - break; - // Unknown/Unsupported recipient - default: TU_BREAKPOINT(); return false; - } - } - return true; -} - -// Handle class control request -// return false to stall control endpoint (e.g unsupported request) -static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) - { - switch (p_request->bRequest) - { - case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); - - case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); - - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; - } - } - - // Handle class requests - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) - { - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t func_id; - - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_entity_cb) - { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall - } - } - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_itf_cb) - { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall - } - } - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } - } - } - break; - - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } - - // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz)); - return true; - } - - // There went something wrong - unsupported control request type - TU_BREAKPOINT(); - return false; -} - -bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - return audiod_control_request(rhport, request); - } - else if ( stage == CONTROL_STAGE_DATA ) - { - return audiod_control_complete(rhport, request); - } - - return true; -} - -bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - (void) xferred_bytes; - - // Search for interface belonging to given end point address and proceed as required - uint8_t func_id; - for (func_id = 0; func_id < CFG_TUD_AUDIO; func_id++) - { - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - - // Data transmission of control interrupt finished - if (_audiod_fct[func_id].ep_int_ctr == ep_addr) - { - // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) - // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? - // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? - - // I assume here, that things above are handled by PHY - // All transmission is done - what remains to do is to inform job was completed - - if (tud_audio_int_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, (uint16_t) xferred_bytes)); - } - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - - // Data transmission of audio packet finished - if (_audiod_fct[func_id].ep_in == ep_addr && _audiod_fct[func_id].alt_setting != 0) - { - // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." - // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." - // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. - - // Check if there is data to load into EPs buffer - if not load it with ZLP - // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! - // This is the only place where we can fill something into the EPs buffer! - - // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); - - // Transmission of ZLP is done by audiod_tx_done_cb() - return true; - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - - // New audio packet received - if (_audiod_fct[func_id].ep_out == ep_addr) - { - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[func_id], (uint16_t) xferred_bytes)); - return true; - } - - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Transmission of feedback EP finished - if (_audiod_fct[func_id].ep_fb == ep_addr) - { - if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - - // Schedule a transmit with the new value if EP is not busy - if (!usbd_edpt_busy(rhport, _audiod_fct[func_id].ep_fb)) - { - // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_fct[func_id]); - } - } -#endif -#endif - } - - return false; -} - -bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) -{ - // Handles only sending of data not receiving - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; - - // Get corresponding driver index - uint8_t func_id; - uint8_t itf = TU_U16_LOW(p_request->wIndex); - - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - } - break; - - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } - - // Crop length - if (len > _audiod_fct[func_id].ctrl_buf_sz) len = _audiod_fct[func_id].ctrl_buf_sz; - - // Copy into buffer - memcpy((void *)_audiod_fct[func_id].ctrl_buf, data, (size_t)len); - - // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len); -} - -// This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function -// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and -// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int) -{ - if (audio->p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; - - // Advance past AC descriptors - uint8_t const *p_desc = tu_desc_next(audio->p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - uint8_t tmp = 0; - while (p_desc < p_desc_end) - { - // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0) - { - if (((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) - { - *idxItf = tmp; - *pp_desc_int = p_desc; - return true; - } - // Increase index, bytes read, and pointer - tmp++; - } - p_desc = tu_desc_next(p_desc); - } - } - return false; -} - -// This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function -// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and -// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int) -{ - // Loop over audio driver interfaces - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) - { - *func_id = i; - return true; - } - } - - return false; -} - -// Verify an entity with the given ID exists and returns also the corresponding driver index -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - // Look for the correct driver by checking if the unique standard AC interface number fits - if (_audiod_fct[i].p_desc && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) - { - // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between - uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); // Points to CS AC descriptor - uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; - p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor - - while (p_desc < p_desc_end) - { - if (p_desc[3] == entityID) // Entity IDs are always at offset 3 - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (_audiod_fct[i].p_desc) - { - // Get pointer at beginning and end - uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) -{ - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (_audiod_fct[i].p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length; - - // Advance past AC descriptors - EP we look for are streaming EPs - uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) - { - *func_id = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } - } - return false; -} - -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -// p_desc points to the AS interface of alternate setting zero -// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter -// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf) -{ - p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor - - while (p_desc < p_desc_end) - { - // Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break; - - // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) - { -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently -#endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num) break; -#endif -#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_out_as_intf_num) break; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (as_itf == audio->ep_in_as_intf_num) - { - audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_tx = (audio_format_type_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType); - -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio->format_type_I_tx = (audio_data_format_type_I_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats); -#endif - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf == audio->ep_out_as_intf_num) - { - audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; -#endif - } -#endif - } - - // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) - { -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently -#endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num) break; -#endif -#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_out_as_intf_num) break; -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN - if (as_itf == audio->ep_in_as_intf_num) - { - audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf == audio->ep_out_as_intf_num) - { - audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; - } -#endif - } -#endif - - // Other format types are not supported yet - - p_desc = tu_desc_next(p_desc); - } -} -#endif - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - // Format the feedback value -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION - if ( TUSB_SPEED_FULL == tud_speed_get() ) - { - uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; - - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - }else -#else - { - // Send value as-is, caller will choose the appropriate format - _audiod_fct[func_id].fb_val = feedback; - } -#endif - - // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) - { - return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]); - } - - return true; -} -#endif - -// No security checks here - internal function only which should always succeed -uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) -{ - for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO; cnt++) - { - if (&_audiod_fct[cnt] == audio) return cnt; - } - return 0; -} - -#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h deleted file mode 100644 index f406cf281..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/audio/audio_device.h +++ /dev/null @@ -1,637 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_AUDIO_DEVICE_H_ -#define _TUSB_AUDIO_DEVICE_H_ - -#include "audio.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -// All sizes are in bytes! - -#ifndef CFG_TUD_AUDIO_FUNC_1_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#endif - -// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces -#ifndef CFG_TUD_AUDIO_FUNC_1_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! -#endif -#endif - -// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors -#ifndef CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif - -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif -#endif - -// End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 -#ifndef CFG_TUD_AUDIO_ENABLE_EP_IN -#define CFG_TUD_AUDIO_ENABLE_EP_IN 0 // TX -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_EP_OUT -#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0 // RX -#endif - -// Maximum EP sizes for all alternate AS interface settings - used for checks and buffer allocation -#if CFG_TUD_AUDIO_ENABLE_EP_IN -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX -#error You must tell the driver the biggest EP IN size! -#endif -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX -#error You must tell the driver the biggest EP OUT size! -#endif -#endif -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - -// Software EP FIFO buffer sizes - must be >= max EP SIZEs! -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ -#define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0 -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif - -#if CFG_TUD_AUDIO > 1 -#if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif - -#if CFG_TUD_AUDIO > 1 -#if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX -#error EP software buffer size MUST BE at least as big as maximum EP size -#endif -#endif -#endif - -// Enable/disable feedback EP (required for asynchronous RX applications) -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 -#endif - -// Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set(). -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 -#endif - -// Audio interrupt control EP size - disabled if 0 -#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) -#endif - -#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) -#endif - -// Use software encoding/decoding - -// The software coding feature of the driver is not mandatory. It is useful if, for instance, you have two I2S streams which need to be interleaved -// into a single PCM stream as SAMPLE_1 | SAMPLE_2 | SAMPLE_3 | SAMPLE_4. -// -// Currently, only PCM type I encoding/decoding is supported! -// -// If the coding feature is to be used, support FIFOs need to be configured. Their sizes and numbers are defined below. - -// Encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the -// support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using -// - tud_audio_n_write() or -// - tud_audio_n_read(). -// To write/read to/from the support FIFOs use -// - tud_audio_n_write_support_ff() or -// - tud_audio_n_read_support_ff(). -// -// The encoding/decoding format type done is defined below. -// -// The encoding/decoding starts when the private callback functions -// - audio_tx_done_cb() -// - audio_rx_done_cb() -// are invoked. If support FIFOs are used, the corresponding encoding/decoding functions are called from there. -// Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions -// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() -// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() -// if you want to get informed what happened. -// -// If you don't use the support FIFOs you may use the public callback functions -// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() -// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() -// to write/read from/into the EP_X_SW_BUFFER_FIFOs at the right time. -// -// If you need a different encoding which is not support so far implement it in the -// - audio_tx_done_cb() -// - audio_rx_done_cb() -// functions. - -// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size -// The actual coding parameters of active AS alternate interface is parsed from the descriptors - -// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)! -// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!! - -// For PCM encoding/decoding - -#ifndef CFG_TUD_AUDIO_ENABLE_ENCODING -#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_DECODING -#define CFG_TUD_AUDIO_ENABLE_DECODING 0 -#endif - -// This enabling allows to save the current coding parameters e.g. # of bytes per sample etc. - TYPE_I includes common PCM encoding -#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING 0 -#endif - -// Type I Coding parameters not given within UAC2 descriptors -// It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING -#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING -#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#endif - -// Remaining types not support so far - -// Number of support FIFOs to set up - multiple channels can be handled by one FIFO - very common is two channels per FIFO stemming from one I2S interface -#ifndef CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO 0 -#endif - -// Size of support FIFOs IN BYTES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_FUNC_X_N_TX_SUPP_SW_FIFO and CFG_TUD_AUDIO_FUNC_X_N_RX_SUPP_SW_FIFO -#ifndef CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of TX channels) / (# of TX support FIFOs) * max(# of bytes per sample) -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of RX channels) / (# of RX support FIFOs) * max(# of bytes per sample) -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ 0 -#endif - -//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); - -// Supported types of this driver: -// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup AUDIO_Serial Serial - * @{ - * \defgroup AUDIO_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -// CFG_TUD_AUDIO > 1 -//--------------------------------------------------------------------+ -bool tud_audio_n_mounted (uint8_t func_id); - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available (uint8_t func_id); -uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); -bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO -tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs -uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); -uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); -tu_fifo_t* tud_audio_n_get_rx_support_ff (uint8_t func_id, uint8_t ff_idx); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); -bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO -tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); -uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); -tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx); -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len); -#endif - -//--------------------------------------------------------------------+ -// Application API (Interface0) -//--------------------------------------------------------------------+ - -static inline bool tud_audio_mounted (void); - -// RX API - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -static inline uint16_t tud_audio_available (void); -static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO -static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -static inline tu_fifo_t* tud_audio_get_ep_out_ff (void); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); -static inline tu_fifo_t* tud_audio_get_rx_support_ff (uint8_t ff_idx); -#endif - -// TX API - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_write (const void * data, uint16_t len); -static inline bool tud_audio_clear_ep_in_ff (void); -static inline tu_fifo_t* tud_audio_get_ep_in_ff (void); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_flush_tx_support_ff (void); -static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); -static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx); -#endif - -// INT CTR API - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); -#endif - -// Buffer control EP data and schedule a transmit -// This function is intended to be used if you do not have a persistent buffer or memory location available (e.g. non-local variables) and need to answer onto a -// get request. This function buffers your answer request frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it. -// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer pointer in pointing. If you already have such -// available you may directly use 'tud_control_xfer(...)'. In this case data does not need to be copied into an additional buffer and you save some time. -// If the request's wLength is zero, a status packet is sent instead. -bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -#if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); - -// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed. -// -// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default, -// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set, then tinyusb -// expects 16.16 format and handles the conversion to 10.14 on FS. -// -// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and macOS it seems the -// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format. -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); -static inline bool tud_audio_fb_set(uint32_t feedback); -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied); -#endif - -// Invoked when audio set interface request received -TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio set interface request received which closes an EP -TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific set request received for an EP -TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific set request received for an interface -TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific set request received for an entity -TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); - -// Invoked when audio class specific get request received for an EP -TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific get request received for an interface -TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -// Invoked when audio class specific get request received for an entity -TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline bool tud_audio_mounted(void) -{ - return tud_audio_n_mounted(0); -} - -// RX API - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING - -static inline uint16_t tud_audio_available(void) -{ - return tud_audio_n_available(0); -} - -static inline uint16_t tud_audio_read(void* buffer, uint16_t bufsize) -{ - return tud_audio_n_read(0, buffer, bufsize); -} - -static inline bool tud_audio_clear_ep_out_ff(void) -{ - return tud_audio_n_clear_ep_out_ff(0); -} - -static inline tu_fifo_t* tud_audio_get_ep_out_ff(void) -{ - return tud_audio_n_get_ep_out_ff(0); -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - -static inline bool tud_audio_clear_rx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_clear_rx_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_available_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_available_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, uint16_t bufsize) -{ - return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); -} - -static inline tu_fifo_t* tud_audio_get_rx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_get_rx_support_ff(0, ff_idx); -} - -#endif - -// TX API - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - -static inline uint16_t tud_audio_write(const void * data, uint16_t len) -{ - return tud_audio_n_write(0, data, len); -} - -static inline bool tud_audio_clear_ep_in_ff(void) -{ - return tud_audio_n_clear_ep_in_ff(0); -} - -static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) -{ - return tud_audio_n_get_ep_in_ff(0); -} - -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - -static inline uint16_t tud_audio_flush_tx_support_ff(void) -{ - return tud_audio_n_flush_tx_support_ff(0); -} - -static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_clear_tx_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * data, uint16_t len) -{ - return tud_audio_n_write_support_ff(0, ff_idx, data, len); -} - -static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_get_tx_support_ff(0, ff_idx); -} - -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) -{ - return tud_audio_int_ctr_n_write(0, buffer, len); -} -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static inline bool tud_audio_fb_set(uint32_t feedback) -{ - return tud_audio_n_fb_set(0, feedback); -} -#endif - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_AUDIO_DEVICE_H_ */ - -/** @} */ -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c deleted file mode 100644 index 8ef609622..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_BTH) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "bth_device.h" -#include - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_ev; - uint8_t ep_acl_in; - uint8_t ep_acl_out; - uint8_t ep_voice[2]; // Not used yet - uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT]; - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE]; - -} btd_interface_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf; - -static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) -{ - // skip if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(TUD_OPT_RHPORT, ep)); - - TU_ASSERT(usbd_edpt_xfer(TUD_OPT_RHPORT, ep, data, len)); - - return true; -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ - - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -bool tud_bt_event_send(void *event, uint16_t event_len) -{ - return bt_tx_data(_btd_itf.ep_ev, event, event_len); -} - -bool tud_bt_acl_data_send(void *event, uint16_t event_len) -{ - return bt_tx_data(_btd_itf.ep_acl_in, event, event_len); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void btd_init(void) -{ - tu_memclr(&_btd_itf, sizeof(_btd_itf)); -} - -void btd_reset(uint8_t rhport) -{ - (void)rhport; -} - -uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - tusb_desc_endpoint_t const *desc_ep; - uint16_t drv_len = 0; - // Size of single alternative of ISO interface - const uint16_t iso_alt_itf_size = sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t); - // Size of hci interface - const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); - // Ensure this is BT Primary Controller - TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && - TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); - - TU_ASSERT(itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size); - - _btd_itf.itf_num = itf_desc->bInterfaceNumber; - - desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); - _btd_itf.ep_ev = desc_ep->bEndpointAddress; - - // Open endpoint pair - TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, - &_btd_itf.ep_acl_in), 0); - - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(tu_desc_next(desc_ep))); - - // Prepare for incoming data from host - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); - - drv_len = hci_itf_size; - - // Ensure this is still BT Primary Controller - TU_ASSERT(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && - TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); - TU_ASSERT(itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size + drv_len); - - uint8_t dir; - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); - TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; - // Store endpoint size for alternative - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; - // Store endpoint size for alternative - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - drv_len += iso_alt_itf_size; - - for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { - // Make sure rest of alternatives matches - itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); - if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || - TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || - TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || - TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) - { - // Not an Iso interface instance - break; - } - TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - // Verify that alternative endpoint are same as first ones - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - - desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); - dir = tu_edpt_dir(desc_ep->bEndpointAddress); - // Verify that alternative endpoint are same as first ones - TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && - _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); - _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t) tu_edpt_packet_size(desc_ep); - drv_len += iso_alt_itf_size; - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) -{ - (void)rhport; - - if ( stage == CONTROL_STAGE_SETUP ) - { - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) - { - // HCI command packet addressing for single function Primary Controllers - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); - } - else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) - { - if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) - { - // TODO: Set interface it would involve changing size of endpoint size - } - else - { - // HCI command packet for Primary Controller function in a composite device - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); - } - } - else return false; - - return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, sizeof(_btd_itf.hci_cmd)); - } - else if ( stage == CONTROL_STAGE_DATA ) - { - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, tu_min16(request->wLength, sizeof(_btd_itf.hci_cmd))); - } - - return true; -} - -bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void)result; - - // received new data from host - if (ep_addr == _btd_itf.ep_acl_out) - { - if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes); - - // prepare for next data - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); - } - else if (ep_addr == _btd_itf.ep_ev) - { - if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes); - } - else if (ep_addr == _btd_itf.ep_acl_in) - { - if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h deleted file mode 100644 index 1b90d0915..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/bth/bth_device.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jerzy Kasenberg - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_BTH_DEVICE_H_ -#define _TUSB_BTH_DEVICE_H_ - -#include -#include - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ -#ifndef CFG_TUD_BTH_EVENT_EPSIZE -#define CFG_TUD_BTH_EVENT_EPSIZE 16 -#endif -#ifndef CFG_TUD_BTH_DATA_EPSIZE -#define CFG_TUD_BTH_DATA_EPSIZE 64 -#endif - -typedef struct TU_ATTR_PACKED -{ - uint16_t op_code; - uint8_t param_length; - uint8_t param[255]; -} bt_hci_cmd_t; - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when HCI command was received over USB from Bluetooth host. -// Detailed format is described in Bluetooth core specification Vol 2, -// Part E, 5.4.1. -// Length of the command is from 3 bytes (2 bytes for OpCode, -// 1 byte for parameter total length) to 258. -TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); - -// Invoked when ACL data was received over USB from Bluetooth host. -// Detailed format is described in Bluetooth core specification Vol 2, -// Part E, 5.4.2. -// Length is from 4 bytes, (12 bits for Handle, 4 bits for flags -// and 16 bits for data total length) to endpoint size. -TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); - -// Called when event sent with tud_bt_event_send() was delivered to BT stack. -// Controller can release/reuse buffer with Event packet at this point. -TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes); - -// Called when ACL data that was sent with tud_bt_acl_data_send() -// was delivered to BT stack. -// Controller can release/reuse buffer with ACL packet at this point. -TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); - -// Bluetooth controller calls this function when it wants to send even packet -// as described in Bluetooth core specification Vol 2, Part E, 5.4.4. -// Event has at least 2 bytes, first is Event code second contains parameter -// total length. Controller can release/reuse event memory after -// tud_bt_event_sent_cb() is called. -bool tud_bt_event_send(void *event, uint16_t event_len); - -// Bluetooth controller calls this to send ACL data packet -// as described in Bluetooth core specification Vol 2, Part E, 5.4.2 -// Minimum length is 4 bytes, (12 bits for Handle, 4 bits for flags -// and 16 bits for data total length). Upper limit is not limited -// to endpoint size since buffer is allocate by controller -// and must not be reused till tud_bt_acl_data_sent_cb() is called. -bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void btd_init (void); -void btd_reset (uint8_t rhport); -uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool btd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *request); -bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_BTH_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h deleted file mode 100644 index e345139ea..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc.h +++ /dev/null @@ -1,409 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_CDC Communication Device Class (CDC) - * Currently only Abstract Control Model subclass is supported - * @{ */ - -#ifndef _TUSB_CDC_H__ -#define _TUSB_CDC_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/** \defgroup ClassDriver_CDC_Common Common Definitions - * @{ */ - -// TODO remove -/// CDC Pipe ID, used to indicate which pipe the API is addressing to (Notification, Out, In) -typedef enum -{ - CDC_PIPE_NOTIFICATION , ///< Notification pipe - CDC_PIPE_DATA_IN , ///< Data in pipe - CDC_PIPE_DATA_OUT , ///< Data out pipe - CDC_PIPE_ERROR , ///< Invalid Pipe ID -}cdc_pipeid_t; - -//--------------------------------------------------------------------+ -// CDC Communication Interface Class -//--------------------------------------------------------------------+ - -/// Communication Interface Subclass Codes -typedef enum -{ - CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01 , ///< Direct Line Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL = 0x02 , ///< Abstract Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL = 0x03 , ///< Telephone Control Model [USBPSTN1.2] - CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL = 0x04 , ///< Multi-Channel Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL = 0x05 , ///< CAPI Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL = 0x06 , ///< Ethernet Networking Control Model [USBECM1.2] - CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL = 0x07 , ///< ATM Networking Control Model [USBATM1.2] - CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL = 0x08 , ///< Wireless Handset Control Model [USBWMC1.1] - CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT = 0x09 , ///< Device Management [USBWMC1.1] - CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL = 0x0A , ///< Mobile Direct Line Model [USBWMC1.1] - CDC_COMM_SUBCLASS_OBEX = 0x0B , ///< OBEX [USBWMC1.1] - CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL = 0x0C , ///< Ethernet Emulation Model [USBEEM1.0] - CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL = 0x0D ///< Network Control Model [USBNCM1.0] -} cdc_comm_sublcass_type_t; - -/// Communication Interface Protocol Codes -typedef enum -{ - CDC_COMM_PROTOCOL_NONE = 0x00 , ///< No specific protocol - CDC_COMM_PROTOCOL_ATCOMMAND = 0x01 , ///< AT Commands: V.250 etc - CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 = 0x02 , ///< AT Commands defined by PCCA-101 - CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO = 0x03 , ///< AT Commands defined by PCCA-101 & Annex O - CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 = 0x04 , ///< AT Commands defined by GSM 07.07 - CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 = 0x05 , ///< AT Commands defined by 3GPP 27.007 - CDC_COMM_PROTOCOL_ATCOMMAND_CDMA = 0x06 , ///< AT Commands defined by TIA for CDMA - CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL = 0x07 ///< Ethernet Emulation Model -} cdc_comm_protocol_type_t; - -//------------- SubType Descriptor in COMM Functional Descriptor -------------// -/// Communication Interface SubType Descriptor -typedef enum -{ - CDC_FUNC_DESC_HEADER = 0x00 , ///< Header Functional Descriptor, which marks the beginning of the concatenated set of functional descriptors for the interface. - CDC_FUNC_DESC_CALL_MANAGEMENT = 0x01 , ///< Call Management Functional Descriptor. - CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT = 0x02 , ///< Abstract Control Management Functional Descriptor. - CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT = 0x03 , ///< Direct Line Management Functional Descriptor. - CDC_FUNC_DESC_TELEPHONE_RINGER = 0x04 , ///< Telephone Ringer Functional Descriptor. - CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY = 0x05 , ///< Telephone Call and Line State Reporting Capabilities Functional Descriptor. - CDC_FUNC_DESC_UNION = 0x06 , ///< Union Functional Descriptor - CDC_FUNC_DESC_COUNTRY_SELECTION = 0x07 , ///< Country Selection Functional Descriptor - CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES = 0x08 , ///< Telephone Operational ModesFunctional Descriptor - CDC_FUNC_DESC_USB_TERMINAL = 0x09 , ///< USB Terminal Functional Descriptor - CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL = 0x0A , ///< Network Channel Terminal Descriptor - CDC_FUNC_DESC_PROTOCOL_UNIT = 0x0B , ///< Protocol Unit Functional Descriptor - CDC_FUNC_DESC_EXTENSION_UNIT = 0x0C , ///< Extension Unit Functional Descriptor - CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT = 0x0D , ///< Multi-Channel Management Functional Descriptor - CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT = 0x0E , ///< CAPI Control Management Functional Descriptor - CDC_FUNC_DESC_ETHERNET_NETWORKING = 0x0F , ///< Ethernet Networking Functional Descriptor - CDC_FUNC_DESC_ATM_NETWORKING = 0x10 , ///< ATM Networking Functional Descriptor - CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL = 0x11 , ///< Wireless Handset Control Model Functional Descriptor - CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL = 0x12 , ///< Mobile Direct Line Model Functional Descriptor - CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL = 0x13 , ///< MDLM Detail Functional Descriptor - CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL = 0x14 , ///< Device Management Model Functional Descriptor - CDC_FUNC_DESC_OBEX = 0x15 , ///< OBEX Functional Descriptor - CDC_FUNC_DESC_COMMAND_SET = 0x16 , ///< Command Set Functional Descriptor - CDC_FUNC_DESC_COMMAND_SET_DETAIL = 0x17 , ///< Command Set Detail Functional Descriptor - CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL = 0x18 , ///< Telephone Control Model Functional Descriptor - CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER = 0x19 , ///< OBEX Service Identifier Functional Descriptor - CDC_FUNC_DESC_NCM = 0x1A , ///< NCM Functional Descriptor -}cdc_func_desc_type_t; - -//--------------------------------------------------------------------+ -// CDC Data Interface Class -//--------------------------------------------------------------------+ - -// SUBCLASS code of Data Interface is not used and should/must be zero - -// Data Interface Protocol Codes -typedef enum{ - CDC_DATA_PROTOCOL_ISDN_BRI = 0x30, ///< Physical interface protocol for ISDN BRI - CDC_DATA_PROTOCOL_HDLC = 0x31, ///< HDLC - CDC_DATA_PROTOCOL_TRANSPARENT = 0x32, ///< Transparent - CDC_DATA_PROTOCOL_Q921_MANAGEMENT = 0x50, ///< Management protocol for Q.921 data link protocol - CDC_DATA_PROTOCOL_Q921_DATA_LINK = 0x51, ///< Data link protocol for Q.931 - CDC_DATA_PROTOCOL_Q921_TEI_MULTIPLEXOR = 0x52, ///< TEI-multiplexor for Q.921 data link protocol - CDC_DATA_PROTOCOL_V42BIS_DATA_COMPRESSION = 0x90, ///< Data compression procedures - CDC_DATA_PROTOCOL_EURO_ISDN = 0x91, ///< Euro-ISDN protocol control - CDC_DATA_PROTOCOL_V24_RATE_ADAPTION_TO_ISDN = 0x92, ///< V.24 rate adaptation to ISDN - CDC_DATA_PROTOCOL_CAPI_COMMAND = 0x93, ///< CAPI Commands - CDC_DATA_PROTOCOL_HOST_BASED_DRIVER = 0xFD, ///< Host based driver. Note: This protocol code should only be used in messages between host and device to identify the host driver portion of a protocol stack. - CDC_DATA_PROTOCOL_IN_PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0xFE ///< The protocol(s) are described using a ProtocolUnit Functional Descriptors on Communications Class Interface -}cdc_data_protocol_type_t; - -//--------------------------------------------------------------------+ -// Management Element Request (Control Endpoint) -//--------------------------------------------------------------------+ - -/// Communication Interface Management Element Request Codes -typedef enum -{ - CDC_REQUEST_SEND_ENCAPSULATED_COMMAND = 0x00, ///< is used to issue a command in the format of the supported control protocol of the Communications Class interface - CDC_REQUEST_GET_ENCAPSULATED_RESPONSE = 0x01, ///< is used to request a response in the format of the supported control protocol of the Communications Class interface. - CDC_REQUEST_SET_COMM_FEATURE = 0x02, - CDC_REQUEST_GET_COMM_FEATURE = 0x03, - CDC_REQUEST_CLEAR_COMM_FEATURE = 0x04, - - CDC_REQUEST_SET_AUX_LINE_STATE = 0x10, - CDC_REQUEST_SET_HOOK_STATE = 0x11, - CDC_REQUEST_PULSE_SETUP = 0x12, - CDC_REQUEST_SEND_PULSE = 0x13, - CDC_REQUEST_SET_PULSE_TIME = 0x14, - CDC_REQUEST_RING_AUX_JACK = 0x15, - - CDC_REQUEST_SET_LINE_CODING = 0x20, - CDC_REQUEST_GET_LINE_CODING = 0x21, - CDC_REQUEST_SET_CONTROL_LINE_STATE = 0x22, - CDC_REQUEST_SEND_BREAK = 0x23, - - CDC_REQUEST_SET_RINGER_PARMS = 0x30, - CDC_REQUEST_GET_RINGER_PARMS = 0x31, - CDC_REQUEST_SET_OPERATION_PARMS = 0x32, - CDC_REQUEST_GET_OPERATION_PARMS = 0x33, - CDC_REQUEST_SET_LINE_PARMS = 0x34, - CDC_REQUEST_GET_LINE_PARMS = 0x35, - CDC_REQUEST_DIAL_DIGITS = 0x36, - CDC_REQUEST_SET_UNIT_PARAMETER = 0x37, - CDC_REQUEST_GET_UNIT_PARAMETER = 0x38, - CDC_REQUEST_CLEAR_UNIT_PARAMETER = 0x39, - CDC_REQUEST_GET_PROFILE = 0x3A, - - CDC_REQUEST_SET_ETHERNET_MULTICAST_FILTERS = 0x40, - CDC_REQUEST_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41, - CDC_REQUEST_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42, - CDC_REQUEST_SET_ETHERNET_PACKET_FILTER = 0x43, - CDC_REQUEST_GET_ETHERNET_STATISTIC = 0x44, - - CDC_REQUEST_SET_ATM_DATA_FORMAT = 0x50, - CDC_REQUEST_GET_ATM_DEVICE_STATISTICS = 0x51, - CDC_REQUEST_SET_ATM_DEFAULT_VC = 0x52, - CDC_REQUEST_GET_ATM_VC_STATISTICS = 0x53, - - CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60, -}cdc_management_request_t; - -//--------------------------------------------------------------------+ -// Management Elemenent Notification (Notification Endpoint) -//--------------------------------------------------------------------+ - -/// 6.3 Notification Codes -typedef enum -{ - CDC_NOTIF_NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status. - CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request. - CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, - CDC_NOTIF_RING_DETECT = 0x09, - CDC_NOTIF_SERIAL_STATE = 0x20, - CDC_NOTIF_CALL_STATE_CHANGE = 0x28, - CDC_NOTIF_LINE_STATE_CHANGE = 0x29, - CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, ///< This notification allows the device to inform the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred - CDC_NOTIF_MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40, -}cdc_notification_request_t; - -//--------------------------------------------------------------------+ -// Class Specific Functional Descriptor (Communication Interface) -//--------------------------------------------------------------------+ - -// Start of all packed definitions for compiler without per-type packed -TU_ATTR_PACKED_BEGIN -TU_ATTR_BIT_FIELD_ORDER_BEGIN - -/// Header Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ - uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal -}cdc_desc_func_header_t; - -/// Union Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - uint8_t bControlInterface ; ///< Interface number of Communication Interface - uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface -}cdc_desc_func_union_t; - -#define cdc_desc_func_union_n_t(no_slave)\ - struct TU_ATTR_PACKED { \ - uint8_t bLength ;\ - uint8_t bDescriptorType ;\ - uint8_t bDescriptorSubType ;\ - uint8_t bControlInterface ;\ - uint8_t bSubordinateInterface[no_slave] ;\ -} - -/// Country Selection Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. - uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. -}cdc_desc_func_country_selection_t; - -#define cdc_desc_func_country_selection_n_t(no_country) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ;\ - uint8_t bDescriptorType ;\ - uint8_t bDescriptorSubType ;\ - uint8_t iCountryCodeRelDate ;\ - uint16_t wCountryCode[no_country] ;\ -} - -//--------------------------------------------------------------------+ -// PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS -//--------------------------------------------------------------------+ - -/// \brief Call Management Functional Descriptor -/// \details This functional descriptor describes the processing of calls for the Communications Class interface. -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - - struct { - uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. - uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. - uint8_t TU_RESERVED : 6; - } bmCapabilities; - - uint8_t bDataInterface; -}cdc_desc_func_call_management_t; - -typedef struct TU_ATTR_PACKED -{ - uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. - uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. - uint8_t support_send_break : 1; ///< Device supports the request Send_Break - uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. - uint8_t TU_RESERVED : 4; -}cdc_acm_capability_t; - -TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); - -/// Abstract Control Management Functional Descriptor -/// This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - cdc_acm_capability_t bmCapabilities ; -}cdc_desc_func_acm_t; - -/// \brief Direct Line Management Functional Descriptor -/// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - struct { - uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. - uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. - uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. - uint8_t TU_RESERVED : 5; - } bmCapabilities; -}cdc_desc_func_direct_line_management_t; - -/// \brief Telephone Ringer Functional Descriptor -/// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, -/// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - uint8_t bRingerVolSteps ; - uint8_t bNumRingerPatterns ; -}cdc_desc_func_telephone_ringer_t; - -/// \brief Telephone Operational Modes Functional Descriptor -/// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by -/// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - struct { - uint8_t simple_mode : 1; - uint8_t standalone_mode : 1; - uint8_t computer_centric_mode : 1; - uint8_t TU_RESERVED : 5; - } bmCapabilities; -}cdc_desc_func_telephone_operational_modes_t; - -/// \brief Telephone Call and Line State Reporting Capabilities Descriptor -/// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a -/// telephone device to report optional call and line states. -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - struct { - uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone - uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states. - uint32_t caller_id : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information. - uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns. - uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line. - uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification - uint32_t TU_RESERVED : 26; - } bmCapabilities; -}cdc_desc_func_telephone_call_state_reporting_capabilities_t; - -// TODO remove -static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) -{ - return p_desc[2]; -} - -//--------------------------------------------------------------------+ -// Requests -//--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED -{ - uint32_t bit_rate; - uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits - uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space - uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 -} cdc_line_coding_t; - -TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR. - uint16_t half_duplex_carrier_control : 1; - uint16_t : 14; -} cdc_line_control_state_t; - -TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); - -TU_ATTR_PACKED_END // End of all packed definitions -TU_ATTR_BIT_FIELD_ORDER_END - -#ifdef __cplusplus - } -#endif - -#endif - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c deleted file mode 100644 index 08f2af253..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "cdc_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -enum -{ - BULK_PACKET_SIZE = (TUD_OPT_HIGH_SPEED ? 512 : 64) -}; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) - uint8_t line_state; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - char wanted_char; - cdc_line_coding_t line_coding; - - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - - uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE]; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; -#endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE]; - -}cdcd_interface_t; - -#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; - -static bool _prep_out_transaction (cdcd_interface_t* p_cdc) -{ - uint8_t const rhport = TUD_OPT_RHPORT; - uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= sizeof(p_cdc->epout_buf)); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out)); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_cdc->rx_ff); - - if ( available >= sizeof(p_cdc->epout_buf) ) - { - return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_cdc->ep_out); - - return false; - } -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_cdc_n_connected(uint8_t itf) -{ - // DTR (bit 0) active is considered as connected - return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0); -} - -uint8_t tud_cdc_n_get_line_state (uint8_t itf) -{ - return _cdcd_itf[itf].line_state; -} - -void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding) -{ - (*coding) = _cdcd_itf[itf].line_coding; -} - -void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted) -{ - _cdcd_itf[itf].wanted_char = wanted; -} - - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ -uint32_t tud_cdc_n_available(uint8_t itf) -{ - return tu_fifo_count(&_cdcd_itf[itf].rx_ff); -} - -uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, bufsize); - _prep_out_transaction(p_cdc); - return num_read; -} - -bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) -{ - return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); -} - -void tud_cdc_n_read_flush (uint8_t itf) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - tu_fifo_clear(&p_cdc->rx_ff); - _prep_out_transaction(p_cdc); -} - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ -uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, bufsize); - - // flush if queue more than packet size - if ( tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE ) - { - tud_cdc_n_write_flush(itf); - } - - return ret; -} - -uint32_t tud_cdc_n_write_flush (uint8_t itf) -{ - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - - // Skip if usb is not ready yet - TU_VERIFY( tud_ready(), 0 ); - - // No data to send - if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; - - uint8_t const rhport = TUD_OPT_RHPORT; - - // Claim the endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); - - // Pull data from FIFO - uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); - - if ( count ) - { - TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); - return count; - }else - { - // Release endpoint since we don't make any transfer - // Note: data is dropped if terminal is not connected - usbd_edpt_release(rhport, p_cdc->ep_in); - return 0; - } -} - -uint32_t tud_cdc_n_write_available (uint8_t itf) -{ - return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff); -} - -bool tud_cdc_n_write_clear (uint8_t itf) -{ - return tu_fifo_clear(&_cdcd_itf[itf].tx_ff); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void cdcd_init(void) -{ - tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); - - for(uint8_t i=0; iwanted_char = (char) -1; - - // default line coding is : stop bit = 1, parity = none, data bits = 8 - p_cdc->line_coding.bit_rate = 115200; - p_cdc->line_coding.stop_bits = 0; - p_cdc->line_coding.parity = 0; - p_cdc->line_coding.data_bits = 8; - - // Config RX fifo - tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); - - // Config TX fifo as overwritable at initialization and will be changed to non-overwritable - // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal. - // In this way, the most current data is prioritized. - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); - -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, osal_mutex_create(&p_cdc->rx_ff_mutex)); - tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex), NULL); -#endif - } -} - -void cdcd_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&p_cdc->tx_ff); - tu_fifo_set_overwritable(&p_cdc->tx_ff, true); - } -} - -uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // Only support ACM subclass - TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); - - // Find available interface - cdcd_interface_t * p_cdc = NULL; - for(uint8_t cdc_id=0; cdc_iditf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - // notification endpoint - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - TU_ASSERT( usbd_edpt_open(rhport, desc_ep), 0 ); - p_cdc->ep_notif = desc_ep->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { - // next to endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - } - - // Prepare for incoming data - _prep_out_transaction(p_cdc); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - uint8_t itf = 0; - cdcd_interface_t* p_cdc = _cdcd_itf; - - // Identify which interface to use - for ( ; ; itf++, p_cdc++) - { - if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false; - - if ( p_cdc->itf_num == request->wIndex ) break; - } - - switch ( request->bRequest ) - { - case CDC_REQUEST_SET_LINE_CODING: - if (stage == CONTROL_STAGE_SETUP) - { - TU_LOG2(" Set Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); - } - else if ( stage == CONTROL_STAGE_ACK) - { - if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); - } - break; - - case CDC_REQUEST_GET_LINE_CODING: - if (stage == CONTROL_STAGE_SETUP) - { - TU_LOG2(" Get Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); - } - break; - - case CDC_REQUEST_SET_CONTROL_LINE_STATE: - if (stage == CONTROL_STAGE_SETUP) - { - tud_control_status(rhport, request); - } - else if (stage == CONTROL_STAGE_ACK) - { - // CDC PSTN v1.2 section 6.3.12 - // Bit 0: Indicates if DTE is present or not. - // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) - // Bit 1: Carrier control for half-duplex modems. - // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) - bool const dtr = tu_bit_test(request->wValue, 0); - bool const rts = tu_bit_test(request->wValue, 1); - - p_cdc->line_state = (uint8_t) request->wValue; - - // Disable fifo overwriting if DTR bit is set - tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); - - TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); - - // Invoke callback - if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); - } - break; - case CDC_REQUEST_SEND_BREAK: - if (stage == CONTROL_STAGE_SETUP) - { - tud_control_status(rhport, request); - } - else if (stage == CONTROL_STAGE_ACK) - { - TU_LOG2(" Send Break\r\n"); - if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); - } - break; - - default: return false; // stall unsupported request - } - - return true; -} - -bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t itf; - cdcd_interface_t* p_cdc; - - // Identify which interface to use - for (itf = 0; itf < CFG_TUD_CDC; itf++) - { - p_cdc = &_cdcd_itf[itf]; - if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break; - } - TU_ASSERT(itf < CFG_TUD_CDC); - - // Received new data - if ( ep_addr == p_cdc->ep_out ) - { - tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); - - // Check for wanted char and invoke callback if needed - if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) - { - for ( uint32_t i = 0; i < xferred_bytes; i++ ) - { - if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) - { - tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); - } - } - } - - // invoke receive callback (if there is still data) - if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); - - // prepare for OUT transaction - _prep_out_transaction(p_cdc); - } - - // Data sent to host, we continue to fetch from tx fifo to send. - // Note: This will cause incorrect baudrate set in line coding. - // Though maybe the baudrate is not really important !!! - if ( ep_addr == p_cdc->ep_in ) - { - // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); - - if ( 0 == tud_cdc_n_write_flush(itf) ) - { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP Packet size and not zero - if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE-1))) ) - { - if ( usbd_edpt_claim(rhport, p_cdc->ep_in) ) - { - usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); - } - } - } - } - - // nothing to do with notif endpoint for now - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h deleted file mode 100644 index fbc7162a3..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_device.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_CDC_DEVICE_H_ -#define _TUSB_CDC_DEVICE_H_ - -#include "common/tusb_common.h" -#include "cdc.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ -#if !defined(CFG_TUD_CDC_EP_BUFSIZE) && defined(CFG_TUD_CDC_EPSIZE) - #warning CFG_TUD_CDC_EPSIZE is renamed to CFG_TUD_CDC_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_CDC_EP_BUFSIZE CFG_TUD_CDC_EPSIZE -#endif - -#ifndef CFG_TUD_CDC_EP_BUFSIZE - #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -/** \addtogroup CDC_Serial Serial - * @{ - * \defgroup CDC_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Ports) -// CFG_TUD_CDC > 1 -//--------------------------------------------------------------------+ - -// Check if terminal is connected to this port -bool tud_cdc_n_connected (uint8_t itf); - -// Get current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) -uint8_t tud_cdc_n_get_line_state (uint8_t itf); - -// Get current line encoding: bit rate, stop bits parity etc .. -void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding); - -// Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving -void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted); - -// Get the number of bytes available for reading -uint32_t tud_cdc_n_available (uint8_t itf); - -// Read received bytes -uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize); - -// Read a byte, return -1 if there is none -static inline -int32_t tud_cdc_n_read_char (uint8_t itf); - -// Clear the received FIFO -void tud_cdc_n_read_flush (uint8_t itf); - -// Get a byte from FIFO at the specified position without removing it -bool tud_cdc_n_peek (uint8_t itf, uint8_t* ui8); - -// Write bytes to TX FIFO, data may remain in the FIFO for a while -uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); - -// Write a byte -static inline -uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); - -// Write a null-terminated string -static inline -uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); - -// Force sending data if possible, return number of forced bytes -uint32_t tud_cdc_n_write_flush (uint8_t itf); - -// Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. -uint32_t tud_cdc_n_write_available (uint8_t itf); - -// Clear the transmit FIFO -bool tud_cdc_n_write_clear (uint8_t itf); - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_cdc_connected (void); -static inline uint8_t tud_cdc_get_line_state (void); -static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding); -static inline void tud_cdc_set_wanted_char (char wanted); - -static inline uint32_t tud_cdc_available (void); -static inline int32_t tud_cdc_read_char (void); -static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize); -static inline void tud_cdc_read_flush (void); -static inline bool tud_cdc_peek (uint8_t* ui8); - -static inline uint32_t tud_cdc_write_char (char ch); -static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); -static inline uint32_t tud_cdc_write_str (char const* str); -static inline uint32_t tud_cdc_write_flush (void); -static inline uint32_t tud_cdc_write_available (void); -static inline bool tud_cdc_write_clear (void); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received new data -TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); - -// Invoked when received `wanted_char` -TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); - -// Invoked when space becomes available in TX buffer -TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf); - -// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE -TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); - -// Invoked when line coding is change via SET_LINE_CODING -TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); - -// Invoked when received send break -TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ -static inline int32_t tud_cdc_n_read_char (uint8_t itf) -{ - uint8_t ch; - return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1; -} - -static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch) -{ - return tud_cdc_n_write(itf, &ch, 1); -} - -static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str) -{ - return tud_cdc_n_write(itf, str, strlen(str)); -} - -static inline bool tud_cdc_connected (void) -{ - return tud_cdc_n_connected(0); -} - -static inline uint8_t tud_cdc_get_line_state (void) -{ - return tud_cdc_n_get_line_state(0); -} - -static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding) -{ - tud_cdc_n_get_line_coding(0, coding); -} - -static inline void tud_cdc_set_wanted_char (char wanted) -{ - tud_cdc_n_set_wanted_char(0, wanted); -} - -static inline uint32_t tud_cdc_available (void) -{ - return tud_cdc_n_available(0); -} - -static inline int32_t tud_cdc_read_char (void) -{ - return tud_cdc_n_read_char(0); -} - -static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize) -{ - return tud_cdc_n_read(0, buffer, bufsize); -} - -static inline void tud_cdc_read_flush (void) -{ - tud_cdc_n_read_flush(0); -} - -static inline bool tud_cdc_peek (uint8_t* ui8) -{ - return tud_cdc_n_peek(0, ui8); -} - -static inline uint32_t tud_cdc_write_char (char ch) -{ - return tud_cdc_n_write_char(0, ch); -} - -static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) -{ - return tud_cdc_n_write(0, buffer, bufsize); -} - -static inline uint32_t tud_cdc_write_str (char const* str) -{ - return tud_cdc_n_write_str(0, str); -} - -static inline uint32_t tud_cdc_write_flush (void) -{ - return tud_cdc_n_write_flush(0); -} - -static inline uint32_t tud_cdc_write_available(void) -{ - return tud_cdc_n_write_available(0); -} - -static inline bool tud_cdc_write_clear(void) -{ - return tud_cdc_n_write_clear(0); -} - -/** @} */ -/** @} */ - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void cdcd_init (void); -void cdcd_reset (uint8_t rhport); -uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c deleted file mode 100644 index f4fb6c1d6..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC) - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "cdc_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct { - uint8_t itf_num; - uint8_t itf_protocol; - - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - cdc_acm_capability_t acm_capability; - -} cdch_data_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static cdch_data_t cdch_data[CFG_TUH_DEVICE_MAX]; - -static inline cdch_data_t* get_itf(uint8_t dev_addr) -{ - return &cdch_data[dev_addr-1]; -} - -bool tuh_cdc_mounted(uint8_t dev_addr) -{ - cdch_data_t* cdc = get_itf(dev_addr); - return cdc->ep_in && cdc->ep_out; -} - -bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) -{ - if ( !tuh_cdc_mounted(dev_addr) ) return false; - - cdch_data_t const * p_cdc = get_itf(dev_addr); - - switch (pipeid) - { - case CDC_PIPE_NOTIFICATION: - return usbh_edpt_busy(dev_addr, p_cdc->ep_notif ); - - case CDC_PIPE_DATA_IN: - return usbh_edpt_busy(dev_addr, p_cdc->ep_in ); - - case CDC_PIPE_DATA_OUT: - return usbh_edpt_busy(dev_addr, p_cdc->ep_out ); - - default: - return false; - } -} - -//--------------------------------------------------------------------+ -// APPLICATION API (parameter validation needed) -//--------------------------------------------------------------------+ -bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) -{ - // TODO consider all AT Command as serial candidate - return tuh_cdc_mounted(dev_addr) && - (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA); -} - -bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify) -{ - (void) is_notify; - TU_VERIFY( tuh_cdc_mounted(dev_addr) ); - TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA); - - uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; - if ( usbh_edpt_busy(dev_addr, ep_out) ) return false; - - return usbh_edpt_xfer(dev_addr, ep_out, (void*)(uintptr_t) p_data, length); -} - -bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify) -{ - (void) is_notify; - TU_VERIFY( tuh_cdc_mounted(dev_addr) ); - TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA); - - uint8_t const ep_in = cdch_data[dev_addr-1].ep_in; - if ( usbh_edpt_busy(dev_addr, ep_in) ) return false; - - return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); -} - -bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb) -{ - cdch_data_t const * p_cdc = get_itf(dev_addr); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0), - .wIndex = p_cdc->itf_num, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, complete_cb) ); - return true; -} - -//--------------------------------------------------------------------+ -// USBH-CLASS DRIVER API -//--------------------------------------------------------------------+ -void cdch_init(void) -{ - tu_memclr(cdch_data, sizeof(cdch_data)); -} - -bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - (void) max_len; - - // Only support ACM subclass - // Protocol 0xFF can be RNDIS device for windows XP - TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0xFF != itf_desc->bInterfaceProtocol); - - cdch_data_t * p_cdc = get_itf(dev_addr); - - p_cdc->itf_num = itf_desc->bInterfaceNumber; - p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; - - //------------- Communication Interface -------------// - uint16_t drv_len = tu_desc_len(itf_desc); - uint8_t const * p_desc = tu_desc_next(itf_desc); - - // Communication Functional Descriptors - while( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) - { - // save ACM bmCapabilities - p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - // notification endpoint - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - p_cdc->ep_notif = desc_ep->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { - // next to endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - // data endpoints expected to be in pairs - for(uint32_t i=0; i<2; i++) - { - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); - - if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) - { - p_cdc->ep_in = desc_ep->bEndpointAddress; - }else - { - p_cdc->ep_out = desc_ep->bEndpointAddress; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next( p_desc ); - } - } - - return true; -} - -bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - (void) dev_addr; (void) itf_num; - return true; -} - -bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - (void) ep_addr; - tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes ); - return true; -} - -void cdch_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - - cdch_data_t * p_cdc = get_itf(dev_addr); - tu_memclr(p_cdc, sizeof(cdch_data_t)); -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h deleted file mode 100644 index 0d435138b..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_host.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_CDC_HOST_H_ -#define _TUSB_CDC_HOST_H_ - -#include "cdc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// CDC APPLICATION PUBLIC API -//--------------------------------------------------------------------+ -/** \ingroup ClassDriver_CDC Communication Device Class (CDC) - * \addtogroup CDC_Serial Serial - * @{ - * \defgroup CDC_Serial_Host Host - * @{ */ - -bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb); - -static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) -{ - return tuh_cdc_set_control_line_state(dev_addr, true, true, complete_cb); -} - -static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) -{ - return tuh_cdc_set_control_line_state(dev_addr, false, false, complete_cb); -} - -/** \brief Check if device support CDC Serial interface or not - * \param[in] dev_addr device address - * \retval true if device supports - * \retval false if device does not support or is not mounted - */ -bool tuh_cdc_serial_is_mounted(uint8_t dev_addr); - -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \param[in] pipeid value from \ref cdc_pipeid_t to indicate target pipe. - * \retval true if the interface is busy, meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy, meaning the stack successfully transferred data from/to device - * \note This function is used to check if previous transfer is complete (success or error), so that the next transfer - * can be scheduled. User needs to make sure the corresponding interface is mounted - * (by \ref tuh_cdc_serial_is_mounted) before calling this function. - */ -bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid); - -/** \brief Perform USB OUT transfer to device - * \param[in] dev_addr device address - * \param[in] p_data Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \param[in] length Number of bytes to be transferred via USB bus - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the - * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION. - */ -bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify); - -/** \brief Perform USB IN transfer to get data from device - * \param[in] dev_addr device address - * \param[in] p_buffer Buffer containing received data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \param[in] length Number of bytes to be transferred via USB bus - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the - * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION. - */ -bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify); - -//--------------------------------------------------------------------+ -// CDC APPLICATION CALLBACKS -//--------------------------------------------------------------------+ - -/** \brief Callback function that is invoked when an transferring event occurred - * \param[in] dev_addr Address of device - * \param[in] event an value from \ref xfer_result_t - * \param[in] pipe_id value from \ref cdc_pipeid_t indicate the pipe - * \param[in] xferred_bytes Number of bytes transferred via USB bus - * \note event can be one of following - * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. - * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. - * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. - * \note - */ -void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes); - -/// @} // group CDC_Serial_Host -/// @} - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void cdch_init (void); -bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); -bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void cdch_close (uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h deleted file mode 100644 index e0f129fe3..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup ClassDriver_CDC Communication Device Class (CDC) - * \defgroup CDC_RNDIS Remote Network Driver Interface Specification (RNDIS) - * @{ - * \defgroup CDC_RNDIS_Common Common Definitions - * @{ */ - -#ifndef _TUSB_CDC_RNDIS_H_ -#define _TUSB_CDC_RNDIS_H_ - -#include "cdc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -#ifdef __CC_ARM -#pragma diag_suppress 66 // Suppress Keil warnings #66-D: enumeration value is out of "int" range -#endif - -/// RNDIS Message Types -typedef enum -{ - RNDIS_MSG_PACKET = 0x00000001UL, ///< The host and device use this to send network data to one another. - - RNDIS_MSG_INITIALIZE = 0x00000002UL, ///< Sent by the host to initialize the device. - RNDIS_MSG_INITIALIZE_CMPLT = 0x80000002UL, ///< Device response to an initialize message. - - RNDIS_MSG_HALT = 0x00000003UL, ///< Sent by the host to halt the device. This does not have a response. It is optional for the device to send this message to the host. - - RNDIS_MSG_QUERY = 0x00000004UL, ///< Sent by the host to send a query OID. - RNDIS_MSG_QUERY_CMPLT = 0x80000004UL, ///< Device response to a query OID. - - RNDIS_MSG_SET = 0x00000005UL, ///< Sent by the host to send a set OID. - RNDIS_MSG_SET_CMPLT = 0x80000005UL, ///< Device response to a set OID. - - RNDIS_MSG_RESET = 0x00000006UL, ///< Sent by the host to perform a soft reset on the device. - RNDIS_MSG_RESET_CMPLT = 0x80000006UL, ///< Device response to reset message. - - RNDIS_MSG_INDICATE_STATUS = 0x00000007UL, ///< Sent by the device to indicate its status or an error when an unrecognized message is received. - - RNDIS_MSG_KEEP_ALIVE = 0x00000008UL, ///< During idle periods, sent every few seconds by the host to check that the device is still responsive. It is optional for the device to send this message to check if the host is active. - RNDIS_MSG_KEEP_ALIVE_CMPLT = 0x80000008UL ///< The device response to a keepalivemessage. The host can respond with this message to a keepalive message from the device when the device implements the optional KeepAliveTimer. -}rndis_msg_type_t; - -/// RNDIS Message Status Values -typedef enum -{ - RNDIS_STATUS_SUCCESS = 0x00000000UL, ///< Success - RNDIS_STATUS_FAILURE = 0xC0000001UL, ///< Unspecified error - RNDIS_STATUS_INVALID_DATA = 0xC0010015UL, ///< Invalid data error - RNDIS_STATUS_NOT_SUPPORTED = 0xC00000BBUL, ///< Unsupported request error - RNDIS_STATUS_MEDIA_CONNECT = 0x4001000BUL, ///< Device is connected to a network medium. - RNDIS_STATUS_MEDIA_DISCONNECT = 0x4001000CUL ///< Device is disconnected from the medium. -}rndis_msg_status_t; - -#ifdef __CC_ARM -#pragma diag_default 66 // return Keil 66 to normal severity -#endif - -//--------------------------------------------------------------------+ -// MESSAGE STRUCTURE -//--------------------------------------------------------------------+ - -//------------- Initialize -------------// -/// \brief Initialize Message -/// \details This message MUST be sent by the host to initialize the device. -typedef struct { - uint32_t type ; ///< Message type, must be \ref RNDIS_MSG_INITIALIZE - uint32_t length ; ///< Message length in bytes, must be 0x18 - uint32_t request_id ; ///< A 32-bit integer value, generated by the host, used to match the host's sent request to the response from the device. - uint32_t major_version ; ///< The major version of the RNDIS Protocol implemented by the host. - uint32_t minor_version ; ///< The minor version of the RNDIS Protocol implemented by the host - uint32_t max_xfer_size ; ///< The maximum size, in bytes, of any single bus data transfer that the host expects to receive from the device. -}rndis_msg_initialize_t; - -/// \brief Initialize Complete Message -/// \details This message MUST be sent by the device in response to an initialize message. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_INITIALIZE_CMPLT - uint32_t length ; ///< Message length in bytes, must be 0x30 - uint32_t request_id ; ///< A 32-bit integer value from \a request_id field of the \ref rndis_msg_initialize_t to which this message is a response. - uint32_t status ; ///< The initialization status of the device, has value from \ref rndis_msg_status_t - uint32_t major_version ; ///< the highest-numbered RNDIS Protocol version supported by the device. - uint32_t minor_version ; ///< the highest-numbered RNDIS Protocol version supported by the device. - uint32_t device_flags ; ///< MUST be set to 0x000000010. Other values are reserved for future use. - uint32_t medium ; ///< is 0x00 for RNDIS_MEDIUM_802_3 - uint32_t max_packet_per_xfer ; ///< The maximum number of concatenated \ref RNDIS_MSG_PACKET messages that the device can handle in a single bus transfer to it. This value MUST be at least 1. - uint32_t max_xfer_size ; ///< The maximum size, in bytes, of any single bus data transfer that the device expects to receive from the host. - uint32_t packet_alignment_factor ; ///< The byte alignment the device expects for each RNDIS message that is part of a multimessage transfer to it. The value is specified as an exponent of 2; for example, the host uses 2{PacketAlignmentFactor} as the alignment value. - uint32_t reserved[2] ; -} rndis_msg_initialize_cmplt_t; - -//------------- Query -------------// -/// \brief Query Message -/// \details This message MUST be sent by the host to query an OID. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_QUERY - uint32_t length ; ///< Message length in bytes, including the header and the \a oid_buffer - uint32_t request_id ; ///< A 32-bit integer value, generated by the host, used to match the host's sent request to the response from the device. - uint32_t oid ; ///< The integer value of the host operating system-defined identifier, for the parameter of the device being queried for. - uint32_t buffer_length ; ///< The length, in bytes, of the input data required for the OID query. This MUST be set to 0 when there is no input data associated with the OID. - uint32_t buffer_offset ; ///< The offset, in bytes, from the beginning of \a request_id field where the input data for the query is located in the message. This value MUST be set to 0 when there is no input data associated with the OID. - uint32_t reserved ; - uint8_t oid_buffer[] ; ///< Flexible array contains the input data supplied by the host, required for the OID query request processing by the device, as per the host NDIS specification. -} rndis_msg_query_t, rndis_msg_set_t; - -TU_VERIFY_STATIC(sizeof(rndis_msg_query_t) == 28, "Make sure flexible array member does not affect layout"); - -/// \brief Query Complete Message -/// \details This message MUST be sent by the device in response to a query OID message. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_QUERY_CMPLT - uint32_t length ; ///< Message length in bytes, including the header and the \a oid_buffer - uint32_t request_id ; ///< A 32-bit integer value from \a request_id field of the \ref rndis_msg_query_t to which this message is a response. - uint32_t status ; ///< The status of processing for the query request, has value from \ref rndis_msg_status_t. - uint32_t buffer_length ; ///< The length, in bytes, of the data in the response to the query. This MUST be set to 0 when there is no OIDInputBuffer. - uint32_t buffer_offset ; ///< The offset, in bytes, from the beginning of \a request_id field where the response data for the query is located in the message. This MUST be set to 0 when there is no \ref oid_buffer. - uint8_t oid_buffer[] ; ///< Flexible array member contains the response data to the OID query request as specified by the host. -} rndis_msg_query_cmplt_t; - -TU_VERIFY_STATIC(sizeof(rndis_msg_query_cmplt_t) == 24, "Make sure flexible array member does not affect layout"); - -//------------- Reset -------------// -/// \brief Reset Message -/// \details This message MUST be sent by the host to perform a soft reset on the device. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_RESET - uint32_t length ; ///< Message length in bytes, MUST be 0x06 - uint32_t reserved ; -} rndis_msg_reset_t; - -/// \brief Reset Complete Message -/// \details This message MUST be sent by the device in response to a reset message. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_RESET_CMPLT - uint32_t length ; ///< Message length in bytes, MUST be 0x10 - uint32_t status ; ///< The status of processing for the \ref rndis_msg_reset_t, has value from \ref rndis_msg_status_t. - uint32_t addressing_reset ; ///< This field indicates whether the addressing information, which is the multicast address list or packet filter, has been lost during the reset operation. This MUST be set to 0x00000001 if the device requires that the host to resend addressing information or MUST be set to zero otherwise. -} rndis_msg_reset_cmplt_t; - -//typedef struct { -// uint32_t type; -// uint32_t length; -// uint32_t status; -// uint32_t buffer_length; -// uint32_t buffer_offset; -// uint32_t diagnostic_status; // optional -// uint32_t diagnostic_error_offset; // optional -// uint32_t status_buffer[0]; // optional -//} rndis_msg_indicate_status_t; - -/// \brief Keep Alive Message -/// \details This message MUST be sent by the host to check that device is still responsive. It is optional for the device to send this message to check if the host is active -typedef struct { - uint32_t type ; ///< Message Type - uint32_t length ; ///< Message length in bytes, MUST be 0x10 - uint32_t request_id ; -} rndis_msg_keep_alive_t, rndis_msg_halt_t; - -/// \brief Set Complete Message -/// \brief This message MUST be sent in response to a the request message -typedef struct { - uint32_t type ; ///< Message Type - uint32_t length ; ///< Message length in bytes, MUST be 0x10 - uint32_t request_id ; ///< must be the same as requesting message - uint32_t status ; ///< The status of processing for the request message request by the device to which this message is the response. -} rndis_msg_set_cmplt_t, rndis_msg_keep_alive_cmplt_t; - -/// \brief Packet Data Message -/// \brief This message MUST be used by the host and the device to send network data to one another. -typedef struct { - uint32_t type ; ///< Message Type, must be \ref RNDIS_MSG_PACKET - uint32_t length ; ///< Message length in bytes, The total length of this RNDIS message including the header, payload, and padding. - uint32_t data_offset ; ///< Specifies the offset, in bytes, from the start of this \a data_offset field of this message to the start of the data. This MUST be an integer multiple of 4. - uint32_t data_length ; ///< Specifies the number of bytes in the payload of this message. - uint32_t out_of_band_data_offet ; ///< Specifies the offset, in bytes, of the first out-of-band data record from the start of the DataOffset field in this message. MUST be an integer multiple of 4 when out-of-band data is present or set to 0 otherwise. When there are multiple out-ofband data records, each subsequent record MUST immediately follow the previous out-of-band data record. - uint32_t out_of_band_data_length ; ///< Specifies, in bytes, the total length of the out-of-band data. - uint32_t num_out_of_band_data_elements ; ///< Specifies the number of out-of-band records in this message. - uint32_t per_packet_info_offset ; ///< Specifies the offset, in bytes, of the start of per-packet-info data record from the start of the \a data_offset field in this message. MUST be an integer multiple of 4 when per-packet-info data record is present or MUST be set to 0 otherwise. When there are multiple per-packet-info data records, each subsequent record MUST immediately follow the previous record. - uint32_t per_packet_info_length ; ///< Specifies, in bytes, the total length of per-packetinformation contained in this message. - uint32_t reserved[2] ; - uint32_t payload[0] ; ///< Network data contained in this message. - - // uint8_t padding[0] - // Additional bytes of zeros added at the end of the message to comply with - // the internal and external padding requirements. Internal padding SHOULD be as per the - // specification of the out-of-band data record and per-packet-info data record. The external - //padding size SHOULD be determined based on the PacketAlignmentFactor field specification - //in REMOTE_NDIS_INITIALIZE_CMPLT message by the device, when multiple - //REMOTE_NDIS_PACKET_MSG messages are bundled together in a single bus-native message. - //In this case, all but the very last REMOTE_NDIS_PACKET_MSG MUST respect the - //PacketAlignmentFactor field. - - // rndis_msg_packet_t [0] : (optional) more packet if multiple packet per bus transaction is supported -} rndis_msg_packet_t; - - -typedef struct { - uint32_t size ; ///< Length, in bytes, of this header and appended data and padding. This value MUST be an integer multiple of 4. - uint32_t type ; ///< MUST be as per host operating system specification. - uint32_t offset ; ///< The byte offset from the beginning of this record to the beginning of data. - uint32_t data[0] ; ///< Flexible array contains data -} rndis_msg_out_of_band_data_t, rndis_msg_per_packet_info_t; - -//--------------------------------------------------------------------+ -// NDIS Object ID -//--------------------------------------------------------------------+ - -/// NDIS Object ID -typedef enum -{ - //------------- General Required OIDs -------------// - RNDIS_OID_GEN_SUPPORTED_LIST = 0x00010101, ///< List of supported OIDs - RNDIS_OID_GEN_HARDWARE_STATUS = 0x00010102, ///< Hardware status - RNDIS_OID_GEN_MEDIA_SUPPORTED = 0x00010103, ///< Media types supported (encoded) - RNDIS_OID_GEN_MEDIA_IN_USE = 0x00010104, ///< Media types in use (encoded) - RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD = 0x00010105, ///< - RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE = 0x00010106, ///< Maximum frame size in bytes - RNDIS_OID_GEN_LINK_SPEED = 0x00010107, ///< Link speed in units of 100 bps - RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE = 0x00010108, ///< Transmit buffer space - RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE = 0x00010109, ///< Receive buffer space - RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE = 0x0001010A, ///< Minimum amount of storage, in bytes, that a single packet occupies in the transmit buffer space of the NIC - RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE = 0x0001010B, ///< Amount of storage, in bytes, that a single packet occupies in the receive buffer space of the NIC - RNDIS_OID_GEN_VENDOR_ID = 0x0001010C, ///< Vendor NIC code - RNDIS_OID_GEN_VENDOR_DESCRIPTION = 0x0001010D, ///< Vendor network card description - RNDIS_OID_GEN_CURRENT_PACKET_FILTER = 0x0001010E, ///< Current packet filter (encoded) - RNDIS_OID_GEN_CURRENT_LOOKAHEAD = 0x0001010F, ///< Current lookahead size in bytes - RNDIS_OID_GEN_DRIVER_VERSION = 0x00010110, ///< NDIS version number used by the driver - RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE = 0x00010111, ///< Maximum total packet length in bytes - RNDIS_OID_GEN_PROTOCOL_OPTIONS = 0x00010112, ///< Optional protocol flags (encoded) - RNDIS_OID_GEN_MAC_OPTIONS = 0x00010113, ///< Optional NIC flags (encoded) - RNDIS_OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114, ///< Whether the NIC is connected to the network - RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS = 0x00010115, ///< The maximum number of send packets the driver can accept per call to its MiniportSendPacketsfunction - - //------------- General Optional OIDs -------------// - RNDIS_OID_GEN_VENDOR_DRIVER_VERSION = 0x00010116, ///< Vendor-assigned version number of the driver - RNDIS_OID_GEN_SUPPORTED_GUIDS = 0x00010117, ///< The custom GUIDs (Globally Unique Identifier) supported by the miniport driver - RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES = 0x00010118, ///< List of network-layer addresses associated with the binding between a transport and the driver - RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET = 0x00010119, ///< Size of packets' additional headers - RNDIS_OID_GEN_MEDIA_CAPABILITIES = 0x00010201, ///< - RNDIS_OID_GEN_PHYSICAL_MEDIUM = 0x00010202, ///< Physical media supported by the miniport driver (encoded) - - //------------- 802.3 Objects (Ethernet) -------------// - RNDIS_OID_802_3_PERMANENT_ADDRESS = 0x01010101, ///< Permanent station address - RNDIS_OID_802_3_CURRENT_ADDRESS = 0x01010102, ///< Current station address - RNDIS_OID_802_3_MULTICAST_LIST = 0x01010103, ///< Current multicast address list - RNDIS_OID_802_3_MAXIMUM_LIST_SIZE = 0x01010104, ///< Maximum size of multicast address list -} rndis_oid_type_t; - -/// RNDIS Packet Filter Bits \ref RNDIS_OID_GEN_CURRENT_PACKET_FILTER. -typedef enum -{ - RNDIS_PACKET_TYPE_DIRECTED = 0x00000001, ///< Directed packets. Directed packets contain a destination address equal to the station address of the NIC. - RNDIS_PACKET_TYPE_MULTICAST = 0x00000002, ///< Multicast address packets sent to addresses in the multicast address list. - RNDIS_PACKET_TYPE_ALL_MULTICAST = 0x00000004, ///< All multicast address packets, not just the ones enumerated in the multicast address list. - RNDIS_PACKET_TYPE_BROADCAST = 0x00000008, ///< Broadcast packets. - RNDIS_PACKET_TYPE_SOURCE_ROUTING = 0x00000010, ///< All source routing packets. If the protocol driver sets this bit, the NDIS library attempts to act as a source routing bridge. - RNDIS_PACKET_TYPE_PROMISCUOUS = 0x00000020, ///< Specifies all packets regardless of whether VLAN filtering is enabled or not and whether the VLAN identifier matches or not. - RNDIS_PACKET_TYPE_SMT = 0x00000040, ///< SMT packets that an FDDI NIC receives. - RNDIS_PACKET_TYPE_ALL_LOCAL = 0x00000080, ///< All packets sent by installed protocols and all packets indicated by the NIC that is identified by a given NdisBindingHandle. - RNDIS_PACKET_TYPE_GROUP = 0x00001000, ///< Packets sent to the current group address. - RNDIS_PACKET_TYPE_ALL_FUNCTIONAL = 0x00002000, ///< All functional address packets, not just the ones in the current functional address. - RNDIS_PACKET_TYPE_FUNCTIONAL = 0x00004000, ///< Functional address packets sent to addresses included in the current functional address. - RNDIS_PACKET_TYPE_MAC_FRAME = 0x00008000, ///< NIC driver frames that a Token Ring NIC receives. - RNDIS_PACKET_TYPE_NO_LOCAL = 0x00010000, -} rndis_packet_filter_type_t; - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_RNDIS_H_ */ - -/** @} */ -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c deleted file mode 100644 index cc4ffd1cf..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC && CFG_TUH_CDC_RNDIS) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "common/tusb_common.h" -#include "cdc_host.h" -#include "cdc_rndis_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -#define RNDIS_MSG_PAYLOAD_MAX (1024*4) - -CFG_TUSB_MEM_SECTION static uint8_t msg_notification[CFG_TUH_DEVICE_MAX][8]; -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX]; - -static rndish_data_t rndish_data[CFG_TUH_DEVICE_MAX]; - -// TODO Microsoft requires message length for any get command must be at least 4096 bytes - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static tusb_error_t rndis_body_subtask(void); -static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, - uint8_t * p_mess, uint32_t mess_length, - uint8_t *p_response ); - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -tusb_error_t tusbh_cdc_rndis_get_mac_addr(uint8_t dev_addr, uint8_t mac_address[6]) -{ - TU_ASSERT( tusbh_cdc_rndis_is_mounted(dev_addr), TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED); - TU_VERIFY( mac_address, TUSB_ERROR_INVALID_PARA); - - memcpy(mac_address, rndish_data[dev_addr-1].mac_address, 6); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ - -// To enable the TASK_ASSERT style (quick return on false condition) in a real RTOS, a task must act as a wrapper -// and is used mainly to call subtasks. Within a subtask return statement can be called freely, the task with -// forever loop cannot have any return at all. -OSAL_TASK_FUNCTION(cdch_rndis_task) (void* param;) -{ - OSAL_TASK_BEGIN - rndis_body_subtask(); - OSAL_TASK_END -} - -static tusb_error_t rndis_body_subtask(void) -{ - static uint8_t relative_addr; - - OSAL_SUBTASK_BEGIN - - for (relative_addr = 0; relative_addr < CFG_TUH_DEVICE_MAX; relative_addr++) - { - - } - - osal_task_delay(100); - - OSAL_SUBTASK_END -} - -//--------------------------------------------------------------------+ -// RNDIS-CDC Driver API -//--------------------------------------------------------------------+ -void rndish_init(void) -{ - tu_memclr(rndish_data, sizeof(rndish_data_t)*CFG_TUH_DEVICE_MAX); - - //------------- Task creation -------------// - - //------------- semaphore creation for notificaiton pipe -------------// - for(uint8_t i=0; itype == RNDIS_MSG_INITIALIZE_CMPLT && p_init_cmpt->status == RNDIS_STATUS_SUCCESS && - p_init_cmpt->max_packet_per_xfer == 1 && p_init_cmpt->max_xfer_size <= RNDIS_MSG_PAYLOAD_MAX); - rndish_data[dev_addr-1].max_xfer_size = p_init_cmpt->max_xfer_size; - - //------------- Message Query 802.3 Permanent Address -------------// - memcpy(msg_payload, &msg_query_permanent_addr, sizeof(rndis_msg_query_t)); - tu_memclr(msg_payload + sizeof(rndis_msg_query_t), 6); // 6 bytes for MAC address - - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_query_t) + 6, - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - rndis_msg_query_cmplt_t * const p_query_cmpt = (rndis_msg_query_cmplt_t *) msg_payload; - STASK_ASSERT(p_query_cmpt->type == RNDIS_MSG_QUERY_CMPLT && p_query_cmpt->status == RNDIS_STATUS_SUCCESS); - memcpy(rndish_data[dev_addr-1].mac_address, msg_payload + 8 + p_query_cmpt->buffer_offset, 6); - - //------------- Set OID_GEN_CURRENT_PACKET_FILTER to (DIRECTED | MULTICAST | BROADCAST) -------------// - memcpy(msg_payload, &msg_set_packet_filter, sizeof(rndis_msg_set_t)); - tu_memclr(msg_payload + sizeof(rndis_msg_set_t), 4); // 4 bytes for filter flags - ((rndis_msg_set_t*) msg_payload)->oid_buffer[0] = (RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_MULTICAST | RNDIS_PACKET_TYPE_BROADCAST); - - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_set_t) + 4, - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - rndis_msg_set_cmplt_t * const p_set_cmpt = (rndis_msg_set_cmplt_t *) msg_payload; - STASK_ASSERT(p_set_cmpt->type == RNDIS_MSG_SET_CMPLT && p_set_cmpt->status == RNDIS_STATUS_SUCCESS); - - tusbh_cdc_rndis_mounted_cb(dev_addr); - - OSAL_SUBTASK_END -} - -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) -{ - if ( pipehandle_is_equal(pipe_hdl, p_cdc->pipe_notification) ) - { - osal_semaphore_post( rndish_data[pipe_hdl.dev_addr-1].sem_notification_hdl ); - } -} - -//--------------------------------------------------------------------+ -// INTERNAL & HELPER -//--------------------------------------------------------------------+ -static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, - uint8_t * p_mess, uint32_t mess_length, - uint8_t *p_response) -{ - tusb_error_t error; - - OSAL_SUBTASK_BEGIN - - //------------- Send RNDIS Control Message -------------// - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), - CDC_REQUEST_SEND_ENCAPSULATED_COMMAND, 0, p_cdc->interface_number, - mess_length, p_mess), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - //------------- waiting for Response Available notification -------------// - (void) usbh_edpt_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8); - osal_semaphore_wait(rndish_data[dev_addr-1].sem_notification_hdl, OSAL_TIMEOUT_NORMAL, &error); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - STASK_ASSERT(msg_notification[dev_addr-1][0] == 1); - - //------------- Get RNDIS Message Initialize Complete -------------// - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), - CDC_REQUEST_GET_ENCAPSULATED_RESPONSE, 0, p_cdc->interface_number, - RNDIS_MSG_PAYLOAD_MAX, p_response), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - OSAL_SUBTASK_END -} - -//static tusb_error_t send_process_msg_initialize_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) -//{ -// tusb_error_t error; -// -// OSAL_SUBTASK_BEGIN -// -// *((rndis_msg_initialize_t*) msg_payload) = (rndis_msg_initialize_t) -// { -// .type = RNDIS_MSG_INITIALIZE, -// .length = sizeof(rndis_msg_initialize_t), -// .request_id = 1, // TODO should use some magic number -// .major_version = 1, -// .minor_version = 0, -// .max_xfer_size = 0x4000 // TODO mimic windows -// }; -// -// -// -// OSAL_SUBTASK_END -//} -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h deleted file mode 100644 index 170cb3b0e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/cdc/cdc_rndis_host.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup CDC_RNDIS - * \defgroup CDC_RNSID_Host Host - * @{ */ - -#ifndef _TUSB_CDC_RNDIS_HOST_H_ -#define _TUSB_CDC_RNDIS_HOST_H_ - -#include "common/tusb_common.h" -#include "host/usbh.h" -#include "cdc_rndis.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// INTERNAL RNDIS-CDC Driver API -//--------------------------------------------------------------------+ -typedef struct { - OSAL_SEM_DEF(semaphore_notification); - osal_semaphore_handle_t sem_notification_hdl; // used to wait on notification pipe - uint32_t max_xfer_size; // got from device's msg initialize complete - uint8_t mac_address[6]; -}rndish_data_t; - -void rndish_init(void); -tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc); -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); -void rndish_close(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_RNDIS_HOST_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h deleted file mode 100644 index 114c827b8..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_H_ -#define _TUSB_DFU_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Common Definitions -//--------------------------------------------------------------------+ - -// DFU Protocol -typedef enum -{ - DFU_PROTOCOL_RT = 0x01, - DFU_PROTOCOL_DFU = 0x02, -} dfu_protocol_type_t; - -// DFU Descriptor Type -typedef enum -{ - DFU_DESC_FUNCTIONAL = 0x21, -} dfu_descriptor_type_t; - -// DFU Requests -typedef enum { - DFU_REQUEST_DETACH = 0, - DFU_REQUEST_DNLOAD = 1, - DFU_REQUEST_UPLOAD = 2, - DFU_REQUEST_GETSTATUS = 3, - DFU_REQUEST_CLRSTATUS = 4, - DFU_REQUEST_GETSTATE = 5, - DFU_REQUEST_ABORT = 6, -} dfu_requests_t; - -// DFU States -typedef enum { - APP_IDLE = 0, - APP_DETACH = 1, - DFU_IDLE = 2, - DFU_DNLOAD_SYNC = 3, - DFU_DNBUSY = 4, - DFU_DNLOAD_IDLE = 5, - DFU_MANIFEST_SYNC = 6, - DFU_MANIFEST = 7, - DFU_MANIFEST_WAIT_RESET = 8, - DFU_UPLOAD_IDLE = 9, - DFU_ERROR = 10, -} dfu_state_t; - -// DFU Status -typedef enum { - DFU_STATUS_OK = 0x00, - DFU_STATUS_ERR_TARGET = 0x01, - DFU_STATUS_ERR_FILE = 0x02, - DFU_STATUS_ERR_WRITE = 0x03, - DFU_STATUS_ERR_ERASE = 0x04, - DFU_STATUS_ERR_CHECK_ERASED = 0x05, - DFU_STATUS_ERR_PROG = 0x06, - DFU_STATUS_ERR_VERIFY = 0x07, - DFU_STATUS_ERR_ADDRESS = 0x08, - DFU_STATUS_ERR_NOTDONE = 0x09, - DFU_STATUS_ERR_FIRMWARE = 0x0A, - DFU_STATUS_ERR_VENDOR = 0x0B, - DFU_STATUS_ERR_USBR = 0x0C, - DFU_STATUS_ERR_POR = 0x0D, - DFU_STATUS_ERR_UNKNOWN = 0x0E, - DFU_STATUS_ERR_STALLEDPKT = 0x0F, -} dfu_status_t; - -#define DFU_ATTR_CAN_DOWNLOAD (1u << 0) -#define DFU_ATTR_CAN_UPLOAD (1u << 1) -#define DFU_ATTR_MANIFESTATION_TOLERANT (1u << 2) -#define DFU_ATTR_WILL_DETACH (1u << 3) - -// DFU Status Request Payload -typedef struct TU_ATTR_PACKED -{ - uint8_t bStatus; - uint8_t bwPollTimeout[3]; - uint8_t bState; - uint8_t iString; -} dfu_status_response_t; - -TU_VERIFY_STATIC( sizeof(dfu_status_response_t) == 6, "size is not correct"); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c deleted file mode 100644 index ddfa608e4..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "dfu_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t attrs; - uint8_t alt; - - dfu_state_t state; - dfu_status_t status; - - bool flashing_in_progress; - uint16_t block; - uint16_t length; - - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE]; -} dfu_state_ctx_t; - -// Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_ctx; - -static void reset_state(void) -{ - _dfu_ctx.state = DFU_IDLE; - _dfu_ctx.status = DFU_STATUS_OK; - _dfu_ctx.flashing_in_progress = false; -} - -static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout); -static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -static tu_lookup_entry_t const _dfu_request_lookup[] = -{ - { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, - { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, - { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, - { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, - { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, - { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, - { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, -}; - -static tu_lookup_table_t const _dfu_request_table = -{ - .count = TU_ARRAY_SIZE(_dfu_request_lookup), - .items = _dfu_request_lookup -}; - -static tu_lookup_entry_t const _dfu_state_lookup[] = -{ - { .key = APP_IDLE , .data = "APP_IDLE" }, - { .key = APP_DETACH , .data = "APP_DETACH" }, - { .key = DFU_IDLE , .data = "IDLE" }, - { .key = DFU_DNLOAD_SYNC , .data = "DNLOAD_SYNC" }, - { .key = DFU_DNBUSY , .data = "DNBUSY" }, - { .key = DFU_DNLOAD_IDLE , .data = "DNLOAD_IDLE" }, - { .key = DFU_MANIFEST_SYNC , .data = "MANIFEST_SYNC" }, - { .key = DFU_MANIFEST , .data = "MANIFEST" }, - { .key = DFU_MANIFEST_WAIT_RESET , .data = "MANIFEST_WAIT_RESET" }, - { .key = DFU_UPLOAD_IDLE , .data = "UPLOAD_IDLE" }, - { .key = DFU_ERROR , .data = "ERROR" }, -}; - -static tu_lookup_table_t const _dfu_state_table = -{ - .count = TU_ARRAY_SIZE(_dfu_state_lookup), - .items = _dfu_state_lookup -}; - -static tu_lookup_entry_t const _dfu_status_lookup[] = -{ - { .key = DFU_STATUS_OK , .data = "OK" }, - { .key = DFU_STATUS_ERR_TARGET , .data = "errTARGET" }, - { .key = DFU_STATUS_ERR_FILE , .data = "errFILE" }, - { .key = DFU_STATUS_ERR_WRITE , .data = "errWRITE" }, - { .key = DFU_STATUS_ERR_ERASE , .data = "errERASE" }, - { .key = DFU_STATUS_ERR_CHECK_ERASED , .data = "errCHECK_ERASED" }, - { .key = DFU_STATUS_ERR_PROG , .data = "errPROG" }, - { .key = DFU_STATUS_ERR_VERIFY , .data = "errVERIFY" }, - { .key = DFU_STATUS_ERR_ADDRESS , .data = "errADDRESS" }, - { .key = DFU_STATUS_ERR_NOTDONE , .data = "errNOTDONE" }, - { .key = DFU_STATUS_ERR_FIRMWARE , .data = "errFIRMWARE" }, - { .key = DFU_STATUS_ERR_VENDOR , .data = "errVENDOR" }, - { .key = DFU_STATUS_ERR_USBR , .data = "errUSBR" }, - { .key = DFU_STATUS_ERR_POR , .data = "errPOR" }, - { .key = DFU_STATUS_ERR_UNKNOWN , .data = "errUNKNOWN" }, - { .key = DFU_STATUS_ERR_STALLEDPKT , .data = "errSTALLEDPKT" }, -}; - -static tu_lookup_table_t const _dfu_status_table = -{ - .count = TU_ARRAY_SIZE(_dfu_status_lookup), - .items = _dfu_status_lookup -}; - -#endif - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_moded_reset(uint8_t rhport) -{ - (void) rhport; - - _dfu_ctx.attrs = 0; - _dfu_ctx.alt = 0; - - reset_state(); -} - -void dfu_moded_init(void) -{ - dfu_moded_reset(0); -} - -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) rhport; - - //------------- Interface (with Alt) descriptor -------------// - uint8_t const itf_num = itf_desc->bInterfaceNumber; - uint8_t alt_count = 0; - - uint16_t drv_len = 0; - while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) - { - TU_ASSERT(max_len > drv_len, 0); - - // Alternate must have the same interface number - TU_ASSERT(itf_desc->bInterfaceNumber == itf_num, 0); - - // Alt should increase by one every time - TU_ASSERT(itf_desc->bAlternateSetting == alt_count, 0); - alt_count++; - - drv_len += tu_desc_len(itf_desc); - itf_desc = (tusb_desc_interface_t const *) tu_desc_next(itf_desc); - } - - //------------- DFU Functional descriptor -------------// - tusb_desc_dfu_functional_t const *func_desc = (tusb_desc_dfu_functional_t const *) itf_desc; - TU_ASSERT(tu_desc_type(func_desc) == TUSB_DESC_FUNCTIONAL, 0); - drv_len += sizeof(tusb_desc_dfu_functional_t); - - _dfu_ctx.attrs = func_desc->bAttributes; - - // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR - uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t const*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) ); - TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - TU_LOG2(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status)); - - if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) - { - // Standard request include GET/SET_INTERFACE - switch ( request->bRequest ) - { - case TUSB_REQ_SET_INTERFACE: - if ( stage == CONTROL_STAGE_SETUP ) - { - // Switch Alt interface and reset state machine - _dfu_ctx.alt = (uint8_t) request->wValue; - reset_state(); - return tud_control_status(rhport, request); - } - break; - - case TUSB_REQ_GET_INTERFACE: - if(stage == CONTROL_STAGE_SETUP) - { - return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1); - } - break; - - // unsupported request - default: return false; - } - } - else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS ) - { - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - - // Class request - switch ( request->bRequest ) - { - case DFU_REQUEST_DETACH: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( tud_dfu_detach_cb ) tud_dfu_detach_cb(); - } - break; - - case DFU_REQUEST_CLRSTATUS: - if ( stage == CONTROL_STAGE_SETUP ) - { - reset_state(); - tud_control_status(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); - } - break; - - case DFU_REQUEST_ABORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - reset_state(); - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt); - } - break; - - case DFU_REQUEST_UPLOAD: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); - TU_VERIFY(tud_dfu_upload_cb); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); - - uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength); - - return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); - } - break; - - case DFU_REQUEST_DNLOAD: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD); - TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); - - // set to true for both download and manifest - _dfu_ctx.flashing_in_progress = true; - - // save block and length for flashing - _dfu_ctx.block = request->wValue; - _dfu_ctx.length = request->wLength; - - if ( request->wLength ) - { - // Download with payload -> transition to DOWNLOAD SYNC - _dfu_ctx.state = DFU_DNLOAD_SYNC; - return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); - } - else - { - // Download is complete -> transition to MANIFEST SYNC - _dfu_ctx.state = DFU_MANIFEST_SYNC; - return tud_control_status(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATUS: - switch ( _dfu_ctx.state ) - { - case DFU_DNLOAD_SYNC: - return process_download_get_status(rhport, stage, request); - break; - - case DFU_MANIFEST_SYNC: - return process_manifest_get_status(rhport, stage, request); - break; - - default: - if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0); - break; - } - break; - - default: return false; // stall unsupported request - } - }else - { - return false; // unsupported request - } - - return true; -} - -void tud_dfu_finish_flashing(uint8_t status) -{ - _dfu_ctx.flashing_in_progress = false; - - if ( status == DFU_STATUS_OK ) - { - if (_dfu_ctx.state == DFU_DNBUSY) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - } - else if (_dfu_ctx.state == DFU_MANIFEST) - { - _dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) - ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET; - } - } - else - { - // failed while flashing, move to dfuError - _dfu_ctx.state = DFU_ERROR; - _dfu_ctx.status = (dfu_status_t)status; - } -} - -static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - // only transition to next state on CONTROL_STAGE_ACK - dfu_state_t next_state; - uint32_t timeout; - - if ( _dfu_ctx.flashing_in_progress ) - { - next_state = DFU_DNBUSY; - timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state); - } - else - { - next_state = DFU_DNLOAD_IDLE; - timeout = 0; - } - - return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( _dfu_ctx.flashing_in_progress ) - { - _dfu_ctx.state = DFU_DNBUSY; - tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length); - }else - { - _dfu_ctx.state = DFU_DNLOAD_IDLE; - } - } - - return true; -} - -static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - // only transition to next state on CONTROL_STAGE_ACK - dfu_state_t next_state; - uint32_t timeout; - - if ( _dfu_ctx.flashing_in_progress ) - { - next_state = DFU_MANIFEST; - timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state); - } - else - { - next_state = DFU_IDLE; - timeout = 0; - } - - return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - if ( _dfu_ctx.flashing_in_progress ) - { - _dfu_ctx.state = DFU_MANIFEST; - tud_dfu_manifest_cb(_dfu_ctx.alt); - } - else - { - _dfu_ctx.state = DFU_IDLE; - } - } - - return true; -} - -static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout) -{ - dfu_status_response_t resp; - resp.bStatus = (uint8_t) status; - resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); - resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); - resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); - resp.bState = (uint8_t) state; - resp.iString = 0; - - return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h deleted file mode 100644 index fecf8596f..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_device.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_DEVICE_H_ -#define _TUSB_DFU_DEVICE_H_ - -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Default Configure & Validation -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_DFU_XFER_BUFSIZE) - #error "CFG_TUD_DFU_XFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Must be called when the application is done with flashing started by -// tud_dfu_download_cb() and tud_dfu_manifest_cb(). -// status is DFU_STATUS_OK if successful, any other error status will cause state to enter dfuError -void tud_dfu_finish_flashing(uint8_t status); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. - -// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) -// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. -// During this period, USB host won't try to communicate with us. -uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state); - -// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests -// This callback could be returned before flashing op is complete (async). -// Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_download_cb (uint8_t alt, uint16_t block_num, uint8_t const *data, uint16_t length); - -// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) -// Application can do checksum, or actual flashing if buffered entire image previously. -// Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_manifest_cb(uint8_t alt); - -// Invoked when received DFU_UPLOAD request -// Application must populate data with up to length bytes and -// Return the number of written bytes -TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); - -// Invoked when a DFU_DETACH request is received -TU_ATTR_WEAK void tud_dfu_detach_cb(void); - -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_moded_init(void); -void dfu_moded_reset(uint8_t rhport); -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c deleted file mode 100644 index afee2aa1f..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Sylvain Munaut - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "dfu_rt_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_rtd_init(void) -{ -} - -void dfu_rtd_reset(uint8_t rhport) -{ - (void) rhport; -} - -uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) rhport; - (void) max_len; - - // Ensure this is DFU Runtime - TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT), 0); - - uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t drv_len = sizeof(tusb_desc_interface_t); - - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA or ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; - - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_INTERFACE == request->bRequest ) - { - tud_control_status(rhport, request); - return true; - } - - // Handle class request only from here - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch (request->bRequest) - { - case DFU_REQUEST_DETACH: - { - TU_LOG2(" DFU RT Request: DETACH\r\n"); - tud_control_status(rhport, request); - tud_dfu_runtime_reboot_to_dfu_cb(); - } - break; - - case DFU_REQUEST_GETSTATUS: - { - TU_LOG2(" DFU RT Request: GETSTATUS\r\n"); - dfu_status_response_t resp; - // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 - memset(&resp, 0x00, sizeof(dfu_status_response_t)); - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); - } - break; - - default: - { - TU_LOG2(" DFU RT Unexpected Request: %d\r\n", request->bRequest); - return false; // stall unsupported request - } - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h deleted file mode 100644 index babaa8214..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/dfu/dfu_rt_device.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Sylvain Munaut - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_RT_DEVICE_H_ -#define _TUSB_DFU_RT_DEVICE_H_ - -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -// Invoked when a DFU_DETACH request is received and bitWillDetach is set -void tud_dfu_runtime_reboot_to_dfu_cb(void); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_rtd_init(void); -void dfu_rtd_reset(uint8_t rhport); -uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_RT_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h deleted file mode 100644 index 9265a2ede..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid.h +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_HID Human Interface Device (HID) - * @{ */ - -#ifndef _TUSB_HID_H_ -#define _TUSB_HID_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Common Definitions -//--------------------------------------------------------------------+ -/** \defgroup ClassDriver_HID_Common Common Definitions - * @{ */ - - /// USB HID Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength; /**< Numeric expression that is the total size of the HID descriptor */ - uint8_t bDescriptorType; /**< Constant name specifying type of HID descriptor. */ - - uint16_t bcdHID; /**< Numeric expression identifying the HID Class Specification release */ - uint8_t bCountryCode; /**< Numeric expression identifying country code of the localized hardware. */ - uint8_t bNumDescriptors; /**< Numeric expression specifying the number of class descriptors */ - - uint8_t bReportType; /**< Type of HID class report. */ - uint16_t wReportLength; /**< the total size of the Report descriptor. */ -} tusb_hid_descriptor_hid_t; - -/// HID Subclass -typedef enum -{ - HID_SUBCLASS_NONE = 0, ///< No Subclass - HID_SUBCLASS_BOOT = 1 ///< Boot Interface Subclass -}hid_subclass_enum_t; - -/// HID Interface Protocol -typedef enum -{ - HID_ITF_PROTOCOL_NONE = 0, ///< None - HID_ITF_PROTOCOL_KEYBOARD = 1, ///< Keyboard - HID_ITF_PROTOCOL_MOUSE = 2 ///< Mouse -}hid_interface_protocol_enum_t; - -/// HID Descriptor Type -typedef enum -{ - HID_DESC_TYPE_HID = 0x21, ///< HID Descriptor - HID_DESC_TYPE_REPORT = 0x22, ///< Report Descriptor - HID_DESC_TYPE_PHYSICAL = 0x23 ///< Physical Descriptor -}hid_descriptor_enum_t; - -/// HID Request Report Type -typedef enum -{ - HID_REPORT_TYPE_INVALID = 0, - HID_REPORT_TYPE_INPUT, ///< Input - HID_REPORT_TYPE_OUTPUT, ///< Output - HID_REPORT_TYPE_FEATURE ///< Feature -}hid_report_type_t; - -/// HID Class Specific Control Request -typedef enum -{ - HID_REQ_CONTROL_GET_REPORT = 0x01, ///< Get Report - HID_REQ_CONTROL_GET_IDLE = 0x02, ///< Get Idle - HID_REQ_CONTROL_GET_PROTOCOL = 0x03, ///< Get Protocol - HID_REQ_CONTROL_SET_REPORT = 0x09, ///< Set Report - HID_REQ_CONTROL_SET_IDLE = 0x0a, ///< Set Idle - HID_REQ_CONTROL_SET_PROTOCOL = 0x0b ///< Set Protocol -}hid_request_enum_t; - -/// HID Local Code -typedef enum -{ - HID_LOCAL_NotSupported = 0 , ///< NotSupported - HID_LOCAL_Arabic , ///< Arabic - HID_LOCAL_Belgian , ///< Belgian - HID_LOCAL_Canadian_Bilingual , ///< Canadian_Bilingual - HID_LOCAL_Canadian_French , ///< Canadian_French - HID_LOCAL_Czech_Republic , ///< Czech_Republic - HID_LOCAL_Danish , ///< Danish - HID_LOCAL_Finnish , ///< Finnish - HID_LOCAL_French , ///< French - HID_LOCAL_German , ///< German - HID_LOCAL_Greek , ///< Greek - HID_LOCAL_Hebrew , ///< Hebrew - HID_LOCAL_Hungary , ///< Hungary - HID_LOCAL_International , ///< International - HID_LOCAL_Italian , ///< Italian - HID_LOCAL_Japan_Katakana , ///< Japan_Katakana - HID_LOCAL_Korean , ///< Korean - HID_LOCAL_Latin_American , ///< Latin_American - HID_LOCAL_Netherlands_Dutch , ///< Netherlands/Dutch - HID_LOCAL_Norwegian , ///< Norwegian - HID_LOCAL_Persian_Farsi , ///< Persian (Farsi) - HID_LOCAL_Poland , ///< Poland - HID_LOCAL_Portuguese , ///< Portuguese - HID_LOCAL_Russia , ///< Russia - HID_LOCAL_Slovakia , ///< Slovakia - HID_LOCAL_Spanish , ///< Spanish - HID_LOCAL_Swedish , ///< Swedish - HID_LOCAL_Swiss_French , ///< Swiss/French - HID_LOCAL_Swiss_German , ///< Swiss/German - HID_LOCAL_Switzerland , ///< Switzerland - HID_LOCAL_Taiwan , ///< Taiwan - HID_LOCAL_Turkish_Q , ///< Turkish-Q - HID_LOCAL_UK , ///< UK - HID_LOCAL_US , ///< US - HID_LOCAL_Yugoslavia , ///< Yugoslavia - HID_LOCAL_Turkish_F ///< Turkish-F -} hid_local_enum_t; - -// HID protocol value used by GetProtocol / SetProtocol -typedef enum -{ - HID_PROTOCOL_BOOT = 0, - HID_PROTOCOL_REPORT = 1 -} hid_protocol_mode_enum_t; - -/** @} */ - -//--------------------------------------------------------------------+ -// GAMEPAD -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Gamepad Gamepad - * @{ */ - -/* From https://www.kernel.org/doc/html/latest/input/gamepad.html - ____________________________ __ - / [__ZL__] [__ZR__] \ | - / [__ TL __] [__ TR __] \ | Front Triggers - __/________________________________\__ __| - / _ \ | - / /\ __ (N) \ | - / || __ |MO| __ _ _ \ | Main Pad - | <===DP===> |SE| |ST| (W) -|- (E) | | - \ || ___ ___ _ / | - /\ \/ / \ / \ (S) /\ __| - / \________ | LS | ____ | RS | ________/ \ | -| / \ \___/ / \ \___/ / \ | | Control Sticks -| / \_____/ \_____/ \ | __| -| / \ | - \_____/ \_____/ - - |________|______| |______|___________| - D-Pad Left Right Action Pad - Stick Stick - - |_____________| - Menu Pad - - Most gamepads have the following features: - - Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST. - - D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right. - - Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START. - - Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also - provide a digital button if you press them. - - Triggers are located on the upper-side of the pad in vertical direction. The upper buttons - are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right. - - Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors. - */ - -/// HID Gamepad Protocol Report. -typedef struct TU_ATTR_PACKED -{ - int8_t x; ///< Delta x movement of left analog-stick - int8_t y; ///< Delta y movement of left analog-stick - int8_t z; ///< Delta z movement of right analog-joystick - int8_t rz; ///< Delta Rz movement of right analog-joystick - int8_t rx; ///< Delta Rx movement of analog left trigger - int8_t ry; ///< Delta Ry movement of analog right trigger - uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat - uint32_t buttons; ///< Buttons mask for currently pressed buttons -}hid_gamepad_report_t; - -/// Standard Gamepad Buttons Bitmap -typedef enum -{ - GAMEPAD_BUTTON_0 = TU_BIT(0), - GAMEPAD_BUTTON_1 = TU_BIT(1), - GAMEPAD_BUTTON_2 = TU_BIT(2), - GAMEPAD_BUTTON_3 = TU_BIT(3), - GAMEPAD_BUTTON_4 = TU_BIT(4), - GAMEPAD_BUTTON_5 = TU_BIT(5), - GAMEPAD_BUTTON_6 = TU_BIT(6), - GAMEPAD_BUTTON_7 = TU_BIT(7), - GAMEPAD_BUTTON_8 = TU_BIT(8), - GAMEPAD_BUTTON_9 = TU_BIT(9), - GAMEPAD_BUTTON_10 = TU_BIT(10), - GAMEPAD_BUTTON_11 = TU_BIT(11), - GAMEPAD_BUTTON_12 = TU_BIT(12), - GAMEPAD_BUTTON_13 = TU_BIT(13), - GAMEPAD_BUTTON_14 = TU_BIT(14), - GAMEPAD_BUTTON_15 = TU_BIT(15), - GAMEPAD_BUTTON_16 = TU_BIT(16), - GAMEPAD_BUTTON_17 = TU_BIT(17), - GAMEPAD_BUTTON_18 = TU_BIT(18), - GAMEPAD_BUTTON_19 = TU_BIT(19), - GAMEPAD_BUTTON_20 = TU_BIT(20), - GAMEPAD_BUTTON_21 = TU_BIT(21), - GAMEPAD_BUTTON_22 = TU_BIT(22), - GAMEPAD_BUTTON_23 = TU_BIT(23), - GAMEPAD_BUTTON_24 = TU_BIT(24), - GAMEPAD_BUTTON_25 = TU_BIT(25), - GAMEPAD_BUTTON_26 = TU_BIT(26), - GAMEPAD_BUTTON_27 = TU_BIT(27), - GAMEPAD_BUTTON_28 = TU_BIT(28), - GAMEPAD_BUTTON_29 = TU_BIT(29), - GAMEPAD_BUTTON_30 = TU_BIT(30), - GAMEPAD_BUTTON_31 = TU_BIT(31), -}hid_gamepad_button_bm_t; - -/// Standard Gamepad Buttons Naming from Linux input event codes -/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h -#define GAMEPAD_BUTTON_A GAMEPAD_BUTTON_0 -#define GAMEPAD_BUTTON_SOUTH GAMEPAD_BUTTON_0 - -#define GAMEPAD_BUTTON_B GAMEPAD_BUTTON_1 -#define GAMEPAD_BUTTON_EAST GAMEPAD_BUTTON_1 - -#define GAMEPAD_BUTTON_C GAMEPAD_BUTTON_2 - -#define GAMEPAD_BUTTON_X GAMEPAD_BUTTON_3 -#define GAMEPAD_BUTTON_NORTH GAMEPAD_BUTTON_3 - -#define GAMEPAD_BUTTON_Y GAMEPAD_BUTTON_4 -#define GAMEPAD_BUTTON_WEST GAMEPAD_BUTTON_4 - -#define GAMEPAD_BUTTON_Z GAMEPAD_BUTTON_5 -#define GAMEPAD_BUTTON_TL GAMEPAD_BUTTON_6 -#define GAMEPAD_BUTTON_TR GAMEPAD_BUTTON_7 -#define GAMEPAD_BUTTON_TL2 GAMEPAD_BUTTON_8 -#define GAMEPAD_BUTTON_TR2 GAMEPAD_BUTTON_9 -#define GAMEPAD_BUTTON_SELECT GAMEPAD_BUTTON_10 -#define GAMEPAD_BUTTON_START GAMEPAD_BUTTON_11 -#define GAMEPAD_BUTTON_MODE GAMEPAD_BUTTON_12 -#define GAMEPAD_BUTTON_THUMBL GAMEPAD_BUTTON_13 -#define GAMEPAD_BUTTON_THUMBR GAMEPAD_BUTTON_14 - -/// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) -typedef enum -{ - GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED - GAMEPAD_HAT_UP = 1, ///< DPAD_UP - GAMEPAD_HAT_UP_RIGHT = 2, ///< DPAD_UP_RIGHT - GAMEPAD_HAT_RIGHT = 3, ///< DPAD_RIGHT - GAMEPAD_HAT_DOWN_RIGHT = 4, ///< DPAD_DOWN_RIGHT - GAMEPAD_HAT_DOWN = 5, ///< DPAD_DOWN - GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT - GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT - GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT -}hid_gamepad_hat_t; - -/// @} - -//--------------------------------------------------------------------+ -// MOUSE -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Mouse Mouse - * @{ */ - -/// Standard HID Boot Protocol Mouse Report. -typedef struct TU_ATTR_PACKED -{ - uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */ - int8_t x; /**< Current delta x movement of the mouse. */ - int8_t y; /**< Current delta y movement on the mouse. */ - int8_t wheel; /**< Current delta wheel movement on the mouse. */ - int8_t pan; // using AC Pan -} hid_mouse_report_t; - -/// Standard Mouse Buttons Bitmap -typedef enum -{ - MOUSE_BUTTON_LEFT = TU_BIT(0), ///< Left button - MOUSE_BUTTON_RIGHT = TU_BIT(1), ///< Right button - MOUSE_BUTTON_MIDDLE = TU_BIT(2), ///< Middle button - MOUSE_BUTTON_BACKWARD = TU_BIT(3), ///< Backward button, - MOUSE_BUTTON_FORWARD = TU_BIT(4), ///< Forward button, -}hid_mouse_button_bm_t; - -/// @} - -//--------------------------------------------------------------------+ -// Keyboard -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Keyboard Keyboard - * @{ */ - -/// Standard HID Boot Protocol Keyboard Report. -typedef struct TU_ATTR_PACKED -{ - uint8_t modifier; /**< Keyboard modifier (KEYBOARD_MODIFIER_* masks). */ - uint8_t reserved; /**< Reserved for OEM use, always set to 0. */ - uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */ -} hid_keyboard_report_t; - -/// Keyboard modifier codes bitmap -typedef enum -{ - KEYBOARD_MODIFIER_LEFTCTRL = TU_BIT(0), ///< Left Control - KEYBOARD_MODIFIER_LEFTSHIFT = TU_BIT(1), ///< Left Shift - KEYBOARD_MODIFIER_LEFTALT = TU_BIT(2), ///< Left Alt - KEYBOARD_MODIFIER_LEFTGUI = TU_BIT(3), ///< Left Window - KEYBOARD_MODIFIER_RIGHTCTRL = TU_BIT(4), ///< Right Control - KEYBOARD_MODIFIER_RIGHTSHIFT = TU_BIT(5), ///< Right Shift - KEYBOARD_MODIFIER_RIGHTALT = TU_BIT(6), ///< Right Alt - KEYBOARD_MODIFIER_RIGHTGUI = TU_BIT(7) ///< Right Window -}hid_keyboard_modifier_bm_t; - -typedef enum -{ - KEYBOARD_LED_NUMLOCK = TU_BIT(0), ///< Num Lock LED - KEYBOARD_LED_CAPSLOCK = TU_BIT(1), ///< Caps Lock LED - KEYBOARD_LED_SCROLLLOCK = TU_BIT(2), ///< Scroll Lock LED - KEYBOARD_LED_COMPOSE = TU_BIT(3), ///< Composition Mode - KEYBOARD_LED_KANA = TU_BIT(4) ///< Kana mode -}hid_keyboard_led_bm_t; - -/// @} - -//--------------------------------------------------------------------+ -// HID KEYCODE -//--------------------------------------------------------------------+ -#define HID_KEY_NONE 0x00 -#define HID_KEY_A 0x04 -#define HID_KEY_B 0x05 -#define HID_KEY_C 0x06 -#define HID_KEY_D 0x07 -#define HID_KEY_E 0x08 -#define HID_KEY_F 0x09 -#define HID_KEY_G 0x0A -#define HID_KEY_H 0x0B -#define HID_KEY_I 0x0C -#define HID_KEY_J 0x0D -#define HID_KEY_K 0x0E -#define HID_KEY_L 0x0F -#define HID_KEY_M 0x10 -#define HID_KEY_N 0x11 -#define HID_KEY_O 0x12 -#define HID_KEY_P 0x13 -#define HID_KEY_Q 0x14 -#define HID_KEY_R 0x15 -#define HID_KEY_S 0x16 -#define HID_KEY_T 0x17 -#define HID_KEY_U 0x18 -#define HID_KEY_V 0x19 -#define HID_KEY_W 0x1A -#define HID_KEY_X 0x1B -#define HID_KEY_Y 0x1C -#define HID_KEY_Z 0x1D -#define HID_KEY_1 0x1E -#define HID_KEY_2 0x1F -#define HID_KEY_3 0x20 -#define HID_KEY_4 0x21 -#define HID_KEY_5 0x22 -#define HID_KEY_6 0x23 -#define HID_KEY_7 0x24 -#define HID_KEY_8 0x25 -#define HID_KEY_9 0x26 -#define HID_KEY_0 0x27 -#define HID_KEY_ENTER 0x28 -#define HID_KEY_ESCAPE 0x29 -#define HID_KEY_BACKSPACE 0x2A -#define HID_KEY_TAB 0x2B -#define HID_KEY_SPACE 0x2C -#define HID_KEY_MINUS 0x2D -#define HID_KEY_EQUAL 0x2E -#define HID_KEY_BRACKET_LEFT 0x2F -#define HID_KEY_BRACKET_RIGHT 0x30 -#define HID_KEY_BACKSLASH 0x31 -#define HID_KEY_EUROPE_1 0x32 -#define HID_KEY_SEMICOLON 0x33 -#define HID_KEY_APOSTROPHE 0x34 -#define HID_KEY_GRAVE 0x35 -#define HID_KEY_COMMA 0x36 -#define HID_KEY_PERIOD 0x37 -#define HID_KEY_SLASH 0x38 -#define HID_KEY_CAPS_LOCK 0x39 -#define HID_KEY_F1 0x3A -#define HID_KEY_F2 0x3B -#define HID_KEY_F3 0x3C -#define HID_KEY_F4 0x3D -#define HID_KEY_F5 0x3E -#define HID_KEY_F6 0x3F -#define HID_KEY_F7 0x40 -#define HID_KEY_F8 0x41 -#define HID_KEY_F9 0x42 -#define HID_KEY_F10 0x43 -#define HID_KEY_F11 0x44 -#define HID_KEY_F12 0x45 -#define HID_KEY_PRINT_SCREEN 0x46 -#define HID_KEY_SCROLL_LOCK 0x47 -#define HID_KEY_PAUSE 0x48 -#define HID_KEY_INSERT 0x49 -#define HID_KEY_HOME 0x4A -#define HID_KEY_PAGE_UP 0x4B -#define HID_KEY_DELETE 0x4C -#define HID_KEY_END 0x4D -#define HID_KEY_PAGE_DOWN 0x4E -#define HID_KEY_ARROW_RIGHT 0x4F -#define HID_KEY_ARROW_LEFT 0x50 -#define HID_KEY_ARROW_DOWN 0x51 -#define HID_KEY_ARROW_UP 0x52 -#define HID_KEY_NUM_LOCK 0x53 -#define HID_KEY_KEYPAD_DIVIDE 0x54 -#define HID_KEY_KEYPAD_MULTIPLY 0x55 -#define HID_KEY_KEYPAD_SUBTRACT 0x56 -#define HID_KEY_KEYPAD_ADD 0x57 -#define HID_KEY_KEYPAD_ENTER 0x58 -#define HID_KEY_KEYPAD_1 0x59 -#define HID_KEY_KEYPAD_2 0x5A -#define HID_KEY_KEYPAD_3 0x5B -#define HID_KEY_KEYPAD_4 0x5C -#define HID_KEY_KEYPAD_5 0x5D -#define HID_KEY_KEYPAD_6 0x5E -#define HID_KEY_KEYPAD_7 0x5F -#define HID_KEY_KEYPAD_8 0x60 -#define HID_KEY_KEYPAD_9 0x61 -#define HID_KEY_KEYPAD_0 0x62 -#define HID_KEY_KEYPAD_DECIMAL 0x63 -#define HID_KEY_EUROPE_2 0x64 -#define HID_KEY_APPLICATION 0x65 -#define HID_KEY_POWER 0x66 -#define HID_KEY_KEYPAD_EQUAL 0x67 -#define HID_KEY_F13 0x68 -#define HID_KEY_F14 0x69 -#define HID_KEY_F15 0x6A -#define HID_KEY_F16 0x6B -#define HID_KEY_F17 0x6C -#define HID_KEY_F18 0x6D -#define HID_KEY_F19 0x6E -#define HID_KEY_F20 0x6F -#define HID_KEY_F21 0x70 -#define HID_KEY_F22 0x71 -#define HID_KEY_F23 0x72 -#define HID_KEY_F24 0x73 -#define HID_KEY_EXECUTE 0x74 -#define HID_KEY_HELP 0x75 -#define HID_KEY_MENU 0x76 -#define HID_KEY_SELECT 0x77 -#define HID_KEY_STOP 0x78 -#define HID_KEY_AGAIN 0x79 -#define HID_KEY_UNDO 0x7A -#define HID_KEY_CUT 0x7B -#define HID_KEY_COPY 0x7C -#define HID_KEY_PASTE 0x7D -#define HID_KEY_FIND 0x7E -#define HID_KEY_MUTE 0x7F -#define HID_KEY_VOLUME_UP 0x80 -#define HID_KEY_VOLUME_DOWN 0x81 -#define HID_KEY_LOCKING_CAPS_LOCK 0x82 -#define HID_KEY_LOCKING_NUM_LOCK 0x83 -#define HID_KEY_LOCKING_SCROLL_LOCK 0x84 -#define HID_KEY_KEYPAD_COMMA 0x85 -#define HID_KEY_KEYPAD_EQUAL_SIGN 0x86 -#define HID_KEY_KANJI1 0x87 -#define HID_KEY_KANJI2 0x88 -#define HID_KEY_KANJI3 0x89 -#define HID_KEY_KANJI4 0x8A -#define HID_KEY_KANJI5 0x8B -#define HID_KEY_KANJI6 0x8C -#define HID_KEY_KANJI7 0x8D -#define HID_KEY_KANJI8 0x8E -#define HID_KEY_KANJI9 0x8F -#define HID_KEY_LANG1 0x90 -#define HID_KEY_LANG2 0x91 -#define HID_KEY_LANG3 0x92 -#define HID_KEY_LANG4 0x93 -#define HID_KEY_LANG5 0x94 -#define HID_KEY_LANG6 0x95 -#define HID_KEY_LANG7 0x96 -#define HID_KEY_LANG8 0x97 -#define HID_KEY_LANG9 0x98 -#define HID_KEY_ALTERNATE_ERASE 0x99 -#define HID_KEY_SYSREQ_ATTENTION 0x9A -#define HID_KEY_CANCEL 0x9B -#define HID_KEY_CLEAR 0x9C -#define HID_KEY_PRIOR 0x9D -#define HID_KEY_RETURN 0x9E -#define HID_KEY_SEPARATOR 0x9F -#define HID_KEY_OUT 0xA0 -#define HID_KEY_OPER 0xA1 -#define HID_KEY_CLEAR_AGAIN 0xA2 -#define HID_KEY_CRSEL_PROPS 0xA3 -#define HID_KEY_EXSEL 0xA4 -// RESERVED 0xA5-DF -#define HID_KEY_CONTROL_LEFT 0xE0 -#define HID_KEY_SHIFT_LEFT 0xE1 -#define HID_KEY_ALT_LEFT 0xE2 -#define HID_KEY_GUI_LEFT 0xE3 -#define HID_KEY_CONTROL_RIGHT 0xE4 -#define HID_KEY_SHIFT_RIGHT 0xE5 -#define HID_KEY_ALT_RIGHT 0xE6 -#define HID_KEY_GUI_RIGHT 0xE7 - - -//--------------------------------------------------------------------+ -// REPORT DESCRIPTOR -//--------------------------------------------------------------------+ - -//------------- ITEM & TAG -------------// -#define HID_REPORT_DATA_0(data) -#define HID_REPORT_DATA_1(data) , data -#define HID_REPORT_DATA_2(data) , U16_TO_U8S_LE(data) -#define HID_REPORT_DATA_3(data) , U32_TO_U8S_LE(data) - -#define HID_REPORT_ITEM(data, tag, type, size) \ - (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data) - -// Report Item Types -enum { - RI_TYPE_MAIN = 0, - RI_TYPE_GLOBAL = 1, - RI_TYPE_LOCAL = 2 -}; - -//------------- Main Items - HID 1.11 section 6.2.2.4 -------------// - -// Report Item Main group -enum { - RI_MAIN_INPUT = 8, - RI_MAIN_OUTPUT = 9, - RI_MAIN_COLLECTION = 10, - RI_MAIN_FEATURE = 11, - RI_MAIN_COLLECTION_END = 12 -}; - -#define HID_INPUT(x) HID_REPORT_ITEM(x, RI_MAIN_INPUT , RI_TYPE_MAIN, 1) -#define HID_OUTPUT(x) HID_REPORT_ITEM(x, RI_MAIN_OUTPUT , RI_TYPE_MAIN, 1) -#define HID_COLLECTION(x) HID_REPORT_ITEM(x, RI_MAIN_COLLECTION , RI_TYPE_MAIN, 1) -#define HID_FEATURE(x) HID_REPORT_ITEM(x, RI_MAIN_FEATURE , RI_TYPE_MAIN, 1) -#define HID_COLLECTION_END HID_REPORT_ITEM(x, RI_MAIN_COLLECTION_END, RI_TYPE_MAIN, 0) - -//------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// -#define HID_DATA (0<<0) -#define HID_CONSTANT (1<<0) - -#define HID_ARRAY (0<<1) -#define HID_VARIABLE (1<<1) - -#define HID_ABSOLUTE (0<<2) -#define HID_RELATIVE (1<<2) - -#define HID_WRAP_NO (0<<3) -#define HID_WRAP (1<<3) - -#define HID_LINEAR (0<<4) -#define HID_NONLINEAR (1<<4) - -#define HID_PREFERRED_STATE (0<<5) -#define HID_PREFERRED_NO (1<<5) - -#define HID_NO_NULL_POSITION (0<<6) -#define HID_NULL_STATE (1<<6) - -#define HID_NON_VOLATILE (0<<7) -#define HID_VOLATILE (1<<7) - -#define HID_BITFIELD (0<<8) -#define HID_BUFFERED_BYTES (1<<8) - -//------------- Collection Item - HID 1.11 section 6.2.2.6 -------------// -enum { - HID_COLLECTION_PHYSICAL = 0, - HID_COLLECTION_APPLICATION, - HID_COLLECTION_LOGICAL, - HID_COLLECTION_REPORT, - HID_COLLECTION_NAMED_ARRAY, - HID_COLLECTION_USAGE_SWITCH, - HID_COLLECTION_USAGE_MODIFIER -}; - -//------------- Global Items - HID 1.11 section 6.2.2.7 -------------// - -// Report Item Global group -enum { - RI_GLOBAL_USAGE_PAGE = 0, - RI_GLOBAL_LOGICAL_MIN = 1, - RI_GLOBAL_LOGICAL_MAX = 2, - RI_GLOBAL_PHYSICAL_MIN = 3, - RI_GLOBAL_PHYSICAL_MAX = 4, - RI_GLOBAL_UNIT_EXPONENT = 5, - RI_GLOBAL_UNIT = 6, - RI_GLOBAL_REPORT_SIZE = 7, - RI_GLOBAL_REPORT_ID = 8, - RI_GLOBAL_REPORT_COUNT = 9, - RI_GLOBAL_PUSH = 10, - RI_GLOBAL_POP = 11 -}; - -#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, 1) -#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, n) - -#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, n) - -#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, n) - -#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, n) - -#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, n) - -#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, n) - -#define HID_UNIT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, n) - -#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, n) - -#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, 1), -#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, n), - -#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, n) - -#define HID_PUSH HID_REPORT_ITEM(x, RI_GLOBAL_PUSH, RI_TYPE_GLOBAL, 0) -#define HID_POP HID_REPORT_ITEM(x, RI_GLOBAL_POP, RI_TYPE_GLOBAL, 0) - -//------------- LOCAL ITEMS 6.2.2.8 -------------// - -enum { - RI_LOCAL_USAGE = 0, - RI_LOCAL_USAGE_MIN = 1, - RI_LOCAL_USAGE_MAX = 2, - RI_LOCAL_DESIGNATOR_INDEX = 3, - RI_LOCAL_DESIGNATOR_MIN = 4, - RI_LOCAL_DESIGNATOR_MAX = 5, - // 6 is reserved - RI_LOCAL_STRING_INDEX = 7, - RI_LOCAL_STRING_MIN = 8, - RI_LOCAL_STRING_MAX = 9, - RI_LOCAL_DELIMITER = 10, -}; - -#define HID_USAGE(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, 1) -#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, n) - -#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, n) - -#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, n) - -//--------------------------------------------------------------------+ -// Usage Table -//--------------------------------------------------------------------+ - -/// HID Usage Table - Table 1: Usage Page Summary -enum { - HID_USAGE_PAGE_DESKTOP = 0x01, - HID_USAGE_PAGE_SIMULATE = 0x02, - HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03, - HID_USAGE_PAGE_SPORT = 0x04, - HID_USAGE_PAGE_GAME = 0x05, - HID_USAGE_PAGE_GENERIC_DEVICE = 0x06, - HID_USAGE_PAGE_KEYBOARD = 0x07, - HID_USAGE_PAGE_LED = 0x08, - HID_USAGE_PAGE_BUTTON = 0x09, - HID_USAGE_PAGE_ORDINAL = 0x0a, - HID_USAGE_PAGE_TELEPHONY = 0x0b, - HID_USAGE_PAGE_CONSUMER = 0x0c, - HID_USAGE_PAGE_DIGITIZER = 0x0d, - HID_USAGE_PAGE_PID = 0x0f, - HID_USAGE_PAGE_UNICODE = 0x10, - HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14, - HID_USAGE_PAGE_MEDICAL = 0x40, - HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83 - HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87 - HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c, - HID_USAGE_PAGE_SCALE = 0x8d, - HID_USAGE_PAGE_MSR = 0x8e, - HID_USAGE_PAGE_CAMERA = 0x90, - HID_USAGE_PAGE_ARCADE = 0x91, - HID_USAGE_PAGE_VENDOR = 0xFF00 // 0xFF00 - 0xFFFF -}; - -/// HID Usage Table - Table 6: Generic Desktop Page -enum { - HID_USAGE_DESKTOP_POINTER = 0x01, - HID_USAGE_DESKTOP_MOUSE = 0x02, - HID_USAGE_DESKTOP_JOYSTICK = 0x04, - HID_USAGE_DESKTOP_GAMEPAD = 0x05, - HID_USAGE_DESKTOP_KEYBOARD = 0x06, - HID_USAGE_DESKTOP_KEYPAD = 0x07, - HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER = 0x08, - HID_USAGE_DESKTOP_TABLET_PC_SYSTEM = 0x09, - HID_USAGE_DESKTOP_X = 0x30, - HID_USAGE_DESKTOP_Y = 0x31, - HID_USAGE_DESKTOP_Z = 0x32, - HID_USAGE_DESKTOP_RX = 0x33, - HID_USAGE_DESKTOP_RY = 0x34, - HID_USAGE_DESKTOP_RZ = 0x35, - HID_USAGE_DESKTOP_SLIDER = 0x36, - HID_USAGE_DESKTOP_DIAL = 0x37, - HID_USAGE_DESKTOP_WHEEL = 0x38, - HID_USAGE_DESKTOP_HAT_SWITCH = 0x39, - HID_USAGE_DESKTOP_COUNTED_BUFFER = 0x3a, - HID_USAGE_DESKTOP_BYTE_COUNT = 0x3b, - HID_USAGE_DESKTOP_MOTION_WAKEUP = 0x3c, - HID_USAGE_DESKTOP_START = 0x3d, - HID_USAGE_DESKTOP_SELECT = 0x3e, - HID_USAGE_DESKTOP_VX = 0x40, - HID_USAGE_DESKTOP_VY = 0x41, - HID_USAGE_DESKTOP_VZ = 0x42, - HID_USAGE_DESKTOP_VBRX = 0x43, - HID_USAGE_DESKTOP_VBRY = 0x44, - HID_USAGE_DESKTOP_VBRZ = 0x45, - HID_USAGE_DESKTOP_VNO = 0x46, - HID_USAGE_DESKTOP_FEATURE_NOTIFICATION = 0x47, - HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER = 0x48, - HID_USAGE_DESKTOP_SYSTEM_CONTROL = 0x80, - HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN = 0x81, - HID_USAGE_DESKTOP_SYSTEM_SLEEP = 0x82, - HID_USAGE_DESKTOP_SYSTEM_WAKE_UP = 0x83, - HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU = 0x84, - HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU = 0x85, - HID_USAGE_DESKTOP_SYSTEM_APP_MENU = 0x86, - HID_USAGE_DESKTOP_SYSTEM_MENU_HELP = 0x87, - HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT = 0x88, - HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT = 0x89, - HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT = 0x8A, - HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT = 0x8B, - HID_USAGE_DESKTOP_SYSTEM_MENU_UP = 0x8C, - HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN = 0x8D, - HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART = 0x8E, - HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART = 0x8F, - HID_USAGE_DESKTOP_DPAD_UP = 0x90, - HID_USAGE_DESKTOP_DPAD_DOWN = 0x91, - HID_USAGE_DESKTOP_DPAD_RIGHT = 0x92, - HID_USAGE_DESKTOP_DPAD_LEFT = 0x93, - HID_USAGE_DESKTOP_SYSTEM_DOCK = 0xA0, - HID_USAGE_DESKTOP_SYSTEM_UNDOCK = 0xA1, - HID_USAGE_DESKTOP_SYSTEM_SETUP = 0xA2, - HID_USAGE_DESKTOP_SYSTEM_BREAK = 0xA3, - HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK = 0xA4, - HID_USAGE_DESKTOP_APPLICATION_BREAK = 0xA5, - HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK = 0xA6, - HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE = 0xA7, - HID_USAGE_DESKTOP_SYSTEM_HIBERNATE = 0xA8, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT = 0xB0, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL = 0xB1, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL = 0xB2, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH = 0xB3, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL = 0xB4, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6, - HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7 -}; - - -/// HID Usage Table: Consumer Page (0x0C) -/// Only contains controls that supported by Windows (whole list is too long) -enum -{ - // Generic Control - HID_USAGE_CONSUMER_CONTROL = 0x0001, - - // Power Control - HID_USAGE_CONSUMER_POWER = 0x0030, - HID_USAGE_CONSUMER_RESET = 0x0031, - HID_USAGE_CONSUMER_SLEEP = 0x0032, - - // Screen Brightness - HID_USAGE_CONSUMER_BRIGHTNESS_INCREMENT = 0x006F, - HID_USAGE_CONSUMER_BRIGHTNESS_DECREMENT = 0x0070, - - // These HID usages operate only on mobile systems (battery powered) and - // require Windows 8 (build 8302 or greater). - HID_USAGE_CONSUMER_WIRELESS_RADIO_CONTROLS = 0x000C, - HID_USAGE_CONSUMER_WIRELESS_RADIO_BUTTONS = 0x00C6, - HID_USAGE_CONSUMER_WIRELESS_RADIO_LED = 0x00C7, - HID_USAGE_CONSUMER_WIRELESS_RADIO_SLIDER_SWITCH = 0x00C8, - - // Media Control - HID_USAGE_CONSUMER_PLAY_PAUSE = 0x00CD, - HID_USAGE_CONSUMER_SCAN_NEXT = 0x00B5, - HID_USAGE_CONSUMER_SCAN_PREVIOUS = 0x00B6, - HID_USAGE_CONSUMER_STOP = 0x00B7, - HID_USAGE_CONSUMER_VOLUME = 0x00E0, - HID_USAGE_CONSUMER_MUTE = 0x00E2, - HID_USAGE_CONSUMER_BASS = 0x00E3, - HID_USAGE_CONSUMER_TREBLE = 0x00E4, - HID_USAGE_CONSUMER_BASS_BOOST = 0x00E5, - HID_USAGE_CONSUMER_VOLUME_INCREMENT = 0x00E9, - HID_USAGE_CONSUMER_VOLUME_DECREMENT = 0x00EA, - HID_USAGE_CONSUMER_BASS_INCREMENT = 0x0152, - HID_USAGE_CONSUMER_BASS_DECREMENT = 0x0153, - HID_USAGE_CONSUMER_TREBLE_INCREMENT = 0x0154, - HID_USAGE_CONSUMER_TREBLE_DECREMENT = 0x0155, - - // Application Launcher - HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x0183, - HID_USAGE_CONSUMER_AL_EMAIL_READER = 0x018A, - HID_USAGE_CONSUMER_AL_CALCULATOR = 0x0192, - HID_USAGE_CONSUMER_AL_LOCAL_BROWSER = 0x0194, - - // Browser/Explorer Specific - HID_USAGE_CONSUMER_AC_SEARCH = 0x0221, - HID_USAGE_CONSUMER_AC_HOME = 0x0223, - HID_USAGE_CONSUMER_AC_BACK = 0x0224, - HID_USAGE_CONSUMER_AC_FORWARD = 0x0225, - HID_USAGE_CONSUMER_AC_STOP = 0x0226, - HID_USAGE_CONSUMER_AC_REFRESH = 0x0227, - HID_USAGE_CONSUMER_AC_BOOKMARKS = 0x022A, - - // Mouse Horizontal scroll - HID_USAGE_CONSUMER_AC_PAN = 0x0238, -}; - -/*-------------------------------------------------------------------- - * ASCII to KEYCODE Conversion - * Expand to array of [128][2] (shift, keycode) - * - * Usage: example to convert input chr into keyboard report (modifier + keycode) - * - * uint8_t const conv_table[128][2] = { HID_ASCII_TO_KEYCODE }; - * - * uint8_t keycode[6] = { 0 }; - * uint8_t modifier = 0; - * - * if ( conv_table[chr][0] ) modifier = KEYBOARD_MODIFIER_LEFTSHIFT; - * keycode[0] = conv_table[chr][1]; - * tud_hid_keyboard_report(report_id, modifier, keycode); - * - *--------------------------------------------------------------------*/ -#define HID_ASCII_TO_KEYCODE \ - {0, 0 }, /* 0x00 Null */ \ - {0, 0 }, /* 0x01 */ \ - {0, 0 }, /* 0x02 */ \ - {0, 0 }, /* 0x03 */ \ - {0, 0 }, /* 0x04 */ \ - {0, 0 }, /* 0x05 */ \ - {0, 0 }, /* 0x06 */ \ - {0, 0 }, /* 0x07 */ \ - {0, HID_KEY_BACKSPACE }, /* 0x08 Backspace */ \ - {0, HID_KEY_TAB }, /* 0x09 Tab */ \ - {0, HID_KEY_ENTER }, /* 0x0A Line Feed */ \ - {0, 0 }, /* 0x0B */ \ - {0, 0 }, /* 0x0C */ \ - {0, HID_KEY_ENTER }, /* 0x0D CR */ \ - {0, 0 }, /* 0x0E */ \ - {0, 0 }, /* 0x0F */ \ - {0, 0 }, /* 0x10 */ \ - {0, 0 }, /* 0x11 */ \ - {0, 0 }, /* 0x12 */ \ - {0, 0 }, /* 0x13 */ \ - {0, 0 }, /* 0x14 */ \ - {0, 0 }, /* 0x15 */ \ - {0, 0 }, /* 0x16 */ \ - {0, 0 }, /* 0x17 */ \ - {0, 0 }, /* 0x18 */ \ - {0, 0 }, /* 0x19 */ \ - {0, 0 }, /* 0x1A */ \ - {0, HID_KEY_ESCAPE }, /* 0x1B Escape */ \ - {0, 0 }, /* 0x1C */ \ - {0, 0 }, /* 0x1D */ \ - {0, 0 }, /* 0x1E */ \ - {0, 0 }, /* 0x1F */ \ - \ - {0, HID_KEY_SPACE }, /* 0x20 */ \ - {1, HID_KEY_1 }, /* 0x21 ! */ \ - {1, HID_KEY_APOSTROPHE }, /* 0x22 " */ \ - {1, HID_KEY_3 }, /* 0x23 # */ \ - {1, HID_KEY_4 }, /* 0x24 $ */ \ - {1, HID_KEY_5 }, /* 0x25 % */ \ - {1, HID_KEY_7 }, /* 0x26 & */ \ - {0, HID_KEY_APOSTROPHE }, /* 0x27 ' */ \ - {1, HID_KEY_9 }, /* 0x28 ( */ \ - {1, HID_KEY_0 }, /* 0x29 ) */ \ - {1, HID_KEY_8 }, /* 0x2A * */ \ - {1, HID_KEY_EQUAL }, /* 0x2B + */ \ - {0, HID_KEY_COMMA }, /* 0x2C , */ \ - {0, HID_KEY_MINUS }, /* 0x2D - */ \ - {0, HID_KEY_PERIOD }, /* 0x2E . */ \ - {0, HID_KEY_SLASH }, /* 0x2F / */ \ - {0, HID_KEY_0 }, /* 0x30 0 */ \ - {0, HID_KEY_1 }, /* 0x31 1 */ \ - {0, HID_KEY_2 }, /* 0x32 2 */ \ - {0, HID_KEY_3 }, /* 0x33 3 */ \ - {0, HID_KEY_4 }, /* 0x34 4 */ \ - {0, HID_KEY_5 }, /* 0x35 5 */ \ - {0, HID_KEY_6 }, /* 0x36 6 */ \ - {0, HID_KEY_7 }, /* 0x37 7 */ \ - {0, HID_KEY_8 }, /* 0x38 8 */ \ - {0, HID_KEY_9 }, /* 0x39 9 */ \ - {1, HID_KEY_SEMICOLON }, /* 0x3A : */ \ - {0, HID_KEY_SEMICOLON }, /* 0x3B ; */ \ - {1, HID_KEY_COMMA }, /* 0x3C < */ \ - {0, HID_KEY_EQUAL }, /* 0x3D = */ \ - {1, HID_KEY_PERIOD }, /* 0x3E > */ \ - {1, HID_KEY_SLASH }, /* 0x3F ? */ \ - \ - {1, HID_KEY_2 }, /* 0x40 @ */ \ - {1, HID_KEY_A }, /* 0x41 A */ \ - {1, HID_KEY_B }, /* 0x42 B */ \ - {1, HID_KEY_C }, /* 0x43 C */ \ - {1, HID_KEY_D }, /* 0x44 D */ \ - {1, HID_KEY_E }, /* 0x45 E */ \ - {1, HID_KEY_F }, /* 0x46 F */ \ - {1, HID_KEY_G }, /* 0x47 G */ \ - {1, HID_KEY_H }, /* 0x48 H */ \ - {1, HID_KEY_I }, /* 0x49 I */ \ - {1, HID_KEY_J }, /* 0x4A J */ \ - {1, HID_KEY_K }, /* 0x4B K */ \ - {1, HID_KEY_L }, /* 0x4C L */ \ - {1, HID_KEY_M }, /* 0x4D M */ \ - {1, HID_KEY_N }, /* 0x4E N */ \ - {1, HID_KEY_O }, /* 0x4F O */ \ - {1, HID_KEY_P }, /* 0x50 P */ \ - {1, HID_KEY_Q }, /* 0x51 Q */ \ - {1, HID_KEY_R }, /* 0x52 R */ \ - {1, HID_KEY_S }, /* 0x53 S */ \ - {1, HID_KEY_T }, /* 0x55 T */ \ - {1, HID_KEY_U }, /* 0x55 U */ \ - {1, HID_KEY_V }, /* 0x56 V */ \ - {1, HID_KEY_W }, /* 0x57 W */ \ - {1, HID_KEY_X }, /* 0x58 X */ \ - {1, HID_KEY_Y }, /* 0x59 Y */ \ - {1, HID_KEY_Z }, /* 0x5A Z */ \ - {0, HID_KEY_BRACKET_LEFT }, /* 0x5B [ */ \ - {0, HID_KEY_BACKSLASH }, /* 0x5C '\' */ \ - {0, HID_KEY_BRACKET_RIGHT }, /* 0x5D ] */ \ - {1, HID_KEY_6 }, /* 0x5E ^ */ \ - {1, HID_KEY_MINUS }, /* 0x5F _ */ \ - \ - {0, HID_KEY_GRAVE }, /* 0x60 ` */ \ - {0, HID_KEY_A }, /* 0x61 a */ \ - {0, HID_KEY_B }, /* 0x62 b */ \ - {0, HID_KEY_C }, /* 0x63 c */ \ - {0, HID_KEY_D }, /* 0x66 d */ \ - {0, HID_KEY_E }, /* 0x65 e */ \ - {0, HID_KEY_F }, /* 0x66 f */ \ - {0, HID_KEY_G }, /* 0x67 g */ \ - {0, HID_KEY_H }, /* 0x68 h */ \ - {0, HID_KEY_I }, /* 0x69 i */ \ - {0, HID_KEY_J }, /* 0x6A j */ \ - {0, HID_KEY_K }, /* 0x6B k */ \ - {0, HID_KEY_L }, /* 0x6C l */ \ - {0, HID_KEY_M }, /* 0x6D m */ \ - {0, HID_KEY_N }, /* 0x6E n */ \ - {0, HID_KEY_O }, /* 0x6F o */ \ - {0, HID_KEY_P }, /* 0x70 p */ \ - {0, HID_KEY_Q }, /* 0x71 q */ \ - {0, HID_KEY_R }, /* 0x72 r */ \ - {0, HID_KEY_S }, /* 0x73 s */ \ - {0, HID_KEY_T }, /* 0x75 t */ \ - {0, HID_KEY_U }, /* 0x75 u */ \ - {0, HID_KEY_V }, /* 0x76 v */ \ - {0, HID_KEY_W }, /* 0x77 w */ \ - {0, HID_KEY_X }, /* 0x78 x */ \ - {0, HID_KEY_Y }, /* 0x79 y */ \ - {0, HID_KEY_Z }, /* 0x7A z */ \ - {1, HID_KEY_BRACKET_LEFT }, /* 0x7B { */ \ - {1, HID_KEY_BACKSLASH }, /* 0x7C | */ \ - {1, HID_KEY_BRACKET_RIGHT }, /* 0x7D } */ \ - {1, HID_KEY_GRAVE }, /* 0x7E ~ */ \ - {0, HID_KEY_DELETE } /* 0x7F Delete */ \ - -/*-------------------------------------------------------------------- - * KEYCODE to Ascii Conversion - * Expand to array of [128][2] (ascii without shift, ascii with shift) - * - * Usage: example to convert ascii from keycode (key) and shift modifier (shift). - * Here we assume key < 128 ( printable ) - * - * uint8_t const conv_table[128][2] = { HID_KEYCODE_TO_ASCII }; - * char ch = shift ? conv_table[chr][1] : conv_table[chr][0]; - * - *--------------------------------------------------------------------*/ -#define HID_KEYCODE_TO_ASCII \ - {0 , 0 }, /* 0x00 */ \ - {0 , 0 }, /* 0x01 */ \ - {0 , 0 }, /* 0x02 */ \ - {0 , 0 }, /* 0x03 */ \ - {'a' , 'A' }, /* 0x04 */ \ - {'b' , 'B' }, /* 0x05 */ \ - {'c' , 'C' }, /* 0x06 */ \ - {'d' , 'D' }, /* 0x07 */ \ - {'e' , 'E' }, /* 0x08 */ \ - {'f' , 'F' }, /* 0x09 */ \ - {'g' , 'G' }, /* 0x0a */ \ - {'h' , 'H' }, /* 0x0b */ \ - {'i' , 'I' }, /* 0x0c */ \ - {'j' , 'J' }, /* 0x0d */ \ - {'k' , 'K' }, /* 0x0e */ \ - {'l' , 'L' }, /* 0x0f */ \ - {'m' , 'M' }, /* 0x10 */ \ - {'n' , 'N' }, /* 0x11 */ \ - {'o' , 'O' }, /* 0x12 */ \ - {'p' , 'P' }, /* 0x13 */ \ - {'q' , 'Q' }, /* 0x14 */ \ - {'r' , 'R' }, /* 0x15 */ \ - {'s' , 'S' }, /* 0x16 */ \ - {'t' , 'T' }, /* 0x17 */ \ - {'u' , 'U' }, /* 0x18 */ \ - {'v' , 'V' }, /* 0x19 */ \ - {'w' , 'W' }, /* 0x1a */ \ - {'x' , 'X' }, /* 0x1b */ \ - {'y' , 'Y' }, /* 0x1c */ \ - {'z' , 'Z' }, /* 0x1d */ \ - {'1' , '!' }, /* 0x1e */ \ - {'2' , '@' }, /* 0x1f */ \ - {'3' , '#' }, /* 0x20 */ \ - {'4' , '$' }, /* 0x21 */ \ - {'5' , '%' }, /* 0x22 */ \ - {'6' , '^' }, /* 0x23 */ \ - {'7' , '&' }, /* 0x24 */ \ - {'8' , '*' }, /* 0x25 */ \ - {'9' , '(' }, /* 0x26 */ \ - {'0' , ')' }, /* 0x27 */ \ - {'\r' , '\r' }, /* 0x28 */ \ - {'\x1b', '\x1b' }, /* 0x29 */ \ - {'\b' , '\b' }, /* 0x2a */ \ - {'\t' , '\t' }, /* 0x2b */ \ - {' ' , ' ' }, /* 0x2c */ \ - {'-' , '_' }, /* 0x2d */ \ - {'=' , '+' }, /* 0x2e */ \ - {'[' , '{' }, /* 0x2f */ \ - {']' , '}' }, /* 0x30 */ \ - {'\\' , '|' }, /* 0x31 */ \ - {'#' , '~' }, /* 0x32 */ \ - {';' , ':' }, /* 0x33 */ \ - {'\'' , '\"' }, /* 0x34 */ \ - {'`' , '~' }, /* 0x35 */ \ - {',' , '<' }, /* 0x36 */ \ - {'.' , '>' }, /* 0x37 */ \ - {'/' , '?' }, /* 0x38 */ \ - \ - {0 , 0 }, /* 0x39 */ \ - {0 , 0 }, /* 0x3a */ \ - {0 , 0 }, /* 0x3b */ \ - {0 , 0 }, /* 0x3c */ \ - {0 , 0 }, /* 0x3d */ \ - {0 , 0 }, /* 0x3e */ \ - {0 , 0 }, /* 0x3f */ \ - {0 , 0 }, /* 0x40 */ \ - {0 , 0 }, /* 0x41 */ \ - {0 , 0 }, /* 0x42 */ \ - {0 , 0 }, /* 0x43 */ \ - {0 , 0 }, /* 0x44 */ \ - {0 , 0 }, /* 0x45 */ \ - {0 , 0 }, /* 0x46 */ \ - {0 , 0 }, /* 0x47 */ \ - {0 , 0 }, /* 0x48 */ \ - {0 , 0 }, /* 0x49 */ \ - {0 , 0 }, /* 0x4a */ \ - {0 , 0 }, /* 0x4b */ \ - {0 , 0 }, /* 0x4c */ \ - {0 , 0 }, /* 0x4d */ \ - {0 , 0 }, /* 0x4e */ \ - {0 , 0 }, /* 0x4f */ \ - {0 , 0 }, /* 0x50 */ \ - {0 , 0 }, /* 0x51 */ \ - {0 , 0 }, /* 0x52 */ \ - {0 , 0 }, /* 0x53 */ \ - \ - {'/' , '/' }, /* 0x54 */ \ - {'*' , '*' }, /* 0x55 */ \ - {'-' , '-' }, /* 0x56 */ \ - {'+' , '+' }, /* 0x57 */ \ - {'\r' , '\r' }, /* 0x58 */ \ - {'1' , 0 }, /* 0x59 */ \ - {'2' , 0 }, /* 0x5a */ \ - {'3' , 0 }, /* 0x5b */ \ - {'4' , 0 }, /* 0x5c */ \ - {'5' , '5' }, /* 0x5d */ \ - {'6' , 0 }, /* 0x5e */ \ - {'7' , 0 }, /* 0x5f */ \ - {'8' , 0 }, /* 0x60 */ \ - {'9' , 0 }, /* 0x61 */ \ - {'0' , 0 }, /* 0x62 */ \ - {'0' , 0 }, /* 0x63 */ \ - {'=' , '=' }, /* 0x67 */ \ - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HID_H__ */ - -/// @} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c deleted file mode 100644 index 588b61254..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_HID) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "hid_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; // optional Out endpoint - uint8_t itf_protocol; // Boot mouse or keyboard - - uint8_t protocol_mode; // Boot (0) or Report protocol (1) - uint8_t idle_rate; // up to application to handle idle rate - uint16_t report_desc_len; - - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; - - // TODO save hid descriptor since host can specifically request this after enumeration - // Note: HID descriptor may be not available from application after enumeration - tusb_hid_descriptor_hid_t const * hid_descriptor; -} hidd_interface_t; - -CFG_TUSB_MEM_SECTION static hidd_interface_t _hidd_itf[CFG_TUD_HID]; - -/*------------- Helpers -------------*/ -static inline uint8_t get_index_by_itfnum(uint8_t itf_num) -{ - for (uint8_t i=0; i < CFG_TUD_HID; i++ ) - { - if ( itf_num == _hidd_itf[i].itf_num ) return i; - } - - return 0xFF; -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_hid_n_ready(uint8_t instance) -{ - uint8_t const ep_in = _hidd_itf[instance].ep_in; - return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); -} - -bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len) -{ - uint8_t const rhport = 0; - hidd_interface_t * p_hid = &_hidd_itf[instance]; - - // claim endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); - - // prepare data - if (report_id) - { - len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); - - p_hid->epin_buf[0] = report_id; - memcpy(p_hid->epin_buf+1, report, len); - len++; - }else - { - // If report id = 0, skip ID field - len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE); - memcpy(p_hid->epin_buf, report, len); - } - - return usbd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len); -} - -uint8_t tud_hid_n_interface_protocol(uint8_t instance) -{ - return _hidd_itf[instance].itf_protocol; -} - -uint8_t tud_hid_n_get_protocol(uint8_t instance) -{ - return _hidd_itf[instance].protocol_mode; -} - -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) -{ - hid_keyboard_report_t report; - - report.modifier = modifier; - report.reserved = 0; - - if ( keycode ) - { - memcpy(report.keycode, keycode, 6); - }else - { - tu_memclr(report.keycode, 6); - } - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, - uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) -{ - hid_mouse_report_t report = - { - .buttons = buttons, - .x = x, - .y = y, - .wheel = vertical, - .pan = horizontal - }; - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, - int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) -{ - hid_gamepad_report_t report = - { - .x = x, - .y = y, - .z = z, - .rz = rz, - .rx = rx, - .ry = ry, - .hat = hat, - .buttons = buttons, - }; - - return tud_hid_n_report(instance, report_id, &report, sizeof(report)); -} - -//--------------------------------------------------------------------+ -// USBD-CLASS API -//--------------------------------------------------------------------+ -void hidd_init(void) -{ - hidd_reset(TUD_OPT_RHPORT); -} - -void hidd_reset(uint8_t rhport) -{ - (void) rhport; - tu_memclr(_hidd_itf, sizeof(_hidd_itf)); -} - -uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) -{ - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); - - // len = interface + hid + n*endpoints - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - TU_ASSERT(max_len >= drv_len, 0); - - // Find available interface - hidd_interface_t * p_hid = NULL; - uint8_t hid_id; - for(hid_id=0; hid_idhid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc; - - //------------- Endpoint Descriptor -------------// - p_desc = tu_desc_next(p_desc); - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); - - if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; - - p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode - p_hid->itf_num = desc_itf->bInterfaceNumber; - - // Use offsetof to avoid pointer to the odd/misaligned address - p_hid->report_desc_len = tu_unaligned_read16((uint8_t const*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength)); - - // Prepare for output endpoint - if (p_hid->ep_out) - { - if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) ) - { - TU_LOG_FAILED(); - TU_BREAKPOINT(); - } - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - uint8_t const hid_itf = get_index_by_itfnum((uint8_t) request->wIndex); - TU_VERIFY(hid_itf < CFG_TUD_HID); - - hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; - - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) - { - //------------- STD Request -------------// - if ( stage == CONTROL_STAGE_SETUP ) - { - uint8_t const desc_type = tu_u16_high(request->wValue); - //uint8_t const desc_index = tu_u16_low (request->wValue); - - if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) - { - TU_VERIFY(p_hid->hid_descriptor); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); - } - else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) - { - uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); - tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_report, p_hid->report_desc_len); - } - else - { - return false; // stall unsupported request - } - } - } - else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) - { - //------------- Class Specific Request -------------// - switch( request->bRequest ) - { - case HID_REQ_CONTROL_GET_REPORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - uint8_t* report_buf = p_hid->epin_buf; - uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); - - uint16_t xferlen = 0; - - // If host request a specific Report ID, add ID to as 1 byte of response - if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) ) - { - *report_buf++ = report_id; - req_len--; - - xferlen++; - } - - xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len); - TU_ASSERT( xferlen > 0 ); - - tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); - } - break; - - case HID_REQ_CONTROL_SET_REPORT: - if ( stage == CONTROL_STAGE_SETUP ) - { - TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); - tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - uint8_t const* report_buf = p_hid->epout_buf; - uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); - - // If host request a specific Report ID, extract report ID in buffer before invoking callback - if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) ) - { - report_buf++; - report_len--; - } - - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len); - } - break; - - case HID_REQ_CONTROL_SET_IDLE: - if ( stage == CONTROL_STAGE_SETUP ) - { - p_hid->idle_rate = tu_u16_high(request->wValue); - if ( tud_hid_set_idle_cb ) - { - // stall request if callback return false - TU_VERIFY( tud_hid_set_idle_cb( hid_itf, p_hid->idle_rate) ); - } - - tud_control_status(rhport, request); - } - break; - - case HID_REQ_CONTROL_GET_IDLE: - if ( stage == CONTROL_STAGE_SETUP ) - { - // TODO idle rate of report - tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); - } - break; - - case HID_REQ_CONTROL_GET_PROTOCOL: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1); - } - break; - - case HID_REQ_CONTROL_SET_PROTOCOL: - if ( stage == CONTROL_STAGE_SETUP ) - { - tud_control_status(rhport, request); - } - else if ( stage == CONTROL_STAGE_ACK ) - { - p_hid->protocol_mode = (uint8_t) request->wValue; - if (tud_hid_set_protocol_cb) - { - tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode); - } - } - break; - - default: return false; // stall unsupported request - } - }else - { - return false; // stall unsupported request - } - - return true; -} - -bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t instance = 0; - hidd_interface_t * p_hid = _hidd_itf; - - // Identify which interface to use - for (instance = 0; instance < CFG_TUD_HID; instance++) - { - p_hid = &_hidd_itf[instance]; - if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; - } - TU_ASSERT(instance < CFG_TUD_HID); - - // Sent report successfully - if (ep_addr == p_hid->ep_in) - { - if (tud_hid_report_complete_cb) - { - tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint8_t) xferred_bytes); - } - } - // Received report - else if (ep_addr == p_hid->ep_out) - { - tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); - TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h deleted file mode 100644 index 078b67349..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_device.h +++ /dev/null @@ -1,393 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HID_DEVICE_H_ -#define _TUSB_HID_DEVICE_H_ - -#include "hid.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Default Configure & Validation -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_HID_EP_BUFSIZE) & defined(CFG_TUD_HID_BUFSIZE) - // TODO warn user to use new name later on - // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE -#endif - -#ifndef CFG_TUD_HID_EP_BUFSIZE - #define CFG_TUD_HID_EP_BUFSIZE 64 -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Instances) -// CFG_TUD_HID > 1 -//--------------------------------------------------------------------+ - -// Check if the interface is ready to use -bool tud_hid_n_ready(uint8_t instance); - -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tud_hid_n_interface_protocol(uint8_t instance); - -// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -uint8_t tud_hid_n_get_protocol(uint8_t instance); - -// Send report to host -bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len); - -// KEYBOARD: convenient helper to send keyboard report if application -// use template layout report as defined by hid_keyboard_report_t -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); - -// MOUSE: convenient helper to send mouse report if application -// use template layout report as defined by hid_mouse_report_t -bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); - -// Gamepad: convenient helper to send gamepad report if application -// use template layout report TUD_HID_REPORT_DESC_GAMEPAD -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void); -static inline uint8_t tud_hid_interface_protocol(void); -static inline uint8_t tud_hid_get_protocol(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); - -//--------------------------------------------------------------------+ -// Callbacks (Weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received GET HID REPORT DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance); - -// Invoked when received GET_REPORT control request -// Application must fill buffer report's content and return its length. -// Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); - -// Invoked when received SET_REPORT control request or -// received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); - -// Invoked when received SET_PROTOCOL request -// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol); - -// Invoked when received SET_IDLE request. return false will stall the request -// - Idle Rate = 0 : only send report if there is changes, i.e skip duplication -// - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate); - -// Invoked when sent REPORT successfully to host -// Application can use this to send the next report -// Note: For composite reports, report[0] is report ID -TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len); - - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void) -{ - return tud_hid_n_ready(0); -} - -static inline uint8_t tud_hid_interface_protocol(void) -{ - return tud_hid_n_interface_protocol(0); -} - -static inline uint8_t tud_hid_get_protocol(void) -{ - return tud_hid_n_get_protocol(0); -} - -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) -{ - return tud_hid_n_report(0, report_id, report, len); -} - -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) -{ - return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); -} - -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) -{ - return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); -} - -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) -{ - return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); -} - -/* --------------------------------------------------------------------+ - * HID Report Descriptor Template - * - * Convenient for declaring popular HID device (keyboard, mouse, consumer, - * gamepad etc...). Templates take "HID_REPORT_ID(n)" as input, leave - * empty if multiple reports is not used - * - * - Only 1 report: no parameter - * uint8_t const report_desc[] = { TUD_HID_REPORT_DESC_KEYBOARD() }; - * - * - Multiple Reports: "HID_REPORT_ID(ID)" must be passed to template - * uint8_t const report_desc[] = - * { - * TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(1) ) , - * TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(2) ) - * }; - *--------------------------------------------------------------------*/ - -// Keyboard Report Descriptor Template -#define TUD_HID_REPORT_DESC_KEYBOARD(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_KEYBOARD ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 8 bits Modifier Keys (Shfit, Control, Alt) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ - HID_USAGE_MIN ( 224 ) ,\ - HID_USAGE_MAX ( 231 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 8 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 8 bit reserved */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - /* Output 5-bit LED Indicator Kana | Compose | ScrollLock | CapsLock | NumLock */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_LED ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 5 ) ,\ - HID_REPORT_COUNT ( 5 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* led padding */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 3 ) ,\ - HID_OUTPUT ( HID_CONSTANT ) ,\ - /* 6-byte Keycodes */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ - HID_USAGE_MIN ( 0 ) ,\ - HID_USAGE_MAX_N ( 255, 2 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX_N( 255, 2 ) ,\ - HID_REPORT_COUNT ( 6 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -// Mouse Report Descriptor Template -#define TUD_HID_REPORT_DESC_MOUSE(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\ - HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 5 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - /* Left, Right, Middle, Backward, Forward buttons */ \ - HID_REPORT_COUNT( 5 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 3 bit padding */ \ - HID_REPORT_COUNT( 1 ) ,\ - HID_REPORT_SIZE ( 3 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - /* X, Y position [-127, 127] */ \ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT( 2 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ - /* Verital wheel scroll [-127, 127] */ \ - HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ - HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \ - /* Horizontal wheel scroll [-127, 127] */ \ - HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \ - HID_LOGICAL_MIN ( 0x81 ), \ - HID_LOGICAL_MAX ( 0x7f ), \ - HID_REPORT_COUNT( 1 ), \ - HID_REPORT_SIZE ( 8 ), \ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \ - HID_COLLECTION_END , \ - HID_COLLECTION_END \ - -// Consumer Control Report Descriptor Template -#define TUD_HID_REPORT_DESC_CONSUMER(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ) ,\ - HID_USAGE ( HID_USAGE_CONSUMER_CONTROL ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - HID_LOGICAL_MIN ( 0x00 ) ,\ - HID_LOGICAL_MAX_N( 0x03FF, 2 ) ,\ - HID_USAGE_MIN ( 0x00 ) ,\ - HID_USAGE_MAX_N ( 0x03FF, 2 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 16 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -/* System Control Report Descriptor Template - * 0x00 - do nothing - * 0x01 - Power Off - * 0x02 - Standby - * 0x03 - Wake Host - */ -#define TUD_HID_REPORT_DESC_SYSTEM_CONTROL(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_CONTROL ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 2 bit system power control */ \ - HID_LOGICAL_MIN ( 1 ) ,\ - HID_LOGICAL_MAX ( 3 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 2 ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_SLEEP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_WAKE_UP ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ - /* 6 bit padding */ \ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 6 ) ,\ - HID_INPUT ( HID_CONSTANT ) ,\ - HID_COLLECTION_END \ - -// Gamepad Report Descriptor Template -// with 32 buttons, 2 joysticks and 1 hat/dpad with following layout -// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (4 bytes) | -#define TUD_HID_REPORT_DESC_GAMEPAD(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_REPORT_COUNT ( 6 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 8 bit DPad/Hat Button Map */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\ - HID_LOGICAL_MIN ( 1 ) ,\ - HID_LOGICAL_MAX ( 8 ) ,\ - HID_PHYSICAL_MIN ( 0 ) ,\ - HID_PHYSICAL_MAX_N ( 315, 2 ) ,\ - HID_REPORT_COUNT ( 1 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* 32 bit Button Map */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ - HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 32 ) ,\ - HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 32 ) ,\ - HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - HID_COLLECTION_END \ - -// HID Generic Input & Output -// - 1st parameter is report size (mandatory) -// - 2nd parameter is report id HID_REPORT_ID(n) (optional) -#define TUD_HID_REPORT_DESC_GENERIC_INOUT(report_size, ...) \ - HID_USAGE_PAGE_N ( HID_USAGE_PAGE_VENDOR, 2 ),\ - HID_USAGE ( 0x01 ),\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ),\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* Input */ \ - HID_USAGE ( 0x02 ),\ - HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX_N ( 0xff, 2 ),\ - HID_REPORT_SIZE ( 8 ),\ - HID_REPORT_COUNT( report_size ),\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ - /* Output */ \ - HID_USAGE ( 0x03 ),\ - HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX_N ( 0xff, 2 ),\ - HID_REPORT_SIZE ( 8 ),\ - HID_REPORT_COUNT( report_size ),\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ - HID_COLLECTION_END \ - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void hidd_init (void); -void hidd_reset (uint8_t rhport); -uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HID_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c deleted file mode 100644 index f19f1ba81..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "hid_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - uint8_t itf_protocol; // None, Keyboard, Mouse - uint8_t protocol_mode; // Boot (0) or Report protocol (1) - - uint8_t report_desc_type; - uint16_t report_desc_len; - - uint16_t epin_size; - uint16_t epout_size; - - uint8_t epin_buf[CFG_TUH_HID_EPIN_BUFSIZE]; - uint8_t epout_buf[CFG_TUH_HID_EPOUT_BUFSIZE]; -} hidh_interface_t; - -typedef struct -{ - uint8_t inst_count; - hidh_interface_t instances[CFG_TUH_HID]; -} hidh_device_t; - -static hidh_device_t _hidh_dev[CFG_TUH_DEVICE_MAX]; - -//------------- Internal prototypes -------------// - -// Get HID device & interface -TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); -TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); -static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); -static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); - -//--------------------------------------------------------------------+ -// Interface API -//--------------------------------------------------------------------+ - -uint8_t tuh_hid_instance_count(uint8_t dev_addr) -{ - return get_dev(dev_addr)->inst_count; -} - -bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); -} - -uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->itf_protocol; -} - -//--------------------------------------------------------------------+ -// Control Endpoint API -//--------------------------------------------------------------------+ - -uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->protocol_mode; -} - -static bool set_protocol_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) request->wValue; - - if (tuh_hid_set_protocol_complete_cb) - { - tuh_hid_set_protocol_complete_cb(dev_addr, instance, hid_itf->protocol_mode); - } - - return true; -} - -bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); - - TU_LOG2("HID Set Protocol = %d\r\n", protocol); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = protocol, - .wIndex = hid_itf->itf_num, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_protocol_complete) ); - return true; -} - -static bool set_report_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_LOG2("HID Set Report complete\r\n"); - - if (tuh_hid_set_report_complete_cb) - { - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? request->wLength : 0); - } - - return true; -} - -bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); - - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_REPORT, - .wValue = tu_u16(report_type, report_id), - .wIndex = hid_itf->itf_num, - .wLength = len - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, report, set_report_complete) ); - return true; -} - -//--------------------------------------------------------------------+ -// Interrupt Endpoint API -//--------------------------------------------------------------------+ - -bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // claim endpoint - TU_VERIFY( usbh_edpt_claim(dev_addr, hid_itf->ep_in) ); - - return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); -} - -//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) -//{ -// TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); -// -// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); -// return !usbh_edpt_busy(dev_addr, hid_itf->ep_in); -//} - -//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); - -//--------------------------------------------------------------------+ -// USBH API -//--------------------------------------------------------------------+ -void hidh_init(void) -{ - tu_memclr(_hidh_dev, sizeof(_hidh_dev)); -} - -bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - uint8_t const dir = tu_edpt_dir(ep_addr); - uint8_t const instance = get_instance_id_by_epaddr(dev_addr, ep_addr); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - if ( dir == TUSB_DIR_IN ) - { - TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance); - TU_LOG3_MEM(hid_itf->epin_buf, xferred_bytes, 2); - tuh_hid_report_received_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); - }else - { - if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(dev_addr, instance, hid_itf->epout_buf, xferred_bytes); - } - - return true; -} - -void hidh_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - - hidh_device_t* hid_dev = get_dev(dev_addr); - - if (tuh_hid_umount_cb) - { - for (uint8_t inst = 0; inst < hid_dev->inst_count; inst++ ) tuh_hid_umount_cb(dev_addr, inst); - } - - tu_memclr(hid_dev, sizeof(hidh_device_t)); -} - -//--------------------------------------------------------------------+ -// Enumeration -//--------------------------------------------------------------------+ - -static bool config_set_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); - -static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); - -bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ - (void) max_len; - - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); - - TU_LOG2("HID opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); - - // len = interface + hid + n*endpoints - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - TU_ASSERT(max_len >= drv_len); - - uint8_t const *p_desc = (uint8_t const *) desc_itf; - - //------------- HID descriptor -------------// - p_desc = tu_desc_next(p_desc); - tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); - - // not enough interface, try to increase CFG_TUH_HID - // TODO multiple devices - hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0); - - //------------- Endpoint Descriptor -------------// - p_desc = tu_desc_next(p_desc); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - - // first endpoint may be OUT, skip to IN endpoint - // TODO also open endpoint OUT - if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT) - { - p_desc = tu_desc_next(p_desc); - desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - } - - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - - hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); - hid_dev->inst_count++; - - hid_itf->itf_num = desc_itf->bInterfaceNumber; - hid_itf->ep_in = desc_ep->bEndpointAddress; - hid_itf->epin_size = tu_edpt_packet_size(desc_ep); - - // Assume bNumDescriptors = 1 - hid_itf->report_desc_type = desc_hid->bReportType; - hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); - - // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config - hid_itf->protocol_mode = HID_PROTOCOL_BOOT; - if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; - - return true; -} - -bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // Idle rate = 0 mean only report when there is changes - uint16_t const idle_rate = 0; - - // SET IDLE request, device can stall if not support this request - TU_LOG2("HID Set Idle \r\n"); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = idle_rate, - .wIndex = itf_num, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc) ); - - return true; -} - -// Force device to work in BOOT protocol -static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - // Stall is a valid response for SET_IDLE, therefore we could ignore its result - (void) result; - - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - TU_LOG2("HID Set Protocol to Boot Mode\r\n"); - hid_itf->protocol_mode = HID_PROTOCOL_BOOT; - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = HID_PROTOCOL_BOOT, - .wIndex = hid_itf->itf_num, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); - return true; -} - -static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - // We can be here after SET_IDLE or SET_PROTOCOL (boot device) - // Trigger assert if result is not successful with set protocol - if ( request->bRequest != HID_REQ_CONTROL_SET_IDLE ) - { - TU_ASSERT(result == XFER_RESULT_SUCCESS); - } - - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // Get Report Descriptor if possible - // using usbh enumeration buffer since report descriptor can be very long - if( hid_itf->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) - { - TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len); - - // Driver is mounted without report descriptor - config_driver_mount_complete(dev_addr, instance, NULL, 0); - }else - { - TU_LOG2("HID Get Report Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_u16(hid_itf->report_desc_type, 0), - .wIndex = itf_num, - .wLength = hid_itf->report_desc_len - }; - - TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); - } - - return true; -} - -static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - - uint8_t const* desc_report = usbh_get_enum_buf(); - uint16_t const desc_len = request->wLength; - - config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); - - return true; -} - -static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // enumeration is complete - tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len); - - // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num); -} - -//--------------------------------------------------------------------+ -// Report Descriptor Parser -//--------------------------------------------------------------------+ - -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) -{ - // Report Item 6.2.2.2 USB HID 1.11 - union TU_ATTR_PACKED - { - uint8_t byte; - struct TU_ATTR_PACKED - { - uint8_t size : 2; - uint8_t type : 2; - uint8_t tag : 4; - }; - } header; - - tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t)); - - uint8_t report_num = 0; - tuh_hid_report_info_t* info = report_info_arr; - - // current parsed report count & size from descriptor -// uint8_t ri_report_count = 0; -// uint8_t ri_report_size = 0; - - uint8_t ri_collection_depth = 0; - - while(desc_len && report_num < arr_count) - { - header.byte = *desc_report++; - desc_len--; - - uint8_t const tag = header.tag; - uint8_t const type = header.type; - uint8_t const size = header.size; - - uint8_t const data8 = desc_report[0]; - - TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size); - for(uint32_t i=0; iusage_page, desc_report, size); - break; - - case RI_GLOBAL_LOGICAL_MIN : break; - case RI_GLOBAL_LOGICAL_MAX : break; - case RI_GLOBAL_PHYSICAL_MIN : break; - case RI_GLOBAL_PHYSICAL_MAX : break; - - case RI_GLOBAL_REPORT_ID: - info->report_id = data8; - break; - - case RI_GLOBAL_REPORT_SIZE: -// ri_report_size = data8; - break; - - case RI_GLOBAL_REPORT_COUNT: -// ri_report_count = data8; - break; - - case RI_GLOBAL_UNIT_EXPONENT : break; - case RI_GLOBAL_UNIT : break; - case RI_GLOBAL_PUSH : break; - case RI_GLOBAL_POP : break; - - default: break; - } - break; - - case RI_TYPE_LOCAL: - switch(tag) - { - case RI_LOCAL_USAGE: - // only take in account the "usage" before starting REPORT ID - if ( ri_collection_depth == 0 ) info->usage = data8; - break; - - case RI_LOCAL_USAGE_MIN : break; - case RI_LOCAL_USAGE_MAX : break; - case RI_LOCAL_DESIGNATOR_INDEX : break; - case RI_LOCAL_DESIGNATOR_MIN : break; - case RI_LOCAL_DESIGNATOR_MAX : break; - case RI_LOCAL_STRING_INDEX : break; - case RI_LOCAL_STRING_MIN : break; - case RI_LOCAL_STRING_MAX : break; - case RI_LOCAL_DELIMITER : break; - default: break; - } - break; - - // error - default: break; - } - - desc_report += size; - desc_len -= size; - } - - for ( uint8_t i = 0; i < report_num; i++ ) - { - info = report_info_arr+i; - TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); - } - - return report_num; -} - -//--------------------------------------------------------------------+ -// Helper -//--------------------------------------------------------------------+ - -// Get Device by address -TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) -{ - return &_hidh_dev[dev_addr-1]; -} - -// Get Interface by instance number -TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) -{ - return &_hidh_dev[dev_addr-1].instances[instance]; -} - -// Get instance ID by interface number -static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return inst; - } - - return 0xff; -} - -// Get instance ID by endpoint address -static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (ep_addr == hid->ep_in) || ( ep_addr == hid->ep_out) ) return inst; - } - - return 0xff; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h deleted file mode 100644 index fe09b03b2..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/hid/hid_host.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HID_HOST_H_ -#define _TUSB_HID_HOST_H_ - -#include "hid.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -// TODO Highspeed interrupt can be up to 512 bytes -#ifndef CFG_TUH_HID_EPIN_BUFSIZE -#define CFG_TUH_HID_EPIN_BUFSIZE 64 -#endif - -#ifndef CFG_TUH_HID_EPOUT_BUFSIZE -#define CFG_TUH_HID_EPOUT_BUFSIZE 64 -#endif - - -typedef struct -{ - uint8_t report_id; - uint8_t usage; - uint16_t usage_page; - - // TODO still use the endpoint size for now -// uint8_t in_len; // length of IN report -// uint8_t out_len; // length of OUT report -} tuh_hid_report_info_t; - -//--------------------------------------------------------------------+ -// Interface API -//--------------------------------------------------------------------+ - -// Get the number of HID instances -uint8_t tuh_hid_instance_count(uint8_t dev_addr); - -// Check if HID instance is mounted -bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); - -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); - -// Parse report descriptor into array of report_info struct and return number of reports. -// For complicated report, application should write its own parser. -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; - -//--------------------------------------------------------------------+ -// Control Endpoint API -//--------------------------------------------------------------------+ - -// Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// Note: Device will be initialized in Boot protocol for simplicity. -// Application can use set_protocol() to switch back to Report protocol. -uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); - -// Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) -bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); - -// Set Report using control endpoint -// report_type is either Intput, Output or Feature, (value from hid_report_type_t) -bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); - -//--------------------------------------------------------------------+ -// Interrupt Endpoint API -//--------------------------------------------------------------------+ - -// Check if the interface is ready to use -//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); - -// Try to receive next report on Interrupt Endpoint. Immediately return -// - true If succeeded, tuh_hid_report_received_cb() callback will be invoked when report is available -// - false if failed to queue the transfer e.g endpoint is busy -bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance); - -// Send report using interrupt endpoint -// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent. -//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); - -//--------------------------------------------------------------------+ -// Callbacks (Weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when device with hid interface is mounted -// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() -// can be used to parse common/simple enough descriptor. -// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped -// therefore report_desc = NULL, desc_len = 0 -void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); - -// Invoked when device with hid interface is un-mounted -TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); - -// Invoked when received report from device via interrupt endpoint -// Note: if there is report ID (composite), it is 1st byte of report -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); - -// Invoked when sent report to device successfully via interrupt endpoint -TU_ATTR_WEAK void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); - -// Invoked when Sent Report to device via either control endpoint -// len = 0 indicate there is error in the transfer e.g stalled response -TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); - -// Invoked when Set Protocol request is complete -TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void hidh_init (void); -bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void hidh_close (uint8_t dev_addr); - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_HID_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h deleted file mode 100644 index 74dc41749..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_CDC Communication Device Class (CDC) - * Currently only Abstract Control Model subclass is supported - * @{ */ - -#ifndef _TUSB_MIDI_H__ -#define _TUSB_MIDI_H__ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Specific Descriptor -//--------------------------------------------------------------------+ - -typedef enum -{ - MIDI_CS_INTERFACE_HEADER = 0x01, - MIDI_CS_INTERFACE_IN_JACK = 0x02, - MIDI_CS_INTERFACE_OUT_JACK = 0x03, - MIDI_CS_INTERFACE_ELEMENT = 0x04, -} midi_cs_interface_subtype_t; - -typedef enum -{ - MIDI_CS_ENDPOINT_GENERAL = 0x01 -} midi_cs_endpoint_subtype_t; - -typedef enum -{ - MIDI_JACK_EMBEDDED = 0x01, - MIDI_JACK_EXTERNAL = 0x02 -} midi_jack_type_t; - -typedef enum -{ - MIDI_CIN_MISC = 0, - MIDI_CIN_CABLE_EVENT = 1, - MIDI_CIN_SYSCOM_2BYTE = 2, // 2 byte system common message e.g MTC, SongSelect - MIDI_CIN_SYSCOM_3BYTE = 3, // 3 byte system common message e.g SPP - MIDI_CIN_SYSEX_START = 4, // SysEx starts or continue - MIDI_CIN_SYSEX_END_1BYTE = 5, // SysEx ends with 1 data, or 1 byte system common message - MIDI_CIN_SYSEX_END_2BYTE = 6, // SysEx ends with 2 data - MIDI_CIN_SYSEX_END_3BYTE = 7, // SysEx ends with 3 data - MIDI_CIN_NOTE_ON = 8, - MIDI_CIN_NOTE_OFF = 9, - MIDI_CIN_POLY_KEYPRESS = 10, - MIDI_CIN_CONTROL_CHANGE = 11, - MIDI_CIN_PROGRAM_CHANGE = 12, - MIDI_CIN_CHANNEL_PRESSURE = 13, - MIDI_CIN_PITCH_BEND_CHANGE = 14, - MIDI_CIN_1BYTE_DATA = 15 -} midi_code_index_number_t; - -// MIDI 1.0 status byte -enum -{ - //------------- System Exclusive -------------// - MIDI_STATUS_SYSEX_START = 0xF0, - MIDI_STATUS_SYSEX_END = 0xF7, - - //------------- System Common -------------// - MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME = 0xF1, - MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER = 0xF2, - MIDI_STATUS_SYSCOM_SONG_SELECT = 0xF3, - // F4, F5 is undefined - MIDI_STATUS_SYSCOM_TUNE_REQUEST = 0xF6, - - //------------- System RealTime -------------// - MIDI_STATUS_SYSREAL_TIMING_CLOCK = 0xF8, - // 0xF9 is undefined - MIDI_STATUS_SYSREAL_START = 0xFA, - MIDI_STATUS_SYSREAL_CONTINUE = 0xFB, - MIDI_STATUS_SYSREAL_STOP = 0xFC, - // 0xFD is undefined - MIDI_STATUS_SYSREAL_ACTIVE_SENSING = 0xFE, - MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF, -}; - -/// MIDI Interface Header Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint16_t bcdMSC ; ///< MidiStreaming SubClass release number in Binary-Coded Decimal - uint16_t wTotalLength ; -} midi_desc_header_t; - -/// MIDI In Jack Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bJackType ; ///< Embedded or External - uint8_t bJackID ; ///< Unique ID for MIDI IN Jack - uint8_t iJack ; ///< string descriptor -} midi_desc_in_jack_t; - - -/// MIDI Out Jack Descriptor with single pin -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bJackType ; ///< Embedded or External - uint8_t bJackID ; ///< Unique ID for MIDI IN Jack - uint8_t bNrInputPins; - - uint8_t baSourceID; - uint8_t baSourcePin; - - uint8_t iJack ; ///< string descriptor -} midi_desc_out_jack_t ; - -/// MIDI Out Jack Descriptor with multiple pins -#define midi_desc_out_jack_n_t(input_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bJackType ; \ - uint8_t bJackID ; \ - uint8_t bNrInputPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID; \ - uint8_t baSourcePin; \ - } pins[input_num]; \ - uint8_t iJack ; \ - } - -/// MIDI Element Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bElementID; - - uint8_t bNrInputPins; - uint8_t baSourceID; - uint8_t baSourcePin; - - uint8_t bNrOutputPins; - uint8_t bInTerminalLink; - uint8_t bOutTerminalLink; - uint8_t bElCapsSize; - - uint16_t bmElementCaps; - uint8_t iElement; -} midi_desc_element_t; - -/// MIDI Element Descriptor with multiple pins -#define midi_desc_element_n_t(input_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength; \ - uint8_t bDescriptorType; \ - uint8_t bDescriptorSubType; \ - uint8_t bElementID; \ - uint8_t bNrInputPins; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID; \ - uint8_t baSourcePin; \ - } pins[input_num]; \ - uint8_t bNrOutputPins; \ - uint8_t bInTerminalLink; \ - uint8_t bOutTerminalLink; \ - uint8_t bElCapsSize; \ - uint16_t bmElementCaps; \ - uint8_t iElement; \ - } - -/** @} */ - -#ifdef __cplusplus - } -#endif - -#endif - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c deleted file mode 100644 index b08b362f9..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MIDI) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "midi_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef struct -{ - uint8_t buffer[4]; - uint8_t index; - uint8_t total; -}midid_stream_t; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - // For Stream read()/write() API - // Messages are always 4 bytes long, queue them for reading and writing so the - // callers can use the Stream interface with single-byte read/write calls. - midid_stream_t stream_write; - midid_stream_t stream_read; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - uint8_t rx_ff_buf[CFG_TUD_MIDI_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_MIDI_TX_BUFSIZE]; - - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; - #endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE]; - -} midid_interface_t; - -#define ITF_MEM_RESET_SIZE offsetof(midid_interface_t, rx_ff) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION midid_interface_t _midid_itf[CFG_TUD_MIDI]; - -bool tud_midi_n_mounted (uint8_t itf) -{ - midid_interface_t* midi = &_midid_itf[itf]; - return midi->ep_in && midi->ep_out; -} - -static void _prep_out_transaction (midid_interface_t* p_midi) -{ - uint8_t const rhport = TUD_OPT_RHPORT; - uint16_t available = tu_fifo_remaining(&p_midi->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= sizeof(p_midi->epout_buf), ); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), ); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_midi->rx_ff); - - if ( available >= sizeof(p_midi->epout_buf) ) { - usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, sizeof(p_midi->epout_buf)); - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_midi->ep_out); - } -} - -//--------------------------------------------------------------------+ -// READ API -//--------------------------------------------------------------------+ -uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) -{ - (void) cable_num; - - midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t const* stream = &midi->stream_read; - - // when using with packet API stream total & index are both zero - return tu_fifo_count(&midi->rx_ff) + (stream->total - stream->index); -} - -uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) -{ - (void) cable_num; - TU_VERIFY(bufsize, 0); - - uint8_t* buf8 = (uint8_t*) buffer; - - midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t* stream = &midi->stream_read; - - uint32_t total_read = 0; - while( bufsize ) - { - // Get new packet from fifo, then set packet expected bytes - if ( stream->total == 0 ) - { - // return if there is no more data from fifo - if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read; - - uint8_t const code_index = stream->buffer[0] & 0x0f; - - // MIDI 1.0 Table 4-1: Code Index Number Classifications - switch(code_index) - { - case MIDI_CIN_MISC: - case MIDI_CIN_CABLE_EVENT: - // These are reserved and unused, possibly issue somewhere, skip this packet - return 0; - break; - - case MIDI_CIN_SYSEX_END_1BYTE: - case MIDI_CIN_1BYTE_DATA: - stream->total = 1; - break; - - case MIDI_CIN_SYSCOM_2BYTE : - case MIDI_CIN_SYSEX_END_2BYTE : - case MIDI_CIN_PROGRAM_CHANGE : - case MIDI_CIN_CHANNEL_PRESSURE : - stream->total = 2; - break; - - default: - stream->total = 3; - break; - } - } - - // Copy data up to bufsize - uint32_t const count = tu_min32(stream->total - stream->index, bufsize); - - // Skip the header (1st byte) in the buffer - memcpy(buf8, stream->buffer + 1 + stream->index, count); - - total_read += count; - stream->index += count; - buf8 += count; - bufsize -= count; - - // complete current event packet, reset stream - if ( stream->total == stream->index ) - { - stream->index = 0; - stream->total = 0; - } - } - - return total_read; -} - -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_out); - - uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4); - _prep_out_transaction(midi); - return (num_read == 4); -} - -//--------------------------------------------------------------------+ -// WRITE API -//--------------------------------------------------------------------+ - -static uint32_t write_flush(midid_interface_t* midi) -{ - // No data to send - if ( !tu_fifo_count(&midi->tx_ff) ) return 0; - - uint8_t const rhport = TUD_OPT_RHPORT; - - // skip if previous transfer not complete - TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); - - uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); - - if (count) - { - TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); - return count; - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, midi->ep_in); - return 0; - } -} - -uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in, 0); - - midid_stream_t* stream = &midi->stream_write; - - uint32_t i = 0; - while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) - { - uint8_t const data = buffer[i]; - i++; - - if ( stream->index == 0 ) - { - //------------- New event packet -------------// - - uint8_t const msg = data >> 4; - - stream->index = 2; - stream->buffer[1] = data; - - // Check to see if we're still in a SysEx transmit. - if ( stream->buffer[0] == MIDI_CIN_SYSEX_START ) - { - if ( data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; - } - else - { - stream->total = 4; - } - } - else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) - { - // Channel Voice Messages - stream->buffer[0] = (cable_num << 4) | msg; - stream->total = 4; - } - else if ( msg == 0xC || msg == 0xD) - { - // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) - stream->buffer[0] = (cable_num << 4) | msg; - stream->total = 3; - } - else if ( msg == 0xf ) - { - // System message - if ( data == MIDI_STATUS_SYSEX_START ) - { - stream->buffer[0] = MIDI_CIN_SYSEX_START; - stream->total = 4; - } - else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) - { - stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - stream->total = 3; - } - else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) - { - stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - stream->total = 4; - } - else - { - stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; - } - } - else - { - // Pack individual bytes if we don't support packing them into words. - stream->buffer[0] = cable_num << 4 | 0xf; - stream->buffer[2] = 0; - stream->buffer[3] = 0; - stream->index = 2; - stream->total = 2; - } - } - else - { - //------------- On-going (buffering) packet -------------// - - TU_ASSERT(stream->index < 4, i); - stream->buffer[stream->index] = data; - stream->index++; - - // See if this byte ends a SysEx. - if ( stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1); - stream->total = stream->index; - } - } - - // Send out packet - if ( stream->index == stream->total ) - { - // zeroes unused bytes - for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; - - uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); - - // complete current event packet, reset stream - stream->index = stream->total = 0; - - // FIFO overflown, since we already check fifo remaining. It is probably race condition - TU_ASSERT(count == 4, i); - } - } - - write_flush(midi); - - return i; -} - -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in); - - if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; - - tu_fifo_write_n(&midi->tx_ff, packet, 4); - write_flush(midi); - - return true; -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void midid_init(void) -{ - tu_memclr(_midid_itf, sizeof(_midid_itf)); - - for(uint8_t i=0; irx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); // true, true - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. - - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&midi->rx_ff, NULL, osal_mutex_create(&midi->rx_ff_mutex)); - tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex), NULL); - #endif - } -} - -void midid_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&midi->tx_ff); - } -} - -uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) -{ - // 1st Interface is Audio Control v1 - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); - - uint16_t drv_len = tu_desc_len(desc_itf); - uint8_t const * p_desc = tu_desc_next(desc_itf); - - // Skip Class Specific descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // 2nd Interface is MIDI Streaming - TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; - - TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && - AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); - - // Find available interface - midid_interface_t * p_midi = NULL; - for(uint8_t i=0; iitf_num = desc_midi->bInterfaceNumber; - (void) p_midi->itf_num; - - // next descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - // Find and open endpoint descriptors - uint8_t found_endpoints = 0; - while ( (found_endpoints < desc_midi->bNumEndpoints) && (drv_len <= max_len) ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) - { - p_midi->ep_in = ep_addr; - } else { - p_midi->ep_out = ep_addr; - } - - // Class Specific MIDI Stream endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - found_endpoints += 1; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // Prepare for incoming data - _prep_out_transaction(p_midi); - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - (void) rhport; - (void) stage; - (void) request; - - // driver doesn't support any request yet - return false; -} - -bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - (void) rhport; - - uint8_t itf; - midid_interface_t* p_midi; - - // Identify which interface to use - for (itf = 0; itf < CFG_TUD_MIDI; itf++) - { - p_midi = &_midid_itf[itf]; - if ( ( ep_addr == p_midi->ep_out ) || ( ep_addr == p_midi->ep_in ) ) break; - } - TU_ASSERT(itf < CFG_TUD_MIDI); - - // receive new data - if ( ep_addr == p_midi->ep_out ) - { - tu_fifo_write_n(&p_midi->rx_ff, p_midi->epout_buf, xferred_bytes); - - // invoke receive callback if available - if (tud_midi_rx_cb) tud_midi_rx_cb(itf); - - // prepare for next - // TODO for now ep_out is not used by public API therefore there is no race condition, - // and does not need to claim like ep_in - _prep_out_transaction(p_midi); - } - else if ( ep_addr == p_midi->ep_in ) - { - if (0 == write_flush(p_midi)) - { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - if ( !tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) - { - if ( usbd_edpt_claim(rhport, p_midi->ep_in) ) - { - usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); - } - } - } - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h deleted file mode 100644 index 211edc8d1..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/midi/midi_device.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MIDI_DEVICE_H_ -#define _TUSB_MIDI_DEVICE_H_ - -#include "class/audio/audio.h" -#include "midi.h" - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_MIDI_EP_BUFSIZE) && defined(CFG_TUD_MIDI_EPSIZE) - #warning CFG_TUD_MIDI_EPSIZE is renamed to CFG_TUD_MIDI_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE -#endif - -#ifndef CFG_TUD_MIDI_EP_BUFSIZE - #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -/** \addtogroup MIDI_Serial Serial - * @{ - * \defgroup MIDI_Serial_Device Device - * @{ */ - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -// CFG_TUD_MIDI > 1 -//--------------------------------------------------------------------+ - -// Check if midi interface is mounted -bool tud_midi_n_mounted (uint8_t itf); - -// Get the number of bytes available for reading -uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); - -// Read byte stream (legacy) -uint32_t tud_midi_n_stream_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); - -// Write byte Stream (legacy) -uint32_t tud_midi_n_stream_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -// Read event packet (4 bytes) -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); - -// Write event packet (4 bytes) -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); - -//--------------------------------------------------------------------+ -// Application API (Single Interface) -//--------------------------------------------------------------------+ -static inline bool tud_midi_mounted (void); -static inline uint32_t tud_midi_available (void); - -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -static inline bool tud_midi_packet_read (uint8_t packet[4]); -static inline bool tud_midi_packet_write (uint8_t const packet[4]); - -//------------- Deprecated API name -------------// -// TODO remove after 0.10.0 release - -TU_ATTR_DEPRECATED("tud_midi_read() is renamed to tud_midi_stream_read()") -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) -{ - return tud_midi_stream_read(buffer, bufsize); -} - -TU_ATTR_DEPRECATED("tud_midi_write() is renamed to tud_midi_stream_write()") -static inline uint32_t tud_midi_write(uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - return tud_midi_stream_write(cable_num, buffer, bufsize); -} - - -TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") -static inline bool tud_midi_send(uint8_t packet[4]) -{ - return tud_midi_packet_write(packet); -} - -TU_ATTR_DEPRECATED("tud_midi_receive() is renamed to tud_midi_packet_read()") -static inline bool tud_midi_receive(uint8_t packet[4]) -{ - return tud_midi_packet_read(packet); -} - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline bool tud_midi_mounted (void) -{ - return tud_midi_n_mounted(0); -} - -static inline uint32_t tud_midi_available (void) -{ - return tud_midi_n_available(0, 0); -} - -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize) -{ - return tud_midi_n_stream_read(0, 0, buffer, bufsize); -} - -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - return tud_midi_n_stream_write(0, cable_num, buffer, bufsize); -} - -static inline bool tud_midi_packet_read (uint8_t packet[4]) -{ - return tud_midi_n_packet_read(0, packet); -} - -static inline bool tud_midi_packet_write (uint8_t const packet[4]) -{ - return tud_midi_n_packet_write(0, packet); -} - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void midid_init (void); -void midid_reset (uint8_t rhport); -uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MIDI_DEVICE_H_ */ - -/** @} */ -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h deleted file mode 100644 index 84b6e4d79..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc.h +++ /dev/null @@ -1,382 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_H_ -#define _TUSB_MSC_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Mass Storage Class Constant -//--------------------------------------------------------------------+ -/// MassStorage Subclass -typedef enum -{ - MSC_SUBCLASS_RBC = 1 , ///< Reduced Block Commands (RBC) T10 Project 1240-D - MSC_SUBCLASS_SFF_MMC , ///< SFF-8020i, MMC-2 (ATAPI). Typically used by a CD/DVD device - MSC_SUBCLASS_QIC , ///< QIC-157. Typically used by a tape device - MSC_SUBCLASS_UFI , ///< UFI. Typically used by Floppy Disk Drive (FDD) device - MSC_SUBCLASS_SFF , ///< SFF-8070i. Can be used by Floppy Disk Drive (FDD) device - MSC_SUBCLASS_SCSI ///< SCSI transparent command set -}msc_subclass_type_t; - -enum { - MSC_CBW_SIGNATURE = 0x43425355, ///< Constant value of 43425355h (little endian) - MSC_CSW_SIGNATURE = 0x53425355 ///< Constant value of 53425355h (little endian) -}; - -/// \brief MassStorage Protocol. -/// \details CBI only approved to use with full-speed floopy disk & should not used with highspeed or device other than floopy -typedef enum -{ - MSC_PROTOCOL_CBI = 0 , ///< Control/Bulk/Interrupt protocol (with command completion interrupt) - MSC_PROTOCOL_CBI_NO_INTERRUPT = 1 , ///< Control/Bulk/Interrupt protocol (without command completion interrupt) - MSC_PROTOCOL_BOT = 0x50 ///< Bulk-Only Transport -}msc_protocol_type_t; - -/// MassStorage Class-Specific Control Request -typedef enum -{ - MSC_REQ_GET_MAX_LUN = 254, ///< The Get Max LUN device request is used to determine the number of logical units supported by the device. Logical Unit Numbers on the device shall be numbered contiguously starting from LUN 0 to a maximum LUN of 15 - MSC_REQ_RESET = 255 ///< This request is used to reset the mass storage device and its associated interface. This class-specific request shall ready the device for the next CBW from the host. -}msc_request_type_t; - -/// \brief Command Block Status Values -/// \details Indicates the success or failure of the command. The device shall set this byte to zero if the command completed -/// successfully. A non-zero value shall indicate a failure during command execution according to the following -typedef enum -{ - MSC_CSW_STATUS_PASSED = 0 , ///< MSC_CSW_STATUS_PASSED - MSC_CSW_STATUS_FAILED , ///< MSC_CSW_STATUS_FAILED - MSC_CSW_STATUS_PHASE_ERROR ///< MSC_CSW_STATUS_PHASE_ERROR -}msc_csw_status_t; - -/// Command Block Wrapper -typedef struct TU_ATTR_PACKED -{ - uint32_t signature; ///< Signature that helps identify this data packet as a CBW. The signature field shall contain the value 43425355h (little endian), indicating a CBW. - uint32_t tag; ///< Tag sent by the host. The device shall echo the contents of this field back to the host in the dCSWTagfield of the associated CSW. The dCSWTagpositively associates a CSW with the corresponding CBW. - uint32_t total_bytes; ///< The number of bytes of data that the host expects to transfer on the Bulk-In or Bulk-Out endpoint (as indicated by the Direction bit) during the execution of this command. If this field is zero, the device and the host shall transfer no data between the CBW and the associated CSW, and the device shall ignore the value of the Direction bit in bmCBWFlags. - uint8_t dir; ///< Bit 7 of this field define transfer direction \n - 0 : Data-Out from host to the device. \n - 1 : Data-In from the device to the host. - uint8_t lun; ///< The device Logical Unit Number (LUN) to which the command block is being sent. For devices that support multiple LUNs, the host shall place into this field the LUN to which this command block is addressed. Otherwise, the host shall set this field to zero. - uint8_t cmd_len; ///< The valid length of the CBWCBin bytes. This defines the valid length of the command block. The only legal values are 1 through 16 - uint8_t command[16]; ///< The command block to be executed by the device. The device shall interpret the first cmd_len bytes in this field as a command block -}msc_cbw_t; - -TU_VERIFY_STATIC(sizeof(msc_cbw_t) == 31, "size is not correct"); - -/// Command Status Wrapper -typedef struct TU_ATTR_PACKED -{ - uint32_t signature ; ///< Signature that helps identify this data packet as a CSW. The signature field shall contain the value 53425355h (little endian), indicating CSW. - uint32_t tag ; ///< The device shall set this field to the value received in the dCBWTag of the associated CBW. - uint32_t data_residue ; ///< For Data-Out the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLength, and the actual amount of data processed by the device. For Data-In the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLengthand the actual amount of relevant data sent by the device - uint8_t status ; ///< indicates the success or failure of the command. Values from \ref msc_csw_status_t -}msc_csw_t; - -TU_VERIFY_STATIC(sizeof(msc_csw_t) == 13, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI Constant -//--------------------------------------------------------------------+ - -/// SCSI Command Operation Code -typedef enum -{ - SCSI_CMD_TEST_UNIT_READY = 0x00, ///< The SCSI Test Unit Ready command is used to determine if a device is ready to transfer data (read/write), i.e. if a disk has spun up, if a tape is loaded and ready etc. The device does not perform a self-test operation. - SCSI_CMD_INQUIRY = 0x12, ///< The SCSI Inquiry command is used to obtain basic information from a target device. - SCSI_CMD_MODE_SELECT_6 = 0x15, ///< provides a means for the application client to specify medium, logical unit, or peripheral device parameters to the device server. Device servers that implement the MODE SELECT(6) command shall also implement the MODE SENSE(6) command. Application clients should issue MODE SENSE(6) prior to each MODE SELECT(6) to determine supported mode pages, page lengths, and other parameters. - SCSI_CMD_MODE_SENSE_6 = 0x1A, ///< provides a means for a device server to report parameters to an application client. It is a complementary command to the MODE SELECT(6) command. Device servers that implement the MODE SENSE(6) command shall also implement the MODE SELECT(6) command. - SCSI_CMD_START_STOP_UNIT = 0x1B, - SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E, - SCSI_CMD_READ_CAPACITY_10 = 0x25, ///< The SCSI Read Capacity command is used to obtain data capacity information from a target device. - SCSI_CMD_REQUEST_SENSE = 0x03, ///< The SCSI Request Sense command is part of the SCSI computer protocol standard. This command is used to obtain sense data -- status/error information -- from a target device. - SCSI_CMD_READ_FORMAT_CAPACITY = 0x23, ///< The command allows the Host to request a list of the possible format capacities for an installed writable media. This command also has the capability to report the writable capacity for a media when it is installed - SCSI_CMD_READ_10 = 0x28, ///< The READ (10) command requests that the device server read the specified logical block(s) and transfer them to the data-in buffer. - SCSI_CMD_WRITE_10 = 0x2A, ///< The WRITE (10) command requests thatthe device server transfer the specified logical block(s) from the data-out buffer and write them. -}scsi_cmd_type_t; - -/// SCSI Sense Key -typedef enum -{ - SCSI_SENSE_NONE = 0x00, ///< no specific Sense Key. This would be the case for a successful command - SCSI_SENSE_RECOVERED_ERROR = 0x01, ///< ndicates the last command completed successfully with some recovery action performed by the disc drive. - SCSI_SENSE_NOT_READY = 0x02, ///< Indicates the logical unit addressed cannot be accessed. - SCSI_SENSE_MEDIUM_ERROR = 0x03, ///< Indicates the command terminated with a non-recovered error condition. - SCSI_SENSE_HARDWARE_ERROR = 0x04, ///< Indicates the disc drive detected a nonrecoverable hardware failure while performing the command or during a self test. - SCSI_SENSE_ILLEGAL_REQUEST = 0x05, ///< Indicates an illegal parameter in the command descriptor block or in the additional parameters - SCSI_SENSE_UNIT_ATTENTION = 0x06, ///< Indicates the disc drive may have been reset. - SCSI_SENSE_DATA_PROTECT = 0x07, ///< Indicates that a command that reads or writes the medium was attempted on a block that is protected from this operation. The read or write operation is not performed. - SCSI_SENSE_FIRMWARE_ERROR = 0x08, ///< Vendor specific sense key. - SCSI_SENSE_ABORTED_COMMAND = 0x0b, ///< Indicates the disc drive aborted the command. - SCSI_SENSE_EQUAL = 0x0c, ///< Indicates a SEARCH DATA command has satisfied an equal comparison. - SCSI_SENSE_VOLUME_OVERFLOW = 0x0d, ///< Indicates a buffered peripheral device has reached the end of medium partition and data remains in the buffer that has not been written to the medium. - SCSI_SENSE_MISCOMPARE = 0x0e ///< ndicates that the source data did not match the data read from the medium. -}scsi_sense_key_type_t; - -//--------------------------------------------------------------------+ -// SCSI Primary Command (SPC-4) -//--------------------------------------------------------------------+ - -/// SCSI Test Unit Ready Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_TEST_UNIT_READY - uint8_t lun ; ///< Logical Unit - uint8_t reserved[3] ; - uint8_t control ; -} scsi_test_unit_ready_t; - -TU_VERIFY_STATIC(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct"); - -/// SCSI Inquiry Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_INQUIRY - uint8_t reserved1 ; - uint8_t page_code ; - uint8_t reserved2 ; - uint8_t alloc_length ; ///< specifies the maximum number of bytes that USB host has allocated in the Data-In Buffer. An allocation length of zero specifies that no data shall be transferred. - uint8_t control ; -} scsi_inquiry_t, scsi_request_sense_t; - -TU_VERIFY_STATIC(sizeof(scsi_inquiry_t) == 6, "size is not correct"); - -/// SCSI Inquiry Response Data -typedef struct TU_ATTR_PACKED -{ - uint8_t peripheral_device_type : 5; - uint8_t peripheral_qualifier : 3; - - uint8_t : 7; - uint8_t is_removable : 1; - - uint8_t version; - - uint8_t response_data_format : 4; - uint8_t hierarchical_support : 1; - uint8_t normal_aca : 1; - uint8_t : 2; - - uint8_t additional_length; - - uint8_t protect : 1; - uint8_t : 2; - uint8_t third_party_copy : 1; - uint8_t target_port_group_support : 2; - uint8_t access_control_coordinator : 1; - uint8_t scc_support : 1; - - uint8_t addr16 : 1; - uint8_t : 3; - uint8_t multi_port : 1; - uint8_t : 1; // vendor specific - uint8_t enclosure_service : 1; - uint8_t : 1; - - uint8_t : 1; // vendor specific - uint8_t cmd_que : 1; - uint8_t : 2; - uint8_t sync : 1; - uint8_t wbus16 : 1; - uint8_t : 2; - - uint8_t vendor_id[8] ; ///< 8 bytes of ASCII data identifying the vendor of the product. - uint8_t product_id[16]; ///< 16 bytes of ASCII data defined by the vendor. - uint8_t product_rev[4]; ///< 4 bytes of ASCII data defined by the vendor. -} scsi_inquiry_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_inquiry_resp_t) == 36, "size is not correct"); - - -typedef struct TU_ATTR_PACKED -{ - uint8_t response_code : 7; ///< 70h - current errors, Fixed Format 71h - deferred errors, Fixed Format - uint8_t valid : 1; - - uint8_t reserved; - - uint8_t sense_key : 4; - uint8_t : 1; - uint8_t ili : 1; ///< Incorrect length indicator - uint8_t end_of_medium : 1; - uint8_t filemark : 1; - - uint32_t information; - uint8_t add_sense_len; - uint32_t command_specific_info; - uint8_t add_sense_code; - uint8_t add_sense_qualifier; - uint8_t field_replaceable_unit_code; - - uint8_t sense_key_specific[3]; ///< sense key specific valid bit is bit 7 of key[0], aka MSB in Big Endian layout - -} scsi_sense_fixed_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_sense_fixed_resp_t) == 18, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_MODE_SENSE_6 - - uint8_t : 3; - uint8_t disable_block_descriptor : 1; - uint8_t : 4; - - uint8_t page_code : 6; - uint8_t page_control : 2; - - uint8_t subpage_code; - uint8_t alloc_length; - uint8_t control; -} scsi_mode_sense6_t; - -TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct"); - -// This is only a Mode parameter header(6). -typedef struct TU_ATTR_PACKED -{ - uint8_t data_len; - uint8_t medium_type; - - uint8_t reserved : 7; - bool write_protected : 1; - - uint8_t block_descriptor_len; -} scsi_mode_sense6_resp_t; - -TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_resp_t) == 4, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; ///< SCSI OpCode for \ref SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL - uint8_t reserved[3]; - uint8_t prohibit_removal; - uint8_t control; -} scsi_prevent_allow_medium_removal_t; - -TU_VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; - - uint8_t immded : 1; - uint8_t : 7; - - uint8_t TU_RESERVED; - - uint8_t power_condition_mod : 4; - uint8_t : 4; - - uint8_t start : 1; - uint8_t load_eject : 1; - uint8_t no_flush : 1; - uint8_t : 1; - uint8_t power_condition : 4; - - uint8_t control; -} scsi_start_stop_unit_t; - -TU_VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI MMC -//--------------------------------------------------------------------+ -/// SCSI Read Format Capacity: Write Capacity -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code; - uint8_t reserved[6]; - uint16_t alloc_length; - uint8_t control; -} scsi_read_format_capacity_t; - -TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_t) == 10, "size is not correct"); - -typedef struct TU_ATTR_PACKED{ - uint8_t reserved[3]; - uint8_t list_length; /// must be 8*n, length in bytes of formattable capacity descriptor followed it. - - uint32_t block_num; /// Number of Logical Blocks - uint8_t descriptor_type; // 00: reserved, 01 unformatted media , 10 Formatted media, 11 No media present - - uint8_t reserved2; - uint16_t block_size_u16; - -} scsi_read_format_capacity_data_t; - -TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_data_t) == 12, "size is not correct"); - -//--------------------------------------------------------------------+ -// SCSI Block Command (SBC-3) -// NOTE: All data in SCSI command are in Big Endian -//--------------------------------------------------------------------+ - -/// SCSI Read Capacity 10 Command: Read Capacity -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode for \ref SCSI_CMD_READ_CAPACITY_10 - uint8_t reserved1 ; - uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command - uint16_t reserved2 ; - uint8_t partial_medium_indicator ; - uint8_t control ; -} scsi_read_capacity10_t; - -TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_t) == 10, "size is not correct"); - -/// SCSI Read Capacity 10 Response Data -typedef struct { - uint32_t last_lba ; ///< The last Logical Block Address of the device - uint32_t block_size ; ///< Block size in bytes -} scsi_read_capacity10_resp_t; - -TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_resp_t) == 8, "size is not correct"); - -/// SCSI Read 10 Command -typedef struct TU_ATTR_PACKED -{ - uint8_t cmd_code ; ///< SCSI OpCode - uint8_t reserved ; // has LUN according to wiki - uint32_t lba ; ///< The first Logical Block Address (LBA) accessed by this command - uint8_t reserved2 ; - uint16_t block_count ; ///< Number of Blocks used by this command - uint8_t control ; -} scsi_read10_t, scsi_write10_t; - -TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); -TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c deleted file mode 100644 index 97837b114..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.c +++ /dev/null @@ -1,939 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MSC) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" -#include "device/dcd.h" // for faking dcd_event_xfer_complete - -#include "msc_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// Can be selectively disabled to reduce logging when troubleshooting other driver -#define MSC_DEBUG 2 - -enum -{ - MSC_STAGE_CMD = 0, - MSC_STAGE_DATA, - MSC_STAGE_STATUS, - MSC_STAGE_STATUS_SENT, - MSC_STAGE_NEED_RESET, -}; - -typedef struct -{ - // TODO optimize alignment - CFG_TUSB_MEM_ALIGN msc_cbw_t cbw; - CFG_TUSB_MEM_ALIGN msc_csw_t csw; - - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - // Bulk Only Transfer (BOT) Protocol - uint8_t stage; - uint32_t total_len; // byte to be transferred, can be smaller than total_bytes in cbw - uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage - - // Sense Response Data - uint8_t sense_key; - uint8_t add_sense_code; - uint8_t add_sense_qualifier; -}mscd_interface_t; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static mscd_interface_t _mscd_itf; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE]; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); -static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc); - -static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); -static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes); - -TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) -{ - return tu_bit_test(dir, 7); -} - -static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc) -{ - // Data residue is always = host expect - actual transferred - p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; - - p_msc->stage = MSC_STAGE_STATUS_SENT; - return usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)); -} - -static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc) -{ - p_msc->stage = MSC_STAGE_CMD; - return usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)); -} - -static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - msc_csw_t * p_csw = &p_msc->csw; - - p_csw->status = status; - p_csw->data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; - p_msc->stage = MSC_STAGE_STATUS; - - // failed but sense key is not set: default to Illegal Request - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); - - // If there is data stage and not yet complete, stall it - if ( p_cbw->total_bytes && p_csw->data_residue ) - { - if ( is_data_in(p_cbw->dir) ) - { - usbd_edpt_stall(rhport, p_msc->ep_in); - } - else - { - usbd_edpt_stall(rhport, p_msc->ep_out); - } - } -} - -static inline uint32_t rdwr10_get_lba(uint8_t const command[]) -{ - // use offsetof to avoid pointer to the odd/unaligned address - uint32_t const lba = tu_unaligned_read32(command + offsetof(scsi_write10_t, lba)); - - // lba is in Big Endian - return tu_ntohl(lba); -} - -static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw) -{ - uint16_t const block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count)); - return tu_ntohs(block_count); -} - -static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) -{ - // first extract block count in the command - uint16_t const block_count = rdwr10_get_blockcount(cbw); - - // invalid block count - if (block_count == 0) return 0; - - return (uint16_t) (cbw->total_bytes / block_count); -} - -uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) -{ - uint8_t status = MSC_CSW_STATUS_PASSED; - uint16_t const block_count = rdwr10_get_blockcount(cbw); - - if ( cbw->total_bytes == 0 ) - { - if ( block_count ) - { - TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - }else - { - // no data transfer, only exist in complaint test suite - } - }else - { - if ( SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir) ) - { - TU_LOG(MSC_DEBUG, " SCSI case 10 (Ho <> Di)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - else if ( SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir) ) - { - TU_LOG(MSC_DEBUG, " SCSI case 8 (Hi <> Do)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - else if ( 0 == block_count ) - { - TU_LOG(MSC_DEBUG, " SCSI case 4 Hi > Dn (READ10) or case 9 Ho > Dn (WRITE10) \r\n"); - status = MSC_CSW_STATUS_FAILED; - } - else if ( cbw->total_bytes / block_count == 0 ) - { - TU_LOG(MSC_DEBUG, " Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n"); - status = MSC_CSW_STATUS_PHASE_ERROR; - } - } - - return status; -} - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -TU_ATTR_UNUSED static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = -{ - { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, - { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, - { .key = SCSI_CMD_MODE_SELECT_6 , .data = "Mode_Select 6" }, - { .key = SCSI_CMD_MODE_SENSE_6 , .data = "Mode_Sense 6" }, - { .key = SCSI_CMD_START_STOP_UNIT , .data = "Start Stop Unit" }, - { .key = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL , .data = "Prevent Allow Medium Removal" }, - { .key = SCSI_CMD_READ_CAPACITY_10 , .data = "Read Capacity10" }, - { .key = SCSI_CMD_REQUEST_SENSE , .data = "Request Sense" }, - { .key = SCSI_CMD_READ_FORMAT_CAPACITY , .data = "Read Format Capacity" }, - { .key = SCSI_CMD_READ_10 , .data = "Read10" }, - { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } -}; - -TU_ATTR_UNUSED static tu_lookup_table_t const _msc_scsi_cmd_table = -{ - .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), - .items = _msc_scsi_cmd_lookup -}; - -#endif - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier) -{ - (void) lun; - - _mscd_itf.sense_key = sense_key; - _mscd_itf.add_sense_code = add_sense_code; - _mscd_itf.add_sense_qualifier = add_sense_qualifier; - - return true; -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void mscd_init(void) -{ - tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); -} - -void mscd_reset(uint8_t rhport) -{ - (void) rhport; - tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); -} - -uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // only support SCSI's BOT protocol - TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && - MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); - - // msc driver length is fixed - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - - // Max length must be at least 1 interface + 2 endpoints - TU_ASSERT(max_len >= drv_len, 0); - - mscd_interface_t * p_msc = &_mscd_itf; - p_msc->itf_num = itf_desc->bInterfaceNumber; - - // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); - - // Prepare for Command Block Wrapper - TU_ASSERT( prepare_cbw(rhport, p_msc), drv_len); - - return drv_len; -} - -static void proc_bot_reset(mscd_interface_t* p_msc) -{ - p_msc->stage = MSC_STAGE_CMD; - p_msc->total_len = 0; - p_msc->xferred_len = 0; - - p_msc->sense_key = 0; - p_msc->add_sense_code = 0; - p_msc->add_sense_qualifier = 0; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA & ACK stage - if (stage != CONTROL_STAGE_SETUP) return true; - - mscd_interface_t* p_msc = &_mscd_itf; - - // Clear Endpoint Feature (stall) for recovery - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_RCPT_ENDPOINT == request->bmRequestType_bit.recipient && - TUSB_REQ_CLEAR_FEATURE == request->bRequest && - TUSB_REQ_FEATURE_EDPT_HALT == request->wValue ) - { - uint8_t const ep_addr = tu_u16_low(request->wIndex); - - if ( p_msc->stage == MSC_STAGE_NEED_RESET ) - { - // reset recovery is required to recover from this stage - // Clear Stall request cannot resolve this -> continue to stall endpoint - usbd_edpt_stall(rhport, ep_addr); - } - else - { - if ( ep_addr == p_msc->ep_in ) - { - if ( p_msc->stage == MSC_STAGE_STATUS ) - { - // resume sending SCSI status if we are in this stage previously before stalled - TU_ASSERT( send_csw(rhport, p_msc) ); - } - } - else if ( ep_addr == p_msc->ep_out ) - { - if ( p_msc->stage == MSC_STAGE_CMD ) - { - // part of reset recovery (probably due to invalid CBW) -> prepare for new command - // Note: skip if already queued previously - if ( usbd_edpt_ready(rhport, p_msc->ep_out) ) - { - TU_ASSERT( prepare_cbw(rhport, p_msc) ); - } - } - } - } - - return true; - } - - // From this point only handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch ( request->bRequest ) - { - case MSC_REQ_RESET: - TU_LOG(MSC_DEBUG, " MSC BOT Reset\r\n"); - TU_VERIFY(request->wValue == 0 && request->wLength == 0); - - // driver state reset - proc_bot_reset(p_msc); - - tud_control_status(rhport, request); - break; - - case MSC_REQ_GET_MAX_LUN: - { - TU_LOG(MSC_DEBUG, " MSC Get Max Lun\r\n"); - TU_VERIFY(request->wValue == 0 && request->wLength == 1); - - uint8_t maxlun = 1; - if (tud_msc_get_maxlun_cb) maxlun = tud_msc_get_maxlun_cb(); - TU_VERIFY(maxlun); - - // MAX LUN is minus 1 by specs - maxlun--; - - tud_control_xfer(rhport, request, &maxlun, 1); - } - break; - - default: return false; // stall unsupported request - } - - return true; -} - -bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - (void) event; - - mscd_interface_t* p_msc = &_mscd_itf; - msc_cbw_t const * p_cbw = &p_msc->cbw; - msc_csw_t * p_csw = &p_msc->csw; - - switch (p_msc->stage) - { - case MSC_STAGE_CMD: - //------------- new CBW received -------------// - // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it - if(ep_addr != p_msc->ep_out) return true; - - if ( !(xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE) ) - { - TU_LOG(MSC_DEBUG, " SCSI CBW is not valid\r\n"); - - // BOT 6.6.1 If CBW is not valid stall both endpoints until reset recovery - p_msc->stage = MSC_STAGE_NEED_RESET; - - // invalid CBW stall both endpoints - usbd_edpt_stall(rhport, p_msc->ep_in); - usbd_edpt_stall(rhport, p_msc->ep_out); - - return false; - } - - TU_LOG(MSC_DEBUG, " SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); - //TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); - - p_csw->signature = MSC_CSW_SIGNATURE; - p_csw->tag = p_cbw->tag; - p_csw->data_residue = 0; - p_csw->status = MSC_CSW_STATUS_PASSED; - - /*------------- Parse command and prepare DATA -------------*/ - p_msc->stage = MSC_STAGE_DATA; - p_msc->total_len = p_cbw->total_bytes; - p_msc->xferred_len = 0; - - // Read10 or Write10 - if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) ) - { - uint8_t const status = rdwr10_validate_cmd(p_cbw); - - if ( status != MSC_CSW_STATUS_PASSED) - { - fail_scsi_op(rhport, p_msc, status); - }else if ( p_cbw->total_bytes ) - { - if (SCSI_CMD_READ_10 == p_cbw->command[0]) - { - proc_read10_cmd(rhport, p_msc); - }else - { - proc_write10_cmd(rhport, p_msc); - } - }else - { - // no data transfer, only exist in complaint test suite - p_msc->stage = MSC_STAGE_STATUS; - } - } - else - { - // For other SCSI commands - // 1. OUT : queue transfer (invoke app callback after done) - // 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length - if ( (p_cbw->total_bytes > 0 ) && !is_data_in(p_cbw->dir) ) - { - if (p_cbw->total_bytes > sizeof(_mscd_buf)) - { - TU_LOG(MSC_DEBUG, " SCSI reject non READ10/WRITE10 with large data\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // Didn't check for case 9 (Ho > Dn), which requires examining scsi command first - // but it is OK to just receive data then responded with failed status - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) ); - } - }else - { - // First process if it is a built-in commands - int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf)); - - // Invoke user callback if not built-in - if ( (resplen < 0) && (p_msc->sense_key == 0) ) - { - resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len); - } - - if ( resplen < 0 ) - { - // unsupported command - TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - } - else if (resplen == 0) - { - if (p_cbw->total_bytes) - { - // 6.7 The 13 Cases: case 4 (Hi > Dn) - // TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // case 1 Hn = Dn: all good - p_msc->stage = MSC_STAGE_STATUS; - } - } - else - { - if ( p_cbw->total_bytes == 0 ) - { - // 6.7 The 13 Cases: case 2 (Hn < Di) - // TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // cannot return more than host expect - p_msc->total_len = tu_min32((uint32_t) resplen, p_cbw->total_bytes); - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) ); - } - } - } - } - break; - - case MSC_STAGE_DATA: - TU_LOG(MSC_DEBUG, " SCSI Data\r\n"); - //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2); - - if (SCSI_CMD_READ_10 == p_cbw->command[0]) - { - p_msc->xferred_len += xferred_bytes; - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - }else - { - proc_read10_cmd(rhport, p_msc); - } - } - else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) - { - proc_write10_new_data(rhport, p_msc, xferred_bytes); - } - else - { - p_msc->xferred_len += xferred_bytes; - - // OUT transfer, invoke callback if needed - if ( !is_data_in(p_cbw->dir) ) - { - int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len); - - if ( cb_result < 0 ) - { - // unsupported command - TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // TODO haven't implement this scenario any further yet - } - } - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - } - else - { - // This scenario with command that take more than one transfer is already rejected at Command stage - TU_BREAKPOINT(); - } - } - break; - - case MSC_STAGE_STATUS: - // processed immediately after this switch, supposedly to be empty - break; - - case MSC_STAGE_STATUS_SENT: - // Wait for the Status phase to complete - if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) - { - TU_LOG(MSC_DEBUG, " SCSI Status = %u\r\n", p_csw->status); - // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2); - - // Invoke complete callback if defined - // Note: There is racing issue with samd51 + qspi flash testing with arduino - // if complete_cb() is invoked after queuing the status. - switch(p_cbw->command[0]) - { - case SCSI_CMD_READ_10: - if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun); - break; - - case SCSI_CMD_WRITE_10: - if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun); - break; - - default: - if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); - break; - } - - TU_ASSERT( prepare_cbw(rhport, p_msc) ); - }else - { - // Any xfer ended here is consider unknown error, ignore it - TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n"); - } - break; - - default : break; - } - - if ( p_msc->stage == MSC_STAGE_STATUS ) - { - // skip status if epin is currently stalled, will do it when received Clear Stall request - if ( !usbd_edpt_stalled(rhport, p_msc->ep_in) ) - { - if ( (p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir) ) - { - // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status - // TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); - usbd_edpt_stall(rhport, p_msc->ep_in); - }else - { - TU_ASSERT( send_csw(rhport, p_msc) ); - } - } - - #if TU_CHECK_MCU(OPT_MCU_CXD56) - // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD. - // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and - // hope everything will work - if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) - { - usbd_edpt_clear_stall(rhport, p_msc->ep_in); - send_csw(rhport, p_msc); - } - #endif - } - - return true; -} - -/*------------------------------------------------------------------*/ -/* SCSI Command Process - *------------------------------------------------------------------*/ - -// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) -// In case of a failed status, sense key must be set for reason of failure -static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) -{ - (void) bufsize; // TODO refractor later - int32_t resplen; - - mscd_interface_t* p_msc = &_mscd_itf; - - switch ( scsi_cmd[0] ) - { - case SCSI_CMD_TEST_UNIT_READY: - resplen = 0; - if ( !tud_msc_test_unit_ready_cb(lun) ) - { - // Failed status response - resplen = - 1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - } - break; - - case SCSI_CMD_START_STOP_UNIT: - resplen = 0; - - if (tud_msc_start_stop_cb) - { - scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; - if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) - { - // Failed status response - resplen = - 1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - } - } - break; - - case SCSI_CMD_READ_CAPACITY_10: - { - uint32_t block_count; - uint32_t block_size; - uint16_t block_size_u16; - - tud_msc_capacity_cb(lun, &block_count, &block_size_u16); - block_size = (uint32_t) block_size_u16; - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - }else - { - scsi_read_capacity10_resp_t read_capa10; - - read_capa10.last_lba = tu_htonl(block_count-1); - read_capa10.block_size = tu_htonl(block_size); - - resplen = sizeof(read_capa10); - memcpy(buffer, &read_capa10, resplen); - } - } - break; - - case SCSI_CMD_READ_FORMAT_CAPACITY: - { - scsi_read_format_capacity_data_t read_fmt_capa = - { - .list_length = 8, - .block_num = 0, - .descriptor_type = 2, // formatted media - .block_size_u16 = 0 - }; - - uint32_t block_count; - uint16_t block_size; - - tud_msc_capacity_cb(lun, &block_count, &block_size); - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - }else - { - read_fmt_capa.block_num = tu_htonl(block_count); - read_fmt_capa.block_size_u16 = tu_htons(block_size); - - resplen = sizeof(read_fmt_capa); - memcpy(buffer, &read_fmt_capa, resplen); - } - } - break; - - case SCSI_CMD_INQUIRY: - { - scsi_inquiry_resp_t inquiry_rsp = - { - .is_removable = 1, - .version = 2, - .response_data_format = 2, - }; - - // vendor_id, product_id, product_rev is space padded string - memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); - memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); - memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); - - tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); - - resplen = sizeof(inquiry_rsp); - memcpy(buffer, &inquiry_rsp, resplen); - } - break; - - case SCSI_CMD_MODE_SENSE_6: - { - scsi_mode_sense6_resp_t mode_resp = - { - .data_len = 3, - .medium_type = 0, - .write_protected = false, - .reserved = 0, - .block_descriptor_len = 0 // no block descriptor are included - }; - - bool writable = true; - if ( tud_msc_is_writable_cb ) - { - writable = tud_msc_is_writable_cb(lun); - } - - mode_resp.write_protected = !writable; - - resplen = sizeof(mode_resp); - memcpy(buffer, &mode_resp, resplen); - } - break; - - case SCSI_CMD_REQUEST_SENSE: - { - scsi_sense_fixed_resp_t sense_rsp = - { - .response_code = 0x70, - .valid = 1 - }; - - sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; - - sense_rsp.sense_key = p_msc->sense_key; - sense_rsp.add_sense_code = p_msc->add_sense_code; - sense_rsp.add_sense_qualifier = p_msc->add_sense_qualifier; - - resplen = sizeof(sense_rsp); - memcpy(buffer, &sense_rsp, resplen); - - // Clear sense data after copy - tud_msc_set_sense(lun, 0, 0, 0); - } - break; - - default: resplen = -1; break; - } - - return resplen; -} - -static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - - // block size already verified not zero - uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); - - // Adjust lba with transferred bytes - uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); - - // remaining bytes capped at class buffer - int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); - - // Application can consume smaller bytes - uint32_t const offset = p_msc->xferred_len % block_sz; - nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_buf, (uint32_t) nbytes); - - if ( nbytes < 0 ) - { - // negative means error -> endpoint is stalled & status in CSW set to failed - TU_LOG(MSC_DEBUG, " tud_msc_read10_cb() return -1\r\n"); - - // Sense = Flash not ready for access - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00); - - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - } - else if ( nbytes == 0 ) - { - // zero means not ready -> simulate an transfer complete so that this driver callback will fired again - dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); - } - else - { - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, nbytes), ); - } -} - -static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - bool writable = true; - - if ( tud_msc_is_writable_cb ) - { - writable = tud_msc_is_writable_cb(p_cbw->lun); - } - - if ( !writable ) - { - // Not writable, complete this SCSI op with error - // Sense = Write protected - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - return; - } - - // remaining bytes capped at class buffer - int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len); - - // Write10 callback will be called later when usb transfer complete - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), ); -} - -// process new data arrived from WRITE10 -static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes) -{ - msc_cbw_t const * p_cbw = &p_msc->cbw; - - // block size already verified not zero - uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); - - // Adjust lba with transferred bytes - uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); - - // Invoke callback to consume new data - uint32_t const offset = p_msc->xferred_len % block_sz; - int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_buf, xferred_bytes); - - if ( nbytes < 0 ) - { - // negative means error -> failed this scsi op - TU_LOG(MSC_DEBUG, " tud_msc_write10_cb() return -1\r\n"); - - // update actual byte before failed - p_msc->xferred_len += xferred_bytes; - - // Sense = Flash not ready for access - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00); - - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); - }else - { - // Application consume less than what we got (including zero) - if ( (uint32_t) nbytes < xferred_bytes ) - { - if ( nbytes > 0 ) - { - p_msc->xferred_len += nbytes; - memmove(_mscd_buf, _mscd_buf+nbytes, xferred_bytes-nbytes); - } - - // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter - dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, XFER_RESULT_SUCCESS, false); - } - else - { - // Application consume all bytes in our buffer - p_msc->xferred_len += xferred_bytes; - - if ( p_msc->xferred_len >= p_msc->total_len ) - { - // Data Stage is complete - p_msc->stage = MSC_STAGE_STATUS; - }else - { - // prepare to receive more data from host - proc_write10_cmd(rhport, p_msc); - } - } - } -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h deleted file mode 100644 index d32694340..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_device.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_DEVICE_H_ -#define _TUSB_MSC_DEVICE_H_ - -#include "common/tusb_common.h" -#include "msc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#if !defined(CFG_TUD_MSC_EP_BUFSIZE) & defined(CFG_TUD_MSC_BUFSIZE) - // TODO warn user to use new name later on - // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_MSC_EP_BUFSIZE CFG_TUD_MSC_BUFSIZE -#endif - -#ifndef CFG_TUD_MSC_EP_BUFSIZE - #error CFG_TUD_MSC_EP_BUFSIZE must be defined, value of a block size should work well, the more the better -#endif - -TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Set SCSI sense response -bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); - -//--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) -//--------------------------------------------------------------------+ - -// Invoked when received SCSI READ10 command -// - Address = lba * BLOCK_SIZE + offset -// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. -// -// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If -// - read < bufsize : These bytes are transferred first and callback invoked again for remaining data. -// -// - read == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback invoked again with the same parameters later on. -// -// - read < 0 : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. -int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); - -// Invoked when received SCSI WRITE10 command -// - Address = lba * BLOCK_SIZE + offset -// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. -// -// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If -// - write < bufsize : callback invoked again with remaining data later on. -// -// - write == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback invoked again with the same parameters later on. -// -// - write < 0 : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. -// -// TODO change buffer to const uint8_t* -int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); - -// Invoked when received SCSI_CMD_INQUIRY -// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively -void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]); - -// Invoked when received Test Unit Ready command. -// return true allowing host to read/write this LUN e.g SD card inserted -bool tud_msc_test_unit_ready_cb(uint8_t lun); - -// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size -// Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size); - -/** - * Invoked when received an SCSI command not in built-in list below. - * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE - * - READ10 and WRITE10 has their own callbacks - * - * \param[in] lun Logical unit number - * \param[in] scsi_cmd SCSI command contents which application must examine to response accordingly - * \param[out] buffer Buffer for SCSI Data Stage. - * - For INPUT: application must fill this with response. - * - For OUTPUT it holds the Data from host - * \param[in] bufsize Buffer's length. - * - * \return Actual bytes processed, can be zero for no-data command. - * \retval negative Indicate error e.g unsupported command, tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ -int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize); - -/*------------- Optional callbacks -------------*/ - -// Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation -TU_ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void); - -// Invoked when received Start Stop Unit command -// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage -// - Start = 1 : active mode, if load_eject = 1 : load disk storage -TU_ATTR_WEAK bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject); - -// Invoked when Read10 command is complete -TU_ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun); - -// Invoke when Write10 command is complete, can be used to flush flash caching -TU_ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun); - -// Invoked when command in tud_msc_scsi_cb is complete -TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]); - -// Invoked to check if device is writable as part of SCSI WRITE10 -TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c deleted file mode 100644 index fa6519956..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC - -#include "host/usbh.h" -#include "host/usbh_classdriver.h" - -#include "msc_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -enum -{ - MSC_STAGE_IDLE = 0, - MSC_STAGE_CMD, - MSC_STAGE_DATA, - MSC_STAGE_STATUS, -}; - -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - uint8_t max_lun; - - volatile bool configured; // Receive SET_CONFIGURE - volatile bool mounted; // Enumeration is complete - - struct { - uint32_t block_size; - uint32_t block_count; - } capacity[CFG_TUH_MSC_MAXLUN]; - - //------------- SCSI -------------// - uint8_t stage; - void* buffer; - tuh_msc_complete_cb_t complete_cb; - - msc_cbw_t cbw; - msc_csw_t csw; -}msch_interface_t; - -CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; - -// buffer used to read scsi information when mounted -// largest response data currently is inquiry TODO Inquiry is not part of enum anymore -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) -static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; - -TU_ATTR_ALWAYS_INLINE -static inline msch_interface_t* get_itf(uint8_t dev_addr) -{ - return &_msch_itf[dev_addr-1]; -} - -//--------------------------------------------------------------------+ -// PUBLIC API -//--------------------------------------------------------------------+ -uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->max_lun; -} - -uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->capacity[lun].block_count; -} - -uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->capacity[lun].block_size; -} - -bool tuh_msc_mounted(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted; -} - -bool tuh_msc_ready(uint8_t dev_addr) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in); -} - -//--------------------------------------------------------------------+ -// PUBLIC API: SCSI COMMAND -//--------------------------------------------------------------------+ -static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) -{ - tu_memclr(cbw, sizeof(msc_cbw_t)); - cbw->signature = MSC_CBW_SIGNATURE; - cbw->tag = 0x54555342; // TUSB - cbw->lun = lun; -} - -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - // TODO claim endpoint - - p_msc->cbw = *cbw; - p_msc->stage = MSC_STAGE_CMD; - p_msc->buffer = data; - p_msc->complete_cb = complete_cb; - - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))); - - return true; -} - -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read_capacity10_t); - cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - - return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); -} - -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = sizeof(scsi_inquiry_resp_t); - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_inquiry_t); - - scsi_inquiry_t const cmd_inquiry = - { - .cmd_code = SCSI_CMD_INQUIRY, - .alloc_length = sizeof(scsi_inquiry_resp_t) - }; - memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); -} - -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = 0; - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_test_unit_ready_t); - cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; - cbw.command[1] = lun; // according to wiki TODO need verification - - return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb); -} - -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb) -{ - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = 18; // TODO sense response - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_request_sense_t); - - scsi_request_sense_t const cmd_request_sense = - { - .cmd_code = SCSI_CMD_REQUEST_SENSE, - .alloc_length = 18 - }; - - memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb); -} - -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read10_t); - - scsi_read10_t const cmd_read10 = - { - .cmd_code = SCSI_CMD_READ_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(cbw.command, &cmd_read10, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb); -} - -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); - - msc_cbw_t cbw; - cbw_init(&cbw, lun); - - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_write10_t); - - scsi_write10_t const cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(cbw.command, &cmd_write10, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, (void*)(uintptr_t) buffer, complete_cb); -} - -#if 0 -// MSC interface Reset (not used now) -bool tuh_msc_reset(uint8_t dev_addr) -{ - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = MSC_REQ_RESET, - .wValue = 0, - .wIndex = p_msc->itf_num, - .wLength = 0 - }; - TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); -} -#endif - -//--------------------------------------------------------------------+ -// CLASS-USBH API -//--------------------------------------------------------------------+ -void msch_init(void) -{ - tu_memclr(_msch_itf, sizeof(_msch_itf)); -} - -void msch_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); - - msch_interface_t* p_msc = get_itf(dev_addr); - - // invoke Application Callback - if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); - - tu_memclr(p_msc, sizeof(msch_interface_t)); -} - -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - msc_cbw_t const * cbw = &p_msc->cbw; - msc_csw_t * csw = &p_msc->csw; - - switch (p_msc->stage) - { - case MSC_STAGE_CMD: - // Must be Command Block - TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); - - if ( cbw->total_bytes && p_msc->buffer ) - { - // Data stage if any - p_msc->stage = MSC_STAGE_DATA; - - uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out; - TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, cbw->total_bytes)); - }else - { - // Status stage - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); - } - break; - - case MSC_STAGE_DATA: - // Status stage - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); - break; - - case MSC_STAGE_STATUS: - // SCSI op is complete - p_msc->stage = MSC_STAGE_IDLE; - - if (p_msc->complete_cb) p_msc->complete_cb(dev_addr, cbw, csw); - break; - - // unknown state - default: break; - } - - return true; -} - -//--------------------------------------------------------------------+ -// MSC Enumeration -//--------------------------------------------------------------------+ - -static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); - -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ - TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && - MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); - - // msc driver length is fixed - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len); - - msch_interface_t* p_msc = get_itf(dev_addr); - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); - - for(uint32_t i=0; i<2; i++) - { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); - - if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) - { - p_msc->ep_in = ep_desc->bEndpointAddress; - }else - { - p_msc->ep_out = ep_desc->bEndpointAddress; - } - - ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); - } - - p_msc->itf_num = desc_itf->bInterfaceNumber; - - return true; -} - -bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_ASSERT(p_msc->itf_num == itf_num); - - p_msc->configured = true; - - //------------- Get Max Lun -------------// - TU_LOG2("MSC Get Max Lun\r\n"); - tusb_control_request_t request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = MSC_REQ_GET_MAX_LUN, - .wValue = 0, - .wIndex = itf_num, - .wLength = 1 - }; - TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, config_get_maxlun_complete)); - - return true; -} - -static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - - msch_interface_t* p_msc = get_itf(dev_addr); - - // STALL means zero - p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0; - p_msc->max_lun++; // MAX LUN is minus 1 by specs - - // TODO multiple LUN support - TU_LOG2("SCSI Test Unit Ready\r\n"); - uint8_t const lun = 0; - tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete); - - return true; -} - -static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - if (csw->status == 0) - { - // Unit is ready, read its capacity - TU_LOG2("SCSI Read Capacity\r\n"); - tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete); - }else - { - // Note: During enumeration, some device fails Test Unit Ready and require a few retries - // with Request Sense to start working !! - // TODO limit number of retries - TU_LOG2("SCSI Request Sense\r\n"); - TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete)); - } - - return true; -} - -static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - TU_ASSERT(csw->status == 0); - TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, config_test_unit_ready_complete)); - return true; -} - -static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - TU_ASSERT(csw->status == 0); - - msch_interface_t* p_msc = get_itf(dev_addr); - - // Capacity response field: Block size and Last LBA are both Big-Endian - scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer); - p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; - p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); - - // Mark enumeration is complete - p_msc->mounted = true; - if (tuh_msc_mount_cb) tuh_msc_mount_cb(dev_addr); - - // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h deleted file mode 100644 index 7718ad4fe..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/msc/msc_host.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_MSC_HOST_H_ -#define _TUSB_MSC_HOST_H_ - -#include "msc.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver Configuration -//--------------------------------------------------------------------+ - -#ifndef CFG_TUH_MSC_MAXLUN -#define CFG_TUH_MSC_MAXLUN 4 -#endif - -typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Check if device supports MassStorage interface. -// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() -bool tuh_msc_mounted(uint8_t dev_addr); - -// Check if the interface is currently ready or busy transferring data -bool tuh_msc_ready(uint8_t dev_addr); - -// Get Max Lun -uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); - -// Get number of block -uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun); - -// Get block size in bytes -uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun); - -// Perform a full SCSI command (cbw, data, csw) in non-blocking manner. -// Complete callback is invoked when SCSI op is complete. -// return true if success, false if there is already pending operation. -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Inquiry command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Test Unit Ready command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Request Sense 10 command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Write 10 command. Write n blocks starting from LBA to device -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); - -// Perform SCSI Read Capacity 10 command -// Complete callback is invoked when SCSI op is complete. -// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by -// simply call tuh_msc_get_block_count() and tuh_msc_get_block_size() -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); - -//------------- Application Callback -------------// - -// Invoked when a device with MassStorage interface is mounted -TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); - -// Invoked when a device with MassStorage interface is unmounted -TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ - -void msch_init (void); -bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); -void msch_close (uint8_t dev_addr); -bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_MSC_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c deleted file mode 100644 index c6cd388e3..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ecm_rndis_device.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_ECM_RNDIS ) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "net_device.h" -#include "rndis_protocol.h" - -void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface - uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active - - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - bool ecm_mode; - - // Endpoint descriptor use to open/close when receving SetInterface - // TODO since configuration descriptor may not be long-lived memory, we should - // keep a copy of endpoint attribute instead - uint8_t const * ecm_desc_epdata; - -} netd_interface_t; - -#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) -#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; - -struct ecm_notify_struct -{ - tusb_control_request_t header; - uint32_t downlink, uplink; -}; - -static const struct ecm_notify_struct ecm_notify_nc = -{ - .header = { - .bmRequestType = 0xA1, - .bRequest = 0 /* NETWORK_CONNECTION aka NetworkConnection */, - .wValue = 1 /* Connected */, - .wLength = 0, - }, -}; - -static const struct ecm_notify_struct ecm_notify_csc = -{ - .header = { - .bmRequestType = 0xA1, - .bRequest = 0x2A /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */, - .wLength = 8, - }, - .downlink = 9728000, - .uplink = 9728000, -}; - -// TODO remove CFG_TUSB_MEM_SECTION, control internal buffer is already in this special section -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union -{ - uint8_t rndis_buf[120]; - struct ecm_notify_struct ecm_buf; -} notify; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -// TODO remove CFG_TUSB_MEM_SECTION -CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf; - -static bool can_xmit; - -void tud_network_recv_renew(void) -{ - usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_out, received, sizeof(received)); -} - -static void do_in_xfer(uint8_t *buf, uint16_t len) -{ - can_xmit = false; - usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_in, buf, len); -} - -void netd_report(uint8_t *buf, uint16_t len) -{ - // skip if previous report not yet acknowledged by host - if ( usbd_edpt_busy(TUD_OPT_RHPORT, _netd_itf.ep_notif) ) return; - usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void netd_init(void) -{ - tu_memclr(&_netd_itf, sizeof(_netd_itf)); -} - -void netd_reset(uint8_t rhport) -{ - (void) rhport; - - netd_init(); -} - -uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass && - TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && - TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol); - - bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0x00 == itf_desc->bInterfaceProtocol); - - TU_VERIFY(is_rndis || is_ecm, 0); - - // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_notif, 0); - - // sanity check the descriptor - _netd_itf.ecm_mode = is_ecm; - - //------------- Management Interface -------------// - _netd_itf.itf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // notification endpoint (if any) - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); - - _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface -------------// - // - RNDIS Data followed immediately by a pair of endpoints - // - CDC-ECM data interface has 2 alternate settings - // - 0 : zero endpoints for inactive (default) - // - 1 : IN & OUT endpoints for active networking - TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - - do - { - tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; - TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len) ); - - // Pair of endpoints - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); - - if ( _netd_itf.ecm_mode ) - { - // ECM by default is in-active, save the endpoint attribute - // to open later when received setInterface - _netd_itf.ecm_desc_epdata = p_desc; - }else - { - // Open endpoint pair for RNDIS - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0 ); - - tud_network_init_cb(); - - // we are ready to transmit a packet - can_xmit = true; - - // prepare for incoming packets - tud_network_recv_renew(); - } - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - - return drv_len; -} - -static void ecm_report(bool nc) -{ - notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; - notify.ecm_buf.header.wIndex = _netd_itf.itf_num; - netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage == CONTROL_STAGE_SETUP ) - { - switch ( request->bmRequestType_bit.type ) - { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); - - tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); - } - break; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; - - // Only valid for Data Interface with Alternate is either 0 or 1 - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); - - // ACM-ECM only: qequest to enable/disable network activities - TU_VERIFY(_netd_itf.ecm_mode); - - _netd_itf.itf_data_alt = req_alt; - - if ( _netd_itf.itf_data_alt ) - { - // TODO since we don't actually close endpoint - // hack here to not re-open it - if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) - { - TU_ASSERT(_netd_itf.ecm_desc_epdata); - TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); - - // TODO should be merge with RNDIS's after endpoint opened - // Also should have opposite callback for application to disable network !! - tud_network_init_cb(); - can_xmit = true; // we are ready to transmit a packet - tud_network_recv_renew(); // prepare for incoming packets - } - }else - { - // TODO close the endpoint pair - // For now pretend that we did, this should have no harm since host won't try to - // communicate with the endpoints again - // _netd_itf.ep_in = _netd_itf.ep_out = 0 - } - - tud_control_status(rhport, request); - } - break; - - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (_netd_itf.itf_num == request->wIndex); - - if (_netd_itf.ecm_mode) - { - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) - { - tud_control_xfer(rhport, request, NULL, 0); - ecm_report(true); - } - } - else - { - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) notify.rndis_buf); - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); - tud_control_xfer(rhport, request, notify.rndis_buf, msglen); - } - else - { - tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); - } - } - break; - - // unsupported request - default: return false; - } - } - else if ( stage == CONTROL_STAGE_DATA ) - { - // Handle RNDIS class control OUT only - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.direction == TUSB_DIR_OUT && - _netd_itf.itf_num == request->wIndex) - { - if ( !_netd_itf.ecm_mode ) - { - rndis_class_set_handler(notify.rndis_buf, request->wLength); - } - } - } - - return true; -} - -static void handle_incoming_packet(uint32_t len) -{ - uint8_t *pnt = received; - uint32_t size = 0; - - if (_netd_itf.ecm_mode) - { - size = len; - } - else - { - rndis_data_packet_t *r = (rndis_data_packet_t *) ((void*) pnt); - if (len >= sizeof(rndis_data_packet_t)) - if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) - if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) - { - pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; - size = r->DataLength; - } - } - - if (!tud_network_recv_cb(pnt, size)) - { - /* if a buffer was never handled by user code, we must renew on the user's behalf */ - tud_network_recv_renew(); - } -} - -bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - /* new packet received */ - if ( ep_addr == _netd_itf.ep_out ) - { - handle_incoming_packet(xferred_bytes); - } - - /* data transmission finished */ - if ( ep_addr == _netd_itf.ep_in ) - { - /* TinyUSB requires the class driver to implement ZLP (since ZLP usage is class-specific) */ - - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE)) ) - { - do_in_xfer(NULL, 0); /* a ZLP is needed */ - } - else - { - /* we're finally finished */ - can_xmit = true; - } - } - - if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) - { - if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); - } - - return true; -} - -bool tud_network_can_xmit(uint16_t size) -{ - (void)size; - - return can_xmit; -} - -void tud_network_xmit(void *ref, uint16_t arg) -{ - uint8_t *data; - uint16_t len; - - if (!can_xmit) - return; - - len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; - data = transmitted + len; - - len += tud_network_xmit_cb(data, ref, arg); - - if (!_netd_itf.ecm_mode) - { - rndis_data_packet_t *hdr = (rndis_data_packet_t *) ((void*) transmitted); - memset(hdr, 0, sizeof(rndis_data_packet_t)); - hdr->MessageType = REMOTE_NDIS_PACKET_MSG; - hdr->MessageLength = len; - hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); - hdr->DataLength = len - sizeof(rndis_data_packet_t); - } - - do_in_xfer(transmitted, len); -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h deleted file mode 100644 index 96ba11fbc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef _TUSB_NCM_H_ -#define _TUSB_NCM_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -// Table 4.3 Data Class Interface Protocol Codes -typedef enum -{ - NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK = 0x01 -} ncm_data_interface_protocol_code_t; - - -// Table 6.2 Class-Specific Request Codes for Network Control Model subclass -typedef enum -{ - NCM_SET_ETHERNET_MULTICAST_FILTERS = 0x40, - NCM_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41, - NCM_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42, - NCM_SET_ETHERNET_PACKET_FILTER = 0x43, - NCM_GET_ETHERNET_STATISTIC = 0x44, - NCM_GET_NTB_PARAMETERS = 0x80, - NCM_GET_NET_ADDRESS = 0x81, - NCM_SET_NET_ADDRESS = 0x82, - NCM_GET_NTB_FORMAT = 0x83, - NCM_SET_NTB_FORMAT = 0x84, - NCM_GET_NTB_INPUT_SIZE = 0x85, - NCM_SET_NTB_INPUT_SIZE = 0x86, - NCM_GET_MAX_DATAGRAM_SIZE = 0x87, - NCM_SET_MAX_DATAGRAM_SIZE = 0x88, - NCM_GET_CRC_MODE = 0x89, - NCM_SET_CRC_MODE = 0x8A, -} ncm_request_code_t; - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c deleted file mode 100644 index 3e131a85c..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/ncm_device.c +++ /dev/null @@ -1,510 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Jacob Berg Potter - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NCM ) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" -#include "net_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -#define NTH16_SIGNATURE 0x484D434E -#define NDP16_SIGNATURE_NCM0 0x304D434E -#define NDP16_SIGNATURE_NCM1 0x314D434E - -typedef struct TU_ATTR_PACKED -{ - uint16_t wLength; - uint16_t bmNtbFormatsSupported; - uint32_t dwNtbInMaxSize; - uint16_t wNdbInDivisor; - uint16_t wNdbInPayloadRemainder; - uint16_t wNdbInAlignment; - uint16_t wReserved; - uint32_t dwNtbOutMaxSize; - uint16_t wNdbOutDivisor; - uint16_t wNdbOutPayloadRemainder; - uint16_t wNdbOutAlignment; - uint16_t wNtbOutMaxDatagrams; -} ntb_parameters_t; - -typedef struct TU_ATTR_PACKED -{ - uint32_t dwSignature; - uint16_t wHeaderLength; - uint16_t wSequence; - uint16_t wBlockLength; - uint16_t wNdpIndex; -} nth16_t; - -typedef struct TU_ATTR_PACKED -{ - uint16_t wDatagramIndex; - uint16_t wDatagramLength; -} ndp16_datagram_t; - -typedef struct TU_ATTR_PACKED -{ - uint32_t dwSignature; - uint16_t wLength; - uint16_t wNextNdpIndex; - ndp16_datagram_t datagram[]; -} ndp16_t; - -typedef union TU_ATTR_PACKED { - struct { - nth16_t nth; - ndp16_t ndp; - }; - uint8_t data[CFG_TUD_NCM_IN_NTB_MAX_SIZE]; -} transmit_ntb_t; - -struct ecm_notify_struct -{ - tusb_control_request_t header; - uint32_t downlink, uplink; -}; - -typedef struct -{ - uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface - uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active - - uint8_t ep_notif; - uint8_t ep_in; - uint8_t ep_out; - - const ndp16_t *ndp; - uint8_t num_datagrams, current_datagram_index; - - enum { - REPORT_SPEED, - REPORT_CONNECTED, - REPORT_DONE - } report_state; - bool report_pending; - - uint8_t current_ntb; // Index in transmit_ntb[] that is currently being filled with datagrams - uint8_t datagram_count; // Number of datagrams in transmit_ntb[current_ntb] - uint16_t next_datagram_offset; // Offset in transmit_ntb[current_ntb].data to place the next datagram - uint16_t ntb_in_size; // Maximum size of transmitted (IN to host) NTBs; initially CFG_TUD_NCM_IN_NTB_MAX_SIZE - uint8_t max_datagrams_per_ntb; // Maximum number of datagrams per NTB; initially CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB - - uint16_t nth_sequence; // Sequence number counter for transmitted NTBs - - bool transferring; - -} ncm_interface_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static const ntb_parameters_t ntb_parameters = { - .wLength = sizeof(ntb_parameters_t), - .bmNtbFormatsSupported = 0x01, - .dwNtbInMaxSize = CFG_TUD_NCM_IN_NTB_MAX_SIZE, - .wNdbInDivisor = 4, - .wNdbInPayloadRemainder = 0, - .wNdbInAlignment = CFG_TUD_NCM_ALIGNMENT, - .wReserved = 0, - .dwNtbOutMaxSize = CFG_TUD_NCM_OUT_NTB_MAX_SIZE, - .wNdbOutDivisor = 4, - .wNdbOutPayloadRemainder = 0, - .wNdbOutAlignment = CFG_TUD_NCM_ALIGNMENT, - .wNtbOutMaxDatagrams = 0 -}; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static transmit_ntb_t transmit_ntb[2]; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t receive_ntb[CFG_TUD_NCM_OUT_NTB_MAX_SIZE]; - -static ncm_interface_t ncm_interface; - -/* - * Set up the NTB state in ncm_interface to be ready to add datagrams. - */ -static void ncm_prepare_for_tx(void) { - ncm_interface.datagram_count = 0; - // datagrams start after all the headers - ncm_interface.next_datagram_offset = sizeof(nth16_t) + sizeof(ndp16_t) - + ((CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB + 1) * sizeof(ndp16_datagram_t)); -} - -/* - * If not already transmitting, start sending the current NTB to the host and swap buffers - * to start filling the other one with datagrams. - */ -static void ncm_start_tx(void) { - if (ncm_interface.transferring) { - return; - } - - transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; - size_t ntb_length = ncm_interface.next_datagram_offset; - - // Fill in NTB header - ntb->nth.dwSignature = NTH16_SIGNATURE; - ntb->nth.wHeaderLength = sizeof(nth16_t); - ntb->nth.wSequence = ncm_interface.nth_sequence++; - ntb->nth.wBlockLength = ntb_length; - ntb->nth.wNdpIndex = sizeof(nth16_t); - - // Fill in NDP16 header and terminator - ntb->ndp.dwSignature = NDP16_SIGNATURE_NCM0; - ntb->ndp.wLength = sizeof(ndp16_t) + (ncm_interface.datagram_count + 1) * sizeof(ndp16_datagram_t); - ntb->ndp.wNextNdpIndex = 0; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = 0; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = 0; - - // Kick off an endpoint transfer - usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_in, ntb->data, ntb_length); - ncm_interface.transferring = true; - - // Swap to the other NTB and clear it out - ncm_interface.current_ntb = 1 - ncm_interface.current_ntb; - ncm_prepare_for_tx(); -} - -static struct ecm_notify_struct ncm_notify_connected = -{ - .header = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = CDC_NOTIF_NETWORK_CONNECTION, - .wValue = 1 /* Connected */, - .wLength = 0, - }, -}; - -static struct ecm_notify_struct ncm_notify_speed_change = -{ - .header = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE, - .wLength = 8, - }, - .downlink = 10000000, - .uplink = 10000000, -}; - -void tud_network_recv_renew(void) -{ - if (!ncm_interface.num_datagrams) - { - usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_out, receive_ntb, sizeof(receive_ntb)); - return; - } - - const ndp16_t *ndp = ncm_interface.ndp; - const int i = ncm_interface.current_datagram_index; - ncm_interface.current_datagram_index++; - ncm_interface.num_datagrams--; - - tud_network_recv_cb(receive_ntb + ndp->datagram[i].wDatagramIndex, ndp->datagram[i].wDatagramLength); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ - -void netd_init(void) -{ - tu_memclr(&ncm_interface, sizeof(ncm_interface)); - ncm_interface.ntb_in_size = CFG_TUD_NCM_IN_NTB_MAX_SIZE; - ncm_interface.max_datagrams_per_ntb = CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB; - ncm_prepare_for_tx(); -} - -void netd_reset(uint8_t rhport) -{ - (void) rhport; - - netd_init(); -} - -uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - // confirm interface hasn't already been allocated - TU_ASSERT(0 == ncm_interface.ep_notif, 0); - - //------------- Management Interface -------------// - ncm_interface.itf_num = itf_desc->bInterfaceNumber; - - uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); - - // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // notification endpoint (if any) - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); - - ncm_interface.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - //------------- Data Interface -------------// - // - CDC-NCM data interface has 2 alternate settings - // - 0 : zero endpoints for inactive (default) - // - 1 : IN & OUT endpoints for transfer of NTBs - TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); - - do - { - tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; - TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } while((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (drv_len <= max_len)); - - // Pair of endpoints - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); - - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &ncm_interface.ep_out, &ncm_interface.ep_in) ); - - drv_len += 2*sizeof(tusb_desc_endpoint_t); - - return drv_len; -} - -static void ncm_report(void) -{ - if (ncm_interface.report_state == REPORT_SPEED) { - ncm_notify_speed_change.header.wIndex = ncm_interface.itf_num; - usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_speed_change, sizeof(ncm_notify_speed_change)); - ncm_interface.report_state = REPORT_CONNECTED; - ncm_interface.report_pending = true; - } else if (ncm_interface.report_state == REPORT_CONNECTED) { - ncm_notify_connected.header.wIndex = ncm_interface.itf_num; - usbd_edpt_xfer(TUD_OPT_RHPORT, ncm_interface.ep_notif, (uint8_t *) &ncm_notify_connected, sizeof(ncm_notify_connected)); - ncm_interface.report_state = REPORT_DONE; - ncm_interface.report_pending = true; - } -} - -TU_ATTR_WEAK void tud_network_link_state_cb(bool state) -{ - (void)state; -} - -// Handle class control request -// return false to stall control endpoint (e.g unsupported request) -bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( stage != CONTROL_STAGE_SETUP ) return true; - - switch ( request->bmRequestType_bit.type ) - { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum); - - tud_control_xfer(rhport, request, &ncm_interface.itf_data_alt, 1); - } - break; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; - - // Only valid for Data Interface with Alternate is either 0 or 1 - TU_VERIFY(ncm_interface.itf_num + 1 == req_itfnum && req_alt < 2); - - if (req_alt != ncm_interface.itf_data_alt) { - ncm_interface.itf_data_alt = req_alt; - - if (ncm_interface.itf_data_alt) { - if (!usbd_edpt_busy(rhport, ncm_interface.ep_out)) { - tud_network_recv_renew(); // prepare for incoming datagrams - } - if (!ncm_interface.report_pending) { - ncm_report(); - } - } - - tud_network_link_state_cb(ncm_interface.itf_data_alt); - } - - tud_control_status(rhport, request); - } - break; - - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (ncm_interface.itf_num == request->wIndex); - - if (NCM_GET_NTB_PARAMETERS == request->bRequest) - { - tud_control_xfer(rhport, request, (void*)&ntb_parameters, sizeof(ntb_parameters)); - } - - break; - - // unsupported request - default: return false; - } - - return true; -} - -static void handle_incoming_datagram(uint32_t len) -{ - uint32_t size = len; - - if (len == 0) { - return; - } - - TU_ASSERT(size >= sizeof(nth16_t), ); - - const nth16_t *hdr = (const nth16_t *)receive_ntb; - TU_ASSERT(hdr->dwSignature == NTH16_SIGNATURE, ); - TU_ASSERT(hdr->wNdpIndex >= sizeof(nth16_t) && (hdr->wNdpIndex + sizeof(ndp16_t)) <= len, ); - - const ndp16_t *ndp = (const ndp16_t *)(receive_ntb + hdr->wNdpIndex); - TU_ASSERT(ndp->dwSignature == NDP16_SIGNATURE_NCM0 || ndp->dwSignature == NDP16_SIGNATURE_NCM1, ); - TU_ASSERT(hdr->wNdpIndex + ndp->wLength <= len, ); - - int num_datagrams = (ndp->wLength - 12) / 4; - ncm_interface.current_datagram_index = 0; - ncm_interface.num_datagrams = 0; - ncm_interface.ndp = ndp; - for (int i = 0; i < num_datagrams && ndp->datagram[i].wDatagramIndex && ndp->datagram[i].wDatagramLength; i++) - { - ncm_interface.num_datagrams++; - } - - tud_network_recv_renew(); -} - -bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - /* new datagram receive_ntb */ - if (ep_addr == ncm_interface.ep_out ) - { - handle_incoming_datagram(xferred_bytes); - } - - /* data transmission finished */ - if (ep_addr == ncm_interface.ep_in ) - { - if (ncm_interface.transferring) { - ncm_interface.transferring = false; - } - - // If there are datagrams queued up that we tried to send while this NTB was being emitted, send them now - if (ncm_interface.datagram_count && ncm_interface.itf_data_alt == 1) { - ncm_start_tx(); - } - } - - if (ep_addr == ncm_interface.ep_notif ) - { - ncm_interface.report_pending = false; - ncm_report(); - } - - return true; -} - -// poll network driver for its ability to accept another packet to transmit -bool tud_network_can_xmit(uint16_t size) -{ - TU_VERIFY(ncm_interface.itf_data_alt == 1); - - if (ncm_interface.datagram_count >= ncm_interface.max_datagrams_per_ntb) { - TU_LOG2("NTB full [by count]\r\n"); - return false; - } - - size_t next_datagram_offset = ncm_interface.next_datagram_offset; - if (next_datagram_offset + size > ncm_interface.ntb_in_size) { - TU_LOG2("ntb full [by size]\r\n"); - return false; - } - - return true; -} - -void tud_network_xmit(void *ref, uint16_t arg) -{ - transmit_ntb_t *ntb = &transmit_ntb[ncm_interface.current_ntb]; - size_t next_datagram_offset = ncm_interface.next_datagram_offset; - - uint16_t size = tud_network_xmit_cb(ntb->data + next_datagram_offset, ref, arg); - - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramIndex = ncm_interface.next_datagram_offset; - ntb->ndp.datagram[ncm_interface.datagram_count].wDatagramLength = size; - - ncm_interface.datagram_count++; - next_datagram_offset += size; - - // round up so the next datagram is aligned correctly - next_datagram_offset += (CFG_TUD_NCM_ALIGNMENT - 1); - next_datagram_offset -= (next_datagram_offset % CFG_TUD_NCM_ALIGNMENT); - - ncm_interface.next_datagram_offset = next_datagram_offset; - - ncm_start_tx(); -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h deleted file mode 100644 index 6e294465b..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/net/net_device.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Peter Lawrence - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_NET_DEVICE_H_ -#define _TUSB_NET_DEVICE_H_ - -#include "class/cdc/cdc.h" - -#if CFG_TUD_ECM_RNDIS && CFG_TUD_NCM -#error "Cannot enable both ECM_RNDIS and NCM network drivers" -#endif - -#include "ncm.h" - -/* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ -#define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - -/* Maximum Transmission Unit (in bytes) of the network, including Ethernet header */ -#ifndef CFG_TUD_NET_MTU -#define CFG_TUD_NET_MTU 1514 -#endif - -#ifndef CFG_TUD_NCM_IN_NTB_MAX_SIZE -#define CFG_TUD_NCM_IN_NTB_MAX_SIZE 3200 -#endif - -#ifndef CFG_TUD_NCM_OUT_NTB_MAX_SIZE -#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200 -#endif - -#ifndef CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB -#define CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB 8 -#endif - -#ifndef CFG_TUD_NCM_ALIGNMENT -#define CFG_TUD_NCM_ALIGNMENT 4 -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// indicate to network driver that client has finished with the packet provided to network_recv_cb() -void tud_network_recv_renew(void); - -// poll network driver for its ability to accept another packet to transmit -bool tud_network_can_xmit(uint16_t size); - -// if network_can_xmit() returns true, network_xmit() can be called once -void tud_network_xmit(void *ref, uint16_t arg); - -//--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) -//--------------------------------------------------------------------+ - -// client must provide this: return false if the packet buffer was not accepted -bool tud_network_recv_cb(const uint8_t *src, uint16_t size); - -// client must provide this: copy from network stack packet pointer to dst -uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg); - -//------------- ECM/RNDIS -------------// - -// client must provide this: initialize any network state back to the beginning -void tud_network_init_cb(void); - -// client must provide this: 48-bit MAC address -// TODO removed later since it is not part of tinyusb stack -extern const uint8_t tud_network_mac_address[6]; - -//------------- NCM -------------// - -// callback to client providing optional indication of internal state of network driver -void tud_network_link_state_cb(bool state); - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void netd_init (void); -void netd_reset (uint8_t rhport); -uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void netd_report (uint8_t *buf, uint16_t len); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_NET_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h deleted file mode 100644 index 7d7005c2e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc.h +++ /dev/null @@ -1,316 +0,0 @@ - -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 N Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBTMC_H__ -#define _TUSB_USBTMC_H__ - -#include "common/tusb_common.h" - - -/* Implements USBTMC Revision 1.0, April 14, 2003 - - String descriptors must have a "LANGID=0x409"/US English string. - Characters must be 0x20 (' ') to 0x7E ('~') ASCII, - But MUST not contain: "/:?\* - Also must not have leading or trailing space (' ') - Device descriptor must state USB version 0x0200 or greater - - If USB488DeviceCapabilites.D2 = 1 (SR1), then there must be a INT endpoint. -*/ - -#define USBTMC_VERSION 0x0100 -#define USBTMC_488_VERSION 0x0100 - -typedef enum { - USBTMC_MSGID_DEV_DEP_MSG_OUT = 1u, - USBTMC_MSGID_DEV_DEP_MSG_IN = 2u, - USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT = 126u, - USBTMC_MSGID_VENDOR_SPECIFIC_IN = 127u, - USBTMC_MSGID_USB488_TRIGGER = 128u, -} usbtmc_msgid_enum; - -/// \brief Message header (For BULK OUT and BULK IN); 4 bytes -typedef struct TU_ATTR_PACKED -{ - uint8_t MsgID ; ///< Message type ID (usbtmc_msgid_enum) - uint8_t bTag ; ///< Transfer ID 1<=bTag<=255 - uint8_t bTagInverse ; ///< Complement of the tag - uint8_t _reserved ; ///< Must be 0x00 -} usbtmc_msg_header_t; - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header; - uint8_t data[8]; -} usbtmc_msg_generic_t; - -/* Uses on the bulk-out endpoint: */ -// Next 8 bytes are message-specific -typedef struct TU_ATTR_PACKED { - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - struct TU_ATTR_PACKED - { - unsigned int EOM : 1 ; ///< EOM set on last byte - } bmTransferAttributes; - uint8_t _reserved[3]; -} usbtmc_msg_request_dev_dep_out; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_out) == 12u, "struct wrong length"); - -// Next 8 bytes are message-specific -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - struct TU_ATTR_PACKED - { - unsigned int TermCharEnabled : 1 ; ///< "The Bulk-IN transfer must terminate on the specified TermChar."; CAPABILITIES must list TermChar - } bmTransferAttributes; - uint8_t TermChar; - uint8_t _reserved[2]; -} usbtmc_msg_request_dev_dep_in; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_dev_dep_in) == 12u, "struct wrong length"); - -/* Bulk-in headers */ - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header; - uint32_t TransferSize; - struct TU_ATTR_PACKED - { - uint8_t EOM: 1; ///< Last byte of transfer is the end of the message - uint8_t UsingTermChar: 1; ///< Support TermChar && Request.TermCharEnabled && last char in transfer is TermChar - } bmTransferAttributes; - uint8_t _reserved[3]; -} usbtmc_msg_dev_dep_msg_in_header_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_dev_dep_msg_in_header_t) == 12u, "struct wrong length"); - -/* Unsupported vendor things.... Are these ever used?*/ - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - uint8_t _reserved[4]; -} usbtmc_msg_request_vendor_specific_out; - - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_out) == 12u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - usbtmc_msg_header_t header ; ///< Header - uint32_t TransferSize ; ///< Transfer size; LSB first - uint8_t _reserved[4]; -} usbtmc_msg_request_vendor_specific_in; - -TU_VERIFY_STATIC(sizeof(usbtmc_msg_request_vendor_specific_in) == 12u, "struct wrong length"); - -// Control request type should use tusb_control_request_t - -/* -typedef struct TU_ATTR_PACKED { - struct { - unsigned int Recipient : 5 ; ///< EOM set on last byte - unsigned int Type : 2 ; ///< EOM set on last byte - unsigned int DirectionToHost : 1 ; ///< 0 is OUT, 1 is IN - } bmRequestType; - uint8_t bRequest ; ///< If bmRequestType.Type = Class, see usmtmc_request_type_enum - uint16_t wValue ; - uint16_t wIndex ; - uint16_t wLength ; // Number of bytes in data stage -} usbtmc_class_specific_control_req; - -*/ -// bulk-in protocol errors -enum { - USBTMC_BULK_IN_ERR_INCOMPLETE_HEADER = 1u, - USBTMC_BULK_IN_ERR_UNSUPPORTED = 2u, - USBTMC_BULK_IN_ERR_BAD_PARAMETER = 3u, - USBTMC_BULK_IN_ERR_DATA_TOO_SHORT = 4u, - USBTMC_BULK_IN_ERR_DATA_TOO_LONG = 5u, -}; -// bult-in halt errors -enum { - USBTMC_BULK_IN_ERR = 1u, ///< receives a USBTMC command message that expects a response while a - /// Bulk-IN transfer is in progress -}; - -typedef enum { - USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT = 1u, - USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS = 2u, - USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN = 3u, - USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS = 4u, - USBTMC_bREQUEST_INITIATE_CLEAR = 5u, - USBTMC_bREQUEST_CHECK_CLEAR_STATUS = 6u, - USBTMC_bREQUEST_GET_CAPABILITIES = 7u, - - USBTMC_bREQUEST_INDICATOR_PULSE = 64u, // Optional - - /****** USBTMC 488 *************/ - USB488_bREQUEST_READ_STATUS_BYTE = 128u, - USB488_bREQUEST_REN_CONTROL = 160u, - USB488_bREQUEST_GO_TO_LOCAL = 161u, - USB488_bREQUEST_LOCAL_LOCKOUT = 162u, - -} usmtmc_request_type_enum; - -typedef enum { - USBTMC_STATUS_SUCCESS = 0x01, - USBTMC_STATUS_PENDING = 0x02, - USBTMC_STATUS_FAILED = 0x80, - USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81, - USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS = 0x82, - USBTMC_STATUS_SPLIT_IN_PROGRESS = 0x83 -} usbtmc_status_enum; - -/************************************************************ - * Control Responses - */ - -typedef struct TU_ATTR_PACKED { - uint8_t USBTMC_status; ///< usbtmc_status_enum - uint8_t _reserved; - uint16_t bcdUSBTMC; ///< USBTMC_VERSION - - struct TU_ATTR_PACKED - { - unsigned int listenOnly :1; - unsigned int talkOnly :1; - unsigned int supportsIndicatorPulse :1; - } bmIntfcCapabilities; - struct TU_ATTR_PACKED - { - unsigned int canEndBulkInOnTermChar :1; - } bmDevCapabilities; - uint8_t _reserved2[6]; - uint8_t _reserved3[12]; -} usbtmc_response_capabilities_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_t) == 0x18, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - struct TU_ATTR_PACKED - { - unsigned int BulkInFifoBytes :1; - } bmClear; -} usbtmc_get_clear_status_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); - -// Used for both abort bulk IN and bulk OUT -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - uint8_t bTag; -} usbtmc_initiate_abort_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_get_clear_status_rsp_t) == 2u, "struct wrong length"); - -// Used for both check_abort_bulk_in_status and check_abort_bulk_out_status -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - struct TU_ATTR_PACKED - { - unsigned int BulkInFifoBytes : 1; ///< Has queued data or a short packet that is queued - } bmAbortBulkIn; - uint8_t _reserved[2]; ///< Must be zero - uint32_t NBYTES_RXD_TXD; -} usbtmc_check_abort_bulk_rsp_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_check_abort_bulk_rsp_t) == 8u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; ///< usbtmc_status_enum - uint8_t _reserved; - uint16_t bcdUSBTMC; ///< USBTMC_VERSION - - struct TU_ATTR_PACKED - { - unsigned int listenOnly :1; - unsigned int talkOnly :1; - unsigned int supportsIndicatorPulse :1; - } bmIntfcCapabilities; - - struct TU_ATTR_PACKED - { - unsigned int canEndBulkInOnTermChar :1; - } bmDevCapabilities; - - uint8_t _reserved2[6]; - uint16_t bcdUSB488; - - struct TU_ATTR_PACKED - { - unsigned int is488_2 :1; - unsigned int supportsREN_GTL_LLO :1; - unsigned int supportsTrigger :1; - } bmIntfcCapabilities488; - - struct TU_ATTR_PACKED - { - unsigned int SCPI :1; - unsigned int SR1 :1; - unsigned int RL1 :1; - unsigned int DT1 :1; - } bmDevCapabilities488; - uint8_t _reserved3[8]; -} usbtmc_response_capabilities_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_response_capabilities_488_t) == 0x18, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - uint8_t USBTMC_status; - uint8_t bTag; - uint8_t statusByte; -} usbtmc_read_stb_rsp_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length"); - -typedef struct TU_ATTR_PACKED -{ - struct TU_ATTR_PACKED - { - unsigned int bTag : 7; - unsigned int one : 1; - } bNotify1; - uint8_t StatusByte; -} usbtmc_read_stb_interrupt_488_t; - -TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_interrupt_488_t) == 2u, "struct wrong length"); - -#endif - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c deleted file mode 100644 index 26be987cf..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Nathan Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* - * This library is not fully reentrant, though it is reentrant from the view - * of either the application layer or the USB stack. Due to its locking, - * it is not safe to call its functions from interrupts. - * - * The one exception is that its functions may not be called from the application - * until the USB stack is initialized. This should not be a problem since the - * device shouldn't be sending messages until it receives a request from the - * host. - */ - - -/* - * In the case of single-CPU "no OS", this task is never preempted other than by - * interrupts, and the USBTMC code isn't called by interrupts, so all is OK. For "no OS", - * the mutex structure's main effect is to disable the USB interrupts. - * With an OS, this class driver uses the OSAL to perform locking. The code uses a single lock - * and does not call outside of this class with a lock held, so deadlocks won't happen. - */ - -//Limitations: -// "vendor-specific" commands are not handled. -// Dealing with "termchar" must be handled by the application layer, -// though additional error checking is does in this module. -// talkOnly and listenOnly are NOT supported. They're not permitted -// in USB488, anyway. - -/* Supported: - * - * Notification pulse - * Trigger - * Read status byte (both by interrupt endpoint and control message) - * - */ - - -// TODO: -// USBTMC 3.2.2 error conditions not strictly followed -// No local lock-out, REN, or GTL. -// Clear message available status byte at the correct time? (488 4.3.1.3) - - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "usbtmc_device.h" - -#ifdef xDEBUG -#include "uart_util.h" -static char logMsg[150]; -#endif - -/* - * The state machine does not allow simultaneous reading and writing. This is - * consistent with USBTMC. - */ - -typedef enum -{ - STATE_CLOSED, // Endpoints have not yet been opened since USB reset - STATE_NAK, // Bulk-out endpoint is in NAK state. - STATE_IDLE, // Bulk-out endpoint is waiting for CMD. - STATE_RCV, // Bulk-out is receiving DEV_DEP message - STATE_TX_REQUESTED, - STATE_TX_INITIATED, - STATE_TX_SHORTED, - STATE_CLEARING, - STATE_ABORTING_BULK_IN, - STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission - STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been transmitted - STATE_ABORTING_BULK_OUT, - STATE_NUM_STATES -} usbtmcd_state_enum; - -#if (CFG_TUD_USBTMC_ENABLE_488) - typedef usbtmc_response_capabilities_488_t usbtmc_capabilities_specific_t; -#else - typedef usbtmc_response_capabilities_t usbtmc_capabilities_specific_t; -#endif - - -typedef struct -{ - volatile usbtmcd_state_enum state; - - uint8_t itf_id; - uint8_t rhport; - uint8_t ep_bulk_in; - uint8_t ep_bulk_out; - uint8_t ep_int_in; - // IN buffer is only used for first packet, not the remainder - // in order to deal with prepending header - CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_MAX_PACKET_SIZE]; - // OUT buffer receives one packet at a time - CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; - uint32_t transfer_size_remaining; // also used for requested length for bulk IN. - uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) - - uint8_t lastBulkOutTag; // used for aborts (mostly) - uint8_t lastBulkInTag; // used for aborts (mostly) - - uint8_t const * devInBuffer; // pointer to application-layer used for transmissions - - usbtmc_capabilities_specific_t const * capabilities; -} usbtmc_interface_state_t; - -CFG_TUSB_MEM_SECTION static usbtmc_interface_state_t usbtmc_state = -{ - .itf_id = 0xFF, -}; - -// We need all headers to fit in a single packet in this implementation. -TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small"); -TU_VERIFY_STATIC( - (sizeof(usbtmc_state.ep_bulk_in_buf) % USBTMCD_MAX_PACKET_SIZE) == 0, - "packet buffer must be a multiple of the packet size"); - -static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); - -static uint8_t termChar; -static uint8_t termCharRequested = false; - - -osal_mutex_def_t usbtmcLockBuffer; -static osal_mutex_t usbtmcLock; - -// Our own private lock, mostly for the state variable. -#define criticalEnter() do {osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0) -#define criticalLeave() do {osal_mutex_unlock(usbtmcLock); } while (0) - -bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newState) -{ - bool ret = true; - criticalEnter(); - usbtmcd_state_enum oldState = usbtmc_state.state; - if (oldState == expectedState) - { - usbtmc_state.state = newState; - } - else - { - ret = false; - } - criticalLeave(); - return ret; -} - -// called from app -// We keep a reference to the buffer, so it MUST not change until the app is -// notified that the transfer is complete. -// length of data is specified in the hdr. - -// We can't just send the whole thing at once because we need to concatanate the -// header with the data. -bool tud_usbtmc_transmit_dev_msg_data( - const void * data, size_t len, - bool endOfMessage, - bool usingTermChar) -{ - const unsigned int txBufLen = sizeof(usbtmc_state.ep_bulk_in_buf); - -#ifndef NDEBUG - TU_ASSERT(len > 0u); - TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); - TU_ASSERT(usbtmc_state.transfer_size_sent == 0u); - if(usingTermChar) - { - TU_ASSERT(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); - TU_ASSERT(termCharRequested); - TU_ASSERT(((uint8_t const*)data)[len-1u] == termChar); - } -#endif - - TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); - usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_state.ep_bulk_in_buf; - tu_varclr(hdr); - hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; - hdr->header.bTag = usbtmc_state.lastBulkInTag; - hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); - hdr->TransferSize = len; - hdr->bmTransferAttributes.EOM = endOfMessage; - hdr->bmTransferAttributes.UsingTermChar = usingTermChar; - - // Copy in the header - const size_t headerLen = sizeof(*hdr); - const size_t dataLen = ((headerLen + hdr->TransferSize) <= txBufLen) ? - len : (txBufLen - headerLen); - const size_t packetLen = headerLen + dataLen; - - memcpy((uint8_t*)(usbtmc_state.ep_bulk_in_buf) + headerLen, data, dataLen); - usbtmc_state.transfer_size_remaining = len - dataLen; - usbtmc_state.transfer_size_sent = dataLen; - usbtmc_state.devInBuffer = (uint8_t const*) data + (dataLen); - - bool stateChanged = - atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); - TU_VERIFY(stateChanged); - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen)); - return true; -} - -void usbtmcd_init_cb(void) -{ - usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb(); -#ifndef NDEBUG -# if CFG_TUD_USBTMC_ENABLE_488 - if (usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) { - TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL,); - } - // Per USB488 spec: table 8 - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); -# endif - if (usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) { - TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL,); - } -#endif - - usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); -} - -uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void)rhport; - - uint16_t drv_len; - uint8_t const * p_desc; - uint8_t found_endpoints = 0; - - TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS , 0); - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS, 0); - -#ifndef NDEBUG - // Only 2 or 3 endpoints are allowed for USBTMC. - TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3), 0); -#endif - - TU_ASSERT(usbtmc_state.state == STATE_CLOSED, 0); - - // Interface - drv_len = 0u; - p_desc = (uint8_t const *) itf_desc; - - usbtmc_state.itf_id = itf_desc->bInterfaceNumber; - usbtmc_state.rhport = rhport; - - while (found_endpoints < itf_desc->bNumEndpoints && drv_len <= max_len) - { - if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) - { - tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; - switch(ep_desc->bmAttributes.xfer) { - case TUSB_XFER_BULK: - TU_ASSERT(tu_edpt_packet_size(ep_desc) == USBTMCD_MAX_PACKET_SIZE, 0); - if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) - { - usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; - } else { - usbtmc_state.ep_bulk_out = ep_desc->bEndpointAddress; - } - - break; - case TUSB_XFER_INTERRUPT: -#ifndef NDEBUG - TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN, 0); - TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); -#endif - usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; - break; - default: - TU_ASSERT(false, 0); - } - TU_ASSERT( usbd_edpt_open(rhport, ep_desc), 0); - found_endpoints++; - } - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - // bulk endpoints are required, but interrupt IN is optional -#ifndef NDEBUG - TU_ASSERT(usbtmc_state.ep_bulk_in != 0, 0); - TU_ASSERT(usbtmc_state.ep_bulk_out != 0, 0); - if (itf_desc->bNumEndpoints == 2) - { - TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); - } - else if (itf_desc->bNumEndpoints == 3) - { - TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); - } -#if (CFG_TUD_USBTMC_ENABLE_488) - if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || - usbtmc_state.capabilities->bmDevCapabilities488.SR1) - { - TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); - } -#endif -#endif - atomicChangeState(STATE_CLOSED, STATE_NAK); - tud_usbtmc_open_cb(itf_desc->iInterface); - - return drv_len; -} -// Tell USBTMC class to set its bulk-in EP to ACK so that it can -// receive USBTMC commands. -// Returns false if it was already in an ACK state or is busy -// processing a command (such as a clear). Returns true if it was -// in the NAK state and successfully transitioned to the ACK wait -// state. -bool tud_usbtmc_start_bus_read() -{ - usbtmcd_state_enum oldState = usbtmc_state.state; - switch(oldState) - { - // These may transition to IDLE - case STATE_NAK: - case STATE_ABORTING_BULK_IN_ABORTED: - TU_VERIFY(atomicChangeState(oldState, STATE_IDLE)); - break; - // When receiving, let it remain receiving - case STATE_RCV: - break; - default: - TU_VERIFY(false); - } - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64)); - return true; -} - -void usbtmcd_reset_cb(uint8_t rhport) -{ - (void)rhport; - usbtmc_capabilities_specific_t const * capabilities = tud_usbtmc_get_capabilities_cb(); - - criticalEnter(); - tu_varclr(&usbtmc_state); - usbtmc_state.capabilities = capabilities; - usbtmc_state.itf_id = 0xFFu; - criticalLeave(); -} - -static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) -{ - (void)rhport; - // return true upon failure, as we can assume error is being handled elsewhere. - TU_VERIFY(atomicChangeState(STATE_IDLE, STATE_RCV), true); - usbtmc_state.transfer_size_sent = 0u; - - // must be a header, should have been confirmed before calling here. - usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - TU_VERIFY(tud_usbtmc_msgBulkOut_start_cb(msg)); - - TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); - usbtmc_state.lastBulkOutTag = msg->header.bTag; - return true; -} - -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) -{ - (void)rhport; - // return true upon failure, as we can assume error is being handled elsewhere. - TU_VERIFY(usbtmc_state.state == STATE_RCV,true); - - bool shortPacket = (packetLen < USBTMCD_MAX_PACKET_SIZE); - - // Packet is to be considered complete when we get enough data or at a short packet. - bool atEnd = false; - if(len >= usbtmc_state.transfer_size_remaining || shortPacket) - { - atEnd = true; - TU_VERIFY(atomicChangeState(STATE_RCV, STATE_NAK)); - } - - len = tu_min32(len, usbtmc_state.transfer_size_remaining); - - usbtmc_state.transfer_size_remaining -= len; - usbtmc_state.transfer_size_sent += len; - - // App may (should?) call the wait_for_bus() command at this point - if(!tud_usbtmc_msg_data_cb(data, len, atEnd)) - { - // TODO: Go to an error state upon failure other than just stalling the EP? - return false; - } - - - return true; -} - -static bool handle_devMsgIn(void *data, size_t len) -{ - TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); - usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; - bool stateChanged = atomicChangeState(STATE_IDLE, STATE_TX_REQUESTED); - TU_VERIFY(stateChanged); - usbtmc_state.lastBulkInTag = msg->header.bTag; - usbtmc_state.transfer_size_remaining = msg->TransferSize; - usbtmc_state.transfer_size_sent = 0u; - - termCharRequested = msg->bmTransferAttributes.TermCharEnabled; - termChar = msg->TermChar; - - if(termCharRequested) - TU_VERIFY(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); - - TU_VERIFY(tud_usbtmc_msgBulkIn_request_cb(msg)); - return true; -} - -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - TU_VERIFY(result == XFER_RESULT_SUCCESS); - //uart_tx_str_sync("TMC XFER CB\r\n"); - if(usbtmc_state.state == STATE_CLEARING) { - return true; /* I think we can ignore everything here */ - } - - if(ep_addr == usbtmc_state.ep_bulk_out) - { - usbtmc_msg_generic_t *msg = NULL; - - switch(usbtmc_state.state) - { - case STATE_IDLE: - TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t)); - msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf); - uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); - TU_VERIFY(msg->header.bTag == invInvTag); - TU_VERIFY(msg->header.bTag != 0x00); - - switch(msg->header.MsgID) { - case USBTMC_MSGID_DEV_DEP_MSG_OUT: - if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) - { - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - TU_VERIFY(false); - } - break; - - case USBTMC_MSGID_DEV_DEP_MSG_IN: - TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); - break; - -#if (CFG_TUD_USBTMC_ENABLE_488) - case USBTMC_MSGID_USB488_TRIGGER: - // Spec says we halt the EP if we didn't declare we support it. - TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg)); - - break; -#endif - case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: - case USBTMC_MSGID_VENDOR_SPECIFIC_IN: - default: - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - TU_VERIFY(false); - return false; - } - return true; - - case STATE_RCV: - if(!handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes)) - { - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - TU_VERIFY(false); - } - return true; - - case STATE_ABORTING_BULK_OUT: - TU_VERIFY(false); - return false; // Should be stalled by now, shouldn't have received a packet. - - case STATE_TX_REQUESTED: - case STATE_TX_INITIATED: - case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_IN_SHORTED: - case STATE_ABORTING_BULK_IN_ABORTED: - default: - TU_VERIFY(false); - } - } - else if(ep_addr == usbtmc_state.ep_bulk_in) - { - switch(usbtmc_state.state) { - case STATE_TX_SHORTED: - TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); - TU_VERIFY(tud_usbtmc_msgBulkIn_complete_cb()); - break; - - case STATE_TX_INITIATED: - if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf)) - { - // FIXME! This removes const below! - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, - (void*)(uintptr_t) usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf))); - usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf); - usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf); - } - else // last packet - { - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen) ); - if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 )) - { - usbtmc_state.state = STATE_TX_SHORTED; - } - } - return true; - - case STATE_ABORTING_BULK_IN: - // need to send short packet (ZLP?) - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); - usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; - return true; - - case STATE_ABORTING_BULK_IN_SHORTED: - /* Done. :)*/ - usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; - return true; - - default: - TU_ASSERT(false); - return false; - } - } - else if (ep_addr == usbtmc_state.ep_int_in) { - // Good? - return true; - } - return false; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to do with DATA and ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; - - uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; -#if (CFG_TUD_USBTMC_ENABLE_488) - uint8_t bTag; -#endif - - if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && - (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && - (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && - (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) - { - uint32_t ep_addr = (request->wIndex); - - if(ep_addr == usbtmc_state.ep_bulk_out) - { - criticalEnter(); - usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us - criticalLeave(); - tud_usbtmc_bulkOut_clearFeature_cb(); - } - else if (ep_addr == usbtmc_state.ep_bulk_in) - { - tud_usbtmc_bulkIn_clearFeature_cb(); - } - else - { - return false; - } - return true; - } - - // Otherwise, we only handle class requests. - if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) - { - return false; - } - - // Verification that we own the interface is unneeded since it's been routed to us specifically. - - switch(request->bRequest) - { - // USBTMC required requests - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: - { - usbtmc_initiate_abort_rsp_t rsp = { - .bTag = usbtmc_state.lastBulkOutTag, - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - - // wValue is the requested bTag to abort - if(usbtmc_state.state != STATE_RCV) - { - rsp.USBTMC_status = USBTMC_STATUS_FAILED; - } - else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0x7Fu)) - { - rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - // Check if we've queued a short packet - criticalEnter(); - usbtmc_state.state = STATE_ABORTING_BULK_OUT; - criticalLeave(); - TU_VERIFY(tud_usbtmc_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: - { - usbtmc_check_abort_bulk_rsp_t rsp = { - .USBTMC_status = USBTMC_STATUS_SUCCESS, - .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: - { - usbtmc_initiate_abort_rsp_t rsp = { - .bTag = usbtmc_state.lastBulkInTag, - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); - // wValue is the requested bTag to abort - if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && - usbtmc_state.lastBulkInTag == (request->wValue & 0x7Fu)) - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.transfer_size_remaining = 0u; - // Check if we've queued a short packet - criticalEnter(); - usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) == 0) ? - STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; - criticalLeave(); - if(usbtmc_state.transfer_size_sent == 0) - { - // Send short packet, nothing is in the buffer yet - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf,(uint16_t)0u)); - usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; - } - TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); - } - else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) - { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... - rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_FAILED; - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 8u); - - usbtmc_check_abort_bulk_rsp_t rsp = - { - .USBTMC_status = USBTMC_STATUS_FAILED, - .bmAbortBulkIn = - { - .BulkInFifoBytes = (usbtmc_state.state != STATE_ABORTING_BULK_IN_ABORTED) - }, - .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, - }; - TU_VERIFY(tud_usbtmc_check_abort_bulk_in_cb(&rsp)); - criticalEnter(); - switch(usbtmc_state.state) - { - case STATE_ABORTING_BULK_IN_ABORTED: - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.state = STATE_IDLE; - break; - case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_OUT: - rsp.USBTMC_status = USBTMC_STATUS_PENDING; - break; - default: - break; - } - criticalLeave(); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - - return true; - } - - case USBTMC_bREQUEST_INITIATE_CLEAR: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the - // control endpoint response shown in Table 31, and clear all input buffers and output buffers. - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - usbtmc_state.transfer_size_remaining = 0; - criticalEnter(); - usbtmc_state.state = STATE_CLEARING; - criticalLeave(); - TU_VERIFY(tud_usbtmc_initiate_clear_cb(&tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); - return true; - } - - case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; - TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); - - if(usbd_edpt_busy(rhport, usbtmc_state.ep_bulk_in)) - { - // Stuff stuck in TX buffer? - clearStatusRsp.bmClear.BulkInFifoBytes = 1; - clearStatusRsp.USBTMC_status = USBTMC_STATUS_PENDING; - } - else - { - // Let app check if it's clear - TU_VERIFY(tud_usbtmc_check_clear_cb(&clearStatusRsp)); - } - if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) - { - criticalEnter(); - usbtmc_state.state = STATE_IDLE; - criticalLeave(); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); - return true; - } - - case USBTMC_bREQUEST_GET_CAPABILITIES: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(*(usbtmc_state.capabilities))); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); - return true; - } - // USBTMC Optional Requests - - case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); - TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse); - TU_VERIFY(tud_usbtmc_indicator_pulse_cb(request, &tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); - return true; - } -#if (CFG_TUD_USBTMC_ENABLE_488) - - // USB488 required requests - case USB488_bREQUEST_READ_STATUS_BYTE: - { - usbtmc_read_stb_rsp_488_t rsp; - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface - - bTag = request->wValue & 0x7F; - TU_VERIFY(request->bmRequestType == 0xA1); - TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero - TU_VERIFY(bTag >= 0x02 && bTag <= 127); - TU_VERIFY(request->wIndex == usbtmc_state.itf_id); - TU_VERIFY(request->wLength == 0x0003); - rsp.bTag = (uint8_t)bTag; - if(usbtmc_state.ep_int_in != 0) - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - rsp.statusByte = 0x00; // Use interrupt endpoint, instead. - - usbtmc_read_stb_interrupt_488_t intMsg = - { - .bNotify1 = { - .one = 1, - .bTag = bTag & 0x7Fu, - }, - .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)) - }; - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); - } - else - { - rsp.statusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); - return true; - } - // USB488 optional requests - case USB488_bREQUEST_REN_CONTROL: - case USB488_bREQUEST_GO_TO_LOCAL: - case USB488_bREQUEST_LOCAL_LOCKOUT: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(false); - return false; - } -#endif - - default: - TU_VERIFY(false); - return false; - } - TU_VERIFY(false); -} - -#endif /* CFG_TUD_TSMC */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h deleted file mode 100644 index 0549a1569..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/usbtmc/usbtmc_device.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 N Conrad - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef CLASS_USBTMC_USBTMC_DEVICE_H_ -#define CLASS_USBTMC_USBTMC_DEVICE_H_ - -#include "usbtmc.h" - -// Enable 488 mode by default -#if !defined(CFG_TUD_USBTMC_ENABLE_488) -#define CFG_TUD_USBTMC_ENABLE_488 (1) -#endif - -// USB spec says that full-speed must be 8,16,32, or 64. -// However, this driver implementation requires it to be >=32 -#define USBTMCD_MAX_PACKET_SIZE (64u) - -/*********************************************** - * Functions to be implemeted by the class implementation - */ - -// In order to proceed, app must call call tud_usbtmc_start_bus_read(rhport) during or soon after: -// * tud_usbtmc_open_cb -// * tud_usbtmc_msg_data_cb -// * tud_usbtmc_msgBulkIn_complete_cb -// * tud_usbtmc_msg_trigger_cb -// * (successful) tud_usbtmc_check_abort_bulk_out_cb -// * (successful) tud_usbtmc_check_abort_bulk_in_cb -// * (successful) tud_usmtmc_bulkOut_clearFeature_cb - -#if (CFG_TUD_USBTMC_ENABLE_488) -usbtmc_response_capabilities_488_t const * tud_usbtmc_get_capabilities_cb(void); -#else -usbtmc_response_capabilities_t const * tud_usbtmc_get_capabilities_cb(void); -#endif - -void tud_usbtmc_open_cb(uint8_t interface_id); - -bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); -// transfer_complete does not imply that a message is complete. -bool tud_usbtmc_msg_data_cb( void *data, size_t len, bool transfer_complete); -void tud_usbtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer - -bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); -bool tud_usbtmc_msgBulkIn_complete_cb(void); -void tud_usbtmc_bulkIn_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer - -bool tud_usbtmc_initiate_abort_bulk_in_cb(uint8_t *tmcResult); -bool tud_usbtmc_initiate_abort_bulk_out_cb(uint8_t *tmcResult); -bool tud_usbtmc_initiate_clear_cb(uint8_t *tmcResult); - -bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp); -bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp); - -// Indicator pulse should be 0.5 to 1.0 seconds long -TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult); - -#if (CFG_TUD_USBTMC_ENABLE_488) -uint8_t tud_usbtmc_get_stb_cb(uint8_t *tmcResult); -TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg); -//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb(); -#endif - -/******************************************* - * Called from app - * - * We keep a reference to the buffer, so it MUST not change until the app is - * notified that the transfer is complete. - ******************************************/ - -bool tud_usbtmc_transmit_dev_msg_data( - const void * data, size_t len, - bool endOfMessage, bool usingTermChar); - -bool tud_usbtmc_start_bus_read(void); - - -/* "callbacks" from USB device core */ - -uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -void usbtmcd_reset_cb(uint8_t rhport); -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -void usbtmcd_init_cb(void); - -/************************************************************ - * USBTMC Descriptor Templates - *************************************************************/ - - -#endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c deleted file mode 100644 index 8a4ca1d2e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VENDOR) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "vendor_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - - uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE]; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; -#endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_VENDOR_EPSIZE]; -} vendord_interface_t; - -CFG_TUSB_MEM_SECTION static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR]; - -#define ITF_MEM_RESET_SIZE offsetof(vendord_interface_t, rx_ff) - - -bool tud_vendor_n_mounted (uint8_t itf) -{ - return _vendord_itf[itf].ep_in && _vendord_itf[itf].ep_out; -} - -uint32_t tud_vendor_n_available (uint8_t itf) -{ - return tu_fifo_count(&_vendord_itf[itf].rx_ff); -} - -bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) -{ - return tu_fifo_peek(&_vendord_itf[itf].rx_ff, u8); -} - -//--------------------------------------------------------------------+ -// Read API -//--------------------------------------------------------------------+ -static void _prep_out_transaction (vendord_interface_t* p_itf) -{ - // skip if previous transfer not complete - if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_itf->ep_out) ) return; - - // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t max_read = tu_fifo_remaining(&p_itf->rx_ff); - if ( max_read >= CFG_TUD_VENDOR_EPSIZE ) - { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_out, p_itf->epout_buf, CFG_TUD_VENDOR_EPSIZE); - } -} - -uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_itf->rx_ff, buffer, bufsize); - _prep_out_transaction(p_itf); - return num_read; -} - -void tud_vendor_n_read_flush (uint8_t itf) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - tu_fifo_clear(&p_itf->rx_ff); - _prep_out_transaction(p_itf); -} - -//--------------------------------------------------------------------+ -// Write API -//--------------------------------------------------------------------+ -static bool maybe_transmit(vendord_interface_t* p_itf) -{ - // skip if previous transfer not complete - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_itf->ep_in) ); - - uint16_t count = tu_fifo_read_n(&p_itf->tx_ff, p_itf->epin_buf, CFG_TUD_VENDOR_EPSIZE); - if (count > 0) - { - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_itf->ep_in, p_itf->epin_buf, count) ); - } - return true; -} - -uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize) -{ - vendord_interface_t* p_itf = &_vendord_itf[itf]; - uint16_t ret = tu_fifo_write_n(&p_itf->tx_ff, buffer, bufsize); - maybe_transmit(p_itf); - return ret; -} - -uint32_t tud_vendor_n_write_available (uint8_t itf) -{ - return tu_fifo_remaining(&_vendord_itf[itf].tx_ff); -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void vendord_init(void) -{ - tu_memclr(_vendord_itf, sizeof(_vendord_itf)); - - for(uint8_t i=0; irx_ff, p_itf->rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, 1, false); - tu_fifo_config(&p_itf->tx_ff, p_itf->tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, 1, false); - -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_itf->rx_ff, NULL, osal_mutex_create(&p_itf->rx_ff_mutex)); - tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex), NULL); -#endif - } -} - -void vendord_reset(uint8_t rhport) -{ - (void) rhport; - - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&p_itf->tx_ff); - } -} - -uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) -{ - TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); - - uint8_t const * p_desc = tu_desc_next(desc_itf); - uint8_t const * desc_end = p_desc + max_len; - - // Find available interface - vendord_interface_t* p_vendor = NULL; - for(uint8_t i=0; iitf_num = desc_itf->bInterfaceNumber; - if (desc_itf->bNumEndpoints) - { - // skip non-endpoint descriptors - while ( (TUSB_DESC_ENDPOINT != tu_desc_type(p_desc)) && (p_desc < desc_end) ) - { - p_desc = tu_desc_next(p_desc); - } - - // Open endpoint pair with usbd helper - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); - - p_desc += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - - // Prepare for incoming data - if ( p_vendor->ep_out ) - { - TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)), 0); - } - - if ( p_vendor->ep_in ) maybe_transmit(p_vendor); - } - - return (uintptr_t) p_desc - (uintptr_t) desc_itf; -} - -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) result; - - uint8_t itf = 0; - vendord_interface_t* p_itf = _vendord_itf; - - for ( ; ; itf++, p_itf++) - { - if (itf >= TU_ARRAY_SIZE(_vendord_itf)) return false; - - if ( ( ep_addr == p_itf->ep_out ) || ( ep_addr == p_itf->ep_in ) ) break; - } - - if ( ep_addr == p_itf->ep_out ) - { - // Receive new data - tu_fifo_write_n(&p_itf->rx_ff, p_itf->epout_buf, xferred_bytes); - - // Invoked callback if any - if (tud_vendor_rx_cb) tud_vendor_rx_cb(itf); - - _prep_out_transaction(p_itf); - } - else if ( ep_addr == p_itf->ep_in ) - { - // Send complete, try to send more if possible - maybe_transmit(p_itf); - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h deleted file mode 100644 index d71c2a3e9..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_device.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_VENDOR_DEVICE_H_ -#define _TUSB_VENDOR_DEVICE_H_ - -#include "common/tusb_common.h" - -#ifndef CFG_TUD_VENDOR_EPSIZE -#define CFG_TUD_VENDOR_EPSIZE 64 -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) -//--------------------------------------------------------------------+ -bool tud_vendor_n_mounted (uint8_t itf); - -uint32_t tud_vendor_n_available (uint8_t itf); -uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); -bool tud_vendor_n_peek (uint8_t itf, uint8_t* ui8); -void tud_vendor_n_read_flush (uint8_t itf); - -uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); -uint32_t tud_vendor_n_write_available (uint8_t itf); - -static inline -uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str); - -//--------------------------------------------------------------------+ -// Application API (Single Port) -//--------------------------------------------------------------------+ -static inline bool tud_vendor_mounted (void); -static inline uint32_t tud_vendor_available (void); -static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); -static inline bool tud_vendor_peek (uint8_t* ui8); -static inline void tud_vendor_read_flush (void); -static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); -static inline uint32_t tud_vendor_write_str (char const* str); -static inline uint32_t tud_vendor_write_available (void); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received new data -TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t itf); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ - -static inline uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str) -{ - return tud_vendor_n_write(itf, str, strlen(str)); -} - -static inline bool tud_vendor_mounted (void) -{ - return tud_vendor_n_mounted(0); -} - -static inline uint32_t tud_vendor_available (void) -{ - return tud_vendor_n_available(0); -} - -static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) -{ - return tud_vendor_n_read(0, buffer, bufsize); -} - -static inline bool tud_vendor_peek (uint8_t* ui8) -{ - return tud_vendor_n_peek(0, ui8); -} - -static inline void tud_vendor_read_flush(void) -{ - tud_vendor_n_read_flush(0); -} - -static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) -{ - return tud_vendor_n_write(0, buffer, bufsize); -} - -static inline uint32_t tud_vendor_write_str (char const* str) -{ - return tud_vendor_n_write_str(0, str); -} - -static inline uint32_t tud_vendor_write_available (void) -{ - return tud_vendor_n_write_available(0); -} - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void vendord_init(void); -void vendord_reset(uint8_t rhport); -uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_VENDOR_DEVICE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c deleted file mode 100644 index 1e28e9af4..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_VENDOR) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "host/usbh.h" -#include "vendor_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -custom_interface_info_t custom_interface[CFG_TUH_DEVICE_MAX]; - -static tusb_error_t cush_validate_paras(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) -{ - if ( !tusbh_custom_is_mounted(dev_addr, vendor_id, product_id) ) - { - return TUSB_ERROR_DEVICE_NOT_READY; - } - - TU_ASSERT( p_buffer != NULL && length != 0, TUSB_ERROR_INVALID_PARA); - - return TUSB_ERROR_NONE; -} -//--------------------------------------------------------------------+ -// APPLICATION API (need to check parameters) -//--------------------------------------------------------------------+ -tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length) -{ - TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_buffer, length) ); - - if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_in) ) - { - return TUSB_ERROR_INTERFACE_IS_BUSY; - } - - (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length) -{ - TU_ASSERT_ERR( cush_validate_paras(dev_addr, vendor_id, product_id, p_data, length) ); - - if ( !hcd_pipe_is_idle(custom_interface[dev_addr-1].pipe_out) ) - { - return TUSB_ERROR_INTERFACE_IS_BUSY; - } - - (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// USBH-CLASS API -//--------------------------------------------------------------------+ -void cush_init(void) -{ - tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUH_DEVICE_MAX); -} - -tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) -{ - // FIXME quick hack to test lpc1k custom class with 2 bulk endpoints - uint8_t const *p_desc = (uint8_t const *) p_interface_desc; - p_desc = tu_desc_next(p_desc); - - //------------- Bulk Endpoints Descriptor -------------// - for(uint32_t i=0; i<2; i++) - { - tusb_desc_endpoint_t const *p_endpoint = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint->bDescriptorType, TUSB_ERROR_INVALID_PARA); - - pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_IN_MASK ) ? - &custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out; - *p_pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); - TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); - - p_desc = tu_desc_next(p_desc); - } - - (*p_length) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - return TUSB_ERROR_NONE; -} - -void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event) -{ - -} - -void cush_close(uint8_t dev_addr) -{ - tusb_error_t err1, err2; - custom_interface_info_t * p_interface = &custom_interface[dev_addr-1]; - - // TODO re-consider to check pipe valid before calling pipe_close - if( pipehandle_is_valid( p_interface->pipe_in ) ) - { - err1 = hcd_pipe_close( p_interface->pipe_in ); - } - - if ( pipehandle_is_valid( p_interface->pipe_out ) ) - { - err2 = hcd_pipe_close( p_interface->pipe_out ); - } - - tu_memclr(p_interface, sizeof(custom_interface_info_t)); - - TU_ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 ); -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h deleted file mode 100644 index 07fa56c61..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/vendor/vendor_host.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_VENDOR_HOST_H_ -#define _TUSB_VENDOR_HOST_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -typedef struct { - pipe_handle_t pipe_in; - pipe_handle_t pipe_out; -}custom_interface_info_t; - -//--------------------------------------------------------------------+ -// USBH-CLASS DRIVER API -//--------------------------------------------------------------------+ -static inline bool tusbh_custom_is_mounted(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id) -{ - (void) vendor_id; // TODO check this later - (void) product_id; -// return (tusbh_device_get_mounted_class_flag(dev_addr) & TU_BIT(TUSB_CLASS_MAPPED_INDEX_END-1) ) != 0; - return false; -} - -tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length); -tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void const * p_data, uint16_t length); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void cush_init(void); -tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event); -void cush_close(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_VENDOR_HOST_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h deleted file mode 100644 index 844746546..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video.h +++ /dev/null @@ -1,480 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Koji KITAYAMA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_VIDEO_H_ -#define TUSB_VIDEO_H_ - -#include "common/tusb_common.h" - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_PRIMARIES_UNDEFINED = 0x00, - VIDEO_COLOR_PRIMARIES_BT709, // sRGB (default) - VIDEO_COLOR_PRIMARIES_BT470_2M, - VIDEO_COLOR_PRIMARIES_BT470_2BG, - VIDEO_COLOR_PRIMARIES_SMPTE170M, - VIDEO_COLOR_PRIMARIES_SMPTE240M, -} video_color_primaries_t; - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_XFER_CH_UNDEFINED = 0x00, - VIDEO_COLOR_XFER_CH_BT709, // default - VIDEO_COLOR_XFER_CH_BT470_2M, - VIDEO_COLOR_XFER_CH_BT470_2BG, - VIDEO_COLOR_XFER_CH_SMPTE170M, - VIDEO_COLOR_XFER_CH_SMPTE240M, - VIDEO_COLOR_XFER_CH_LINEAR, - VIDEO_COLOR_XFER_CH_SRGB, -} video_color_transfer_characteristics_t; - -// Table 3-19 Color Matching Descriptor -typedef enum { - VIDEO_COLOR_COEF_UNDEFINED = 0x00, - VIDEO_COLOR_COEF_BT709, - VIDEO_COLOR_COEF_FCC, - VIDEO_COLOR_COEF_BT470_2BG, - VIDEO_COLOR_COEF_SMPTE170M, // BT.601 default - VIDEO_COLOR_COEF_SMPTE240M, -} video_color_matrix_coefficients_t; - -/* 4.2.1.2 Request Error Code Control */ -typedef enum { - VIDEO_ERROR_NONE = 0, /* The request succeeded. */ - VIDEO_ERROR_NOT_READY, - VIDEO_ERROR_WRONG_STATE, - VIDEO_ERROR_POWER, - VIDEO_ERROR_OUT_OF_RANGE, - VIDEO_ERROR_INVALID_UNIT, - VIDEO_ERROR_INVALID_CONTROL, - VIDEO_ERROR_INVALID_REQUEST, - VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE, - VIDEO_ERROR_UNKNOWN = 0xFF, -} video_error_code_t; - -/* A.2 Interface Subclass */ -typedef enum { - VIDEO_SUBCLASS_UNDEFINED = 0x00, - VIDEO_SUBCLASS_CONTROL, - VIDEO_SUBCLASS_STREAMING, - VIDEO_SUBCLASS_INTERFACE_COLLECTION, -} video_subclass_type_t; - -/* A.3 Interface Protocol */ -typedef enum { - VIDEO_ITF_PROTOCOL_UNDEFINED = 0x00, - VIDEO_ITF_PROTOCOL_15, -} video_interface_protocol_code_t; - -/* A.5 Class-Specific VideoControl Interface Descriptor Subtypes */ -typedef enum { - VIDEO_CS_ITF_VC_UNDEFINED = 0x00, - VIDEO_CS_ITF_VC_HEADER, - VIDEO_CS_ITF_VC_INPUT_TERMINAL, - VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, - VIDEO_CS_ITF_VC_SELECTOR_UNIT, - VIDEO_CS_ITF_VC_PROCESSING_UNIT, - VIDEO_CS_ITF_VC_EXTENSION_UNIT, - VIDEO_CS_ITF_VC_ENCODING_UNIT, - VIDEO_CS_ITF_VC_MAX, -} video_cs_vc_interface_subtype_t; - -/* A.6 Class-Specific VideoStreaming Interface Descriptor Subtypes */ -typedef enum { - VIDEO_CS_ITF_VS_UNDEFINED = 0x00, - VIDEO_CS_ITF_VS_INPUT_HEADER = 0x01, - VIDEO_CS_ITF_VS_OUTPUT_HEADER = 0x02, - VIDEO_CS_ITF_VS_STILL_IMAGE_FRAME = 0x03, - VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED = 0x04, - VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED = 0x05, - VIDEO_CS_ITF_VS_FORMAT_MJPEG = 0x06, - VIDEO_CS_ITF_VS_FRAME_MJPEG = 0x07, - VIDEO_CS_ITF_VS_FORMAT_MPEG2TS = 0x0A, - VIDEO_CS_ITF_VS_FORMAT_DV = 0x0C, - VIDEO_CS_ITF_VS_COLORFORMAT = 0x0D, - VIDEO_CS_ITF_VS_FORMAT_FRAME_BASED = 0x10, - VIDEO_CS_ITF_VS_FRAME_FRAME_BASED = 0x11, - VIDEO_CS_ITF_VS_FORMAT_STREAM_BASED = 0x12, - VIDEO_CS_ITF_VS_FORMAT_H264 = 0x13, - VIDEO_CS_ITF_VS_FRAME_H264 = 0x14, - VIDEO_CS_ITF_VS_FORMAT_H264_SIMULCAST = 0x15, - VIDEO_CS_ITF_VS_FORMAT_VP8 = 0x16, - VIDEO_CS_ITF_VS_FRAME_VP8 = 0x17, - VIDEO_CS_ITF_VS_FORMAT_VP8_SIMULCAST = 0x18, -} video_cs_vs_interface_subtype_t; - -/* A.7. Class-Specific Endpoint Descriptor Subtypes */ -typedef enum { - VIDEO_CS_EP_UNDEFINED = 0x00, - VIDEO_CS_EP_GENERAL, - VIDEO_CS_EP_ENDPOINT, - VIDEO_CS_EP_INTERRUPT -} video_cs_ep_subtype_t; - -/* A.8 Class-Specific Request Codes */ -typedef enum { - VIDEO_REQUEST_UNDEFINED = 0x00, - VIDEO_REQUEST_SET_CUR = 0x01, - VIDEO_REQUEST_SET_CUR_ALL = 0x11, - VIDEO_REQUEST_GET_CUR = 0x81, - VIDEO_REQUEST_GET_MIN = 0x82, - VIDEO_REQUEST_GET_MAX = 0x83, - VIDEO_REQUEST_GET_RES = 0x84, - VIDEO_REQUEST_GET_LEN = 0x85, - VIDEO_REQUEST_GET_INFO = 0x86, - VIDEO_REQUEST_GET_DEF = 0x87, - VIDEO_REQUEST_GET_CUR_ALL = 0x91, - VIDEO_REQUEST_GET_MIN_ALL = 0x92, - VIDEO_REQUEST_GET_MAX_ALL = 0x93, - VIDEO_REQUEST_GET_RES_ALL = 0x94, - VIDEO_REQUEST_GET_DEF_ALL = 0x97 -} video_control_request_t; - -/* A.9.1 VideoControl Interface Control Selectors */ -typedef enum { - VIDEO_VC_CTL_UNDEFINED = 0x00, - VIDEO_VC_CTL_VIDEO_POWER_MODE, - VIDEO_VC_CTL_REQUEST_ERROR_CODE, -} video_interface_control_selector_t; - -/* A.9.8 VideoStreaming Interface Control Selectors */ -typedef enum { - VIDEO_VS_CTL_UNDEFINED = 0x00, - VIDEO_VS_CTL_PROBE, - VIDEO_VS_CTL_COMMIT, - VIDEO_VS_CTL_STILL_PROBE, - VIDEO_VS_CTL_STILL_COMMIT, - VIDEO_VS_CTL_STILL_IMAGE_TRIGGER, - VIDEO_VS_CTL_STREAM_ERROR_CODE, - VIDEO_VS_CTL_GENERATE_KEY_FRAME, - VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT, - VIDEO_VS_CTL_SYNCH_DELAY_CONTROL, -} video_interface_streaming_selector_t; - -/* B. Terminal Types */ -typedef enum { - // Terminal - VIDEO_TT_VENDOR_SPECIFIC = 0x0100, - VIDEO_TT_STREAMING = 0x0101, - - // Input - VIDEO_ITT_VENDOR_SPECIFIC = 0x0200, - VIDEO_ITT_CAMERA = 0x0201, - VIDEO_ITT_MEDIA_TRANSPORT_INPUT = 0x0202, - - // Output - VIDEO_OTT_VENDOR_SPECIFIC = 0x0300, - VIDEO_OTT_DISPLAY = 0x0301, - VIDEO_OTT_MEDIA_TRANSPORT_OUTPUT = 0x0302, - - // External - VIDEO_ETT_VENDOR_SPEIFIC = 0x0400, - VIDEO_ETT_COMPOSITE_CONNECTOR = 0x0401, - VIDEO_ETT_SVIDEO_CONNECTOR = 0x0402, - VIDEO_ETT_COMPONENT_CONNECTOR = 0x0403, -} video_terminal_type_t; - -//--------------------------------------------------------------------+ -// Descriptors -//--------------------------------------------------------------------+ - -/* 2.3.4.2 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint16_t bcdUVC; - uint16_t wTotalLength; - uint32_t dwClockFrequency; - uint8_t bInCollection; - uint8_t baInterfaceNr[]; -} tusb_desc_cs_video_ctl_itf_hdr_t; - -/* 2.4.3.3 */ -typedef struct TU_ATTR_PACKED { - uint8_t bHeaderLength; - union { - uint8_t bmHeaderInfo; - struct { - uint8_t FrameID: 1; - uint8_t EndOfFrame: 1; - uint8_t PresentationTime: 1; - uint8_t SourceClockReference: 1; - uint8_t PayloadSpecific: 1; - uint8_t StillImage: 1; - uint8_t Error: 1; - uint8_t EndOfHeader: 1; - }; - }; -} tusb_video_payload_header_t; - -/* 3.9.2.1 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - uint8_t bmInfo; - uint8_t bTerminalLink; - uint8_t bStillCaptureMethod; - uint8_t bTriggerSupport; - uint8_t bTriggerUsage; - uint8_t bControlSize; - uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_in_hdr_t; - -/* 3.9.2.2 */ -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - uint8_t bTerminalLink; - uint8_t bControlSize; - uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_out_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - union { - struct { - uint8_t bmInfo; - uint8_t bTerminalLink; - uint8_t bStillCaptureMethod; - uint8_t bTriggerSupport; - uint8_t bTriggerUsage; - uint8_t bControlSize; - uint8_t bmaControls[]; - } input; - struct { - uint8_t bEndpointAddress; - uint8_t bTerminalLink; - uint8_t bControlSize; - uint8_t bmaControls[]; - } output; - }; -} tusb_desc_cs_video_stm_itf_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; - uint8_t guidFormat[16]; - uint8_t bBitsPerPixel; - uint8_t bDefaultFrameIndex; - uint8_t bAspectRatioX; - uint8_t bAspectRatioY; - uint8_t bmInterlaceFlags; - uint8_t bCopyProtect; -} tusb_desc_cs_video_fmt_uncompressed_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFrameIndex; - uint8_t bmCapabilities; - uint16_t wWidth; - uint16_t wHeight; - uint32_t dwMinBitRate; - uint32_t dwMaxBitRate; - uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ - uint32_t dwDefaultFrameInterval; - uint8_t bFrameIntervalType; - uint32_t dwFrameInterval[]; -} tusb_desc_cs_video_frm_uncompressed_t; - -//--------------------------------------------------------------------+ -// Requests -//--------------------------------------------------------------------+ - -/* 4.3.1.1 */ -typedef struct TU_ATTR_PACKED { - union { - uint8_t bmHint; - struct TU_ATTR_PACKED { - uint16_t dwFrameInterval: 1; - uint16_t wKeyFrameRatel : 1; - uint16_t wPFrameRate : 1; - uint16_t wCompQuality : 1; - uint16_t wCompWindowSize: 1; - uint16_t : 0; - } Hint; - }; - uint8_t bFormatIndex; - uint8_t bFrameIndex; - uint32_t dwFrameInterval; - uint16_t wKeyFrameRate; - uint16_t wPFrameRate; - uint16_t wCompQuality; - uint16_t wCompWindowSize; - uint16_t wDelay; - uint32_t dwMaxVideoFrameSize; - uint32_t dwMaxPayloadTransferSize; - uint32_t dwClockFrequency; - union { - uint8_t bmFramingInfo; - struct TU_ATTR_PACKED { - uint8_t FrameID : 1; - uint8_t EndOfFrame: 1; - uint8_t EndOfSlice: 1; - uint8_t : 0; - } FramingInfo; - }; - uint8_t bPreferedVersion; - uint8_t bMinVersion; - uint8_t bMaxVersion; - uint8_t bUsage; - uint8_t bBitDepthLuma; - uint8_t bmSettings; - uint8_t bMaxNumberOfRefFramesPlus1; - uint16_t bmRateControlModes; - uint64_t bmLayoutPerStream; -} video_probe_and_commit_control_t; - -TU_VERIFY_STATIC( sizeof(video_probe_and_commit_control_t) == 48, "size is not correct"); - -#define TUD_VIDEO_DESC_IAD_LEN 8 -#define TUD_VIDEO_DESC_STD_VC_LEN 9 -#define TUD_VIDEO_DESC_CS_VC_LEN 12 -#define TUD_VIDEO_DESC_INPUT_TERM_LEN 8 -#define TUD_VIDEO_DESC_OUTPUT_TERM_LEN 9 -#define TUD_VIDEO_DESC_CAMERA_TERM_LEN 18 -#define TUD_VIDEO_DESC_STD_VS_LEN 9 -#define TUD_VIDEO_DESC_CS_VS_IN_LEN 13 -#define TUD_VIDEO_DESC_CS_VS_OUT_LEN 9 -#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN 27 -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN 38 -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN 26 -#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN 6 - -/* 2.2 compression formats */ -#define TUD_VIDEO_GUID_YUY2 0x59,0x55,0x59,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_NV12 0x4E,0x56,0x31,0x32,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_M420 0x4D,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 -#define TUD_VIDEO_GUID_I420 0x49,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 - -#define TUD_VIDEO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_VIDEO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, \ - _firstitfs, _nitfs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_INTERFACE_COLLECTION, \ - VIDEO_ITF_PROTOCOL_UNDEFINED, _stridx - -#define TUD_VIDEO_DESC_STD_VC(_itfnum, _nEPs, _stridx) \ - TUD_VIDEO_DESC_STD_VC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, \ - _nEPs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_CONTROL, VIDEO_ITF_PROTOCOL_15, _stridx - -/* 3.7.2 */ -#define TUD_VIDEO_DESC_CS_VC(_bcdUVC, _totallen, _clkfreq, ...) \ - TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_HEADER, \ - U16_TO_U8S_LE(_bcdUVC), U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VC_LEN + (TU_ARGS_NUM(__VA_ARGS__))), \ - U32_TO_U8S_LE(_clkfreq), TU_ARGS_NUM(__VA_ARGS__), __VA_ARGS__ - -/* 3.7.2.1 */ -#define TUD_VIDEO_DESC_INPUT_TERM(_tid, _tt, _at, _stridx) \ - TUD_VIDEO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(_tt), _at, _stridx - -/* 3.7.2.2 */ -#define TUD_VIDEO_DESC_OUTPUT_TERM(_tid, _tt, _at, _srcid, _stridx) \ - TUD_VIDEO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(_tt), _at, _srcid, _stridx - -/* 3.7.2.3 */ -#define TUD_VIDEO_DESC_CAMERA_TERM(_tid, _at, _stridx, _focal_min, _focal_max, _focal, _ctls) \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VC_INPUT_TERMINAL, \ - _tid, U16_TO_U8S_LE(VIDEO_ITT_CAMERA), _at, _stridx, \ - U16_TO_U8S_LE(_focal_min), U16_TO_U8S_LE(_focal_max), U16_TO_U8S_LE(_focal), 3, \ - TU_U32_BYTE0(_ctls), TU_U32_BYTE1(_ctls), TU_U32_BYTE2(_ctls) - -/* 3.9.1 */ -#define TUD_VIDEO_DESC_STD_VS(_itfnum, _alt, _epn, _stridx) \ - TUD_VIDEO_DESC_STD_VS_LEN, TUSB_DESC_INTERFACE, _itfnum, _alt, \ - _epn, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_STREAMING, VIDEO_ITF_PROTOCOL_15, _stridx - -/* 3.9.2.1 */ -#define TUD_VIDEO_DESC_CS_VS_INPUT(_numfmt, _totallen, _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, ...) \ - TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ - VIDEO_CS_ITF_VS_INPUT_HEADER, _numfmt, \ - U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_IN_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ - _ep, _inf, _termlnk, _sticaptmeth, _trgspt, _trgusg, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* 3.9.2.2 */ -#define TUD_VIDEO_DESC_CS_VS_OUTPUT(_numfmt, _totallen, _ep, _inf, _termlnk, ...) \ - TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, \ - VIDEO_CS_ITF_VS_OUTPUT_HEADER, _numfmt, \ - U16_TO_U8S_LE((_totallen) + TUD_VIDEO_DESC_CS_VS_OUT_LEN + (_numfmt) * (TU_ARGS_NUM(__VA_ARGS__))), \ - _ep, _inf, _termlnk, (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* Uncompressed 3.1.1 */ -#define TUD_VIDEO_GUID(_g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15) _g0,_g1,_g2,_g3,_g4,_g5,_g6,_g7,_g8,_g9,_g10,_g11,_g12,_g13,_g14,_g15 - -#define TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfrmdesc, \ - _guid, _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp) \ - TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, \ - _fmtidx, _numfrmdesc, TUD_VIDEO_GUID(_guid), \ - _bitsperpix, _frmidx, _asrx, _asry, _interlace, _cp - -/* Uncompressed 3.1.2 Table 3-3 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, _minfrminterval, _maxfrminterval, _frmintervalstep) \ - TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), 0, \ - U32_TO_U8S_LE(_minfrminterval), U32_TO_U8S_LE(_maxfrminterval), U32_TO_U8S_LE(_frmintervalstep) - -/* Uncompressed 3.1.2 Table 3-4 */ -#define TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \ - TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, \ - _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ - U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ - -/* 3.9.2.6 */ -#define TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(_color, _trns, _mat) \ - TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_COLORFORMAT, \ - _color, _trns, _mat - -/* 3.10.1.1 */ -#define TUD_VIDEO_DESC_EP_ISO(_ep, _epsize, _ep_interval) \ - 7, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS,\ - U16_TO_U8S_LE(_epsize), _ep_interval - -/* 3.10.1.2 */ -#define TUD_VIDEO_DESC_EP_BULK(_ep, _epsize, _ep_interval) \ - 7, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), _ep_interval - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c deleted file mode 100644 index eeb068197..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.c +++ /dev/null @@ -1,1149 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Koji KITAYAMA - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VIDEO && CFG_TUD_VIDEO_STREAMING) - -#include "device/usbd.h" -#include "device/usbd_pvt.h" - -#include "video_device.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct { - tusb_desc_interface_t std; - tusb_desc_cs_video_ctl_itf_hdr_t ctl; -} tusb_desc_vc_itf_t; - -typedef struct { - tusb_desc_interface_t std; - tusb_desc_cs_video_stm_itf_hdr_t stm; -} tusb_desc_vs_itf_t; - -typedef union { - tusb_desc_cs_video_ctl_itf_hdr_t ctl; - tusb_desc_cs_video_stm_itf_hdr_t stm; -} tusb_desc_video_itf_hdr_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bEntityId; -} tusb_desc_cs_video_entity_itf_t; - -/* video streaming interface */ -typedef struct TU_ATTR_PACKED { - uint8_t index_vc; /* index of bound video control interface */ - uint8_t index_vs; /* index from the video control interface */ - struct { - uint16_t beg; /* Offset of the begging of video streaming interface descriptor */ - uint16_t end; /* Offset of the end of video streaming interface descriptor */ - uint16_t cur; /* Offset of the current settings */ - uint16_t ep[2]; /* Offset of endpoint descriptors. 0: streaming, 1: still capture */ - } desc; - uint8_t *buffer; /* frame buffer. assume linear buffer. no support for stride access */ - uint32_t bufsize; /* frame buffer size */ - uint32_t offset; /* offset for the next payload transfer */ - uint32_t max_payload_transfer_size; - uint8_t error_code;/* error code */ - /*------------- From this point, data is not cleared by bus reset -------------*/ - CFG_TUSB_MEM_ALIGN uint8_t ep_buf[CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE]; /* EP transfer buffer for streaming */ -} videod_streaming_interface_t; - -/* video control interface */ -typedef struct TU_ATTR_PACKED { - void const *beg; /* The head of the first video control interface descriptor */ - uint16_t len; /* Byte length of the descriptors */ - uint16_t cur; /* offset for current video control interface */ - uint8_t stm[CFG_TUD_VIDEO_STREAMING]; /* Indices of streaming interface */ - uint8_t error_code; /* error code */ - uint8_t power_mode; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - // CFG_TUSB_MEM_ALIGN uint8_t ctl_buf[64]; /* EP transfer buffer for interrupt transfer */ - -} videod_interface_t; - -#define ITF_STM_MEM_RESET_SIZE offsetof(videod_streaming_interface_t, ep_buf) - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static videod_interface_t _videod_itf[CFG_TUD_VIDEO]; -CFG_TUSB_MEM_SECTION static videod_streaming_interface_t _videod_streaming_itf[CFG_TUD_VIDEO_STREAMING]; - -static uint8_t const _cap_get = 0x1u; /* support for GET */ -static uint8_t const _cap_get_set = 0x3u; /* support for GET and SET */ - -/** Get interface number from the interface descriptor - * - * @param[in] desc interface descriptor - * - * @return bInterfaceNumber */ -static inline uint8_t _desc_itfnum(void const *desc) -{ - return ((uint8_t const*)desc)[2]; -} - -/** Get endpoint address from the endpoint descriptor - * - * @param[in] desc endpoint descriptor - * - * @return bEndpointAddress */ -static inline uint8_t _desc_ep_addr(void const *desc) -{ - return ((uint8_t const*)desc)[2]; -} - -/** Get instance of streaming interface - * - * @param[in] ctl_idx instance number of video control - * @param[in] stm_idx index number of streaming interface - * - * @return instance */ -static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - videod_interface_t *ctl = &_videod_itf[ctl_idx]; - if (!ctl->beg) return NULL; - videod_streaming_interface_t *stm = &_videod_streaming_itf[ctl->stm[stm_idx]]; - if (!stm->desc.beg) return NULL; - return stm; -} - -static tusb_desc_vc_itf_t const* _get_desc_vc(videod_interface_t const *self) -{ - return (tusb_desc_vc_itf_t const *)(self->beg + self->cur); -} - -static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const *self) -{ - if (!self->desc.cur) return NULL; - void const *desc = _videod_itf[self->index_vc].beg; - return (tusb_desc_vs_itf_t const*)(desc + self->desc.cur); -} - -/** Find the first descriptor of a given type - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] desc_type The target descriptor type. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc(void const *beg, void const *end, uint_fast8_t desc_type) -{ - void const *cur = beg; - while ((cur < end) && (desc_type != tu_desc_type(cur))) { - cur = tu_desc_next(cur); - } - return cur; -} - -/** Find the first descriptor specified by the arguments - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] desc_type The target descriptor type - * @param[in] element_0 The target element following the desc_type - * @param[in] element_1 The target element following the element_0 - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc_3(void const *beg, void const *end, - uint_fast8_t desc_type, - uint_fast8_t element_0, - uint_fast8_t element_1) -{ - for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, desc_type)) { - uint8_t const *p = (uint8_t const *)cur; - if ((p[2] == element_0) && (p[3] == element_1)) { - return cur; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Return the next interface descriptor which has another interface number. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _next_desc_itf(void const *beg, void const *end) -{ - void const *cur = beg; - uint_fast8_t itfnum = ((tusb_desc_interface_t const*)cur)->bInterfaceNumber; - while ((cur < end) && - (itfnum == ((tusb_desc_interface_t const*)cur)->bInterfaceNumber)) { - cur = _find_desc(tu_desc_next(cur), end, TUSB_DESC_INTERFACE); - } - return cur; -} - -/** Find the first interface descriptor with the specified interface number and alternate setting number. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * @param[in] itfnum The target interface number. - * @param[in] altnum The target alternate setting number. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static inline void const* _find_desc_itf(void const *beg, void const *end, uint_fast8_t itfnum, uint_fast8_t altnum) -{ - return _find_desc_3(beg, end, TUSB_DESC_INTERFACE, itfnum, altnum); -} - -/** Find the first endpoint descriptor belonging to the current interface descriptor. - * - * The search range is from `beg` to `end` or the next interface descriptor. - * - * @param[in] beg The head of descriptor byte array. - * @param[in] end The tail of descriptor byte array. - * - * @return The pointer for endpoint descriptor. - * @retval end did not found endpoint descriptor */ -static void const* _find_desc_ep(void const *beg, void const *end) -{ - for (void const *cur = beg; cur < end; cur = tu_desc_next(cur)) { - uint_fast8_t desc_type = tu_desc_type(cur); - if (TUSB_DESC_ENDPOINT == desc_type) return cur; - if (TUSB_DESC_INTERFACE == desc_type) break; - } - return end; -} - -/** Find the first entity descriptor with the entity ID - * specified by the argument belonging to the current video control descriptor. - * - * @param[in] desc The video control interface descriptor. - * @param[in] entityid The target entity id. - * - * @return The pointer for interface descriptor. - * @retval end did not found interface descriptor */ -static void const* _find_desc_entity(void const *desc, uint_fast8_t entityid) -{ - tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const*)desc; - void const *beg = vc; - void const *end = beg + vc->std.bLength + vc->ctl.wTotalLength; - for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, TUSB_DESC_CS_INTERFACE)) { - tusb_desc_cs_video_entity_itf_t const *itf = (tusb_desc_cs_video_entity_itf_t const *)cur; - if ((VIDEO_CS_ITF_VC_INPUT_TERMINAL <= itf->bDescriptorSubtype - && itf->bDescriptorSubtype < VIDEO_CS_ITF_VC_MAX) - && itf->bEntityId == entityid) { - return itf; - } - cur = tu_desc_next(cur); - } - return end; -} - -/** Return the end of the video streaming descriptor. */ -static inline void const* _end_of_streaming_descriptor(void const *desc) -{ - tusb_desc_vs_itf_t const *vs = (tusb_desc_vs_itf_t const *)desc; - return desc + vs->std.bLength + vs->stm.wTotalLength; -} - -/** Find the first format descriptor with the specified format number. */ -static inline tusb_desc_cs_video_fmt_uncompressed_t const *_find_desc_format(void const *beg, void const *end, uint_fast8_t fmtnum) -{ - return (tusb_desc_cs_video_fmt_uncompressed_t const*) - _find_desc_3(beg, end, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, fmtnum); -} - -/** Find the first frame descriptor with the specified format number. */ -static inline tusb_desc_cs_video_frm_uncompressed_t const *_find_desc_frame(void const *beg, void const *end, uint_fast8_t frmnum) -{ - return (tusb_desc_cs_video_frm_uncompressed_t const*) - _find_desc_3(beg, end, TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, frmnum); -} - -/** Set uniquely determined values to variables that have not been set - * - * @param[in,out] param Target */ -static bool _update_streaming_parameters(videod_streaming_interface_t const *stm, - video_probe_and_commit_control_t *param) -{ - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - uint_fast8_t fmtnum = param->bFormatIndex; - TU_ASSERT(fmtnum <= vs->stm.bNumFormats); - if (!fmtnum) { - if (1 < vs->stm.bNumFormats) return true; /* Need to negotiate all variables. */ - fmtnum = 1; - param->bFormatIndex = 1; - } - - /* Set the parameters determined by the format */ - param->wKeyFrameRate = 1; - param->wPFrameRate = 0; - param->wCompQuality = 1; /* 1 to 10000 */ - param->wCompWindowSize = 1; /* GOP size? */ - param->wDelay = 0; /* milliseconds */ - param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ - param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ - param->bPreferedVersion = 1; - param->bMinVersion = 1; - param->bMaxVersion = 1; - param->bUsage = 0; - param->bBitDepthLuma = 8; - - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - TU_ASSERT(fmt != end); - uint_fast8_t frmnum = param->bFrameIndex; - TU_ASSERT(frmnum <= fmt->bNumFrameDescriptors); - if (!frmnum) { - if (1 < fmt->bNumFrameDescriptors) return true; - frmnum = 1; - param->bFrameIndex = 1; - } - tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - TU_ASSERT(frm != end); - - /* Set the parameters determined by the frame */ - uint_fast32_t frame_size = param->dwMaxVideoFrameSize; - if (!frame_size) { - frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->bBitsPerPixel / 8; - param->dwMaxVideoFrameSize = frame_size; - } - - uint_fast32_t interval = param->dwFrameInterval; - if (!interval) { - if ((1 < frm->bFrameIntervalType) || - ((0 == frm->bFrameIntervalType) && (frm->dwFrameInterval[1] != frm->dwFrameInterval[0]))) { - return true; - } - interval = frm->dwFrameInterval[0]; - param->dwFrameInterval = interval; - } - uint_fast32_t interval_ms = interval / 10000; - TU_ASSERT(interval_ms); - uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; - param->dwMaxPayloadTransferSize = payload_size; - return true; -} - -/** Set the minimum, maximum, default values or resolutions to variables which need to negotiate with the host - * - * @param[in] request GET_MAX, GET_MIN, GET_RES or GET_DEF - * @param[in,out] param Target - */ -static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *stm, uint_fast8_t request, - video_probe_and_commit_control_t *param) -{ - uint_fast8_t const fmtnum = param->bFormatIndex; - if (!fmtnum) { - switch (request) { - case VIDEO_REQUEST_GET_MAX: - param->bFormatIndex = _get_desc_vs(stm)->stm.bNumFormats; - break; - case VIDEO_REQUEST_GET_MIN: - case VIDEO_REQUEST_GET_DEF: - param->bFormatIndex = 1; - break; - default: return false; - } - /* Set the parameters determined by the format */ - param->wKeyFrameRate = 1; - param->wPFrameRate = 0; - param->wCompQuality = 1; /* 1 to 10000 */ - param->wCompWindowSize = 1; /* GOP size? */ - param->wDelay = 0; /* milliseconds */ - param->dwClockFrequency = 27000000; /* same as MPEG-2 system time clock */ - param->bmFramingInfo = 0x3; /* enables FrameID and EndOfFrame */ - param->bPreferedVersion = 1; - param->bMinVersion = 1; - param->bMaxVersion = 1; - param->bUsage = 0; - param->bBitDepthLuma = 8; - return true; - } - - uint_fast8_t frmnum = param->bFrameIndex; - if (!frmnum) { - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - switch (request) { - case VIDEO_REQUEST_GET_MAX: - frmnum = fmt->bNumFrameDescriptors; - break; - case VIDEO_REQUEST_GET_MIN: - frmnum = 1; - break; - case VIDEO_REQUEST_GET_DEF: - frmnum = fmt->bDefaultFrameIndex; - break; - default: return false; - } - param->bFrameIndex = frmnum; - /* Set the parameters determined by the frame */ - tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - param->dwMaxVideoFrameSize = frm->wWidth * frm->wHeight * fmt->bBitsPerPixel / 8; - return true; - } - - if (!param->dwFrameInterval) { - tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); - void const *end = _end_of_streaming_descriptor(vs); - tusb_desc_cs_video_fmt_uncompressed_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); - tusb_desc_cs_video_frm_uncompressed_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - - uint_fast32_t interval, interval_ms; - switch (request) { - case VIDEO_REQUEST_GET_MAX: - { - uint_fast32_t min_interval, max_interval; - uint_fast8_t num_intervals = frm->bFrameIntervalType; - max_interval = num_intervals ? frm->dwFrameInterval[num_intervals - 1]: frm->dwFrameInterval[1]; - min_interval = frm->dwFrameInterval[0]; - interval = max_interval; - interval_ms = min_interval / 10000; - } - break; - case VIDEO_REQUEST_GET_MIN: - { - uint_fast32_t min_interval, max_interval; - uint_fast8_t num_intervals = frm->bFrameIntervalType; - max_interval = num_intervals ? frm->dwFrameInterval[num_intervals - 1]: frm->dwFrameInterval[1]; - min_interval = frm->dwFrameInterval[0]; - interval = min_interval; - interval_ms = max_interval / 10000; - } - break; - case VIDEO_REQUEST_GET_DEF: - interval = frm->dwDefaultFrameInterval; - interval_ms = interval / 10000; - break; - case VIDEO_REQUEST_GET_RES: - { - uint_fast8_t num_intervals = frm->bFrameIntervalType; - if (num_intervals) { - interval = 0; - } else { - interval = frm->dwFrameInterval[2]; - interval_ms = interval / 10000; - } - } - break; - default: return false; - } - param->dwFrameInterval = interval; - if (!interval) { - param->dwMaxPayloadTransferSize = 0; - } else { - uint_fast32_t frame_size = param->dwMaxVideoFrameSize; - if (!interval_ms) { - param->dwMaxPayloadTransferSize = frame_size + 2; - } else { - param->dwMaxPayloadTransferSize = (frame_size + interval_ms - 1) / interval_ms + 2; - } - } - return true; - } - return true; -} - -/** Close current video control interface. - * - * @param[in,out] self Video control interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _close_vc_itf(uint8_t rhport, videod_interface_t *self) -{ - tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); - /* The next descriptor after the class-specific VC interface header descriptor. */ - void const *cur = (void const*)vc + vc->std.bLength + vc->ctl.bLength; - /* The end of the video control interface descriptor. */ - void const *end = (void const*)vc + vc->std.bLength + vc->ctl.wTotalLength; - if (vc->std.bNumEndpoints) { - /* Find the notification endpoint descriptor. */ - cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); - TU_ASSERT(cur < end); - tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; - usbd_edpt_close(rhport, notif->bEndpointAddress); - } - self->cur = 0; - return true; -} - -/** Set the alternate setting to own video control interface. - * - * @param[in,out] self Video control interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t altnum) -{ - TU_LOG2(" open VC %d\n", altnum); - void const *beg = self->beg; - void const *end = beg + self->len; - /* The first descriptor is a video control interface descriptor. */ - void const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); - TU_LOG2(" cur %d\n", cur - beg); - TU_VERIFY(cur < end); - - tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const *)cur; - TU_LOG2(" bInCollection %d\n", vc->ctl.bInCollection); - /* Support for up to 2 streaming interfaces only. */ - TU_ASSERT(vc->ctl.bInCollection <= CFG_TUD_VIDEO_STREAMING); - - /* Update to point the end of the video control interface descriptor. */ - end = cur + vc->std.bLength + vc->ctl.wTotalLength; - /* Advance to the next descriptor after the class-specific VC interface header descriptor. */ - cur += vc->std.bLength + vc->ctl.bLength; - TU_LOG2(" bNumEndpoints %d\n", vc->std.bNumEndpoints); - /* Open the notification endpoint if it exist. */ - if (vc->std.bNumEndpoints) { - /* Support for 1 endpoint only. */ - TU_VERIFY(1 == vc->std.bNumEndpoints); - /* Find the notification endpoint descriptor. */ - cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); - TU_VERIFY(cur < end); - tusb_desc_endpoint_t const *notif = (tusb_desc_endpoint_t const *)cur; - /* Open the notification endpoint */ - TU_ASSERT(usbd_edpt_open(rhport, notif)); - } - self->cur = (void const*)vc - beg; - return true; -} - -/** Set the alternate setting to own video streaming interface. - * - * @param[in,out] stm Streaming interface context. - * @param[in] altnum The target alternate setting number. */ -static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint_fast8_t altnum) -{ - uint_fast8_t i; - TU_LOG2(" reopen VS %d\n", altnum); - void const *desc = _videod_itf[stm->index_vc].beg; - - /* Close endpoints of previous settings. */ - for (i = 0; i < TU_ARRAY_SIZE(stm->desc.ep); ++i) { - uint_fast16_t ofs_ep = stm->desc.ep[i]; - if (!ofs_ep) break; - uint_fast8_t ep_adr = _desc_ep_addr(desc + ofs_ep); - usbd_edpt_close(rhport, ep_adr); - stm->desc.ep[i] = 0; - TU_LOG2(" close EP%02x\n", ep_adr); - } - /* clear transfer management information */ - stm->buffer = NULL; - stm->bufsize = 0; - stm->offset = 0; - - /* Find a alternate interface */ - void const *beg = desc + stm->desc.beg; - void const *end = desc + stm->desc.end; - void const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum); - TU_VERIFY(cur < end); - uint_fast8_t numeps = ((tusb_desc_interface_t const *)cur)->bNumEndpoints; - TU_ASSERT(numeps <= TU_ARRAY_SIZE(stm->desc.ep)); - stm->desc.cur = cur - desc; /* Save the offset of the new settings */ - if (!altnum) { - /* initialize streaming settings */ - stm->max_payload_transfer_size = 0; - video_probe_and_commit_control_t *param = - (video_probe_and_commit_control_t *)&stm->ep_buf; - tu_memclr(param, sizeof(*param)); - return _update_streaming_parameters(stm, param); - } - /* Open endpoints of the new settings. */ - for (i = 0, cur = tu_desc_next(cur); i < numeps; ++i, cur = tu_desc_next(cur)) { - cur = _find_desc_ep(cur, end); - TU_ASSERT(cur < end); - tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)cur; - if (!stm->max_payload_transfer_size) { - video_probe_and_commit_control_t const *param = (video_probe_and_commit_control_t const*)&stm->ep_buf; - uint_fast32_t max_size = param->dwMaxPayloadTransferSize; - if ((TUSB_XFER_ISOCHRONOUS == ep->bmAttributes.xfer) && - (tu_edpt_packet_size(ep) < max_size)) - { - /* FS must be less than or equal to max packet size */ - return false; - } - /* Set the negotiated value */ - stm->max_payload_transfer_size = max_size; - } - TU_ASSERT(usbd_edpt_open(rhport, ep)); - stm->desc.ep[i] = cur - desc; - TU_LOG2(" open EP%02x\n", _desc_ep_addr(cur)); - } - /* initialize payload header */ - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->bHeaderLength = sizeof(*hdr); - hdr->bmHeaderInfo = 0; - - return true; -} - -/** Prepare the next packet payload. */ -static uint_fast16_t _prepare_in_payload(videod_streaming_interface_t *stm) -{ - uint_fast16_t remaining = stm->bufsize - stm->offset; - uint_fast16_t hdr_len = stm->ep_buf[0]; - uint_fast16_t pkt_len = stm->max_payload_transfer_size; - if (hdr_len + remaining < pkt_len) { - pkt_len = hdr_len + remaining; - } - uint_fast16_t data_len = pkt_len - hdr_len; - memcpy(&stm->ep_buf[hdr_len], stm->buffer + stm->offset, data_len); - stm->offset += data_len; - remaining -= data_len; - if (!remaining) { - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->EndOfFrame = 1; - } - return hdr_len + data_len; -} - -/** Handle a standard request to the video control interface. */ -static int handle_video_ctl_std_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - switch (request->bRequest) { - case TUSB_REQ_GET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - tusb_desc_vc_itf_t const *vc = _get_desc_vc(&_videod_itf[ctl_idx]); - TU_VERIFY(vc, VIDEO_ERROR_UNKNOWN); - - uint8_t alt_num = vc->std.bAlternateSetting; - - TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case TUSB_REQ_SET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(0 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(_close_vc_itf(rhport, &_videod_itf[ctl_idx]), VIDEO_ERROR_UNKNOWN); - TU_VERIFY(_open_vc_itf(rhport, &_videod_itf[ctl_idx], request->wValue), VIDEO_ERROR_UNKNOWN); - tud_control_status(rhport, request); - } - return VIDEO_ERROR_NONE; - - default: /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - videod_interface_t *self = &_videod_itf[ctl_idx]; - - /* 4.2.1 Interface Control Request */ - switch (TU_U16_HIGH(request->wValue)) { - case VIDEO_VC_CTL_VIDEO_POWER_MODE: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_ACK) { - if (tud_video_power_mode_cb) return tud_video_power_mode_cb(ctl_idx, self->power_mode); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VC_CTL_REQUEST_ERROR_CODE: - switch (request->bRequest) { - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - default: break; - } - - /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; -} - -static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t ctl_idx) -{ - uint_fast8_t entity_id; - switch (request->bmRequestType_bit.type) { - case TUSB_REQ_TYPE_STANDARD: - return handle_video_ctl_std_req(rhport, stage, request, ctl_idx); - - case TUSB_REQ_TYPE_CLASS: - entity_id = TU_U16_HIGH(request->wIndex); - if (!entity_id) { - return handle_video_ctl_cs_req(rhport, stage, request, ctl_idx); - } else { - TU_VERIFY(_find_desc_entity(_get_desc_vc(&_videod_itf[ctl_idx]), entity_id), VIDEO_ERROR_INVALID_REQUEST); - return VIDEO_ERROR_NONE; - } - - default: - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; - switch (request->bRequest) { - case TUSB_REQ_GET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - tusb_desc_vs_itf_t const *vs = _get_desc_vs(self); - TU_VERIFY(vs, VIDEO_ERROR_UNKNOWN); - uint8_t alt_num = vs->std.bAlternateSetting; - - TU_VERIFY(tud_control_xfer(rhport, request, &alt_num, sizeof(alt_num)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case TUSB_REQ_SET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(_open_vs_itf(rhport, self, request->wValue), VIDEO_ERROR_UNKNOWN); - tud_control_status(rhport, request); - } - return VIDEO_ERROR_NONE; - - default: /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; - } -} - -static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - (void)rhport; - videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; - - /* 4.2.1 Interface Control Request */ - switch (TU_U16_HIGH(request->wValue)) { - case VIDEO_VS_CTL_STREAM_ERROR_CODE: - switch (request->bRequest) { - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - /* TODO */ - TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_PROBE: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(sizeof(video_probe_and_commit_control_t) == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), - VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_ACK) { - TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), - VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_MIN: - case VIDEO_REQUEST_GET_MAX: - case VIDEO_REQUEST_GET_RES: - case VIDEO_REQUEST_GET_DEF: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - video_probe_and_commit_control_t tmp; - tmp = *(video_probe_and_commit_control_t*)&self->ep_buf; - TU_VERIFY(_negotiate_streaming_parameters(self, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_LEN: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); - uint16_t len = sizeof(video_probe_and_commit_control_t); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_COMMIT: - switch (request->bRequest) { - case VIDEO_REQUEST_SET_CUR: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(sizeof(video_probe_and_commit_control_t) == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } else if (stage == CONTROL_STAGE_ACK) { - TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); - if (tud_video_commit_cb) { - return tud_video_commit_cb(self->index_vc, self->index_vs, (video_probe_and_commit_control_t*)self->ep_buf); - } - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_LEN: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN); - uint16_t len = sizeof(video_probe_and_commit_control_t); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { - TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); - TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); - } - return VIDEO_ERROR_NONE; - - default: break; - } - break; - - case VIDEO_VS_CTL_STILL_PROBE: - case VIDEO_VS_CTL_STILL_COMMIT: - case VIDEO_VS_CTL_STILL_IMAGE_TRIGGER: - case VIDEO_VS_CTL_GENERATE_KEY_FRAME: - case VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT: - case VIDEO_VS_CTL_SYNCH_DELAY_CONTROL: - /* TODO */ - break; - - default: break; - } - - /* Unknown/Unsupported request */ - TU_BREAKPOINT(); - return VIDEO_ERROR_INVALID_REQUEST; -} - -static int handle_video_stm_req(uint8_t rhport, uint8_t stage, - tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ - switch (request->bmRequestType_bit.type) { - case TUSB_REQ_TYPE_STANDARD: - return handle_video_stm_std_req(rhport, stage, request, stm_idx); - - case TUSB_REQ_TYPE_CLASS: - if (TU_U16_HIGH(request->wIndex)) return VIDEO_ERROR_INVALID_REQUEST; - return handle_video_stm_cs_req(rhport, stage, request, stm_idx); - - default: return VIDEO_ERROR_INVALID_REQUEST; - } - return VIDEO_ERROR_UNKNOWN; -} - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ - -bool tud_video_n_connected(uint_fast8_t ctl_idx) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, 0); - if (stm) return true; - return false; -} - -bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); - if (!stm || !stm->desc.ep[0]) return false; - return true; -} - -bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize) -{ - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); - TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); - if (!buffer || !bufsize) return false; - videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); - if (!stm || !stm->desc.ep[0] || stm->buffer) return false; - - /* Find EP address */ - void const *desc = _videod_itf[stm->index_vc].beg; - uint_fast8_t ep_addr = 0; - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - uint_fast16_t ofs_ep = stm->desc.ep[i]; - if (!ofs_ep) continue; - ep_addr = _desc_ep_addr(desc + ofs_ep); - break; - } - if (!ep_addr) return false; - - TU_VERIFY( usbd_edpt_claim(0, ep_addr)); - /* update the packet header */ - tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf; - hdr->FrameID ^= 1; - hdr->EndOfFrame = 0; - /* update the packet data */ - stm->buffer = (uint8_t*)buffer; - stm->bufsize = bufsize; - uint_fast16_t pkt_len = _prepare_in_payload(stm); - TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm->ep_buf, pkt_len), 0); - return true; -} - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void videod_init(void) -{ - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { - videod_interface_t* ctl = &_videod_itf[i]; - tu_memclr(ctl, sizeof(*ctl)); - } - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; - tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); - } -} - -void videod_reset(uint8_t rhport) -{ - (void) rhport; - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) { - videod_interface_t* ctl = &_videod_itf[i]; - tu_memclr(ctl, sizeof(*ctl)); - } - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[i]; - tu_memclr(stm, ITF_STM_MEM_RESET_SIZE); - } -} - -uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - TU_VERIFY((TUSB_CLASS_VIDEO == itf_desc->bInterfaceClass) && - (VIDEO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass) && - (VIDEO_ITF_PROTOCOL_15 == itf_desc->bInterfaceProtocol), 0); - - /* Find available interface */ - videod_interface_t *self = NULL; - uint_fast8_t ctl_idx; - for (ctl_idx = 0; ctl_idx < CFG_TUD_VIDEO; ++ctl_idx) { - if (_videod_itf[ctl_idx].beg) continue; - self = &_videod_itf[ctl_idx]; - break; - } - TU_ASSERT(ctl_idx < CFG_TUD_VIDEO, 0); - - void const *end = (void const*)itf_desc + max_len; - self->beg = itf_desc; - self->len = max_len; - /*------------- Video Control Interface -------------*/ - TU_VERIFY(_open_vc_itf(rhport, self, 0), 0); - tusb_desc_vc_itf_t const *vc = _get_desc_vc(self); - uint_fast8_t bInCollection = vc->ctl.bInCollection; - /* Find the end of the video interface descriptor */ - void const *cur = _next_desc_itf(itf_desc, end); - for (uint_fast8_t stm_idx = 0; stm_idx < bInCollection; ++stm_idx) { - videod_streaming_interface_t *stm = NULL; - /* find free streaming interface handle */ - for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - if (_videod_streaming_itf[i].desc.beg) continue; - stm = &_videod_streaming_itf[i]; - self->stm[stm_idx] = i; - break; - } - TU_ASSERT(stm, 0); - stm->index_vc = ctl_idx; - stm->index_vs = stm_idx; - stm->desc.beg = (uintptr_t)cur - (uintptr_t)itf_desc; - cur = _next_desc_itf(cur, end); - stm->desc.end = (uintptr_t)cur - (uintptr_t)itf_desc; - } - self->len = (uintptr_t)cur - (uintptr_t)itf_desc; - return (uintptr_t)cur - (uintptr_t)itf_desc; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - int err; - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - uint_fast8_t itfnum = tu_u16_low(request->wIndex); - - /* Identify which control interface to use */ - uint_fast8_t itf; - for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) { - void const *desc = _videod_itf[itf].beg; - if (!desc) continue; - if (itfnum == _desc_itfnum(desc)) break; - } - - if (itf < CFG_TUD_VIDEO) { - err = handle_video_ctl_req(rhport, stage, request, itf); - _videod_itf[itf].error_code = (uint8_t)err; - if (err) return false; - return true; - } - - /* Identify which streaming interface to use */ - for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { - videod_streaming_interface_t *stm = &_videod_streaming_itf[itf]; - if (!stm->desc.beg) continue; - void const *desc = _videod_itf[stm->index_vc].beg; - if (itfnum == _desc_itfnum(desc + stm->desc.beg)) break; - } - - if (itf < CFG_TUD_VIDEO_STREAMING) { - err = handle_video_stm_req(rhport, stage, request, itf); - _videod_streaming_itf[itf].error_code = (uint8_t)err; - if (err) return false; - return true; - } - return false; -} - -bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void)result; (void)xferred_bytes; - - /* find streaming handle */ - uint_fast8_t itf; - videod_interface_t *ctl; - videod_streaming_interface_t *stm; - for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { - stm = &_videod_streaming_itf[itf]; - uint_fast16_t const ep_ofs = stm->desc.ep[0]; - if (!ep_ofs) continue; - ctl = &_videod_itf[stm->index_vc]; - void const *desc = ctl->beg; - if (ep_addr == _desc_ep_addr(desc + ep_ofs)) break; - } - - TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING); - if (stm->offset < stm->bufsize) { - /* Claim the endpoint */ - TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0); - uint_fast16_t pkt_len = _prepare_in_payload(stm); - TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm->ep_buf, pkt_len), 0); - } else { - stm->buffer = NULL; - stm->bufsize = 0; - stm->offset = 0; - if (tud_video_frame_xfer_complete_cb) { - tud_video_frame_xfer_complete_cb(stm->index_vc, stm->index_vs); - } - } - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h deleted file mode 100644 index ee2fcb9d5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/class/video/video_device.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2021 Koji KITAYAMA - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_VIDEO_DEVICE_H_ -#define TUSB_VIDEO_DEVICE_H_ - -#include "common/tusb_common.h" -#include "video.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API (Multiple Ports) -// CFG_TUD_VIDEO > 1 -//--------------------------------------------------------------------+ - -/** Return true if streaming - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index */ -bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); - -/** Transfer a frame - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @param[in] buffer Frame buffer. The caller must not use this buffer until the operation is completed. - * @param[in] bufsize Byte size of the frame buffer */ -bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize); - -/*------------- Optional callbacks -------------*/ -/** Invoked when compeletion of a frame transfer - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index */ -TU_ATTR_WEAK void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -/** Invoked when SET_POWER_MODE request received - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @return video_error_code_t */ -TU_ATTR_WEAK int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod); - -/** Invoked when VS_COMMIT_CONTROL(SET_CUR) request received - * - * @param[in] ctl_idx Destination control interface index - * @param[in] stm_idx Destination streaming interface index - * @param[in] parameters Video streaming parameters - * @return video_error_code_t */ -TU_ATTR_WEAK int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, - video_probe_and_commit_control_t const *parameters); - -//--------------------------------------------------------------------+ -// INTERNAL USBD-CLASS DRIVER API -//--------------------------------------------------------------------+ -void videod_init (void); -void videod_reset (uint8_t rhport); -uint16_t videod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool videod_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h deleted file mode 100644 index 9b9e2b007..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_common.h +++ /dev/null @@ -1,406 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_COMMON_H_ -#define _TUSB_COMMON_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Macros Helper -//--------------------------------------------------------------------+ -#define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) -#define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) ) -#define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) ) - -#define TU_U16_HIGH(_u16) ((uint8_t) (((_u16) >> 8) & 0x00ff)) -#define TU_U16_LOW(_u16) ((uint8_t) ((_u16) & 0x00ff)) -#define U16_TO_U8S_BE(_u16) TU_U16_HIGH(_u16), TU_U16_LOW(_u16) -#define U16_TO_U8S_LE(_u16) TU_U16_LOW(_u16), TU_U16_HIGH(_u16) - -#define TU_U32_BYTE3(_u32) ((uint8_t) ((((uint32_t) _u32) >> 24) & 0x000000ff)) // MSB -#define TU_U32_BYTE2(_u32) ((uint8_t) ((((uint32_t) _u32) >> 16) & 0x000000ff)) -#define TU_U32_BYTE1(_u32) ((uint8_t) ((((uint32_t) _u32) >> 8) & 0x000000ff)) -#define TU_U32_BYTE0(_u32) ((uint8_t) (((uint32_t) _u32) & 0x000000ff)) // LSB - -#define U32_TO_U8S_BE(_u32) TU_U32_BYTE3(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE0(_u32) -#define U32_TO_U8S_LE(_u32) TU_U32_BYTE0(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE3(_u32) - -#define TU_BIT(n) (1UL << (n)) -#define TU_GENMASK(h, l) ( (UINT32_MAX << (l)) & (UINT32_MAX >> (31 - (h))) ) - -//--------------------------------------------------------------------+ -// Includes -//--------------------------------------------------------------------+ - -// Standard Headers -#include -#include -#include -#include -#include - -// Tinyusb Common Headers -#include "tusb_option.h" -#include "tusb_compiler.h" -#include "tusb_verify.h" -#include "tusb_types.h" - -#include "tusb_error.h" // TODO remove -#include "tusb_timeout.h" // TODO remove - -//--------------------------------------------------------------------+ -// Internal Helper used by Host and Device Stack -//--------------------------------------------------------------------+ - -// Check if endpoint descriptor is valid per USB specs -bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); - -// Bind all endpoint of a interface descriptor to class driver -void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); - -// Calculate total length of n interfaces (depending on IAD) -uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); - -//--------------------------------------------------------------------+ -// Internal Inline Functions -//--------------------------------------------------------------------+ - -//------------- Mem -------------// -#define tu_memclr(buffer, size) memset((buffer), 0, (size)) -#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) - -//------------- Bytes -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) -{ - return ( ((uint32_t) b3) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b1) << 8) | b0; -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) -{ - return (uint16_t) ((((uint16_t) high) << 8) | low); -} - -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte3(uint32_t ui32) { return TU_U32_BYTE3(ui32); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte2(uint32_t ui32) { return TU_U32_BYTE2(ui32); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte1(uint32_t ui32) { return TU_U32_BYTE1(ui32); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte0(uint32_t ui32) { return TU_U32_BYTE0(ui32); } - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u32_high16(uint32_t ui32) { return (uint16_t) (ui32 >> 16); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u32_low16 (uint32_t ui32) { return (uint16_t) (ui32 & 0x0000ffffu); } - -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t ui16) { return TU_U16_HIGH(ui16); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t ui16) { return TU_U16_LOW(ui16); } - -//------------- Bits -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_clear(uint32_t value, uint8_t pos) { return value & (~TU_BIT(pos)); } -TU_ATTR_ALWAYS_INLINE static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value & TU_BIT(pos)) ? true : false; } - -//------------- Min -------------// -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_min8 (uint8_t x, uint8_t y ) { return (x < y) ? x : y; } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_min32 (uint32_t x, uint32_t y) { return (x < y) ? x : y; } - -//------------- Max -------------// -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_max8 (uint8_t x, uint8_t y ) { return (x > y) ? x : y; } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_max16 (uint16_t x, uint16_t y) { return (x > y) ? x : y; } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; } - -//------------- Align -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment) -{ - return value & ((uint32_t) ~(alignment-1)); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } - -//------------- Mathematics -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return (v + d -1)/d; } - -/// inclusive range checking TODO remove -TU_ATTR_ALWAYS_INLINE static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) -{ - return (lower <= value) && (value <= upper); -} - -// log2 of a value is its MSB's position -// TODO use clz TODO remove -static inline uint8_t tu_log2(uint32_t value) -{ - uint8_t result = 0; - while (value >>= 1) { result++; } - return result; -} - -//------------- Unaligned Access -------------// -#if TUP_ARCH_STRICT_ALIGN - -// Rely on compiler to generate correct code for unaligned access -typedef struct { uint16_t val; } TU_ATTR_PACKED tu_unaligned_uint16_t; -typedef struct { uint32_t val; } TU_ATTR_PACKED tu_unaligned_uint32_t; - -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) -{ - tu_unaligned_uint32_t const* ua32 = (tu_unaligned_uint32_t const*) mem; - return ua32->val; -} - -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) -{ - tu_unaligned_uint32_t* ua32 = (tu_unaligned_uint32_t*) mem; - ua32->val = value; -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) -{ - tu_unaligned_uint16_t const* ua16 = (tu_unaligned_uint16_t const*) mem; - return ua16->val; -} - -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) -{ - tu_unaligned_uint16_t* ua16 = (tu_unaligned_uint16_t*) mem; - ua16->val = value; -} - -#elif TUP_MCU_STRICT_ALIGN - -// MCU such as LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM although it is ARM M4. -// We have to manually pick up bytes since tu_unaligned_uint32_t will still generate unaligned code -// NOTE: volatile cast to memory to prevent compiler to optimize and generate unaligned code -// TODO Big Endian may need minor changes -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) -{ - volatile uint8_t const* buf8 = (uint8_t const*) mem; - return tu_u32(buf8[3], buf8[2], buf8[1], buf8[0]); -} - -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) -{ - volatile uint8_t* buf8 = (uint8_t*) mem; - buf8[0] = tu_u32_byte0(value); - buf8[1] = tu_u32_byte1(value); - buf8[2] = tu_u32_byte2(value); - buf8[3] = tu_u32_byte3(value); -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) -{ - volatile uint8_t const* buf8 = (uint8_t const*) mem; - return tu_u16(buf8[1], buf8[0]); -} - -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) -{ - volatile uint8_t* buf8 = (uint8_t*) mem; - buf8[0] = tu_u16_low(value); - buf8[1] = tu_u16_high(value); -} - - -#else - -// MCU that could access unaligned memory natively -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem) { return *((uint32_t const *) mem); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem) { return *((uint16_t const *) mem); } - -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32 (void* mem, uint32_t value ) { *((uint32_t*) mem) = value; } -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, uint16_t value ) { *((uint16_t*) mem) = value; } - -#endif - -// To be removed -//------------- Binary constant -------------// -#if defined(__GNUC__) && !defined(__CC_ARM) - -#define TU_BIN8(x) ((uint8_t) (0b##x)) -#define TU_BIN16(b1, b2) ((uint16_t) (0b##b1##b2)) -#define TU_BIN32(b1, b2, b3, b4) ((uint32_t) (0b##b1##b2##b3##b4)) - -#else - -// internal macro of B8, B16, B32 -#define _B8__(x) (((x&0x0000000FUL)?1:0) \ - +((x&0x000000F0UL)?2:0) \ - +((x&0x00000F00UL)?4:0) \ - +((x&0x0000F000UL)?8:0) \ - +((x&0x000F0000UL)?16:0) \ - +((x&0x00F00000UL)?32:0) \ - +((x&0x0F000000UL)?64:0) \ - +((x&0xF0000000UL)?128:0)) - -#define TU_BIN8(d) ((uint8_t) _B8__(0x##d##UL)) -#define TU_BIN16(dmsb,dlsb) (((uint16_t)TU_BIN8(dmsb)<<8) + TU_BIN8(dlsb)) -#define TU_BIN32(dmsb,db2,db3,dlsb) \ - (((uint32_t)TU_BIN8(dmsb)<<24) \ - + ((uint32_t)TU_BIN8(db2)<<16) \ - + ((uint32_t)TU_BIN8(db3)<<8) \ - + TU_BIN8(dlsb)) -#endif - -//--------------------------------------------------------------------+ -// Debug Function -//--------------------------------------------------------------------+ - -// CFG_TUSB_DEBUG for debugging -// 0 : no debug -// 1 : print error -// 2 : print warning -// 3 : print info -#if CFG_TUSB_DEBUG - -void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); - -#ifdef CFG_TUSB_DEBUG_PRINTF - extern int CFG_TUSB_DEBUG_PRINTF(const char *format, ...); - #define tu_printf CFG_TUSB_DEBUG_PRINTF -#else - #define tu_printf printf -#endif - -static inline -void tu_print_var(uint8_t const* buf, uint32_t bufsize) -{ - for(uint32_t i=0; i= 2 - #define TU_LOG2 TU_LOG1 - #define TU_LOG2_MEM TU_LOG1_MEM - #define TU_LOG2_VAR TU_LOG1_VAR - #define TU_LOG2_INT TU_LOG1_INT - #define TU_LOG2_HEX TU_LOG1_HEX -#endif - -// Log Level 3: Info -#if CFG_TUSB_DEBUG >= 3 - #define TU_LOG3 TU_LOG1 - #define TU_LOG3_MEM TU_LOG1_MEM - #define TU_LOG3_VAR TU_LOG1_VAR - #define TU_LOG3_INT TU_LOG1_INT - #define TU_LOG3_HEX TU_LOG1_HEX -#endif - -typedef struct -{ - uint32_t key; - const char* data; -} tu_lookup_entry_t; - -typedef struct -{ - uint16_t count; - tu_lookup_entry_t const* items; -} tu_lookup_table_t; - -static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) -{ - static char not_found[11]; - - for(uint16_t i=0; icount; i++) - { - if (p_table->items[i].key == key) return p_table->items[i].data; - } - - // not found return the key value in hex - sprintf(not_found, "0x%08lX", (unsigned long) key); - - return not_found; -} - -#endif // CFG_TUSB_DEBUG - -#ifndef TU_LOG -#define TU_LOG(n, ...) -#define TU_LOG_MEM(n, ...) -#define TU_LOG_VAR(n, ...) -#define TU_LOG_INT(n, ...) -#define TU_LOG_HEX(n, ...) -#define TU_LOG_LOCATION() -#define TU_LOG_FAILED() -#endif - -// TODO replace all TU_LOGn with TU_LOG(n) - -#define TU_LOG0(...) -#define TU_LOG0_MEM(...) -#define TU_LOG0_VAR(...) -#define TU_LOG0_INT(...) -#define TU_LOG0_HEX(...) - - -#ifndef TU_LOG1 - #define TU_LOG1(...) - #define TU_LOG1_MEM(...) - #define TU_LOG1_VAR(...) - #define TU_LOG1_INT(...) - #define TU_LOG1_HEX(...) -#endif - -#ifndef TU_LOG2 - #define TU_LOG2(...) - #define TU_LOG2_MEM(...) - #define TU_LOG2_VAR(...) - #define TU_LOG2_INT(...) - #define TU_LOG2_HEX(...) -#endif - -#ifndef TU_LOG3 - #define TU_LOG3(...) - #define TU_LOG3_MEM(...) - #define TU_LOG3_VAR(...) - #define TU_LOG3_INT(...) - #define TU_LOG3_HEX(...) -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_COMMON_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h deleted file mode 100644 index d3284c62a..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_compiler.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_Common - * \defgroup Group_Compiler Compiler - * \brief Group_Compiler brief - * @{ */ - -#ifndef _TUSB_COMPILER_H_ -#define _TUSB_COMPILER_H_ - -#define TU_TOKEN(x) x -#define TU_STRING(x) #x ///< stringify without expand -#define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify - -#define TU_STRCAT(a, b) a##b ///< concat without expand -#define TU_STRCAT3(a, b, c) a##b##c ///< concat without expand - -#define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat -#define TU_XSTRCAT3(a, b, c) TU_STRCAT3(a, b, c) ///< expand then concat 3 tokens - -#define TU_INCLUDE_PATH(_dir,_file) TU_XSTRING( TU_TOKEN(_dir)TU_TOKEN(_file) ) - -#if defined __COUNTER__ && __COUNTER__ != __COUNTER__ - #define _TU_COUNTER_ __COUNTER__ -#else - #define _TU_COUNTER_ __LINE__ -#endif - -// Compile-time Assert -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #define TU_VERIFY_STATIC _Static_assert -#elif defined (__cplusplus) && __cplusplus >= 201103L - #define TU_VERIFY_STATIC static_assert -#elif defined(__CCRX__) - #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0]; -#else - #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } -#endif - -// for declaration of reserved field, make use of _TU_COUNTER_ -#define TU_RESERVED TU_XSTRCAT(reserved, _TU_COUNTER_) - -#define TU_LITTLE_ENDIAN (0x12u) -#define TU_BIG_ENDIAN (0x21u) - -/*------------------------------------------------------------------*/ -/* Count number of arguments of __VA_ARGS__ - * - reference https://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments - * - _GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th) - * - _RSEQ_N() is reverse sequential to N to add padding to have - * Nth position is the same as the number of arguments - * - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma) - *------------------------------------------------------------------*/ -#define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N()) - -#define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__) -#define _GET_NTH_ARG( \ - _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ - _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ - _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ - _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ - _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ - _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ - _61,_62,_63,N,...) N -#define _RSEQ_N() \ - 62,61,60, \ - 59,58,57,56,55,54,53,52,51,50, \ - 49,48,47,46,45,44,43,42,41,40, \ - 39,38,37,36,35,34,33,32,31,30, \ - 29,28,27,26,25,24,23,22,21,20, \ - 19,18,17,16,15,14,13,12,11,10, \ - 9,8,7,6,5,4,3,2,1,0 - -// Apply an macro X to each of the arguments with an separated of choice -#define TU_ARGS_APPLY(_X, _s, ...) TU_XSTRCAT(_TU_ARGS_APPLY_, TU_ARGS_NUM(__VA_ARGS__))(_X, _s, __VA_ARGS__) - -#define _TU_ARGS_APPLY_1(_X, _s, _a1) _X(_a1) -#define _TU_ARGS_APPLY_2(_X, _s, _a1, _a2) _X(_a1) _s _X(_a2) -#define _TU_ARGS_APPLY_3(_X, _s, _a1, _a2, _a3) _X(_a1) _s _TU_ARGS_APPLY_2(_X, _s, _a2, _a3) -#define _TU_ARGS_APPLY_4(_X, _s, _a1, _a2, _a3, _a4) _X(_a1) _s _TU_ARGS_APPLY_3(_X, _s, _a2, _a3, _a4) -#define _TU_ARGS_APPLY_5(_X, _s, _a1, _a2, _a3, _a4, _a5) _X(_a1) _s _TU_ARGS_APPLY_4(_X, _s, _a2, _a3, _a4, _a5) -#define _TU_ARGS_APPLY_6(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6) _X(_a1) _s _TU_ARGS_APPLY_5(_X, _s, _a2, _a3, _a4, _a5, _a6) -#define _TU_ARGS_APPLY_7(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7) _X(_a1) _s _TU_ARGS_APPLY_6(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7) -#define _TU_ARGS_APPLY_8(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) _X(_a1) _s _TU_ARGS_APPLY_7(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7, _a8) - -//--------------------------------------------------------------------+ -// Compiler porting with Attribute and Endian -//--------------------------------------------------------------------+ - -// TODO refactor since __attribute__ is supported across many compiler -#if defined(__GNUC__) - #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) - #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) - #define TU_ATTR_PACKED __attribute__ ((packed)) - #define TU_ATTR_WEAK __attribute__ ((weak)) - #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) - #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used - #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused - #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used - - #define TU_ATTR_PACKED_BEGIN - #define TU_ATTR_PACKED_END - #define TU_ATTR_BIT_FIELD_ORDER_BEGIN - #define TU_ATTR_BIT_FIELD_ORDER_END - - // Endian conversion use well-known host to network (big endian) naming - #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #else - #define TU_BYTE_ORDER TU_BIG_ENDIAN - #endif - - #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) - #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) - - // List of obsolete callback function that is renamed and should not be defined. - // Put it here since only gcc support this pragma - #pragma GCC poison tud_vendor_control_request_cb - -#elif defined(__TI_COMPILER_VERSION__) - #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) - #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) - #define TU_ATTR_PACKED __attribute__ ((packed)) - #define TU_ATTR_WEAK __attribute__ ((weak)) - #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) - #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used - #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused - #define TU_ATTR_USED __attribute__ ((used)) - - #define TU_ATTR_PACKED_BEGIN - #define TU_ATTR_PACKED_END - #define TU_ATTR_BIT_FIELD_ORDER_BEGIN - #define TU_ATTR_BIT_FIELD_ORDER_END - - // __BYTE_ORDER is defined in the TI ARM compiler, but not MSP430 (which is little endian) - #if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) || defined(__MSP430__) - #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #else - #define TU_BYTE_ORDER TU_BIG_ENDIAN - #endif - - #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) - #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) - -#elif defined(__ICCARM__) - #include - #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) - #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) - #define TU_ATTR_PACKED __attribute__ ((packed)) - #define TU_ATTR_WEAK __attribute__ ((weak)) - #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) - #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used - #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused - #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used - - #define TU_ATTR_PACKED_BEGIN - #define TU_ATTR_PACKED_END - #define TU_ATTR_BIT_FIELD_ORDER_BEGIN - #define TU_ATTR_BIT_FIELD_ORDER_END - - // Endian conversion use well-known host to network (big endian) naming - #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #else - #define TU_BYTE_ORDER TU_BIG_ENDIAN - #endif - - #define TU_BSWAP16(u16) (__iar_builtin_REV16(u16)) - #define TU_BSWAP32(u32) (__iar_builtin_REV(u32)) - -#elif defined(__CCRX__) - #define TU_ATTR_ALIGNED(Bytes) - #define TU_ATTR_SECTION(sec_name) - #define TU_ATTR_PACKED - #define TU_ATTR_WEAK - #define TU_ATTR_ALWAYS_INLINE - #define TU_ATTR_DEPRECATED(mess) - #define TU_ATTR_UNUSED - #define TU_ATTR_USED - - #define TU_ATTR_PACKED_BEGIN _Pragma("pack") - #define TU_ATTR_PACKED_END _Pragma("packoption") - #define TU_ATTR_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") - #define TU_ATTR_BIT_FIELD_ORDER_END _Pragma("bit_order") - - // Endian conversion use well-known host to network (big endian) naming - #if defined(__LIT) - #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #else - #define TU_BYTE_ORDER TU_BIG_ENDIAN - #endif - - #define TU_BSWAP16(u16) ((unsigned short)_builtin_revw((unsigned long)u16)) - #define TU_BSWAP32(u32) (_builtin_revl(u32)) - -#else - #error "Compiler attribute porting is required" -#endif - -#if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN) - - #define tu_htons(u16) (TU_BSWAP16(u16)) - #define tu_ntohs(u16) (TU_BSWAP16(u16)) - - #define tu_htonl(u32) (TU_BSWAP32(u32)) - #define tu_ntohl(u32) (TU_BSWAP32(u32)) - - #define tu_htole16(u16) (u16) - #define tu_le16toh(u16) (u16) - - #define tu_htole32(u32) (u32) - #define tu_le32toh(u32) (u32) - -#elif (TU_BYTE_ORDER == TU_BIG_ENDIAN) - - #define tu_htons(u16) (u16) - #define tu_ntohs(u16) (u16) - - #define tu_htonl(u32) (u32) - #define tu_ntohl(u32) (u32) - - #define tu_htole16(u16) (TU_BSWAP16(u16)) - #define tu_le16toh(u16) (TU_BSWAP16(u16)) - - #define tu_htole32(u32) (TU_BSWAP32(u32)) - #define tu_le32toh(u32) (TU_BSWAP32(u32)) - -#else - #error Byte order is undefined -#endif - -#endif /* _TUSB_COMPILER_H_ */ - -/// @} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h deleted file mode 100644 index d7ad8c318..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_error.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_Common - * \defgroup Group_Error Error Codes - * @{ */ - -#ifndef _TUSB_ERRORS_H_ -#define _TUSB_ERRORS_H_ - -#include "tusb_option.h" - -#ifdef __cplusplus - extern "C" { -#endif - -#define ERROR_ENUM(x) x, -#define ERROR_STRING(x) #x, - -#define ERROR_TABLE(ENTRY) \ - ENTRY(TUSB_ERROR_NONE )\ - ENTRY(TUSB_ERROR_INVALID_PARA )\ - ENTRY(TUSB_ERROR_DEVICE_NOT_READY )\ - ENTRY(TUSB_ERROR_INTERFACE_IS_BUSY )\ - ENTRY(TUSB_ERROR_HCD_OPEN_PIPE_FAILED )\ - ENTRY(TUSB_ERROR_OSAL_TIMEOUT )\ - ENTRY(TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED )\ - ENTRY(TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED )\ - ENTRY(TUSB_ERROR_NOT_SUPPORTED )\ - ENTRY(TUSB_ERROR_NOT_ENOUGH_MEMORY )\ - ENTRY(TUSB_ERROR_FAILED )\ - -/// \brief Error Code returned -/// TODO obsolete and to be remove -typedef enum -{ - ERROR_TABLE(ERROR_ENUM) - TUSB_ERROR_COUNT -}tusb_error_t; - -#if CFG_TUSB_DEBUG -/// Enum to String for debugging purposes. Only available if \ref CFG_TUSB_DEBUG > 0 -extern char const* const tusb_strerr[TUSB_ERROR_COUNT]; -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_ERRORS_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c deleted file mode 100644 index 183c9c6fc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.c +++ /dev/null @@ -1,1007 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - rework to unmasked pointers - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "osal/osal.h" -#include "tusb_fifo.h" - -// Supress IAR warning -// Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement -#if defined(__ICCARM__) -#pragma diag_suppress = Pa082 -#endif - -// implement mutex lock and unlock -#if CFG_FIFO_MUTEX - -static inline void _ff_lock(tu_fifo_mutex_t mutex) -{ - if (mutex) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); -} - -static inline void _ff_unlock(tu_fifo_mutex_t mutex) -{ - if (mutex) osal_mutex_unlock(mutex); -} - -#else - -#define _ff_lock(_mutex) -#define _ff_unlock(_mutex) - -#endif - -/** \enum tu_fifo_copy_mode_t - * \brief Write modes intended to allow special read and write functions to be able to - * copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others - */ -typedef enum -{ - TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode - TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO -} tu_fifo_copy_mode_t; - -bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) -{ - if (depth > 0x8000) return false; // Maximum depth is 2^15 items - - _ff_lock(f->mutex_wr); - _ff_lock(f->mutex_rd); - - f->buffer = (uint8_t*) buffer; - f->depth = depth; - f->item_size = item_size; - f->overwritable = overwritable; - - // Limit index space to 2*depth - this allows for a fast "modulo" calculation - // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable - // only if overflow happens once (important for unsupervised DMA applications) - f->max_pointer_idx = 2*depth - 1; - f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; - - f->rd_idx = f->wr_idx = 0; - - _ff_unlock(f->mutex_wr); - _ff_unlock(f->mutex_rd); - - return true; -} - -// Static functions are intended to work on local variables -static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) -{ - while ( idx >= depth) idx -= depth; - return idx; -} - -// Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address -// Code adapted from dcd_synopsis.c -// TODO generalize with configurable 1 byte or 4 byte each read -static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t len) -{ - volatile const uint32_t * rx_fifo = (volatile const uint32_t *) app_buf; - - // Reading full available 32 bit words from const app address - uint16_t full_words = len >> 2; - while(full_words--) - { - tu_unaligned_write32(ff_buf, *rx_fifo); - ff_buf += 4; - } - - // Read the remaining 1-3 bytes from const app address - uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem ) - { - uint32_t tmp32 = *rx_fifo; - memcpy(ff_buf, &tmp32, bytes_rem); - } -} - -// Intended to be used to write to hardware USB FIFO in e.g. STM32 -// where all data is written to a constant address in full word copies -static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t len) -{ - volatile uint32_t * tx_fifo = (volatile uint32_t *) app_buf; - - // Pushing full available 32 bit words to const app address - uint16_t full_words = len >> 2; - while(full_words--) - { - *tx_fifo = tu_unaligned_read32(ff_buf); - ff_buf += 4; - } - - // Write the remaining 1-3 bytes into const app address - uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem ) - { - uint32_t tmp32 = 0; - memcpy(&tmp32, ff_buf, bytes_rem); - - *tx_fifo = tmp32; - } -} - -// send one item to FIFO WITHOUT updating write pointer -static inline void _ff_push(tu_fifo_t* f, void const * app_buf, uint16_t rel) -{ - memcpy(f->buffer + (rel * f->item_size), app_buf, f->item_size); -} - -// send n items to FIFO WITHOUT updating write pointer -static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t rel, tu_fifo_copy_mode_t copy_mode) -{ - uint16_t const nLin = f->depth - rel; - uint16_t const nWrap = n - nLin; - - uint16_t nLin_bytes = nLin * f->item_size; - uint16_t nWrap_bytes = nWrap * f->item_size; - - // current buffer of fifo - uint8_t* ff_buf = f->buffer + (rel * f->item_size); - - switch (copy_mode) - { - case TU_FIFO_COPY_INC: - if(n <= nLin) - { - // Linear only - memcpy(ff_buf, app_buf, n*f->item_size); - } - else - { - // Wrap around - - // Write data to linear part of buffer - memcpy(ff_buf, app_buf, nLin_bytes); - - // Write data wrapped around - memcpy(f->buffer, ((uint8_t const*) app_buf) + nLin_bytes, nWrap_bytes); - } - break; - - case TU_FIFO_COPY_CST_FULL_WORDS: - // Intended for hardware buffers from which it can be read word by word only - if(n <= nLin) - { - // Linear only - _ff_push_const_addr(ff_buf, app_buf, n*f->item_size); - } - else - { - // Wrap around case - - // Write full words to linear part of buffer - uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; - _ff_push_const_addr(ff_buf, app_buf, nLin_4n_bytes); - ff_buf += nLin_4n_bytes; - - // There could be odd 1-3 bytes before the wrap-around boundary - volatile const uint32_t * rx_fifo = (volatile const uint32_t *) app_buf; - uint8_t rem = nLin_bytes & 0x03; - if (rem > 0) - { - uint8_t remrem = tu_min16(nWrap_bytes, 4-rem); - nWrap_bytes -= remrem; - - uint32_t tmp32 = *rx_fifo; - uint8_t * src_u8 = ((uint8_t *) &tmp32); - - // Write 1-3 bytes before wrapped boundary - while(rem--) *ff_buf++ = *src_u8++; - - // Read more bytes to beginning to complete a word - ff_buf = f->buffer; - while(remrem--) *ff_buf++ = *src_u8++; - } - else - { - ff_buf = f->buffer; // wrap around to beginning - } - - // Write data wrapped part - if (nWrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, nWrap_bytes); - } - break; - } -} - -// get one item from FIFO WITHOUT updating read pointer -static inline void _ff_pull(tu_fifo_t* f, void * app_buf, uint16_t rel) -{ - memcpy(app_buf, f->buffer + (rel * f->item_size), f->item_size); -} - -// get n items from FIFO WITHOUT updating read pointer -static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rel, tu_fifo_copy_mode_t copy_mode) -{ - uint16_t const nLin = f->depth - rel; - uint16_t const nWrap = n - nLin; // only used if wrapped - - uint16_t nLin_bytes = nLin * f->item_size; - uint16_t nWrap_bytes = nWrap * f->item_size; - - // current buffer of fifo - uint8_t* ff_buf = f->buffer + (rel * f->item_size); - - switch (copy_mode) - { - case TU_FIFO_COPY_INC: - if ( n <= nLin ) - { - // Linear only - memcpy(app_buf, ff_buf, n*f->item_size); - } - else - { - // Wrap around - - // Read data from linear part of buffer - memcpy(app_buf, ff_buf, nLin_bytes); - - // Read data wrapped part - memcpy((uint8_t*) app_buf + nLin_bytes, f->buffer, nWrap_bytes); - } - break; - - case TU_FIFO_COPY_CST_FULL_WORDS: - if ( n <= nLin ) - { - // Linear only - _ff_pull_const_addr(app_buf, ff_buf, n*f->item_size); - } - else - { - // Wrap around case - - // Read full words from linear part of buffer - uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; - _ff_pull_const_addr(app_buf, ff_buf, nLin_4n_bytes); - ff_buf += nLin_4n_bytes; - - // There could be odd 1-3 bytes before the wrap-around boundary - volatile uint32_t * tx_fifo = (volatile uint32_t *) app_buf; - uint8_t rem = nLin_bytes & 0x03; - if (rem > 0) - { - uint8_t remrem = tu_min16(nWrap_bytes, 4-rem); - nWrap_bytes -= remrem; - - uint32_t tmp32=0; - uint8_t * dst_u8 = (uint8_t *)&tmp32; - - // Read 1-3 bytes before wrapped boundary - while(rem--) *dst_u8++ = *ff_buf++; - - // Read more bytes from beginning to complete a word - ff_buf = f->buffer; - while(remrem--) *dst_u8++ = *ff_buf++; - - *tx_fifo = tmp32; - } - else - { - ff_buf = f->buffer; // wrap around to beginning - } - - // Read data wrapped part - if (nWrap_bytes > 0) _ff_pull_const_addr(app_buf, ff_buf, nWrap_bytes); - } - break; - - default: break; - } -} - -// Advance an absolute pointer -static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) -{ - // We limit the index space of p such that a correct wrap around happens - // Check for a wrap around or if we are in unused index space - This has to be checked first!! - // We are exploiting the wrap around to the correct index - if ((p > (uint16_t)(p + offset)) || ((uint16_t)(p + offset) > f->max_pointer_idx)) - { - p = (p + offset) + f->non_used_index_space; - } - else - { - p += offset; - } - return p; -} - -// Backward an absolute pointer -static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) -{ - // We limit the index space of p such that a correct wrap around happens - // Check for a wrap around or if we are in unused index space - This has to be checked first!! - // We are exploiting the wrap around to the correct index - if ((p < (uint16_t)(p - offset)) || ((uint16_t)(p - offset) > f->max_pointer_idx)) - { - p = (p - offset) - f->non_used_index_space; - } - else - { - p -= offset; - } - return p; -} - -// get relative from absolute pointer -static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p) -{ - return _ff_mod(p, f->depth); -} - -// Works on local copies of w and r - return only the difference and as such can be used to determine an overflow -static inline uint16_t _tu_fifo_count(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) -{ - uint16_t cnt = wAbs-rAbs; - - // In case we have non-power of two depth we need a further modification - if (rAbs > wAbs) cnt -= f->non_used_index_space; - - return cnt; -} - -// Works on local copies of w and r -static inline bool _tu_fifo_empty(uint16_t wAbs, uint16_t rAbs) -{ - return wAbs == rAbs; -} - -// Works on local copies of w and r -static inline bool _tu_fifo_full(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) -{ - return (_tu_fifo_count(f, wAbs, rAbs) == f->depth); -} - -// Works on local copies of w and r -// BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" -// Only one overflow is allowed for this function to work e.g. if depth = 100, you must not -// write more than 2*depth-1 items in one rush without updating write pointer. Otherwise -// write pointer wraps and you pointer states are messed up. This can only happen if you -// use DMAs, write functions do not allow such an error. -static inline bool _tu_fifo_overflowed(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) -{ - return (_tu_fifo_count(f, wAbs, rAbs) > f->depth); -} - -// Works on local copies of w -// For more details see _tu_fifo_overflow()! -static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) -{ - f->rd_idx = backward_pointer(f, wAbs, f->depth); -} - -// Works on local copies of w and r -// Must be protected by mutexes since in case of an overflow read pointer gets modified -static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) -{ - uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); - - // Check overflow and correct if required - if (cnt > f->depth) - { - _tu_fifo_correct_read_pointer(f, wAbs); - cnt = f->depth; - } - - // Skip beginning of buffer - if (cnt == 0) return false; - - uint16_t rRel = get_relative_pointer(f, rAbs); - - // Peek data - _ff_pull(f, p_buffer, rRel); - - return true; -} - -// Works on local copies of w and r -// Must be protected by mutexes since in case of an overflow read pointer gets modified -static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) -{ - uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); - - // Check overflow and correct if required - if (cnt > f->depth) - { - _tu_fifo_correct_read_pointer(f, wAbs); - rAbs = f->rd_idx; - cnt = f->depth; - } - - // Skip beginning of buffer - if (cnt == 0) return 0; - - // Check if we can read something at and after offset - if too less is available we read what remains - if (cnt < n) n = cnt; - - uint16_t rRel = get_relative_pointer(f, rAbs); - - // Peek data - _ff_pull_n(f, p_buffer, n, rRel, copy_mode); - - return n; -} - -// Works on local copies of w and r -static inline uint16_t _tu_fifo_remaining(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) -{ - return f->depth - _tu_fifo_count(f, wAbs, rAbs); -} - -static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu_fifo_copy_mode_t copy_mode) -{ - if ( n == 0 ) return 0; - - _ff_lock(f->mutex_wr); - - uint16_t w = f->wr_idx, r = f->rd_idx; - uint8_t const* buf8 = (uint8_t const*) data; - - if (!f->overwritable) - { - // Not overwritable limit up to full - n = tu_min16(n, _tu_fifo_remaining(f, w, r)); - } - else if (n >= f->depth) - { - // Only copy last part - buf8 = buf8 + (n - f->depth) * f->item_size; - n = f->depth; - - // We start writing at the read pointer's position since we fill the complete - // buffer and we do not want to modify the read pointer within a write function! - // This would end up in a race condition with read functions! - w = r; - } - - uint16_t wRel = get_relative_pointer(f, w); - - // Write data - _ff_push_n(f, buf8, n, wRel, copy_mode); - - // Advance pointer - f->wr_idx = advance_pointer(f, w, n); - - _ff_unlock(f->mutex_wr); - - return n; -} - -static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) -{ - _ff_lock(f->mutex_rd); - - // Peek the data - // f->rd_idx might get modified in case of an overflow so we can not use a local variable - n = _tu_fifo_peek_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); - - // Advance read pointer - f->rd_idx = advance_pointer(f, f->rd_idx, n); - - _ff_unlock(f->mutex_rd); - return n; -} - -/******************************************************************************/ -/*! - @brief Get number of items in FIFO. - - As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. In case an - overflow occurred, this function return f.depth at maximum. Overflows are - checked and corrected for in the read functions! - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns Number of items in FIFO - */ -/******************************************************************************/ -uint16_t tu_fifo_count(tu_fifo_t* f) -{ - return tu_min16(_tu_fifo_count(f, f->wr_idx, f->rd_idx), f->depth); -} - -/******************************************************************************/ -/*! - @brief Check if FIFO is empty. - - As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns Number of items in FIFO - */ -/******************************************************************************/ -bool tu_fifo_empty(tu_fifo_t* f) -{ - return _tu_fifo_empty(f->wr_idx, f->rd_idx); -} - -/******************************************************************************/ -/*! - @brief Check if FIFO is full. - - As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns Number of items in FIFO - */ -/******************************************************************************/ -bool tu_fifo_full(tu_fifo_t* f) -{ - return _tu_fifo_full(f, f->wr_idx, f->rd_idx); -} - -/******************************************************************************/ -/*! - @brief Get remaining space in FIFO. - - As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns Number of items in FIFO - */ -/******************************************************************************/ -uint16_t tu_fifo_remaining(tu_fifo_t* f) -{ - return _tu_fifo_remaining(f, f->wr_idx, f->rd_idx); -} - -/******************************************************************************/ -/*! - @brief Check if overflow happened. - - BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" - Only one overflow is allowed for this function to work e.g. if depth = 100, you must not - write more than 2*depth-1 items in one rush without updating write pointer. Otherwise - write pointer wraps and your pointer states are messed up. This can only happen if you - use DMAs, write functions do not allow such an error. Avoid such nasty things! - - All reading functions (read, peek) check for overflows and correct read pointer on their own such - that latest items are read. - If required (e.g. for DMA use) you can also correct the read pointer by - tu_fifo_correct_read_pointer(). - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns True if overflow happened - */ -/******************************************************************************/ -bool tu_fifo_overflowed(tu_fifo_t* f) -{ - return _tu_fifo_overflowed(f, f->wr_idx, f->rd_idx); -} - -// Only use in case tu_fifo_overflow() returned true! -void tu_fifo_correct_read_pointer(tu_fifo_t* f) -{ - _ff_lock(f->mutex_rd); - _tu_fifo_correct_read_pointer(f, f->wr_idx); - _ff_unlock(f->mutex_rd); -} - -/******************************************************************************/ -/*! - @brief Read one element out of the buffer. - - This function will return the element located at the array index of the - read pointer, and then increment the read pointer index. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] buffer - Pointer to the place holder for data read from the buffer - - @returns TRUE if the queue is not empty - */ -/******************************************************************************/ -bool tu_fifo_read(tu_fifo_t* f, void * buffer) -{ - _ff_lock(f->mutex_rd); - - // Peek the data - // f->rd_idx might get modified in case of an overflow so we can not use a local variable - bool ret = _tu_fifo_peek(f, buffer, f->wr_idx, f->rd_idx); - - // Advance pointer - f->rd_idx = advance_pointer(f, f->rd_idx, ret); - - _ff_unlock(f->mutex_rd); - return ret; -} - -/******************************************************************************/ -/*! - @brief This function will read n elements from the array index specified by - the read pointer and increment the read index. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] buffer - The pointer to data location - @param[in] n - Number of element that buffer can afford - - @returns number of items read from the FIFO - */ -/******************************************************************************/ -uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n) -{ - return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_INC); -} - -uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint16_t n) -{ - return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST_FULL_WORDS); -} - -/******************************************************************************/ -/*! - @brief Read one item without removing it from the FIFO. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] offset - Position to read from in the FIFO buffer with respect to read pointer - @param[in] p_buffer - Pointer to the place holder for data read from the buffer - - @returns TRUE if the queue is not empty - */ -/******************************************************************************/ -bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) -{ - _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek(f, p_buffer, f->wr_idx, f->rd_idx); - _ff_unlock(f->mutex_rd); - return ret; -} - -/******************************************************************************/ -/*! - @brief Read n items without removing it from the FIFO - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] p_buffer - Pointer to the place holder for data read from the buffer - @param[in] n - Number of items to peek - - @returns Number of bytes written to p_buffer - */ -/******************************************************************************/ -uint16_t tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n) -{ - _ff_lock(f->mutex_rd); - uint16_t ret = _tu_fifo_peek_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); - _ff_unlock(f->mutex_rd); - return ret; -} - -/******************************************************************************/ -/*! - @brief Write one element into the buffer. - - This function will write one element into the array index specified by - the write pointer and increment the write index. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - The byte to add to the FIFO - - @returns TRUE if the data was written to the FIFO (overwrittable - FIFO will always return TRUE) - */ -/******************************************************************************/ -bool tu_fifo_write(tu_fifo_t* f, const void * data) -{ - _ff_lock(f->mutex_wr); - - bool ret; - uint16_t const w = f->wr_idx; - - if ( _tu_fifo_full(f, w, f->rd_idx) && !f->overwritable ) - { - ret = false; - }else - { - uint16_t wRel = get_relative_pointer(f, w); - - // Write data - _ff_push(f, data, wRel); - - // Advance pointer - f->wr_idx = advance_pointer(f, w, 1); - - ret = true; - } - - _ff_unlock(f->mutex_wr); - - return ret; -} - -/******************************************************************************/ -/*! - @brief This function will write n elements into the array index specified by - the write pointer and increment the write index. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - The pointer to data to add to the FIFO - @param[in] count - Number of element - @return Number of written elements - */ -/******************************************************************************/ -uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n) -{ - return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_INC); -} - -/******************************************************************************/ -/*! - @brief This function will write n elements into the array index specified by - the write pointer and increment the write index. The source address will - not be incremented which is useful for reading from registers. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - The pointer to data to add to the FIFO - @param[in] count - Number of element - @return Number of written elements - */ -/******************************************************************************/ -uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t* f, const void * data, uint16_t n) -{ - return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_CST_FULL_WORDS); -} - -/******************************************************************************/ -/*! - @brief Clear the fifo read and write pointers - - @param[in] f - Pointer to the FIFO buffer to manipulate - */ -/******************************************************************************/ -bool tu_fifo_clear(tu_fifo_t *f) -{ - _ff_lock(f->mutex_wr); - _ff_lock(f->mutex_rd); - - f->rd_idx = f->wr_idx = 0; - f->max_pointer_idx = 2*f->depth-1; - f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; - - _ff_unlock(f->mutex_wr); - _ff_unlock(f->mutex_rd); - return true; -} - -/******************************************************************************/ -/*! - @brief Change the fifo mode to overwritable or not overwritable - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] overwritable - Overwritable mode the fifo is set to - */ -/******************************************************************************/ -bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) -{ - _ff_lock(f->mutex_wr); - _ff_lock(f->mutex_rd); - - f->overwritable = overwritable; - - _ff_unlock(f->mutex_wr); - _ff_unlock(f->mutex_rd); - - return true; -} - -/******************************************************************************/ -/*! - @brief Advance write pointer - intended to be used in combination with DMA. - It is possible to fill the FIFO by use of a DMA in circular mode. Within - DMA ISRs you may update the write pointer to be able to read from the FIFO. - As long as the DMA is the only process writing into the FIFO this is safe - to use. - - USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] n - Number of items the write pointer moves forward - */ -/******************************************************************************/ -void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) -{ - f->wr_idx = advance_pointer(f, f->wr_idx, n); -} - -/******************************************************************************/ -/*! - @brief Advance read pointer - intended to be used in combination with DMA. - It is possible to read from the FIFO by use of a DMA in linear mode. Within - DMA ISRs you may update the read pointer to be able to again write into the - FIFO. As long as the DMA is the only process reading from the FIFO this is - safe to use. - - USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] n - Number of items the read pointer moves forward - */ -/******************************************************************************/ -void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) -{ - f->rd_idx = advance_pointer(f, f->rd_idx, n); -} - -/******************************************************************************/ -/*! - @brief Get read info - - Returns the length and pointer from which bytes can be read in a linear manner. - This is of major interest for DMA transmissions. If returned length is zero the - corresponding pointer is invalid. - The read pointer does NOT get advanced, use tu_fifo_advance_read_pointer() to - do so! - @param[in] f - Pointer to FIFO - @param[out] *info - Pointer to struct which holds the desired infos - */ -/******************************************************************************/ -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) -{ - // Operate on temporary values in case they change in between - uint16_t w = f->wr_idx, r = f->rd_idx; - - uint16_t cnt = _tu_fifo_count(f, w, r); - - // Check overflow and correct if required - may happen in case a DMA wrote too fast - if (cnt > f->depth) - { - _ff_lock(f->mutex_rd); - _tu_fifo_correct_read_pointer(f, w); - _ff_unlock(f->mutex_rd); - r = f->rd_idx; - cnt = f->depth; - } - - // Check if fifo is empty - if (cnt == 0) - { - info->len_lin = 0; - info->len_wrap = 0; - info->ptr_lin = NULL; - info->ptr_wrap = NULL; - return; - } - - // Get relative pointers - w = get_relative_pointer(f, w); - r = get_relative_pointer(f, r); - - // Copy pointer to buffer to start reading from - info->ptr_lin = &f->buffer[r]; - - // Check if there is a wrap around necessary - if (w > r) { - // Non wrapping case - info->len_lin = cnt; - info->len_wrap = 0; - info->ptr_wrap = NULL; - } - else - { - info->len_lin = f->depth - r; // Also the case if FIFO was full - info->len_wrap = cnt - info->len_lin; - info->ptr_wrap = f->buffer; - } -} - -/******************************************************************************/ -/*! - @brief Get linear write info - - Returns the length and pointer to which bytes can be written into FIFO in a linear manner. - This is of major interest for DMA transmissions not using circular mode. If a returned length is zero the - corresponding pointer is invalid. The returned lengths summed up are the currently free space in the FIFO. - The write pointer does NOT get advanced, use tu_fifo_advance_write_pointer() to do so! - TAKE CARE TO NOT OVERFLOW THE BUFFER MORE THAN TWO TIMES THE FIFO DEPTH - IT CAN NOT RECOVERE OTHERWISE! - @param[in] f - Pointer to FIFO - @param[out] *info - Pointer to struct which holds the desired infos - */ -/******************************************************************************/ -void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) -{ - uint16_t w = f->wr_idx, r = f->rd_idx; - uint16_t free = _tu_fifo_remaining(f, w, r); - - if (free == 0) - { - info->len_lin = 0; - info->len_wrap = 0; - info->ptr_lin = NULL; - info->ptr_wrap = NULL; - return; - } - - // Get relative pointers - w = get_relative_pointer(f, w); - r = get_relative_pointer(f, r); - - // Copy pointer to buffer to start writing to - info->ptr_lin = &f->buffer[w]; - - if (w < r) - { - // Non wrapping case - info->len_lin = r-w; - info->len_wrap = 0; - info->ptr_wrap = NULL; - } - else - { - info->len_lin = f->depth - w; - info->len_wrap = free - info->len_lin; // Remaining length - n already was limited to free or FIFO depth - info->ptr_wrap = f->buffer; // Always start of buffer - } -} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h deleted file mode 100644 index 18db289a1..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_fifo.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber - rework to unmasked pointers - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_FIFO_H_ -#define _TUSB_FIFO_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// Due to the use of unmasked pointers, this FIFO does not suffer from loosing -// one item slice. Furthermore, write and read operations are completely -// decoupled as write and read functions do not modify a common state. Henceforth, -// writing or reading from the FIFO within an ISR is safe as long as no other -// process (thread or ISR) interferes. -// Also, this FIFO is ready to be used in combination with a DMA as the write and -// read pointers can be updated from within a DMA ISR. Overflows are detectable -// within a certain number (see tu_fifo_overflow()). - -#include "common/tusb_common.h" - -// mutex is only needed for RTOS -// for OS None, we don't get preempted -#define CFG_FIFO_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) - -#if CFG_FIFO_MUTEX -#include "osal/osal.h" -#define tu_fifo_mutex_t osal_mutex_t -#endif - -typedef struct -{ - uint8_t* buffer ; ///< buffer pointer - uint16_t depth ; ///< max items - uint16_t item_size ; ///< size of each item - bool overwritable ; - - uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length - uint16_t max_pointer_idx ; ///< maximum absolute pointer index - - volatile uint16_t wr_idx ; ///< write pointer - volatile uint16_t rd_idx ; ///< read pointer - -#if CFG_FIFO_MUTEX - tu_fifo_mutex_t mutex_wr; - tu_fifo_mutex_t mutex_rd; -#endif - -} tu_fifo_t; - -typedef struct -{ - uint16_t len_lin ; ///< linear length in item size - uint16_t len_wrap ; ///< wrapped length in item size - void * ptr_lin ; ///< linear part start pointer - void * ptr_wrap ; ///< wrapped part start pointer -} tu_fifo_buffer_info_t; - -#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ -{ \ - .buffer = _buffer, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ - .non_used_index_space = UINT16_MAX - (2*(_depth)-1), \ - .max_pointer_idx = 2*(_depth)-1, \ -} - -#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) - - -bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); -bool tu_fifo_clear(tu_fifo_t *f); -bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); - -#if CFG_FIFO_MUTEX -TU_ATTR_ALWAYS_INLINE static inline -void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl) -{ - f->mutex_wr = write_mutex_hdl; - f->mutex_rd = read_mutex_hdl; -} -#endif - -bool tu_fifo_write (tu_fifo_t* f, void const * p_data); -uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t n); -uint16_t tu_fifo_write_n_const_addr_full_words (tu_fifo_t* f, const void * data, uint16_t n); - -bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); -uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); - -bool tu_fifo_peek (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_peek_n (tu_fifo_t* f, void * p_buffer, uint16_t n); - -uint16_t tu_fifo_count (tu_fifo_t* f); -uint16_t tu_fifo_remaining (tu_fifo_t* f); -bool tu_fifo_empty (tu_fifo_t* f); -bool tu_fifo_full (tu_fifo_t* f); -bool tu_fifo_overflowed (tu_fifo_t* f); -void tu_fifo_correct_read_pointer (tu_fifo_t* f); - -TU_ATTR_ALWAYS_INLINE static inline -uint16_t tu_fifo_depth(tu_fifo_t* f) -{ - return f->depth; -} - -// Pointer modifications intended to be used in combinations with DMAs. -// USE WITH CARE - NO SAFTY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! -void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n); -void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); - -// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies -// to handle a possible wrapping part. These functions deliver a pointer to start -// reading/writing from/to and a valid linear length along which no wrap occurs. -void tu_fifo_get_read_info (tu_fifo_t *f, tu_fifo_buffer_info_t *info); -void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); - - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_FIFO_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h deleted file mode 100644 index ce53955f0..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_timeout.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_Common Common Files - * \defgroup Group_TimeoutTimer timeout timer - * @{ */ - -#ifndef _TUSB_TIMEOUT_H_ -#define _TUSB_TIMEOUT_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint32_t start; - uint32_t interval; -}tu_timeout_t; - -#if 0 - -extern uint32_t tusb_hal_millis(void); - -static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec) -{ - tt->interval = msec; - tt->start = tusb_hal_millis(); -} - -static inline bool tu_timeout_expired(tu_timeout_t* tt) -{ - return ( tusb_hal_millis() - tt->start ) >= tt->interval; -} - -// For used with periodic event to prevent drift -static inline void tu_timeout_reset(tu_timeout_t* tt) -{ - tt->start += tt->interval; -} - -static inline void tu_timeout_restart(tu_timeout_t* tt) -{ - tt->start = tusb_hal_millis(); -} - -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_TIMEOUT_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h deleted file mode 100644 index 5b26f5aec..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_types.h +++ /dev/null @@ -1,546 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_usb_definitions - * \defgroup USBDef_Type USB Types - * @{ */ - -#ifndef _TUSB_TYPES_H_ -#define _TUSB_TYPES_H_ - -#include -#include -#include "tusb_compiler.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/*------------------------------------------------------------------*/ -/* CONSTANTS - *------------------------------------------------------------------*/ - -/// defined base on EHCI specs value for Endpoint Speed -typedef enum -{ - TUSB_SPEED_FULL = 0, - TUSB_SPEED_LOW = 1, - TUSB_SPEED_HIGH = 2, - TUSB_SPEED_INVALID = 0xff, -}tusb_speed_t; - -/// defined base on USB Specs Endpoint's bmAttributes -typedef enum -{ - TUSB_XFER_CONTROL = 0 , - TUSB_XFER_ISOCHRONOUS , - TUSB_XFER_BULK , - TUSB_XFER_INTERRUPT -}tusb_xfer_type_t; - -typedef enum -{ - TUSB_DIR_OUT = 0, - TUSB_DIR_IN = 1, - - TUSB_DIR_IN_MASK = 0x80 -}tusb_dir_t; - -/// Isochronous End Point Attributes -typedef enum -{ - TUSB_ISO_EP_ATT_NO_SYNC = 0x00, - TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, - TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, - TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, - TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point - TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point - TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback -}tusb_iso_ep_attribute_t; - -/// USB Descriptor Types -typedef enum -{ - TUSB_DESC_DEVICE = 0x01, - TUSB_DESC_CONFIGURATION = 0x02, - TUSB_DESC_STRING = 0x03, - TUSB_DESC_INTERFACE = 0x04, - TUSB_DESC_ENDPOINT = 0x05, - TUSB_DESC_DEVICE_QUALIFIER = 0x06, - TUSB_DESC_OTHER_SPEED_CONFIG = 0x07, - TUSB_DESC_INTERFACE_POWER = 0x08, - TUSB_DESC_OTG = 0x09, - TUSB_DESC_DEBUG = 0x0A, - TUSB_DESC_INTERFACE_ASSOCIATION = 0x0B, - - TUSB_DESC_BOS = 0x0F, - TUSB_DESC_DEVICE_CAPABILITY = 0x10, - - TUSB_DESC_FUNCTIONAL = 0x21, - - // Class Specific Descriptor - TUSB_DESC_CS_DEVICE = 0x21, - TUSB_DESC_CS_CONFIGURATION = 0x22, - TUSB_DESC_CS_STRING = 0x23, - TUSB_DESC_CS_INTERFACE = 0x24, - TUSB_DESC_CS_ENDPOINT = 0x25, - - TUSB_DESC_SUPERSPEED_ENDPOINT_COMPANION = 0x30, - TUSB_DESC_SUPERSPEED_ISO_ENDPOINT_COMPANION = 0x31 -}tusb_desc_type_t; - -typedef enum -{ - TUSB_REQ_GET_STATUS = 0 , - TUSB_REQ_CLEAR_FEATURE = 1 , - TUSB_REQ_RESERVED = 2 , - TUSB_REQ_SET_FEATURE = 3 , - TUSB_REQ_RESERVED2 = 4 , - TUSB_REQ_SET_ADDRESS = 5 , - TUSB_REQ_GET_DESCRIPTOR = 6 , - TUSB_REQ_SET_DESCRIPTOR = 7 , - TUSB_REQ_GET_CONFIGURATION = 8 , - TUSB_REQ_SET_CONFIGURATION = 9 , - TUSB_REQ_GET_INTERFACE = 10 , - TUSB_REQ_SET_INTERFACE = 11 , - TUSB_REQ_SYNCH_FRAME = 12 -}tusb_request_code_t; - -typedef enum -{ - TUSB_REQ_FEATURE_EDPT_HALT = 0, - TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1, - TUSB_REQ_FEATURE_TEST_MODE = 2 -}tusb_request_feature_selector_t; - -typedef enum -{ - TUSB_REQ_TYPE_STANDARD = 0, - TUSB_REQ_TYPE_CLASS, - TUSB_REQ_TYPE_VENDOR, - TUSB_REQ_TYPE_INVALID -} tusb_request_type_t; - -typedef enum -{ - TUSB_REQ_RCPT_DEVICE =0, - TUSB_REQ_RCPT_INTERFACE, - TUSB_REQ_RCPT_ENDPOINT, - TUSB_REQ_RCPT_OTHER -} tusb_request_recipient_t; - -// https://www.usb.org/defined-class-codes -typedef enum -{ - TUSB_CLASS_UNSPECIFIED = 0 , - TUSB_CLASS_AUDIO = 1 , - TUSB_CLASS_CDC = 2 , - TUSB_CLASS_HID = 3 , - TUSB_CLASS_RESERVED_4 = 4 , - TUSB_CLASS_PHYSICAL = 5 , - TUSB_CLASS_IMAGE = 6 , - TUSB_CLASS_PRINTER = 7 , - TUSB_CLASS_MSC = 8 , - TUSB_CLASS_HUB = 9 , - TUSB_CLASS_CDC_DATA = 10 , - TUSB_CLASS_SMART_CARD = 11 , - TUSB_CLASS_RESERVED_12 = 12 , - TUSB_CLASS_CONTENT_SECURITY = 13 , - TUSB_CLASS_VIDEO = 14 , - TUSB_CLASS_PERSONAL_HEALTHCARE = 15 , - TUSB_CLASS_AUDIO_VIDEO = 16 , - - TUSB_CLASS_DIAGNOSTIC = 0xDC , - TUSB_CLASS_WIRELESS_CONTROLLER = 0xE0 , - TUSB_CLASS_MISC = 0xEF , - TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE , - TUSB_CLASS_VENDOR_SPECIFIC = 0xFF -}tusb_class_code_t; - -typedef enum -{ - MISC_SUBCLASS_COMMON = 2 -}misc_subclass_type_t; - -typedef enum -{ - MISC_PROTOCOL_IAD = 1 -}misc_protocol_type_t; - -typedef enum -{ - APP_SUBCLASS_USBTMC = 0x03, - APP_SUBCLASS_DFU_RUNTIME = 0x01 -} app_subclass_type_t; - -typedef enum -{ - DEVICE_CAPABILITY_WIRELESS_USB = 0x01, - DEVICE_CAPABILITY_USB20_EXTENSION = 0x02, - DEVICE_CAPABILITY_SUPERSPEED_USB = 0x03, - DEVICE_CAPABILITY_CONTAINER_id = 0x04, - DEVICE_CAPABILITY_PLATFORM = 0x05, - DEVICE_CAPABILITY_POWER_DELIVERY = 0x06, - DEVICE_CAPABILITY_BATTERY_INFO = 0x07, - DEVICE_CAPABILITY_PD_CONSUMER_PORT = 0x08, - DEVICE_CAPABILITY_PD_PROVIDER_PORT = 0x09, - DEVICE_CAPABILITY_SUPERSPEED_PLUS = 0x0A, - DEVICE_CAPABILITY_PRECESION_TIME_MEASUREMENT = 0x0B, - DEVICE_CAPABILITY_WIRELESS_USB_EXT = 0x0C, - DEVICE_CAPABILITY_BILLBOARD = 0x0D, - DEVICE_CAPABILITY_AUTHENTICATION = 0x0E, - DEVICE_CAPABILITY_BILLBOARD_EX = 0x0F, - DEVICE_CAPABILITY_CONFIGURATION_SUMMARY = 0x10 -}device_capability_type_t; - -enum { - TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5), - TUSB_DESC_CONFIG_ATT_SELF_POWERED = TU_BIT(6), -}; - -#define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2) - -/// Device State TODO remove -typedef enum -{ - TUSB_DEVICE_STATE_UNPLUG = 0 , - TUSB_DEVICE_STATE_CONFIGURED , - TUSB_DEVICE_STATE_SUSPENDED , -}tusb_device_state_t; - -typedef enum -{ - XFER_RESULT_SUCCESS, - XFER_RESULT_FAILED, - XFER_RESULT_STALLED, -}xfer_result_t; - -enum // TODO remove -{ - DESC_OFFSET_LEN = 0, - DESC_OFFSET_TYPE = 1 -}; - -enum -{ - INTERFACE_INVALID_NUMBER = 0xff -}; - - -typedef enum -{ - MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00, - MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01, - MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02, - MS_OS_20_FEATURE_COMPATBLE_ID = 0x03, - MS_OS_20_FEATURE_REG_PROPERTY = 0x04, - MS_OS_20_FEATURE_MIN_RESUME_TIME = 0x05, - MS_OS_20_FEATURE_MODEL_ID = 0x06, - MS_OS_20_FEATURE_CCGP_DEVICE = 0x07, - MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 -} microsoft_os_20_type_t; - -enum -{ - CONTROL_STAGE_SETUP, - CONTROL_STAGE_DATA, - CONTROL_STAGE_ACK -}; - -//--------------------------------------------------------------------+ -// USB Descriptors -//--------------------------------------------------------------------+ - -// Start of all packed definitions for compiler without per-type packed -TU_ATTR_PACKED_BEGIN -TU_ATTR_BIT_FIELD_ORDER_BEGIN - -/// USB Device Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< DEVICE Descriptor Type. - uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant. - - uint8_t bDeviceClass ; ///< Class code (assigned by the USB-IF). \li If this field is reset to zero, each interface within a configuration specifies its own class information and the various interfaces operate independently. \li If this field is set to a value between 1 and FEH, the device supports different class specifications on different interfaces and the interfaces may not operate independently. This value identifies the class definition used for the aggregate interfaces. \li If this field is set to FFH, the device class is vendor-specific. - uint8_t bDeviceSubClass ; ///< Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass field. \li If the bDeviceClass field is reset to zero, this field must also be reset to zero. \li If the bDeviceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. - uint8_t bDeviceProtocol ; ///< Protocol code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass and the bDeviceSubClass fields. If a device supports class-specific protocols on a device basis as opposed to an interface basis, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use class-specific protocols on a device basis. However, it may use classspecific protocols on an interface basis. \li If this field is set to FFH, the device uses a vendor-specific protocol on a device basis. - uint8_t bMaxPacketSize0 ; ///< Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid). For HS devices is fixed to 64. - - uint16_t idVendor ; ///< Vendor ID (assigned by the USB-IF). - uint16_t idProduct ; ///< Product ID (assigned by the manufacturer). - uint16_t bcdDevice ; ///< Device release number in binary-coded decimal. - uint8_t iManufacturer ; ///< Index of string descriptor describing manufacturer. - uint8_t iProduct ; ///< Index of string descriptor describing product. - uint8_t iSerialNumber ; ///< Index of string descriptor describing the device's serial number. - - uint8_t bNumConfigurations ; ///< Number of possible configurations. -} tusb_desc_device_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); - -// USB Binary Device Object Store (BOS) Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes - uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type - uint16_t wTotalLength ; ///< Total length of data returned for this descriptor - uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS -} tusb_desc_bos_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct"); - -/// USB Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes - uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type - uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration. - - uint8_t bNumInterfaces ; ///< Number of interfaces supported by this configuration - uint8_t bConfigurationValue ; ///< Value to use as an argument to the SetConfiguration() request to select this configuration. - uint8_t iConfiguration ; ///< Index of string descriptor describing this configuration - uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. - uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). -} tusb_desc_configuration_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); - -/// USB Interface Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes - uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type - - uint8_t bInterfaceNumber ; ///< Number of this interface. Zero-based value identifying the index in the array of concurrent interfaces supported by this configuration. - uint8_t bAlternateSetting ; ///< Value used to select this alternate setting for the interface identified in the prior field - uint8_t bNumEndpoints ; ///< Number of endpoints used by this interface (excluding endpoint zero). If this value is zero, this interface only uses the Default Control Pipe. - uint8_t bInterfaceClass ; ///< Class code (assigned by the USB-IF). \li A value of zero is reserved for future standardization. \li If this field is set to FFH, the interface class is vendor-specific. \li All other values are reserved for assignment by the USB-IF. - uint8_t bInterfaceSubClass ; ///< Subclass code (assigned by the USB-IF). \n These codes are qualified by the value of the bInterfaceClass field. \li If the bInterfaceClass field is reset to zero, this field must also be reset to zero. \li If the bInterfaceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. - uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. - uint8_t iInterface ; ///< Index of string descriptor describing this interface -} tusb_desc_interface_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); - -/// USB Endpoint Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; // Size of this descriptor in bytes - uint8_t bDescriptorType ; // ENDPOINT Descriptor Type - - uint8_t bEndpointAddress ; // The address of the endpoint - - struct TU_ATTR_PACKED { - uint8_t xfer : 2; // Control, ISO, Bulk, Interrupt - uint8_t sync : 2; // None, Asynchronous, Adaptive, Synchronous - uint8_t usage : 2; // Data, Feedback, Implicit feedback - uint8_t : 2; - } bmAttributes; - - uint16_t wMaxPacketSize ; // Bit 10..0 : max packet size, bit 12..11 additional transaction per highspeed micro-frame - uint8_t bInterval ; // Polling interval, in frames or microframes depending on the operating speed -} tusb_desc_endpoint_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct"); - -/// USB Other Speed Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of descriptor - uint8_t bDescriptorType ; ///< Other_speed_Configuration Type - uint16_t wTotalLength ; ///< Total length of data returned - - uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration - uint8_t bConfigurationValue ; ///< Value to use to select configuration - uint8_t iConfiguration ; ///< Index of string descriptor - uint8_t bmAttributes ; ///< Same as Configuration descriptor - uint8_t bMaxPower ; ///< Same as Configuration descriptor -} tusb_desc_other_speed_t; - -/// USB Device Qualifier Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of descriptor - uint8_t bDescriptorType ; ///< Device Qualifier Type - uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) - - uint8_t bDeviceClass ; ///< Class Code - uint8_t bDeviceSubClass ; ///< SubClass Code - uint8_t bDeviceProtocol ; ///< Protocol Code - - uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed - uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations - uint8_t bReserved ; ///< Reserved for future use, must be zero -} tusb_desc_device_qualifier_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct"); - -/// USB Interface Association Descriptor (IAD ECN) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of descriptor - uint8_t bDescriptorType ; ///< Other_speed_Configuration Type - - uint8_t bFirstInterface ; ///< Index of the first associated interface. - uint8_t bInterfaceCount ; ///< Total number of associated interfaces. - - uint8_t bFunctionClass ; ///< Interface class ID. - uint8_t bFunctionSubClass ; ///< Interface subclass ID. - uint8_t bFunctionProtocol ; ///< Interface protocol ID. - - uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. -} tusb_desc_interface_assoc_t; - -// USB String Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes - uint8_t bDescriptorType ; ///< Descriptor Type - uint16_t unicode_string[]; -} tusb_desc_string_t; - -// USB Binary Device Object Store (BOS) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength; - uint8_t bDescriptorType ; - uint8_t bDevCapabilityType; - uint8_t bReserved; - uint8_t PlatformCapabilityUUID[16]; - uint8_t CapabilityData[]; -} tusb_desc_bos_platform_t; - -// USB WebuSB URL Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bScheme; - char url[]; -} tusb_desc_webusb_url_t; - -// DFU Functional Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength; - uint8_t bDescriptorType; - - union { - struct TU_ATTR_PACKED { - uint8_t bitCanDnload : 1; - uint8_t bitCanUpload : 1; - uint8_t bitManifestationTolerant : 1; - uint8_t bitWillDetach : 1; - uint8_t reserved : 4; - } bmAttributes; - - uint8_t bAttributes; - }; - - uint16_t wDetachTimeOut; - uint16_t wTransferSize; - uint16_t bcdDFUVersion; -} tusb_desc_dfu_functional_t; - -/*------------------------------------------------------------------*/ -/* Types - *------------------------------------------------------------------*/ -typedef struct TU_ATTR_PACKED{ - union { - struct TU_ATTR_PACKED { - uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. - uint8_t type : 2; ///< Request type tusb_request_type_t. - uint8_t direction : 1; ///< Direction type. tusb_dir_t - } bmRequestType_bit; - - uint8_t bmRequestType; - }; - - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; -} tusb_control_request_t; - -TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); - - -TU_ATTR_PACKED_END // End of all packed definitions -TU_ATTR_BIT_FIELD_ORDER_END - -//--------------------------------------------------------------------+ -// Endpoint helper -//--------------------------------------------------------------------+ - -// Get direction from Endpoint address -static inline tusb_dir_t tu_edpt_dir(uint8_t addr) -{ - return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; -} - -// Get Endpoint number from address -static inline uint8_t tu_edpt_number(uint8_t addr) -{ - return (uint8_t)(addr & (~TUSB_DIR_IN_MASK)); -} - -static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) -{ - return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0)); -} - -static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) -{ - return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0); -} - -//--------------------------------------------------------------------+ -// Descriptor helper -//--------------------------------------------------------------------+ -static inline uint8_t const * tu_desc_next(void const* desc) -{ - uint8_t const* desc8 = (uint8_t const*) desc; - return desc8 + desc8[DESC_OFFSET_LEN]; -} - -static inline uint8_t tu_desc_type(void const* desc) -{ - return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; -} - -static inline uint8_t tu_desc_len(void const* desc) -{ - return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_TYPES_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h deleted file mode 100644 index 8fef11dc7..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/common/tusb_verify.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ -#ifndef TUSB_VERIFY_H_ -#define TUSB_VERIFY_H_ - -#include -#include -#include "tusb_option.h" -#include "tusb_compiler.h" - -/*------------------------------------------------------------------*/ -/* This file use an advanced macro technique to mimic the default parameter - * as C++ for the sake of code simplicity. Beware of a headache macro - * manipulation that you are told to stay away. - * - * This contains macros for both VERIFY and ASSERT: - * - * VERIFY: Used when there is an error condition which is not the - * fault of the MCU. For example, bounds checking on data - * sent to the micro over USB should use this function. - * Another example is checking for buffer overflows, where - * returning from the active function causes a NAK. - * - * ASSERT: Used for error conditions that are caused by MCU firmware - * bugs. This is used to discover bugs in the code more - * quickly. One example would be adding assertions in library - * function calls to confirm a function's (untainted) - * parameters are valid. - * - * The difference in behavior is that ASSERT triggers a breakpoint while - * verify does not. - * - * #define TU_VERIFY(cond) if(cond) return false; - * #define TU_VERIFY(cond,ret) if(cond) return ret; - * - * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;} - * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;} - * - * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} - * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} - * - *------------------------------------------------------------------*/ - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TU_VERIFY Helper -//--------------------------------------------------------------------+ - -#if CFG_TUSB_DEBUG - #include - #define _MESS_ERR(_err) tu_printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) - #define _MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__) -#else - #define _MESS_ERR(_err) do {} while (0) - #define _MESS_FAILED() do {} while (0) -#endif - -// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33 -#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) - #define TU_BREAKPOINT() do \ - { \ - volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ - } while(0) - -#elif defined(__riscv) - #define TU_BREAKPOINT() do { __asm("ebreak\n"); } while(0) - -#else - #define TU_BREAKPOINT() do {} while (0) -#endif - -/*------------------------------------------------------------------*/ -/* Macro Generator - *------------------------------------------------------------------*/ - -// Helper to implement optional parameter for TU_VERIFY Macro family -#define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 -#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 - -/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/ -#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do \ -{ \ - if ( !(_cond) ) { _handler; return _ret; } \ -} while(0) - -/*------------------------------------------------------------------*/ -/* TU_VERIFY - * - TU_VERIFY_1ARGS : return false if failed - * - TU_VERIFY_2ARGS : return provided value if failed - *------------------------------------------------------------------*/ -#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false) -#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret) - -#define TU_VERIFY(...) GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__) - - -/*------------------------------------------------------------------*/ -/* TU_VERIFY WITH HANDLER - * - TU_VERIFY_HDLR_2ARGS : execute handler, return false if failed - * - TU_VERIFY_HDLR_3ARGS : execute handler, return provided error if failed - *------------------------------------------------------------------*/ -#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false) -#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret) - -#define TU_VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__) - -/*------------------------------------------------------------------*/ -/* ASSERT - * basically TU_VERIFY with TU_BREAKPOINT() as handler - * - 1 arg : return false if failed - * - 2 arg : return error if failed - *------------------------------------------------------------------*/ -#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false) -#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret) - -#ifndef TU_ASSERT -#define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__) -#endif - -// TODO remove TU_ASSERT_ERR() later - -/*------------- Generator for TU_VERIFY_ERR and TU_VERIFY_ERR_HDLR -------------*/ -#define TU_VERIFY_ERR_DEF2(_error, _handler) do \ -{ \ - uint32_t _err = (uint32_t)(_error); \ - if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _err; } \ -} while(0) - -#define TU_VERIFY_ERR_DEF3(_error, _handler, _ret) do \ -{ \ - uint32_t _err = (uint32_t)(_error); \ - if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _ret; } \ -} while(0) - -/*------------------------------------------------------------------*/ -/* ASSERT Error - * basically TU_VERIFY Error with TU_BREAKPOINT() as handler - *------------------------------------------------------------------*/ -#define ASSERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, TU_BREAKPOINT()) -#define ASSERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, TU_BREAKPOINT(), _ret) - -#ifndef TU_ASSERT_ERR -#define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_ERR_2ARGS, ASSERT_ERR_1ARGS,UNUSED)(__VA_ARGS__) -#endif - -/*------------------------------------------------------------------*/ -/* ASSERT HDLR - *------------------------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif /* TUSB_VERIFY_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h deleted file mode 100644 index c042cc708..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DCD_H_ -#define _TUSB_DCD_H_ - -#include "common/tusb_common.h" -#include "osal/osal.h" -#include "common/tusb_fifo.h" -#include "dcd_attr.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Configuration -//--------------------------------------------------------------------+ - -#ifndef CFG_TUD_ENDPPOINT_MAX - #define CFG_TUD_ENDPPOINT_MAX DCD_ATTR_ENDPOINT_MAX -#endif - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES -//--------------------------------------------------------------------+ - -typedef enum -{ - DCD_EVENT_INVALID = 0, - DCD_EVENT_BUS_RESET, - DCD_EVENT_UNPLUGGED, - DCD_EVENT_SOF, - DCD_EVENT_SUSPEND, // TODO LPM Sleep L1 support - DCD_EVENT_RESUME, - - DCD_EVENT_SETUP_RECEIVED, - DCD_EVENT_XFER_COMPLETE, - - // Not an DCD event, just a convenient way to defer ISR function - USBD_EVENT_FUNC_CALL, - - DCD_EVENT_COUNT -} dcd_eventid_t; - -typedef struct TU_ATTR_ALIGNED(4) -{ - uint8_t rhport; - uint8_t event_id; - - union - { - // BUS RESET - struct { - tusb_speed_t speed; - } bus_reset; - - // SETUP_RECEIVED - tusb_control_request_t setup_received; - - // XFER_COMPLETE - struct { - uint8_t ep_addr; - uint8_t result; - uint32_t len; - }xfer_complete; - - // FUNC_CALL - struct { - void (*func) (void*); - void* param; - }func_call; - }; -} dcd_event_t; - -//TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); - -//--------------------------------------------------------------------+ -// Controller API -//--------------------------------------------------------------------+ - -// Initialize controller to device mode -void dcd_init (uint8_t rhport); - -// Interrupt Handler -#if __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wredundant-decls" -#endif -void dcd_int_handler(uint8_t rhport); -#if __GNUC__ -#pragma GCC diagnostic pop -#endif - -// Enable device interrupt -void dcd_int_enable (uint8_t rhport); - -// Disable device interrupt -void dcd_int_disable(uint8_t rhport); - -// Receive Set Address request, mcu port must also include status IN response -void dcd_set_address(uint8_t rhport, uint8_t dev_addr); - -// Wake up host -void dcd_remote_wakeup(uint8_t rhport); - -// Connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; - -// Disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; - -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ - -// Invoked when a control transfer's status stage is complete. -// May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; - -// Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); - -// Close all non-control endpoints, cancel all pending transfers if any. -// Invoked when switching from a non-zero Configuration by SET_CONFIGURE therefore -// required for multiple configuration support. -void dcd_edpt_close_all (uint8_t rhport); - -// Close an endpoint. -// Since it is weak, caller must TU_ASSERT this function's existence before calling it. -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; - -// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -// Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack -// This API is optional, may be useful for register-based for transferring data. -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; - -// Stall endpoint, any queuing transfer should be removed from endpoint -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); - -// clear stall, data toggle is also reset to DATA0 -// This API never calls with control endpoints, since it is auto cleared when receiving setup packet -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); - -//--------------------------------------------------------------------+ -// Event API (implemented by stack) -//--------------------------------------------------------------------+ - -// Called by DCD to notify device stack -extern void dcd_event_handler(dcd_event_t const * event, bool in_isr); - -// helper to send bus signal event -extern void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr); - -// helper to send bus reset event -extern void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr); - -// helper to send setup received -extern void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr); - -// helper to send transfer complete event -extern void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DCD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h deleted file mode 100644 index b40c2ad07..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/dcd_attr.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_DCD_ATTR_H_ -#define TUSB_DCD_ATTR_H_ - -#include "tusb_option.h" - -// Attribute includes -// - ENDPOINT_MAX: max (logical) number of endpoint -// - ENDPOINT_EXCLUSIVE_NUMBER: endpoint number with different direction IN and OUT aren't allowed, -// e.g EP1 OUT & EP1 IN cannot exist together -// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. - -//------------- NXP -------------// -#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) - #define DCD_ATTR_ENDPOINT_MAX 5 - -#elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) - #define DCD_ATTR_ENDPOINT_MAX 16 - -#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) - // TODO USB0 has 6, USB1 has 4 - #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS - #define DCD_ATTR_ENDPOINT_MAX 6 - -#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) - #define DCD_ATTR_ENDPOINT_MAX 5 - -#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) - // TODO USB0 has 5, USB1 has 6 - #define DCD_ATTR_ENDPOINT_MAX 6 - -#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) - // TODO USB0 has 5, USB1 has 6 - #define DCD_ATTR_ENDPOINT_MAX 6 - -#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX) - #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX, OPT_MCU_K32L2BXX) - #define DCD_ATTR_ENDPOINT_MAX 16 - -#elif TU_CHECK_MCU(OPT_MCU_MM32F327X) - #define DCD_ATTR_ENDPOINT_MAX 16 - -//------------- Nordic -------------// -#elif TU_CHECK_MCU(OPT_MCU_NRF5X) - // 8 CBI + 1 ISO - #define DCD_ATTR_ENDPOINT_MAX 9 - -//------------- Microchip -------------// -#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ - TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_SAMG) - #define DCD_ATTR_ENDPOINT_MAX 6 - #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER - -#elif TU_CHECK_MCU(OPT_MCU_SAMX7X) - #define DCD_ATTR_ENDPOINT_MAX 10 - #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER - -#elif TU_CHECK_MCU(OPT_MCU_PIC32MZ) - #define DCD_ATTR_ENDPOINT_MAX 8 - #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER - -//------------- ST -------------// -#elif TU_CHECK_MCU(OPT_MCU_STM32F0) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32F1) - #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ - defined (STM32F107xB) || defined (STM32F107xC) - #define DCD_ATTR_ENDPOINT_MAX 4 - #define DCD_ATTR_DWC2_STM32 - #else - #define DCD_ATTR_ENDPOINT_MAX 8 - #endif - -#elif TU_CHECK_MCU(OPT_MCU_STM32F2) - // FS has 4 ep, HS has 5 ep - #define DCD_ATTR_ENDPOINT_MAX 6 - #define DCD_ATTR_DWC2_STM32 - -#elif TU_CHECK_MCU(OPT_MCU_STM32F3) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32F4) - // For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9 - #define DCD_ATTR_ENDPOINT_MAX 6 - #define DCD_ATTR_DWC2_STM32 - -#elif TU_CHECK_MCU(OPT_MCU_STM32F7) - // FS has 6, HS has 9 - #define DCD_ATTR_ENDPOINT_MAX 9 - #define DCD_ATTR_DWC2_STM32 - -#elif TU_CHECK_MCU(OPT_MCU_STM32H7) - #define DCD_ATTR_ENDPOINT_MAX 9 - #define DCD_ATTR_DWC2_STM32 - -#elif TU_CHECK_MCU(OPT_MCU_STM32G4) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_STM32L4) - #if defined (STM32L475xx) || defined (STM32L476xx) || \ - defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ - defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \ - defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ - defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) - #define DCD_ATTR_ENDPOINT_MAX 6 - #define DCD_ATTR_DWC2_STM32 - #else - #define DCD_ATTR_ENDPOINT_MAX 8 - #endif - -//------------- Sony -------------// -#elif TU_CHECK_MCU(OPT_MCU_CXD56) - #define DCD_ATTR_ENDPOINT_MAX 7 - #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER - -//------------- TI -------------// -#elif TU_CHECK_MCU(OPT_MCU_MSP430x5xx) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) - #define DCD_ATTR_ENDPOINT_MAX 8 - -//------------- ValentyUSB -------------// -#elif TU_CHECK_MCU(OPT_MCU_VALENTYUSB_EPTRI) - #define DCD_ATTR_ENDPOINT_MAX 16 - -//------------- Nuvoton -------------// -#elif TU_CHECK_MCU(OPT_MCU_NUC121, OPT_MCU_NUC126) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_NUC120) - #define DCD_ATTR_ENDPOINT_MAX 6 - -#elif TU_CHECK_MCU(OPT_MCU_NUC505) - #define DCD_ATTR_ENDPOINT_MAX 12 - -//------------- Espressif -------------// -#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - #define DCD_ATTR_ENDPOINT_MAX 6 - -//------------- Dialog -------------// -#elif TU_CHECK_MCU(OPT_MCU_DA1469X) - #define DCD_ATTR_ENDPOINT_MAX 4 - -//------------- Raspberry Pi -------------// -#elif TU_CHECK_MCU(OPT_MCU_RP2040) - #define DCD_ATTR_ENDPOINT_MAX 16 - -//------------- Silabs -------------// -#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) - #define DCD_ATTR_ENDPOINT_MAX 7 - -//------------- Renesas -------------// -#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) - #define DCD_ATTR_ENDPOINT_MAX 10 - -//------------- GigaDevice -------------// -#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) - #define DCD_ATTR_ENDPOINT_MAX 4 - -//------------- Broadcom -------------// -#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) - #define DCD_ATTR_ENDPOINT_MAX 8 - -//------------- Broadcom -------------// -#elif TU_CHECK_MCU(OPT_MCU_XMC4000) - #define DCD_ATTR_ENDPOINT_MAX 8 - -//------------- BridgeTek -------------// -#elif TU_CHECK_MCU(OPT_MCU_FT90X) - #define DCD_ATTR_ENDPOINT_MAX 8 - -#elif TU_CHECK_MCU(OPT_MCU_FT93X) - #define DCD_ATTR_ENDPOINT_MAX 16 - -#else - #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" - #define DCD_ATTR_ENDPOINT_MAX 8 -#endif - -// Default to fullspeed if not defined -//#ifndef PORT_HIGHSPEED -// #define DCD_ATTR_PORT_HIGHSPEED 0x00 -//#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c deleted file mode 100644 index 6a5210b34..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.c +++ /dev/null @@ -1,1419 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_DEVICE_ENABLED - -#include "tusb.h" -#include "device/usbd.h" -#include "device/usbd_pvt.h" -#include "device/dcd.h" - -//--------------------------------------------------------------------+ -// USBD Configuration -//--------------------------------------------------------------------+ - -// Debug level of USBD -#define USBD_DBG 2 - -#ifndef CFG_TUD_TASK_QUEUE_SZ - #define CFG_TUD_TASK_QUEUE_SZ 16 -#endif - -//--------------------------------------------------------------------+ -// Device Data -//--------------------------------------------------------------------+ - -// Invalid driver ID in itf2drv[] ep2drv[][] mapping -enum { DRVID_INVALID = 0xFFu }; - -typedef struct -{ - struct TU_ATTR_PACKED - { - volatile uint8_t connected : 1; - volatile uint8_t addressed : 1; - volatile uint8_t suspended : 1; - - uint8_t remote_wakeup_en : 1; // enable/disable by host - uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute - uint8_t self_powered : 1; // configuration descriptor's attribute - }; - - volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) - uint8_t speed; - - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) - - struct TU_ATTR_PACKED - { - volatile bool busy : 1; - volatile bool stalled : 1; - volatile bool claimed : 1; - - // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[CFG_TUD_ENDPPOINT_MAX][2]; - -}usbd_device_t; - -static usbd_device_t _usbd_dev; - -//--------------------------------------------------------------------+ -// Class Driver -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - #define DRIVER_NAME(_name) .name = _name, -#else - #define DRIVER_NAME(_name) -#endif - -// Built-in class drivers -static usbd_class_driver_t const _usbd_driver[] = -{ - #if CFG_TUD_CDC - { - DRIVER_NAME("CDC") - .init = cdcd_init, - .reset = cdcd_reset, - .open = cdcd_open, - .control_xfer_cb = cdcd_control_xfer_cb, - .xfer_cb = cdcd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_MSC - { - DRIVER_NAME("MSC") - .init = mscd_init, - .reset = mscd_reset, - .open = mscd_open, - .control_xfer_cb = mscd_control_xfer_cb, - .xfer_cb = mscd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_HID - { - DRIVER_NAME("HID") - .init = hidd_init, - .reset = hidd_reset, - .open = hidd_open, - .control_xfer_cb = hidd_control_xfer_cb, - .xfer_cb = hidd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_AUDIO - { - DRIVER_NAME("AUDIO") - .init = audiod_init, - .reset = audiod_reset, - .open = audiod_open, - .control_xfer_cb = audiod_control_xfer_cb, - .xfer_cb = audiod_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_VIDEO - { - DRIVER_NAME("VIDEO") - .init = videod_init, - .reset = videod_reset, - .open = videod_open, - .control_xfer_cb = videod_control_xfer_cb, - .xfer_cb = videod_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_MIDI - { - DRIVER_NAME("MIDI") - .init = midid_init, - .open = midid_open, - .reset = midid_reset, - .control_xfer_cb = midid_control_xfer_cb, - .xfer_cb = midid_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_VENDOR - { - DRIVER_NAME("VENDOR") - .init = vendord_init, - .reset = vendord_reset, - .open = vendord_open, - .control_xfer_cb = tud_vendor_control_xfer_cb, - .xfer_cb = vendord_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_USBTMC - { - DRIVER_NAME("TMC") - .init = usbtmcd_init_cb, - .reset = usbtmcd_reset_cb, - .open = usbtmcd_open_cb, - .control_xfer_cb = usbtmcd_control_xfer_cb, - .xfer_cb = usbtmcd_xfer_cb, - .sof = NULL - }, - #endif - - #if CFG_TUD_DFU_RUNTIME - { - DRIVER_NAME("DFU-RUNTIME") - .init = dfu_rtd_init, - .reset = dfu_rtd_reset, - .open = dfu_rtd_open, - .control_xfer_cb = dfu_rtd_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - - #if CFG_TUD_DFU - { - DRIVER_NAME("DFU") - .init = dfu_moded_init, - .reset = dfu_moded_reset, - .open = dfu_moded_open, - .control_xfer_cb = dfu_moded_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - - #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM - { - DRIVER_NAME("NET") - .init = netd_init, - .reset = netd_reset, - .open = netd_open, - .control_xfer_cb = netd_control_xfer_cb, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, - #endif - - #if CFG_TUD_BTH - { - DRIVER_NAME("BTH") - .init = btd_init, - .reset = btd_reset, - .open = btd_open, - .control_xfer_cb = btd_control_xfer_cb, - .xfer_cb = btd_xfer_cb, - .sof = NULL - }, - #endif -}; - -enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; - -// Additional class drivers implemented by application -static usbd_class_driver_t const * _app_driver = NULL; -static uint8_t _app_driver_count = 0; - -// virtually joins built-in and application drivers together. -// Application is positioned first to allow overwriting built-in ones. -static inline usbd_class_driver_t const * get_driver(uint8_t drvid) -{ - // Application drivers - if ( usbd_app_driver_get_cb ) - { - if ( drvid < _app_driver_count ) return &_app_driver[drvid]; - drvid -= _app_driver_count; - } - - // Built-in drivers - if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid]; - - return NULL; -} - -#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) - -//--------------------------------------------------------------------+ -// DCD Event -//--------------------------------------------------------------------+ - -static bool _usbd_initialized = false; - -// Event queue -// OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr) -OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); -static osal_queue_t _usbd_q; - -// Mutex for claiming endpoint, only needed when using with preempted RTOS -#if CFG_TUSB_OS != OPT_OS_NONE -static osal_mutex_def_t _ubsd_mutexdef; -static osal_mutex_t _usbd_mutex; -#endif - - -//--------------------------------------------------------------------+ -// Prototypes -//--------------------------------------------------------------------+ -static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); -static bool process_set_config(uint8_t rhport, uint8_t cfg_num); -static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); - -// from usbd_control.c -void usbd_control_reset(void); -void usbd_control_set_request(tusb_control_request_t const *request); -void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 -static char const* const _usbd_event_str[DCD_EVENT_COUNT] = -{ - "Invalid" , - "Bus Reset" , - "Unplugged" , - "SOF" , - "Suspend" , - "Resume" , - "Setup Received" , - "Xfer Complete" , - "Func Call" -}; - -static char const* const _tusb_std_request_str[] = -{ - "Get Status" , - "Clear Feature" , - "Reserved" , - "Set Feature" , - "Reserved" , - "Set Address" , - "Get Descriptor" , - "Set Descriptor" , - "Get Configuration" , - "Set Configuration" , - "Get Interface" , - "Set Interface" , - "Synch Frame" -}; - -static char const* const _tusb_speed_str[] = { "Full", "Low", "High" }; - -// for usbd_control to print the name of control complete driver -void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) -{ - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) - { - usbd_class_driver_t const * driver = get_driver(i); - if ( driver->control_xfer_cb == callback ) - { - TU_LOG2(" %s control complete\r\n", driver->name); - return; - } - } -} - -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ -tusb_speed_t tud_speed_get(void) -{ - return (tusb_speed_t) _usbd_dev.speed; -} - -bool tud_connected(void) -{ - return _usbd_dev.connected; -} - -bool tud_mounted(void) -{ - return _usbd_dev.cfg_num ? true : false; -} - -bool tud_suspended(void) -{ - return _usbd_dev.suspended; -} - -bool tud_remote_wakeup(void) -{ - // only wake up host if this feature is supported and enabled and we are suspended - TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en ); - dcd_remote_wakeup(TUD_OPT_RHPORT); - return true; -} - -bool tud_disconnect(void) -{ - TU_VERIFY(dcd_disconnect); - dcd_disconnect(TUD_OPT_RHPORT); - return true; -} - -bool tud_connect(void) -{ - TU_VERIFY(dcd_connect); - dcd_connect(TUD_OPT_RHPORT); - return true; -} - -//--------------------------------------------------------------------+ -// USBD Task -//--------------------------------------------------------------------+ -bool tud_inited(void) -{ - return _usbd_initialized; -} - -bool tud_init (uint8_t rhport) -{ - // skip if already initialized - if (_usbd_initialized) return _usbd_initialized; - - TU_LOG2("USBD init\r\n"); - - tu_varclr(&_usbd_dev); - -#if CFG_TUSB_OS != OPT_OS_NONE - // Init device mutex - _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef); - TU_ASSERT(_usbd_mutex); -#endif - - // Init device queue & task - _usbd_q = osal_queue_create(&_usbd_qdef); - TU_ASSERT(_usbd_q); - - // Get application driver if available - if ( usbd_app_driver_get_cb ) - { - _app_driver = usbd_app_driver_get_cb(&_app_driver_count); - } - - // Init class drivers - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) - { - usbd_class_driver_t const * driver = get_driver(i); - TU_LOG2("%s init\r\n", driver->name); - driver->init(); - } - - // Init device controller driver - dcd_init(rhport); - dcd_int_enable(rhport); - - _usbd_initialized = true; - - return true; -} - -static void configuration_reset(uint8_t rhport) -{ - for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) - { - get_driver(i)->reset(rhport); - } - - tu_varclr(&_usbd_dev); - memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping - memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping -} - -static void usbd_reset(uint8_t rhport) -{ - configuration_reset(rhport); - usbd_control_reset(); -} - -bool tud_task_event_ready(void) -{ - // Skip if stack is not initialized - if ( !tusb_inited() ) return false; - - return !osal_queue_empty(_usbd_q); -} - -/* USB Device Driver task - * This top level thread manages all device controller event and delegates events to class-specific drivers. - * This should be called periodically within the mainloop or rtos thread. - * - @code - int main(void) - { - application_init(); - tusb_init(); - - while(1) // the mainloop - { - application_code(); - tud_task(); // tinyusb device task - } - } - @endcode - */ -void tud_task (void) -{ - // Skip if stack is not initialized - if ( !tusb_inited() ) return; - - // Loop until there is no more events in the queue - while (1) - { - dcd_event_t event; - - if ( !osal_queue_receive(_usbd_q, &event) ) return; - -#if CFG_TUSB_DEBUG >= 2 - if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG2("\r\n"); // extra line for setup - TU_LOG2("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); -#endif - - switch ( event.event_id ) - { - case DCD_EVENT_BUS_RESET: - TU_LOG2(": %s Speed\r\n", _tusb_speed_str[event.bus_reset.speed]); - usbd_reset(event.rhport); - _usbd_dev.speed = event.bus_reset.speed; - break; - - case DCD_EVENT_UNPLUGGED: - TU_LOG2("\r\n"); - usbd_reset(event.rhport); - - // invoke callback - if (tud_umount_cb) tud_umount_cb(); - break; - - case DCD_EVENT_SETUP_RECEIVED: - TU_LOG2_VAR(&event.setup_received); - TU_LOG2("\r\n"); - - // Mark as connected after receiving 1st setup packet. - // But it is easier to set it every time instead of wasting time to check then set - _usbd_dev.connected = 1; - - // mark both in & out control as free - _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = false; - _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0; - _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = false; - _usbd_dev.ep_status[0][TUSB_DIR_IN ].claimed = 0; - - // Process control request - if ( !process_control_request(event.rhport, &event.setup_received) ) - { - TU_LOG2(" Stall EP0\r\n"); - // Failed -> stall both control endpoint IN and OUT - dcd_edpt_stall(event.rhport, 0); - dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK); - } - break; - - case DCD_EVENT_XFER_COMPLETE: - { - // Invoke the class callback associated with the endpoint address - uint8_t const ep_addr = event.xfer_complete.ep_addr; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - - _usbd_dev.ep_status[epnum][ep_dir].busy = false; - _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; - - if ( 0 == epnum ) - { - usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); - } - else - { - usbd_class_driver_t const * driver = get_driver( _usbd_dev.ep2drv[epnum][ep_dir] ); - TU_ASSERT(driver, ); - - TU_LOG2(" %s xfer callback\r\n", driver->name); - driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); - } - } - break; - - case DCD_EVENT_SUSPEND: - // NOTE: When plugging/unplugging device, the D+/D- state are unstable and - // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event - // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected - if ( _usbd_dev.connected ) - { - TU_LOG2(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); - if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); - }else - { - TU_LOG2(" Skipped\r\n"); - } - break; - - case DCD_EVENT_RESUME: - if ( _usbd_dev.connected ) - { - TU_LOG2("\r\n"); - if (tud_resume_cb) tud_resume_cb(); - }else - { - TU_LOG2(" Skipped\r\n"); - } - break; - - case DCD_EVENT_SOF: - TU_LOG2("\r\n"); - for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) - { - usbd_class_driver_t const * driver = get_driver(i); - if ( driver->sof ) driver->sof(event.rhport); - } - break; - - case USBD_EVENT_FUNC_CALL: - TU_LOG2("\r\n"); - if ( event.func_call.func ) event.func_call.func(event.func_call.param); - break; - - default: - TU_BREAKPOINT(); - break; - } - } -} - -//--------------------------------------------------------------------+ -// Control Request Parser & Handling -//--------------------------------------------------------------------+ - -// Helper to invoke class driver control request handler -static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) -{ - usbd_control_set_complete_callback(driver->control_xfer_cb); - TU_LOG2(" %s control request\r\n", driver->name); - return driver->control_xfer_cb(rhport, CONTROL_STAGE_SETUP, request); -} - -// This handles the actual request and its response. -// return false will cause its caller to stall control endpoint -static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ - usbd_control_set_complete_callback(NULL); - - TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); - - // Vendor request - if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) - { - TU_VERIFY(tud_vendor_control_xfer_cb); - - usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); - return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); - } - -#if CFG_TUSB_DEBUG >= 2 - if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) - { - TU_LOG2(" %s", _tusb_std_request_str[p_request->bRequest]); - if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG2("\r\n"); - } -#endif - - switch ( p_request->bmRequestType_bit.recipient ) - { - //------------- Device Requests e.g in enumeration -------------// - case TUSB_REQ_RCPT_DEVICE: - if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) - { - uint8_t const itf = tu_u16_low(p_request->wIndex); - TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); - - usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]); - TU_VERIFY(driver); - - // forward to class driver: "non-STD request to Interface" - return invoke_class_control(rhport, driver, p_request); - } - - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) - { - // Non standard request is not supported - TU_BREAKPOINT(); - return false; - } - - switch ( p_request->bRequest ) - { - case TUSB_REQ_SET_ADDRESS: - // Depending on mcu, status phase could be sent either before or after changing device address, - // or even require stack to not response with status at all - // Therefore DCD must take full responsibility to response and include zlp status packet if needed. - usbd_control_set_request(p_request); // set request since DCD has no access to tud_control_status() API - dcd_set_address(rhport, (uint8_t) p_request->wValue); - // skip tud_control_status() - _usbd_dev.addressed = 1; - break; - - case TUSB_REQ_GET_CONFIGURATION: - { - uint8_t cfg_num = _usbd_dev.cfg_num; - tud_control_xfer(rhport, p_request, &cfg_num, 1); - } - break; - - case TUSB_REQ_SET_CONFIGURATION: - { - uint8_t const cfg_num = (uint8_t) p_request->wValue; - - // Only process if new configure is different - if (_usbd_dev.cfg_num != cfg_num) - { - if ( _usbd_dev.cfg_num ) - { - // already configured: need to clear all endpoints and driver first - TU_LOG(USBD_DBG, " Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); - - // close all non-control endpoints, cancel all pending transfers if any - dcd_edpt_close_all(rhport); - - // close all drivers and current configured state except bus speed - uint8_t const speed = _usbd_dev.speed; - configuration_reset(rhport); - - _usbd_dev.speed = speed; // restore speed - } - - // switch to new configuration if not zero - if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); - } - - _usbd_dev.cfg_num = cfg_num; - tud_control_status(rhport, p_request); - } - break; - - case TUSB_REQ_GET_DESCRIPTOR: - TU_VERIFY( process_get_descriptor(rhport, p_request) ); - break; - - case TUSB_REQ_SET_FEATURE: - // Only support remote wakeup for device feature - TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - - TU_LOG(USBD_DBG, " Enable Remote Wakeup\r\n"); - - // Host may enable remote wake up before suspending especially HID device - _usbd_dev.remote_wakeup_en = true; - tud_control_status(rhport, p_request); - break; - - case TUSB_REQ_CLEAR_FEATURE: - // Only support remote wakeup for device feature - TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - - TU_LOG(USBD_DBG, " Disable Remote Wakeup\r\n"); - - // Host may disable remote wake up after resuming - _usbd_dev.remote_wakeup_en = false; - tud_control_status(rhport, p_request); - break; - - case TUSB_REQ_GET_STATUS: - { - // Device status bit mask - // - Bit 0: Self Powered - // - Bit 1: Remote Wakeup enabled - uint16_t status = (_usbd_dev.self_powered ? 1 : 0) | (_usbd_dev.remote_wakeup_en ? 2 : 0); - tud_control_xfer(rhport, p_request, &status, 2); - } - break; - - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; - } - break; - - //------------- Class/Interface Specific Request -------------// - case TUSB_REQ_RCPT_INTERFACE: - { - uint8_t const itf = tu_u16_low(p_request->wIndex); - TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); - - usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]); - TU_VERIFY(driver); - - // all requests to Interface (STD or Class) is forwarded to class driver. - // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE - if ( !invoke_class_control(rhport, driver, p_request) ) - { - // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class - // driver doesn't use alternate settings or implement this - TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - - switch(p_request->bRequest) - { - case TUSB_REQ_GET_INTERFACE: - case TUSB_REQ_SET_INTERFACE: - // Clear complete callback if driver set since it can also stall the request. - usbd_control_set_complete_callback(NULL); - - if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) - { - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); - }else - { - tud_control_status(rhport, p_request); - } - break; - - default: return false; - } - } - } - break; - - //------------- Endpoint Request -------------// - case TUSB_REQ_RCPT_ENDPOINT: - { - uint8_t const ep_addr = tu_u16_low(p_request->wIndex); - uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); - - usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); - - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) - { - // Forward class request to its driver - TU_VERIFY(driver); - return invoke_class_control(rhport, driver, p_request); - } - else - { - // Handle STD request to endpoint - switch ( p_request->bRequest ) - { - case TUSB_REQ_GET_STATUS: - { - uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000; - tud_control_xfer(rhport, p_request, &status, 2); - } - break; - - case TUSB_REQ_CLEAR_FEATURE: - case TUSB_REQ_SET_FEATURE: - { - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) - { - usbd_edpt_clear_stall(rhport, ep_addr); - }else - { - usbd_edpt_stall(rhport, ep_addr); - } - } - - if (driver) - { - // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request - // We will also forward std request targeted endpoint to class drivers as well - - // STD request must always be ACKed regardless of driver returned value - // Also clear complete callback if driver set since it can also stall the request. - (void) invoke_class_control(rhport, driver, p_request); - usbd_control_set_complete_callback(NULL); - - // skip ZLP status if driver already did that - if ( !_usbd_dev.ep_status[0][TUSB_DIR_IN].busy ) tud_control_status(rhport, p_request); - } - } - break; - - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; - } - } - } - break; - - // Unknown recipient - default: TU_BREAKPOINT(); return false; - } - - return true; -} - -// Process Set Configure Request -// This function parse configuration descriptor & open drivers accordingly -static bool process_set_config(uint8_t rhport, uint8_t cfg_num) -{ - // index is cfg_num-1 - tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); - TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION); - - // Parse configuration descriptor - _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0; - _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED ) ? 1 : 0; - - // Parse interface descriptor - uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); - uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); - - while( p_desc < desc_end ) - { - uint8_t assoc_itf_count = 1; - - // Class will always starts with Interface Association (if any) and then Interface descriptor - if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) - { - tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; - assoc_itf_count = desc_iad->bInterfaceCount; - - p_desc = tu_desc_next(p_desc); // next to Interface - - // IAD's first interface number and class should match with opened interface - //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && - // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); - } - - TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; - - // Find driver for this interface - uint16_t const remaining_len = desc_end-p_desc; - uint8_t drv_id; - for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) - { - usbd_class_driver_t const *driver = get_driver(drv_id); - uint16_t const drv_len = driver->open(rhport, desc_itf, remaining_len); - - if ( (sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len) ) - { - // Open successfully - TU_LOG2(" %s opened\r\n", driver->name); - - // Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or - // BTH (even CDC) with class in device descriptor (single interface) - if ( assoc_itf_count == 1) - { - #if CFG_TUD_CDC - if ( driver->open == cdcd_open ) assoc_itf_count = 2; - #endif - - #if CFG_TUD_MIDI - if ( driver->open == midid_open ) assoc_itf_count = 2; - #endif - - #if CFG_TUD_BTH && CFG_TUD_BTH_ISO_ALT_COUNT - if ( driver->open == btd_open ) assoc_itf_count = 2; - #endif - } - - // bind (associated) interfaces to found driver - for(uint8_t i=0; ibInterfaceNumber+i; - - // Interface number must not be used already - TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[itf_num]); - _usbd_dev.itf2drv[itf_num] = drv_id; - } - - // bind all endpoints to found driver - tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); - - // next Interface - p_desc += drv_len; - - break; // exit driver find loop - } - } - - // Failed if there is no supported drivers - TU_ASSERT(drv_id < TOTAL_DRIVER_COUNT); - } - - // invoke callback - if (tud_mount_cb) tud_mount_cb(); - - return true; -} - -// return descriptor's buffer and update desc_len -static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request) -{ - tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue); - uint8_t const desc_index = tu_u16_low( p_request->wValue ); - - switch(desc_type) - { - case TUSB_DESC_DEVICE: - { - TU_LOG2(" Device\r\n"); - - void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb(); - - // Only response with exactly 1 Packet if: not addressed and host requested more data than device descriptor has. - // This only happens with the very first get device descriptor and EP0 size = 8 or 16. - if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed && - ((tusb_control_request_t const*) p_request)->wLength > sizeof(tusb_desc_device_t)) - { - // Hack here: we modify the request length to prevent usbd_control response with zlp - // since we are responding with 1 packet & less data than wLength. - tusb_control_request_t mod_request = *p_request; - mod_request.wLength = CFG_TUD_ENDPOINT0_SIZE; - - return tud_control_xfer(rhport, &mod_request, desc_device, CFG_TUD_ENDPOINT0_SIZE); - }else - { - return tud_control_xfer(rhport, p_request, desc_device, sizeof(tusb_desc_device_t)); - } - } - break; - - case TUSB_DESC_BOS: - { - TU_LOG2(" BOS\r\n"); - - // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) - if (!tud_descriptor_bos_cb) return false; - - uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb(); - TU_ASSERT(desc_bos); - - // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) ); - - return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); - } - break; - - case TUSB_DESC_CONFIGURATION: - case TUSB_DESC_OTHER_SPEED_CONFIG: - { - uintptr_t desc_config; - - if ( desc_type == TUSB_DESC_CONFIGURATION ) - { - TU_LOG2(" Configuration[%u]\r\n", desc_index); - desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index); - }else - { - // Host only request this after getting Device Qualifier descriptor - TU_LOG2(" Other Speed Configuration\r\n"); - TU_VERIFY( tud_descriptor_other_speed_configuration_cb ); - desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index); - } - - TU_ASSERT(desc_config); - - // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))) ); - - return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); - } - break; - - case TUSB_DESC_STRING: - { - TU_LOG2(" String[%u]\r\n", desc_index); - - // String Descriptor always uses the desc set from user - uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, tu_le16toh(p_request->wIndex)); - TU_VERIFY(desc_str); - - // first byte of descriptor is its size - return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_str, tu_desc_len(desc_str)); - } - break; - - case TUSB_DESC_DEVICE_QUALIFIER: - { - TU_LOG2(" Device Qualifier\r\n"); - - TU_VERIFY( tud_descriptor_device_qualifier_cb ); - - uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); - TU_VERIFY(desc_qualifier); - - // first byte of descriptor is its size - return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_qualifier, tu_desc_len(desc_qualifier)); - } - break; - - default: return false; - } -} - -//--------------------------------------------------------------------+ -// DCD Event Handler -//--------------------------------------------------------------------+ -void dcd_event_handler(dcd_event_t const * event, bool in_isr) -{ - switch (event->event_id) - { - case DCD_EVENT_UNPLUGGED: - _usbd_dev.connected = 0; - _usbd_dev.addressed = 0; - _usbd_dev.cfg_num = 0; - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); - break; - - case DCD_EVENT_SUSPEND: - // NOTE: When plugging/unplugging device, the D+/D- state are unstable and - // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). - // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish - // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected - if ( _usbd_dev.connected ) - { - _usbd_dev.suspended = 1; - osal_queue_send(_usbd_q, event, in_isr); - } - break; - - case DCD_EVENT_RESUME: - // skip event if not connected (especially required for SAMD) - if ( _usbd_dev.connected ) - { - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); - } - break; - - case DCD_EVENT_SOF: - // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup - // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational - if ( _usbd_dev.suspended ) - { - _usbd_dev.suspended = 0; - dcd_event_t const event_resume = { .rhport = event->rhport, .event_id = DCD_EVENT_RESUME }; - osal_queue_send(_usbd_q, &event_resume, in_isr); - } - break; - - default: - osal_queue_send(_usbd_q, event, in_isr); - break; - } -} - -void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) -{ - dcd_event_t event = { .rhport = rhport, .event_id = eid }; - dcd_event_handler(&event, in_isr); -} - -void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) -{ - dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_BUS_RESET }; - event.bus_reset.speed = speed; - dcd_event_handler(&event, in_isr); -} - -void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) -{ - dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED }; - memcpy(&event.setup_received, setup, 8); - - dcd_event_handler(&event, in_isr); -} - -void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) -{ - dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE }; - - event.xfer_complete.ep_addr = ep_addr; - event.xfer_complete.len = xferred_bytes; - event.xfer_complete.result = result; - - dcd_event_handler(&event, in_isr); -} - -//--------------------------------------------------------------------+ -// USBD API For Class Driver -//--------------------------------------------------------------------+ - -// Parse consecutive endpoint descriptors (IN & OUT) -bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in) -{ - for(int i=0; ibDescriptorType && xfer_type == desc_ep->bmAttributes.xfer); - TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); - - if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) - { - (*ep_in) = desc_ep->bEndpointAddress; - }else - { - (*ep_out) = desc_ep->bEndpointAddress; - } - - p_desc = tu_desc_next(p_desc); - } - - return true; -} - -// Helper to defer an isr function -void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) -{ - dcd_event_t event = - { - .rhport = 0, - .event_id = USBD_EVENT_FUNC_CALL, - }; - - event.func_call.func = func; - event.func_call.param = param; - - dcd_event_handler(&event, in_isr); -} - -//--------------------------------------------------------------------+ -// USBD Endpoint API -//--------------------------------------------------------------------+ - -bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) -{ - TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); - TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); - - return dcd_edpt_open(rhport, desc_ep); -} - -bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - // TODO add this check later, also make sure we don't starve an out endpoint while suspending - // TU_VERIFY(tud_ready()); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - -#if CFG_TUSB_OS != OPT_OS_NONE - // pre-check to help reducing mutex lock - TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only claim the endpoint if it is not busy and not claimed yet. - bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); - if (ret) - { - _usbd_dev.ep_status[epnum][dir].claimed = 1; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(_usbd_mutex); -#endif - - return ret; -} - -bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only release the endpoint if it is claimed and not busy - bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); - if (ret) - { - _usbd_dev.ep_status[epnum][dir].claimed = 0; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(_usbd_mutex); -#endif - - return ret; -} - -bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // TODO skip ready() check for now since enumeration also use this API - // TU_VERIFY(tud_ready()); - - TU_LOG2(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() - // could return and USBD task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = true; - - if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) - { - return true; - }else - { - // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = 0; - TU_LOG2("FAILED\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -// The number of bytes has to be given explicitly to allow more flexible control of how many -// bytes should be written and second to keep the return value free to give back a boolean -// success message. If total_bytes is too big, the FIFO will copy only what is available -// into the USB buffer! -bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return - // and usbd task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = true; - - if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) - { - TU_LOG2("OK\r\n"); - return true; - }else - { - // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - return _usbd_dev.ep_status[epnum][dir].busy; -} - -void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // only stalled if currently cleared - if ( !_usbd_dev.ep_status[epnum][dir].stalled ) - { - TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr); - dcd_edpt_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = true; - _usbd_dev.ep_status[epnum][dir].busy = true; - } -} - -void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // only clear if currently stalled - if ( _usbd_dev.ep_status[epnum][dir].stalled ) - { - TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr); - dcd_edpt_clear_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - } -} - -bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - return _usbd_dev.ep_status[epnum][dir].stalled; -} - -/** - * usbd_edpt_close will disable an endpoint. - * - * In progress transfers on this EP may be delivered after this call. - * - */ -void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - TU_ASSERT(dcd_edpt_close, /**/); - TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - dcd_edpt_close(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = false; - _usbd_dev.ep_status[epnum][dir].busy = false; - _usbd_dev.ep_status[epnum][dir].claimed = false; - - return; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h deleted file mode 100644 index ec34817fa..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd.h +++ /dev/null @@ -1,853 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBD_H_ -#define _TUSB_USBD_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Init device stack -bool tud_init (uint8_t rhport); - -// Check if device stack is already initialized -bool tud_inited(void); - -// Task function should be called in main/rtos loop -void tud_task (void); - -// Check if there is pending events need proccessing by tud_task() -bool tud_task_event_ready(void); - -// Interrupt handler, name alias to DCD -extern void dcd_int_handler(uint8_t rhport); -#define tud_int_handler dcd_int_handler - -// Get current bus speed -tusb_speed_t tud_speed_get(void); - -// Check if device is connected (may not mounted/configured yet) -// True if just got out of Bus Reset and received the very first data from host -bool tud_connected(void); - -// Check if device is connected and configured -bool tud_mounted(void); - -// Check if device is suspended -bool tud_suspended(void); - -// Check if device is ready to transfer -TU_ATTR_ALWAYS_INLINE static inline -bool tud_ready(void) -{ - return tud_mounted() && !tud_suspended(); -} - -// Remote wake up host, only if suspended and enabled by host -bool tud_remote_wakeup(void); - -// Enable pull-up resistor on D+ D- -// Return false on unsupported MCUs -bool tud_disconnect(void); - -// Disable pull-up resistor on D+ D- -// Return false on unsupported MCUs -bool tud_connect(void); - -// Carry out Data and Status stage of control transfer -// - If len = 0, it is equivalent to sending status only -// - If len > wLength : it will be truncated -bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len); - -// Send STATUS (zero length) packet -bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) -//--------------------------------------------------------------------+ - -// Invoked when received GET DEVICE DESCRIPTOR request -// Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void); - -// Invoked when received GET CONFIGURATION DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index); - -// Invoked when received GET STRING DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); - -// Invoked when received GET BOS DESCRIPTOR request -// Application return pointer to descriptor -TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); - -// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. -// device_qualifier descriptor describes information about a high-speed capable device that would -// change if the device were operating at the other speed. If not highspeed capable stall this request. -TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); - -// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa -TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index); - -// Invoked when device is mounted (configured) -TU_ATTR_WEAK void tud_mount_cb(void); - -// Invoked when device is unmounted -TU_ATTR_WEAK void tud_umount_cb(void); - -// Invoked when usb bus is suspended -// Within 7ms, device must draw an average of current less than 2.5 mA from bus -TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en); - -// Invoked when usb bus is resumed -TU_ATTR_WEAK void tud_resume_cb(void); - -// Invoked when received control request with VENDOR TYPE -TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Binary Device Object Store (BOS) Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_BOS_DESC_LEN 5 - -// total length, number of device caps -#define TUD_BOS_DESCRIPTOR(_total_len, _caps_num) \ - 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num - -// Device Capability Platform 128-bit UUID + Data -#define TUD_BOS_PLATFORM_DESCRIPTOR(...) \ - 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ - -//------------- WebUSB BOS Platform -------------// - -// Descriptor Length -#define TUD_BOS_WEBUSB_DESC_LEN 24 - -// Vendor Code, iLandingPage -#define TUD_BOS_WEBUSB_DESCRIPTOR(_vendor_code, _ipage) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) - -#define TUD_BOS_WEBUSB_UUID \ - 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ - 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 - -//------------- Microsoft OS 2.0 Platform -------------// -#define TUD_BOS_MICROSOFT_OS_DESC_LEN 28 - -// Total Length of descriptor set, vendor code -#define TUD_BOS_MS_OS_20_DESCRIPTOR(_desc_set_len, _vendor_code) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) - -#define TUD_BOS_MS_OS_20_UUID \ - 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ - 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F - -//--------------------------------------------------------------------+ -// Configuration Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_CONFIG_DESC_LEN (9) - -// Config number, interface count, string index, total length, attribute, power in mA -#define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ - 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 - -//--------------------------------------------------------------------+ -// CDC Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor: 66 bytes -#define TUD_CDC_DESC_LEN (8+9+5+5+4+5+7+9+7+7) - -// CDC Descriptor Template -// Interface number, string index, EP notification address and size, EP data address (out, in) and size. -#define TUD_CDC_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Associate */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ - /* CDC Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC Call */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* CDC ACM: support line request */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -//--------------------------------------------------------------------+ -// MSC Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor: 23 bytes -#define TUD_MSC_DESC_LEN (9 + 7 + 7) - -// Interface number, string index, EP Out & EP In address, EP size -#define TUD_MSC_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - - -//--------------------------------------------------------------------+ -// HID Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor: 25 bytes -#define TUD_HID_DESC_LEN (9 + 9 + 7) - -// HID Input only descriptor -// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval -#define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval - -// Length of template descriptor: 32 bytes -#define TUD_HID_INOUT_DESC_LEN (9 + 9 + 7 + 7) - -// HID Input & Output descriptor -// Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval -#define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval - -//--------------------------------------------------------------------+ -// MIDI Descriptor Templates -// Note: MIDI v1.0 is based on Audio v1.0 -//--------------------------------------------------------------------+ - -#define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) -#define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ - /* Audio Control (AC) Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ - /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ - /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ - /* MS Header */\ - 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) - -#define TUD_MIDI_JACKID_IN_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 1) - -#define TUD_MIDI_JACKID_IN_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 2) - -#define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 3) - -#define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 4) - -#define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9) -#define TUD_MIDI_DESC_JACK(_cablenum) \ - /* MS In Jack (Embedded) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ - /* MS In Jack (External) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ - /* MS Out Jack (Embedded), connected to In Jack External */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ - /* MS Out Jack (External), connected to In Jack Embedded */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 - -#define TUD_MIDI_DESC_EP_LEN(_numcables) (9 + 4 + (_numcables)) -#define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ - /* Endpoint: Note Audio v1.0's endpoint has 9 bytes instead of 7 */\ - 9, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, 0, 0, \ - /* MS Endpoint (connected to embedded jack) */\ - (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables - -// Length of template descriptor (88 bytes) -#define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2) - -// MIDI simple descriptor -// - 1 Embedded Jack In connected to 1 External Jack Out -// - 1 Embedded Jack out connected to 1 External Jack In -#define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ - TUD_MIDI_DESC_JACK(1),\ - TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ - TUD_MIDI_JACKID_IN_EMB(1),\ - TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ - TUD_MIDI_JACKID_OUT_EMB(1) - -//--------------------------------------------------------------------+ -// Audio v2.0 Descriptor Templates -//--------------------------------------------------------------------+ - -/* Standard Interface Association Descriptor (IAD) */ -#define TUD_AUDIO_DESC_IAD_LEN 8 -#define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx - -/* Standard AC Interface Descriptor(4.7.1) */ -#define TUD_AUDIO_DESC_STD_AC_LEN 9 -#define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ - TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx - -/* Class-Specific AC Interface Header Descriptor(4.7.2) */ -#define TUD_AUDIO_DESC_CS_AC_LEN 9 -#define TUD_AUDIO_DESC_CS_AC(_bcdADC, _category, _totallen, _ctrl) /* _bcdADC : Audio Device Class Specification Release Number in Binary-Coded Decimal, _category : see audio_function_t, _totallen : Total number of bytes returned for the class-specific AudioControl interface i.e. Clock Source, Unit and Terminal descriptors - Do not include TUD_AUDIO_DESC_CS_AC_LEN, we already do this here*/ \ - TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl - -/* Clock Source Descriptor(4.7.2.1) */ -#define TUD_AUDIO_DESC_CLK_SRC_LEN 8 -#define TUD_AUDIO_DESC_CLK_SRC(_clkid, _attr, _ctrl, _assocTerm, _stridx) \ - TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx - -/* Input Terminal Descriptor(4.7.2.4) */ -#define TUD_AUDIO_DESC_INPUT_TERM_LEN 17 -#define TUD_AUDIO_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _clkid, _nchannelslogical, _channelcfg, _idxchannelnames, _ctrl, _stridx) \ - TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx - -/* Output Terminal Descriptor(4.7.2.5) */ -#define TUD_AUDIO_DESC_OUTPUT_TERM_LEN 12 -#define TUD_AUDIO_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _clkid, _ctrl, _stridx) \ - TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx - -/* Feature Unit Descriptor(4.7.2.8) */ -// 1 - Channel -#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN 6+(1+1)*4 -#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx - -// 2 - Channels -#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN (6+(2+1)*4) -#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), _stridx -// 4 - Channels -#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN (6+(4+1)*4) -#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _ctrlch3, _ctrlch4, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), U32_TO_U8S_LE(_ctrlch3), U32_TO_U8S_LE(_ctrlch4), _stridx - -// For more channels, add definitions here - -/* Standard AS Interface Descriptor(4.9.1) */ -#define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 -#define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ - TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx - -/* Class-Specific AS Interface Descriptor(4.9.2) */ -#define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 -#define TUD_AUDIO_DESC_CS_AS_INT(_termid, _ctrl, _formattype, _formats, _nchannelsphysical, _channelcfg, _stridx) \ - TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx - -/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ -#define TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN 6 -#define TUD_AUDIO_DESC_TYPE_I_FORMAT(_subslotsize, _bitresolution) /* _subslotsize is number of bytes per sample (i.e. subslot) and can be 1,2,3, or 4 */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution - -/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ -#define TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN 7 -#define TUD_AUDIO_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval - -/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ -#define TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN 8 -#define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ - TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) - -/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ -#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 -#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval - -// AUDIO simple descriptor (UAC2) for 1 microphone input -// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source - -#define TUD_AUDIO_MIC_ONE_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) - -#define TUD_AUDIO_MIC_ONE_CH_DESC_N_AS_INT 1 // Number of AS interfaces - -#define TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ - /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ - /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ - /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ - /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ - /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ - /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) - -// AUDIO simple descriptor (UAC2) for 4 microphone input -// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source - -#define TUD_AUDIO_MIC_FOUR_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) - -#define TUD_AUDIO_MIC_FOUR_CH_DESC_N_AS_INT 1 // Number of AS interfaces - -#define TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ - /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ - /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ - /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ - /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ - /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ - /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch2*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch3*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch4*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) - -// AUDIO simple descriptor (UAC2) for mono speaker -// - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source - -#define TUD_AUDIO_SPEAKER_MONO_FB_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) - -#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ - /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ - /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ - /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ - /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ - /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ - /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ - /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ - -// Calculate wMaxPacketSize of Endpoints -#define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \ - ((((_maxFrequency + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 7999 : 999)) / ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels) - - -//--------------------------------------------------------------------+ -// USBTMC/USB488 Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) -#define TUD_USBTMC_APP_SUBCLASS 0x03u - -#define TUD_USBTMC_PROTOCOL_STD 0x00u -#define TUD_USBTMC_PROTOCOL_USB488 0x01u - -// Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, -// bulk-in endpoint ID -#define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ - /* Interface */ \ - 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx - -#define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u - -#define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \ - /* Endpoint Out */ \ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ - /* Endpoint In */ \ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u - -#define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) - -/* optional interrupt endpoint */ \ -// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? -#define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ - 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 - -#define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) - -//--------------------------------------------------------------------+ -// Vendor Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_VENDOR_DESC_LEN (9+7+7) - -// Interface number, string index, EP Out & IN address, EP size -#define TUD_VENDOR_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -//--------------------------------------------------------------------+ -// DFU Runtime Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) -#define TUD_DFU_APP_SUBCLASS (APP_SUBCLASS_DFU_RUNTIME) - -// Length of template descriptr: 18 bytes -#define TUD_DFU_RT_DESC_LEN (9 + 9) - -// DFU runtime descriptor -// Interface number, string index, attributes, detach timeout, transfer size -#define TUD_DFU_RT_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \ - /* Function */ \ - 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) - -//--------------------------------------------------------------------+ -// DFU Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor: 9 bytes + number of alternatives * 9 -#define TUD_DFU_DESC_LEN(_alt_count) (9 + (_alt_count) * 9) - -// Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size -// Note: Alternate count must be numberic or macro, string index is increased by one for each Alt interface -#define TUD_DFU_DESCRIPTOR(_itfnum, _alt_count, _stridx, _attr, _timeout, _xfer_size) \ - TU_XSTRCAT(_TUD_DFU_ALT_,_alt_count)(_itfnum, 0, _stridx), \ - /* Function */ \ - 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) - -#define _TUD_DFU_ALT(_itfnum, _alt, _stridx) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx - -#define _TUD_DFU_ALT_1(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx) - -#define _TUD_DFU_ALT_2(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_1(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_3(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_2(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_4(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_3(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_5(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_4(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_6(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_5(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_7(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_6(_itfnum, _alt_count+1, _stridx+1) - -#define _TUD_DFU_ALT_8(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) - -//--------------------------------------------------------------------+ -// CDC-ECM Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor: 71 bytes -#define TUD_CDC_ECM_DESC_LEN (8+9+5+5+13+7+9+9+7+7) - -// CDC-ECM Descriptor Template -// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. -#define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, _desc_stridx,\ - /* CDC-ECM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC-ECM Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* CDC-ECM Functional Descriptor */\ - 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface (default inactive) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* CDC Data Interface (alternative active) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -//--------------------------------------------------------------------+ -// RNDIS Descriptor Templates -//--------------------------------------------------------------------+ - -#if 0 -/* Windows XP */ -#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC -#define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL -#define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ -#else -/* Windows 7+ */ -#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER -#define TUD_RNDIS_ITF_SUBCLASS 0x01 -#define TUD_RNDIS_ITF_PROTOCOL 0x03 -#endif - -// Length of template descriptor: 66 bytes -#define TUD_RNDIS_DESC_LEN (8+9+5+5+4+5+7+9+7+7) - -// RNDIS Descriptor Template -// Interface number, string index, EP notification address and size, EP data address (out, in) and size. -#define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ - /* CDC-ACM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ - /* CDC Call Management */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* ACM */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -//--------------------------------------------------------------------+ -// Bluetooth Radio Descriptor Templates -//--------------------------------------------------------------------+ - -#define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) -#define TUD_BT_APP_SUBCLASS 0x01 -#define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 -#define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02 - -#ifndef CFG_TUD_BTH_ISO_ALT_COUNT -#define CFG_TUD_BTH_ISO_ALT_COUNT 0 -#endif - -// Length of template descriptor: 38 bytes + number of ISO alternatives * 23 -#define TUD_BTH_DESC_LEN (8 + 9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) - -/* Primary Interface */ -#define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, _stridx, \ - /* Endpoint In for events */ \ - 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ - /* Endpoint In for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ - /* Endpoint Out for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 - -#define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ - /* Interface with 2 endpoints */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Isochronous endpoints */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 - -#define _FIRST(a, ...) a -#define _REST(a, ...) __VA_ARGS__ - -#define TUD_BTH_ISO_ITF_0(_itfnum, ...) -#define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) -#define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) -#define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) -#define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) -#define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) -#define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) - -#define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ - TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) - -// BT Primary controller descriptor -// Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes -// TODO BTH should also use IAD like CDC for composite device -#define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ - /* Interface Associate */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0,\ - TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) - -//--------------------------------------------------------------------+ -// CDC-NCM Descriptor Templates -//--------------------------------------------------------------------+ - -// Length of template descriptor -#define TUD_CDC_NCM_DESC_LEN (8+9+5+5+13+6+7+9+9+7+7) - -// CDC-ECM Descriptor Template -// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. -#define TUD_CDC_NCM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, _desc_stridx,\ - /* CDC-NCM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ - /* CDC-NCM Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* CDC-NCM Functional Descriptor */\ - 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0, \ - /* CDC-NCM Functional Descriptor */\ - 6, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_NCM, U16_TO_U8S_LE(0x0100), 0, \ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 50,\ - /* CDC Data Interface (default inactive) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK, 0,\ - /* CDC Data Interface (alternative active) */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK, 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_USBD_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c deleted file mode 100644 index 7a8244699..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_control.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_DEVICE_ENABLED - -#include "tusb.h" -#include "device/usbd_pvt.h" -#include "dcd.h" - -#if CFG_TUSB_DEBUG >= 2 -extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); -#endif - -enum -{ - EDPT_CTRL_OUT = 0x00, - EDPT_CTRL_IN = 0x80 -}; - -typedef struct -{ - tusb_control_request_t request; - - uint8_t* buffer; - uint16_t data_len; - uint16_t total_xferred; - - usbd_control_xfer_cb_t complete_cb; -} usbd_control_xfer_t; - -static usbd_control_xfer_t _ctrl_xfer; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN -static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; - -//--------------------------------------------------------------------+ -// Application API -//--------------------------------------------------------------------+ - -// Queue ZLP status transaction -static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) -{ - // Opposite to endpoint in Data Phase - uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); -} - -// Status phase -bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = NULL; - _ctrl_xfer.total_xferred = 0; - _ctrl_xfer.data_len = 0; - - return _status_stage_xact(rhport, request); -} - -// Queue a transaction in Data Stage -// Each transaction has up to Endpoint0's max packet size. -// This function can also transfer an zero-length packet -static bool _data_stage_xact(uint8_t rhport) -{ - uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE); - - uint8_t ep_addr = EDPT_CTRL_OUT; - - if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN ) - { - ep_addr = EDPT_CTRL_IN; - if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); - } - - return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); -} - -// Transmit data to/from the control endpoint. -// If the request's wLength is zero, a status packet is sent instead. -bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = (uint8_t*) buffer; - _ctrl_xfer.total_xferred = 0U; - _ctrl_xfer.data_len = tu_min16(len, request->wLength); - - if (request->wLength > 0U) - { - if(_ctrl_xfer.data_len > 0U) - { - TU_ASSERT(buffer); - } - -// TU_LOG2(" Control total data length is %u bytes\r\n", _ctrl_xfer.data_len); - - // Data stage - TU_ASSERT( _data_stage_xact(rhport) ); - } - else - { - // Status stage - TU_ASSERT( _status_stage_xact(rhport, request) ); - } - - return true; -} - -//--------------------------------------------------------------------+ -// USBD API -//--------------------------------------------------------------------+ - -void usbd_control_reset(void); -void usbd_control_set_request(tusb_control_request_t const *request); -void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - -void usbd_control_reset(void) -{ - tu_varclr(&_ctrl_xfer); -} - -// Set complete callback -void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) -{ - _ctrl_xfer.complete_cb = fp; -} - -// for dcd_set_address where DCD is responsible for status response -void usbd_control_set_request(tusb_control_request_t const *request) -{ - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = NULL; - _ctrl_xfer.total_xferred = 0; - _ctrl_xfer.data_len = 0; -} - -// callback when a transaction complete on -// - DATA stage of control endpoint or -// - Status stage -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - - // Endpoint Address is opposite to direction bit, this is Status Stage complete event - if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) - { - TU_ASSERT(0 == xferred_bytes); - - // invoke optional dcd hook if available - if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); - - if (_ctrl_xfer.complete_cb) - { - // TODO refactor with usbd_driver_print_control_complete_name - _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); - } - - return true; - } - - if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT ) - { - TU_VERIFY(_ctrl_xfer.buffer); - memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); - TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2); - } - - _ctrl_xfer.total_xferred += xferred_bytes; - _ctrl_xfer.buffer += xferred_bytes; - - // Data Stage is complete when all request's length are transferred or - // a short packet is sent including zero-length packet. - if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE) ) - { - // DATA stage is complete - bool is_ok = true; - - // invoke complete callback if set - // callback can still stall control in status phase e.g out data does not make sense - if ( _ctrl_xfer.complete_cb ) - { - #if CFG_TUSB_DEBUG >= 2 - usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); - #endif - - is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request); - } - - if ( is_ok ) - { - // Send status - TU_ASSERT( _status_stage_xact(rhport, &_ctrl_xfer.request) ); - }else - { - // Stall both IN and OUT control endpoint - dcd_edpt_stall(rhport, EDPT_CTRL_OUT); - dcd_edpt_stall(rhport, EDPT_CTRL_IN); - } - } - else - { - // More data to transfer - TU_ASSERT( _data_stage_xact(rhport) ); - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h deleted file mode 100644 index 7607b9895..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/device/usbd_pvt.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ -#ifndef USBD_PVT_H_ -#define USBD_PVT_H_ - -#include "osal/osal.h" -#include "common/tusb_fifo.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver API -//--------------------------------------------------------------------+ - -typedef struct -{ - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - void (* init ) (void); - void (* reset ) (uint8_t rhport); - uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); - bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); /* optional */ -} usbd_class_driver_t; - -// Invoked when initializing device stack to get additional class drivers. -// Can optionally implemented by application to extend/overwrite class driver support. -// Note: The drivers array must be accessible at all time when stack is active -usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; - -typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// USBD Endpoint API -//--------------------------------------------------------------------+ - -// Open an endpoint -bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); - -// Close an endpoint -void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); - -// Submit a usb transfer -bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -// Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); - -// Claim an endpoint before submitting a transfer. -// If caller does not make any transfer, it must release endpoint for others. -bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); - -// Release an endpoint without submitting a transfer -bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr); - -// Check if endpoint is busy transferring -bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); - -// Stall endpoint -void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr); - -// Clear stalled endpoint -void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr); - -// Check if endpoint is stalled -bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr); - -// Check if endpoint is ready (not busy and not stalled) -TU_ATTR_ALWAYS_INLINE static inline -bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) -{ - return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); -} - -/*------------------------------------------------------------------*/ -/* Helper - *------------------------------------------------------------------*/ - -bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in); -void usbd_defer_func( osal_task_func_t func, void* param, bool in_isr ); - - -#ifdef __cplusplus - } -#endif - -#endif /* USBD_PVT_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h deleted file mode 100644 index eb53d2e80..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_HCD_H_ -#define _TUSB_HCD_H_ - -#include "common/tusb_common.h" -#include "osal/osal.h" -#include "common/tusb_fifo.h" -#include "hcd_attr.h" - -#ifdef __cplusplus - extern "C" { -#endif - - //--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef enum -{ - HCD_EVENT_DEVICE_ATTACH, - HCD_EVENT_DEVICE_REMOVE, - HCD_EVENT_XFER_COMPLETE, - - // Not an HCD event, just a convenient way to defer ISR function - USBH_EVENT_FUNC_CALL, - - HCD_EVENT_COUNT -} hcd_eventid_t; - -typedef struct -{ - uint8_t rhport; - uint8_t event_id; - uint8_t dev_addr; - - union - { - // Attach, Remove - struct { - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; - } connection; - - // XFER_COMPLETE - struct { - uint8_t ep_addr; - uint8_t result; - uint32_t len; - } xfer_complete; - - // FUNC_CALL - struct { - void (*func) (void*); - void* param; - }func_call; - }; - -} hcd_event_t; - -#if TUSB_OPT_HOST_ENABLED -// Max number of endpoints per device -enum { - // TODO better computation - HCD_MAX_ENDPOINT = CFG_TUH_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3), - HCD_MAX_XFER = HCD_MAX_ENDPOINT*2, -}; - -//#define HCD_MAX_ENDPOINT 16 -//#define HCD_MAX_XFER 16 - -typedef struct { - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; -} hcd_devtree_info_t; - -#endif - -//--------------------------------------------------------------------+ -// Controller API -//--------------------------------------------------------------------+ - -// Initialize controller to host mode -bool hcd_init(uint8_t rhport); - -// Interrupt Handler -void hcd_int_handler(uint8_t rhport); - -// Enable USB interrupt -void hcd_int_enable (uint8_t rhport); - -// Disable USB interrupt -void hcd_int_disable(uint8_t rhport); - -// Get frame number (1ms) -uint32_t hcd_frame_number(uint8_t rhport); - -//--------------------------------------------------------------------+ -// Port API -//--------------------------------------------------------------------+ - -// Get the current connect status of roothub port -bool hcd_port_connect_status(uint8_t rhport); - -// Reset USB bus on the port -void hcd_port_reset(uint8_t rhport); - -// TODO implement later -void hcd_port_reset_end(uint8_t rhport); - -// Get port link speed -tusb_speed_t hcd_port_speed_get(uint8_t rhport); - -// HCD closes all opened endpoints belong to this device -void hcd_device_close(uint8_t rhport, uint8_t dev_addr); - -//--------------------------------------------------------------------+ -// Endpoints API -//--------------------------------------------------------------------+ - -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); -bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); - -//--------------------------------------------------------------------+ -// USBH implemented API -//--------------------------------------------------------------------+ - -// Get device tree information of a device -// USB device tree can be complicated and manged by USBH, this help HCD to retrieve -// needed topology info to carry out its work -extern void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info); - -//------------- Event API -------------// - -// Called by HCD to notify stack -extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); - -// Helper to send device attach event -extern void hcd_event_device_attach(uint8_t rhport, bool in_isr); - -// Helper to send device removal event -extern void hcd_event_device_remove(uint8_t rhport, bool in_isr); - -// Helper to send USB transfer event -extern void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HCD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h deleted file mode 100644 index 06011c63c..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hcd_attr.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef TUSB_HCD_ATTR_H_ -#define TUSB_HCD_ATTR_H_ - -#include "tusb_option.h" - -// Attribute includes -// - ENDPOINT_MAX: max (logical) number of endpoint -// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. - -//------------- NXP -------------// -#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) - #define HCD_ATTR_OHCI - -#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) - #define HCD_ATTR_EHCI_TRANSDIMENSION - -#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX) - // #define HCD_ATTR_EHCI_NXP_PTD - -#elif TU_CHECK_MCU(OPT_MCU_LPC55XX) - // #define HCD_ATTR_EHCI_NXP_PTD - -#elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX) - #define HCD_ATTR_EHCI_TRANSDIMENSION - -#elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX) - -//------------- Microchip -------------// -#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ - TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) - -#elif TU_CHECK_MCU(OPT_MCU_SAMG) - -#elif TU_CHECK_MCU(OPT_MCU_SAMX7X) - -//------------- ST -------------// -#elif TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F1, OPT_MCU_STM32F3) || \ - TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1, OPT_MCU_STM32L4) - -#elif TU_CHECK_MCU(OPT_MCU_STM32F2, OPT_MCU_STM32F3, OPT_MCU_STM32F4) - -#elif TU_CHECK_MCU(OPT_MCU_STM32F7) - -#elif TU_CHECK_MCU(OPT_MCU_STM32H7) - -//------------- Sony -------------// -#elif TU_CHECK_MCU(OPT_MCU_CXD56) - -//------------- Nuvoton -------------// -#elif TU_CHECK_MCU(OPT_MCU_NUC505) - -//------------- Espressif -------------// -#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - -//------------- Raspberry Pi -------------// -#elif TU_CHECK_MCU(OPT_MCU_RP2040) - -//------------- Silabs -------------// -#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) - -//------------- Renesas -------------// -#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) - -//#elif TU_CHECK_MCU(OPT_MCU_MM32F327X) -// #define DCD_ATTR_ENDPOINT_MAX not known yet - -//------------- GigaDevice -------------// -#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) - -#else -// #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" -#endif - -// Default to fullspeed if not defined -//#ifndef PORT_HIGHSPEED -// #define DCD_ATTR_PORT_HIGHSPEED 0x00 -//#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c deleted file mode 100644 index fd4dbd04a..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HUB) - -#include "usbh.h" -#include "usbh_classdriver.h" -#include "hub.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t port_count; - uint8_t status_change; // data from status change interrupt endpoint - - hub_port_status_response_t port_status; -} hub_interface_t; - -CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB]; -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)]; - -TU_ATTR_ALWAYS_INLINE -static inline hub_interface_t* get_itf(uint8_t dev_addr) -{ - return &hub_data[dev_addr-1-CFG_TUH_DEVICE_MAX]; -} - -#if CFG_TUSB_DEBUG -static char const* const _hub_feature_str[] = -{ - [HUB_FEATURE_PORT_CONNECTION ] = "PORT_CONNECTION", - [HUB_FEATURE_PORT_ENABLE ] = "PORT_ENABLE", - [HUB_FEATURE_PORT_SUSPEND ] = "PORT_SUSPEND", - [HUB_FEATURE_PORT_OVER_CURRENT ] = "PORT_OVER_CURRENT", - [HUB_FEATURE_PORT_RESET ] = "PORT_RESET", - [HUB_FEATURE_PORT_POWER ] = "PORT_POWER", - [HUB_FEATURE_PORT_LOW_SPEED ] = "PORT_LOW_SPEED", - [HUB_FEATURE_PORT_CONNECTION_CHANGE ] = "PORT_CONNECTION_CHANGE", - [HUB_FEATURE_PORT_ENABLE_CHANGE ] = "PORT_ENABLE_CHANGE", - [HUB_FEATURE_PORT_SUSPEND_CHANGE ] = "PORT_SUSPEND_CHANGE", - [HUB_FEATURE_PORT_OVER_CURRENT_CHANGE ] = "PORT_OVER_CURRENT_CHANGE", - [HUB_FEATURE_PORT_RESET_CHANGE ] = "PORT_RESET_CHANGE", - [HUB_FEATURE_PORT_TEST ] = "PORT_TEST", - [HUB_FEATURE_PORT_INDICATOR ] = "PORT_INDICATOR", -}; -#endif - -//--------------------------------------------------------------------+ -// HUB -//--------------------------------------------------------------------+ -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb) -{ - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HUB_REQUEST_CLEAR_FEATURE, - .wValue = feature, - .wIndex = hub_port, - .wLength = 0 - }; - - TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); - return true; -} - -bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb) -{ - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HUB_REQUEST_SET_FEATURE, - .wValue = feature, - .wIndex = hub_port, - .wLength = 0 - }; - - TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); - return true; -} - -bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb) -{ - return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb); -} - -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb) -{ - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_OTHER, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = HUB_REQUEST_GET_STATUS, - .wValue = 0, - .wIndex = hub_port, - .wLength = 4 - }; - - TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer( hub_addr, &request, resp, complete_cb) ); - return true; -} - -//--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) -//--------------------------------------------------------------------+ -void hub_init(void) -{ - tu_memclr(hub_data, sizeof(hub_data)); -} - -bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && - 0 == itf_desc->bInterfaceSubClass); - - // hub driver does not support multiple TT yet - TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); - - // msc driver length is fixed - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len); - - //------------- Interrupt Status endpoint -------------// - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && - TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); - - hub_interface_t* p_hub = get_itf(dev_addr); - - p_hub->itf_num = itf_desc->bInterfaceNumber; - p_hub->ep_in = desc_ep->bEndpointAddress; - - return true; -} - -void hub_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr > CFG_TUH_DEVICE_MAX, ); - hub_interface_t* p_hub = get_itf(dev_addr); - - if (p_hub->ep_in) tu_memclr(p_hub, sizeof( hub_interface_t)); -} - -bool hub_status_pipe_queue(uint8_t dev_addr) -{ - hub_interface_t* hub_itf = get_itf(dev_addr); - return usbh_edpt_xfer(dev_addr, hub_itf->ep_in, &hub_itf->status_change, 1); -} - - -//--------------------------------------------------------------------+ -// Set Configure -//--------------------------------------------------------------------+ - -static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); - -bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - hub_interface_t* p_hub = get_itf(dev_addr); - TU_ASSERT(itf_num == p_hub->itf_num); - - // Get Hub Descriptor - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = HUB_REQUEST_GET_DESCRIPTOR, - .wValue = 0, - .wIndex = 0, - .wLength = sizeof(descriptor_hub_desc_t) - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, _hub_buffer, config_set_port_power) ); - - return true; -} - -static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - hub_interface_t* p_hub = get_itf(dev_addr); - - // only use number of ports in hub descriptor - descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer; - p_hub->port_count = desc_hub->bNbrPorts; - - // May need to GET_STATUS - - // Set Port Power to be able to detect connection, starting with port 1 - uint8_t const hub_port = 1; - return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); -} - -static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(XFER_RESULT_SUCCESS == result); - hub_interface_t* p_hub = get_itf(dev_addr); - - if (request->wIndex == p_hub->port_count) - { - // All ports are power -> queue notification status endpoint and - // complete the SET CONFIGURATION - TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1) ); - - usbh_driver_set_config_complete(dev_addr, p_hub->itf_num); - }else - { - // power next port - uint8_t const hub_port = (uint8_t) (request->wIndex + 1); - return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); - } - - return true; -} - -//--------------------------------------------------------------------+ -// Connection Changes -//--------------------------------------------------------------------+ - -static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); - -// callback as response of interrupt endpoint polling -bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports - (void) ep_addr; - TU_ASSERT(result == XFER_RESULT_SUCCESS); - - hub_interface_t* p_hub = get_itf(dev_addr); - - TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change); - - // Hub ignore bit0 in status change - for (uint8_t port=1; port <= p_hub->port_count; port++) - { - if ( tu_bit_test(p_hub->status_change, port) ) - { - hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete); - break; - } - } - - // NOTE: next status transfer is queued by usbh.c after handling this request - - return true; -} - -static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(result == XFER_RESULT_SUCCESS); - - hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) request->wIndex; - - // Connection change - if (p_hub->port_status.change.connection) - { - // Port is powered and enabled - //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); - - // Acknowledge Port Connection Change - hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete); - }else - { - // Other changes are: Enable, Suspend, Over Current, Reset, L1 state - // TODO clear change - - // prepare for next hub status - // TODO continue with status_change, or maybe we can do it again with status - hub_status_pipe_queue(dev_addr); - } - - return true; -} - -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(result == XFER_RESULT_SUCCESS); - - hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) request->wIndex; - - if ( p_hub->port_status.status.connection ) - { - // Reset port if attach event - hub_port_reset(dev_addr, port_num, connection_port_reset_complete); - }else - { - // submit detach event - hcd_event_t event = - { - .rhport = usbh_get_rhport(dev_addr), - .event_id = HCD_EVENT_DEVICE_REMOVE, - .connection = - { - .hub_addr = dev_addr, - .hub_port = port_num - } - }; - - hcd_event_handler(&event, false); - } - - return true; -} - -static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(result == XFER_RESULT_SUCCESS); - - // hub_interface_t* p_hub = get_itf(dev_addr); - uint8_t const port_num = (uint8_t) request->wIndex; - - // submit attach event - hcd_event_t event = - { - .rhport = usbh_get_rhport(dev_addr), - .event_id = HCD_EVENT_DEVICE_ATTACH, - .connection = - { - .hub_addr = dev_addr, - .hub_port = port_num - } - }; - - hcd_event_handler(&event, false); - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h deleted file mode 100644 index c4d544193..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/hub.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup group_class - * \defgroup ClassDriver_Hub Hub (Host only) - * \details Like most PC's OS, Hub support is completely hidden from Application. In fact, application cannot determine whether - * a device is mounted directly via roothub or via a hub's port. All Hub-related procedures are performed and managed - * by tinyusb stack. Unless you are trying to develop the stack itself, there are nothing else can be used by Application. - * \note Due to my laziness, only 1-level of Hub is supported. In other way, the stack cannot mount a hub via another hub. - * @{ - */ - -#ifndef _TUSB_HUB_H_ -#define _TUSB_HUB_H_ - -#include "common/tusb_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//D1...D0: Logical Power Switching Mode -//00: Ganged power switching (all ports’power at -//once) -//01: Individual port power switching -//1X: Reserved. Used only on 1.0 compliant hubs -//that implement no power switching -//D2: Identifies a Compound Device -//0: Hub is not part of a compound device. -//1: Hub is part of a compound device. -//D4...D3: Over-current Protection Mode -//00: Global Over-current Protection. The hub -//reports over-current as a summation of all -//ports’current draw, without a breakdown of -//individual port over-current status. -//01: Individual Port Over-current Protection. The -//hub reports over-current on a per-port basis. -//Each port has an over-current status. -//1X: No Over-current Protection. This option is -//allowed only for bus-powered hubs that do not -//implement over-current protection. -// -//D6...D5: TT Think TIme -//00: TT requires at most 8 FS bit times of inter -//transaction gap on a full-/low-speed -//downstream bus. -//01: TT requires at most 16 FS bit times. -//10: TT requires at most 24 FS bit times. -//11: TT requires at most 32 FS bit times. -//D7: Port Indicators Supported -//0: Port Indicators are not supported on its -//downstream facing ports and the -//PORT_INDICATOR request has no effect. -//1: Port Indicators are supported on its -//downstream facing ports and the -//PORT_INDICATOR request controls the -//indicators. See Section 11.5.3. -//D15...D8: Reserved - -typedef struct TU_ATTR_PACKED{ - uint8_t bLength ; ///< Size of descriptor - uint8_t bDescriptorType ; ///< Other_speed_Configuration Type - uint8_t bNbrPorts; - uint16_t wHubCharacteristics; - uint8_t bPwrOn2PwrGood; - uint8_t bHubContrCurrent; - uint8_t DeviceRemovable; // bitmap each bit for a port (from bit1) - uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff -} descriptor_hub_desc_t; - -TU_VERIFY_STATIC( sizeof(descriptor_hub_desc_t) == 9, "size is not correct"); - -enum { - HUB_REQUEST_GET_STATUS = 0 , - HUB_REQUEST_CLEAR_FEATURE = 1 , - - HUB_REQUEST_SET_FEATURE = 3 , - - HUB_REQUEST_GET_DESCRIPTOR = 6 , - HUB_REQUEST_SET_DESCRIPTOR = 7 , - HUB_REQUEST_CLEAR_TT_BUFFER = 8 , - HUB_REQUEST_RESET_TT = 9 , - HUB_REQUEST_GET_TT_STATE = 10 , - HUB_REQUEST_STOP_TT = 11 -}; - -enum { - HUB_FEATURE_HUB_LOCAL_POWER_CHANGE = 0, - HUB_FEATURE_HUB_OVER_CURRENT_CHANGE -}; - -enum{ - HUB_FEATURE_PORT_CONNECTION = 0, - HUB_FEATURE_PORT_ENABLE = 1, - HUB_FEATURE_PORT_SUSPEND = 2, - HUB_FEATURE_PORT_OVER_CURRENT = 3, - HUB_FEATURE_PORT_RESET = 4, - - HUB_FEATURE_PORT_POWER = 8, - HUB_FEATURE_PORT_LOW_SPEED = 9, - - HUB_FEATURE_PORT_CONNECTION_CHANGE = 16, - HUB_FEATURE_PORT_ENABLE_CHANGE = 17, - HUB_FEATURE_PORT_SUSPEND_CHANGE = 18, - HUB_FEATURE_PORT_OVER_CURRENT_CHANGE = 19, - HUB_FEATURE_PORT_RESET_CHANGE = 20, - HUB_FEATURE_PORT_TEST = 21, - HUB_FEATURE_PORT_INDICATOR = 22 -}; - -// data in response of HUB_REQUEST_GET_STATUS, wIndex = 0 (hub) -typedef struct { - union{ - struct TU_ATTR_PACKED { - uint16_t local_power_source : 1; - uint16_t over_current : 1; - uint16_t : 14; - }; - - uint16_t value; - } status, change; -} hub_status_response_t; - -TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); - -// data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num -typedef struct { - union { - struct TU_ATTR_PACKED { - uint16_t connection : 1; - uint16_t port_enable : 1; - uint16_t suspend : 1; - uint16_t over_current : 1; - uint16_t reset : 1; - - uint16_t : 3; - uint16_t port_power : 1; - uint16_t low_speed : 1; - uint16_t high_speed : 1; - uint16_t port_test_mode : 1; - uint16_t port_indicator_control : 1; - uint16_t TU_RESERVED : 3; - }; - - uint16_t value; - } status, change; -} hub_port_status_response_t; - -TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); - -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); -bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); - -bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb); -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb); -bool hub_status_pipe_queue(uint8_t dev_addr); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void hub_init (void); -bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void hub_close (uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_HUB_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c deleted file mode 100644 index b8439addc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.c +++ /dev/null @@ -1,1204 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_HOST_ENABLED - -#include "tusb.h" -#include "host/usbh.h" -#include "host/usbh_classdriver.h" -#include "hub.h" - -//--------------------------------------------------------------------+ -// USBH Configuration -//--------------------------------------------------------------------+ - -// TODO remove,update -#ifndef CFG_TUH_EP_MAX -#define CFG_TUH_EP_MAX 9 -#endif - -#ifndef CFG_TUH_TASK_QUEUE_SZ -#define CFG_TUH_TASK_QUEUE_SZ 16 -#endif - -// Debug level of USBD -#define USBH_DBG_LVL 2 - -//--------------------------------------------------------------------+ -// USBH-HCD common data structure -//--------------------------------------------------------------------+ - -// device0 struct must be strictly a subset of normal device struct -typedef struct -{ - // port - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; - - volatile struct TU_ATTR_PACKED - { - uint8_t connected : 1; - uint8_t addressed : 1; - uint8_t configured : 1; - uint8_t suspended : 1; - }; -} usbh_dev0_t; - -typedef struct { - // port - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; - - volatile struct TU_ATTR_PACKED - { - uint8_t connected : 1; - uint8_t addressed : 1; - uint8_t configured : 1; - uint8_t suspended : 1; - }; - - //------------- device descriptor -------------// - uint16_t vid; - uint16_t pid; - - uint8_t ep0_size; - uint8_t i_manufacturer; - uint8_t i_product; - uint8_t i_serial; - - //------------- configuration descriptor -------------// - // uint8_t interface_count; // bNumInterfaces alias - - //------------- device -------------// - volatile uint8_t state; // device state, value from enum tusbh_device_state_t - - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) - - struct TU_ATTR_PACKED - { - volatile bool busy : 1; - volatile bool stalled : 1; - volatile bool claimed : 1; - - // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[CFG_TUH_EP_MAX][2]; - - // Mutex for claiming endpoint, only needed when using with preempted RTOS -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_def_t mutexdef; - osal_mutex_t mutex; -#endif - -} usbh_device_t; - - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// Invalid driver ID in itf2drv[] ep2drv[][] mapping -enum { DRVID_INVALID = 0xFFu }; -enum { ADDR_INVALID = 0xFFu }; - -#if CFG_TUSB_DEBUG >= 2 - #define DRIVER_NAME(_name) .name = _name, -#else - #define DRIVER_NAME(_name) -#endif - -static usbh_class_driver_t const usbh_class_drivers[] = -{ - #if CFG_TUH_CDC - { - DRIVER_NAME("CDC") - .init = cdch_init, - .open = cdch_open, - .set_config = cdch_set_config, - .xfer_cb = cdch_xfer_cb, - .close = cdch_close - }, - #endif - - #if CFG_TUH_MSC - { - DRIVER_NAME("MSC") - .init = msch_init, - .open = msch_open, - .set_config = msch_set_config, - .xfer_cb = msch_xfer_cb, - .close = msch_close - }, - #endif - - #if CFG_TUH_HID - { - DRIVER_NAME("HID") - .init = hidh_init, - .open = hidh_open, - .set_config = hidh_set_config, - .xfer_cb = hidh_xfer_cb, - .close = hidh_close - }, - #endif - - #if CFG_TUH_HUB - { - DRIVER_NAME("HUB") - .init = hub_init, - .open = hub_open, - .set_config = hub_set_config, - .xfer_cb = hub_xfer_cb, - .close = hub_close - }, - #endif - - #if CFG_TUH_VENDOR - { - DRIVER_NAME("VENDOR") - .init = cush_init, - .open = cush_open_subtask, - .xfer_cb = cush_isr, - .close = cush_close - } - #endif -}; - -enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; - -enum { RESET_DELAY = 500 }; // 200 USB specs say only 50ms but many devices require much longer - -enum { CONFIG_NUM = 1 }; // default to use configuration 1 - - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -static bool _usbh_initialized = false; - -// Device with address = 0 for enumeration -static usbh_dev0_t _dev0; - -// all devices excluding zero-address -// hub address start from CFG_TUH_DEVICE_MAX+1 -CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUH_DEVICE_MAX + CFG_TUH_HUB]; - -// Event queue -// role device/host is used by OS NONE for mutex (disable usb isr) -OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); -static osal_queue_t _usbh_q; - -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; - -//------------- Helper Function -------------// - -TU_ATTR_ALWAYS_INLINE -static inline usbh_device_t* get_device(uint8_t dev_addr) -{ - TU_ASSERT(dev_addr, NULL); - return &_usbh_devices[dev_addr-1]; -} - -static bool enum_new_device(hcd_event_t* event); -static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); -static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); - -// from usbh_control.c -extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - -//--------------------------------------------------------------------+ -// PUBLIC API (Parameter Verification is required) -//--------------------------------------------------------------------+ -bool tuh_mounted(uint8_t dev_addr) -{ - return get_device(dev_addr)->configured; -} - -bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) -{ - *vid = *pid = 0; - - TU_VERIFY(tuh_mounted(dev_addr)); - - usbh_device_t const* dev = get_device(dev_addr); - - *vid = dev->vid; - *pid = dev->pid; - - return true; -} - -tusb_speed_t tuh_speed_get (uint8_t dev_addr) -{ - return (tusb_speed_t) (dev_addr ? get_device(dev_addr)->speed : _dev0.speed); -} - -#if CFG_TUSB_OS == OPT_OS_NONE -void osal_task_delay(uint32_t msec) -{ - (void) msec; - - const uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); - while ( ( hcd_frame_number(TUH_OPT_RHPORT) - start ) < msec ) {} -} -#endif - -//--------------------------------------------------------------------+ -// CLASS-USBD API (don't require to verify parameters) -//--------------------------------------------------------------------+ - -bool tuh_inited(void) -{ - return _usbh_initialized; -} - -bool tuh_init(uint8_t rhport) -{ - // skip if already initialized - if (_usbh_initialized) return _usbh_initialized; - - TU_LOG2("USBH init\r\n"); - - tu_memclr(_usbh_devices, sizeof(_usbh_devices)); - tu_memclr(&_dev0, sizeof(_dev0)); - - //------------- Enumeration & Reporter Task init -------------// - _usbh_q = osal_queue_create( &_usbh_qdef ); - TU_ASSERT(_usbh_q != NULL); - - //------------- Semaphore, Mutex for Control Pipe -------------// - for(uint8_t i=0; imutex = osal_mutex_create(&dev->mutexdef); - TU_ASSERT(dev->mutex); -#endif - - memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping - } - - // Class drivers init - for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - TU_LOG2("%s init\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].init(); - } - - TU_ASSERT(hcd_init(rhport)); - hcd_int_enable(rhport); - - _usbh_initialized = true; - return true; -} - -/* USB Host Driver task - * This top level thread manages all host controller event and delegates events to class-specific drivers. - * This should be called periodically within the mainloop or rtos thread. - * - @code - int main(void) - { - application_init(); - tusb_init(); - - while(1) // the mainloop - { - application_code(); - tuh_task(); // tinyusb host task - } - } - @endcode - */ -void tuh_task(void) -{ - // Skip if stack is not initialized - if ( !tusb_inited() ) return; - - // Loop until there is no more events in the queue - while (1) - { - hcd_event_t event; - if ( !osal_queue_receive(_usbh_q, &event) ) return; - - switch (event.event_id) - { - case HCD_EVENT_DEVICE_ATTACH: - // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating - // one device before enumerating another one. - TU_LOG2("USBH DEVICE ATTACH\r\n"); - enum_new_device(&event); - break; - - case HCD_EVENT_DEVICE_REMOVE: - TU_LOG2("USBH DEVICE REMOVED\r\n"); - process_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); - - #if CFG_TUH_HUB - // TODO remove - if ( event.connection.hub_addr != 0) - { - // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( event.connection.hub_addr ); - } - #endif - break; - - case HCD_EVENT_XFER_COMPLETE: - { - uint8_t const ep_addr = event.xfer_complete.ep_addr; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - - if (event.dev_addr == 0) - { - // device 0 only has control endpoint - TU_ASSERT(epnum == 0, ); - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - } - else - { - usbh_device_t* dev = get_device(event.dev_addr); - dev->ep_status[epnum][ep_dir].busy = false; - dev->ep_status[epnum][ep_dir].claimed = 0; - - if ( 0 == epnum ) - { - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - }else - { - uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); - - TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - } - } - } - break; - - case USBH_EVENT_FUNC_CALL: - if ( event.func_call.func ) event.func_call.func(event.func_call.param); - break; - - default: break; - } - } -} - -//--------------------------------------------------------------------+ -// USBH API For Class Driver -//--------------------------------------------------------------------+ - -uint8_t usbh_get_rhport(uint8_t dev_addr) -{ - return (dev_addr == 0) ? _dev0.rhport : get_device(dev_addr)->rhport; -} - -uint8_t* usbh_get_enum_buf(void) -{ - return _usbh_ctrl_buf; -} - -//--------------------------------------------------------------------+ -// HCD Event Handler -//--------------------------------------------------------------------+ - -void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info) -{ - if (dev_addr) - { - usbh_device_t const* dev = get_device(dev_addr); - - devtree_info->rhport = dev->rhport; - devtree_info->hub_addr = dev->hub_addr; - devtree_info->hub_port = dev->hub_port; - devtree_info->speed = dev->speed; - }else - { - devtree_info->rhport = _dev0.rhport; - devtree_info->hub_addr = _dev0.hub_addr; - devtree_info->hub_port = _dev0.hub_port; - devtree_info->speed = _dev0.speed; - } -} - -void hcd_event_handler(hcd_event_t const* event, bool in_isr) -{ - switch (event->event_id) - { - default: - osal_queue_send(_usbh_q, event, in_isr); - break; - } -} - -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) -{ - hcd_event_t event = - { - .rhport = 0, // TODO correct rhport - .event_id = HCD_EVENT_XFER_COMPLETE, - .dev_addr = dev_addr, - .xfer_complete = - { - .ep_addr = ep_addr, - .result = result, - .len = xferred_bytes - } - }; - - hcd_event_handler(&event, in_isr); -} - -void hcd_event_device_attach(uint8_t rhport, bool in_isr) -{ - hcd_event_t event = - { - .rhport = rhport, - .event_id = HCD_EVENT_DEVICE_ATTACH - }; - - event.connection.hub_addr = 0; - event.connection.hub_port = 0; - - hcd_event_handler(&event, in_isr); -} - -void hcd_event_device_remove(uint8_t hostid, bool in_isr) -{ - hcd_event_t event = - { - .rhport = hostid, - .event_id = HCD_EVENT_DEVICE_REMOVE - }; - - event.connection.hub_addr = 0; - event.connection.hub_port = 0; - - hcd_event_handler(&event, in_isr); -} - - -// a device unplugged on hostid, hub_addr, hub_port -// return true if found and unmounted device, false if cannot find -void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) -{ - //------------- find the all devices (star-network) under port that is unplugged -------------// - // TODO mark as disconnected in ISR, also handle dev0 - for ( uint8_t dev_id = 0; dev_id < TU_ARRAY_SIZE(_usbh_devices); dev_id++ ) - { - usbh_device_t* dev = &_usbh_devices[dev_id]; - uint8_t const dev_addr = dev_id+1; - - // TODO Hub multiple level - if (dev->rhport == rhport && - (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub - (hub_port == 0 || dev->hub_port == hub_port) && - dev->state != TUSB_DEVICE_STATE_UNPLUG) - { - // Invoke callback before close driver - if (tuh_umount_cb) tuh_umount_cb(dev_addr); - - // Close class driver - for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - TU_LOG2("%s close\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].close(dev_addr); - } - - hcd_device_close(rhport, dev_addr); - - // release all endpoints associated with the device - memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping - tu_memclr(dev->ep_status, sizeof(dev->ep_status)); - - dev->state = TUSB_DEVICE_STATE_UNPLUG; - } - } -} - -//--------------------------------------------------------------------+ -// INTERNAL HELPER -//--------------------------------------------------------------------+ -static uint8_t get_new_address(bool is_hub) -{ - uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1; - uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX); - - for (uint8_t i=0; i < count; i++) - { - uint8_t const addr = start + i; - if (get_device(addr)->state == TUSB_DEVICE_STATE_UNPLUG) return addr; - } - return ADDR_INVALID; -} - -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) -{ - usbh_device_t* dev = get_device(dev_addr); - - for(itf_num++; itf_num < sizeof(dev->itf2drv); itf_num++) - { - // continue with next valid interface - // TODO skip IAD binding interface such as CDCs - uint8_t const drv_id = dev->itf2drv[itf_num]; - if (drv_id != DRVID_INVALID) - { - usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num); - driver->set_config(dev_addr, itf_num); - break; - } - } - - // all interface are configured - if (itf_num == sizeof(dev->itf2drv)) - { - // Invoke callback if available - if (tuh_mount_cb) tuh_mount_cb(dev_addr); - } -} - -//--------------------------------------------------------------------+ -// Enumeration Process -// is a lengthy process with a seires of control transfer to configure -// newly attached device. Each step is handled by a function in this -// section -// TODO due to the shared _usbh_ctrl_buf, we must complete enumerating -// one device before enumerating another one. -//--------------------------------------------------------------------+ - -static bool enum_request_addr0_device_desc(void); -static bool enum_request_set_addr(void); - -static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_set_address_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_get_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_get_9byte_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_get_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool enum_set_config_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); - -#if CFG_TUH_HUB -static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - enum_request_addr0_device_desc(); - return true; -} - -static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - enum_request_set_addr(); - - // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( _dev0.hub_addr ); - - return true; -} - -static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - hub_port_status_response_t port_status; - memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); - - // Acknowledge Port Reset Change if Reset Successful - if (port_status.change.reset) - { - TU_ASSERT( hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); - } - - return true; -} - -static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) dev_addr; (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - hub_port_status_response_t port_status; - memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); - - if ( !port_status.status.connection ) - { - // device unplugged while delaying, nothing else to do, queue hub status - return hub_status_pipe_queue(dev_addr); - } - - _dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : - (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; - - // Acknowledge Port Reset Change - if (port_status.change.reset) - { - hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset0_complete); - } - - return true; -} -#endif - -static bool enum_new_device(hcd_event_t* event) -{ - _dev0.rhport = event->rhport; // TODO refractor integrate to device_pool - _dev0.hub_addr = event->connection.hub_addr; - _dev0.hub_port = event->connection.hub_port; - - //------------- connected/disconnected directly with roothub -------------// - if (_dev0.hub_addr == 0) - { - // wait until device is stable TODO non blocking - osal_task_delay(RESET_DELAY); - - // device unplugged while delaying - if ( !hcd_port_connect_status(_dev0.rhport) ) return true; - - _dev0.speed = hcd_port_speed_get(_dev0.rhport ); - - enum_request_addr0_device_desc(); - } -#if CFG_TUH_HUB - //------------- connected/disconnected via hub -------------// - else - { - // wait until device is stable - osal_task_delay(RESET_DELAY); - TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete) ); - } -#endif // CFG_TUH_HUB - - return true; -} - -static bool enum_request_addr0_device_desc(void) -{ - // TODO probably doesn't need to open/close each enumeration - uint8_t const addr0 = 0; - TU_ASSERT( usbh_edpt_control_open(addr0, 8) ); - - //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// - TU_LOG2("Get 8 byte of Device Descriptor\r\n"); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_DEVICE << 8, - .wIndex = 0, - .wLength = 8 - }; - TU_ASSERT( tuh_control_xfer(addr0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete) ); - - return true; -} - -// After Get Device Descriptor of Address 0 -static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(0 == dev_addr); - - if (XFER_RESULT_SUCCESS != result) - { -#if CFG_TUH_HUB - // TODO remove, waiting for next data on status pipe - if (_dev0.hub_addr != 0) hub_status_pipe_queue(_dev0.hub_addr); -#endif - - return false; - } - - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - TU_ASSERT( tu_desc_type(desc_device) == TUSB_DESC_DEVICE ); - - // Reset device again before Set Address - TU_LOG2("Port reset \r\n"); - - if (_dev0.hub_addr == 0) - { - // connected directly to roothub - hcd_port_reset( _dev0.rhport ); // reset port after 8 byte descriptor - osal_task_delay(RESET_DELAY); - - enum_request_set_addr(); - } -#if CFG_TUH_HUB - else - { - // after RESET_DELAY the hub_port_reset() already complete - TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, NULL) ); - osal_task_delay(RESET_DELAY); - - tuh_task(); // FIXME temporarily to clean up port_reset control transfer - - TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) ); - } -#endif - - return true; -} - -static bool enum_request_set_addr(void) -{ - uint8_t const addr0 = 0; - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - - // Get new address - uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); - TU_ASSERT(new_addr != ADDR_INVALID); - - TU_LOG2("Set Address = %d\r\n", new_addr); - - usbh_device_t* new_dev = get_device(new_addr); - - new_dev->rhport = _dev0.rhport; - new_dev->hub_addr = _dev0.hub_addr; - new_dev->hub_port = _dev0.hub_port; - new_dev->speed = _dev0.speed; - new_dev->connected = 1; - new_dev->ep0_size = desc_device->bMaxPacketSize0; - - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = new_addr, - .wIndex = 0, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(addr0, &new_request, NULL, enum_set_address_complete) ); - - return true; -} - -// After SET_ADDRESS is complete -static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(0 == dev_addr); - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - uint8_t const new_addr = (uint8_t const) request->wValue; - - usbh_device_t* new_dev = get_device(new_addr); - new_dev->addressed = 1; - - // TODO close device 0, may not be needed - hcd_device_close(_dev0.rhport, 0); - - // open control pipe for new address - TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size) ); - - // Get full device descriptor - TU_LOG2("Get Device Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_DEVICE << 8, - .wIndex = 0, - .wLength = sizeof(tusb_desc_device_t) - }; - - TU_ASSERT(tuh_control_xfer(new_addr, &new_request, _usbh_ctrl_buf, enum_get_device_desc_complete)); - - return true; -} - -static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - usbh_device_t* dev = get_device(dev_addr); - - dev->vid = desc_device->idVendor; - dev->pid = desc_device->idProduct; - dev->i_manufacturer = desc_device->iManufacturer; - dev->i_product = desc_device->iProduct; - dev->i_serial = desc_device->iSerialNumber; - -// if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); - - TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), - .wIndex = 0, - .wLength = 9 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_9byte_config_desc_complete) ); - - return true; -} - -static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - // TODO not enough buffer to hold configuration descriptor - uint8_t const * desc_config = _usbh_ctrl_buf; - - // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); - - TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); - - // Get full configuration descriptor - TU_LOG2("Get Configuration Descriptor\r\n"); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), - .wIndex = 0, - .wLength = total_len - - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); - - return true; -} - -static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - // Parse configuration & set up drivers - // Driver open aren't allowed to make any usb transfer yet - TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); - - TU_LOG2("Set Configuration = %d\r\n", CONFIG_NUM); - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_CONFIGURATION, - .wValue = CONFIG_NUM, - .wIndex = 0, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, enum_set_config_complete) ); - - return true; -} - -static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - TU_LOG2("Device configured\r\n"); - usbh_device_t* dev = get_device(dev_addr); - dev->configured = 1; - dev->state = TUSB_DEVICE_STATE_CONFIGURED; - - // Start the Set Configuration process for interfaces (itf = DRVID_INVALID) - // Since driver can perform control transfer within its set_config, this is done asynchronously. - // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() - // TODO use separated API instead of using DRVID_INVALID - usbh_driver_set_config_complete(dev_addr, DRVID_INVALID); - - return true; -} - -static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) -{ - usbh_device_t* dev = get_device(dev_addr); - - uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); - uint8_t const* p_desc = tu_desc_next(desc_cfg); - - // parse each interfaces - while( p_desc < desc_end ) - { - uint8_t assoc_itf_count = 1; - - // Class will always starts with Interface Association (if any) and then Interface descriptor - if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) - { - tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; - assoc_itf_count = desc_iad->bInterfaceCount; - - p_desc = tu_desc_next(p_desc); // next to Interface - - // IAD's first interface number and class should match with opened interface - //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && - // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); - } - - TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - -#if CFG_TUH_MIDI - // MIDI has 2 interfaces (Audio Control v1 + MIDIStreaming) but does not have IAD - // manually increase the associated count - if (1 == assoc_itf_count && - TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) - { - assoc_itf_count = 2; - } -#endif - - uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, assoc_itf_count, desc_end-p_desc); - TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t)); - - if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) - { - // TODO Attach hub to Hub is not currently supported - // skip this interface - TU_LOG(USBH_DBG_LVL, "Only 1 level of HUB is supported\r\n"); - } - else - { - // Find driver for this interface - uint8_t drv_id; - for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - - if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) - { - // open successfully - TU_LOG2(" %s opened\r\n", driver->name); - - // bind (associated) interfaces to found driver - for(uint8_t i=0; ibInterfaceNumber+i; - - // Interface number must not be used already - TU_ASSERT( DRVID_INVALID == dev->itf2drv[itf_num] ); - dev->itf2drv[itf_num] = drv_id; - } - - // bind all endpoints to found driver - tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); - - break; // exit driver find loop - } - } - - if( drv_id >= USBH_CLASS_DRIVER_COUNT ) - { - TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", - desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); - } - } - - // next Interface or IAD descriptor - p_desc += drv_len; - } - - return true; -} - -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - -#if CFG_TUSB_OS != OPT_OS_NONE - // pre-check to help reducing mutex lock - TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only claim the endpoint if it is not busy and not claimed yet. - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 1; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif - - return ret; -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only release the endpoint if it is claimed and not busy - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 0; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif - - return ret; -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() - // could return and USBH task can preempt and clear the busy - dev->ep_status[epnum][dir].busy = true; - - if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) - { - TU_LOG2("OK\r\n"); - return true; - }else - { - // HCD error, mark endpoint as ready to allow next transfer - dev->ep_status[epnum][dir].busy = false; - dev->ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) -{ - TU_LOG2("Open EP0 with Size = %u (addr = %u)\r\n", max_packet_size, dev_addr); - - tusb_desc_endpoint_t ep0_desc = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = max_packet_size, - .bInterval = 0 - }; - - return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc); -} - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) -{ - usbh_device_t* dev = get_device(dev_addr); - TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed)); - - return hcd_edpt_open(rhport, dev_addr, desc_ep); -} - -bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = get_device(dev_addr); - - return dev->ep_status[epnum][dir].busy; -} - - - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h deleted file mode 100644 index 8411cad28..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBH_H_ -#define _TUSB_USBH_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#include "common/tusb_common.h" -#include "hcd.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ - -// Init host stack -bool tuh_init(uint8_t rhport); - -// Check if host stack is already initialized -bool tuh_inited(void); - -// Task function should be called in main/rtos loop -void tuh_task(void); - -// Interrupt handler, name alias to HCD -extern void hcd_int_handler(uint8_t rhport); -#define tuh_int_handler hcd_int_handler - -bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid); -tusb_speed_t tuh_speed_get(uint8_t dev_addr); - -// Check if device is connected and configured -bool tuh_mounted(uint8_t dev_addr); - -// Check if device is suspended -static inline bool tuh_suspended(uint8_t dev_addr) -{ - // TODO implement suspend & resume on host - (void) dev_addr; - return false; -} - -// Check if device is ready to communicate with -TU_ATTR_ALWAYS_INLINE -static inline bool tuh_ready(uint8_t dev_addr) -{ - return tuh_mounted(dev_addr) && !tuh_suspended(dev_addr); -} - -// Carry out control transfer -bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); - -//--------------------------------------------------------------------+ -// APPLICATION CALLBACK -//--------------------------------------------------------------------+ -//TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); - -// Invoked when device is mounted (configured) -TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); - -/// Invoked when device is unmounted (bus reset/unplugged) -TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h deleted file mode 100644 index 8bc2622aa..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_classdriver.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_USBH_CLASSDRIVER_H_ -#define _TUSB_USBH_CLASSDRIVER_H_ - -#include "osal/osal.h" -#include "common/tusb_fifo.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Class Driver API -//--------------------------------------------------------------------+ - -typedef struct { - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - void (* const init )(void); - bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); -} usbh_class_driver_t; - -// Call by class driver to tell USBH that it has complete the enumeration -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); - -uint8_t usbh_get_rhport(uint8_t dev_addr); - -uint8_t* usbh_get_enum_buf(void); - -//--------------------------------------------------------------------+ -// USBH Endpoint API -//--------------------------------------------------------------------+ - -// Open an endpoint -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); - -// Submit a usb transfer -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -// Claim an endpoint before submitting a transfer. -// If caller does not make any transfer, it must release endpoint for others. -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); - -bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr); - -// Check if endpoint transferring is complete -bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c deleted file mode 100644 index 9204576ac..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/host/usbh_control.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_HOST_ENABLED - -#include "tusb.h" -#include "usbh_classdriver.h" - -enum -{ - STAGE_SETUP, - STAGE_DATA, - STAGE_ACK -}; - -typedef struct -{ - tusb_control_request_t request TU_ATTR_ALIGNED(4); - - uint8_t stage; - uint8_t* buffer; - tuh_control_complete_cb_t complete_cb; -} usbh_control_xfer_t; - -static usbh_control_xfer_t _ctrl_xfer; - -//CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN -//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) -{ - // TODO need to claim the endpoint first - const uint8_t rhport = usbh_get_rhport(dev_addr); - - _ctrl_xfer.request = (*request); - _ctrl_xfer.buffer = buffer; - _ctrl_xfer.stage = STAGE_SETUP; - _ctrl_xfer.complete_cb = complete_cb; - - TU_LOG2("Control Setup (addr = %u): ", dev_addr); - TU_LOG2_VAR(request); - TU_LOG2("\r\n"); - - // Send setup packet - TU_ASSERT( hcd_setup_send(rhport, dev_addr, (uint8_t const*) &_ctrl_xfer.request) ); - - return true; -} - -static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) -{ - TU_LOG2("\r\n"); - if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); -} - -bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) ep_addr; - (void) xferred_bytes; - - const uint8_t rhport = usbh_get_rhport(dev_addr); - - tusb_control_request_t const * request = &_ctrl_xfer.request; - - if (XFER_RESULT_SUCCESS != result) - { - TU_LOG2("Control failed: result = %d\r\n", result); - - // terminate transfer if any stage failed - _xfer_complete(dev_addr, result); - }else - { - switch(_ctrl_xfer.stage) - { - case STAGE_SETUP: - _ctrl_xfer.stage = STAGE_DATA; - if (request->wLength) - { - // DATA stage: initial data toggle is always 1 - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); - return true; - } - __attribute__((fallthrough)); - - case STAGE_DATA: - _ctrl_xfer.stage = STAGE_ACK; - - if (request->wLength) - { - TU_LOG2("Control data (addr = %u):\r\n", dev_addr); - TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); - } - - // ACK stage: toggle is always 1 - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); - break; - - case STAGE_ACK: - _xfer_complete(dev_addr, result); - break; - - default: return false; - } - } - - return true; -} - -#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h deleted file mode 100644 index c8131d19d..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_H_ -#define _TUSB_OSAL_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -/** \addtogroup group_osal - * @{ */ - -#include "common/tusb_common.h" - -// Return immediately -#define OSAL_TIMEOUT_NOTIMEOUT (0) -// Default timeout -#define OSAL_TIMEOUT_NORMAL (10) -// Wait forever -#define OSAL_TIMEOUT_WAIT_FOREVER (UINT32_MAX) - -#define OSAL_TIMEOUT_CONTROL_XFER OSAL_TIMEOUT_WAIT_FOREVER - -typedef void (*osal_task_func_t)( void * ); - -#if CFG_TUSB_OS == OPT_OS_NONE - #include "osal_none.h" -#elif CFG_TUSB_OS == OPT_OS_FREERTOS - #include "osal_freertos.h" -#elif CFG_TUSB_OS == OPT_OS_MYNEWT - #include "osal_mynewt.h" -#elif CFG_TUSB_OS == OPT_OS_PICO - #include "osal_pico.h" -#elif CFG_TUSB_OS == OPT_OS_RTTHREAD - #include "osal_rtthread.h" -#elif CFG_TUSB_OS == OPT_OS_CUSTOM - #include "tusb_os_custom.h" // implemented by application -#else - #error OS is not supported yet -#endif - -//--------------------------------------------------------------------+ -// OSAL Porting API -//--------------------------------------------------------------------+ - -#if __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wredundant-decls" -#endif -//------------- Semaphore -------------// -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); -static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec); - -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed - -//------------- Mutex -------------// -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef); -static inline bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec); -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl); - -//------------- Queue -------------// -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef); -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data); -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); -static inline bool osal_queue_empty(osal_queue_t qhdl); -#if __GNUC__ -#pragma GCC diagnostic pop -#endif - -#if 0 // TODO remove subtask related macros later -// Sub Task -#define OSAL_SUBTASK_BEGIN -#define OSAL_SUBTASK_END return TUSB_ERROR_NONE; - -#define STASK_RETURN(_error) return _error; -#define STASK_INVOKE(_subtask, _status) (_status) = _subtask -#define STASK_ASSERT(_cond) TU_VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED) -#endif - -#ifdef __cplusplus - } -#endif - -/** @} */ - -#endif /* _TUSB_OSAL_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h deleted file mode 100644 index 4573e01f5..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_freertos.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_FREERTOS_H_ -#define _TUSB_OSAL_FREERTOS_H_ - -// FreeRTOS Headers -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,FreeRTOS.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,semphr.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,queue.h) -#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,task.h) - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) -{ - vTaskDelay( pdMS_TO_TICKS(msec) ); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef StaticSemaphore_t osal_semaphore_def_t; -typedef SemaphoreHandle_t osal_semaphore_t; - -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - return xSemaphoreCreateBinaryStatic(semdef); -} - -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - if ( !in_isr ) - { - return xSemaphoreGive(sem_hdl) != 0; - } - else - { - BaseType_t xHigherPriorityTaskWoken; - BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - - return res != 0; - } -} - -static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) -{ - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(msec); - return xSemaphoreTake(sem_hdl, ticks); -} - -static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) -{ - xQueueReset(sem_hdl); -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef StaticSemaphore_t osal_mutex_def_t; -typedef SemaphoreHandle_t osal_mutex_t; - -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - return xSemaphoreCreateMutexStatic(mdef); -} - -static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ - return osal_semaphore_wait(mutex_hdl, msec); -} - -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return xSemaphoreGive(mutex_hdl); -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - static _type _name##_##buf[_depth];\ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; - -typedef struct -{ - uint16_t depth; - uint16_t item_sz; - void* buf; - - StaticQueue_t sq; -}osal_queue_def_t; - -typedef QueueHandle_t osal_queue_t; - -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); -} - -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) -{ - return xQueueReceive(qhdl, data, portMAX_DELAY); -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - if ( !in_isr ) - { - return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0; - } - else - { - BaseType_t xHigherPriorityTaskWoken; - BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - - return res != 0; - } -} - -static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - return uxQueueMessagesWaiting(qhdl) == 0; -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_OSAL_FREERTOS_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h deleted file mode 100644 index 6882329c1..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_mynewt.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef OSAL_MYNEWT_H_ -#define OSAL_MYNEWT_H_ - -#include "os/os.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) -{ - os_time_delay( os_time_ms_to_ticks32(msec) ); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef struct os_sem osal_semaphore_def_t; -typedef struct os_sem* osal_semaphore_t; - -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - return (os_sem_init(semdef, 0) == OS_OK) ? (osal_semaphore_t) semdef : NULL; -} - -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - (void) in_isr; - return os_sem_release(sem_hdl) == OS_OK; -} - -static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) -{ - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); - return os_sem_pend(sem_hdl, ticks) == OS_OK; -} - -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ - // TODO implement later -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef struct os_mutex osal_mutex_def_t; -typedef struct os_mutex* osal_mutex_t; - -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - return (os_mutex_init(mdef) == OS_OK) ? (osal_mutex_t) mdef : NULL; -} - -static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) -{ - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec); - return os_mutex_pend(mutex_hdl, ticks) == OS_OK; -} - -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return os_mutex_release(mutex_hdl) == OS_OK; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - static _type _name##_##buf[_depth];\ - static struct os_event _name##_##evbuf[_depth];\ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, .evbuf = _name##_##evbuf};\ - -typedef struct -{ - uint16_t depth; - uint16_t item_sz; - void* buf; - void* evbuf; - - struct os_mempool mpool; - struct os_mempool epool; - - struct os_eventq evq; -}osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - if ( OS_OK != os_mempool_init(&qdef->mpool, qdef->depth, qdef->item_sz, qdef->buf, "usbd queue") ) return NULL; - if ( OS_OK != os_mempool_init(&qdef->epool, qdef->depth, sizeof(struct os_event), qdef->evbuf, "usbd evqueue") ) return NULL; - - os_eventq_init(&qdef->evq); - return (osal_queue_t) qdef; -} - -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) -{ - struct os_event* ev; - ev = os_eventq_get(&qhdl->evq); - - memcpy(data, ev->ev_arg, qhdl->item_sz); // copy message - os_memblock_put(&qhdl->mpool, ev->ev_arg); // put back mem block - os_memblock_put(&qhdl->epool, ev); // put back ev block - - return true; -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - (void) in_isr; - - // get a block from mem pool for data - void* ptr = os_memblock_get(&qhdl->mpool); - if (!ptr) return false; - memcpy(ptr, data, qhdl->item_sz); - - // get a block from event pool to put into queue - struct os_event* ev = (struct os_event*) os_memblock_get(&qhdl->epool); - if (!ev) - { - os_memblock_put(&qhdl->mpool, ptr); - return false; - } - tu_memclr(ev, sizeof(struct os_event)); - ev->ev_arg = ptr; - - os_eventq_put(&qhdl->evq, ev); - - return true; -} - -static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - return STAILQ_EMPTY(&qhdl->evq.evq_list); -} - - -#ifdef __cplusplus - } -#endif - -#endif /* OSAL_MYNEWT_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h deleted file mode 100644 index a1f997cf2..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_none.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_NONE_H_ -#define _TUSB_OSAL_NONE_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ - - -//--------------------------------------------------------------------+ -// Binary Semaphore API -//--------------------------------------------------------------------+ -typedef struct -{ - volatile uint16_t count; -}osal_semaphore_def_t; - -typedef osal_semaphore_def_t* osal_semaphore_t; - -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - semdef->count = 0; - return semdef; -} - -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - (void) in_isr; - sem_hdl->count++; - return true; -} - -// TODO blocking for now -static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) -{ - (void) msec; - - while (sem_hdl->count == 0) { } - sem_hdl->count--; - - return true; -} - -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ - sem_hdl->count = 0; -} - -//--------------------------------------------------------------------+ -// MUTEX API -// Within tinyusb, mutex is never used in ISR context -//--------------------------------------------------------------------+ -typedef osal_semaphore_def_t osal_mutex_def_t; -typedef osal_semaphore_t osal_mutex_t; - -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - mdef->count = 1; - return mdef; -} - -static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ - return osal_semaphore_wait(mutex_hdl, msec); -} - -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - return osal_semaphore_post(mutex_hdl, false); -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ -#include "common/tusb_fifo.h" - -// extern to avoid including dcd.h and hcd.h -#if TUSB_OPT_DEVICE_ENABLED -extern void dcd_int_disable(uint8_t rhport); -extern void dcd_int_enable(uint8_t rhport); -#endif - -#if TUSB_OPT_HOST_ENABLED -extern void hcd_int_disable(uint8_t rhport); -extern void hcd_int_enable(uint8_t rhport); -#endif - -typedef struct -{ - uint8_t role; // device or host - tu_fifo_t ff; -}osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .role = _role, \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } - -// lock queue by disable USB interrupt -static inline void _osal_q_lock(osal_queue_t qhdl) -{ - (void) qhdl; - -#if TUSB_OPT_DEVICE_ENABLED - if (qhdl->role == OPT_MODE_DEVICE) dcd_int_disable(TUD_OPT_RHPORT); -#endif - -#if TUSB_OPT_HOST_ENABLED - if (qhdl->role == OPT_MODE_HOST) hcd_int_disable(TUH_OPT_RHPORT); -#endif -} - -// unlock queue -static inline void _osal_q_unlock(osal_queue_t qhdl) -{ - (void) qhdl; - -#if TUSB_OPT_DEVICE_ENABLED - if (qhdl->role == OPT_MODE_DEVICE) dcd_int_enable(TUD_OPT_RHPORT); -#endif - -#if TUSB_OPT_HOST_ENABLED - if (qhdl->role == OPT_MODE_HOST) hcd_int_enable(TUH_OPT_RHPORT); -#endif -} - -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - tu_fifo_clear(&qdef->ff); - return (osal_queue_t) qdef; -} - -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) -{ - _osal_q_lock(qhdl); - bool success = tu_fifo_read(&qhdl->ff, data); - _osal_q_unlock(qhdl); - - return success; -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - if (!in_isr) { - _osal_q_lock(qhdl); - } - - bool success = tu_fifo_write(&qhdl->ff, data); - - if (!in_isr) { - _osal_q_unlock(qhdl); - } - - TU_ASSERT(success); - - return success; -} - -static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - // Skip queue lock/unlock since this function is primarily called - // with interrupt disabled before going into low power mode - return tu_fifo_empty(&qhdl->ff); -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_OSAL_NONE_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h deleted file mode 100644 index 1c3366e01..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_pico.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_PICO_H_ -#define _TUSB_OSAL_PICO_H_ - -#include "pico/time.h" -#include "pico/sem.h" -#include "pico/mutex.h" -#include "pico/critical_section.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) -{ - sleep_ms(msec); -} - -//--------------------------------------------------------------------+ -// Binary Semaphore API -//--------------------------------------------------------------------+ -typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; - -static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) -{ - sem_init(semdef, 0, 255); - return semdef; -} - -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) -{ - (void) in_isr; - sem_release(sem_hdl); - return true; -} - -static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) -{ - return sem_acquire_timeout_ms(sem_hdl, msec); -} - -static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) -{ - sem_reset(sem_hdl, 0); -} - -//--------------------------------------------------------------------+ -// MUTEX API -// Within tinyusb, mutex is never used in ISR context -//--------------------------------------------------------------------+ -typedef struct mutex osal_mutex_def_t, *osal_mutex_t; - -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) -{ - mutex_init(mdef); - return mdef; -} - -static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) -{ - return mutex_enter_timeout_ms(mutex_hdl, msec); -} - -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) -{ - mutex_exit(mutex_hdl); - return true; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ -#include "common/tusb_fifo.h" - -#if TUSB_OPT_HOST_ENABLED -extern void hcd_int_disable(uint8_t rhport); -extern void hcd_int_enable(uint8_t rhport); -#endif - -typedef struct -{ - tu_fifo_t ff; - struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section -} osal_queue_def_t; - -typedef osal_queue_def_t* osal_queue_t; - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } - -// lock queue by disable USB interrupt -static inline void _osal_q_lock(osal_queue_t qhdl) -{ - critical_section_enter_blocking(&qhdl->critsec); -} - -// unlock queue -static inline void _osal_q_unlock(osal_queue_t qhdl) -{ - critical_section_exit(&qhdl->critsec); -} - -static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) -{ - critical_section_init(&qdef->critsec); - tu_fifo_clear(&qdef->ff); - return (osal_queue_t) qdef; -} - -static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) -{ - // TODO: revisit... docs say that mutexes are never used from IRQ context, - // however osal_queue_recieve may be. therefore my assumption is that - // the fifo mutex is not populated for queues used from an IRQ context - //assert(!qhdl->ff.mutex); - - _osal_q_lock(qhdl); - bool success = tu_fifo_read(&qhdl->ff, data); - _osal_q_unlock(qhdl); - - return success; -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - // TODO: revisit... docs say that mutexes are never used from IRQ context, - // however osal_queue_recieve may be. therefore my assumption is that - // the fifo mutex is not populated for queues used from an IRQ context - //assert(!qhdl->ff.mutex); - (void) in_isr; - - _osal_q_lock(qhdl); - bool success = tu_fifo_write(&qhdl->ff, data); - _osal_q_unlock(qhdl); - - TU_ASSERT(success); - - return success; -} - -static inline bool osal_queue_empty(osal_queue_t qhdl) -{ - // TODO: revisit; whether this is true or not currently, tu_fifo_empty is a single - // volatile read. - - // Skip queue lock/unlock since this function is primarily called - // with interrupt disabled before going into low power mode - return tu_fifo_empty(&qhdl->ff); -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_OSAL_PICO_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h deleted file mode 100644 index d5c062ac1..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/osal/osal_rtthread.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 tfx2001 (2479727366@qq.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_OSAL_RTTHREAD_H_ -#define _TUSB_OSAL_RTTHREAD_H_ - -// RT-Thread Headers -#include "rtthread.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//--------------------------------------------------------------------+ -// TASK API -//--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) { - rt_thread_mdelay(msec); -} - -//--------------------------------------------------------------------+ -// Semaphore API -//--------------------------------------------------------------------+ -typedef struct rt_semaphore osal_semaphore_def_t; -typedef rt_sem_t osal_semaphore_t; - -static inline osal_semaphore_t -osal_semaphore_create(osal_semaphore_def_t *semdef) { - rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_FIFO); - return semdef; -} - -static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - (void) in_isr; - return rt_sem_release(sem_hdl) == RT_EOK; -} - -static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { - return rt_sem_take(sem_hdl, rt_tick_from_millisecond(msec)) == RT_EOK; -} - -static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { - // TODO: implement -} - -//--------------------------------------------------------------------+ -// MUTEX API (priority inheritance) -//--------------------------------------------------------------------+ -typedef struct rt_mutex osal_mutex_def_t; -typedef rt_mutex_t osal_mutex_t; - -static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { - rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_FIFO); - return mdef; -} - -static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) { - return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond(msec)) == RT_EOK; -} - -static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { - return rt_mutex_release(mutex_hdl) == RT_EOK; -} - -//--------------------------------------------------------------------+ -// QUEUE API -//--------------------------------------------------------------------+ - -// role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - static _type _name##_##buf[_depth]; \ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; - -typedef struct { - uint16_t depth; - uint16_t item_sz; - void *buf; - - struct rt_messagequeue sq; -} osal_queue_def_t; - -typedef rt_mq_t osal_queue_t; - -static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { - rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz, - qdef->item_sz * qdef->depth, RT_IPC_FLAG_FIFO); - return &(qdef->sq); -} - -static inline bool osal_queue_receive(osal_queue_t qhdl, void *data) { - return rt_mq_recv(qhdl, data, qhdl->msg_size, RT_WAITING_FOREVER) == RT_EOK; -} - -static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) { - (void) in_isr; - return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK; -} - -static inline bool osal_queue_empty(osal_queue_t qhdl) { - return (qhdl->entry) == 0; -} - -#ifdef __cplusplus -} -#endif - -#endif /* _TUSB_OSAL_RTTHREAD_H_ */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c deleted file mode 100644 index a9c311324..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c +++ /dev/null @@ -1,854 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Additions Copyright (c) 2020, Espressif Systems (Shanghai) Co. Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && TUSB_OPT_DEVICE_ENABLED) - -// Espressif -#include "freertos/xtensa_api.h" -#include "esp_intr_alloc.h" -#include "esp_log.h" -#include "driver/gpio.h" -#include "soc/dport_reg.h" -#include "soc/gpio_sig_map.h" -#include "soc/usb_periph.h" -#include "soc/periph_defs.h" // for interrupt source - -#include "device/dcd.h" - -// Max number of bi-directional endpoints including EP0 -// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0 -// We should probably prohibit enabling Endpoint IN > 4 (not done yet) -#define EP_MAX USB_OUT_EP_NUM - -// FIFO size in bytes -#define EP_FIFO_SIZE 1024 - -// Max number of IN EP FIFOs -#define EP_FIFO_NUM 5 - -typedef struct { - uint8_t *buffer; - // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API - uint16_t total_len; - uint16_t queued_len; - uint16_t max_size; - bool short_packet; -} xfer_ctl_t; - -static const char *TAG = "TUSB:DCD"; -static intr_handle_t usb_ih; - - -static uint32_t _setup_packet[2]; - -#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] -static xfer_ctl_t xfer_status[EP_MAX][2]; - -// Keep count of how many FIFOs are in use -static uint8_t _allocated_fifos = 1; //FIFO0 is always in use - -// Will either return an unused FIFO number, or 0 if all are used. -static uint8_t get_free_fifo(void) -{ - if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; - return 0; -} - -// Setup the control endpoint 0. -static void bus_reset(void) -{ - for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { - USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - // clear device address - USB0.dcfg &= ~USB_DEVADDR_M; - - USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; - USB0.doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK; - USB0.diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; - - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): - // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN - // - // - All EP OUT shared a unique OUT FIFO which uses - // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). - // * 2 locations for OUT endpoint control words. - // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) - // * 1 location for global NAK (not required/used here). - // * It is recommended to allocate 2 times the largest packet size, therefore - // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 - USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, - USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo - USB0.grxfsiz = 52; - - // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); - - // Ready to receive SETUP packet - USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; - - USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; -} - -static void enum_done_processing(void) -{ - ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); - // On current silicon on the Full Speed core, speed is fixed to Full Speed. - // However, keep for debugging and in case Low Speed is ever supported. - uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); - - // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL - if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) - USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - } else { - USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; - } -} - - -/*------------------------------------------------------------------*/ -/* Controller API - *------------------------------------------------------------------*/ -void dcd_init(uint8_t rhport) -{ - ESP_LOGV(TAG, "DCD init - Start"); - - // A. Disconnect - ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); - USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect - - // B. Programming DCFG - /* If USB host misbehaves during status portion of control xfer - (non zero-length packet), send STALL back and discard. Full speed. */ - USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL - (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) - - USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON - USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode - USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides - - // C. Setting SNAKs, then connect - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - // D. Interruption masking - USB0.gintmsk = 0; //mask all - USB0.gotgint = ~0U; //clear OTG ints - USB0.gintsts = ~0U; //clear pending ints - USB0.gintmsk = USB_OTGINTMSK_M | - USB_MODEMISMSK_M | - USB_RXFLVIMSK_M | - USB_ERLYSUSPMSK_M | - USB_USBSUSPMSK_M | - USB_USBRSTMSK_M | - USB_ENUMDONEMSK_M | - USB_RESETDETMSK_M | - USB_DISCONNINTMSK_M; // host most only - - dcd_connect(rhport); -} - -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -{ - (void)rhport; - ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); - USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); - // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -} - -void dcd_remote_wakeup(uint8_t rhport) -{ - (void)rhport; - - // set remote wakeup - USB0.dctl |= USB_RMTWKUPSIG_M; - - // enable SOF to detect bus resume - USB0.gintsts = USB_SOF_M; - USB0.gintmsk |= USB_SOFMSK_M; - - // Per specs: remote wakeup signal bit must be clear within 1-15ms - vTaskDelay(pdMS_TO_TICKS(1)); - - USB0.dctl &= ~USB_RMTWKUPSIG_M; -} - -// connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) -{ - (void) rhport; - USB0.dctl &= ~USB_SFTDISCON_M; -} - -// disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; - USB0.dctl |= USB_SFTDISCON_M; -} - -/*------------------------------------------------------------------*/ -/* DCD Endpoint port - *------------------------------------------------------------------*/ - -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) -{ - ESP_LOGV(TAG, "DCD endpoint opened"); - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - - TU_ASSERT(epnum < EP_MAX); - - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = tu_edpt_packet_size(desc_edpt); - - if (dir == TUSB_DIR_OUT) { - out_ep[epnum].doepctl |= USB_USBACTEP1_M | - desc_edpt->bmAttributes.xfer << USB_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0) | - xfer->max_size << USB_MPS1_S; - USB0.daintmsk |= (1 << (16 + epnum)); - } else { - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints - // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) - // - Offset: GRXFSIZ + 16 + Size*(epnum-1) - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - - uint8_t fifo_num = get_free_fifo(); - TU_ASSERT(fifo_num != 0); - - in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M); - in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | - fifo_num << USB_D_TXFNUM1_S | - desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | - xfer->max_size << 0; - - USB0.daintmsk |= (1 << (0 + epnum)); - - // Both TXFD and TXSA are in unit of 32-bit words. - // IN FIFO 0 was configured during enumeration, hence the "+ 16". - uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; - uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); - uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); - - // DIEPTXF starts at FIFO #1. - USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; - } - return true; -} - -void dcd_edpt_close_all(uint8_t rhport) -{ - (void) rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - // Disable non-control interrupt - USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; - - for(uint8_t n = 1; n < EP_MAX; n++) - { - // disable OUT endpoint - out_ep[n].doepctl = 0; - xfer_status[n][TUSB_DIR_OUT].max_size = 0; - - // disable IN endpoint - in_ep[n].diepctl = 0; - xfer_status[n][TUSB_DIR_IN].max_size = 0; - } - - _allocated_fifos = 1; -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) -{ - (void)rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; - - uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if (short_packet_size > 0 || (total_bytes == 0)) { - num_packets++; - } - - ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", - epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), - num_packets, total_bytes); - - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them - // here. - if (dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; - USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK - - // Enable fifo empty interrupt only if there are something to put in the fifo. - if(total_bytes != 0) { - USB0.dtknqr4_fifoemptymsk |= (1 << epnum); - } - } else { - // Each complete packet for OUT xfers triggers XFRC. - USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - return true; -} - -#if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ - (void)rhport; -} -#endif - -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); - } else { - // Stop transmitting packets and NAK IN xfers. - in_ep[epnum].diepctl |= USB_DI_SNAK1_M; - while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) ; - - // Disable the endpoint. Note that both SNAK and STALL are set here. - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | USB_D_EPDIS1_M); - while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) ; - in_ep[epnum].diepint = USB_D_EPDISBLD0_M; - } - - // Flush the FIFO, and wait until we have confirmed it cleared. - uint8_t const fifo_num = ((in_ep[epnum].diepctl >> USB_D_TXFNUM1_S) & USB_D_TXFNUM1_V); - USB0.grstctl |= (fifo_num << USB_TXFNUM_S); - USB0.grstctl |= USB_TXFFLSH_M; - while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ; - } else { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { - out_ep[epnum].doepctl |= USB_STALL0_M; - } else { - // Asserting GONAK is required to STALL an OUT endpoint. - // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt - // anyway, and it can't be cleared by user code. If this while loop never - // finishes, we have bigger problems than just the stack. - USB0.dctl |= USB_SGOUTNAK_M; - while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) ; - - // Ditto here- disable the endpoint. Note that only STALL and not SNAK - // is set here. - out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); - while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) ; - out_ep[epnum].doepint = USB_EPDISBLD0_M; - - // Allow other OUT endpoints to keep receiving. - USB0.dctl |= USB_CGOUTNAK_M; - } - } -} - -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - in_ep[epnum].diepctl &= ~USB_D_STALL1_M; - - uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; - } - } else { - out_ep[epnum].doepctl &= ~USB_STALL1_M; - - uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; - } - } -} - -/*------------------------------------------------------------------*/ - -static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) -{ - ESP_EARLY_LOGV(TAG, "USB - receive_packet"); - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // See above TODO - // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; - // xfer->queued_len = xfer->total_len - remaining; - - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t to_recv_size; - - if (remaining <= xfer->max_size) { - // Avoid buffer overflow. - to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; - } else { - // Room for full packet, choose recv_size based on what the microcontroller - // claims. - to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; - } - - // Common buffer read -#if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - // Ring buffer - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); - } - else -#endif - { - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - - // Do not assume xfer buffer is aligned. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to collect. - if (to_recv_size >= 4) { - for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { - uint32_t tmp = (*rx_fifo); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; - } - } - - // Do not read invalid bytes from RX FIFO. - if (to_recv_rem != 0) { - uint32_t tmp = (*rx_fifo); - uint8_t *last_32b_bound = base + to_recv_size_aligned; - - last_32b_bound[0] = tmp & 0x000000FF; - if (to_recv_rem > 1) { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; - } - if (to_recv_rem > 2) { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; - } - } - } - - xfer->queued_len += xfer_size; - - // Per USB spec, a short OUT packet (including length 0) is always - // indicative of the end of a transfer (at least for ctl, bulk, int). - xfer->short_packet = (xfer_size < xfer->max_size); -} - -static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) -{ - ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); - volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; - - uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; - xfer->queued_len = xfer->total_len - remaining; - - uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - -#if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); - } - else -#endif - { - uint8_t to_xfer_rem = to_xfer_size % 4; - uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - - // Buffer might not be aligned to 32b, so we need to force alignment - // by copying to a temp var. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to send off. - if (to_xfer_size >= 4) { - for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { - uint32_t tmp = base[i] | (base[i + 1] << 8) | - (base[i + 2] << 16) | (base[i + 3] << 24); - (*tx_fifo) = tmp; - } - } - - // Do not read beyond end of buffer if not divisible by 4. - if (to_xfer_rem != 0) { - uint32_t tmp = 0; - uint8_t *last_32b_bound = base + to_xfer_size_aligned; - - tmp |= last_32b_bound[0]; - if (to_xfer_rem > 1) { - tmp |= (last_32b_bound[1] << 8); - } - if (to_xfer_rem > 2) { - tmp |= (last_32b_bound[2] << 16); - } - - (*tx_fifo) = tmp; - } - } -} - -static void read_rx_fifo(void) -{ - // Pop control word off FIFO (completed xfers will have 2 control words, - // we only pop one ctl word each interrupt). - uint32_t const ctl_word = USB0.grxstsp; - uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; - uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; - uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; - - switch (pktsts) { - case 0x01: // Global OUT NAK (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); - break; - - case 0x02: { // Out packet recvd - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - receive_packet(xfer, bcnt); - } - break; - - case 0x03: // Out packet done (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); - break; - - case 0x04: // Step 2: Setup transaction completed (Interrupt) - // After this event, OEPINT interrupt will occur with SETUP bit set - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); - USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; - break; - - case 0x06: { // Step1: Setup data packet received - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // We can receive up to three setup packets in succession, but - // only the last one is valid. Therefore we just overwrite it - _setup_packet[0] = (*rx_fifo); - _setup_packet[1] = (*rx_fifo); - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); - } - break; - - default: // Invalid, do something here, like breakpoint? - TU_BREAKPOINT(); - break; - } -} - -static void handle_epout_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DOEPINTx is cleared. - // DOEPINT will be cleared when DAINT's out bits are cleared. - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); - - if (USB0.daint & (1 << (16 + n))) { - // SETUP packet Setup Phase done. - if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { - USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear - dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); - } - - // OUT XFER complete (single packet).q - if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); - USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; - - // Transfer complete if short packet or total len is transferred - if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { - xfer->short_packet = false; - dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } else { - // Schedule another packet to be received. - USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - } - } - } -} - -static void handle_epin_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DIEPINTx is cleared. - // IEPINT will be cleared when DAINT's out bits are cleared. - for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { - xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; - - if (USB0.daint & (1 << (0 + n))) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); - // IN XFER complete (entire xfer). - if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); - USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; - dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - - // XFER FIFO empty - if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); - USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; - transmit_packet(xfer, &USB0.in_ep_reg[n], n); - - // Turn off TXFE if all bytes are written. - if (xfer->queued_len == xfer->total_len) - { - USB0.dtknqr4_fifoemptymsk &= ~(1 << n); - } - } - - // XFER Timeout - if (USB0.in_ep_reg[n].diepint & USB_D_TIMEOUT0_M) { - // Clear interrupt or enpoint will hang. - USB0.in_ep_reg[n].diepint = USB_D_TIMEOUT0_M; - // Maybe retry? - } - } - } -} - - -static void _dcd_int_handler(void* arg) -{ - (void) arg; - uint8_t const rhport = 0; - - const uint32_t int_msk = USB0.gintmsk; - const uint32_t int_status = USB0.gintsts & int_msk; - - if (int_status & USB_USBRST_M) { - // start of reset - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); - USB0.gintsts = USB_USBRST_M; - // FIFOs will be reassigned when the endpoints are reopen - _allocated_fifos = 1; - bus_reset(); - } - - if (int_status & USB_RESETDET_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); - USB0.gintsts = USB_RESETDET_M; - bus_reset(); - } - - if (int_status & USB_ENUMDONE_M) { - // ENUMDNE detects speed of the link. For full-speed, we - // always expect the same value. This interrupt is considered - // the end of reset. - USB0.gintsts = USB_ENUMDONE_M; - enum_done_processing(); - dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); - } - - if(int_status & USB_USBSUSP_M) - { - USB0.gintsts = USB_USBSUSP_M; - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); - } - - if(int_status & USB_WKUPINT_M) - { - USB0.gintsts = USB_WKUPINT_M; - dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); - } - - if (int_status & USB_OTGINT_M) - { - // OTG INT bit is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); - - uint32_t const otg_int = USB0.gotgint; - - if (otg_int & USB_SESENDDET_M) - { - dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); - } - - USB0.gotgint = otg_int; - } - - if (int_status & USB_SOF_M) { - USB0.gintsts = USB_SOF_M; - - // Disable SOF interrupt since currently only used for remote wakeup detection - USB0.gintmsk &= ~USB_SOFMSK_M; - - dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); - } - - - if (int_status & USB_RXFLVI_M) { - // RXFLVL bit is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); - - // Mask out RXFLVL while reading data from FIFO - USB0.gintmsk &= ~USB_RXFLVIMSK_M; - read_rx_fifo(); - USB0.gintmsk |= USB_RXFLVIMSK_M; - } - - // OUT endpoint interrupt handling. - if (int_status & USB_OEPINT_M) { - // OEPINT is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); - handle_epout_ints(); - } - - // IN endpoint interrupt handling. - if (int_status & USB_IEPINT_M) { - // IEPINT bit read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); - handle_epin_ints(); - } - - // Without handling - USB0.gintsts |= USB_CURMOD_INT_M | - USB_MODEMIS_M | - USB_OTGINT_M | - USB_NPTXFEMP_M | - USB_GINNAKEFF_M | - USB_GOUTNAKEFF | - USB_ERLYSUSP_M | - USB_USBSUSP_M | - USB_ISOOUTDROP_M | - USB_EOPF_M | - USB_EPMIS_M | - USB_INCOMPISOIN_M | - USB_INCOMPIP_M | - USB_FETSUSP_M | - USB_PTXFEMP_M; -} - -void dcd_int_enable (uint8_t rhport) -{ - (void) rhport; - esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) _dcd_int_handler, NULL, &usb_ih); -} - -void dcd_int_disable (uint8_t rhport) -{ - (void) rhport; - esp_intr_free(usb_ih); -} - -#endif // #if OPT_MCU_ESP32S2 || OPT_MCU_ESP32S3 - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c deleted file mode 100644 index 9583f509d..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/src/tusb.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_HOST_ENABLED || TUSB_OPT_DEVICE_ENABLED - -#include "tusb.h" - -// TODO clean up -#if TUSB_OPT_DEVICE_ENABLED -#include "device/usbd_pvt.h" -#endif - -bool tusb_init(void) -{ -#if TUSB_OPT_DEVICE_ENABLED - TU_ASSERT ( tud_init(TUD_OPT_RHPORT) ); // init device stack -#endif - -#if TUSB_OPT_HOST_ENABLED - TU_ASSERT( tuh_init(TUH_OPT_RHPORT) ); // init host stack -#endif - - return true; -} - -bool tusb_inited(void) -{ - bool ret = false; - -#if TUSB_OPT_DEVICE_ENABLED - ret = ret || tud_inited(); -#endif - -#if TUSB_OPT_HOST_ENABLED - ret = ret || tuh_inited(); -#endif - - return ret; -} - -//--------------------------------------------------------------------+ -// Internal Helper for both Host and Device stack -//--------------------------------------------------------------------+ - -bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) -{ - uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); - - switch (desc_ep->bmAttributes.xfer) - { - case TUSB_XFER_ISOCHRONOUS: - { - uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023); - TU_ASSERT(max_packet_size <= spec_size); - } - break; - - case TUSB_XFER_BULK: - if (speed == TUSB_SPEED_HIGH) - { - // Bulk highspeed must be EXACTLY 512 - TU_ASSERT(max_packet_size == 512); - }else - { - // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(max_packet_size <= 64); - } - break; - - case TUSB_XFER_INTERRUPT: - { - uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64); - TU_ASSERT(max_packet_size <= spec_size); - } - break; - - default: return false; - } - - return true; -} - -void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) -{ - uint8_t const* p_desc = (uint8_t const*) desc_itf; - uint8_t const* desc_end = p_desc + desc_len; - - while( p_desc < desc_end ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - TU_LOG(2, " Bind EP %02x to driver id %u\r\n", ep_addr, driver_id); - ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; - } - - p_desc = tu_desc_next(p_desc); - } -} - -uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) -{ - uint8_t const* p_desc = (uint8_t const*) desc_itf; - uint16_t len = 0; - - while (itf_count--) - { - // Next on interface desc - len += tu_desc_len(desc_itf); - p_desc = tu_desc_next(p_desc); - - while (len < max_len) - { - // return on IAD regardless of itf count - if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; - - if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && - ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) - { - break; - } - - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - } - - return len; -} - -/*------------------------------------------------------------------*/ -/* Debug - *------------------------------------------------------------------*/ -#if CFG_TUSB_DEBUG -#include - -char const* const tusb_strerr[TUSB_ERROR_COUNT] = { ERROR_TABLE(ERROR_STRING) }; - -static void dump_str_line(uint8_t const* buf, uint16_t count) -{ - tu_printf(" |"); - - // each line is 16 bytes - for(uint16_t i=0; i= 0 ) - -// Which roothub port is configured as device -#define TUD_OPT_RHPORT ( ((CFG_TUSB_RHPORT0_MODE) & OPT_MODE_DEVICE) ? 0 : (((CFG_TUSB_RHPORT1_MODE) & OPT_MODE_DEVICE) ? 1 : -1) ) - -#if TUD_OPT_RHPORT == 0 -#define TUD_OPT_HIGH_SPEED ( (CFG_TUSB_RHPORT0_MODE) & OPT_MODE_HIGH_SPEED ) -#else -#define TUD_OPT_HIGH_SPEED ( (CFG_TUSB_RHPORT1_MODE) & OPT_MODE_HIGH_SPEED ) -#endif - -#define TUSB_OPT_DEVICE_ENABLED ( TUD_OPT_RHPORT >= 0 ) - -//--------------------------------------------------------------------+ -// COMMON OPTIONS -//--------------------------------------------------------------------+ - -// Debug enable to print out error message -#ifndef CFG_TUSB_DEBUG - #define CFG_TUSB_DEBUG 0 -#endif - -// place data in accessible RAM for usb controller -#ifndef CFG_TUSB_MEM_SECTION - #define CFG_TUSB_MEM_SECTION -#endif - -// alignment requirement of buffer used for endpoint transferring -#ifndef CFG_TUSB_MEM_ALIGN - #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) -#endif - -// OS selection -#ifndef CFG_TUSB_OS - #define CFG_TUSB_OS OPT_OS_NONE -#endif - -#ifndef CFG_TUSB_OS_INC_PATH - #define CFG_TUSB_OS_INC_PATH -#endif - -//-------------------------------------------------------------------- -// DEVICE OPTIONS -//-------------------------------------------------------------------- - -#ifndef CFG_TUD_ENDPOINT0_SIZE - #define CFG_TUD_ENDPOINT0_SIZE 64 -#endif - -#ifndef CFG_TUD_CDC - #define CFG_TUD_CDC 0 -#endif - -#ifndef CFG_TUD_MSC - #define CFG_TUD_MSC 0 -#endif - -#ifndef CFG_TUD_HID - #define CFG_TUD_HID 0 -#endif - -#ifndef CFG_TUD_AUDIO - #define CFG_TUD_AUDIO 0 -#endif - -#ifndef CFG_TUD_VIDEO - #define CFG_TUD_VIDEO 0 -#endif - -#ifndef CFG_TUD_MIDI - #define CFG_TUD_MIDI 0 -#endif - -#ifndef CFG_TUD_VENDOR - #define CFG_TUD_VENDOR 0 -#endif - -#ifndef CFG_TUD_USBTMC - #define CFG_TUD_USBTMC 0 -#endif - -#ifndef CFG_TUD_DFU_RUNTIME - #define CFG_TUD_DFU_RUNTIME 0 -#endif - -#ifndef CFG_TUD_DFU - #define CFG_TUD_DFU 0 -#endif - -#ifndef CFG_TUD_BTH - #define CFG_TUD_BTH 0 -#endif - -#ifndef CFG_TUD_ECM_RNDIS - #ifdef CFG_TUD_NET - #warning "CFG_TUD_NET is renamed to CFG_TUD_ECM_RNDIS" - #define CFG_TUD_ECM_RNDIS CFG_TUD_NET - #else - #define CFG_TUD_ECM_RNDIS 0 - #endif -#endif - -#ifndef CFG_TUD_NCM - #define CFG_TUD_NCM 0 -#endif - -//-------------------------------------------------------------------- -// HOST OPTIONS -//-------------------------------------------------------------------- -#if TUSB_OPT_HOST_ENABLED - #ifndef CFG_TUH_DEVICE_MAX - #define CFG_TUH_DEVICE_MAX 1 - #endif - - #ifndef CFG_TUH_ENUMERATION_BUFSIZE - #define CFG_TUH_ENUMERATION_BUFSIZE 256 - #endif -#endif // TUSB_OPT_HOST_ENABLED - -//------------- CLASS -------------// - -#ifndef CFG_TUH_HUB -#define CFG_TUH_HUB 0 -#endif - -#ifndef CFG_TUH_CDC -#define CFG_TUH_CDC 0 -#endif - -#ifndef CFG_TUH_HID -#define CFG_TUH_HID 0 -#endif - -#ifndef CFG_TUH_MIDI -#define CFG_TUH_MIDI 0 -#endif - -#ifndef CFG_TUH_MSC -#define CFG_TUH_MSC 0 -#endif - -#ifndef CFG_TUH_VENDOR -#define CFG_TUH_VENDOR 0 -#endif - -//--------------------------------------------------------------------+ -// Port Specific -// TUP stand for TinyUSB Port (can be renamed) -//--------------------------------------------------------------------+ - -//------------- Unaligned Memory -------------// - -// ARMv7+ (M3-M7, M23-M33) can access unaligned memory -#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) - #define TUP_ARCH_STRICT_ALIGN 0 -#else - #define TUP_ARCH_STRICT_ALIGN 1 -#endif - -// TUP_MCU_STRICT_ALIGN will overwrite TUP_ARCH_STRICT_ALIGN. -// In case TUP_MCU_STRICT_ALIGN = 1 and TUP_ARCH_STRICT_ALIGN =0, we will not reply on compiler -// to generate unaligned access code. -// LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM -#if TUD_OPT_HIGH_SPEED && (CFG_TUSB_MCU == OPT_MCU_LPC54XXX || CFG_TUSB_MCU == OPT_MCU_LPC55XX) - #define TUP_MCU_STRICT_ALIGN 1 -#else - #define TUP_MCU_STRICT_ALIGN 0 -#endif - - -//------------------------------------------------------------------ -// Configuration Validation -//------------------------------------------------------------------ -#if CFG_TUD_ENDPOINT0_SIZE > 64 - #error Control Endpoint Max Packet Size cannot be larger than 64 -#endif - -#endif /* _TUSB_OPTION_H_ */ - -/** @} */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/CMakeLists.txt new file mode 100644 index 000000000..637991e7c --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.22) +project(libusb_test + LANGUAGES C +) + +add_executable(libusb_test libusb_test.c) +target_link_libraries(libusb_test -lusb-1.0) + diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/libusb_test.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/libusb_test.c new file mode 100644 index 000000000..3c86f44e0 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test/local/libusb_test.c @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define TINYUSB_VENDOR 0x303A +#define TINYUSB_PRODUCT 0x4002 + +#define DESC_TYPE_DEVICE_QUALIFIER 0x06 +#define DESC_TYOE_OTHER_SPEED_CONFIG 0x07 + +// Buffer for descriptor data +unsigned char buffer[512] = { 0 }; + +// USB Other Speed Configuration Descriptor +typedef struct __attribute__ ((packed)) +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + uint16_t wTotalLength ; ///< Total length of data returned + + uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration + uint8_t bConfigurationValue ; ///< Value to use to select configuration + uint8_t iConfiguration ; ///< Index of string descriptor + uint8_t bmAttributes ; ///< Same as Configuration descriptor + uint8_t bMaxPower ; ///< Same as Configuration descriptor +} desc_other_speed_t; + +// USB Device Qualifier Descriptor +typedef struct __attribute__ ((packed)) +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Device Qualifier Type + uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) + + uint8_t bDeviceClass ; ///< Class Code + uint8_t bDeviceSubClass ; ///< SubClass Code + uint8_t bDeviceProtocol ; ///< Protocol Code + + uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed + uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations + uint8_t bReserved ; ///< Reserved for future use, must be zero +} desc_device_qualifier_t; + +// printf helpers +static void _print_device_qulifier_desc(unsigned char *buffer, int length); +static void _print_other_speed_desc(unsigned char *buffer, int length); + +// +// MAIN +// +int main() +{ + libusb_context *context = NULL; + int rc = 0; + + rc = libusb_init(&context); + assert(rc == 0); + libusb_device_handle *dev_handle = libusb_open_device_with_vid_pid(context, + TINYUSB_VENDOR, + TINYUSB_PRODUCT); + + if (dev_handle != NULL) { + printf("TinyUSB Device has been found\n"); + + // Test Qualifier Descriprtor + // 1. Get Qualifier Descriptor + // 2. print descriptor data + rc = libusb_get_descriptor(dev_handle, DESC_TYPE_DEVICE_QUALIFIER, 0, buffer, 512); + _print_device_qulifier_desc(buffer, rc); + + // Test Other Speed Descriptor + // 1. Get Other Speed Descriptor + // 2. print descriptor data + rc = libusb_get_descriptor(dev_handle, DESC_TYOE_OTHER_SPEED_CONFIG, 0, buffer, 512); + _print_other_speed_desc(buffer, rc); + + libusb_close(dev_handle); + } else { + printf("TinyUSB Device has NOT been found\n"); + } + + libusb_exit(context); +} + + +// ============================================================================= +static void _print_device_qulifier_desc(unsigned char *buffer, int length) +{ + assert(buffer); + desc_device_qualifier_t *qualifier_desc = (desc_device_qualifier_t *) buffer; + printf("========= Device Qualifier ========== \n"); + printf("\t bLength: %d \n", qualifier_desc->bLength); + printf("\t bDescriptorType: %d (%#x)\n", qualifier_desc->bDescriptorType, qualifier_desc->bDescriptorType); + printf("\t bcdUSB: %d (%#x) \n", qualifier_desc->bcdUSB, qualifier_desc->bcdUSB); + printf("\t bDeviceClass: %d (%#x) \n", qualifier_desc->bDeviceClass, qualifier_desc->bDeviceClass); + printf("\t bDeviceSubClass: %d \n", qualifier_desc->bDeviceSubClass); + printf("\t bDeviceProtocol: %d \n", qualifier_desc->bDeviceProtocol); + printf("\t bMaxPacketSize0: %d \n", qualifier_desc->bMaxPacketSize0); + printf("\t bNumConfigurations: %d \n", qualifier_desc->bNumConfigurations); +} + +static void _print_other_speed_desc(unsigned char *buffer, int length) +{ + assert(buffer); + desc_other_speed_t *other_speed = (desc_other_speed_t *) buffer; + printf("============ Other Speed ============ \n"); + printf("\t bLength: %d \n", other_speed->bLength); + printf("\t bDescriptorType: %d (%#x) \n", other_speed->bDescriptorType, other_speed->bDescriptorType); + printf("\t wTotalLength: %d \n", other_speed->wTotalLength); + printf("\t bNumInterfaces: %d \n", other_speed->bNumInterfaces); + printf("\t bConfigurationValue: %d \n", other_speed->bConfigurationValue); + printf("\t iConfiguration: %d \n", other_speed->iConfiguration); + printf("\t bmAttributes: %d (%#x) \n", other_speed->bmAttributes, other_speed->bmAttributes); + printf("\t bMaxPower: %d (%#x) \n", other_speed->bMaxPower, other_speed->bMaxPower); +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/CMakeLists.txt new file mode 100644 index 000000000..9298e904a --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/CMakeLists.txt @@ -0,0 +1,11 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +# Set the components to include the tests for. +set(EXTRA_COMPONENT_DIRS + ../ + ) + +project(test_app_usb_device_esp_tinyusb) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/README.md b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/README.md new file mode 100644 index 000000000..c3b5e9e95 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/README.md @@ -0,0 +1,4 @@ +| Supported Targets | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | + +# USB: esp_tinyusb test application \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/CMakeLists.txt b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/CMakeLists.txt new file mode 100644 index 000000000..3cb6ad50a --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/CMakeLists.txt @@ -0,0 +1,6 @@ +include($ENV{IDF_PATH}/tools/cmake/version.cmake) + +idf_component_register(SRC_DIRS . + INCLUDE_DIRS . + REQUIRES unity esp_tinyusb + WHOLE_ARCHIVE) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/idf_component.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/idf_component.yml new file mode 100644 index 000000000..43ab3419f --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/idf_component.yml @@ -0,0 +1,7 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/esp_tinyusb: + version: "*" + override_path: "../../" + rules: + - if: "idf_version >= 5.0" \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_app_main.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_app_main.c new file mode 100644 index 000000000..b25c8df7e --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_app_main.c @@ -0,0 +1,57 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "unity.h" +#include "esp_heap_caps.h" + +static size_t before_free_8bit; +static size_t before_free_32bit; + +#define TEST_MEMORY_LEAK_THRESHOLD (-530) +static void check_leak(size_t before_free, size_t after_free, const char *type) +{ + ssize_t delta = after_free - before_free; + printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta); + TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak"); +} + +void app_main(void) +{ + // ____ ___ ___________________ __ __ + // | | \/ _____/\______ \ _/ |_ ____ _______/ |_ + // | | /\_____ \ | | _/ \ __\/ __ \ / ___/\ __\. + // | | / / \ | | \ | | \ ___/ \___ \ | | + // |______/ /_______ / |______ / |__| \___ >____ > |__| + // \/ \/ \/ \/ + printf(" ____ ___ ___________________ __ __ \r\n"); + printf("| | \\/ _____/\\______ \\ _/ |_ ____ _______/ |_ \r\n"); + printf("| | /\\_____ \\ | | _/ \\ __\\/ __ \\ / ___/\\ __\\\r\n"); + printf("| | / / \\ | | \\ | | \\ ___/ \\___ \\ | | \r\n"); + printf("|______/ /_______ / |______ / |__| \\___ >____ > |__| \r\n"); + printf(" \\/ \\/ \\/ \\/ \r\n"); + + UNITY_BEGIN(); + unity_run_menu(); + UNITY_END(); +} + +/* setUp runs before every test */ +void setUp(void) +{ + before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); +} + +/* tearDown runs after every test */ +void tearDown(void) +{ + size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); + check_leak(before_free_8bit, after_free_8bit, "8BIT"); + check_leak(before_free_32bit, after_free_32bit, "32BIT"); +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.c new file mode 100644 index 000000000..b596564f7 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.c @@ -0,0 +1,103 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" + +#if SOC_USB_OTG_SUPPORTED + +#include +#include +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_err.h" +#include "driver/gpio.h" +#include "esp_rom_gpio.h" +#include "soc/gpio_sig_map.h" +#include "unity.h" +#include "tinyusb.h" +#include "tusb_tasks.h" + +#define DEVICE_DETACH_TEST_ROUNDS 10 +#define DEVICE_DETACH_ROUND_DELAY_MS 1000 + +#if (CONFIG_IDF_TARGET_ESP32P4) +#define USB_SRP_BVALID_IN_IDX USB_SRP_BVALID_PAD_IN_IDX +#endif // CONFIG_IDF_TARGET_ESP32P4 + +/* TinyUSB descriptors + ********************************************************************* */ +#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN) + +static unsigned int dev_mounted = 0; +static unsigned int dev_umounted = 0; + +static uint8_t const test_configuration_descriptor[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_SELF_POWERED | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), +}; + +static const tusb_desc_device_t test_device_descriptor = { + .bLength = sizeof(test_device_descriptor), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = 0x303A, // This is Espressif VID. This needs to be changed according to Users / Customers + .idProduct = 0x4002, + .bcdDevice = 0x100, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + .bNumConfigurations = 0x01 +}; + +void test_bvalid_sig_mount_cb(void) +{ + dev_mounted++; +} + +void test_bvalid_sig_umount_cb(void) +{ + dev_umounted++; +} + +TEST_CASE("bvalid_signal", "[esp_tinyusb][usb_device]") +{ + unsigned int rounds = DEVICE_DETACH_TEST_ROUNDS; + + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = test_configuration_descriptor, + }; + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + + dev_mounted = 0; + dev_umounted = 0; + + while (rounds--) { + // LOW to emulate disconnect USB device + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_SRP_BVALID_IN_IDX, false); + vTaskDelay(pdMS_TO_TICKS(DEVICE_DETACH_ROUND_DELAY_MS)); + // HIGH to emulate connect USB device + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, false); + vTaskDelay(pdMS_TO_TICKS(DEVICE_DETACH_ROUND_DELAY_MS)); + } + + // Verify + TEST_ASSERT_EQUAL(dev_umounted, dev_mounted); + TEST_ASSERT_EQUAL(DEVICE_DETACH_TEST_ROUNDS, dev_mounted); + + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); +} +#endif // SOC_USB_OTG_SUPPORTED diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.h new file mode 100644 index 000000000..82dd31b90 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_bvalid_sig.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test_bvalid_sig_mount_cb(void); +void test_bvalid_sig_umount_cb(void); + +#ifdef __cplusplus +} +#endif //__cplusplus diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.c new file mode 100644 index 000000000..2b92b5151 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.c @@ -0,0 +1,235 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" + +#if SOC_USB_OTG_SUPPORTED + +#include +#include +#include "esp_system.h" +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_log.h" +#include "esp_err.h" +#include "driver/gpio.h" +#include "esp_rom_gpio.h" +#include "soc/gpio_sig_map.h" +#include "unity.h" +#include "tinyusb.h" +#include "tusb_tasks.h" + +#define DEVICE_MOUNT_TIMEOUT_MS 5000 + +// ========================= TinyUSB descriptors =============================== +#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN) + +static uint8_t const test_fs_configuration_descriptor[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_SELF_POWERED | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), +}; + +#if (TUD_OPT_HIGH_SPEED) +static uint8_t const test_hs_configuration_descriptor[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_SELF_POWERED | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), +}; +#endif // TUD_OPT_HIGH_SPEED + +static const tusb_desc_device_t test_device_descriptor = { + .bLength = sizeof(test_device_descriptor), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = 0x303A, // This is Espressif VID. This needs to be changed according to Users / Customers + .idProduct = 0x4002, + .bcdDevice = 0x100, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + .bNumConfigurations = 0x01 +}; + +// ========================== Private logic ==================================== +SemaphoreHandle_t desc_config_device_mounted = NULL; + +static bool __test_prep(void) +{ + desc_config_device_mounted = xSemaphoreCreateBinary(); + return (desc_config_device_mounted != NULL); +} + +static esp_err_t __test_wait_conn(void) +{ + if (!desc_config_device_mounted) { + return ESP_ERR_INVALID_STATE; + } + + return ( xSemaphoreTake(desc_config_device_mounted, pdMS_TO_TICKS(DEVICE_MOUNT_TIMEOUT_MS)) + ? ESP_OK + : ESP_ERR_TIMEOUT ); +} + +static void __test_conn(void) +{ + if (desc_config_device_mounted) { + xSemaphoreGive(desc_config_device_mounted); + } +} + +static void __test_free(void) +{ + if (desc_config_device_mounted) { + vSemaphoreDelete(desc_config_device_mounted); + } +} + +// ========================== Callbacks ======================================== +// Invoked when device is mounted +void test_descriptors_config_mount_cb(void) +{ + __test_conn(); +} + +void test_descriptors_config_umount_cb(void) +{ + +} + +TEST_CASE("descriptors_config_all_default", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = NULL, + .configuration_descriptor = NULL, +#if (TUD_OPT_HIGH_SPEED) + .hs_configuration_descriptor = NULL, +#endif // TUD_OPT_HIGH_SPEED + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_device", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = NULL, +#if (TUD_OPT_HIGH_SPEED) + .hs_configuration_descriptor = NULL, +#endif // TUD_OPT_HIGH_SPEED + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_device_and_config", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = test_fs_configuration_descriptor, +#if (TUD_OPT_HIGH_SPEED) + .hs_configuration_descriptor = NULL, +#endif // TUD_OPT_HIGH_SPEED + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +#if (TUD_OPT_HIGH_SPEED) +TEST_CASE("descriptors_config_device_and_fs_config_only", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = test_fs_configuration_descriptor, + .hs_configuration_descriptor = NULL, + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_device_and_hs_config_only", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = NULL, + .hs_configuration_descriptor = test_hs_configuration_descriptor, + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_all_configured", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .fs_configuration_descriptor = test_fs_configuration_descriptor, + .hs_configuration_descriptor = test_hs_configuration_descriptor, + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} +#endif // TUD_OPT_HIGH_SPEED + +#endif // SOC_USB_OTG_SUPPORTED diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.h b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.h new file mode 100644 index 000000000..6bdd77b7a --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_descriptors_config.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test_descriptors_config_mount_cb(void); +void test_descriptors_config_umount_cb(void); + +#ifdef __cplusplus +} +#endif //__cplusplus diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_esp_tinyusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_esp_tinyusb.c new file mode 100644 index 000000000..b71d48702 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_esp_tinyusb.c @@ -0,0 +1,132 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" +#if SOC_USB_OTG_SUPPORTED + +#include +#include +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_err.h" + +#include "unity.h" +#include "tinyusb.h" +#include "tusb_cdc_acm.h" +#include "vfs_tinyusb.h" + +#define VFS_PATH "/dev/usb-cdc1" + +// idf_component_register(WHOLE_ARCHIVE) backward compatibility to IDF_v4.4 +void linker_hook(void) {}; + +static const tusb_desc_device_t cdc_device_descriptor = { + .bLength = sizeof(cdc_device_descriptor), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = USB_ESPRESSIF_VID, + .idProduct = 0x4002, + .bcdDevice = 0x0100, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + .bNumConfigurations = 0x01 +}; + +static const uint16_t cdc_desc_config_len = TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN; +static const uint8_t cdc_desc_configuration[] = { + TUD_CONFIG_DESCRIPTOR(1, 4, 0, cdc_desc_config_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + TUD_CDC_DESCRIPTOR(0, 4, 0x81, 8, 0x02, 0x82, 64), + TUD_CDC_DESCRIPTOR(2, 4, 0x83, 8, 0x04, 0x84, 64), +}; + +static void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event) +{ +} + +/** + * @brief TinyUSB CDC testcase + * + * This is not a 'standard' testcase, as it never exits. The testcase runs in a loop where it echoes back all the data received. + * + * - Init TinyUSB with standard CDC device and configuration descriptors + * - Init 2 CDC-ACM interfaces + * - Map CDC1 to Virtual File System + * - In a loop: Read data from CDC0 and CDC1. Echo received data back + * + * Note: CDC0 appends 'novfs' to echoed data, so the host (test runner) can easily determine which port is which. + */ +TEST_CASE("tinyusb_cdc", "[esp_tinyusb]") +{ + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &cdc_device_descriptor, + .configuration_descriptor = cdc_desc_configuration + }; + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + + tinyusb_config_cdcacm_t acm_cfg = { + .usb_dev = TINYUSB_USBDEV_0, + .cdc_port = TINYUSB_CDC_ACM_0, + .rx_unread_buf_sz = 64, + .callback_rx = &tinyusb_cdc_rx_callback, + .callback_rx_wanted_char = NULL, + .callback_line_state_changed = NULL, + .callback_line_coding_changed = NULL + }; + + // Init CDC 0 + TEST_ASSERT_FALSE(tusb_cdc_acm_initialized(TINYUSB_CDC_ACM_0)); + TEST_ASSERT_EQUAL(ESP_OK, tusb_cdc_acm_init(&acm_cfg)); + TEST_ASSERT_TRUE(tusb_cdc_acm_initialized(TINYUSB_CDC_ACM_0)); + + // Init CDC 1 + acm_cfg.cdc_port = TINYUSB_CDC_ACM_1; + acm_cfg.callback_rx = NULL; + TEST_ASSERT_FALSE(tusb_cdc_acm_initialized(TINYUSB_CDC_ACM_1)); + TEST_ASSERT_EQUAL(ESP_OK, tusb_cdc_acm_init(&acm_cfg)); + TEST_ASSERT_TRUE(tusb_cdc_acm_initialized(TINYUSB_CDC_ACM_1)); + + // Install VFS to CDC 1 + TEST_ASSERT_EQUAL(ESP_OK, esp_vfs_tusb_cdc_register(TINYUSB_CDC_ACM_1, VFS_PATH)); + esp_vfs_tusb_cdc_set_rx_line_endings(ESP_LINE_ENDINGS_CRLF); + esp_vfs_tusb_cdc_set_tx_line_endings(ESP_LINE_ENDINGS_LF); + FILE *cdc = fopen(VFS_PATH, "r+"); + TEST_ASSERT_NOT_NULL(cdc); + + uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE + 1]; + while (true) { + size_t b = fread(buf, 1, sizeof(buf), cdc); + if (b > 0) { + printf("Intf VFS, RX %d bytes\n", b); + //ESP_LOG_BUFFER_HEXDUMP("test", buf, b, ESP_LOG_INFO); + fwrite(buf, 1, b, cdc); + } + vTaskDelay(1); + + size_t rx_size = 0; + int itf = 0; + ESP_ERROR_CHECK(tinyusb_cdcacm_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size)); + if (rx_size > 0) { + printf("Intf %d, RX %d bytes\n", itf, rx_size); + + // Add 'novfs' to reply so the host can identify the port + strcpy((char *)&buf[rx_size - 2], "novfs\r\n"); + tinyusb_cdcacm_write_queue(itf, buf, rx_size + sizeof("novfs") - 1); + + tinyusb_cdcacm_write_flush(itf, 0); + } + } +} + +#endif diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_tud_cb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_tud_cb.c new file mode 100644 index 000000000..37d0a3338 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/main/test_tud_cb.c @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "tinyusb.h" +#include "tusb_tasks.h" +#include "test_bvalid_sig.h" +#include "test_descriptors_config.h" + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + printf("%s\n", __FUNCTION__); + test_bvalid_sig_mount_cb(); + test_descriptors_config_mount_cb(); +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + printf("%s\n", __FUNCTION__); + test_bvalid_sig_umount_cb(); + test_descriptors_config_umount_cb(); +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_cdc.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_cdc.py new file mode 100644 index 000000000..1b48438a2 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_cdc.py @@ -0,0 +1,73 @@ +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import pytest +from pytest_embedded_idf.dut import IdfDut +from time import sleep +from serial import Serial +from serial.tools.list_ports import comports + + +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.usb_device +def test_usb_device_cdc(dut) -> None: + ''' + Running the test locally: + 1. Build the testa app for your DUT (ESP32-S2 or S3) + 2. Connect you DUT to your test runner (local machine) with USB port and flashing port + 3. Run `pytest --target esp32s3` + + Test procedure: + 1. Run the test on the DUT + 2. Expect 2 Virtual COM Ports in the system + 3. Open both comports and send some data. Expect echoed data + ''' + dut.expect_exact('Press ENTER to see the list of tests.') + dut.write('[esp_tinyusb]') + dut.expect_exact('TinyUSB: TinyUSB Driver installed') + sleep(2) # Some time for the OS to enumerate our USB device + + # Find devices with Espressif TinyUSB VID/PID + s = [] + ports = comports() + for port, _, hwid in ports: + if '303A:4002' in hwid: + s.append(port) + + if len(s) != 2: + raise Exception('TinyUSB COM port not found') + + with Serial(s[0]) as cdc0: + with Serial(s[1]) as cdc1: + # Write dummy string and check for echo + cdc0.write('text\r\n'.encode()) + res = cdc0.readline() + assert b'text' in res + if b'novfs' in res: + novfs_cdc = cdc0 + vfs_cdc = cdc1 + + cdc1.write('text\r\n'.encode()) + res = cdc1.readline() + assert b'text' in res + if b'novfs' in res: + novfs_cdc = cdc1 + vfs_cdc = cdc0 + + # Write more than MPS, check that the transfer is not divided + novfs_cdc.write(bytes(100)) + dut.expect_exact("Intf 0, RX 100 bytes") + + # Write more than RX buffer, check correct reception + novfs_cdc.write(bytes(600)) + transfer_len1 = int(dut.expect(r'Intf 0, RX (\d+) bytes')[1].decode()) + transfer_len2 = int(dut.expect(r'Intf 0, RX (\d+) bytes')[1].decode()) + assert transfer_len1 + transfer_len2 == 600 + + # The VFS is setup for CRLF RX and LF TX + vfs_cdc.write('text\r\n'.encode()) + res = vfs_cdc.readline() + assert b'text\n' in res + + return diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_esp_tinyusb.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_esp_tinyusb.py new file mode 100644 index 000000000..78765bcbb --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/pytest_usb_device_esp_tinyusb.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import pytest +from pytest_embedded_idf.dut import IdfDut + + +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.usb_device +def test_usb_device_esp_tinyusb(dut: IdfDut) -> None: + dut.run_all_single_board_cases(group='usb_device') diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/sdkconfig.defaults b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/sdkconfig.defaults new file mode 100644 index 000000000..e68b6cd87 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/test_app/sdkconfig.defaults @@ -0,0 +1,19 @@ +# Configure TinyUSB, it will be used to mock USB devices +CONFIG_TINYUSB=y +CONFIG_TINYUSB_MSC_ENABLED=n +CONFIG_TINYUSB_CDC_ENABLED=y +CONFIG_TINYUSB_CDC_COUNT=2 +CONFIG_TINYUSB_HID_COUNT=0 + +# Disable watchdogs, they'd get triggered during unity interactive menu +CONFIG_ESP_INT_WDT=n +CONFIG_ESP_TASK_WDT=n + +# Run-time checks of Heap and Stack +CONFIG_HEAP_POISONING_COMPREHENSIVE=y +CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y +CONFIG_COMPILER_STACK_CHECK=y + +CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y + +CONFIG_COMPILER_CXX_EXCEPTIONS=y diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tinyusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb.c similarity index 53% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tinyusb.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb.c index a081030c3..52bc2aebc 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tinyusb.c +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,7 +13,6 @@ #include "soc/usb_pins.h" #include "tinyusb.h" #include "descriptors_control.h" -#include "usb_descriptors.h" #include "tusb.h" #include "tusb_tasks.h" @@ -22,10 +21,7 @@ static usb_phy_handle_t phy_hdl; esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) { - const tusb_desc_device_t *dev_descriptor; - const char **string_descriptor; - const uint8_t *cfg_descriptor; - ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "Config can't be NULL"); // Configure USB PHY usb_phy_config_t phy_conf = { @@ -56,38 +52,22 @@ esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) } ESP_RETURN_ON_ERROR(usb_new_phy(&phy_conf, &phy_hdl), TAG, "Install USB PHY failed"); - if (config->configuration_descriptor) { - cfg_descriptor = config->configuration_descriptor; - } else { -#if (CONFIG_TINYUSB_HID_COUNT > 0 || CONFIG_TINYUSB_MIDI_COUNT > 0) - // For HID device, configuration descriptor must be provided - ESP_RETURN_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for this device"); -#else - cfg_descriptor = descriptor_cfg_kconfig; - ESP_LOGW(TAG, "The device's configuration descriptor is not provided by user, using default."); -#endif - } - - if (config->string_descriptor) { - string_descriptor = config->string_descriptor; - } else { - string_descriptor = descriptor_str_kconfig; - ESP_LOGW(TAG, "The device's string descriptor is not provided by user, using default."); - } - - if (config->device_descriptor) { - dev_descriptor = config->device_descriptor; - } else { - dev_descriptor = &descriptor_dev_kconfig; - ESP_LOGW(TAG, "The device's device descriptor is not provided by user, using default."); - } - - tusb_set_descriptor(dev_descriptor, string_descriptor, cfg_descriptor); + // Descriptors config + ESP_RETURN_ON_ERROR(tinyusb_set_descriptors(config), TAG, "Descriptors config failed"); + // Init +#if !CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK ESP_RETURN_ON_FALSE(tusb_init(), ESP_FAIL, TAG, "Init TinyUSB stack failed"); +#endif #if !CONFIG_TINYUSB_NO_DEFAULT_TASK ESP_RETURN_ON_ERROR(tusb_run_task(), TAG, "Run TinyUSB task failed"); #endif ESP_LOGI(TAG, "TinyUSB Driver installed"); return ESP_OK; } + +esp_err_t tinyusb_driver_uninstall() +{ + tinyusb_free_descriptors(); + return usb_del_phy(phy_hdl); +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb_net.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb_net.c new file mode 100644 index 000000000..f7390d763 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tinyusb_net.c @@ -0,0 +1,174 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "tinyusb_net.h" +#include "descriptors_control.h" +#include "usb_descriptors.h" +#include "device/usbd_pvt.h" +#include "esp_check.h" + +#define MAC_ADDR_LEN 6 + +typedef struct packet { + void *buffer; + void *buff_free_arg; + uint16_t len; + esp_err_t result; +} packet_t; + +struct tinyusb_net_handle { + bool initialized; + SemaphoreHandle_t buffer_sema; + EventGroupHandle_t tx_flags; + tusb_net_rx_cb_t rx_cb; + tusb_net_free_tx_cb_t tx_buff_free_cb; + tusb_net_init_cb_t init_cb; + char mac_str[2 * MAC_ADDR_LEN + 1]; + void *ctx; + packet_t *packet_to_send; +}; + +const static int TX_FINISHED_BIT = BIT0; +static struct tinyusb_net_handle s_net_obj = { }; +static const char *TAG = "tusb_net"; + +static void do_send_sync(void *ctx) +{ + (void) ctx; + if (xSemaphoreTake(s_net_obj.buffer_sema, 0) != pdTRUE || s_net_obj.packet_to_send == NULL) { + return; + } + + packet_t *packet = s_net_obj.packet_to_send; + if (tud_network_can_xmit(packet->len)) { + tud_network_xmit(packet, packet->len); + packet->result = ESP_OK; + } else { + packet->result = ESP_FAIL; + } + xSemaphoreGive(s_net_obj.buffer_sema); + xEventGroupSetBits(s_net_obj.tx_flags, TX_FINISHED_BIT); +} + +static void do_send_async(void *ctx) +{ + packet_t *packet = ctx; + if (tud_network_can_xmit(packet->len)) { + tud_network_xmit(packet, packet->len); + } else if (s_net_obj.tx_buff_free_cb) { + ESP_LOGW(TAG, "Packet cannot be accepted on USB interface, dropping"); + s_net_obj.tx_buff_free_cb(packet->buff_free_arg, s_net_obj.ctx); + } + free(packet); +} + +esp_err_t tinyusb_net_send_async(void *buffer, uint16_t len, void *buff_free_arg) +{ + if (!tud_ready()) { + return ESP_ERR_INVALID_STATE; + } + + packet_t *packet = calloc(1, sizeof(packet_t)); + packet->len = len; + packet->buffer = buffer; + packet->buff_free_arg = buff_free_arg; + ESP_RETURN_ON_FALSE(packet, ESP_ERR_NO_MEM, TAG, "Failed to allocate packet to send"); + usbd_defer_func(do_send_async, packet, false); + return ESP_OK; +} + +esp_err_t tinyusb_net_send_sync(void *buffer, uint16_t len, void *buff_free_arg, TickType_t timeout) +{ + if (!tud_ready()) { + return ESP_ERR_INVALID_STATE; + } + + // Lazy init the flags and semaphores, as they might not be needed (if async approach is used) + if (!s_net_obj.tx_flags) { + s_net_obj.tx_flags = xEventGroupCreate(); + ESP_RETURN_ON_FALSE(s_net_obj.tx_flags, ESP_ERR_NO_MEM, TAG, "Failed to allocate event flags"); + } + if (!s_net_obj.buffer_sema) { + s_net_obj.buffer_sema = xSemaphoreCreateBinary(); + ESP_RETURN_ON_FALSE(s_net_obj.buffer_sema, ESP_ERR_NO_MEM, TAG, "Failed to allocate buffer semaphore"); + } + + packet_t packet = { + .buffer = buffer, + .len = len, + .buff_free_arg = buff_free_arg + }; + s_net_obj.packet_to_send = &packet; + xSemaphoreGive(s_net_obj.buffer_sema); // now the packet is ready, let's mark it available to tusb send + + // to execute the send function in tinyUSB task context + usbd_defer_func(do_send_sync, NULL, false); // arg=NULL -> sync send, we keep the packet inside the object + + // wait wor completion with defined timeout + EventBits_t bits = xEventGroupWaitBits(s_net_obj.tx_flags, TX_FINISHED_BIT, pdTRUE, pdTRUE, timeout); + xSemaphoreTake(s_net_obj.buffer_sema, portMAX_DELAY); // if tusb sending already started, we have wait before ditching the packet + s_net_obj.packet_to_send = NULL; // invalidate the argument + if (bits & TX_FINISHED_BIT) { // If transaction finished, return error code + return packet.result; + } + return ESP_ERR_TIMEOUT; +} + +esp_err_t tinyusb_net_init(tinyusb_usbdev_t usb_dev, const tinyusb_net_config_t *cfg) +{ + (void) usb_dev; + + ESP_RETURN_ON_FALSE(s_net_obj.initialized == false, ESP_ERR_INVALID_STATE, TAG, "TinyUSB Net class is already initialized"); + + // the semaphore and event flags are initialized only if needed + s_net_obj.rx_cb = cfg->on_recv_callback; + s_net_obj.init_cb = cfg->on_init_callback; + s_net_obj.tx_buff_free_cb = cfg->free_tx_buffer; + s_net_obj.ctx = cfg->user_context; + + const uint8_t *mac = &cfg->mac_addr[0]; + snprintf(s_net_obj.mac_str, sizeof(s_net_obj.mac_str), "%02X%02X%02X%02X%02X%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + uint8_t mac_id = tusb_get_mac_string_id(); + // Pass it to Descriptor control module + tinyusb_set_str_descriptor(s_net_obj.mac_str, mac_id); + + s_net_obj.initialized = true; + + return ESP_OK; +} + +//--------------------------------------------------------------------+ +// tinyusb callbacks +//--------------------------------------------------------------------+ +bool tud_network_recv_cb(const uint8_t *src, uint16_t size) +{ + if (s_net_obj.rx_cb) { + s_net_obj.rx_cb((void *)src, size, s_net_obj.ctx); + } + tud_network_recv_renew(); + return true; +} + +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) +{ + packet_t *packet = ref; + uint16_t len = arg; + + memcpy(dst, packet->buffer, packet->len); + if (s_net_obj.tx_buff_free_cb) { + s_net_obj.tx_buff_free_cb(packet->buff_free_arg, s_net_obj.ctx); + } + return len; +} + +void tud_network_init_cb(void) +{ + if (s_net_obj.init_cb) { + s_net_obj.init_cb(s_net_obj.ctx); + } +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py deleted file mode 100644 index b2a80c680..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_board.py +++ /dev/null @@ -1,100 +0,0 @@ -import os -import glob -import sys -import subprocess -import time - -import build_utils - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -success_count = 0 -fail_count = 0 -skip_count = 0 -exit_status = 0 - -total_time = time.monotonic() - -build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |' -build_separator = '-' * 106 - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - -# If examples are not specified in arguments, build all -all_examples = [] -for entry in os.scandir("examples/device"): - if entry.is_dir(): - all_examples.append("device/" + entry.name) -for entry in os.scandir("examples/host"): - if entry.is_dir(): - all_examples.append("host/" + entry.name) -filter_with_input(all_examples) -all_examples.sort() - -# If boards are not specified in arguments, build all -all_boards = [] -for entry in os.scandir("hw/bsp"): - if entry.is_dir() and os.path.exists(entry.path + "/board.mk"): - all_boards.append(entry.name) -filter_with_input(all_boards) -all_boards.sort() - -def build_board(example, board): - global success_count, fail_count, skip_count, exit_status - start_time = time.monotonic() - flash_size = "-" - sram_size = "-" - - # Check if board is skipped - if build_utils.skip_example(example, board): - success = SKIPPED - skip_count += 1 - print(build_format.format(example, board, success, '-', flash_size, sram_size)) - else: - subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - if build_result.returncode == 0: - success = SUCCEEDED - success_count += 1 - (flash_size, sram_size) = build_size(example, board) - else: - exit_status = build_result.returncode - success = FAILED - fail_count += 1 - - build_duration = time.monotonic() - start_time - print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) - - if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) - -def build_size(example, board): - #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) - elf_file = 'examples/{}/_build/{}/*.elf'.format(example, board) - size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") - size_list = size_output.split('\n')[1].split('\t') - flash_size = int(size_list[0]) - sram_size = int(size_list[1]) + int(size_list[2]) - return (flash_size, sram_size) - -print(build_separator) -print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) - -for example in all_examples: - print(build_separator) - for board in all_boards: - build_board(example, board) - -total_time = time.monotonic() - total_time -print(build_separator) -print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) -print(build_separator) - -sys.exit(exit_status) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py deleted file mode 100644 index 2947a0a6b..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_esp32sx.py +++ /dev/null @@ -1,101 +0,0 @@ -import os -import glob -import sys -import subprocess -import time - -import build_utils - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -success_count = 0 -fail_count = 0 -skip_count = 0 -exit_status = 0 - -total_time = time.monotonic() - -build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |' -build_separator = '-' * 100 - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - -# Build all examples if not specified -all_examples = [] -for entry in os.scandir("examples/device"): - # Only includes example with CMakeLists.txt for esp32s, and skip board_test to speed up ci - if entry.is_dir() and os.path.exists(entry.path + "/sdkconfig.defaults") and entry.name != 'board_test': - all_examples.append(entry.name) -filter_with_input(all_examples) -all_examples.sort() - -# Build all boards if not specified -all_boards = [] -for entry in os.scandir("hw/bsp/esp32s2/boards"): - if entry.is_dir(): - all_boards.append(entry.name) -for entry in os.scandir("hw/bsp/esp32s3/boards"): - if entry.is_dir(): - all_boards.append(entry.name) -filter_with_input(all_boards) -all_boards.sort() - -def build_board(example, board): - global success_count, fail_count, skip_count, exit_status - start_time = time.monotonic() - flash_size = "-" - sram_size = "-" - - # Check if board is skipped - if build_utils.skip_example(example, board): - success = SKIPPED - skip_count += 1 - print(build_format.format(example, board, success, '-', flash_size, sram_size)) - else: - subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - build_result = subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - if build_result.returncode == 0: - success = SUCCEEDED - success_count += 1 - (flash_size, sram_size) = build_size(example, board) - else: - exit_status = build_result.returncode - success = FAILED - fail_count += 1 - - build_duration = time.monotonic() - start_time - print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) - - if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) - -def build_size(example, board): - #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) - elf_file = 'examples/device/{}/_build/{}/*.elf'.format(example, board) - size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") - size_list = size_output.split('\n')[1].split('\t') - flash_size = int(size_list[0]) - sram_size = int(size_list[1]) + int(size_list[2]) - return (flash_size, sram_size) - -print(build_separator) -print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) -print(build_separator) - -for example in all_examples: - for board in all_boards: - build_board(example, board) - -total_time = time.monotonic() - total_time -print(build_separator) -print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) -print(build_separator) - -sys.exit(exit_status) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py deleted file mode 100644 index 4094d07db..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_family.py +++ /dev/null @@ -1,113 +0,0 @@ -import os -import glob -import sys -import subprocess -import time - -import build_utils - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -success_count = 0 -fail_count = 0 -skip_count = 0 -exit_status = 0 - -total_time = time.monotonic() - -build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |' -build_separator = '-' * 106 - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - -# If examples are not specified in arguments, build all -all_examples = [] -for entry in os.scandir("examples/device"): - if entry.is_dir(): - all_examples.append("device/" + entry.name) -for entry in os.scandir("examples/host"): - if entry.is_dir(): - all_examples.append("host/" + entry.name) -filter_with_input(all_examples) -all_examples.sort() - -# If family are not specified in arguments, build all -all_families = [] -for entry in os.scandir("hw/bsp"): - if entry.is_dir() and os.path.isdir(entry.path + "/boards") and entry.name not in ("esp32s2", "esp32s3"): - all_families.append(entry.name) - -filter_with_input(all_families) -all_families.sort() - -def build_family(example, family): - all_boards = [] - for entry in os.scandir("hw/bsp/{}/boards".format(family)): - if entry.is_dir(): - all_boards.append(entry.name) - filter_with_input(all_boards) - all_boards.sort() - - for board in all_boards: - build_board(example, board) - -def build_board(example, board): - global success_count, fail_count, skip_count, exit_status - start_time = time.monotonic() - flash_size = "-" - sram_size = "-" - - # Check if board is skipped - if build_utils.skip_example(example, board): - success = SKIPPED - skip_count += 1 - print(build_format.format(example, board, success, '-', flash_size, sram_size)) - else: - #subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - if build_result.returncode == 0: - success = SUCCEEDED - success_count += 1 - (flash_size, sram_size) = build_size(example, board) - subprocess.run("make -j -C examples/{} BOARD={} copy-artifact".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - else: - exit_status = build_result.returncode - success = FAILED - fail_count += 1 - - build_duration = time.monotonic() - start_time - print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) - - if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) - -def build_size(example, board): - #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) - elf_file = 'examples/{}/_build/{}/*.elf'.format(example, board) - size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") - size_list = size_output.split('\n')[1].split('\t') - flash_size = int(size_list[0]) - sram_size = int(size_list[1]) + int(size_list[2]) - return (flash_size, sram_size) - -print(build_separator) -print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) - -for example in all_examples: - print(build_separator) - for family in all_families: - build_family(example, family) - -total_time = time.monotonic() - total_time -print(build_separator) -print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) -print(build_separator) - -sys.exit(exit_status) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py deleted file mode 100644 index 299fffa4d..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/build_utils.py +++ /dev/null @@ -1,61 +0,0 @@ -import pathlib - -def skip_example(example, board): - ex_dir = pathlib.Path('examples/') / example - bsp = pathlib.Path("hw/bsp") - - board_dir = list(bsp.glob("*/boards/" + board)) - if not board_dir: - # Skip unknown boards - return True - - board_dir = list(board_dir)[0] - - family_dir = board_dir.parent.parent - family = family_dir.name - - # family CMake - family_mk = family_dir / "family.cmake" - - # family.mk - if not family_mk.exists(): - family_mk = family_dir / "family.mk" - - mk_contents = family_mk.read_text() - - # Find the mcu - if "CFG_TUSB_MCU=OPT_MCU_" not in mk_contents: - board_mk = board_dir / "board.cmake" - if not board_mk.exists(): - board_mk = board_dir / "board.mk" - - mk_contents = board_mk.read_text() - - for token in mk_contents.split(): - if "CFG_TUSB_MCU=OPT_MCU_" in token: - # Strip " because cmake files has them. - token = token.strip("\"") - _, opt_mcu = token.split("=") - mcu = opt_mcu[len("OPT_MCU_"):] - - # Skip all OPT_MCU_NONE these are WIP port - if mcu == "NONE": - return True - - skip_file = ex_dir / "skip.txt" - only_file = ex_dir / "only.txt" - - if skip_file.exists() and only_file.exists(): - raise RuntimeError("Only have a skip or only file. Not both.") - elif skip_file.exists(): - skips = skip_file.read_text().split() - return ("mcu:" + mcu in skips or - "board:" + board in skips or - "family:" + family in skips) - elif only_file.exists(): - onlys = only_file.read_text().split() - return not ("mcu:" + mcu in onlys or - "board:" + board in onlys or - "family:" + family in onlys) - - return False diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py deleted file mode 100644 index 73c8b29fc..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_gen.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/python3 - -import os -import xml.dom.minidom as XML - -# Read base configuration -base = "" -with open("iar_template.ipcf") as f: - base = f.read() - -# Enumerate all device/host examples -dir_1 = os.listdir("../examples") -for dir_2 in dir_1: - if os.path.isdir("../examples/{}".format(dir_2)): - print(dir_2) - examples = os.listdir("../examples/{}".format(dir_2)) - for example in examples: - if os.path.isdir("../examples/{}/{}".format(dir_2, example)): - print("../examples/{}/{}".format(dir_2, example)) - conf = XML.parseString(base) - files = conf.getElementsByTagName("files")[0] - inc = conf.getElementsByTagName("includePath")[0] - # Add bsp inc - path = conf.createElement('path') - path_txt = conf.createTextNode("$TUSB_DIR$/hw") - path.appendChild(path_txt) - inc.appendChild(path) - # Add board.c/.h - grp = conf.createElement('group') - grp.setAttribute("name", "bsp") - path = conf.createElement('path') - path_txt = conf.createTextNode("$TUSB_DIR$/hw/bsp/board.c") - path.appendChild(path_txt) - grp.appendChild(path) - files.appendChild(grp) - # Add example's .c/.h - grp = conf.createElement('group') - grp.setAttribute("name", "example") - for file in os.listdir("../examples/{}/{}/src".format(dir_2, example)): - if file.endswith(".c") or file.endswith(".h"): - path = conf.createElement('path') - path.setAttribute("copyTo", "$PROJ_DIR$/{}".format(file)) - path_txt = conf.createTextNode("$TUSB_DIR$/examples/{0}/{1}/src/{2}".format(dir_2, example, file)) - path.appendChild(path_txt) - grp.appendChild(path) - files.appendChild(grp) - cfg_str = conf.toprettyxml() - cfg_str = '\n'.join([s for s in cfg_str.splitlines() if s.strip()]) - #print(cfg_str) - with open("../examples/{0}/{1}/iar_{1}.ipcf".format(dir_2, example), 'w') as f: - f.write(cfg_str) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf deleted file mode 100644 index ba54fe057..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/iar_template.ipcf +++ /dev/null @@ -1,145 +0,0 @@ - - - - - $TUSB_DIR$/src - $TUSB_DIR$/lib/SEGGER_RTT/RTT - $PROJ_DIR$ - - - - $TUSB_DIR$/src/device/usbd.c - $TUSB_DIR$/src/device/usbd_control.c - - - $TUSB_DIR$/src/common/tusb_fifo.c - - - $TUSB_DIR$/src/class/audio/audio_device.c - - - $TUSB_DIR$/src/class/bth/bth_device.c - - - $TUSB_DIR$/src/class/cdc/cdc_device.c - $TUSB_DIR$/src/class/cdc/cdc_host.c - $TUSB_DIR$/src/class/cdc/cdc_rndis_host.c - - - $TUSB_DIR$/src/class/dfu/dfu_device.c - $TUSB_DIR$/src/class/dfu/dfu_rt_device.c - - - $TUSB_DIR$/src/class/hid/hid_device.c - $TUSB_DIR$/src/class/hid/hid_host.c - - - $TUSB_DIR$/src/class/midi/midi_device.c - - - $TUSB_DIR$/src/class/msc/msc_device.c - $TUSB_DIR$/src/class/msc/msc_host.c - - - $TUSB_DIR$/src/class/net/ecm_rndis_device.c - $TUSB_DIR$/src/class/net/ncm_device.c - - - $TUSB_DIR$/src/class/usbtmc/usbtmc_device.c - - - $TUSB_DIR$/src/class/vendor/vendor_device.c - $TUSB_DIR$/src/class/vendor/vendor_host.c - - - $TUSB_DIR$/src/tusb.c - - - $TUSB_DIR$/src/host/hub.c - $TUSB_DIR$/src/host/usbh.c - $TUSB_DIR$/src/host/usbh_control.c - - - $TUSB_DIR$/src/portable/synopsys/dwc2/dcd_dwc2.c - - - $TUSB_DIR$/src/portable/dialog/da146xx/dcd_da146xx.c - - - $TUSB_DIR$/src/portable/ehci/ehci.c - - - $TUSB_DIR$/src/portable/espressif/esp32sx/dcd_esp32sx.c - - - $TUSB_DIR$/src/portable/mentor/musb/dcd_musb.c - - - $TUSB_DIR$/src/portable/microchip/samd/dcd_samd.c - - - $TUSB_DIR$/src/portable/microchip/samg/dcd_samg.c - - - $TUSB_DIR$/src/portable/microchip/samx7x/dcd_samx7x.c - - - $TUSB_DIR$/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c - - - $TUSB_DIR$/src/portable/nordic/nrf5x/dcd_nrf5x.c - - - $TUSB_DIR$/src/portable/nuvoton/nuc120/dcd_nuc120.c - - - $TUSB_DIR$/src/portable/nuvoton/nuc121/dcd_nuc121.c - - - $TUSB_DIR$/src/portable/nuvoton/nuc505/dcd_nuc505.c - - - $TUSB_DIR$/src/portable/nxp/khci/dcd_khci.c - - - $TUSB_DIR$/src/portable/nxp/lpc17_40/dcd_lpc17_40.c - $TUSB_DIR$/src/portable/nxp/lpc17_40/hcd_lpc17_40.c - - - $TUSB_DIR$/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c - - - $TUSB_DIR$/src/portable/nxp/transdimension/dcd_transdimension.c - $TUSB_DIR$/src/portable/nxp/transdimension/hcd_transdimension.c - - - $TUSB_DIR$/src/portable/ohci/ohci.c - - - $TUSB_DIR$/src/portable/raspberrypi/rp2040/dcd_rp2040.c - $TUSB_DIR$/src/portable/raspberrypi/rp2040/hcd_rp2040.c - $TUSB_DIR$/src/portable/raspberrypi/rp2040/rp2040_usb.c - - - $TUSB_DIR$/src/portable/renesas/usba/dcd_usba.c - - - $TUSB_DIR$/src/portable/sony/cxd56/dcd_cxd56.c - - - $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - - - $TUSB_DIR$/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c - - - $TUSB_DIR$/src/portable/valentyusb/eptri/dcd_eptri.c - - - $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT.c - $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c - $TUSB_DIR$/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c - - - - diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk deleted file mode 100644 index 84523a557..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/top.mk +++ /dev/null @@ -1,30 +0,0 @@ -ifneq ($(lastword a b),b) -$(error This Makefile require make 3.81 or newer) -endif - -# Detect whether shell style is windows or not -# https://stackoverflow.com/questions/714100/os-detecting-makefile/52062069#52062069 -ifeq '$(findstring ;,$(PATH))' ';' -CMDEXE := 1 -endif - -# Set TOP to be the path to get from the current directory (where make was -# invoked) to the top of the tree. $(lastword $(MAKEFILE_LIST)) returns -# the name of this makefile relative to where make was invoked. - -THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) -TOP := $(patsubst %/tools/top.mk,%,$(THIS_MAKEFILE)) - -ifeq ($(CMDEXE),1) -TOP := $(subst \,/,$(shell for %%i in ( $(TOP) ) do echo %%~fi)) -else -TOP := $(shell realpath $(TOP)) -endif -#$(info Top directory is $(TOP)) - -ifeq ($(CMDEXE),1) -CURRENT_PATH := $(subst $(TOP)/,,$(subst \,/,$(shell echo %CD%))) -else -CURRENT_PATH := $(shell realpath --relative-to=$(TOP) `pwd`) -endif -#$(info Path from top is $(CURRENT_PATH)) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf b/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf deleted file mode 100644 index e7f7a9b22..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/tools/usb_drivers/tinyusb_win_usbser.inf +++ /dev/null @@ -1,108 +0,0 @@ -;************************************************************ -; Windows USB CDC ACM Setup File -; Copyright (c) 2000 Microsoft Corporation - - -[Version] -Signature="$Windows NT$" -Class=Ports -ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} -Provider=%MFGNAME% -LayoutFile=layout.inf -CatalogFile=%MFGFILENAME%.cat -DriverVer=11/15/2007,5.1.2600.0 -DriverPackageDisplayName=%DESCRIPTION% - -[Manufacturer] -%MFGNAME%=DeviceList, NTamd64 - -[DestinationDirs] -DefaultDestDir=12 - - -;------------------------------------------------------------------------------ -; Windows 2000/XP/Vista-32bit Sections -;------------------------------------------------------------------------------ - -[DriverInstall.nt] -include=mdmcpq.inf -CopyFiles=DriverCopyFiles.nt -AddReg=DriverInstall.nt.AddReg - -[DriverCopyFiles.nt] -usbser.sys,,,0x20 - -[DriverInstall.nt.AddReg] -HKR,,DevLoader,,*ntkern -HKR,,NTMPDriver,,%DRIVERFILENAME%.sys -HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" - -[DriverInstall.nt.Services] -AddService=usbser, 0x00000002, DriverService.nt - -[DriverService.nt] -DisplayName=%SERVICE% -ServiceType=1 -StartType=3 -ErrorControl=1 -ServiceBinary=%12%\%DRIVERFILENAME%.sys - -;------------------------------------------------------------------------------ -; Vista-64bit Sections -;------------------------------------------------------------------------------ - -[DriverInstall.NTamd64] -include=mdmcpq.inf -CopyFiles=DriverCopyFiles.NTamd64 -AddReg=DriverInstall.NTamd64.AddReg - -[DriverCopyFiles.NTamd64] -%DRIVERFILENAME%.sys,,,0x20 - -[DriverInstall.NTamd64.AddReg] -HKR,,DevLoader,,*ntkern -HKR,,NTMPDriver,,%DRIVERFILENAME%.sys -HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" - -[DriverInstall.NTamd64.Services] -AddService=usbser, 0x00000002, DriverService.NTamd64 - -[DriverService.NTamd64] -DisplayName=%SERVICE% -ServiceType=1 -StartType=3 -ErrorControl=1 -ServiceBinary=%12%\%DRIVERFILENAME%.sys - - -;------------------------------------------------------------------------------ -; Vendor and Product ID Definitions -;------------------------------------------------------------------------------ -; When developing your USB device, the VID and PID used in the PC side -; application program and the firmware on the microcontroller must match. -; Modify the below line to use your VID and PID. Use the format as shown below. -; Note: One INF file can be used for multiple devices with different VID and PIDs. -; For each supported device, append ",USB\VID_xxxx&PID_yyyy" to the end of the line. -;------------------------------------------------------------------------------ -[SourceDisksFiles] -[SourceDisksNames] -[DeviceList] - -%DESCRIPTION%=DriverInstall, USB\VID_CAFE&PID_4001&MI_00, USB\VID_CAFE&PID_4003&MI_00, USB\VID_CAFE&PID_4005&MI_00, USB\VID_CAFE&PID_4007&MI_00, USB\VID_CAFE&PID_4009&MI_00, USB\VID_CAFE&PID_400b&MI_00, USB\VID_CAFE&PID_400d&MI_00, USB\VID_CAFE&PID_400f&MI_00, USB\VID_CAFE&PID_4011&MI_00, USB\VID_CAFE&PID_4013&MI_00, USB\VID_CAFE&PID_4015&MI_00, USB\VID_CAFE&PID_4017&MI_00, USB\VID_CAFE&PID_4019&MI_00, USB\VID_CAFE&PID_401b&MI_00, USB\VID_CAFE&PID_401d&MI_00, USB\VID_CAFE&PID_401f&MI_00, USB\VID_CAFE&PID_4021&MI_00, USB\VID_CAFE&PID_4023&MI_00, USB\VID_CAFE&PID_4025&MI_00, USB\VID_CAFE&PID_4027&MI_00, USB\VID_CAFE&PID_4029&MI_00, USB\VID_CAFE&PID_402b&MI_00, USB\VID_CAFE&PID_402d&MI_00, USB\VID_CAFE&PID_402f&MI_00, USB\VID_CAFE&PID_4031&MI_00, USB\VID_CAFE&PID_4033&MI_00, USB\VID_CAFE&PID_4035&MI_00, USB\VID_CAFE&PID_4037&MI_00, USB\VID_CAFE&PID_4039&MI_00, USB\VID_CAFE&PID_403b&MI_00, USB\VID_CAFE&PID_403d&MI_00, USB\VID_CAFE&PID_403f&MI_00 - - -[DeviceList.NTamd64] -%DESCRIPTION%=DriverInstall, USB\VID_CAFE&PID_4001&MI_00, USB\VID_CAFE&PID_4003&MI_00, USB\VID_CAFE&PID_4005&MI_00, USB\VID_CAFE&PID_4007&MI_00, USB\VID_CAFE&PID_4009&MI_00, USB\VID_CAFE&PID_400b&MI_00, USB\VID_CAFE&PID_400d&MI_00, USB\VID_CAFE&PID_400f&MI_00, USB\VID_CAFE&PID_4011&MI_00, USB\VID_CAFE&PID_4013&MI_00, USB\VID_CAFE&PID_4015&MI_00, USB\VID_CAFE&PID_4017&MI_00, USB\VID_CAFE&PID_4019&MI_00, USB\VID_CAFE&PID_401b&MI_00, USB\VID_CAFE&PID_401d&MI_00, USB\VID_CAFE&PID_401f&MI_00, USB\VID_CAFE&PID_4021&MI_00, USB\VID_CAFE&PID_4023&MI_00, USB\VID_CAFE&PID_4025&MI_00, USB\VID_CAFE&PID_4027&MI_00, USB\VID_CAFE&PID_4029&MI_00, USB\VID_CAFE&PID_402b&MI_00, USB\VID_CAFE&PID_402d&MI_00, USB\VID_CAFE&PID_402f&MI_00, USB\VID_CAFE&PID_4031&MI_00, USB\VID_CAFE&PID_4033&MI_00, USB\VID_CAFE&PID_4035&MI_00, USB\VID_CAFE&PID_4037&MI_00, USB\VID_CAFE&PID_4039&MI_00, USB\VID_CAFE&PID_403b&MI_00, USB\VID_CAFE&PID_403d&MI_00, USB\VID_CAFE&PID_403f&MI_00 - -;------------------------------------------------------------------------------ -; String Definitions -;------------------------------------------------------------------------------ -;Modify these strings to customize your device -;------------------------------------------------------------------------------ -[Strings] -MFGFILENAME="tinyusb_usbser" -DRIVERFILENAME ="usbser" -MFGNAME="tinyusb.org" -INSTDISK="tinyusb CDC Driver" -DESCRIPTION="tinyusb Serial" -SERVICE="USB RS-232 Emulation Driver" \ No newline at end of file diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_cdc_acm.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_cdc_acm.c similarity index 65% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_cdc_acm.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_cdc_acm.c index 725426ead..a69ba6e2a 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_cdc_acm.c +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_cdc_acm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,22 +10,21 @@ #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/ringbuf.h" #include "tusb.h" #include "tusb_cdc_acm.h" #include "cdc.h" #include "sdkconfig.h" -#define RX_UNREADBUF_SZ_DEFAULT 64 // buffer storing all unread RX data +#ifndef MIN #define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#endif +// CDC-ACM spinlock +static portMUX_TYPE cdc_acm_lock = portMUX_INITIALIZER_UNLOCKED; +#define CDC_ACM_ENTER_CRITICAL() portENTER_CRITICAL(&cdc_acm_lock) +#define CDC_ACM_EXIT_CRITICAL() portEXIT_CRITICAL(&cdc_acm_lock) typedef struct { - bool initialized; - size_t rx_unread_buf_sz; - RingbufHandle_t rx_unread_buf; - SemaphoreHandle_t ringbuf_read_mux; - uint8_t *rx_tfbuf; tusb_cdcacm_callback_t callback_rx; tusb_cdcacm_callback_t callback_rx_wanted_char; tusb_cdcacm_callback_t callback_line_state_changed; @@ -66,7 +65,9 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) } } if (acm) { + CDC_ACM_ENTER_CRITICAL(); tusb_cdcacm_callback_t cb = acm->callback_line_state_changed; + CDC_ACM_EXIT_CRITICAL(); if (cb) { cdcacm_event_t event = { .type = CDC_EVENT_LINE_STATE_CHANGED, @@ -85,29 +86,9 @@ void tud_cdc_rx_cb(uint8_t itf) { esp_tusb_cdcacm_t *acm = get_acm(itf); if (acm) { - if (!acm->rx_unread_buf) { - ESP_LOGE(TAG, "There is no RX buffer created"); - abort(); - } - } else { - tud_cdc_n_read_flush(itf); // we have no place to store data, so just drop it - return; - } - while (tud_cdc_n_available(itf)) { - int read_res = tud_cdc_n_read( itf, - acm->rx_tfbuf, - CONFIG_TINYUSB_CDC_RX_BUFSIZE ); - int res = xRingbufferSend(acm->rx_unread_buf, - acm->rx_tfbuf, - read_res, 0); - if (res != pdTRUE) { - ESP_LOGW(TAG, "The unread buffer is too small, the data has been lost"); - } else { - ESP_LOGV(TAG, "Sent %d bytes to the buffer", read_res); - } - } - if (acm) { + CDC_ACM_ENTER_CRITICAL(); tusb_cdcacm_callback_t cb = acm->callback_rx; + CDC_ACM_EXIT_CRITICAL(); if (cb) { cdcacm_event_t event = { .type = CDC_EVENT_RX @@ -122,7 +103,9 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) { esp_tusb_cdcacm_t *acm = get_acm(itf); if (acm) { + CDC_ACM_ENTER_CRITICAL(); tusb_cdcacm_callback_t cb = acm->callback_line_coding_changed; + CDC_ACM_EXIT_CRITICAL(); if (cb) { cdcacm_event_t event = { .type = CDC_EVENT_LINE_CODING_CHANGED, @@ -132,8 +115,6 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) }; cb(itf, &event); } - } else { - return; } } @@ -142,7 +123,9 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { esp_tusb_cdcacm_t *acm = get_acm(itf); if (acm) { + CDC_ACM_ENTER_CRITICAL(); tusb_cdcacm_callback_t cb = acm->callback_rx_wanted_char; + CDC_ACM_EXIT_CRITICAL(); if (cb) { cdcacm_event_t event = { .type = CDC_EVENT_RX_WANTED_CHAR, @@ -152,8 +135,6 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) }; cb(itf, &event); } - } else { - return; } } @@ -165,16 +146,24 @@ esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf, if (acm) { switch (event_type) { case CDC_EVENT_RX: + CDC_ACM_ENTER_CRITICAL(); acm->callback_rx = callback; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_RX_WANTED_CHAR: + CDC_ACM_ENTER_CRITICAL(); acm->callback_rx_wanted_char = callback; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_LINE_STATE_CHANGED: + CDC_ACM_ENTER_CRITICAL(); acm->callback_line_state_changed = callback; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_LINE_CODING_CHANGED: + CDC_ACM_ENTER_CRITICAL(); acm->callback_line_coding_changed = callback; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; default: ESP_LOGE(TAG, "Wrong event type"); @@ -196,16 +185,24 @@ esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, } switch (event_type) { case CDC_EVENT_RX: + CDC_ACM_ENTER_CRITICAL(); acm->callback_rx = NULL; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_RX_WANTED_CHAR: + CDC_ACM_ENTER_CRITICAL(); acm->callback_rx_wanted_char = NULL; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_LINE_STATE_CHANGED: + CDC_ACM_ENTER_CRITICAL(); acm->callback_line_state_changed = NULL; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; case CDC_EVENT_LINE_CODING_CHANGED: + CDC_ACM_ENTER_CRITICAL(); acm->callback_line_coding_changed = NULL; + CDC_ACM_EXIT_CRITICAL(); return ESP_OK; default: ESP_LOGE(TAG, "Wrong event type"); @@ -217,56 +214,16 @@ esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, /* CDC-ACM ********************************************************************* */ -static esp_err_t read_from_rx_unread_to_buffer(esp_tusb_cdcacm_t *acm, uint8_t *out_buf, size_t req_bytes, size_t *read_bytes) -{ - uint8_t *buf = xRingbufferReceiveUpTo(acm->rx_unread_buf, read_bytes, 0, req_bytes); - if (buf) { - memcpy(out_buf, buf, *read_bytes); - vRingbufferReturnItem(acm->rx_unread_buf, (void *)(buf)); - return ESP_OK; - } else { - return ESP_ERR_NO_MEM; - } -} - -static esp_err_t ringbuf_mux_take(esp_tusb_cdcacm_t *acm) -{ - if (xSemaphoreTake(acm->ringbuf_read_mux, 0) != pdTRUE) { - ESP_LOGW(TAG, "Read error: ACM is busy"); - return ESP_ERR_INVALID_STATE; - } - return ESP_OK; -} - -static esp_err_t ringbuf_mux_give(esp_tusb_cdcacm_t *acm) -{ - BaseType_t ret = xSemaphoreGive(acm->ringbuf_read_mux); - assert(ret == pdTRUE); - return ESP_OK; -} - esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size) { esp_tusb_cdcacm_t *acm = get_acm(itf); ESP_RETURN_ON_FALSE(acm, ESP_ERR_INVALID_STATE, TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization"); - size_t read_sz; - - /* Take a mutex to proceed two uninterrupted read operations */ - ESP_RETURN_ON_ERROR(ringbuf_mux_take(acm), TAG, "ringbuf_mux_take failed"); - - esp_err_t res = read_from_rx_unread_to_buffer(acm, out_buf, out_buf_sz, &read_sz); - if (res != ESP_OK) { - ESP_RETURN_ON_ERROR(ringbuf_mux_give(acm), TAG, "ringbuf_mux_give failed"); - return res; - } - *rx_data_size = read_sz; - /* Buffer's data can be wrapped, at that situations we should make another retrievement */ - if (read_from_rx_unread_to_buffer(acm, out_buf + read_sz, out_buf_sz - read_sz, &read_sz) == ESP_OK) { - *rx_data_size += read_sz; + if (tud_cdc_n_available(itf) == 0) { + *rx_data_size = 0; + } else { + *rx_data_size = tud_cdc_n_read(itf, out_buf, out_buf_sz); } - - ESP_RETURN_ON_ERROR(ringbuf_mux_give(acm), TAG, "ringbuf_mux_give failed"); return ESP_OK; } @@ -299,27 +256,21 @@ esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ } if (!timeout_ticks) { // if no timeout - nonblocking mode - int res = tud_cdc_n_write_flush(itf); - if (!res) { - ESP_LOGW(TAG, "flush failed (res: %d)", res); - return ESP_FAIL; - } else { - if (tud_cdc_n_write_occupied(itf)) { - ESP_LOGW(TAG, "remained data to flush!"); - return ESP_FAIL; - } + // It might take some time until TinyUSB flushes the endpoint + // Since this call is non-blocking, we don't wait for flush finished, + // We only inform the user by returning ESP_ERR_NOT_FINISHED + tud_cdc_n_write_flush(itf); + if (tud_cdc_n_write_occupied(itf)) { + return ESP_ERR_NOT_FINISHED; } - return ESP_ERR_TIMEOUT; } else { // trying during the timeout uint32_t ticks_start = xTaskGetTickCount(); uint32_t ticks_now = ticks_start; while (1) { // loop until success or until the time runs out ticks_now = xTaskGetTickCount(); - if (!tud_cdc_n_write_occupied(itf)) { // if nothing to write - nothing to flush - break; - } - if (tud_cdc_n_write_flush(itf)) { // Success - break; + tud_cdc_n_write_flush(itf); + if (tud_cdc_n_write_occupied(itf) == 0) { + break; // All data flushed } if ( (ticks_now - ticks_start) > timeout_ticks ) { // Time is up ESP_LOGW(TAG, "Flush failed"); @@ -327,30 +278,26 @@ esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ } vTaskDelay(1); } - return ESP_OK; } + return ESP_OK; } static esp_err_t alloc_obj(tinyusb_cdcacm_itf_t itf) { esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf); + if (cdc_inst == NULL) { + return ESP_FAIL; + } cdc_inst->subclass_obj = calloc(1, sizeof(esp_tusb_cdcacm_t)); - if (!cdc_inst->subclass_obj) { + if (cdc_inst->subclass_obj == NULL) { return ESP_FAIL; - } else { - return ESP_OK; } -} - -static void free_obj(tinyusb_cdcacm_itf_t itf) -{ - esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf); - free(cdc_inst->subclass_obj); - cdc_inst->subclass_obj = NULL; + return ESP_OK; } esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg) { + esp_err_t ret = ESP_OK; int itf = (int)cfg->cdc_port; /* Creating a CDC object */ const tinyusb_config_cdc_t cdc_cfg = { @@ -358,10 +305,10 @@ esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg) .cdc_class = TUSB_CLASS_CDC, .cdc_subclass.comm_subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL }; + ESP_RETURN_ON_ERROR(tinyusb_cdc_init(itf, &cdc_cfg), TAG, "tinyusb_cdc_init failed"); - ESP_RETURN_ON_ERROR(alloc_obj(itf), TAG, "alloc_obj failed"); + ESP_GOTO_ON_ERROR(alloc_obj(itf), fail, TAG, "alloc_obj failed"); - esp_tusb_cdcacm_t *acm = get_acm(itf); /* Callbacks setting up*/ if (cfg->callback_rx) { tinyusb_cdcacm_register_callback(itf, CDC_EVENT_RX, cfg->callback_rx); @@ -376,31 +323,15 @@ esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg) tinyusb_cdcacm_register_callback( itf, CDC_EVENT_LINE_CODING_CHANGED, cfg->callback_line_coding_changed); } - /* Buffers */ - - acm->ringbuf_read_mux = xSemaphoreCreateMutex(); - if (acm->ringbuf_read_mux == NULL) { - ESP_LOGE(TAG, "Creation of a ringbuf mutex failed"); - free_obj(itf); - return ESP_ERR_NO_MEM; - } + return ESP_OK; +fail: + tinyusb_cdc_deinit(itf); + return ret; +} - acm->rx_tfbuf = malloc(CONFIG_TINYUSB_CDC_RX_BUFSIZE); - if (!acm->rx_tfbuf) { - ESP_LOGE(TAG, "Creation buffer error"); - free_obj(itf); - return ESP_ERR_NO_MEM; - } - acm->rx_unread_buf_sz = cfg->rx_unread_buf_sz == 0 ? RX_UNREADBUF_SZ_DEFAULT : cfg->rx_unread_buf_sz; - acm->rx_unread_buf = xRingbufferCreate(acm->rx_unread_buf_sz, RINGBUF_TYPE_BYTEBUF); - if (acm->rx_unread_buf == NULL) { - ESP_LOGE(TAG, "Creation buffer error"); - free_obj(itf); - return ESP_ERR_NO_MEM; - } else { - ESP_LOGD(TAG, "Comm Initialized buff:%d bytes", cfg->rx_unread_buf_sz); - return ESP_OK; - } +esp_err_t tusb_cdc_acm_deinit(int itf) +{ + return tinyusb_cdc_deinit(itf); } bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf) diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_console.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_console.c similarity index 97% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_console.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_console.c index 97c3e256d..692f64f7b 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/tusb_console.c +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_console.c @@ -103,7 +103,7 @@ esp_err_t esp_tusb_init_console(int cdc_intf) { /* Registering TUSB at VFS */ ESP_RETURN_ON_ERROR(esp_vfs_tusb_cdc_register(cdc_intf, NULL), TAG, ""); - ESP_RETURN_ON_ERROR(redirect_std_streams_to(&con.in, &con.out, &con.err, "/dev/tusb_cdc"), TAG, "Failed to redirect STD streams"); + ESP_RETURN_ON_ERROR(redirect_std_streams_to(&con.in, &con.out, &con.err, VFS_TUSB_PATH_DEFAULT), TAG, "Failed to redirect STD streams"); return ESP_OK; } diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_msc_storage.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_msc_storage.c new file mode 100644 index 000000000..356ad2c28 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_msc_storage.c @@ -0,0 +1,640 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_log.h" +#include "esp_err.h" +#include "esp_check.h" +#include "esp_vfs_fat.h" +#include "diskio_impl.h" +#include "diskio_wl.h" +#include "wear_levelling.h" +#include "esp_partition.h" +#include "vfs_fat_internal.h" +#include "tinyusb.h" +#include "class/msc/msc_device.h" +#include "tusb_msc_storage.h" +#include "esp_vfs_fat.h" +#if SOC_SDMMC_HOST_SUPPORTED +#include "diskio_sdmmc.h" +#endif + +static const char *TAG = "tinyusb_msc_storage"; + +typedef struct { + bool is_fat_mounted; + const char *base_path; + union { + wl_handle_t wl_handle; +#if SOC_SDMMC_HOST_SUPPORTED + sdmmc_card_t *card; +#endif + }; + esp_err_t (*mount)(BYTE pdrv); + esp_err_t (*unmount)(void); + uint32_t (*sector_count)(void); + uint32_t (*sector_size)(void); + esp_err_t (*read)(size_t sector_size, uint32_t lba, uint32_t offset, size_t size, void *dest); + esp_err_t (*write)(size_t sector_size, size_t addr, uint32_t lba, uint32_t offset, size_t size, const void *src); + tusb_msc_callback_t callback_mount_changed; + tusb_msc_callback_t callback_premount_changed; + int max_files; +} tinyusb_msc_storage_handle_s; /*!< MSC object */ + +/* handle of tinyusb driver connected to application */ +static tinyusb_msc_storage_handle_s *s_storage_handle; + +static esp_err_t _mount_spiflash(BYTE pdrv) +{ + return ff_diskio_register_wl_partition(pdrv, s_storage_handle->wl_handle); +} + +static esp_err_t _unmount_spiflash(void) +{ + BYTE pdrv; + pdrv = ff_diskio_get_pdrv_wl(s_storage_handle->wl_handle); + if (pdrv == 0xff) { + ESP_LOGE(TAG, "Invalid state"); + return ESP_ERR_INVALID_STATE; + } + ff_diskio_clear_pdrv_wl(s_storage_handle->wl_handle); + + char drv[3] = {(char)('0' + pdrv), ':', 0}; + f_mount(0, drv, 0); + ff_diskio_unregister(pdrv); + + return ESP_OK; +} + +static uint32_t _get_sector_count_spiflash(void) +{ + uint32_t result = 0; + assert(s_storage_handle->wl_handle != WL_INVALID_HANDLE); + size_t size = wl_sector_size(s_storage_handle->wl_handle); + if (size == 0) { + ESP_LOGW(TAG, "WL Sector size is zero !!!"); + result = 0; + } else { + result = (uint32_t)(wl_size(s_storage_handle->wl_handle) / size); + } + return result; +} + +static uint32_t _get_sector_size_spiflash(void) +{ + assert(s_storage_handle->wl_handle != WL_INVALID_HANDLE); + return (uint32_t)wl_sector_size(s_storage_handle->wl_handle); +} + +static esp_err_t _read_sector_spiflash(size_t sector_size, + uint32_t lba, + uint32_t offset, + size_t size, + void *dest) +{ + size_t temp = 0; + size_t addr = 0; // Address of the data to be read, relative to the beginning of the partition. + ESP_RETURN_ON_FALSE(!__builtin_umul_overflow(lba, sector_size, &temp), ESP_ERR_INVALID_SIZE, TAG, "overflow lba %lu sector_size %u", lba, sector_size); + ESP_RETURN_ON_FALSE(!__builtin_uadd_overflow(temp, offset, &addr), ESP_ERR_INVALID_SIZE, TAG, "overflow addr %u offset %lu", temp, offset); + return wl_read(s_storage_handle->wl_handle, addr, dest, size); +} + +static esp_err_t _write_sector_spiflash(size_t sector_size, + size_t addr, + uint32_t lba, + uint32_t offset, + size_t size, + const void *src) +{ + ESP_RETURN_ON_ERROR(wl_erase_range(s_storage_handle->wl_handle, addr, size), + TAG, "Failed to erase"); + return wl_write(s_storage_handle->wl_handle, addr, src, size); +} + +#if SOC_SDMMC_HOST_SUPPORTED +static esp_err_t _mount_sdmmc(BYTE pdrv) +{ + ff_diskio_register_sdmmc(pdrv, s_storage_handle->card); + ff_sdmmc_set_disk_status_check(pdrv, false); + return ESP_OK; +} + +static esp_err_t _unmount_sdmmc(void) +{ + BYTE pdrv; + pdrv = ff_diskio_get_pdrv_card(s_storage_handle->card); + if (pdrv == 0xff) { + ESP_LOGE(TAG, "Invalid state"); + return ESP_ERR_INVALID_STATE; + } + + char drv[3] = {(char)('0' + pdrv), ':', 0}; + f_mount(0, drv, 0); + ff_diskio_unregister(pdrv); + + return ESP_OK; +} + +static uint32_t _get_sector_count_sdmmc(void) +{ + assert(s_storage_handle->card); + return (uint32_t)s_storage_handle->card->csd.capacity; +} + +static uint32_t _get_sector_size_sdmmc(void) +{ + assert(s_storage_handle->card); + return (uint32_t)s_storage_handle->card->csd.sector_size; +} + +static esp_err_t _read_sector_sdmmc(size_t sector_size, + uint32_t lba, + uint32_t offset, + size_t size, + void *dest) +{ + return sdmmc_read_sectors(s_storage_handle->card, dest, lba, size / sector_size); +} + +static esp_err_t _write_sector_sdmmc(size_t sector_size, + size_t addr, + uint32_t lba, + uint32_t offset, + size_t size, + const void *src) +{ + return sdmmc_write_sectors(s_storage_handle->card, src, lba, size / sector_size); +} +#endif + +static esp_err_t msc_storage_read_sector(uint32_t lba, + uint32_t offset, + size_t size, + void *dest) +{ + assert(s_storage_handle); + size_t sector_size = tinyusb_msc_storage_get_sector_size(); + return (s_storage_handle->read)(sector_size, lba, offset, size, dest); +} + +static esp_err_t msc_storage_write_sector(uint32_t lba, + uint32_t offset, + size_t size, + const void *src) +{ + assert(s_storage_handle); + if (s_storage_handle->is_fat_mounted) { + ESP_LOGE(TAG, "can't write, FAT mounted"); + return ESP_ERR_INVALID_STATE; + } + size_t sector_size = tinyusb_msc_storage_get_sector_size(); + size_t temp = 0; + size_t addr = 0; // Address of the data to be read, relative to the beginning of the partition. + ESP_RETURN_ON_FALSE(!__builtin_umul_overflow(lba, sector_size, &temp), ESP_ERR_INVALID_SIZE, TAG, "overflow lba %lu sector_size %u", lba, sector_size); + ESP_RETURN_ON_FALSE(!__builtin_uadd_overflow(temp, offset, &addr), ESP_ERR_INVALID_SIZE, TAG, "overflow addr %u offset %lu", temp, offset); + + if (addr % sector_size != 0 || size % sector_size != 0) { + ESP_LOGE(TAG, "Invalid Argument lba(%lu) offset(%lu) size(%u) sector_size(%u)", lba, offset, size, sector_size); + return ESP_ERR_INVALID_ARG; + } + return (s_storage_handle->write)(sector_size, addr, lba, offset, size, src); +} + +static esp_err_t _mount(char *drv, FATFS *fs) +{ + void *workbuf = NULL; + const size_t workbuf_size = 4096; + esp_err_t ret; + // Try to mount partition + FRESULT fresult = f_mount(fs, drv, 1); + if (fresult != FR_OK) { + ESP_LOGW(TAG, "f_mount failed (%d)", fresult); + if (!((fresult == FR_NO_FILESYSTEM || fresult == FR_INT_ERR))) { + ret = ESP_FAIL; + goto fail; + } + workbuf = ff_memalloc(workbuf_size); + if (workbuf == NULL) { + ret = ESP_ERR_NO_MEM; + goto fail; + } + size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size( + CONFIG_WL_SECTOR_SIZE, + 4096); + ESP_LOGW(TAG, "formatting card, allocation unit size=%d", alloc_unit_size); + const MKFS_PARM opt = {(BYTE)FM_FAT, 0, 0, 0, alloc_unit_size}; + fresult = f_mkfs("", &opt, workbuf, workbuf_size); // Use default volume + if (fresult != FR_OK) { + ret = ESP_FAIL; + ESP_LOGE(TAG, "f_mkfs failed (%d)", fresult); + goto fail; + } + free(workbuf); + workbuf = NULL; + fresult = f_mount(fs, drv, 0); + if (fresult != FR_OK) { + ret = ESP_FAIL; + ESP_LOGE(TAG, "f_mount failed after formatting (%d)", fresult); + goto fail; + } + } + return ESP_OK; +fail: + if (workbuf) { + free(workbuf); + } + return ret; +} + +esp_err_t tinyusb_msc_storage_mount(const char *base_path) +{ + esp_err_t ret = ESP_OK; + assert(s_storage_handle); + + if (s_storage_handle->is_fat_mounted) { + return ESP_OK; + } + + tusb_msc_callback_t cb = s_storage_handle->callback_premount_changed; + if (cb) { + tinyusb_msc_event_t event = { + .type = TINYUSB_MSC_EVENT_PREMOUNT_CHANGED, + .mount_changed_data = { + .is_mounted = s_storage_handle->is_fat_mounted + } + }; + cb(&event); + } + + if (!base_path) { + base_path = CONFIG_TINYUSB_MSC_MOUNT_PATH; + } + + // connect driver to FATFS + BYTE pdrv = 0xFF; + ESP_RETURN_ON_ERROR(ff_diskio_get_drive(&pdrv), TAG, + "The maximum count of volumes is already mounted"); + char drv[3] = {(char)('0' + pdrv), ':', 0}; + + ESP_GOTO_ON_ERROR((s_storage_handle->mount)(pdrv), fail, TAG, "Failed pdrv=%d", pdrv); + + FATFS *fs = NULL; + ret = esp_vfs_fat_register(base_path, drv, s_storage_handle->max_files, &fs); + if (ret == ESP_ERR_INVALID_STATE) { + ESP_LOGD(TAG, "it's okay, already registered with VFS"); + } else if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_vfs_fat_register failed (0x%x)", ret); + goto fail; + } + + ESP_GOTO_ON_ERROR(_mount(drv, fs), fail, TAG, "Failed _mount"); + + s_storage_handle->is_fat_mounted = true; + s_storage_handle->base_path = base_path; + + cb = s_storage_handle->callback_mount_changed; + if (cb) { + tinyusb_msc_event_t event = { + .type = TINYUSB_MSC_EVENT_MOUNT_CHANGED, + .mount_changed_data = { + .is_mounted = s_storage_handle->is_fat_mounted + } + }; + cb(&event); + } + + return ret; + +fail: + if (fs) { + esp_vfs_fat_unregister_path(base_path); + } + ff_diskio_unregister(pdrv); + s_storage_handle->is_fat_mounted = false; + ESP_LOGW(TAG, "Failed to mount storage (0x%x)", ret); + return ret; +} + +esp_err_t tinyusb_msc_storage_unmount(void) +{ + if (!s_storage_handle) { + return ESP_FAIL; + } + + if (!s_storage_handle->is_fat_mounted) { + return ESP_OK; + } + + tusb_msc_callback_t cb = s_storage_handle->callback_premount_changed; + if (cb) { + tinyusb_msc_event_t event = { + .type = TINYUSB_MSC_EVENT_PREMOUNT_CHANGED, + .mount_changed_data = { + .is_mounted = s_storage_handle->is_fat_mounted + } + }; + cb(&event); + } + + esp_err_t err = (s_storage_handle->unmount)(); + if (err) { + return err; + } + err = esp_vfs_fat_unregister_path(s_storage_handle->base_path); + s_storage_handle->base_path = NULL; + s_storage_handle->is_fat_mounted = false; + + cb = s_storage_handle->callback_mount_changed; + if (cb) { + tinyusb_msc_event_t event = { + .type = TINYUSB_MSC_EVENT_MOUNT_CHANGED, + .mount_changed_data = { + .is_mounted = s_storage_handle->is_fat_mounted + } + }; + cb(&event); + } + + return err; +} + +uint32_t tinyusb_msc_storage_get_sector_count(void) +{ + assert(s_storage_handle); + return (s_storage_handle->sector_count)(); +} + +uint32_t tinyusb_msc_storage_get_sector_size(void) +{ + assert(s_storage_handle); + return (s_storage_handle->sector_size)(); +} + +esp_err_t tinyusb_msc_storage_init_spiflash(const tinyusb_msc_spiflash_config_t *config) +{ + assert(!s_storage_handle); + s_storage_handle = (tinyusb_msc_storage_handle_s *)malloc(sizeof(tinyusb_msc_storage_handle_s)); + ESP_RETURN_ON_FALSE(s_storage_handle, ESP_ERR_NO_MEM, TAG, "could not allocate new handle for storage"); + s_storage_handle->mount = &_mount_spiflash; + s_storage_handle->unmount = &_unmount_spiflash; + s_storage_handle->sector_count = &_get_sector_count_spiflash; + s_storage_handle->sector_size = &_get_sector_size_spiflash; + s_storage_handle->read = &_read_sector_spiflash; + s_storage_handle->write = &_write_sector_spiflash; + s_storage_handle->is_fat_mounted = false; + s_storage_handle->base_path = NULL; + s_storage_handle->wl_handle = config->wl_handle; + // In case the user does not set mount_config.max_files + // and for backward compatibility with versions <1.4.2 + // max_files is set to 2 + const int max_files = config->mount_config.max_files; + s_storage_handle->max_files = max_files > 0 ? max_files : 2; + + /* Callbacks setting up*/ + if (config->callback_mount_changed) { + tinyusb_msc_register_callback(TINYUSB_MSC_EVENT_MOUNT_CHANGED, config->callback_mount_changed); + } else { + tinyusb_msc_unregister_callback(TINYUSB_MSC_EVENT_MOUNT_CHANGED); + } + if (config->callback_premount_changed) { + tinyusb_msc_register_callback(TINYUSB_MSC_EVENT_PREMOUNT_CHANGED, config->callback_premount_changed); + } else { + tinyusb_msc_unregister_callback(TINYUSB_MSC_EVENT_PREMOUNT_CHANGED); + } + + return ESP_OK; +} + +#if SOC_SDMMC_HOST_SUPPORTED +esp_err_t tinyusb_msc_storage_init_sdmmc(const tinyusb_msc_sdmmc_config_t *config) +{ + assert(!s_storage_handle); + s_storage_handle = (tinyusb_msc_storage_handle_s *)malloc(sizeof(tinyusb_msc_storage_handle_s)); + ESP_RETURN_ON_FALSE(s_storage_handle, ESP_ERR_NO_MEM, TAG, "could not allocate new handle for storage"); + s_storage_handle->mount = &_mount_sdmmc; + s_storage_handle->unmount = &_unmount_sdmmc; + s_storage_handle->sector_count = &_get_sector_count_sdmmc; + s_storage_handle->sector_size = &_get_sector_size_sdmmc; + s_storage_handle->read = &_read_sector_sdmmc; + s_storage_handle->write = &_write_sector_sdmmc; + s_storage_handle->is_fat_mounted = false; + s_storage_handle->base_path = NULL; + s_storage_handle->card = config->card; + // In case the user does not set mount_config.max_files + // and for backward compatibility with versions <1.4.2 + // max_files is set to 2 + const int max_files = config->mount_config.max_files; + s_storage_handle->max_files = max_files > 0 ? max_files : 2; + + /* Callbacks setting up*/ + if (config->callback_mount_changed) { + tinyusb_msc_register_callback(TINYUSB_MSC_EVENT_MOUNT_CHANGED, config->callback_mount_changed); + } else { + tinyusb_msc_unregister_callback(TINYUSB_MSC_EVENT_MOUNT_CHANGED); + } + if (config->callback_premount_changed) { + tinyusb_msc_register_callback(TINYUSB_MSC_EVENT_PREMOUNT_CHANGED, config->callback_premount_changed); + } else { + tinyusb_msc_unregister_callback(TINYUSB_MSC_EVENT_PREMOUNT_CHANGED); + } + + return ESP_OK; +} +#endif + +void tinyusb_msc_storage_deinit(void) +{ + assert(s_storage_handle); + free(s_storage_handle); + s_storage_handle = NULL; +} + +esp_err_t tinyusb_msc_register_callback(tinyusb_msc_event_type_t event_type, + tusb_msc_callback_t callback) +{ + assert(s_storage_handle); + switch (event_type) { + case TINYUSB_MSC_EVENT_MOUNT_CHANGED: + s_storage_handle->callback_mount_changed = callback; + return ESP_OK; + case TINYUSB_MSC_EVENT_PREMOUNT_CHANGED: + s_storage_handle->callback_premount_changed = callback; + return ESP_OK; + default: + ESP_LOGE(TAG, "Wrong event type"); + return ESP_ERR_INVALID_ARG; + } +} + +esp_err_t tinyusb_msc_unregister_callback(tinyusb_msc_event_type_t event_type) +{ + assert(s_storage_handle); + switch (event_type) { + case TINYUSB_MSC_EVENT_MOUNT_CHANGED: + s_storage_handle->callback_mount_changed = NULL; + return ESP_OK; + case TINYUSB_MSC_EVENT_PREMOUNT_CHANGED: + s_storage_handle->callback_premount_changed = NULL; + return ESP_OK; + default: + ESP_LOGE(TAG, "Wrong event type"); + return ESP_ERR_INVALID_ARG; + } +} + +bool tinyusb_msc_storage_in_use_by_usb_host(void) +{ + assert(s_storage_handle); + return !s_storage_handle->is_fat_mounted; +} + + +/* TinyUSB MSC callbacks + ********************************************************************* */ + +/** SCSI ASC/ASCQ codes. **/ +/** User can add and use more codes as per the need of the application **/ +#define SCSI_CODE_ASC_MEDIUM_NOT_PRESENT 0x3A /** SCSI ASC code for 'MEDIUM NOT PRESENT' **/ +#define SCSI_CODE_ASC_INVALID_COMMAND_OPERATION_CODE 0x20 /** SCSI ASC code for 'INVALID COMMAND OPERATION CODE' **/ +#define SCSI_CODE_ASCQ 0x00 + +// Invoked when received SCSI_CMD_INQUIRY +// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) +{ + (void) lun; + const char vid[] = "TinyUSB"; + const char pid[] = "Flash Storage"; + const char rev[] = "0.1"; + + memcpy(vendor_id, vid, strlen(vid)); + memcpy(product_id, pid, strlen(pid)); + memcpy(product_rev, rev, strlen(rev)); +} + +// Invoked when received Test Unit Ready command. +// return true allowing host to read/write this LUN e.g SD card inserted +bool tud_msc_test_unit_ready_cb(uint8_t lun) +{ + (void) lun; + bool result = false; + + if (s_storage_handle->is_fat_mounted) { + tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, SCSI_CODE_ASC_MEDIUM_NOT_PRESENT, SCSI_CODE_ASCQ); + result = false; + } else { + if (tinyusb_msc_storage_unmount() != ESP_OK) { + ESP_LOGW(TAG, "tud_msc_test_unit_ready_cb() unmount Fails"); + } + result = true; + } + return result; +} + +// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size +// Application update block count and block size +void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) +{ + (void) lun; + + uint32_t sec_count = tinyusb_msc_storage_get_sector_count(); + uint32_t sec_size = tinyusb_msc_storage_get_sector_size(); + *block_count = sec_count; + *block_size = (uint16_t)sec_size; +} + +// Invoked when received Start Stop Unit command +// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage +// - Start = 1 : active mode, if load_eject = 1 : load disk storage +bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) +{ + (void) lun; + (void) power_condition; + + if (load_eject && !start) { + if (tinyusb_msc_storage_mount(s_storage_handle->base_path) != ESP_OK) { + ESP_LOGW(TAG, "tud_msc_start_stop_cb() mount Fails"); + } + } + return true; +} + +// Invoked when received SCSI READ10 command +// - Address = lba * BLOCK_SIZE + offset +// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. +int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) +{ + esp_err_t err = msc_storage_read_sector(lba, offset, bufsize, buffer); + if (err != ESP_OK) { + ESP_LOGE(TAG, "msc_storage_read_sector failed: 0x%x", err); + return 0; + } + return bufsize; +} + +// Invoked when received SCSI WRITE10 command +// - Address = lba * BLOCK_SIZE + offset +// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) +{ + esp_err_t err = msc_storage_write_sector(lba, offset, bufsize, buffer); + if (err != ESP_OK) { + ESP_LOGE(TAG, "msc_storage_write_sector failed: 0x%x", err); + return 0; + } + return bufsize; +} + +/** + * Invoked when received an SCSI command not in built-in list below. + * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE + * - READ10 and WRITE10 has their own callbacks + * + * \param[in] lun Logical unit number + * \param[in] scsi_cmd SCSI command contents which application must examine to response accordingly + * \param[out] buffer Buffer for SCSI Data Stage. + * - For INPUT: application must fill this with response. + * - For OUTPUT it holds the Data from host + * \param[in] bufsize Buffer's length. + * + * \return Actual bytes processed, can be zero for no-data command. + * \retval negative Indicate error e.g unsupported command, tinyusb will \b STALL the corresponding + * endpoint and return failed status in command status wrapper phase. + */ +int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) +{ + int32_t ret; + + switch (scsi_cmd[0]) { + case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + /* SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL is the Prevent/Allow Medium Removal + command (1Eh) that requests the library to enable or disable user access to + the storage media/partition. */ + ret = 0; + break; + default: + ESP_LOGW(TAG, "tud_msc_scsi_cb() invoked: %d", scsi_cmd[0]); + tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_CODE_ASC_INVALID_COMMAND_OPERATION_CODE, SCSI_CODE_ASCQ); + ret = -1; + break; + } + return ret; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + if (tinyusb_msc_storage_mount(s_storage_handle->base_path) != ESP_OK) { + ESP_LOGW(TAG, "tud_umount_cb() mount Fails"); + } +} + +// Invoked when device is mounted (configured) +void tud_mount_cb(void) +{ + tinyusb_msc_storage_unmount(); +} +/*********************************************************************** TinyUSB MSC callbacks*/ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_tasks.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_tasks.c new file mode 100644 index 000000000..cd4add4e1 --- /dev/null +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/tusb_tasks.c @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_log.h" +#include "esp_check.h" +#include "tinyusb.h" +#include "tusb_tasks.h" + +const static char *TAG = "tusb_tsk"; +static TaskHandle_t s_tusb_tskh; + +#if CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK +const static int INIT_OK = BIT0; +const static int INIT_FAILED = BIT1; +#endif + +/** + * @brief This top level thread processes all usb events and invokes callbacks + */ +static void tusb_device_task(void *arg) +{ + ESP_LOGD(TAG, "tinyusb task started"); +#if CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK + EventGroupHandle_t *init_flags = arg; + if (!tusb_init()) { + ESP_LOGI(TAG, "Init TinyUSB stack failed"); + xEventGroupSetBits(*init_flags, INIT_FAILED); + vTaskDelete(NULL); + } + ESP_LOGD(TAG, "tinyusb task has been initialized"); + xEventGroupSetBits(*init_flags, INIT_OK); +#endif // CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK + while (1) { // RTOS forever loop + tud_task(); + } +} + +esp_err_t tusb_run_task(void) +{ + // This function is not guaranteed to be thread safe, if invoked multiple times without calling `tusb_stop_task`, will cause memory leak + // doing a sanity check anyway + ESP_RETURN_ON_FALSE(!s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task already started"); + + void *task_arg = NULL; +#if CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK + // need to synchronize to potentially report issue if init failed + EventGroupHandle_t init_flags = xEventGroupCreate(); + ESP_RETURN_ON_FALSE(init_flags, ESP_ERR_NO_MEM, TAG, "Failed to allocate task sync flags"); + task_arg = &init_flags; +#endif + // Create a task for tinyusb device stack: + xTaskCreatePinnedToCore(tusb_device_task, "TinyUSB", CONFIG_TINYUSB_TASK_STACK_SIZE, task_arg, CONFIG_TINYUSB_TASK_PRIORITY, &s_tusb_tskh, CONFIG_TINYUSB_TASK_AFFINITY); + ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_FAIL, TAG, "create TinyUSB main task failed"); +#if CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK + // wait until tusb initialization has completed + EventBits_t bits = xEventGroupWaitBits(init_flags, INIT_OK | INIT_FAILED, pdFALSE, pdFALSE, portMAX_DELAY); + vEventGroupDelete(init_flags); + ESP_RETURN_ON_FALSE(bits & INIT_OK, ESP_FAIL, TAG, "Init TinyUSB stack failed"); +#endif + + return ESP_OK; +} + +esp_err_t tusb_stop_task(void) +{ + ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task not started yet"); + vTaskDelete(s_tusb_tskh); + s_tusb_tskh = NULL; + return ESP_OK; +} diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/usb_descriptors.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/usb_descriptors.c similarity index 50% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/usb_descriptors.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/usb_descriptors.c index d4d3004e7..891091336 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/usb_descriptors.c +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/usb_descriptors.c @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "usb_descriptors.h" #include "sdkconfig.h" +#include "tinyusb_types.h" /* * A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. @@ -14,12 +15,15 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ +#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) #define USB_TUSB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ _PID_MAP(MIDI, 3) ) //| _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) -/**** TinyUSB default ****/ -tusb_desc_device_t descriptor_tinyusb = { - .bLength = sizeof(descriptor_tinyusb), +/**** Kconfig driven Descriptor ****/ + +//------------- Device Descriptor -------------// +const tusb_desc_device_t descriptor_dev_default = { + .bLength = sizeof(descriptor_dev_default), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, @@ -37,9 +41,19 @@ tusb_desc_device_t descriptor_tinyusb = { .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, +#if CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID + .idVendor = USB_ESPRESSIF_VID, +#else + .idVendor = CONFIG_TINYUSB_DESC_CUSTOM_VID, +#endif + +#if CONFIG_TINYUSB_DESC_USE_DEFAULT_PID .idProduct = USB_TUSB_PID, - .bcdDevice = 0x0100, +#else + .idProduct = CONFIG_TINYUSB_DESC_CUSTOM_PID, +#endif + + .bcdDevice = CONFIG_TINYUSB_DESC_BCD_DEVICE, .iManufacturer = 0x01, .iProduct = 0x02, @@ -48,19 +62,10 @@ tusb_desc_device_t descriptor_tinyusb = { .bNumConfigurations = 0x01 }; -tusb_desc_strarray_device_t descriptor_str_tinyusb = { - // array of pointer to string descriptors - (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - "123456", // 3: Serials, should use chip ID -}; -/* End of TinyUSB default */ - -/**** Kconfig driven Descriptor ****/ -const tusb_desc_device_t descriptor_dev_kconfig = { - .bLength = sizeof(descriptor_dev_kconfig), - .bDescriptorType = TUSB_DESC_DEVICE, +#if (TUD_OPT_HIGH_SPEED) +const tusb_desc_device_qualifier_t descriptor_qualifier_default = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, .bcdUSB = 0x0200, #if CFG_TUD_CDC @@ -76,29 +81,13 @@ const tusb_desc_device_t descriptor_dev_kconfig = { #endif .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - -#if CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID - .idVendor = USB_ESPRESSIF_VID, -#else - .idVendor = CONFIG_TINYUSB_DESC_CUSTOM_VID, -#endif - -#if CONFIG_TINYUSB_DESC_USE_DEFAULT_PID - .idProduct = USB_TUSB_PID, -#else - .idProduct = CONFIG_TINYUSB_DESC_CUSTOM_PID, -#endif - - .bcdDevice = CONFIG_TINYUSB_DESC_BCD_DEVICE, - - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - - .bNumConfigurations = 0x01 + .bNumConfigurations = 0x01, + .bReserved = 0 }; +#endif // TUD_OPT_HIGH_SPEED -tusb_desc_strarray_device_t descriptor_str_kconfig = { +//------------- Array of String Descriptors -------------// +const char *descriptor_str_default[] = { // array of pointer to string descriptors (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) CONFIG_TINYUSB_DESC_MANUFACTURER_STRING, // 1: Manufacturer @@ -117,9 +106,14 @@ tusb_desc_strarray_device_t descriptor_str_kconfig = { "", #endif +#if CONFIG_TINYUSB_NET_MODE_ECM_RNDIS || CONFIG_TINYUSB_NET_MODE_NCM + "USB net", // 6. NET Interface + "", // 7. MAC +#endif + NULL // NULL: Must be last. Indicates end of array }; -//------------- Configuration Descriptor -------------// +//------------- Interfaces enumeration -------------// enum { #if CFG_TUD_CDC ITF_NUM_CDC = 0, @@ -135,13 +129,19 @@ enum { ITF_NUM_MSC, #endif +#if CFG_TUD_NCM + ITF_NUM_NET, + ITF_NUM_NET_DATA, +#endif + ITF_NUM_TOTAL }; enum { TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN + - CFG_TUD_CDC * TUD_CDC_DESC_LEN + - CFG_TUD_MSC * TUD_MSC_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN + + CFG_TUD_MSC * TUD_MSC_DESC_LEN + + CFG_TUD_NCM * TUD_CDC_NCM_DESC_LEN }; //------------- USB Endpoint numbers -------------// @@ -161,26 +161,91 @@ enum { #if CFG_TUD_MSC EPNUM_MSC, #endif + +#if CFG_TUD_NCM + EPNUM_NET_NOTIF, + EPNUM_NET_DATA, +#endif +}; + +//------------- STRID -------------// +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, +#if CFG_TUD_CDC + STRID_CDC_INTERFACE, +#endif + +#if CFG_TUD_MSC + STRID_MSC_INTERFACE, +#endif + +#if CFG_TUD_NCM + STRID_NET_INTERFACE, + STRID_MAC, +#endif + }; -uint8_t const descriptor_cfg_kconfig[] = { +//------------- Configuration Descriptor -------------// +uint8_t const descriptor_fs_cfg_default[] = { // Configuration number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), #if CFG_TUD_CDC // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, CFG_TUD_CDC_EP_BUFSIZE), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, STRID_CDC_INTERFACE, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, 64), #endif #if CFG_TUD_CDC > 1 // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, CFG_TUD_CDC_EP_BUFSIZE), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, STRID_CDC_INTERFACE, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, 64), #endif #if CFG_TUD_MSC // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512 + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_MSC_INTERFACE, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), +#endif + +#if CFG_TUD_NCM + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_NET, STRID_NET_INTERFACE, STRID_MAC, (0x80 | EPNUM_NET_NOTIF), 64, EPNUM_NET_DATA, (0x80 | EPNUM_NET_DATA), 64, CFG_TUD_NET_MTU), #endif }; +#if (TUD_OPT_HIGH_SPEED) +uint8_t const descriptor_hs_cfg_default[] = { + // Configuration number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + +#if CFG_TUD_CDC + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, STRID_CDC_INTERFACE, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, 512), +#endif + +#if CFG_TUD_CDC > 1 + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, STRID_CDC_INTERFACE, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, 512), +#endif + +#if CFG_TUD_MSC + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_MSC_INTERFACE, EPNUM_MSC, 0x80 | EPNUM_MSC, 512), +#endif + +#if CFG_TUD_NCM + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_NET, STRID_NET_INTERFACE, STRID_MAC, (0x80 | EPNUM_NET_NOTIF), 64, EPNUM_NET_DATA, (0x80 | EPNUM_NET_DATA), 512, CFG_TUD_NET_MTU), +#endif +}; +#endif // TUD_OPT_HIGH_SPEED + +#if CFG_TUD_NCM +uint8_t tusb_get_mac_string_id(void) +{ + return STRID_MAC; +} +#endif /* End of Kconfig driven Descriptor */ diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml b/examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml deleted file mode 100644 index db103d80e..000000000 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/version.yml +++ /dev/null @@ -1,3 +0,0 @@ -# Newt uses this file to determine the version of a checked out repo. -# This should always be 0.0.0 in the master branch. -repo.version: 0.0.0 diff --git a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/vfs_tinyusb.c b/examples/espidf-peripherals-usb/components/esp_tinyusb/vfs_tinyusb.c similarity index 66% rename from examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/vfs_tinyusb.c rename to examples/espidf-peripherals-usb/components/esp_tinyusb/vfs_tinyusb.c index fdf31e6a9..8b8cea9ee 100644 --- a/examples/espidf-peripherals-usb/components/esp_tinyusb/additions/src/vfs_tinyusb.c +++ b/examples/espidf-peripherals-usb/components/esp_tinyusb/vfs_tinyusb.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,8 +23,6 @@ #include "sdkconfig.h" const static char *TAG = "tusb_vfs"; -#define VFS_TUSB_MAX_PATH 16 -#define VFS_TUSB_PATH_DEFAULT "/dev/tusb_cdc" // Token signifying that no character is available #define NONE -1 @@ -69,19 +67,17 @@ static vfs_tinyusb_t s_vfstusb; static esp_err_t apply_path(char const *path) { - if (path != NULL) { - size_t path_len = strlen(path) + 1; - if (path_len > VFS_TUSB_MAX_PATH) { - ESP_LOGE(TAG, "The path is too long; maximum is %d characters", VFS_TUSB_MAX_PATH); - return ESP_ERR_INVALID_ARG; - } - strncpy(s_vfstusb.vfs_path, path, (VFS_TUSB_MAX_PATH - 1)); - } else { - strncpy(s_vfstusb.vfs_path, - VFS_TUSB_PATH_DEFAULT, - (VFS_TUSB_MAX_PATH - 1)); + if (path == NULL) { + path = VFS_TUSB_PATH_DEFAULT; } - ESP_LOGV(TAG, "Path is set to `%s`", s_vfstusb.vfs_path); + + size_t path_len = strlen(path) + 1; + if (path_len > VFS_TUSB_MAX_PATH) { + ESP_LOGE(TAG, "The path is too long; maximum is %d characters", VFS_TUSB_MAX_PATH); + return ESP_ERR_INVALID_ARG; + } + strncpy(s_vfstusb.vfs_path, path, (VFS_TUSB_MAX_PATH - 1)); + ESP_LOGV(TAG, "Path is set to `%s`", path); return ESP_OK; } @@ -109,7 +105,6 @@ static void vfstusb_deinit(void) memset(&s_vfstusb, 0, sizeof(s_vfstusb)); } - static int tusb_open(const char *path, int flags, int mode) { (void) mode; @@ -126,24 +121,25 @@ static ssize_t tusb_write(int fd, const void *data, size_t size) _lock_acquire(&(s_vfstusb.write_lock)); for (size_t i = 0; i < size; i++) { int c = data_c[i]; - /* handling the EOL */ - if (c == '\n' && s_vfstusb.tx_mode != ESP_LINE_ENDINGS_LF) { - if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, '\r')) { - written_sz++; - } else { + if (c != '\n') { + if (!tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, c)) { break; // can't write anymore } - if (s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CR) { - continue; - } - } - /* write a char */ - if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, c)) { - written_sz++; } else { - break; // can't write anymore + if (s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CRLF || s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CR) { + char cr = '\r'; + if (!tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, cr)) { + break; // can't write anymore + } + } + if (s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CRLF || s_vfstusb.tx_mode == ESP_LINE_ENDINGS_LF) { + char lf = '\n'; + if (!tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, lf)) { + break; // can't write anymore + } + } } - + written_sz++; } tud_cdc_n_write_flush(s_vfstusb.cdc_intf); _lock_release(&(s_vfstusb.write_lock)); @@ -162,31 +158,40 @@ static ssize_t tusb_read(int fd, void *data, size_t size) char *data_c = (char *) data; size_t received = 0; _lock_acquire(&(s_vfstusb.read_lock)); - int cm1 = NONE; - int c = NONE; + if (tud_cdc_n_available(s_vfstusb.cdc_intf) == 0) { + goto finish; + } while (received < size) { - cm1 = c; // store the old char - int c = tud_cdc_n_read_char(0); // get a new one + int c = tud_cdc_n_read_char(s_vfstusb.cdc_intf); + if ( c == NONE) { // if data ends + break; + } + + // Handle line endings. From configured mode -> LF mode if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) { + // Change CRs to newlines if (c == '\r') { c = '\n'; } - } else if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) { - if ((c == '\n') & (cm1 == '\r')) { - --received; // step back - c = '\n'; + } else if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CRLF) { + if (c == '\r') { + uint8_t next_char = NONE; + // Check if next char is newline. If yes, we got CRLF sequence + tud_cdc_n_peek(s_vfstusb.cdc_intf, &next_char); + if (next_char == '\n') { + c = tud_cdc_n_read_char(s_vfstusb.cdc_intf); // Remove '\n' from the fifo + } } } - if ( c == NONE) { // if data ends - break; - } + data_c[received] = (char) c; ++received; if (c == '\n') { break; } } +finish: _lock_release(&(s_vfstusb.read_lock)); if (received > 0) { return received; @@ -195,7 +200,6 @@ static ssize_t tusb_read(int fd, void *data, size_t size) return -1; } - static int tusb_fstat(int fd, struct stat *st) { FD_CHECK(fd, -1); @@ -225,39 +229,33 @@ static int tusb_fcntl(int fd, int cmd, int arg) esp_err_t esp_vfs_tusb_cdc_unregister(char const *path) { - ESP_LOGD(TAG, "Unregistering TinyUSB driver"); + ESP_LOGD(TAG, "Unregistering CDC-VFS driver"); int res; if (path == NULL) { // NULL means using the default path for unregistering: VFS_TUSB_PATH_DEFAULT - res = strcmp(s_vfstusb.vfs_path, VFS_TUSB_PATH_DEFAULT); - } else { - res = strcmp(s_vfstusb.vfs_path, path); + path = VFS_TUSB_PATH_DEFAULT; } + res = strcmp(s_vfstusb.vfs_path, path); if (res) { res = ESP_ERR_INVALID_ARG; - ESP_LOGE(TAG, "There is no TinyUSB driver registerred to the path '%s' (err: 0x%x)", s_vfstusb.vfs_path, res); + ESP_LOGE(TAG, "There is no CDC-VFS driver registered to path '%s' (err: 0x%x)", path, res); return res; } - - res = esp_vfs_unregister(s_vfstusb.vfs_path); if (res != ESP_OK) { - ESP_LOGE(TAG, "Can't unregister TinyUSB driver from '%s' (err: 0x%x)", s_vfstusb.vfs_path, res); + ESP_LOGE(TAG, "Can't unregister CDC-VFS driver from '%s' (err: 0x%x)", s_vfstusb.vfs_path, res); } else { - ESP_LOGD(TAG, "Unregistered TinyUSB driver"); + ESP_LOGD(TAG, "Unregistered CDC-VFS driver"); vfstusb_deinit(); } return res; } - - - esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path) { - ESP_LOGD(TAG, "Registering TinyUSB CDC driver"); + ESP_LOGD(TAG, "Registering CDC-VFS driver"); int res; if (!tusb_cdc_acm_initialized(cdc_intf)) { ESP_LOGE(TAG, "TinyUSB CDC#%d is not initialized", cdc_intf); @@ -281,9 +279,23 @@ esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path) res = esp_vfs_register(s_vfstusb.vfs_path, &vfs, NULL); if (res != ESP_OK) { - ESP_LOGE(TAG, "Can't register TinyUSB driver (err: %x)", res); + ESP_LOGE(TAG, "Can't register CDC-VFS driver (err: %x)", res); } else { - ESP_LOGD(TAG, "TinyUSB CDC registered (%s)", s_vfstusb.vfs_path); + ESP_LOGD(TAG, "CDC-VFS registered (%s)", s_vfstusb.vfs_path); } return res; } + +void esp_vfs_tusb_cdc_set_rx_line_endings(esp_line_endings_t mode) +{ + _lock_acquire(&(s_vfstusb.read_lock)); + s_vfstusb.rx_mode = mode; + _lock_release(&(s_vfstusb.read_lock)); +} + +void esp_vfs_tusb_cdc_set_tx_line_endings(esp_line_endings_t mode) +{ + _lock_acquire(&(s_vfstusb.write_lock)); + s_vfstusb.tx_mode = mode; + _lock_release(&(s_vfstusb.write_lock)); +} diff --git a/examples/espidf-peripherals-usb/platformio.ini b/examples/espidf-peripherals-usb/platformio.ini index a1883d5a1..438ef31be 100644 --- a/examples/espidf-peripherals-usb/platformio.ini +++ b/examples/espidf-peripherals-usb/platformio.ini @@ -14,3 +14,6 @@ monitor_speed = 115200 [env:esp32-s2-saola-1] board = esp32-s2-saola-1 + +[env:esp32-s2-kaluga-1] +board = esp32-s2-kaluga-1 From 4ffc31c80f81b5ed29a06e762850583bfdf5c234 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 28 May 2024 14:29:47 +0200 Subject: [PATCH 633/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index d6b2a5aa9..854835d91 100644 --- a/platform.json +++ b/platform.json @@ -92,7 +92,7 @@ "tool-esptoolpy": { "type": "uploader", "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.2/esptool.zip" + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.3/esptool.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From 65fa53fbc8ff0caedb70b798caf3df2ca53053dd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 31 May 2024 16:00:01 +0200 Subject: [PATCH 634/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index 854835d91..22bbc4625 100644 --- a/platform.json +++ b/platform.json @@ -45,7 +45,7 @@ "type": "framework", "optional": true, "owner": "jason2866", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.4.240525/esp-idf-v5.1.4.zip" + "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.4.240530/esp-idf-v5.1.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From bed6e50d15cee7a37b50961750eb5f25aa50ea3d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jun 2024 22:45:34 +0200 Subject: [PATCH 635/666] Update platform.json --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 22bbc4625..40302ec51 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/d45f35a2c8fd6e1ebe11ffecbd9eb5e13e26edd8" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/640523827be8db2ed201623f107569a6dd1b2a13" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/b692a53c52f960457583b0f1646df9f80998be4b" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6" }, "framework-espidf": { "type": "framework", From 2d559725d813c3806887a4bf1c8239c7215e82a6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jun 2024 22:48:58 +0200 Subject: [PATCH 636/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 2fef2f4a2..4d5bb634f 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -19,8 +19,8 @@ board_build.embed_txtfiles = managed_components/espressif__esp_rainmaker/server_certs/rmaker_claim_service_server.crt managed_components/espressif__esp_rainmaker/server_certs/rmaker_ota_server.crt -[env:esp32dev] -board = esp32dev +[env:esp32-s3] +board = 4d_systems_esp32s3_gen4_r8n16 [env:esp32-c6-devkitm-1] board = esp32-c6-devkitm-1 From 760cd033209b0621d850f6f7bdb3ef5dca9d6ea7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jun 2024 22:54:46 +0200 Subject: [PATCH 637/666] add missing "H2" --- builder/frameworks/_embed_files.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index 354c244bb..caa12c4c4 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -110,14 +110,14 @@ def transform_to_asm(target, source, env): " ".join( [ "riscv32-esp-elf-objcopy" - if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2") + if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2") else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", "elf32-littleriscv" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2") else "elf32-xtensa-le", "--binary-architecture", - "riscv" if mcu in ("esp32c2","esp32c3","esp32c6") else "xtensa", + "riscv" if mcu in ("esp32c2","esp32c3","esp32c6","esp32h2") else "xtensa", "--rename-section", ".data=.rodata.embedded", "$SOURCE", From 722e90af2e9f2c3559ad0ed0a8cc9aaa9bd9ff22 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jun 2024 22:57:59 +0200 Subject: [PATCH 638/666] Fix h2 entrys --- boards/esp32-h2-devkitm-1.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/boards/esp32-h2-devkitm-1.json b/boards/esp32-h2-devkitm-1.json index 8aedb337b..519f61b22 100644 --- a/boards/esp32-h2-devkitm-1.json +++ b/boards/esp32-h2-devkitm-1.json @@ -1,8 +1,5 @@ { "build": { - "arduino": { - "ldscript": "esp32h2_out.ld" - }, "core": "esp32", "f_cpu": "96000000L", "f_flash": "64000000L", @@ -18,7 +15,8 @@ ] }, "connectivity": [ - "wifi" + "bluetooth", + "zigbee" ], "debug": { "openocd_target": "esp32h2.cfg" From c94ce1764d7ae89f7de69e3f80a70da6b3c59f85 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jun 2024 23:04:09 +0200 Subject: [PATCH 639/666] Create partitions_customs.csv --- examples/espidf-arduino-blink/partitions_customs.csv | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 examples/espidf-arduino-blink/partitions_customs.csv diff --git a/examples/espidf-arduino-blink/partitions_customs.csv b/examples/espidf-arduino-blink/partitions_customs.csv new file mode 100644 index 000000000..97e41c452 --- /dev/null +++ b/examples/espidf-arduino-blink/partitions_customs.csv @@ -0,0 +1,8 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x300000, +app1, app, ota_1, 0x310000, 0x300000, +spiffs, data, spiffs, 0x610000, 0x700000, +model, data, spiffs, 0xD10000, 0x2E0000, +coredump, data, coredump,0xFF0000, 0x10000, From 33e128b38dbc02269d7e8b314f07267575e7d063 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jun 2024 23:05:41 +0200 Subject: [PATCH 640/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 4d5bb634f..e8e89db9c 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -21,6 +21,8 @@ board_build.embed_txtfiles = [env:esp32-s3] board = 4d_systems_esp32s3_gen4_r8n16 +board_build.partitions = partitions_custom.csv [env:esp32-c6-devkitm-1] board = esp32-c6-devkitm-1 +board_build.partitions = partitions_custom.csv From d00d48b9f9a6c567c80e4d57f57b70c8a806e5a0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 4 Jun 2024 23:06:16 +0200 Subject: [PATCH 641/666] Rename partitions_customs.csv to partitions_custom.csv --- .../{partitions_customs.csv => partitions_custom.csv} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/espidf-arduino-blink/{partitions_customs.csv => partitions_custom.csv} (100%) diff --git a/examples/espidf-arduino-blink/partitions_customs.csv b/examples/espidf-arduino-blink/partitions_custom.csv similarity index 100% rename from examples/espidf-arduino-blink/partitions_customs.csv rename to examples/espidf-arduino-blink/partitions_custom.csv From 2990e440f9c2c04b08f3e42359336edc2767a223 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:29:45 +0200 Subject: [PATCH 642/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index e8e89db9c..0f03c2745 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -25,4 +25,3 @@ board_build.partitions = partitions_custom.csv [env:esp32-c6-devkitm-1] board = esp32-c6-devkitm-1 -board_build.partitions = partitions_custom.csv From 7d84cb759dbd2c0bfa11c169eb193d2b71cc9b37 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:33:54 +0200 Subject: [PATCH 643/666] Delete examples/espidf-arduino-blink/partitions_custom.csv --- examples/espidf-arduino-blink/partitions_custom.csv | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 examples/espidf-arduino-blink/partitions_custom.csv diff --git a/examples/espidf-arduino-blink/partitions_custom.csv b/examples/espidf-arduino-blink/partitions_custom.csv deleted file mode 100644 index 97e41c452..000000000 --- a/examples/espidf-arduino-blink/partitions_custom.csv +++ /dev/null @@ -1,8 +0,0 @@ -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x5000, -otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x300000, -app1, app, ota_1, 0x310000, 0x300000, -spiffs, data, spiffs, 0x610000, 0x700000, -model, data, spiffs, 0xD10000, 0x2E0000, -coredump, data, coredump,0xFF0000, 0x10000, From 08c18837e54985171e04be6369467af5e89fdf22 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:34:18 +0200 Subject: [PATCH 644/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 0f03c2745..02a10a874 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -21,7 +21,8 @@ board_build.embed_txtfiles = [env:esp32-s3] board = 4d_systems_esp32s3_gen4_r8n16 -board_build.partitions = partitions_custom.csv +board_build.partitions = esp_sr_16.csv + [env:esp32-c6-devkitm-1] board = esp32-c6-devkitm-1 From 8371a93f2e574e0b6873538216b74494ae60c137 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:42:30 +0200 Subject: [PATCH 645/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 02a10a874..4d5bb634f 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -21,8 +21,6 @@ board_build.embed_txtfiles = [env:esp32-s3] board = 4d_systems_esp32s3_gen4_r8n16 -board_build.partitions = esp_sr_16.csv - [env:esp32-c6-devkitm-1] board = esp32-c6-devkitm-1 From 6927e5763bc8ea81429dd30e11d4e2182b5ce8b6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:44:11 +0200 Subject: [PATCH 646/666] Update 4d_systems_esp32s3_gen4_r8n16.json --- boards/4d_systems_esp32s3_gen4_r8n16.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boards/4d_systems_esp32s3_gen4_r8n16.json b/boards/4d_systems_esp32s3_gen4_r8n16.json index 4418be557..753980a74 100644 --- a/boards/4d_systems_esp32s3_gen4_r8n16.json +++ b/boards/4d_systems_esp32s3_gen4_r8n16.json @@ -1,9 +1,8 @@ { "build": { "arduino": { - "ldscript": "esp32s3_out.ld", "memory_type": "qio_opi", - "partitions": "default_16MB.csv" + "partitions": "esp_sr_16.csv" }, "core": "esp32", "extra_flags": [ From 84322aeea14ea079c7e58f782ec1eebc34a7693a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:52:46 +0200 Subject: [PATCH 647/666] Update sdkconfig.defaults --- examples/espidf-arduino-blink/sdkconfig.defaults | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index 5ef23a055..8e508ea38 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -5,13 +5,13 @@ CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y # # SPI RAM config # -CONFIG_SPIRAM_MODE_QUAD=y +CONFIG_SPIRAM_MODE_OCT=y CONFIG_SPIRAM_TYPE_AUTO=y CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y CONFIG_SPIRAM_SPEED_80M=y From 464961f56e49dd872c597ea7120405dc2e5c65ca Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:04:47 +0200 Subject: [PATCH 648/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index 4d5bb634f..c1b28aea2 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -21,6 +21,8 @@ board_build.embed_txtfiles = [env:esp32-s3] board = 4d_systems_esp32s3_gen4_r8n16 +build_flags = + -DARDUINO_PARTITION_esp_sr_16 [env:esp32-c6-devkitm-1] board = esp32-c6-devkitm-1 From 99fe4ef2042c40de664da5bbdcc17146bab62bd8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:07:38 +0200 Subject: [PATCH 649/666] Update sdkconfig.defaults --- .../espidf-arduino-blink/sdkconfig.defaults | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index 8e508ea38..d3a1b69a8 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -20,3 +20,40 @@ CONFIG_SPIRAM_USE_MALLOC=y CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096 CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=0 + +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_SR_WN_WN9_HIESP=y +CONFIG_SR_MN_CN_NONE=y +CONFIG_SR_MN_EN_MULTINET5_SINGLE_RECOGNITION_QUANT8=y +CONFIG_EN_SPEECH_COMMAND_ID0="" +CONFIG_EN_SPEECH_COMMAND_ID1="" +CONFIG_EN_SPEECH_COMMAND_ID2="" +CONFIG_EN_SPEECH_COMMAND_ID3="" +CONFIG_EN_SPEECH_COMMAND_ID4="" +CONFIG_EN_SPEECH_COMMAND_ID5="" +CONFIG_EN_SPEECH_COMMAND_ID6="" +CONFIG_EN_SPEECH_COMMAND_ID7="" +CONFIG_EN_SPEECH_COMMAND_ID8="" +CONFIG_EN_SPEECH_COMMAND_ID9="" +CONFIG_EN_SPEECH_COMMAND_ID10="" +CONFIG_EN_SPEECH_COMMAND_ID11="" +CONFIG_EN_SPEECH_COMMAND_ID12="" +CONFIG_EN_SPEECH_COMMAND_ID13="" +CONFIG_EN_SPEECH_COMMAND_ID14="" +CONFIG_EN_SPEECH_COMMAND_ID15="" +CONFIG_EN_SPEECH_COMMAND_ID16="" +CONFIG_EN_SPEECH_COMMAND_ID17="" +CONFIG_EN_SPEECH_COMMAND_ID18="" +CONFIG_EN_SPEECH_COMMAND_ID19="" +CONFIG_EN_SPEECH_COMMAND_ID20="" +CONFIG_EN_SPEECH_COMMAND_ID21="" +CONFIG_EN_SPEECH_COMMAND_ID22="" +CONFIG_EN_SPEECH_COMMAND_ID23="" +CONFIG_EN_SPEECH_COMMAND_ID24="" +CONFIG_EN_SPEECH_COMMAND_ID25="" +CONFIG_EN_SPEECH_COMMAND_ID26="" +CONFIG_EN_SPEECH_COMMAND_ID27="" +CONFIG_EN_SPEECH_COMMAND_ID28="" +CONFIG_EN_SPEECH_COMMAND_ID29="" +CONFIG_EN_SPEECH_COMMAND_ID30="" +CONFIG_EN_SPEECH_COMMAND_ID31="" From bacc48c033349a5eec59cbd398c0d5b8b8b50911 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:15:46 +0200 Subject: [PATCH 650/666] Update platformio.ini --- examples/espidf-arduino-blink/platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/espidf-arduino-blink/platformio.ini b/examples/espidf-arduino-blink/platformio.ini index c1b28aea2..0399901d7 100644 --- a/examples/espidf-arduino-blink/platformio.ini +++ b/examples/espidf-arduino-blink/platformio.ini @@ -22,6 +22,7 @@ board_build.embed_txtfiles = [env:esp32-s3] board = 4d_systems_esp32s3_gen4_r8n16 build_flags = + -DCONFIG_BLINK_GPIO=2 -DARDUINO_PARTITION_esp_sr_16 [env:esp32-c6-devkitm-1] From dda65e6c2104c8f01f19dc848b9885fec1e9e4d9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:50:32 +0200 Subject: [PATCH 651/666] Orig 3.0.1 Arduino release --- platform.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 40302ec51..e69bd032e 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,15 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/640523827be8db2ed201623f107569a6dd1b2a13" + // "version": "https://codeload.github.com/espressif/arduino-esp32/zip/640523827be8db2ed201623f107569a6dd1b2a13" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-3.0.1.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6" + // "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip" }, "framework-espidf": { "type": "framework", From 4158efbe158d858c3c6957c3458eab76580fa376 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:52:19 +0200 Subject: [PATCH 652/666] Update platform.json --- platform.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform.json b/platform.json index e69bd032e..c728fc327 100644 --- a/platform.json +++ b/platform.json @@ -33,14 +33,12 @@ "type": "framework", "optional": true, "owner": "espressif", - // "version": "https://codeload.github.com/espressif/arduino-esp32/zip/640523827be8db2ed201623f107569a6dd1b2a13" "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-3.0.1.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - // "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6" "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip" }, "framework-espidf": { From 00ebcdb50936df6a2539c03a3f308ad43a9cc2ed Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:58:04 +0200 Subject: [PATCH 653/666] Update platform.json --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index c728fc327..c2b565ca2 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-3.0.1.zip" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/ebb77c46112dde9b84f7039234541011688df918" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6" }, "framework-espidf": { "type": "framework", From f2d7aad5e2421a48fb9a31a3747b40ea0b3af3d7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:17:36 +0200 Subject: [PATCH 654/666] Update espidf.py --- builder/frameworks/espidf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 0042acd81..793997015 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -744,8 +744,8 @@ def compile_source_files( obj_path = os.path.join(obj_path, os.path.basename(src_path)) preserve_source_file_extension = board.get( - "build.esp-idf.preserve_source_file_extension", True - ) + "build.esp-idf.preserve_source_file_extension", "yes" + ) == "yes" objects.append( build_envs[compile_group_idx].StaticObject( From b8284018a68e3d04b06607e566f8bbe7b1e47d4d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:25:12 +0200 Subject: [PATCH 655/666] Update sdkconfig.defaults --- .../espidf-arduino-blink/sdkconfig.defaults | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index d3a1b69a8..791a3b868 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -21,6 +21,27 @@ CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096 CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=0 +CONFIG_ESP_RMAKER_SKIP_VERSION_CHECK=y +CONFIG_ESP_RMAKER_USER_ID_CHECK=y +CONFIG_ESP_INSIGHTS_ENABLED=y +CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE=n +CONFIG_ESP_INSIGHTS_TRANSPORT_HTTPS=y +CONFIG_DIAG_LOG_DROP_WIFI_LOGS=y +CONFIG_DIAG_ENABLE_METRICS=y +CONFIG_DIAG_ENABLE_HEAP_METRICS=y +CONFIG_DIAG_ENABLE_WIFI_METRICS=y +CONFIG_DIAG_ENABLE_VARIABLES=y +CONFIG_DIAG_ENABLE_NETWORK_VARIABLES=y +CONFIG_ESP_COREDUMP_ENABLE=y +CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=n +CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y +CONFIG_ESP_COREDUMP_CHECKSUM_CRC32=y +CONFIG_ESP_COREDUMP_MAX_TASKS_NUM=64 +CONFIG_ESP_COREDUMP_STACK_SIZE=1024 +CONFIG_MBEDTLS_DYNAMIC_BUFFER=y +CONFIG_MBEDTLS_DYNAMIC_FREE_PEER_CERT=y +CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_SR_WN_WN9_HIESP=y CONFIG_SR_MN_CN_NONE=y From f863bf07a48efe265217846479fdfed2c84b4292 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:37:22 +0200 Subject: [PATCH 656/666] Update sdkconfig.defaults --- .../espidf-arduino-blink/sdkconfig.defaults | 93 +++++++++++++++++-- 1 file changed, 85 insertions(+), 8 deletions(-) diff --git a/examples/espidf-arduino-blink/sdkconfig.defaults b/examples/espidf-arduino-blink/sdkconfig.defaults index 791a3b868..54ef4be5d 100644 --- a/examples/espidf-arduino-blink/sdkconfig.defaults +++ b/examples/espidf-arduino-blink/sdkconfig.defaults @@ -1,12 +1,4 @@ -CONFIG_AUTOSTART_ARDUINO=y -# CONFIG_WS2812_LED_ENABLE is not set -CONFIG_FREERTOS_HZ=1000 -CONFIG_MBEDTLS_PSK_MODES=y -CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y -CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y -CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y -CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y # # SPI RAM config @@ -21,6 +13,91 @@ CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096 CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=0 +CONFIG_AUTOSTART_ARDUINO=y +# CONFIG_WS2812_LED_ENABLE is not set +CONFIG_ARDUHAL_ESP_LOG=y +CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y +CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y +CONFIG_BT_BLE_BLUFI_ENABLE=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BTC_TASK_STACK_SIZE=8192 +CONFIG_BT_BTU_TASK_STACK_SIZE=8192 +CONFIG_BLE_MESH=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_COMPILER_STACK_CHECK_MODE_NORM=y +CONFIG_COMPILER_WARN_WRITE_STRINGS=y +CONFIG_ESP_HTTPS_SERVER_ENABLE=y +CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2048 +CONFIG_ESP_TASK_WDT_PANIC=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=4096 +CONFIG_ESP_WIFI_FTM_ENABLE=y +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=8 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=8 +CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=16 +CONFIG_ESP_WIFI_CSI_ENABLED=y +CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y +# CONFIG_ESP_WIFI_IRAM_OPT is not set +# CONFIG_ESP_WIFI_RX_IRAM_OPT is not set +CONFIG_ETH_SPI_ETHERNET_DM9051=y +CONFIG_ETH_SPI_ETHERNET_W5500=y +CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL=y +CONFIG_FATFS_CODEPAGE_850=y +CONFIG_FATFS_LFN_STACK=y +# CONFIG_FATFS_API_ENCODING_ANSI_OEM is not set +CONFIG_FATFS_API_ENCODING_UTF_8=y +CONFIG_FATFS_USE_LABEL=y +# CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_FMB_TIMER_PORT_ENABLED=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y +# CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 +CONFIG_HEAP_POISONING_LIGHT=y +CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024 +CONFIG_HTTPD_WS_SUPPORT=y +# CONFIG_LOG_COLORS is not set +CONFIG_LWIP_ETHARP_TRUST_IP_MAC=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +CONFIG_LWIP_TCP_SYNMAXRTX=6 +CONFIG_LWIP_TCP_MSS=1436 +CONFIG_LWIP_TCP_RTO_TIME=3000 +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0=y +CONFIG_LWIP_MAX_SOCKETS=16 +CONFIG_LWIP_IP_FORWARD=y +CONFIG_LWIP_IPV4_NAPT=y +CONFIG_LWIP_DHCP_RESTORE_LAST_IP=n +CONFIG_LWIP_DHCP_OPTIONS_LEN=128 +CONFIG_LWIP_SNTP_MAX_SERVERS=3 +CONFIG_LWIP_SNTP_UPDATE_DELAY=10800000 +CONFIG_LWIP_DHCP_GET_NTP_SRV=y +CONFIG_LWIP_IPV6_AUTOCONFIG=y +CONFIG_LWIP_IPV6_DHCP6=y +CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=2 +CONFIG_LWIP_PPP_SUPPORT=y +CONFIG_LWIP_PPP_NOTIFY_PHASE_SUPPORT=y +CONFIG_LWIP_PPP_PAP_SUPPORT=y +CONFIG_LWIP_PPP_ENABLE_IPV6=n +CONFIG_MBEDTLS_PSK_MODES=y +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_MBEDTLS_CAMELLIA_C=y +# CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN is not set +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_OPENSSL_ASSERT_DO_NOTHING=y +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=2048 +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=10 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=2 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=4096 +# CONFIG_SPI_MASTER_ISR_IN_IRAM is not set +# CONFIG_SPI_SLAVE_ISR_IN_IRAM is not set +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096 +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=0 CONFIG_ESP_RMAKER_SKIP_VERSION_CHECK=y CONFIG_ESP_RMAKER_USER_ID_CHECK=y CONFIG_ESP_INSIGHTS_ENABLED=y From 0cef0c4345a91023437b38e28a9d1ce36621bde2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:50:38 +0200 Subject: [PATCH 657/666] maybe esptool v4.5.1? --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index c2b565ca2..26a3a9b78 100644 --- a/platform.json +++ b/platform.json @@ -91,8 +91,8 @@ }, "tool-esptoolpy": { "type": "uploader", - "owner": "tasmota", - "version": "https://github.com/tasmota/esptool/releases/download/v4.7.3/esptool.zip" + "owner": "platformio", + "version": "~1.40501.0" }, "tool-dfuutil-arduino": { "type": "uploader", From 1e792fa87155dc3214cbf7f3c1aae1e3c184edcb Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:59:47 +0200 Subject: [PATCH 658/666] Update platform.json --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 26a3a9b78..c2b565ca2 100644 --- a/platform.json +++ b/platform.json @@ -91,8 +91,8 @@ }, "tool-esptoolpy": { "type": "uploader", - "owner": "platformio", - "version": "~1.40501.0" + "owner": "tasmota", + "version": "https://github.com/tasmota/esptool/releases/download/v4.7.3/esptool.zip" }, "tool-dfuutil-arduino": { "type": "uploader", From 7ca9893950a7d30005748a9634c756adeba21003 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:07:49 +0200 Subject: [PATCH 659/666] Update Arduino & idf --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index c2b565ca2..7734fec91 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/ebb77c46112dde9b84f7039234541011688df918" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/297757a6bfafcbf2818347386299fb67f22ca568" }, "framework-arduinoespressif32-libs": { "type": "framework", @@ -45,7 +45,7 @@ "type": "framework", "optional": true, "owner": "jason2866", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.4.240530/esp-idf-v5.1.4.zip" + "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.4.240602/esp-idf-v5.1.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From e40259dd0f48c6bbd246e3d462e55d1b0097a50b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:53:03 +0200 Subject: [PATCH 660/666] latest commits 240613 --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index 7734fec91..ba56ed9d4 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/297757a6bfafcbf2818347386299fb67f22ca568" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/1d895e58e7b131682cc2ac7b5dcd2ac3ef84dcb3" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/a6dac936bfcfa4c11468e003f550b41c76efeae6" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/9f889b1dadfb54c37f017b21f70c35828941a3fd" }, "framework-espidf": { "type": "framework", From 3c7902388dc2a782ed8fd67a46555106194459b8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:58:26 +0200 Subject: [PATCH 661/666] Update platform.json --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index ba56ed9d4..a4775d0db 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/1d895e58e7b131682cc2ac7b5dcd2ac3ef84dcb3" + "version": "https://codeload.github.com/espressif/arduino-esp32/zip/cbf1e94dd5f9ac8bdabaae9603611a3b81d8fbe4" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/9f889b1dadfb54c37f017b21f70c35828941a3fd" + "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/81f40959b1f1beee1fb24822d757221cb496a41f" }, "framework-espidf": { "type": "framework", From ced69f2d7ea61adbd29630c38a52c539ce24a4d7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:02:10 +0200 Subject: [PATCH 662/666] Update IDF 5.1.4.240614 --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index a4775d0db..ac5525155 100644 --- a/platform.json +++ b/platform.json @@ -45,7 +45,7 @@ "type": "framework", "optional": true, "owner": "jason2866", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.4.240602/esp-idf-v5.1.4.zip" + "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.4.240614/esp-idf-v5.1.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 238dc537adbc09afe2603fe2c5d80a1e453c7062 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:10:54 +0200 Subject: [PATCH 663/666] Use always latest commits for Arduino core & libs --- platform.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.json b/platform.json index ac5525155..a9509aea2 100644 --- a/platform.json +++ b/platform.json @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/arduino-esp32/zip/cbf1e94dd5f9ac8bdabaae9603611a3b81d8fbe4" + "version": "https://github.com/espressif/arduino-esp32/archive/refs/heads/master.zip" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://codeload.github.com/espressif/esp32-arduino-libs/zip/81f40959b1f1beee1fb24822d757221cb496a41f" + "version": "https://github.com/espressif/esp32-arduino-libs/archive/refs/heads/idf-release/v5.1.zip" }, "framework-espidf": { "type": "framework", From 7cab348f1c2ae1e8bec4936f4c97155c3e00beda Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 26 Jun 2024 22:32:39 +0200 Subject: [PATCH 664/666] Update platform.json --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index a9509aea2..e2eb929a2 100644 --- a/platform.json +++ b/platform.json @@ -45,7 +45,7 @@ "type": "framework", "optional": true, "owner": "jason2866", - "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.4.240614/esp-idf-v5.1.4.zip" + "version": "https://github.com/Jason2866/esp-idf/releases/download/v5.1.4.240625/esp-idf-v5.1.4.zip" }, "toolchain-xtensa-esp32": { "type": "toolchain", From 56648b6c4c2c0159b949ffc2ef1d19b405e7ee84 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 7 Jul 2024 13:21:34 +0200 Subject: [PATCH 665/666] more failsafe IDF version get --- builder/frameworks/espidf.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 793997015..a289b2bfa 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -745,7 +745,7 @@ def compile_source_files( preserve_source_file_extension = board.get( "build.esp-idf.preserve_source_file_extension", "yes" - ) == "yes" + ) == "yes" objects.append( build_envs[compile_group_idx].StaticObject( @@ -991,12 +991,24 @@ def find_default_component(target_configs): env.Exit(1) +def get_version_cmake_file(): + version_cmake = os.path.join(FRAMEWORK_DIR, "tools", "cmake", "version.cmake") + with open(version_cmake, "r") as file: + string = file.read().replace("\n", "").replace("(", " ").replace(")", " ") + list = string.split() + v_major = list[(list.index("IDF_VERSION_MAJOR"))+1] + v_minor = list[(list.index("IDF_VERSION_MINOR"))+1] + v_patch = list[(list.index("IDF_VERSION_PATCH"))+1] + version = v_major + "." + v_minor + "." + v_patch + return version + + def create_version_file(): version_file = os.path.join(FRAMEWORK_DIR, "version.txt") if not os.path.isfile(version_file): with open(version_file, "w") as fp: - package_version = platform.get_package_version("framework-espidf") - fp.write(get_original_version(package_version) or package_version) + version = get_version_cmake_file() + fp.write(version) def generate_empty_partition_image(binary_path, image_size): @@ -1229,10 +1241,8 @@ def get_idf_venv_dir(): # unnecessary reinstallation of Python dependencies in cases when Arduino # as an IDF component requires a different version of the IDF package and # hence a different set of Python deps or their versions - idf_version = get_original_version(platform.get_package_version("framework-espidf")) - return os.path.join( - env.subst("$PROJECT_CORE_DIR"), "penv", ".espidf-" + idf_version - ) + idf_version = get_version_cmake_file() + return os.path.join(env.subst("$PROJECT_CORE_DIR"), "penv", ".espidf-" + idf_version) def ensure_python_venv_available(): From 79a0cb7aadf5afd0137abc7e3f1e8aece76c1db9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 Jul 2024 20:21:58 +0200 Subject: [PATCH 666/666] Update espidf.py --- builder/frameworks/espidf.py | 44 ++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index a289b2bfa..f6ef68b43 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -991,24 +991,38 @@ def find_default_component(target_configs): env.Exit(1) -def get_version_cmake_file(): - version_cmake = os.path.join(FRAMEWORK_DIR, "tools", "cmake", "version.cmake") - with open(version_cmake, "r") as file: - string = file.read().replace("\n", "").replace("(", " ").replace(")", " ") - list = string.split() - v_major = list[(list.index("IDF_VERSION_MAJOR"))+1] - v_minor = list[(list.index("IDF_VERSION_MINOR"))+1] - v_patch = list[(list.index("IDF_VERSION_PATCH"))+1] - version = v_major + "." + v_minor + "." + v_patch - return version +def get_framework_version(): + def _extract_from_cmake_version_file(): + version_cmake_file = os.path.join( + FRAMEWORK_DIR, "tools", "cmake", "version.cmake" + ) + if not os.path.isfile(version_cmake_file): + return + + with open(version_cmake_file, encoding="utf8") as fp: + pattern = r"set\(IDF_VERSION_(MAJOR|MINOR|PATCH) (\d+)\)" + matches = re.findall(pattern, fp.read()) + if len(matches) != 3: + return + # If found all three parts of the version + return ".".join([match[1] for match in matches]) + + pkg = platform.get_package("framework-espidf") + version = get_original_version(str(pkg.metadata.version.truncate())) + if not version: + # Fallback value extracted directly from the cmake version file + version = _extract_from_cmake_version_file() + if not version: + version = "0.0.0" + + return version def create_version_file(): version_file = os.path.join(FRAMEWORK_DIR, "version.txt") if not os.path.isfile(version_file): with open(version_file, "w") as fp: - version = get_version_cmake_file() - fp.write(version) + fp.write(get_framework_version()) def generate_empty_partition_image(binary_path, image_size): @@ -1241,8 +1255,10 @@ def get_idf_venv_dir(): # unnecessary reinstallation of Python dependencies in cases when Arduino # as an IDF component requires a different version of the IDF package and # hence a different set of Python deps or their versions - idf_version = get_version_cmake_file() - return os.path.join(env.subst("$PROJECT_CORE_DIR"), "penv", ".espidf-" + idf_version) + idf_version = get_framework_version() + return os.path.join( + env.subst("$PROJECT_CORE_DIR"), "penv", ".espidf-" + idf_version + ) def ensure_python_venv_available():